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:
authorLluis Sanchez Gual <lluis@xamarin.com>2015-04-20 19:07:51 +0300
committerLluis Sanchez Gual <lluis@xamarin.com>2015-04-20 19:07:51 +0300
commit95408b1a41b31b645f3a8c3323ab7d3ca4bff26b (patch)
treef8f137cddcb9a40499d303be95722fd2c6081bce /main/src/core/MonoDevelop.Ide
parentb70e4e04b4e41b8ec28d7e4b220b401ecf467e7a (diff)
parentde043d330a8bf5855d4d983c804cd36727cb2406 (diff)
Merge remote-tracking branch 'origin/roslyn' into new-project-model
Diffstat (limited to 'main/src/core/MonoDevelop.Ide')
-rw-r--r--main/src/core/MonoDevelop.Ide/AssemblyInfo.cs10
-rw-r--r--main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml24
-rw-r--r--main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml7
-rw-r--r--main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml40
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/BasicChart.cs52
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandFrame.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs5
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandMenuBar.cs4
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/KeyBindingManager.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockWindow.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/PlaceholderWindow.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/TabStrip.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockToolbars/DockToolbar.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockToolbars/DockToolbarFrame.cs3
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockToolbars/FixedPanel.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/AutoHideBox.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBar.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBarItem.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockContainer.cs2
-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.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockItemContainer.cs3
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockItemTitleTab.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/PlaceholderWindow.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Extensions/TextQuestionDialog.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/FileSearchCategory.cs25
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/ISearchDataSource.cs6
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbar.cs6
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarController.cs10
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/ProjectSearchCategory.cs280
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/ResultsDataSource.cs12
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/RoundButton.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchCategory.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchInSolutionSearchCategory.cs10
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchPopupWindow.cs66
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchResult.cs189
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/StatusArea.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/StatusAreaBuildTheme.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/StatusAreaTheme.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/ExpandableObjectEditor.cs61
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/PropertyTextEditor.cs (renamed from main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/TextEditor.cs)4
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/EditorManager.cs134
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyEditorCell.cs55
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGridTable.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Theming/GtkTheme.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/CairoExtensions.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/CompactScrolledWindow.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsGtk.cs4
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuTreeView.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Control.cs6
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/DropDownBox.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkGestures.cs252
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkUtil.cs13
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkWorkarounds.cs1275
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HPanedThin.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HeaderBox.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HelperMethods.cs136
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HslColor.cs292
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ImageView.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MiniButton.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PangoUtil.cs260
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PathBar.cs4
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PopoverWindow.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PopoverWindowTheme.cs5
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SearchEntry.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SectionList.cs3
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/TooltipWindow.cs4
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/VPanedThin.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/WindowTransparencyDecorator.cs116
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CodeCompletionContextEventArgs.cs4
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionCategory.cs50
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionData.cs39
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionDataList.cs24
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionListWindow.cs153
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionWindowManager.cs28
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/DisplayFlags.cs (renamed from main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/IRefactoringContext.cs)23
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ICompletionWidget.cs20
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ListWidget.cs60
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ListWindow.cs250
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/MemberCompletionData.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/MruCache.cs67
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/MutableCompletionDataList.cs14
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ParameterHintingData.cs (renamed from main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ParameterDataProvider.cs)57
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ParameterHintingResult.cs88
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ParameterInformationWindow.cs32
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ParameterInformationWindowManager.cs29
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/TooltipInformationWindow.cs5
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeFormatting/CodeFormatter.cs21
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeFormatting/CodeFormatterService.cs20
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeFormatting/CodeFormattingCommands.cs15
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeFormatting/IAdvancedCodeFormatter.cs34
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplate.cs103
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplateCompletionData.cs14
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplateListDataProvider.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplatePanel.cs26
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/EditTemplateDialog.cs54
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/ExpansionObject.cs213
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/IListDataProvider.cs (renamed from main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/ProjectContentEventArgs.cs)39
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/CustomStringTagProvider.cs6
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/EditCommands.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileCommands.cs3
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ProjectCommands.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/TextEditorCommands.cs6
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ViewCommands.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/AbstractUsagesExtension.cs246
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/CompletionTextEditorExtension.cs (renamed from main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/CompletionTextEditorExtension.cs)392
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/IQuickTaskProvider.cs (renamed from main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/ParsedFileEventArgs.cs)22
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/IndentationTracker.cs40
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/KeyDescriptor.cs222
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/ModifierKeys.cs40
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/QuickTask.cs76
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/SelectionSurroundingProvider.cs57
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/SpecialKey.cs49
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/TextEditorExtension.cs107
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/TextPasteHandler.cs64
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/Usage.cs49
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/AmbientColor.cs188
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/ChunkStyle.cs186
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/ColorDescriptionAttribute.cs (renamed from main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/PreProcessorDefine.cs)41
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/ColorScheme.cs1030
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/ColoredSegment.cs59
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/IStreamProvider.cs97
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/SemanticHighlighting.cs76
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/SyntaxModeService.cs216
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/TemplateCodon.cs (renamed from main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/ConditionalRegion.cs)78
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/TemplateExtensionNodeLoader.cs55
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Util/Diff.cs587
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Util/SimpleBracketMatcher.cs273
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Util/SimpleReadonlyDocument.cs414
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/AutoSave.cs225
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Commands/DynamicAbbrevHandler.cs193
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/CustomEditorOptions.cs186
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/DefaultSourceEditorOptions.cs785
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/DocumentContext.cs158
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/DocumentLocation.cs241
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/DocumentRegion.cs181
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/EditActions.cs516
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/FileSettingsStore.cs73
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/FoldSegmentFactory.cs86
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/IDocumentLine.cs118
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/IFoldSegment.cs74
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/IReadonlyTextDocument.cs246
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/ITextDocument.cs140
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/ITextEditorOptions.cs124
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/ITextLineMarker.cs80
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/ITextSegmentMarker.cs86
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/IUnitTestMarker.cs38
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InsertionCursorEventArgs.cs51
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InsertionModeOptions.cs88
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InsertionPoint.cs119
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InternalExtensionAPI/IEditorActionHost.cs123
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InternalExtensionAPI/ITextEditorFactory.cs44
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InternalExtensionAPI/ITextEditorImpl.cs244
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InternalExtensionAPI/ITextMarkerFactory.cs58
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/LineEventArgs.cs48
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/MessageBubbles/MessageBubbleCommands.cs77
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/IProjectionExtension.cs39
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/ProjectedCompletionExtension.cs433
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/ProjectedDocumentContext.cs143
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/ProjectedFilterCompletionTextEditorExtension.cs186
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/ProjectedSegment.cs89
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/ProjectedSemanticHighlighting.cs98
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/ProjectedTooltipProvider.cs95
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/Projection.cs130
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/SegmentTree.cs801
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/SelectionMode.cs33
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextEditor.cs1260
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextEditorDisplayBinding.cs114
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextEditorFactory.cs95
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextEditorViewContent.cs1233
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextLink.cs136
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextLinkModeEventArgs.cs43
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextLinkModeOptions.cs66
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextMarkerFactory.cs121
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextMarkerMouseEventArgs.cs49
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TooltipExtensionNode.cs49
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TooltipProvider.cs177
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/WordFindStrategy.cs38
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FileProvider.cs8
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindInFilesDialog.cs22
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/ISearchProgressMonitor.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/MemberCollector.cs472
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/MemberReference.cs28
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/ReferencesFinder.cs636
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/Scope.cs12
-rwxr-xr-xmain/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchCollector.cs544
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchProgressMonitor.cs6
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResult.cs12
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResultPad.cs6
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResultWidget.cs100
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ExtensibleTreeView.cs8
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/PadTreeView.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/DocumentStateTracker.cs19
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/IEditableTextBuffer.cs70
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/IEncodedTextContent.cs41
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/IFoldable.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/IOpenNamedElementHandler.cs5
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/ISmartIndenter.cs63
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/ITextBuffer.cs46
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/ITextEditorResolver.cs37
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/TextEditorExtension.cs181
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/ClassNodeBuilder.cs10
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/EventNodeBuilder.cs6
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/FieldNodeBuilder.cs6
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/MemberNodeBuilder.cs8
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/MemberNodeCommandHandler.cs4
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/MethodNodeBuilder.cs6
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/ProjectNodeBuilder.cs35
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/PropertyNodeBuilder.cs6
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/AbstractBaseViewContent.cs8
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/AbstractViewContent.cs16
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/CommonTextEditorOptions.cs90
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DefaultWorkbench.cs9
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Document.cs531
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DocumentSwitcher.cs5
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DocumentToolbar.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/HiddenTextEditorViewContent.cs79
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/IBaseViewContent.cs4
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/IViewContent.cs8
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/SdiWorkspaceWindow.cs3
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Styles.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ViewCommandHandlers.cs85
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs110
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/WorkbenchWindow.cs3
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/NavigationHistoryService.cs10
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/TextFileNavigationPoint.cs11
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.ProgressMonitoring/MultiTaskDialogProgressMonitor.cs3
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ApplyPolicyDialog.cs3
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AssemblyReferencePanel.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkNewProjectDialogBackend.UI.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewProjectController.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/PackageReferencePanel.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/SelectReferenceDialog.cs3
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/CommentTasksChangedEventHandler.cs10
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/CommentTasksView.cs142
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/ProjectCommentTags.cs (renamed from main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/ProjectCommentTags.cs)21
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/TaskListEntry.cs (renamed from main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/UserTask.cs)22
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/TaskService.cs6
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/TaskStore.cs52
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/CodeDomFileDescriptionTemplate.cs14
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectTemplatingProvider.cs4
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/SingleFileDescriptionTemplate.cs11
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/FileExtension.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/FileExtensionEventArgs.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/FileLineExtension.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/HorizontalAlignment.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/LineCountEventArgs.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/TextEditorService.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/TextFileEventArgs.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/TextLineMarkerExtension.cs8
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/VerticalAlignment.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/Ambience.cs623
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/AmbienceService.cs559
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/AmbienceTooltipProvider.cs (renamed from main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/IExtensibleTextEditor.cs)27
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/CodeGenerationService.cs563
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/CodeGenerator.cs70
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/Comment.cs11
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/Error.cs216
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/FoldingRegion.cs16
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/IFoldingParser.cs41
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MetadataReferenceCache.cs166
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopProjectContent.cs109
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopSourceTextContainer.cs123
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopTextLoader.cs69
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspace.cs848
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDocDocumentationProvider.cs146
-rwxr-xr-xmain/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/NetAmbience.cs367
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/OutputFlags.cs65
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/OutputSettings.cs268
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/ParsedDocument.cs347
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/StockIcons.cs288
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/Tag.cs11
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemParser.cs99
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemParserNode.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService.cs2680
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService_WorkspaceHandling.cs488
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/AddinsUpdateHandler.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.WelcomePage/WelcomePageFirstRun.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.WelcomePage/WelcomePageLinkButton.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.WelcomePage/WelcomePageListButton.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.WelcomePage/WelcomePageSection.cs13
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj198
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/DesktopService.cs9
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/HelpOperations.cs19
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs15
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ImageService.cs16
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/MessageService.cs3
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs303
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs24
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Services.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/packages.config10
293 files changed, 23121 insertions, 8815 deletions
diff --git a/main/src/core/MonoDevelop.Ide/AssemblyInfo.cs b/main/src/core/MonoDevelop.Ide/AssemblyInfo.cs
index df2563993f..6d7c8abadf 100644
--- a/main/src/core/MonoDevelop.Ide/AssemblyInfo.cs
+++ b/main/src/core/MonoDevelop.Ide/AssemblyInfo.cs
@@ -14,7 +14,17 @@ using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("MonoDevelop.DesignerSupport")]
[assembly: InternalsVisibleTo("Ide.Tests")]
[assembly: InternalsVisibleTo("UnitTests")]
+[assembly: InternalsVisibleTo("MonoDevelop.SourceEditor")]
+[assembly: InternalsVisibleTo("Xamarin.OSXEditor")]
[assembly: InternalsVisibleTo("MonoDevelop.Refactoring")]
+[assembly: InternalsVisibleTo("MonoDevelop.CSharpBinding")]
+[assembly: InternalsVisibleTo("FSharpBinding")]
+[assembly: InternalsVisibleTo("MonoDevelop.CBinding")]
+[assembly: InternalsVisibleTo("MonoDevelop.Xml")]
+[assembly: InternalsVisibleTo("MonoDevelop.AspNet")]
[assembly: InternalsVisibleTo("Xamarin.Ide")]
[assembly: InternalsVisibleTo("MonoDevelop.SourceEditor")]
[assembly: InternalsVisibleTo("MonoDevelop.SourceEditor2")]
+[assembly: InternalsVisibleTo("MonoDevelop.AssemblyBrowser")]
+[assembly: InternalsVisibleTo("MonoDevelop.AspNet")]
+[assembly: InternalsVisibleTo("Xamarin.Sketches")]
diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml
index 7697bc917a..f98ef0fbde 100644
--- a/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml
+++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml
@@ -1021,8 +1021,28 @@
_label = "Toggle block selection mode"/>
<Command id = "MonoDevelop.Ide.Commands.TextEditorCommands.DuplicateLine"
_label = "Duplicate line"/>
+ <Command id = "MonoDevelop.Ide.Commands.TextEditorCommands.DynamicAbbrev"
+ defaultHandler = "MonoDevelop.Ide.Editor.DynamicAbbrevHandler"
+ _label = "Dynamic abbrev"
+ _description = "Cycles completing the current word from matching words in all open files"
+ macShortcut = "Ctrl|/"
+ shortcut = "Alt|/" />
+ <Command id = "MonoDevelop.Ide.Commands.TextEditorCommands.PulseCaret"
+ _label = "Find caret"
+ _description = "Animates the text editor caret to help find it"
+ shortcut = "Ctrl||"
+ macShortcut = "Meta||" />
+
+ <Command id = "MonoDevelop.Ide.Editor.MessageBubbleCommands.Toggle"
+ _label = "Toggle message bubble"
+ _description = "Toggles message bubble on/off"/>
+ <Command id = "MonoDevelop.Ide.Editor.MessageBubbleCommands.HideIssues"
+ defaultHandler = "MonoDevelop.Ide.Editor.HideIssuesHandler"
+ _label = "_Hide Issues"/>
+ <Command id = "MonoDevelop.Ide.Editor.MessageBubbleCommands.ToggleIssues"
+ defaultHandler = "MonoDevelop.Ide.Editor.ToggleIssuesHandler"
+ _label = "Toggle Issues"
+ type="array"/>
</Category>
-
</Extension>
-
</ExtensionModel>
diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml
index 25cda3ed16..75c69530f4 100644
--- a/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml
+++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml
@@ -115,6 +115,12 @@
<CommandItem id = "MonoDevelop.Ide.Commands.ViewCommands.DeleteCurrentLayout" />
<SeparatorItem id = "ViewSeparator2" />
<CommandItem id = "MonoDevelop.Ide.Commands.ViewCommands.ViewList" />
+ <ItemSet id = "MessageBubbles" _label = "_Message Bubbles">
+ <CommandItem id = "MonoDevelop.Ide.Editor.MessageBubbleCommands.Toggle" />
+ <CommandItem id = "MonoDevelop.Ide.Editor.MessageBubbleCommands.HideIssues" />
+ <SeparatorItem id = "Separator1" />
+ <CommandItem id = "MonoDevelop.Ide.Editor.MessageBubbleCommands.ToggleIssues" />
+ </ItemSet>
<SeparatorItem id = "ViewSeparator3" />
<SeparatorItem id = "ViewItemsSeparator" />
<CommandItem id = "MonoDevelop.Ide.Commands.ViewCommands.ZoomIn" />
@@ -128,6 +134,7 @@
<CommandItem id = "MonoDevelop.Ide.Commands.ViewCommands.FocusCurrentDocument" />
<CommandItem id = "MonoDevelop.Ide.Commands.ViewCommands.ShowWelcomePage" />
<CommandItem id = "MonoDevelop.Ide.Commands.ViewCommands.FullScreen" />
+
</ItemSet>
<ItemSet id = "Search" _label = "_Search">
diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml
index c510afb657..6cdd5cb768 100644
--- a/main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml
+++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml
@@ -155,15 +155,43 @@
<ExtensionNode name="Parser" type="MonoDevelop.Ide.Extensions.MimeTypeExtensionNode"/>
</ExtensionPoint>
- <ExtensionPoint path = "/MonoDevelop/TypeSystem/Ambiences" name = "Language ambiences">
+ <ExtensionPoint path = "/MonoDevelop/TypeSystem/AmbienceTooltipProviders" name = "Language ambiences">
<Description>Language ambiences. Specified classes must implement IAmbience.</Description>
- <ExtensionNode name="Ambience" type="MonoDevelop.Ide.Extensions.MimeTypeExtensionNode" />
+ <ExtensionNode name="Provider" type="MonoDevelop.Ide.Extensions.MimeTypeExtensionNode" />
</ExtensionPoint>
<ExtensionPoint path = "/MonoDevelop/TypeSystem/CodeGenerators">
<ExtensionNode name="Generator" type="MonoDevelop.Ide.Extensions.MimeTypeExtensionNode"/>
</ExtensionPoint>
+ <ExtensionPoint path = "/MonoDevelop/SourceEditor2/SyntaxModes" name = "Text editor syntax modes">
+ <Description>Syntax modes</Description>
+ <ExtensionNode name="Templates" type="MonoDevelop.Ide.Editor.Highlighting.TemplateCodon"/>
+ </ExtensionPoint>
+
+ <ExtensionPoint path = "/MonoDevelop/SourceEditor2/Styles" name = "Text editor styles">
+ <Description>Styles</Description>
+ <ExtensionNode name="Templates" type="MonoDevelop.Ide.Editor.Highlighting.TemplateCodon"/>
+ </ExtensionPoint>
+
+ <ExtensionPoint path = "/MonoDevelop/SourceEditor2/CustomModes" name = "Text editor custom syntax modes">
+ <Description>Styles</Description>
+ <ExtensionNode name="SyntaxMode" type="MonoDevelop.Ide.Editor.Highlighting.SyntaxModeCodon"/>
+ </ExtensionPoint>
+
+ <ExtensionPoint path = "/MonoDevelop/SourceEditor2/EditorFactory" name = "Editor factories">
+ <Description>Allows providing a platform-specific implementation for the text editor</Description>
+ <ExtensionNode name="Class" />
+ </ExtensionPoint>
+
+ <ExtensionPoint path = "/MonoDevelop/SourceEditor2/TooltipProviders" name = "Tooltip providers">
+ <Description>Tooltip providers. Classes must implement ITooltipProvider.</Description>
+ <ExtensionNode name="Class" type="MonoDevelop.Ide.Editor.TooltipExtensionNode" />
+ <ConditionType id="FileType" type="MonoDevelop.Ide.Extensions.FileTypeCondition">
+ <Description>Type of the file being edited.</Description>
+ </ConditionType>
+ </ExtensionPoint>
+
<!-- Extensions -->
<Extension path = "/MonoDevelop/Core/Applications">
@@ -179,6 +207,8 @@
<Extension path = "/MonoDevelop/Ide/DisplayBindings">
<DisplayBinding id = "DefaultDisplayBinding"
class = "MonoDevelop.Ide.Gui.DefaultDisplayBinding"/>
+ <DisplayBinding id = "TextEditor"
+ class = "MonoDevelop.Ide.Editor.TextEditorDisplayBinding" />
</Extension>
<Extension path = "/MonoDevelop/Ide/StartupHandlers">
@@ -228,9 +258,9 @@
</Extension>
<Extension path = "/MonoDevelop/Ide/TextEditorExtensions">
- <Class id="InitialStep" class = "MonoDevelop.Ide.Gui.Content.TextEditorExtensionMarker" />
- <Class id="MidStep" class = "MonoDevelop.Ide.Gui.Content.TextEditorExtensionMarker" />
- <Class id="FinalStep" class = "MonoDevelop.Ide.Gui.Content.TextEditorExtensionMarker" />
+ <Class id="InitialStep" class = "MonoDevelop.Ide.Editor.Extension.TextEditorExtensionMarker" />
+ <Class id="MidStep" class = "MonoDevelop.Ide.Editor.Extension.TextEditorExtensionMarker" />
+ <Class id="FinalStep" class = "MonoDevelop.Ide.Editor.Extension.TextEditorExtensionMarker" />
</Extension>
<Extension path = "/MonoDevelop/Ide/ContextMenu/DocumentTab">
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/BasicChart.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/BasicChart.cs
index 28366ed5eb..6ed67e3ac5 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/BasicChart.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/BasicChart.cs
@@ -28,10 +28,8 @@
using System;
using System.Collections;
-using System.Collections.Generic;
using Gtk;
using Gdk;
-using Mono.TextEditor;
namespace MonoDevelop.Components.Chart
{
@@ -577,9 +575,9 @@ namespace MonoDevelop.Components.Chart
win.DrawLine (gc, px, top + height, px, top + height - tick);
}
}
- else {
- if (Math.Abs ((long)lastPos - (long)py) < minTickStep || py < top || py > top + height)
- continue;
+ else {
+ if (Math.Abs ((long)lastPos - (long)py) < minTickStep || py < top || py > top + height)
+ continue;
lastPos = py;
bool labelFits = false;
@@ -780,32 +778,32 @@ namespace MonoDevelop.Components.Chart
}
void GetPoint (double wx, double wy, out double x, out double y)
- {
- unchecked {
- if (reverseXAxis)
- x = left + width - (((wx - startX) * ((double) width)) / (endX - startX));
- else
- x = left + (((wx - startX) * ((double) width)) / (endX - startX));
-
- if (reverseYAxis)
- y = top + ((wy - startY) * ((double) height) / (endY - startY));
- else
- y = top + height - ((wy - startY) * ((double) height) / (endY - startY));
+ {
+ unchecked {
+ if (reverseXAxis)
+ x = left + width - (((wx - startX) * ((double) width)) / (endX - startX));
+ else
+ x = left + (((wx - startX) * ((double) width)) / (endX - startX));
+
+ if (reverseYAxis)
+ y = top + ((wy - startY) * ((double) height) / (endY - startY));
+ else
+ y = top + height - ((wy - startY) * ((double) height) / (endY - startY));
}
}
void GetValue (int x, int y, out double wx, out double wy)
- {
- unchecked {
- if (reverseXAxis)
- wx = startX + ((double) (left + width - 1 - x)) * (endX - startX) / (double) width;
- else
- wx = startX + ((double) (x - left)) * (endX - startX) / (double) width;
-
- if (reverseYAxis)
- wy = startY + ((double) (top + y)) * (endY - startY) / (double) height;
- else
- wy = startY + ((double) (top + height - y - 1)) * (endY - startY) / (double) height;
+ {
+ unchecked {
+ if (reverseXAxis)
+ wx = startX + ((double) (left + width - 1 - x)) * (endX - startX) / (double) width;
+ else
+ wx = startX + ((double) (x - left)) * (endX - startX) / (double) width;
+
+ if (reverseYAxis)
+ wy = startY + ((double) (top + y)) * (endY - startY) / (double) height;
+ else
+ wy = startY + ((double) (top + height - y - 1)) * (endY - startY) / (double) height;
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandFrame.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandFrame.cs
index 836250a967..266d6f83af 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandFrame.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandFrame.cs
@@ -26,10 +26,8 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-using System;
using Mono.Addins;
using MonoDevelop.Components.DockToolbars;
-using Mono.TextEditor;
namespace MonoDevelop.Components.Commands
{
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 c7064e52e8..aefb043257 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs
@@ -34,7 +34,6 @@ using System.Collections.Generic;
using System.Linq;
using MonoDevelop.Components.Commands.ExtensionNodes;
-using Mono.TextEditor;
using Mono.Addins;
using MonoDevelop.Core;
using MonoDevelop.Ide;
@@ -847,8 +846,8 @@ namespace MonoDevelop.Components.Commands
if (menu is CommandMenu) {
((CommandMenu)menu).InitialCommandTarget = initialCommandTarget ?? parent;
}
-
- Mono.TextEditor.GtkWorkarounds.ShowContextMenu (menu, parent, evt);
+
+ GtkWorkarounds.ShowContextMenu (menu, parent, evt);
}
/// <summary>
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandMenuBar.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandMenuBar.cs
index 3030a5dcbc..b7da31e1be 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandMenuBar.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandMenuBar.cs
@@ -26,11 +26,7 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-using System;
using Gtk;
-using Gdk;
-using MonoDevelop.Ide.Gui;
-using Mono.TextEditor;
namespace MonoDevelop.Components.Commands
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/KeyBindingManager.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/KeyBindingManager.cs
index b4a590202b..ec563318db 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/KeyBindingManager.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/KeyBindingManager.cs
@@ -26,10 +26,8 @@
//
using System;
-using System.Collections;
using System.Collections.Generic;
-using Mono.TextEditor;
// Terminology:
// chord: A 'chord' is a key binding prefix / modifier meant to allow a
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockWindow.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockWindow.cs
index d525e048d8..e74496696c 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockWindow.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockWindow.cs
@@ -27,7 +27,6 @@
using Gdk;
using Gtk;
using MonoDevelop.Components.Docking;
-using Mono.TextEditor;
using MonoDevelop.Ide;
using System.Collections.Generic;
using MonoDevelop.Ide.Gui;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/PlaceholderWindow.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/PlaceholderWindow.cs
index bf874ce3a7..397d413170 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/PlaceholderWindow.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/PlaceholderWindow.cs
@@ -27,7 +27,6 @@
using Gdk;
using Gtk;
using MonoDevelop.Components.Docking;
-using Mono.TextEditor;
using MonoDevelop.Ide;
using System.Collections.Generic;
using MonoDevelop.Ide.Gui;
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..245c0a2e86 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/TabStrip.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/TabStrip.cs
@@ -28,7 +28,6 @@ using System.Linq;
using Gdk;
using Gtk;
using System;
-using Mono.TextEditor;
using System.Collections.Generic;
using Cairo;
using MonoDevelop.Components;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockToolbars/DockToolbar.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockToolbars/DockToolbar.cs
index 4e7c905e0f..3e3f6a4b21 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockToolbars/DockToolbar.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockToolbars/DockToolbar.cs
@@ -30,7 +30,6 @@ using System;
using System.Collections.Generic;
using Gtk;
using Gdk;
-using Mono.TextEditor;
namespace MonoDevelop.Components.DockToolbars
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockToolbars/DockToolbarFrame.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockToolbars/DockToolbarFrame.cs
index 791bb12428..e1efdd06a6 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockToolbars/DockToolbarFrame.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockToolbars/DockToolbarFrame.cs
@@ -26,14 +26,11 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-using System;
using Gtk;
using Gdk;
-using System.Collections;
using System.Xml;
using System.Xml.Serialization;
using System.Collections.Generic;
-using Mono.TextEditor;
namespace MonoDevelop.Components.DockToolbars
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockToolbars/FixedPanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockToolbars/FixedPanel.cs
index ab3daa2305..90ca29dfe6 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockToolbars/FixedPanel.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockToolbars/FixedPanel.cs
@@ -45,7 +45,7 @@ namespace MonoDevelop.Components.DockToolbars
public FixedPanel ()
{
- Mono.TextEditor.GtkWorkarounds.FixContainerLeak (this);
+ GtkWorkarounds.FixContainerLeak (this);
WidgetFlags |= WidgetFlags.NoWindow;
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/AutoHideBox.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/AutoHideBox.cs
index b3d5cf4779..0ad3d05024 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/AutoHideBox.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/AutoHideBox.cs
@@ -30,10 +30,8 @@
//#define ANIMATE_DOCKING
-using System;
using Gtk;
using Gdk;
-using Mono.TextEditor;
namespace MonoDevelop.Components.Docking
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBar.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBar.cs
index c3d7ae3c1a..2466ff5e6b 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBar.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBar.cs
@@ -31,9 +31,7 @@
using System;
using Gtk;
-using System.Collections.Generic;
using MonoDevelop.Ide.Gui;
-using Mono.TextEditor;
namespace MonoDevelop.Components.Docking
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBarItem.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBarItem.cs
index 4efd300406..b1a04940f1 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBarItem.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBarItem.cs
@@ -31,7 +31,6 @@
using System;
using Gtk;
-using Mono.TextEditor;
using MonoDevelop.Ide.Gui;
using MonoDevelop.Components;
using Xwt.Motion;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockContainer.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockContainer.cs
index b02b654ba6..aa58869f97 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockContainer.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockContainer.cs
@@ -56,7 +56,7 @@ namespace MonoDevelop.Components.Docking
public DockContainer (DockFrame frame)
{
- Mono.TextEditor.GtkWorkarounds.FixContainerLeak (this);
+ GtkWorkarounds.FixContainerLeak (this);
this.Events = EventMask.ButtonPressMask | EventMask.ButtonReleaseMask | EventMask.PointerMotionMask | EventMask.LeaveNotifyMask;
this.frame = frame;
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..98b7666572 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockFrame.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockFrame.cs
@@ -68,7 +68,7 @@ namespace MonoDevelop.Components.Docking
public DockFrame ()
{
- Mono.TextEditor.GtkWorkarounds.FixContainerLeak (this);
+ GtkWorkarounds.FixContainerLeak (this);
dockBarTop = new DockBar (this, Gtk.PositionType.Top);
dockBarBottom = new DockBar (this, Gtk.PositionType.Bottom);
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..94febd4940 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockItem.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockItem.cs
@@ -32,7 +32,6 @@ using System;
using System.Xml;
using Gtk;
using Mono.Unix;
-using Mono.TextEditor;
namespace MonoDevelop.Components.Docking
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockItemContainer.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockItemContainer.cs
index 6fef6b1d98..d6a332b165 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockItemContainer.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockItemContainer.cs
@@ -30,9 +30,6 @@
using System;
using Gtk;
-using Mono.Unix;
-using Mono.TextEditor;
-using MonoDevelop.Ide.Gui;
namespace MonoDevelop.Components.Docking
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockItemTitleTab.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockItemTitleTab.cs
index 652b1f725b..6d0c73a1f8 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockItemTitleTab.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockItemTitleTab.cs
@@ -32,7 +32,6 @@ using MonoDevelop.Ide.Gui;
using System.Linq;
using MonoDevelop.Core;
using MonoDevelop.Ide;
-using Mono.TextEditor;
using MonoDevelop.Components;
namespace MonoDevelop.Components.Docking
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/PlaceholderWindow.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/PlaceholderWindow.cs
index ff99bf3c61..faf3966c12 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/PlaceholderWindow.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/PlaceholderWindow.cs
@@ -110,7 +110,7 @@ namespace MonoDevelop.Components.Docking
public void Relocate (int x, int y, int w, int h, bool animate)
{
- Gdk.Rectangle geometry = Mono.TextEditor.GtkWorkarounds.GetUsableMonitorGeometry (Screen, Screen.GetMonitorAtPoint (x, y));
+ Gdk.Rectangle geometry = GtkWorkarounds.GetUsableMonitorGeometry (Screen, Screen.GetMonitorAtPoint (x, y));
if (x < geometry.X)
x = geometry.X;
if (x + w > geometry.Right)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Extensions/TextQuestionDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Extensions/TextQuestionDialog.cs
index 43d814ebe4..a0c8af95be 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Extensions/TextQuestionDialog.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Extensions/TextQuestionDialog.cs
@@ -86,7 +86,7 @@ namespace MonoDevelop.Components.Extensions
};
md.VBox.PackStart (responseEntry, false, true, 6);
- md.AddActionWidget (new Button (Gtk.Stock.Cancel), ResponseType.Cancel);
+ md.AddActionWidget (new Button (Gtk.Stock.Cancel) { CanDefault = true }, ResponseType.Cancel);
md.AddActionWidget (new Button (Gtk.Stock.Ok), ResponseType.Ok);
md.DefaultResponse = ResponseType.Cancel;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/FileSearchCategory.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/FileSearchCategory.cs
index 34b1968ba3..9e502170ca 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/FileSearchCategory.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/FileSearchCategory.cs
@@ -32,11 +32,12 @@ using MonoDevelop.Core.Instrumentation;
using MonoDevelop.Projects;
using MonoDevelop.Ide.Gui;
using MonoDevelop.Ide;
-using ICSharpCode.NRefactory.TypeSystem;
using MonoDevelop.Ide.TypeSystem;
using MonoDevelop.Core.Text;
using Gtk;
using System.Linq;
+using Microsoft.CodeAnalysis;
+using ICSharpCode.NRefactory6.CSharp;
namespace MonoDevelop.Components.MainToolbar
{
@@ -51,7 +52,7 @@ namespace MonoDevelop.Components.MainToolbar
IEnumerable<ProjectFile> files {
get {
- foreach (Document doc in IdeApp.Workbench.Documents) {
+ foreach (var doc in IdeApp.Workbench.Documents) {
// We only want to check it here if it's not part
// of the open combine. Otherwise, it will get
// checked down below.
@@ -61,7 +62,7 @@ namespace MonoDevelop.Components.MainToolbar
var projects = IdeApp.Workspace.GetAllProjects ();
- foreach (Project p in projects) {
+ foreach (var p in projects) {
foreach (ProjectFile file in p.Files) {
if (file.Subtype != Subtype.Directory && (file.Flags & ProjectItemFlags.Hidden) != ProjectItemFlags.Hidden)
yield return file;
@@ -126,9 +127,7 @@ namespace MonoDevelop.Components.MainToolbar
class WorkerResult
{
public List<ProjectFile> filteredFiles = null;
- public List<ITypeDefinition> filteredTypes = null;
- public List<IMember> filteredMembers = null;
-
+
public string pattern = null;
public bool isGotoFilePattern;
public ResultsDataSource results;
@@ -137,8 +136,6 @@ namespace MonoDevelop.Components.MainToolbar
public bool IncludeFiles, IncludeTypes, IncludeMembers;
- public Ambience ambience;
-
public StringMatcher matcher = null;
public WorkerResult (Widget widget)
@@ -162,18 +159,6 @@ namespace MonoDevelop.Components.MainToolbar
return null;
}
- internal SearchResult CheckType (ITypeDefinition type)
- {
- int rank;
- if (MatchName (type.Name, out rank))
- return new TypeSearchResult (pattern, type.Name, rank, type, false) { Ambience = ambience };
- if (!FullSearch)
- return null;
- if (MatchName (type.FullName, out rank))
- return new TypeSearchResult (pattern, type.FullName, rank, type, true) { Ambience = ambience };
- return null;
- }
-
Dictionary<string, MatchResult> savedMatches = new Dictionary<string, MatchResult> ();
bool MatchName (string name, out int matchRank)
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/ISearchDataSource.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/ISearchDataSource.cs
index b1a90a607b..4648be4d3a 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/ISearchDataSource.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/ISearchDataSource.cs
@@ -26,8 +26,8 @@
using System.Threading;
using System.Threading.Tasks;
-using ICSharpCode.NRefactory.TypeSystem;
using MonoDevelop.Ide.CodeCompletion;
+using MonoDevelop.Core.Text;
namespace MonoDevelop.Components.MainToolbar
{
@@ -42,7 +42,9 @@ namespace MonoDevelop.Components.MainToolbar
TooltipInformation GetTooltip (int item);
double GetWeight (int item);
- DomRegion GetRegion (int item);
+ ISegment GetRegion (int item);
+ string GetFileName (int item);
+
bool CanActivate (int item);
void Activate (int item);
}
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..bad71a8f9c 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbar.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbar.cs
@@ -30,7 +30,6 @@ using MonoDevelop.Ide;
using MonoDevelop.Ide.Commands;
using MonoDevelop.Core;
using System.Linq;
-using MonoDevelop.Core.Assemblies;
using MonoDevelop.Components;
using Cairo;
using MonoDevelop.Projects;
@@ -38,15 +37,12 @@ using System.Collections.Generic;
using Mono.Addins;
using MonoDevelop.Components.Commands.ExtensionNodes;
using MonoDevelop.Ide.Gui;
-using MonoDevelop.Ide.Execution;
using MonoDevelop.Core.Execution;
using MonoDevelop.Ide.TypeSystem;
using System.Threading;
-using ICSharpCode.NRefactory.TypeSystem;
-using Mono.TextEditor;
+using MonoDevelop.Ide.Editor;
using System.Text;
-
namespace MonoDevelop.Components.MainToolbar
{
class MainToolbar: Gtk.EventBox, IMainToolbarView
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 123893630e..76d9eaea10 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarController.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarController.cs
@@ -35,6 +35,7 @@ using Mono.Addins;
using MonoDevelop.Projects;
using MonoDevelop.Core.Execution;
using System.Text;
+using MonoDevelop.Ide.TypeSystem;
namespace MonoDevelop.Components.MainToolbar
{
@@ -107,6 +108,10 @@ namespace MonoDevelop.Components.MainToolbar
IdeApp.ProjectOperations.CurrentSelectedSolutionChanged += HandleCurrentSelectedSolutionChanged;
AddinManager.ExtensionChanged += OnExtensionChanged;
+ MonoDevelopWorkspace.LoadingFinished += delegate {
+ ProjectSearchCategory.UpdateSymbolInfos ();
+ HandleSearchEntryChanged (null, EventArgs.Empty);
+ };
}
public void Initialize ()
@@ -533,7 +538,6 @@ namespace MonoDevelop.Components.MainToolbar
PositionPopup ();
popup.ShowAll ();
}
-
popup.Update (pattern);
}
@@ -545,9 +549,9 @@ namespace MonoDevelop.Components.MainToolbar
var doc = IdeApp.Workbench.ActiveDocument;
if (doc != null && doc.Editor != null) {
doc.Select ();
- doc.Editor.Caret.Location = new Mono.TextEditor.DocumentLocation (pattern.LineNumber, pattern.Column > 0 ? pattern.Column : 1);
+ doc.Editor.CaretLocation = new MonoDevelop.Ide.Editor.DocumentLocation (pattern.LineNumber, pattern.Column > 0 ? pattern.Column : 1);
doc.Editor.CenterToCaret ();
- doc.Editor.Parent.StartCaretPulseAnimation ();
+ doc.Editor.StartCaretPulseAnimation ();
}
return;
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/ProjectSearchCategory.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/ProjectSearchCategory.cs
index 3af7fa2545..1731f08255 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/ProjectSearchCategory.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/ProjectSearchCategory.cs
@@ -32,64 +32,89 @@ using MonoDevelop.Core.Instrumentation;
using MonoDevelop.Projects;
using MonoDevelop.Ide.Gui;
using MonoDevelop.Ide;
-using ICSharpCode.NRefactory.TypeSystem;
using MonoDevelop.Ide.TypeSystem;
using MonoDevelop.Core.Text;
using Gtk;
using System.Linq;
+using ICSharpCode.NRefactory6.CSharp;
+using Microsoft.CodeAnalysis;
+using System.Collections.Immutable;
+using System.Diagnostics;
+using System.Collections.Concurrent;
namespace MonoDevelop.Components.MainToolbar
{
class ProjectSearchCategory : SearchCategory
{
- SearchPopupWindow widget;
+ static SearchPopupWindow widget;
- public ProjectSearchCategory (SearchPopupWindow widget) : base (GettextCatalog.GetString("Solution"))
+ public ProjectSearchCategory (SearchPopupWindow widget) : base (GettextCatalog.GetString ("Solution"))
{
- this.widget = widget;
- this.lastResult = new WorkerResult (widget);
+ ProjectSearchCategory.widget = widget;
+ lastResult = new WorkerResult (widget);
}
+ internal static Task<ImmutableList<DeclaredSymbolInfo>> SymbolInfoTask;
+
static TimerCounter getMembersTimer = InstrumentationService.CreateTimerCounter ("Time to get all members", "NavigateToDialog");
+ static TimerCounter getTypesTimer = InstrumentationService.CreateTimerCounter ("Time to get all types", "NavigateToDialog");
+ static CancellationTokenSource symbolInfoTokenSrc = new CancellationTokenSource();
+ public static void UpdateSymbolInfos ()
+ {
+ symbolInfoTokenSrc.Cancel ();
+ symbolInfoTokenSrc = new CancellationTokenSource();
+ CancellationToken token = symbolInfoTokenSrc.Token;
+ lastResult = new WorkerResult (widget);
+ SymbolInfoTask = Task.Run (delegate {
+ return GetSymbolInfos (token);
+ }, token);
+ }
- static TimerCounter getTypesTimer = InstrumentationService.CreateTimerCounter ("Time to get all types", "NavigateToDialog");
+ static ImmutableList<DeclaredSymbolInfo> GetSymbolInfos (CancellationToken token)
+ {
+ getTypesTimer.BeginTiming ();
+ try {
+ var result = ImmutableList<DeclaredSymbolInfo>.Empty;
+ Stopwatch sw = new Stopwatch();
+ sw.Start ();
+ foreach (var workspace in TypeSystemService.AllWorkspaces) {
+ result = result.AddRange (workspace.CurrentSolution.Projects.Select (p => SearchAsync (p, token)).SelectMany (i => i));
+ }
+ sw.Stop ();
+ return result;
+ } catch (AggregateException ae) {
+ ae.Flatten ().Handle (ex => ex is TaskCanceledException);
+ return ImmutableList<DeclaredSymbolInfo>.Empty;
+ } catch (TaskCanceledException) {
+ return ImmutableList<DeclaredSymbolInfo>.Empty;
+ } finally {
+ getTypesTimer.EndTiming ();
+ }
+ }
- IEnumerable<ITypeDefinition> types {
- get {
- getTypesTimer.BeginTiming ();
+ static IEnumerable<DeclaredSymbolInfo> SearchAsync(Microsoft.CodeAnalysis.Project project, CancellationToken cancellationToken)
+ {
+ var result = new ConcurrentBag<DeclaredSymbolInfo> ();
+ Parallel.ForEach (project.Documents, async delegate (Microsoft.CodeAnalysis.Document document) {
try {
- foreach (Document doc in IdeApp.Workbench.Documents) {
- // We only want to check it here if it's not part
- // of the open combine. Otherwise, it will get
- // checked down below.
- if (doc.Project == null && doc.IsFile) {
- var info = doc.ParsedDocument;
- if (info != null) {
- var ctx = doc.Compilation;
- foreach (var type in ctx.MainAssembly.GetAllTypeDefinitions ()) {
- yield return type;
- }
- }
+ cancellationToken.ThrowIfCancellationRequested ();
+ var root = await document.GetSyntaxRootAsync (cancellationToken).ConfigureAwait (false);
+ foreach (var current in root.DescendantNodesAndSelf (CSharpSyntaxFactsService.DescentIntoSymbolForDeclarationSearch)) {
+ DeclaredSymbolInfo declaredSymbolInfo;
+ if (current.TryGetDeclaredSymbolInfo (out declaredSymbolInfo)) {
+ result.Add (declaredSymbolInfo);
}
}
-
- var projects = IdeApp.Workspace.GetAllProjects ();
-
- foreach (Project p in projects) {
- var pctx = TypeSystemService.GetCompilation (p);
- foreach (var type in pctx.MainAssembly.GetAllTypeDefinitions ())
- yield return type;
- }
- } finally {
- getTypesTimer.EndTiming ();
+ } catch (OperationCanceledException) {
}
- }
+ });
+ return (IEnumerable<DeclaredSymbolInfo>)result;
}
- WorkerResult lastResult;
- string[] typeTags = new [] { "type", "c", "s", "i", "e", "d"};
- string[] memberTags = new [] { "member", "m", "p", "f", "evt"};
+ static WorkerResult lastResult;
+ string[] typeTags = new [] { "type", "c", "s", "i", "e", "d" };
+ string[] memberTags = new [] { "member", "m", "p", "f", "evt" };
public override bool IsValidTag (string tag)
{
@@ -98,7 +123,7 @@ namespace MonoDevelop.Components.MainToolbar
public override Task<ISearchDataSource> GetResults (SearchPopupSearchPattern searchPattern, int resultsCount, CancellationToken token)
{
- return Task.Factory.StartNew (delegate {
+ return Task.Run (delegate {
if (searchPattern.Tag != null && !(typeTags.Contains (searchPattern.Tag) || memberTags.Contains (searchPattern.Tag)) || searchPattern.HasLineNumber)
return null;
try {
@@ -106,11 +131,12 @@ namespace MonoDevelop.Components.MainToolbar
newResult.pattern = searchPattern.Pattern;
newResult.IncludeFiles = true;
newResult.Tag = searchPattern.Tag;
- newResult.IncludeTypes = searchPattern.Tag == null || typeTags.Contains (searchPattern.Tag) ;
+ newResult.IncludeTypes = searchPattern.Tag == null || typeTags.Contains (searchPattern.Tag);
newResult.IncludeMembers = searchPattern.Tag == null || memberTags.Contains (searchPattern.Tag);
- var firstType = types.FirstOrDefault ();
- newResult.ambience = firstType != null ? AmbienceService.GetAmbienceForFile (firstType.Region.FileName) : AmbienceService.DefaultAmbience;
-
+ ImmutableList<DeclaredSymbolInfo> allTypes;
+ if (SymbolInfoTask == null)
+ SymbolInfoTask = Task.FromResult(GetSymbolInfos (token));
+ allTypes = SymbolInfoTask.Result;
string toMatch = searchPattern.Pattern;
newResult.matcher = StringMatcher.GetMatcher (toMatch, false);
newResult.FullSearch = toMatch.IndexOf ('.') > 0;
@@ -119,7 +145,7 @@ namespace MonoDevelop.Components.MainToolbar
oldLastResult = new WorkerResult (widget);
// var now = DateTime.Now;
- AllResults (oldLastResult, newResult, token);
+ AllResults (oldLastResult, newResult, allTypes, token);
newResult.results.SortUpToN (new DataItemComparer (token), resultsCount);
lastResult = newResult;
// Console.WriteLine ((now - DateTime.Now).TotalMilliseconds);
@@ -131,104 +157,58 @@ namespace MonoDevelop.Components.MainToolbar
}, token);
}
- void AllResults (WorkerResult lastResult, WorkerResult newResult, CancellationToken token)
+ void AllResults (WorkerResult lastResult, WorkerResult newResult, IReadOnlyList<DeclaredSymbolInfo> completeTypeList, CancellationToken token)
{
if (newResult.isGotoFilePattern)
return;
uint x = 0;
// Search Types
if (newResult.IncludeTypes && (newResult.Tag == null || typeTags.Any (t => t == newResult.Tag))) {
- newResult.filteredTypes = new List<ITypeDefinition> ();
- bool startsWithLastFilter = lastResult.pattern != null && newResult.pattern.StartsWith (lastResult.pattern, StringComparison.Ordinal) && lastResult.filteredTypes != null;
- var allTypes = startsWithLastFilter ? lastResult.filteredTypes : types;
+ newResult.filteredSymbols = new List<DeclaredSymbolInfo> ();
+ bool startsWithLastFilter = lastResult.pattern != null && newResult.pattern.StartsWith (lastResult.pattern, StringComparison.Ordinal) && lastResult.filteredSymbols != null;
+ var allTypes = startsWithLastFilter ? lastResult.filteredSymbols : completeTypeList;
foreach (var type in allTypes) {
- if (unchecked(x++) % 100 == 0 && token.IsCancellationRequested)
+ if (unchecked(x++) % 100 == 0 && token.IsCancellationRequested) {
+ newResult.filteredSymbols = null;
return;
+ }
+ if (type.Kind == DeclaredSymbolInfoKind.Constructor ||
+ type.Kind == DeclaredSymbolInfoKind.Module ||
+ type.Kind == DeclaredSymbolInfoKind.Indexer)
+ continue;
+
if (newResult.Tag != null) {
- if (newResult.Tag == "c" && type.Kind != TypeKind.Class)
+ if (newResult.Tag == "c" && type.Kind != DeclaredSymbolInfoKind.Class)
continue;
- if (newResult.Tag == "s" && type.Kind != TypeKind.Struct)
+ if (newResult.Tag == "s" && type.Kind != DeclaredSymbolInfoKind.Struct)
continue;
- if (newResult.Tag == "i" && type.Kind != TypeKind.Interface)
+ if (newResult.Tag == "i" && type.Kind != DeclaredSymbolInfoKind.Interface)
continue;
- if (newResult.Tag == "e" && type.Kind != TypeKind.Enum)
+ if (newResult.Tag == "e" && type.Kind != DeclaredSymbolInfoKind.Enum)
+ continue;
+ if (newResult.Tag == "d" && type.Kind != DeclaredSymbolInfoKind.Delegate)
+ continue;
+
+ if (newResult.Tag == "m" && type.Kind != DeclaredSymbolInfoKind.Method)
continue;
- if (newResult.Tag == "d" && type.Kind != TypeKind.Delegate)
+ if (newResult.Tag == "p" && type.Kind != DeclaredSymbolInfoKind.Property)
continue;
+ if (newResult.Tag == "f" && type.Kind != DeclaredSymbolInfoKind.Field)
+ continue;
+ if (newResult.Tag == "evt" && type.Kind != DeclaredSymbolInfoKind.Event)
+ continue;
+
}
SearchResult curResult = newResult.CheckType (type);
if (curResult != null) {
- newResult.filteredTypes.Add (type);
+ newResult.filteredSymbols.Add (type);
newResult.results.AddResult (curResult);
}
}
}
-
- // Search members
- if (newResult.IncludeMembers && (newResult.Tag == null || memberTags.Any (t => t == newResult.Tag))) {
- newResult.filteredMembers = new List<Tuple<ITypeDefinition, IUnresolvedMember>> ();
- bool startsWithLastFilter = lastResult.pattern != null && newResult.pattern.StartsWith (lastResult.pattern, StringComparison.Ordinal) && lastResult.filteredMembers != null;
- if (startsWithLastFilter) {
- foreach (var t in lastResult.filteredMembers) {
- if (unchecked(x++) % 100 == 0 && token.IsCancellationRequested)
- return;
- var member = t.Item2;
- if (newResult.Tag != null) {
- if (newResult.Tag == "m" && member.SymbolKind != SymbolKind.Method)
- continue;
- if (newResult.Tag == "p" && member.SymbolKind != SymbolKind.Property)
- continue;
- if (newResult.Tag == "f" && member.SymbolKind != SymbolKind.Field)
- continue;
- if (newResult.Tag == "evt" && member.SymbolKind != SymbolKind.Event)
- continue;
- }
- SearchResult curResult = newResult.CheckMember (t.Item1, member);
- if (curResult != null) {
- newResult.filteredMembers.Add (t);
- newResult.results.AddResult (curResult);
- }
- }
- } else {
- Func<IUnresolvedMember, bool> mPred = member => {
- if (newResult.Tag != null) {
- if (newResult.Tag == "m" && member.SymbolKind != SymbolKind.Method)
- return false;
- if (newResult.Tag == "p" && member.SymbolKind != SymbolKind.Property)
- return false;
- if (newResult.Tag == "f" && member.SymbolKind != SymbolKind.Field)
- return false;
- if (newResult.Tag == "evt" && member.SymbolKind != SymbolKind.Event)
- return false;
- }
- return newResult.IsMatchingMember (member);
- };
-
- getMembersTimer.BeginTiming ();
- try {
- foreach (var type in types) {
- if (type.Kind == TypeKind.Delegate)
- continue;
- foreach (var p in type.Parts) {
- foreach (var member in p.Members.Where (mPred)) {
- if (unchecked(x++) % 100 == 0 && token.IsCancellationRequested)
- return;
- SearchResult curResult = newResult.CheckMember (type, member);
- if (curResult != null) {
- newResult.filteredMembers.Add (Tuple.Create (type, member));
- newResult.results.AddResult (curResult);
- }
- }
- }
- }
- } finally {
- getMembersTimer.EndTiming ();
- }
- }
- }
}
-
+
class WorkerResult
{
public string Tag {
@@ -236,12 +216,12 @@ namespace MonoDevelop.Components.MainToolbar
set;
}
- public List<ProjectFile> filteredFiles;
- public List<ITypeDefinition> filteredTypes;
- public List<Tuple<ITypeDefinition, IUnresolvedMember>> filteredMembers;
+ public List<DeclaredSymbolInfo> filteredSymbols;
+
string pattern2;
char firstChar;
char[] firstChars;
+
public string pattern {
get {
return pattern2;
@@ -249,76 +229,42 @@ namespace MonoDevelop.Components.MainToolbar
set {
pattern2 = value;
if (pattern2.Length == 1) {
- firstChar = pattern2[0];
+ firstChar = pattern2 [0];
firstChars = new [] { char.ToUpper (firstChar), char.ToLower (firstChar) };
} else {
firstChars = null;
}
}
}
+
public bool isGotoFilePattern;
public ResultsDataSource results;
public bool FullSearch;
public bool IncludeFiles, IncludeTypes, IncludeMembers;
- public Ambience ambience;
public StringMatcher matcher;
-
+
public WorkerResult (Widget widget)
{
results = new ResultsDataSource (widget);
}
-
- internal SearchResult CheckFile (ProjectFile file)
- {
- int rank;
- string matchString = System.IO.Path.GetFileName (file.FilePath);
- if (MatchName (matchString, out rank))
- return new FileSearchResult (pattern, matchString, rank, file, true);
-
- if (!FullSearch)
- return null;
- matchString = FileSearchResult.GetRelProjectPath (file);
- if (MatchName (matchString, out rank))
- return new FileSearchResult (pattern, matchString, rank, file, false);
-
- return null;
- }
-
- internal SearchResult CheckType (ITypeDefinition type)
+
+ internal SearchResult CheckType (DeclaredSymbolInfo symbol)
{
int rank;
- if (MatchName (TypeSearchResult.GetPlainText (type, false), out rank)) {
- if (type.DeclaringType != null)
- rank--;
- return new TypeSearchResult (pattern, TypeSearchResult.GetPlainText (type, false), rank, type, false) { Ambience = ambience };
+ if (MatchName (symbol.Name, out rank)) {
+// if (type.ContainerDisplayName != null)
+// rank--;
+ return new DeclaredSymbolInfoResult (pattern, symbol.Name, rank, symbol, false);
}
if (!FullSearch)
return null;
- if (MatchName (TypeSearchResult.GetPlainText (type, true), out rank)) {
- if (type.DeclaringType != null)
- rank--;
- return new TypeSearchResult (pattern, TypeSearchResult.GetPlainText (type, true), rank, type, true) { Ambience = ambience };
+ if (MatchName (symbol.FullyQualifiedContainerName, out rank)) {
+// if (type.ContainingType != null)
+// rank--;
+ return new DeclaredSymbolInfoResult (pattern, symbol.FullyQualifiedContainerName, rank, symbol, true);
}
return null;
}
-
- internal SearchResult CheckMember (ITypeDefinition declaringType, IUnresolvedMember member)
- {
- int rank;
- bool useDeclaringTypeName = member is IUnresolvedMethod && (((IUnresolvedMethod)member).IsConstructor || ((IUnresolvedMethod)member).IsDestructor);
- string memberName = useDeclaringTypeName ? member.DeclaringTypeDefinition.Name : member.Name;
- if (MatchName (memberName, out rank))
- return new MemberSearchResult (pattern, memberName, rank, declaringType, member, false) { Ambience = ambience };
- return null;
- }
-
- internal bool IsMatchingMember (IUnresolvedMember member)
- {
- int rank;
- bool useDeclaringTypeName = member is IUnresolvedMethod && (((IUnresolvedMethod)member).IsConstructor || ((IUnresolvedMethod)member).IsDestructor);
- string memberName = useDeclaringTypeName ? member.DeclaringTypeDefinition.Name : member.Name;
- return MatchName (memberName, out rank);
- }
Dictionary<string, MatchResult> savedMatches = new Dictionary<string, MatchResult> (StringComparer.Ordinal);
@@ -335,7 +281,7 @@ namespace MonoDevelop.Components.MainToolbar
doesMatch = idx >= 0;
if (doesMatch) {
matchRank = int.MaxValue - (name.Length - 1) * 10 - idx;
- if (name[idx] != firstChar)
+ if (name [idx] != firstChar)
matchRank /= 2;
return true;
} else {
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/ResultsDataSource.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/ResultsDataSource.cs
index 5de97bdd00..d11204909a 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/ResultsDataSource.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/ResultsDataSource.cs
@@ -38,7 +38,7 @@ using MonoDevelop.Core.Instrumentation;
using MonoDevelop.Ide.Gui;
using MonoDevelop.Ide.CodeCompletion;
using MonoDevelop.Components.MainToolbar;
-using ICSharpCode.NRefactory.TypeSystem;
+using MonoDevelop.Core.Text;
namespace MonoDevelop.Components.MainToolbar
{
@@ -134,10 +134,16 @@ namespace MonoDevelop.Components.MainToolbar
return this [item].GetDescriptionMarkupText (widget);
}
- ICSharpCode.NRefactory.TypeSystem.DomRegion ISearchDataSource.GetRegion (int item)
+ ISegment ISearchDataSource.GetRegion (int item)
{
var result = this [item];
- return new DomRegion (result.File, result.Row, result.Column, result.Row, result.Column);
+ return new TextSegment (result.Offset, result.Length);
+ }
+
+ string ISearchDataSource.GetFileName (int item)
+ {
+ var result = this [item];
+ return result.File;
}
bool ISearchDataSource.CanActivate (int item)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/RoundButton.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/RoundButton.cs
index 4a7bd9074a..f7ea8eb214 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/RoundButton.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/RoundButton.cs
@@ -30,8 +30,6 @@ using MonoDevelop.Components;
using Cairo;
using MonoDevelop.Ide;
using System.Reflection;
-using Mono.TextEditor;
-
namespace MonoDevelop.Components.MainToolbar
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchCategory.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchCategory.cs
index 7c15d26c6f..a2b06f8020 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchCategory.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchCategory.cs
@@ -28,7 +28,6 @@ using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
-using ICSharpCode.NRefactory.TypeSystem;
namespace MonoDevelop.Components.MainToolbar
{
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..82f5bdbaea 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchInSolutionSearchCategory.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchInSolutionSearchCategory.cs
@@ -31,6 +31,7 @@ using ICSharpCode.NRefactory.TypeSystem;
using MonoDevelop.Ide.FindInFiles;
using System.Linq;
using MonoDevelop.Ide.Gui;
+using MonoDevelop.Core.Text;
namespace MonoDevelop.Components.MainToolbar
{
@@ -88,9 +89,14 @@ namespace MonoDevelop.Components.MainToolbar
return 0;
}
- DomRegion ISearchDataSource.GetRegion (int item)
+ ISegment ISearchDataSource.GetRegion (int item)
{
- return DomRegion.Empty;
+ return TextSegment.Invalid;
+ }
+
+ string ISearchDataSource.GetFileName (int item)
+ {
+ return null;
}
bool ISearchDataSource.CanActivate (int item)
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 b996ba099c..b062f6ca28 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchPopupWindow.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchPopupWindow.cs
@@ -30,11 +30,11 @@ using MonoDevelop.Core;
using System.Collections.Generic;
using Gtk;
using System.Linq;
-using ICSharpCode.NRefactory.TypeSystem;
using MonoDevelop.Ide;
using MonoDevelop.Ide.CodeCompletion;
using Mono.Addins;
-using Mono.TextEditor;
+using MonoDevelop.Ide.Gui;
+using MonoDevelop.Core.Text;
namespace MonoDevelop.Components.MainToolbar
{
@@ -84,7 +84,13 @@ namespace MonoDevelop.Components.MainToolbar
{
throw new NotImplementedException ();
}
- DomRegion ISearchDataSource.GetRegion (int item)
+
+ ISegment ISearchDataSource.GetRegion (int item)
+ {
+ throw new NotImplementedException ();
+ }
+
+ string ISearchDataSource.GetFileName (int item)
{
throw new NotImplementedException ();
}
@@ -176,16 +182,18 @@ namespace MonoDevelop.Components.MainToolbar
var region = SelectedItemRegion;
Destroy ();
- if (string.IsNullOrEmpty (region.FileName))
+ if (string.IsNullOrEmpty (SelectedItemFileName))
return;
- if (region.Begin.IsEmpty) {
+ if (region.Length <= 0) {
if (Pattern.LineNumber == 0) {
- IdeApp.Workbench.OpenDocument (region.FileName);
+ IdeApp.Workbench.OpenDocument (SelectedItemFileName);
} else {
- IdeApp.Workbench.OpenDocument (region.FileName, Pattern.LineNumber, Pattern.HasColumn ? Pattern.Column : 1);
+ IdeApp.Workbench.OpenDocument (SelectedItemFileName, Pattern.LineNumber, Pattern.HasColumn ? Pattern.Column : 1);
}
} else {
- IdeApp.Workbench.OpenDocument (region.FileName, region.BeginLine, region.BeginColumn);
+ IdeApp.Workbench.OpenDocument (new FileOpenInformation (SelectedItemFileName, null) {
+ Offset = region.Offset
+ });
}
}
}
@@ -226,6 +234,8 @@ namespace MonoDevelop.Components.MainToolbar
LoggingService.LogError ("Error getting search results", t.Exception);
} else {
Application.Invoke (delegate {
+ if (token.IsCancellationRequested)
+ return;
ShowResult (cat, t.Result ?? new NullDataSource ());
});
}
@@ -344,13 +354,13 @@ namespace MonoDevelop.Components.MainToolbar
return new ItemIdentifier (category, dataSrc, i);
}
- var region = dataSrc.GetRegion (i);
- if (!region.Begin.IsEmpty) {
- layout.SetMarkup (region.BeginLine.ToString ());
- int w2, h2;
- layout.GetPixelSize (out w2, out h2);
- w += w2;
- }
+// var region = dataSrc.GetRegion (i);
+// if (!region.IsEmpty) {
+// layout.SetMarkup (region.BeginLine.ToString ());
+// int w2, h2;
+// layout.GetPixelSize (out w2, out h2);
+// w += w2;
+// }
itemsAdded++;
}
if (itemsAdded > 0)
@@ -743,14 +753,22 @@ namespace MonoDevelop.Components.MainToolbar
handler (this, e);
}
- public DomRegion SelectedItemRegion {
+ public ISegment SelectedItemRegion {
get {
if (selectedItem == null || selectedItem.Item < 0 || selectedItem.Item >= selectedItem.DataSource.ItemCount)
- return DomRegion.Empty;
+ return TextSegment.Invalid;
return selectedItem.DataSource.GetRegion (selectedItem.Item);
}
}
+ public string SelectedItemFileName {
+ get {
+ if (selectedItem == null || selectedItem.Item < 0 || selectedItem.Item >= selectedItem.DataSource.ItemCount)
+ return null;
+ return selectedItem.DataSource.GetFileName (selectedItem.Item);
+ }
+ }
+
class ItemIdentifier {
public SearchCategory Category { get; private set; }
public ISearchDataSource DataSource { get; private set; }
@@ -820,13 +838,13 @@ namespace MonoDevelop.Components.MainToolbar
return new Cairo.Rectangle (0, y, Allocation.Width, h + itemSeparatorHeight);
y += h + itemSeparatorHeight;
- var region = dataSrc.GetRegion (i);
- if (!region.Begin.IsEmpty) {
- layout.SetMarkup (region.BeginLine.ToString ());
- int w2, h2;
- layout.GetPixelSize (out w2, out h2);
- w += w2;
- }
+// var region = dataSrc.GetRegion (i);
+// if (!region.IsEmpty) {
+// layout.SetMarkup (region.BeginLine.ToString ());
+// int w2, h2;
+// layout.GetPixelSize (out w2, out h2);
+// w += w2;
+// }
itemsAdded++;
}
if (itemsAdded > 0)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchResult.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchResult.cs
index 4d67e179ff..525016a618 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchResult.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchResult.cs
@@ -31,11 +31,14 @@ using Gtk;
using MonoDevelop.Core;
using MonoDevelop.Core.Text;
using MonoDevelop.Projects;
-using ICSharpCode.NRefactory.TypeSystem;
using MonoDevelop.Ide.TypeSystem;
using MonoDevelop.Components.Commands;
using MonoDevelop.Ide.CodeCompletion;
using MonoDevelop.Ide;
+using Microsoft.CodeAnalysis;
+using System.Linq;
+using ICSharpCode.NRefactory6.CSharp;
+using System.Threading;
namespace MonoDevelop.Components.MainToolbar
{
@@ -58,7 +61,7 @@ namespace MonoDevelop.Components.MainToolbar
public virtual string GetDescriptionMarkupText (Widget widget)
{
- return AmbienceService.EscapeText (Description);
+ return Ambience.EscapeText (Description);
}
@@ -67,8 +70,8 @@ namespace MonoDevelop.Components.MainToolbar
public int Rank { get; private set; }
- public virtual int Row { get { return -1; } }
- public virtual int Column { get { return -1; } }
+ public virtual int Offset { get { return -1; } }
+ public virtual int Length { get { return -1; } }
public abstract string File { get; }
public abstract Xwt.Drawing.Image Icon { get; }
@@ -117,54 +120,49 @@ namespace MonoDevelop.Components.MainToolbar
}
}
- class TypeSearchResult : MemberSearchResult
+ class DeclaredSymbolInfoResult : SearchResult
{
- ITypeDefinition type;
+ bool useFullName;
+
+ DeclaredSymbolInfo type;
public override SearchResultType SearchResultType { get { return SearchResultType.Type; } }
public override string File {
- get { return type.Region.FileName; }
+ get { return type.Node.GetLocation ().SourceTree.FilePath; }
}
public override Xwt.Drawing.Image Icon {
get {
- return ImageService.GetIcon (type.GetStockIcon (false), IconSize.Menu);
+ return ImageService.GetIcon (type.GetStockIconForSymbolInfo(), IconSize.Menu);
}
}
+
- public override int Row {
- get { return type.Region.BeginLine; }
- }
-
- public override int Column {
- get { return type.Region.BeginColumn; }
+ public override int Offset {
+ get { return type.Span.Start; }
}
- public static string GetPlainText (ITypeDefinition type, bool useFullName)
- {
- if (type.TypeParameterCount == 0)
- return useFullName ? type.FullName : type.Name;
- StringBuilder sb = new StringBuilder (useFullName ? type.FullName : type.Name);
- sb.Append ("<");
- for (int i = 0; i < type.TypeParameterCount; i++) {
- if (i > 0)
- sb.Append (", ");
- sb.Append (type.TypeParameters [i].Name);
- }
- sb.Append (">");
- return sb.ToString ();
+ public override int Length {
+ get { return type.Span.Length; }
}
-
+
public override string PlainText {
get {
- return GetPlainText (type, false);
+ return type.Name;
}
}
- public override MonoDevelop.Ide.CodeCompletion.TooltipInformation TooltipInformation {
+ public override TooltipInformation TooltipInformation {
get {
- return Ambience.GetTooltip (type);
+ var docId = TypeSystemService.GetDocuments (type.Node.SyntaxTree.FilePath).FirstOrDefault ();
+ if (docId == null) {
+ return new TooltipInformation ();
+ }
+ var cancellationToken = default(CancellationToken);
+ var task = type.GetSymbolAsync (TypeSystemService.GetCodeAnysisDocument (docId, cancellationToken), cancellationToken);
+ var tooltipInformation = Ambience.GetTooltip (task.Result);
+ return tooltipInformation;
}
}
@@ -172,34 +170,47 @@ namespace MonoDevelop.Components.MainToolbar
get {
string loc;
MonoDevelop.Projects.Project project;
- if (type.TryGetSourceProject (out project)) {
- loc = GettextCatalog.GetString ("project {0}", project.Name);
- } else {
- loc = GettextCatalog.GetString ("file {0}", type.Region.FileName);
- }
+// if (type.TryGetSourceProject (out project)) {
+// loc = GettextCatalog.GetString ("project {0}", project.Name);
+// } else {
+ loc = GettextCatalog.GetString ("file {0}", File);
+// }
switch (type.Kind) {
- case TypeKind.Interface:
+ case DeclaredSymbolInfoKind.Interface:
return GettextCatalog.GetString ("interface ({0})", loc);
- case TypeKind.Struct:
+ case DeclaredSymbolInfoKind.Struct:
return GettextCatalog.GetString ("struct ({0})", loc);
- case TypeKind.Delegate:
+ case DeclaredSymbolInfoKind.Delegate:
return GettextCatalog.GetString ("delegate ({0})", loc);
- case TypeKind.Enum:
+ case DeclaredSymbolInfoKind.Enum:
return GettextCatalog.GetString ("enumeration ({0})", loc);
- default:
+ case DeclaredSymbolInfoKind.Class:
return GettextCatalog.GetString ("class ({0})", loc);
+
+ case DeclaredSymbolInfoKind.Field:
+ return GettextCatalog.GetString ("field ({0})", loc);
+ case DeclaredSymbolInfoKind.Property:
+ return GettextCatalog.GetString ("property ({0})", loc);
+ case DeclaredSymbolInfoKind.Indexer:
+ return GettextCatalog.GetString ("indexer ({0})", loc);
+ case DeclaredSymbolInfoKind.Event:
+ return GettextCatalog.GetString ("event ({0})", loc);
+ case DeclaredSymbolInfoKind.Method:
+ return GettextCatalog.GetString ("method ({0})", loc);
}
+ return GettextCatalog.GetString ("symbol ({0})", loc);
}
}
public override string GetMarkupText (Widget widget)
{
- return HighlightMatch (widget, GetPlainText (type, useFullName), match);
+ return HighlightMatch (widget, useFullName ? type.FullyQualifiedContainerName : type.Name, match);
}
- public TypeSearchResult (string match, string matchedString, int rank, ITypeDefinition type, bool useFullName) : base (match, matchedString, rank, null, null, useFullName)
+ public DeclaredSymbolInfoResult (string match, string matchedString, int rank, DeclaredSymbolInfo type, bool useFullName) : base (match, matchedString, rank)
{
+ this.useFullName = useFullName;
this.type = type;
}
}
@@ -261,99 +272,7 @@ namespace MonoDevelop.Components.MainToolbar
return file.FilePath;
}
}
-
- class MemberSearchResult : SearchResult
- {
- protected bool useFullName;
- protected IUnresolvedMember member;
- protected ITypeDefinition declaringType;
-
- public override SearchResultType SearchResultType { get { return SearchResultType.Member; } }
-
- protected virtual OutputFlags Flags {
- get {
- return OutputFlags.IncludeParameters | OutputFlags.IncludeGenerics
- | (useFullName ? OutputFlags.UseFullName : OutputFlags.None);
- }
- }
-
- public override string PlainText {
- get {
- return member.Name;
- }
- }
-
- public override MonoDevelop.Ide.CodeCompletion.TooltipInformation TooltipInformation {
- get {
- var ctx = member.DeclaringTypeDefinition.CreateResolveContext (new SimpleTypeResolveContext (declaringType));
- return Ambience.GetTooltip (member.Resolve (ctx));
- }
- }
- public override string File {
- get { return member.DeclaringTypeDefinition.Region.FileName; }
- }
-
- public override Xwt.Drawing.Image Icon {
- get {
- return ImageService.GetIcon (member.GetStockIcon (false), IconSize.Menu);
- }
- }
-
- public override int Row {
- get { return member.Region.BeginLine; }
- }
-
- public override int Column {
- get { return member.Region.BeginColumn; }
- }
-
- public override string Description {
- get {
- string loc = GettextCatalog.GetString ("type \"{0}\"", member.DeclaringTypeDefinition.Name);
-
- switch (member.SymbolKind) {
- case SymbolKind.Field:
- return GettextCatalog.GetString ("field ({0})", loc);
- case SymbolKind.Property:
- return GettextCatalog.GetString ("property ({0})", loc);
- case SymbolKind.Indexer:
- return GettextCatalog.GetString ("indexer ({0})", loc);
- case SymbolKind.Event:
- return GettextCatalog.GetString ("event ({0})", loc);
- case SymbolKind.Method:
- return GettextCatalog.GetString ("method ({0})", loc);
- case SymbolKind.Operator:
- return GettextCatalog.GetString ("operator ({0})", loc);
- case SymbolKind.Constructor:
- return GettextCatalog.GetString ("constructor ({0})", loc);
- case SymbolKind.Destructor:
- return GettextCatalog.GetString ("destructor ({0})", loc);
- default:
- throw new NotSupportedException (member.SymbolKind + " is not supported.");
- }
- }
- }
-
- public MemberSearchResult (string match, string matchedString, int rank, ITypeDefinition declaringType, IUnresolvedMember member, bool useFullName) : base (match, matchedString, rank)
- {
- this.declaringType = declaringType;
- this.member = member;
- this.useFullName = useFullName;
- }
-
- public override string GetMarkupText (Widget widget)
- {
- if (useFullName)
- return HighlightMatch (widget, member.SymbolKind == SymbolKind.Constructor ? member.DeclaringTypeDefinition.FullName : member.FullName, match);
- return HighlightMatch (widget, member.SymbolKind == SymbolKind.Constructor ? member.DeclaringTypeDefinition.Name : member.Name, match);
- }
-
- internal Ambience Ambience {
- get;
- set;
- }
- }
class CommandResult: SearchResult
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/StatusArea.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/StatusArea.cs
index a57d05cf83..cfdf239aa3 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/StatusArea.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/StatusArea.cs
@@ -35,8 +35,6 @@ using System.Collections.Generic;
using MonoDevelop.Ide.CodeCompletion;
using MonoDevelop.Core;
using MonoDevelop.Ide.Gui.Components;
-using Mono.TextEditor;
-
using StockIcons = MonoDevelop.Ide.Gui.Stock;
using Xwt.Motion;
using MonoDevelop.Ide.Fonts;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/StatusAreaBuildTheme.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/StatusAreaBuildTheme.cs
index a86dc68ade..ce58e8d373 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/StatusAreaBuildTheme.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/StatusAreaBuildTheme.cs
@@ -27,7 +27,6 @@ using MonoDevelop.Components;
using Cairo;
using StockIcons = MonoDevelop.Ide.Gui.Stock;
-using Mono.TextEditor;
namespace MonoDevelop.Components.MainToolbar
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/StatusAreaTheme.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/StatusAreaTheme.cs
index 8de5c8ebff..2434d1b7df 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/StatusAreaTheme.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/StatusAreaTheme.cs
@@ -37,7 +37,6 @@ using MonoDevelop.Core;
using MonoDevelop.Ide.Gui.Components;
using StockIcons = MonoDevelop.Ide.Gui.Stock;
-using Mono.TextEditor;
namespace MonoDevelop.Components.MainToolbar
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/ExpandableObjectEditor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/ExpandableObjectEditor.cs
new file mode 100644
index 0000000000..a172e7b4d3
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/ExpandableObjectEditor.cs
@@ -0,0 +1,61 @@
+/*
+ * ExpandableObjectEditor.cs - Temporary editor until we get expandable object support in main grid
+ *
+ * Part of PropertyGrid - A Gtk# widget that displays and allows
+ * editing of all of an object's public properties
+ *
+ * Authors:
+ * Michael Hutchinson <m.j.hutchinson@gmail.com>
+ * Lluis Sanchez Gual
+ *
+ * Copyright (C) 2005 Michael Hutchinson
+ *
+ * This sourcecode is licenced under The MIT License:
+ *
+ * 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 Gtk;
+
+namespace MonoDevelop.Components.PropertyGrid.PropertyEditors
+{
+ class ExpandableObjectEditor : PropertyEditorCell
+ {
+ protected override string GetValueMarkup ()
+ {
+ string val;
+ if (Property.Converter.CanConvertTo (Context, typeof(string)))
+ val = Property.Converter.ConvertToString (Context, Value);
+ else
+ val = Value != null ? Value.ToString () : "";
+
+ return "<b>" + GLib.Markup.EscapeText (val) + "</b>";
+ }
+
+ protected override IPropertyEditor CreateEditor (Gdk.Rectangle cell_area, StateType state)
+ {
+ if (Property.Converter.CanConvertTo (Context, typeof(string)) && Property.Converter.CanConvertFrom (Context, typeof(string)))
+ return new PropertyTextEditor ();
+ else
+ return null;
+ }
+
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/TextEditor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/PropertyTextEditor.cs
index 60734be428..841494977e 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/TextEditor.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/PropertyTextEditor.cs
@@ -35,8 +35,8 @@ using Gdk;
namespace MonoDevelop.Components.PropertyGrid.PropertyEditors
{
- [PropertyEditorType (typeof (string))]
- public class TextEditor: HBox, IPropertyEditor
+ [PropertyEditorType (typeof (string))]
+ public class PropertyTextEditor: Gtk.HBox, IPropertyEditor
{
EditSession session;
bool disposed;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/EditorManager.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/EditorManager.cs
index 918ec9865a..19202cda26 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/EditorManager.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/EditorManager.cs
@@ -5,7 +5,7 @@
* editing of all of an object's public properties
*
* Authors:
- * Michael Hutchinson <m.j.hutchinson@gmail.com>
+ * Michael Hutchinson <m.j.hutchinson@gmail.com>
* Lluis Sanchez Gual
*
* Copyright (C) 2005 Michael Hutchinson
@@ -42,11 +42,11 @@ namespace MonoDevelop.Components.PropertyGrid
{
class EditorManager
{
- readonly Dictionary<Type,Type> editors = new Dictionary<Type,Type> ();
+ readonly Dictionary<Type,Type> editors = new Dictionary<Type,Type> ();
readonly Dictionary<Type,Type> inheritingEditors = new Dictionary<Type, Type>();
readonly Dictionary<Type,Type> surrogates = new Dictionary<Type,Type> ();
- static readonly PropertyEditorCell Default = new PropertyEditorCell ();
- static readonly Dictionary<Type,PropertyEditorCell> cellCache = new Dictionary<Type,PropertyEditorCell> ();
+ static readonly PropertyEditorCell Default = new PropertyEditorCell ();
+ static readonly Dictionary<Type,PropertyEditorCell> cellCache = new Dictionary<Type,PropertyEditorCell> ();
public EditorManager ()
{
@@ -57,12 +57,12 @@ namespace MonoDevelop.Components.PropertyGrid
{
foreach (Type t in editorAssembly.GetTypes ()) {
foreach (Attribute currentAttribute in Attribute.GetCustomAttributes (t)) {
- if (currentAttribute.GetType() == typeof (PropertyEditorTypeAttribute)) {
+ if (currentAttribute.GetType() == typeof (PropertyEditorTypeAttribute)) {
var peta = (PropertyEditorTypeAttribute)currentAttribute;
Type editsType = peta.Type;
- if (t.IsSubclassOf (typeof (PropertyEditorCell)))
- if (peta.Inherits)
- inheritingEditors.Add (editsType, t);
+ if (t.IsSubclassOf (typeof (PropertyEditorCell)))
+ if (peta.Inherits)
+ inheritingEditors.Add (editsType, t);
else
editors.Add (editsType, t);
}
@@ -75,105 +75,105 @@ namespace MonoDevelop.Components.PropertyGrid
}
public PropertyEditorCell GetEditor (ITypeDescriptorContext context)
- {
- var cell = context.PropertyDescriptor.GetEditor (typeof(PropertyEditorCell)) as PropertyEditorCell;
- if (cell != null)
- return cell;
-
- Type editorType = GetEditorType (context);
- if (editorType == null)
- return Default;
-
- if (typeof(IPropertyEditor).IsAssignableFrom (editorType)) {
- if (!typeof(Gtk.Widget).IsAssignableFrom (editorType))
- throw new Exception ("The property editor '" + editorType + "' must be a Gtk Widget");
- return Default;
+ {
+ var cell = context.PropertyDescriptor.GetEditor (typeof(PropertyEditorCell)) as PropertyEditorCell;
+ if (cell != null)
+ return cell;
+
+ Type editorType = GetEditorType (context);
+ if (editorType == null)
+ return Default;
+
+ if (typeof(IPropertyEditor).IsAssignableFrom (editorType)) {
+ if (!typeof(Gtk.Widget).IsAssignableFrom (editorType))
+ throw new Exception ("The property editor '" + editorType + "' must be a Gtk Widget");
+ return Default;
}
-
- if (cellCache.TryGetValue (editorType, out cell)) {
+
+ if (cellCache.TryGetValue (editorType, out cell)) {
return cell;
- }
-
- if (!typeof(PropertyEditorCell).IsAssignableFrom (editorType))
- throw new Exception ("The property editor '" + editorType + "' must be a subclass of Stetic.PropertyEditorCell or implement Stetic.IPropertyEditor");
-
- cell = (PropertyEditorCell) Activator.CreateInstance (editorType);
- cellCache [editorType] = cell;
- return cell;
+ }
+
+ if (!typeof(PropertyEditorCell).IsAssignableFrom (editorType))
+ throw new Exception ("The property editor '" + editorType + "' must be a subclass of Stetic.PropertyEditorCell or implement Stetic.IPropertyEditor");
+
+ cell = (PropertyEditorCell) Activator.CreateInstance (editorType);
+ cellCache [editorType] = cell;
+ return cell;
}
-
+
public Type GetEditorType (ITypeDescriptorContext context)
{
var pd = context.PropertyDescriptor;
-
+
//try to find a custom editor
//TODO: Find a way to provide a IWindowsFormsEditorService so this can work directly
//for now, substitute GTK#-based editors
- /*
+ /*
UITypeEditor UITypeEd = (UITypeEditor) pd.GetEditor(typeof (System.Drawing.Design.UITypeEditor));//first, does it have custom editors?
if (UITypeEd != null)
if (surrogates.Contains(UITypeEd.GetType ()))
- return instantiateEditor((Type) surrogates[UITypeEd.GetType()], parentRow);
+ return instantiateEditor((Type) surrogates[UITypeEd.GetType()], parentRow);
*/
//does a registered GTK# editor support this natively?
Type editType = pd.PropertyType;
if (editors.ContainsKey (editType))
- return editors [editType];
-
+ return editors [editType];
+
//editors that edit derived types
- //TODO: find most derived type?
- foreach (var kvp in inheritingEditors)
+ //TODO: find most derived type?
+ foreach (var kvp in inheritingEditors)
if (editType.IsSubclassOf (kvp.Key))
return kvp.Value;
-
- if (pd.PropertyType.IsEnum) {
+
+ if (pd.PropertyType.IsEnum) {
if (pd.PropertyType.IsDefined (typeof(FlagsAttribute), true))
- return typeof(FlagsEditorCell);
- return typeof(EnumerationEditorCell);
- }
-
+ return typeof(FlagsEditorCell);
+ return typeof(EnumerationEditorCell);
+ }
+
//collections with items of single type that aren't just objects
- if (typeof(System.Collections.IList).IsAssignableFrom (editType)) {
- // Iterate through all properties since there may be more than one indexer.
- if (GetCollectionItemType (editType) != null)
- return typeof (CollectionEditor);
- }
+ if (typeof(System.Collections.IList).IsAssignableFrom (editType)) {
+ // Iterate through all properties since there may be more than one indexer.
+ if (GetCollectionItemType (editType) != null)
+ return typeof (CollectionEditor);
+ }
//TODO: support simple SWF collection editor derivatives that just override Types available
// and reflect protected Type[] NewItemTypes {get;} to get types
//if (UITypeEd is System.ComponentModel.Design.CollectionEditor)
- // ((System.ComponentModel.Design.CollectionEditor)UITypeEd).
-
- //can we use a type converter with a built-in editor?
+ // ((System.ComponentModel.Design.CollectionEditor)UITypeEd).
+
+ //can we use a type converter with a built-in editor?
TypeConverter tc = pd.Converter;
//TODO: find best match, not first
foreach (var kvp in editors)
if (tc.CanConvertFrom (kvp.Key) && tc.CanConvertTo (kvp.Key))
- return kvp.Value;
-
- foreach (var kvp in inheritingEditors)
+ return kvp.Value;
+
+ foreach (var kvp in inheritingEditors)
if (tc.CanConvertFrom (kvp.Key) && tc.CanConvertTo (kvp.Key))
return kvp.Value;
if (tc.CanConvertTo (typeof(string)) || tc.GetStandardValuesSupported (context)) {
- return typeof(TextEditor);
+ return typeof(PropertyTextEditor);
}
//nothing found - just display type
return null;
- }
-
- public static Type GetCollectionItemType (Type colType)
- {
- foreach (PropertyInfo member in colType.GetProperties ()) {
- if (member.Name == "Item") {
+ }
+
+ public static Type GetCollectionItemType (Type colType)
+ {
+ foreach (PropertyInfo member in colType.GetProperties ()) {
+ if (member.Name == "Item") {
if (member.PropertyType != typeof (object))
- return member.PropertyType;
- }
- }
+ return member.PropertyType;
+ }
+ }
return null;
}
}
-}
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyEditorCell.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyEditorCell.cs
index c727deb565..7aa4c1407a 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyEditorCell.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyEditorCell.cs
@@ -30,7 +30,6 @@ using System;
using System.ComponentModel;
using Gdk;
using Gtk;
-using Mono.TextEditor;
namespace MonoDevelop.Components.PropertyGrid
{
@@ -161,27 +160,27 @@ namespace MonoDevelop.Components.PropertyGrid
}
}
- /// <summary>
- /// Whether the editor should show a button.
- /// </summary>
- public virtual bool DialogueEdit {
- get { return false; }
- }
-
- /// <summary>
- /// If the property is read-only, is is usually not edited. If the editor
- /// can edit sub-properties of a read-only complex object, this must return true.
- /// <remarks>The default value is false.</remarks>
- /// </summary>
- /// <returns>True if the editor can edit read-only properties</returns>
- public virtual bool EditsReadOnlyObject {
- get { return false; }
- }
-
- public virtual void LaunchDialogue ()
- {
+ /// <summary>
+ /// Whether the editor should show a button.
+ /// </summary>
+ public virtual bool DialogueEdit {
+ get { return false; }
+ }
+
+ /// <summary>
+ /// If the property is read-only, is is usually not edited. If the editor
+ /// can edit sub-properties of a read-only complex object, this must return true.
+ /// <remarks>The default value is false.</remarks>
+ /// </summary>
+ /// <returns>True if the editor can edit read-only properties</returns>
+ public virtual bool EditsReadOnlyObject {
+ get { return false; }
+ }
+
+ public virtual void LaunchDialogue ()
+ {
if (DialogueEdit)
- throw new NotImplementedException ();
+ throw new NotImplementedException ();
}
}
@@ -358,15 +357,15 @@ namespace MonoDevelop.Components.PropertyGrid
this.cell = cell;
Spacing = 3;
PackStart (new CellRendererWidget (cell, context), true, true, 0);
- Label buttonLabel = new Label ();
- buttonLabel.UseMarkup = true;
- buttonLabel.Xpad = 0; buttonLabel.Ypad = 0;
- buttonLabel.Markup = "<span size=\"small\">...</span>";
- Button dialogueButton = new Button (buttonLabel);
- dialogueButton.Clicked += DialogueButtonClicked;
+ Label buttonLabel = new Label ();
+ buttonLabel.UseMarkup = true;
+ buttonLabel.Xpad = 0; buttonLabel.Ypad = 0;
+ buttonLabel.Markup = "<span size=\"small\">...</span>";
+ Button dialogueButton = new Button (buttonLabel);
+ dialogueButton.Clicked += DialogueButtonClicked;
PackStart (dialogueButton, false, false, 0);
this.ModifyBg (StateType.Normal, this.Style.White);
- ShowAll ();
+ ShowAll ();
}
void DialogueButtonClicked (object s, EventArgs args)
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 dbccc8252f..bbbdc96e16 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGridTable.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGridTable.cs
@@ -30,7 +30,6 @@ using System.ComponentModel;
using System.Collections.Generic;
using Cairo;
using System.Linq;
-using Mono.TextEditor;
using MonoDevelop.Core;
namespace MonoDevelop.Components.PropertyGrid
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Theming/GtkTheme.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Theming/GtkTheme.cs
index 95af7f02ab..8dba0ef095 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Theming/GtkTheme.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Theming/GtkTheme.cs
@@ -29,7 +29,6 @@
using System;
using Cairo;
using Gtk;
-using Mono.TextEditor;
namespace MonoDevelop.Components.Theming
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/CairoExtensions.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/CairoExtensions.cs
index 0b948cd7d0..3a21270833 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/CairoExtensions.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/CairoExtensions.cs
@@ -33,7 +33,6 @@ using System.Runtime.InteropServices;
using Gdk;
using Cairo;
using MonoDevelop.Core;
-using Mono.TextEditor;
namespace MonoDevelop.Components
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/CompactScrolledWindow.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/CompactScrolledWindow.cs
index aef0dcf873..e6f0c23f4b 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/CompactScrolledWindow.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/CompactScrolledWindow.cs
@@ -25,7 +25,6 @@
// THE SOFTWARE.
using System;
-using Mono.TextEditor;
namespace MonoDevelop.Components
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsGtk.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsGtk.cs
index 52607bf131..035a36cb79 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsGtk.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsGtk.cs
@@ -50,7 +50,7 @@ namespace MonoDevelop.Components
if (menu == null)
throw new ArgumentNullException ("menu");
- Mono.TextEditor.GtkWorkarounds.ShowContextMenu (menu, parent, evt);
+ GtkWorkarounds.ShowContextMenu (menu, parent, evt);
}
static Gtk.MenuItem CreateMenuItem (ContextMenuItem item)
@@ -93,7 +93,7 @@ namespace MonoDevelop.Components
var img = new ImageView (item.Image);
img.ShowAll ();
imageItem.Image = img;
- GtkWorkarounds.ForceImageOnMenuItem (imageItem);
+ Xwt.GtkBackend.GtkWorkarounds.ForceImageOnMenuItem (imageItem);
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuTreeView.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuTreeView.cs
index a0e32d669e..c6ea099579 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuTreeView.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuTreeView.cs
@@ -24,7 +24,6 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
-using Mono.TextEditor;
namespace MonoDevelop.Components
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Control.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Control.cs
index dda73fc351..2cd9d466c5 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Control.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Control.cs
@@ -43,6 +43,8 @@ namespace MonoDevelop.Components
public Control (object widget)
{
+ if (widget == null)
+ throw new ArgumentNullException ("widget");
this.nativeWidget = widget;
}
@@ -63,7 +65,9 @@ namespace MonoDevelop.Components
if (!(w is T))
w = ConvertToType (typeof(T), w);
if (w is Gtk.Widget) {
- var c = new CommandRouterContainer ((Gtk.Widget)w, this, true);
+ var gtkWidget = (Gtk.Widget)w;
+ var c = new CommandRouterContainer (gtkWidget, this, true);
+ c.FocusChain = new [] { gtkWidget };
c.Show ();
nativeWidget = c;
c.Destroyed += delegate {
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/DropDownBox.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/DropDownBox.cs
index 1f02fdce8a..df6e49c424 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/DropDownBox.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/DropDownBox.cs
@@ -29,7 +29,6 @@ using System.ComponentModel;
using Gtk;
using MonoDevelop.Ide;
-using Mono.TextEditor;
namespace MonoDevelop.Components
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkGestures.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkGestures.cs
new file mode 100644
index 0000000000..a819fc0f74
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkGestures.cs
@@ -0,0 +1,252 @@
+//
+// GtkGestures.cs
+//
+// Author:
+// Michael Hutchinson <mhutch@xamarin.com>
+//
+// Copyright (c) 2012 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 System.Runtime.InteropServices;
+using Gdk;
+
+namespace MonoDevelop.Components
+{
+ public static class GtkGestures
+ {
+ const int GDK_GESTURE_MAGNIFY = 37;
+ const int GDK_GESTURE_ROTATE = 38;
+ const int GDK_GESTURE_SWIPE = 39;
+
+ [DllImport (PangoUtil.LIBGDK, CallingConvention = CallingConvention.Cdecl)]
+ static extern bool gdk_quartz_supports_gesture_events ();
+
+ static bool isSupported;
+
+ static GtkGestures ()
+ {
+ if (MonoDevelop.Core.Platform.IsMac) {
+ try {
+ isSupported = gdk_quartz_supports_gesture_events ();
+ } catch (EntryPointNotFoundException) {
+ }
+ }
+ }
+
+ public static bool IsSupported { get { return isSupported; } }
+
+ public static void AddGestureMagnifyHandler (this Gtk.Widget widget, EventHandler<GestureMagnifyEventArgs> handler)
+ {
+ if (!isSupported)
+ throw new NotSupportedException ();
+ var signal = GLib.Signal.Lookup (widget, "gesture-magnify-event", typeof(GestureMagnifyEventArgs));
+ signal.AddDelegate (new EventHandler<GestureMagnifyEventArgs> (handler));
+ }
+
+ public static void AddGestureRotateHandler (this Gtk.Widget widget, EventHandler<GestureRotateEventArgs> handler)
+ {
+ if (!isSupported)
+ throw new NotSupportedException ();
+ var signal = GLib.Signal.Lookup (widget, "gesture-rotate-event", typeof(GestureRotateEventArgs));
+ signal.AddDelegate (new EventHandler<GestureRotateEventArgs> (handler));
+ }
+
+ public static void AddGestureSwipeHandler (this Gtk.Widget widget, EventHandler<GestureSwipeEventArgs> handler)
+ {
+ if (!isSupported)
+ throw new NotSupportedException ();
+ var signal = GLib.Signal.Lookup (widget, "gesture-swipe-event", typeof(GestureSwipeEventArgs));
+ signal.AddDelegate (new EventHandler<GestureSwipeEventArgs> (handler));
+ }
+ }
+
+ public unsafe class GestureMagnifyEventArgs : GLib.SignalArgs
+ {
+ //have to force pack=4, or Mono aligns doubles to 8 bytes
+ [StructLayout (LayoutKind.Sequential, Pack=4)]
+ struct GdkEventGestureMagnify
+ {
+ public Gdk.EventType type;
+ public IntPtr window;
+ public sbyte send_event;
+ public uint time;
+ public double x, y;
+ public uint state;
+ public double magnification;
+ public IntPtr device;
+ public double x_root, y_root;
+ }
+
+ // I tried to mimic the GTK# pattern of having a subclassed Event object on the EventArgs, but I gave up on
+ // figuring out how to get GTK# to marshal the event to a custom GestureMagnifyEvent class. Instead we just
+ // lift all the accessors up to the args class and dereference the handle directly.
+ GdkEventGestureMagnify *evt {
+ get {
+ var handle = ((Event)Args[0]).Handle;
+ return (GdkEventGestureMagnify *) handle;
+ }
+ }
+
+ public Gdk.Window Window {
+ get {
+ return (Gdk.Window) GLib.Object.GetObject (evt->window);
+ }
+ }
+
+ public Device Device {
+ get {
+ return (Device) GLib.Object.GetObject (evt->device);
+ }
+ }
+
+ public uint Time { get { return evt->time; } }
+ public double X { get { return evt->x; } }
+ public double Y { get { return evt->y; } }
+ public ModifierType State { get { return (ModifierType) evt->state; } }
+ public double Magnification { get { return evt->magnification; } }
+ public double XRoot { get { return evt->x_root; } }
+ public double YRoot { get { return evt->y_root; } }
+ }
+
+ public unsafe class GestureRotateEventArgs : GLib.SignalArgs
+ {
+ [StructLayout (LayoutKind.Sequential, Pack=4)]
+ struct GdkEventGestureRotate
+ {
+ public Gdk.EventType type;
+ public IntPtr window;
+ public sbyte send_event;
+ public uint time;
+ public double x, y;
+ public uint state;
+ public double rotation;
+ public IntPtr device;
+ public double x_root, y_root;
+ }
+
+ GdkEventGestureRotate *evt {
+ get {
+ var handle = ((Event)Args[0]).Handle;
+ return (GdkEventGestureRotate *) handle;
+ }
+ }
+
+ public Gdk.Window Window {
+ get {
+ return (Gdk.Window) GLib.Object.GetObject (evt->window);
+ }
+ }
+
+ public Device Device {
+ get {
+ return (Device) GLib.Object.GetObject (evt->device);
+ }
+ }
+
+ public uint Time { get { return evt->time; } }
+ public double X { get { return evt->x; } }
+ public double Y { get { return evt->y; } }
+ public ModifierType State { get { return (ModifierType) evt->state; } }
+ public double Rotation { get { return evt->rotation; } }
+ public double XRoot { get { return evt->x_root; } }
+ public double YRoot { get { return evt->y_root; } }
+ }
+
+ public unsafe class GestureSwipeEventArgs : GLib.SignalArgs
+ {
+ [StructLayout (LayoutKind.Sequential, Pack=4)]
+ struct GdkEventGestureSwipe
+ {
+ public Gdk.EventType type;
+ public IntPtr window;
+ public sbyte send_event;
+ public uint time;
+ public double x, y;
+ public uint state;
+ public double delta_x, delta_y;
+ public IntPtr device;
+ public double x_root, y_root;
+ }
+
+ GdkEventGestureSwipe *evt {
+ get {
+ var handle = ((Event)Args[0]).Handle;
+ return (GdkEventGestureSwipe *) handle;
+ }
+ }
+
+ public Gdk.Window Window {
+ get {
+ return (Gdk.Window) GLib.Object.GetObject (evt->window);
+ }
+ }
+
+ public Device Device {
+ get {
+ return (Device) GLib.Object.GetObject (evt->device);
+ }
+ }
+
+ public uint Time { get { return evt->time; } }
+ public double X { get { return evt->x; } }
+ public double Y { get { return evt->y; } }
+ public ModifierType State { get { return (ModifierType) evt->state; } }
+ public double DeltaX { get { return evt->delta_x; } }
+ public double DeltaY { get { return evt->delta_y; } }
+ public double XRoot { get { return evt->x_root; } }
+ public double YRoot { get { return evt->y_root; } }
+ }
+
+ /*
+ void PrintOffsets ()
+ {
+ GdkEventGestureMagnify *v = (GdkEventGestureMagnify *)0;
+ Console.WriteLine ("type {0}", (int)&(v->type));
+ Console.WriteLine ("window {0}", (int)&(v->window));
+ Console.WriteLine ("send_event {0}", (int)&(v->send_event));
+ Console.WriteLine ("time {0}", (int)&(v->time));
+ Console.WriteLine ("x {0}", (int)&(v->x));
+ Console.WriteLine ("y {0}", (int)&(v->y));
+ Console.WriteLine ("state {0}", (int)&(v->state));
+ Console.WriteLine ("magnification {0}", (int)&(v->magnification));
+ Console.WriteLine ("x_root {0}", (int)&(v->x_root));
+ Console.WriteLine ("y_root {0}", (int)&(v->y_root));
+ }
+
+ // gcc -m32 test.c `pkg-config --cflags gtk+-2.0`
+ #include <gtk/gtk.h>
+
+ int main (int argc, char* argv)
+ {
+ GdkEventGestureMagnify *v = (GdkEventGestureMagnify *)0;
+ printf ("type %d\n", (int)&(v->type));
+ printf ("window %d\n", (int)&(v->window));
+ printf ("send_event %d\n", (int)&(v->send_event));
+ printf ("time %d\n", (int)&(v->time));
+ printf ("x %d\n", (int)&(v->x));
+ printf ("y %d\n", (int)&(v->y));
+ printf ("state %d\n", (int)&(v->state));
+ printf ("magnification %d\n", (int)&(v->magnification));
+ printf ("x_root %d\n", (int)&(v->x_root));
+ printf ("y_root %d\n", (int)&(v->y_root));
+ }
+ */
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkUtil.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkUtil.cs
index 5818c33e5b..a083d352f2 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkUtil.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkUtil.cs
@@ -88,6 +88,19 @@ namespace MonoDevelop.Components
return c.ToGdkColor ();
}
+ /// <summary>
+ /// Makes a color lighter or darker
+ /// </summary>
+ /// <param name='lightAmount'>
+ /// Amount of lightness to add. If the value is positive, the color will be lighter,
+ /// if negative it will be darker. Value must be between 0 and 1.
+ /// </param>
+ public static HslColor AddLight (this HslColor color, double lightAmount)
+ {
+ color.L += lightAmount;
+ return color;
+ }
+
public static Cairo.Color AddLight (this Cairo.Color color, double lightAmount)
{
var c = color.ToXwtColor ();
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkWorkarounds.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkWorkarounds.cs
new file mode 100644
index 0000000000..398ae0e0e9
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkWorkarounds.cs
@@ -0,0 +1,1275 @@
+//
+// GtkWorkarounds.cs
+//
+// Authors: Jeffrey Stedfast <jeff@xamarin.com>
+//
+// Copyright (C) 2011 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.Drawing;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Reflection.Emit;
+using Gtk;
+using MonoDevelop.Core;
+using MonoDevelop.Ide.Editor.Highlighting;
+using System.Text.RegularExpressions;
+
+namespace MonoDevelop.Components
+{
+ public static class GtkWorkarounds
+ {
+ const string LIBOBJC ="/usr/lib/libobjc.dylib";
+ const string USER32DLL = "User32.dll";
+
+ [DllImport (LIBOBJC, EntryPoint = "sel_registerName")]
+ static extern IntPtr sel_registerName (string selector);
+
+ [DllImport (LIBOBJC, EntryPoint = "objc_getClass")]
+ static extern IntPtr objc_getClass (string klass);
+
+ [DllImport (LIBOBJC, EntryPoint = "objc_msgSend")]
+ static extern IntPtr objc_msgSend_IntPtr (IntPtr klass, IntPtr selector);
+
+ [DllImport (LIBOBJC, EntryPoint = "objc_msgSend")]
+ static extern void objc_msgSend_void_bool (IntPtr klass, IntPtr selector, bool arg);
+
+ [DllImport (LIBOBJC, EntryPoint = "objc_msgSend")]
+ static extern bool objc_msgSend_bool (IntPtr klass, IntPtr selector);
+
+ [DllImport (LIBOBJC, EntryPoint = "objc_msgSend")]
+ static extern int objc_msgSend_NSInt32_NSInt32 (IntPtr klass, IntPtr selector, int arg);
+
+ [DllImport (LIBOBJC, EntryPoint = "objc_msgSend")]
+ static extern long objc_msgSend_NSInt64_NSInt64 (IntPtr klass, IntPtr selector, long arg);
+
+ [DllImport (LIBOBJC, EntryPoint = "objc_msgSend")]
+ static extern uint objc_msgSend_NSUInt32 (IntPtr klass, IntPtr selector);
+
+ [DllImport (LIBOBJC, EntryPoint = "objc_msgSend")]
+ static extern ulong objc_msgSend_NSUInt64 (IntPtr klass, IntPtr selector);
+
+ [DllImport (LIBOBJC, EntryPoint = "objc_msgSend_stret")]
+ static extern void objc_msgSend_CGRect32 (out CGRect32 rect, IntPtr klass, IntPtr selector);
+
+ [DllImport (LIBOBJC, EntryPoint = "objc_msgSend_stret")]
+ static extern void objc_msgSend_CGRect64 (out CGRect64 rect, IntPtr klass, IntPtr selector);
+
+ [DllImport (PangoUtil.LIBQUARTZ)]
+ static extern IntPtr gdk_quartz_window_get_nswindow (IntPtr window);
+
+ [DllImport (PangoUtil.LIBQUARTZ)]
+ static extern bool gdk_window_has_embedded_nsview_focus (IntPtr window);
+
+ struct CGRect32
+ {
+ public float X, Y, Width, Height;
+ }
+
+ struct CGRect64
+ {
+ public double X, Y, Width, Height;
+
+ public CGRect64 (CGRect32 rect32)
+ {
+ X = rect32.X;
+ Y = rect32.Y;
+ Width = rect32.Width;
+ Height = rect32.Height;
+ }
+ }
+
+ static IntPtr cls_NSScreen;
+ static IntPtr sel_screens, sel_objectEnumerator, sel_nextObject, sel_frame, sel_visibleFrame,
+ sel_requestUserAttention, sel_setHasShadow, sel_invalidateShadow;
+ static IntPtr sharedApp;
+ static IntPtr cls_NSEvent;
+ static IntPtr sel_modifierFlags;
+
+ const int NSCriticalRequest = 0;
+ const int NSInformationalRequest = 10;
+
+ static System.Reflection.MethodInfo glibObjectGetProp, glibObjectSetProp;
+
+ public static int GtkMinorVersion = 12, GtkMicroVersion = 0;
+ static bool oldMacKeyHacks = false;
+
+ static GtkWorkarounds ()
+ {
+ if (Platform.IsMac) {
+ InitMac ();
+ }
+
+ var flags = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic;
+ glibObjectSetProp = typeof (GLib.Object).GetMethod ("SetProperty", flags);
+ glibObjectGetProp = typeof (GLib.Object).GetMethod ("GetProperty", flags);
+
+ foreach (int i in new [] { 24, 22, 20, 18, 16, 14 }) {
+ if (Gtk.Global.CheckVersion (2, (uint)i, 0) == null) {
+ GtkMinorVersion = i;
+ break;
+ }
+ }
+
+ for (int i = 1; i < 20; i++) {
+ if (Gtk.Global.CheckVersion (2, (uint)GtkMinorVersion, (uint)i) == null) {
+ GtkMicroVersion = i;
+ } else {
+ break;
+ }
+ }
+
+ //opt into the fixes on GTK+ >= 2.24.8
+ if (Platform.IsMac) {
+ try {
+ gdk_quartz_set_fix_modifiers (true);
+ } catch (EntryPointNotFoundException) {
+ oldMacKeyHacks = true;
+ }
+ }
+
+ keymap.KeysChanged += delegate {
+ mappedKeys.Clear ();
+ };
+ }
+
+ static void InitMac ()
+ {
+ cls_NSScreen = objc_getClass ("NSScreen");
+ cls_NSEvent = objc_getClass ("NSEvent");
+ sel_screens = sel_registerName ("screens");
+ sel_objectEnumerator = sel_registerName ("objectEnumerator");
+ sel_nextObject = sel_registerName ("nextObject");
+ sel_visibleFrame = sel_registerName ("visibleFrame");
+ sel_frame = sel_registerName ("frame");
+ sel_requestUserAttention = sel_registerName ("requestUserAttention:");
+ sel_modifierFlags = sel_registerName ("modifierFlags");
+ sel_setHasShadow = sel_registerName ("setHasShadow:");
+ sel_invalidateShadow = sel_registerName ("invalidateShadow");
+ sharedApp = objc_msgSend_IntPtr (objc_getClass ("NSApplication"), sel_registerName ("sharedApplication"));
+ }
+
+ static Gdk.Rectangle MacGetUsableMonitorGeometry (Gdk.Screen screen, int monitor)
+ {
+ IntPtr array = objc_msgSend_IntPtr (cls_NSScreen, sel_screens);
+ IntPtr iter = objc_msgSend_IntPtr (array, sel_objectEnumerator);
+ Gdk.Rectangle ygeometry = screen.GetMonitorGeometry (monitor);
+ Gdk.Rectangle xgeometry = screen.GetMonitorGeometry (0);
+ IntPtr scrn;
+ int i = 0;
+
+ while ((scrn = objc_msgSend_IntPtr (iter, sel_nextObject)) != IntPtr.Zero && i < monitor)
+ i++;
+
+ if (scrn == IntPtr.Zero)
+ return screen.GetMonitorGeometry (monitor);
+
+ CGRect64 visible, frame;
+
+ if (IntPtr.Size == 8) {
+ objc_msgSend_CGRect64 (out visible, scrn, sel_visibleFrame);
+ objc_msgSend_CGRect64 (out frame, scrn, sel_frame);
+ } else {
+ CGRect32 visible32, frame32;
+ objc_msgSend_CGRect32 (out visible32, scrn, sel_visibleFrame);
+ objc_msgSend_CGRect32 (out frame32, scrn, sel_frame);
+ visible = new CGRect64 (visible32);
+ frame = new CGRect64 (frame32);
+ }
+
+ // Note: Frame and VisibleFrame rectangles are relative to monitor 0, but we need absolute
+ // coordinates.
+ visible.X += xgeometry.X;
+ frame.X += xgeometry.X;
+
+ // VisibleFrame.Y is the height of the Dock if it is at the bottom of the screen, so in order
+ // to get the menu height, we just figure out the difference between the visibleFrame height
+ // and the actual frame height, then subtract the Dock height.
+ //
+ // We need to swap the Y offset with the menu height because our callers expect the Y offset
+ // to be from the top of the screen, not from the bottom of the screen.
+ double x, y, width, height;
+
+ if (visible.Height < frame.Height) {
+ double dockHeight = visible.Y - frame.Y;
+ double menubarHeight = (frame.Height - visible.Height) - dockHeight;
+
+ height = frame.Height - menubarHeight - dockHeight;
+ y = ygeometry.Y + menubarHeight;
+ } else {
+ height = frame.Height;
+ y = ygeometry.Y;
+ }
+
+ // Takes care of the possibility of the Dock being positioned on the left or right edge of the screen.
+ width = System.Math.Min (visible.Width, frame.Width);
+ x = System.Math.Max (visible.X, frame.X);
+
+ return new Gdk.Rectangle ((int) x, (int) y, (int) width, (int) height);
+ }
+
+ static void MacRequestAttention (bool critical)
+ {
+ int kind = critical? NSCriticalRequest : NSInformationalRequest;
+ if (IntPtr.Size == 8) {
+ objc_msgSend_NSInt64_NSInt64 (sharedApp, sel_requestUserAttention, kind);
+ } else {
+ objc_msgSend_NSInt32_NSInt32 (sharedApp, sel_requestUserAttention, kind);
+ }
+ }
+
+ // Note: we can't reuse RectangleF because the layout is different...
+ [StructLayout (LayoutKind.Sequential)]
+ struct Rect {
+ public int Left;
+ public int Top;
+ public int Right;
+ public int Bottom;
+
+ public int X { get { return Left; } }
+ public int Y { get { return Top; } }
+ public int Width { get { return Right - Left; } }
+ public int Height { get { return Bottom - Top; } }
+ }
+
+ const int MonitorInfoFlagsPrimary = 0x01;
+
+ [StructLayout (LayoutKind.Sequential)]
+ unsafe struct MonitorInfo {
+ public int Size;
+ public Rect Frame; // Monitor
+ public Rect VisibleFrame; // Work
+ public int Flags;
+ public fixed byte Device[32];
+ }
+
+ [UnmanagedFunctionPointer (CallingConvention.Winapi)]
+ delegate int EnumMonitorsCallback (IntPtr hmonitor, IntPtr hdc, IntPtr prect, IntPtr user_data);
+
+ [DllImport (USER32DLL)]
+ extern static int EnumDisplayMonitors (IntPtr hdc, IntPtr clip, EnumMonitorsCallback callback, IntPtr user_data);
+
+ [DllImport (USER32DLL)]
+ extern static int GetMonitorInfoA (IntPtr hmonitor, ref MonitorInfo info);
+
+ static Gdk.Rectangle WindowsGetUsableMonitorGeometry (Gdk.Screen screen, int monitor_id)
+ {
+ Gdk.Rectangle geometry = screen.GetMonitorGeometry (monitor_id);
+ List<MonitorInfo> screens = new List<MonitorInfo> ();
+
+ EnumDisplayMonitors (IntPtr.Zero, IntPtr.Zero, delegate (IntPtr hmonitor, IntPtr hdc, IntPtr prect, IntPtr user_data) {
+ var info = new MonitorInfo ();
+
+ unsafe {
+ info.Size = sizeof (MonitorInfo);
+ }
+
+ GetMonitorInfoA (hmonitor, ref info);
+
+ // In order to keep the order the same as Gtk, we need to put the primary monitor at the beginning.
+ if ((info.Flags & MonitorInfoFlagsPrimary) != 0)
+ screens.Insert (0, info);
+ else
+ screens.Add (info);
+
+ return 1;
+ }, IntPtr.Zero);
+
+ MonitorInfo monitor = screens[monitor_id];
+ Rect visible = monitor.VisibleFrame;
+ Rect frame = monitor.Frame;
+
+ // Rebase the VisibleFrame off of Gtk's idea of this monitor's geometry (since they use different coordinate systems)
+ int x = geometry.X + (visible.Left - frame.Left);
+ int width = visible.Width;
+
+ int y = geometry.Y + (visible.Top - frame.Top);
+ int height = visible.Height;
+
+ return new Gdk.Rectangle (x, y, width, height);
+ }
+
+ public static Gdk.Rectangle GetUsableMonitorGeometry (this Gdk.Screen screen, int monitor)
+ {
+ if (Platform.IsWindows)
+ return WindowsGetUsableMonitorGeometry (screen, monitor);
+
+ if (Platform.IsMac)
+ return MacGetUsableMonitorGeometry (screen, monitor);
+
+ return screen.GetMonitorGeometry (monitor);
+ }
+
+ public static int RunDialogWithNotification (Gtk.Dialog dialog)
+ {
+ if (Platform.IsMac)
+ MacRequestAttention (dialog.Modal);
+
+ return dialog.Run ();
+ }
+
+ public static void PresentWindowWithNotification (this Gtk.Window window)
+ {
+ window.Present ();
+
+ if (Platform.IsMac) {
+ var dialog = window as Gtk.Dialog;
+ MacRequestAttention (dialog == null? false : dialog.Modal);
+ }
+ }
+
+ public static GLib.Value GetProperty (this GLib.Object obj, string name)
+ {
+ return (GLib.Value) glibObjectGetProp.Invoke (obj, new object[] { name });
+ }
+
+ public static void SetProperty (this GLib.Object obj, string name, GLib.Value value)
+ {
+ glibObjectSetProp.Invoke (obj, new object[] { name, value });
+ }
+
+ public static bool TriggersContextMenu (this Gdk.EventButton evt)
+ {
+ return evt.Type == Gdk.EventType.ButtonPress && IsContextMenuButton (evt);
+ }
+
+ public static bool IsContextMenuButton (this Gdk.EventButton evt)
+ {
+ if (evt.Button == 3 &&
+ (evt.State & (Gdk.ModifierType.Button1Mask | Gdk.ModifierType.Button2Mask)) == 0)
+ return true;
+
+ if (Platform.IsMac) {
+ if (!oldMacKeyHacks &&
+ evt.Button == 1 &&
+ (evt.State & Gdk.ModifierType.ControlMask) != 0 &&
+ (evt.State & (Gdk.ModifierType.Button2Mask | Gdk.ModifierType.Button3Mask)) == 0)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public static Gdk.ModifierType GetCurrentKeyModifiers ()
+ {
+ if (Platform.IsMac) {
+ Gdk.ModifierType mtype = Gdk.ModifierType.None;
+ ulong mod;
+ if (IntPtr.Size == 8) {
+ mod = objc_msgSend_NSUInt64 (cls_NSEvent, sel_modifierFlags);
+ } else {
+ mod = objc_msgSend_NSUInt32 (cls_NSEvent, sel_modifierFlags);
+ }
+ if ((mod & (1 << 17)) != 0)
+ mtype |= Gdk.ModifierType.ShiftMask;
+ if ((mod & (1 << 18)) != 0)
+ mtype |= Gdk.ModifierType.ControlMask;
+ if ((mod & (1 << 19)) != 0)
+ mtype |= Gdk.ModifierType.Mod1Mask; // Alt key
+ if ((mod & (1 << 20)) != 0)
+ mtype |= Gdk.ModifierType.Mod2Mask; // Command key
+ return mtype;
+ }
+ else {
+ Gdk.ModifierType mtype;
+ Gtk.Global.GetCurrentEventState (out mtype);
+ return mtype;
+ }
+ }
+
+ public static void GetPageScrollPixelDeltas (this Gdk.EventScroll evt, double pageSizeX, double pageSizeY,
+ out double deltaX, out double deltaY)
+ {
+ if (!GetEventScrollDeltas (evt, out deltaX, out deltaY)) {
+ var direction = evt.Direction;
+ deltaX = deltaY = 0;
+ if (pageSizeY != 0 && (direction == Gdk.ScrollDirection.Down || direction == Gdk.ScrollDirection.Up)) {
+ deltaY = System.Math.Pow (pageSizeY, 2.0 / 3.0);
+ deltaX = 0.0;
+ if (direction == Gdk.ScrollDirection.Up)
+ deltaY = -deltaY;
+ } else if (pageSizeX != 0) {
+ deltaX = System.Math.Pow (pageSizeX, 2.0 / 3.0);
+ deltaY = 0.0;
+ if (direction == Gdk.ScrollDirection.Left)
+ deltaX = -deltaX;
+ }
+ }
+ }
+
+ public static void AddValueClamped (this Gtk.Adjustment adj, double value)
+ {
+ adj.Value = System.Math.Max (adj.Lower, System.Math.Min (adj.Value + value, adj.Upper - adj.PageSize));
+ }
+
+ [DllImport (PangoUtil.LIBGTK, CallingConvention = CallingConvention.Cdecl)]
+ extern static bool gdk_event_get_scroll_deltas (IntPtr eventScroll, out double deltaX, out double deltaY);
+ static bool scrollDeltasNotSupported;
+
+ public static bool GetEventScrollDeltas (Gdk.EventScroll evt, out double deltaX, out double deltaY)
+ {
+ if (!scrollDeltasNotSupported) {
+ try {
+ return gdk_event_get_scroll_deltas (evt.Handle, out deltaX, out deltaY);
+ } catch (EntryPointNotFoundException) {
+ scrollDeltasNotSupported = true;
+ }
+ }
+ deltaX = deltaY = 0;
+ return false;
+ }
+
+ /// <summary>Shows a context menu.</summary>
+ /// <param name='menu'>The menu.</param>
+ /// <param name='parent'>The parent widget.</param>
+ /// <param name='evt'>The mouse event. May be null if triggered by keyboard.</param>
+ /// <param name='caret'>The caret/selection position within the parent, if the EventButton is null.</param>
+ public static void ShowContextMenu (Gtk.Menu menu, Gtk.Widget parent, Gdk.EventButton evt, Gdk.Rectangle caret)
+ {
+ Gtk.MenuPositionFunc posFunc = null;
+
+ if (parent != null) {
+ menu.AttachToWidget (parent, null);
+ menu.Hidden += (sender, e) => {
+ if (menu.AttachWidget != null)
+ menu.Detach ();
+ };
+ posFunc = delegate (Gtk.Menu m, out int x, out int y, out bool pushIn) {
+ Gdk.Window window = evt != null? evt.Window : parent.GdkWindow;
+ window.GetOrigin (out x, out y);
+ var alloc = parent.Allocation;
+ if (evt != null) {
+ x += (int) evt.X;
+ y += (int) evt.Y;
+ } else if (caret.X >= alloc.X && caret.Y >= alloc.Y) {
+ x += caret.X;
+ y += caret.Y + caret.Height;
+ } else {
+ x += alloc.X;
+ y += alloc.Y;
+ }
+ Gtk.Requisition request = m.SizeRequest ();
+ var screen = parent.Screen;
+ Gdk.Rectangle geometry = GetUsableMonitorGeometry (screen, screen.GetMonitorAtPoint (x, y));
+
+ //whether to push or flip menus that would extend offscreen
+ //FIXME: this is the correct behaviour for mac, check other platforms
+ bool flip_left = true;
+ bool flip_up = false;
+
+ if (x + request.Width > geometry.X + geometry.Width) {
+ if (flip_left) {
+ x -= request.Width;
+ } else {
+ x = geometry.X + geometry.Width - request.Width;
+ }
+
+ if (x < geometry.Left)
+ x = geometry.Left;
+ }
+
+ if (y + request.Height > geometry.Y + geometry.Height) {
+ if (flip_up) {
+ y -= request.Height;
+ } else {
+ y = geometry.Y + geometry.Height - request.Height;
+ }
+
+ if (y < geometry.Top)
+ y = geometry.Top;
+ }
+
+ pushIn = false;
+ };
+ }
+
+ uint time;
+ uint button;
+
+ if (evt == null) {
+ time = Gtk.Global.CurrentEventTime;
+ button = 0;
+ } else {
+ time = evt.Time;
+ button = evt.Button;
+ }
+
+ //HACK: work around GTK menu issues on mac when passing button to menu.Popup
+ //some menus appear and immediately hide, and submenus don't activate
+ if (Platform.IsMac) {
+ button = 0;
+ }
+
+ menu.Popup (null, null, posFunc, button, time);
+ }
+
+ public static void ShowContextMenu (Gtk.Menu menu, Gtk.Widget parent, Gdk.EventButton evt)
+ {
+ ShowContextMenu (menu, parent, evt, Gdk.Rectangle.Zero);
+ }
+
+ public static void ShowContextMenu (Gtk.Menu menu, Gtk.Widget parent, Gdk.Rectangle caret)
+ {
+ ShowContextMenu (menu, parent, null, caret);
+ }
+
+ struct MappedKeys
+ {
+ public Gdk.Key Key;
+ public Gdk.ModifierType State;
+ public KeyboardShortcut[] Shortcuts;
+ }
+
+ //introduced in GTK 2.20
+ [DllImport (PangoUtil.LIBGDK, CallingConvention = CallingConvention.Cdecl)]
+ extern static bool gdk_keymap_add_virtual_modifiers (IntPtr keymap, ref Gdk.ModifierType state);
+
+ //Custom patch in Mono Mac w/GTK+ 2.24.8+
+ [DllImport (PangoUtil.LIBGDK, CallingConvention = CallingConvention.Cdecl)]
+ extern static bool gdk_quartz_set_fix_modifiers (bool fix);
+
+ static Gdk.Keymap keymap = Gdk.Keymap.Default;
+ static Dictionary<ulong,MappedKeys> mappedKeys = new Dictionary<ulong,MappedKeys> ();
+
+ /// <summary>Map raw GTK key input to work around platform bugs and decompose accelerator keys</summary>
+ /// <param name='evt'>The raw key event</param>
+ /// <param name='key'>The composed key</param>
+ /// <param name='state'>The composed modifiers</param>
+ /// <param name='shortcuts'>All the key/modifier decompositions that can be used as accelerators</param>
+ public static void MapKeys (Gdk.EventKey evt, out Gdk.Key key, out Gdk.ModifierType state,
+ out KeyboardShortcut[] shortcuts)
+ {
+ //this uniquely identifies the raw key
+ ulong id;
+ unchecked {
+ id = (((ulong)(uint)evt.State) | (((ulong)evt.HardwareKeycode) << 32) | (((ulong)evt.Group) << 48));
+ }
+
+ bool remapKey = Platform.IsWindows && evt.HardwareKeycode == 0;
+ MappedKeys mapped;
+ if (remapKey || !mappedKeys.TryGetValue (id, out mapped))
+ mappedKeys[id] = mapped = MapKeys (evt);
+
+ shortcuts = mapped.Shortcuts;
+ state = mapped.State;
+ key = mapped.Key;
+
+ if (remapKey) {
+ key = (Gdk.Key)evt.KeyValue;
+ }
+ }
+
+ static MappedKeys MapKeys (Gdk.EventKey evt)
+ {
+ MappedKeys mapped;
+ Gdk.ModifierType modifier = evt.State;
+ byte grp = evt.Group;
+
+ if (GtkMinorVersion >= 20) {
+ gdk_keymap_add_virtual_modifiers (keymap.Handle, ref modifier);
+ }
+
+ //full key mapping
+ uint keyval;
+ int effectiveGroup, level;
+ Gdk.ModifierType consumedModifiers;
+ TranslateKeyboardState (evt, modifier, grp, out keyval, out effectiveGroup,
+ out level, out consumedModifiers);
+ mapped.Key = (Gdk.Key)keyval;
+ mapped.State = FixMacModifiers (evt.State & ~consumedModifiers, grp);
+
+ //decompose the key into accel combinations
+ var accelList = new List<KeyboardShortcut> ();
+
+ const Gdk.ModifierType accelMods = Gdk.ModifierType.ShiftMask | Gdk.ModifierType.Mod1Mask
+ | Gdk.ModifierType.ControlMask | Gdk.ModifierType.SuperMask |Gdk.ModifierType.MetaMask;
+
+ //all accels ignore the lock key
+ modifier &= ~Gdk.ModifierType.LockMask;
+
+ //fully decomposed
+ TranslateKeyboardState (evt, Gdk.ModifierType.None, 0,
+ out keyval, out effectiveGroup, out level, out consumedModifiers);
+ accelList.Add (new KeyboardShortcut ((Gdk.Key)keyval, FixMacModifiers (modifier, grp) & accelMods));
+
+ //with shift composed
+ if ((modifier & Gdk.ModifierType.ShiftMask) != 0) {
+ keymap.TranslateKeyboardState (evt.HardwareKeycode, Gdk.ModifierType.ShiftMask, 0,
+ out keyval, out effectiveGroup, out level, out consumedModifiers);
+
+ if (Platform.IsWindows && evt.HardwareKeycode == 0) {
+ keyval = (ushort)evt.KeyValue;
+ }
+
+ // Prevent consumption of non-Shift modifiers (that we didn't even provide!)
+ consumedModifiers &= Gdk.ModifierType.ShiftMask;
+
+ var m = FixMacModifiers ((modifier & ~consumedModifiers), grp) & accelMods;
+ AddIfNotDuplicate (accelList, new KeyboardShortcut ((Gdk.Key)keyval, m));
+ }
+
+ //with group 1 composed
+ if (grp == 1) {
+ TranslateKeyboardState (evt, modifier & ~Gdk.ModifierType.ShiftMask, 1,
+ out keyval, out effectiveGroup, out level, out consumedModifiers);
+
+ // Prevent consumption of Shift modifier (that we didn't even provide!)
+ consumedModifiers &= ~Gdk.ModifierType.ShiftMask;
+
+ var m = FixMacModifiers ((modifier & ~consumedModifiers), 0) & accelMods;
+ AddIfNotDuplicate (accelList, new KeyboardShortcut ((Gdk.Key)keyval, m));
+ }
+
+ //with group 1 and shift composed
+ if (grp == 1 && (modifier & Gdk.ModifierType.ShiftMask) != 0) {
+ TranslateKeyboardState (evt, modifier, 1,
+ out keyval, out effectiveGroup, out level, out consumedModifiers);
+ var m = FixMacModifiers ((modifier & ~consumedModifiers), 0) & accelMods;
+ AddIfNotDuplicate (accelList, new KeyboardShortcut ((Gdk.Key)keyval, m));
+ }
+
+ //and also allow the fully mapped key as an accel
+ AddIfNotDuplicate (accelList, new KeyboardShortcut (mapped.Key, mapped.State & accelMods));
+
+ mapped.Shortcuts = accelList.ToArray ();
+ return mapped;
+ }
+
+ // Workaround for bug "Bug 688247 - Ctrl+Alt key not work on windows7 with bootcamp on a Mac Book Pro"
+ // Ctrl+Alt should behave like right alt key - unfortunately TranslateKeyboardState doesn't handle it.
+ static void TranslateKeyboardState (Gdk.EventKey evt, Gdk.ModifierType state, int group, out uint keyval,
+ out int effective_group, out int level, out Gdk.ModifierType consumed_modifiers)
+ {
+ uint hardware_keycode = evt.HardwareKeycode;
+
+ if (Platform.IsWindows) {
+ const Gdk.ModifierType ctrlAlt = Gdk.ModifierType.ControlMask | Gdk.ModifierType.Mod1Mask;
+ if ((state & ctrlAlt) == ctrlAlt) {
+ state = (state & ~ctrlAlt) | Gdk.ModifierType.Mod2Mask;
+ group = 1;
+ }
+ // Case: Caps lock on + shift + key
+ // See: Bug 8069 - [UI Refresh] If caps lock is on, holding the shift key prevents typed characters from appearing
+ if (state.HasFlag (Gdk.ModifierType.ShiftMask)) {
+ state &= ~Gdk.ModifierType.ShiftMask;
+ }
+ }
+
+ keymap.TranslateKeyboardState (hardware_keycode, state, group, out keyval, out effective_group,
+ out level, out consumed_modifiers);
+
+ if (Platform.IsWindows && hardware_keycode == 0) {
+ keyval = evt.KeyValue;
+ }
+ }
+
+ static Gdk.ModifierType FixMacModifiers (Gdk.ModifierType mod, byte grp)
+ {
+ if (!oldMacKeyHacks)
+ return mod;
+
+ // Mac GTK+ maps the command key to the Mod1 modifier, which usually means alt/
+ // We map this instead to meta, because the Mac GTK+ has mapped the cmd key
+ // to the meta key (yay inconsistency!). IMO super would have been saner.
+ if ((mod & Gdk.ModifierType.Mod1Mask) != 0) {
+ mod ^= Gdk.ModifierType.Mod1Mask;
+ mod |= Gdk.ModifierType.MetaMask;
+ }
+
+ //some versions of GTK map opt as mod5, which converts to the virtual super modifier
+ if ((mod & (Gdk.ModifierType.Mod5Mask | Gdk.ModifierType.SuperMask)) != 0) {
+ mod ^= (Gdk.ModifierType.Mod5Mask | Gdk.ModifierType.SuperMask);
+ mod |= Gdk.ModifierType.Mod1Mask;
+ }
+
+ // When opt modifier is active, we need to decompose this to make the command appear correct for Mac.
+ // In addition, we can only inspect whether the opt/alt key is pressed by examining
+ // the key's "group", because the Mac GTK+ treats opt as a group modifier and does
+ // not expose it as an actual GDK modifier.
+ if (grp == (byte) 1) {
+ mod |= Gdk.ModifierType.Mod1Mask;
+ }
+
+ return mod;
+ }
+
+ static void AddIfNotDuplicate<T> (List<T> list, T item) where T : IEquatable<T>
+ {
+ for (int i = 0; i < list.Count; i++) {
+ if (list[i].Equals (item))
+ return;
+ }
+ list.Add (item);
+ }
+
+ [System.Runtime.InteropServices.DllImport (PangoUtil.LIBGDK, CallingConvention = CallingConvention.Cdecl)]
+ static extern IntPtr gdk_win32_drawable_get_handle (IntPtr drawable);
+
+ enum DwmWindowAttribute
+ {
+ NcRenderingEnabled = 1,
+ NcRenderingPolicy,
+ TransitionsForceDisabled,
+ AllowNcPaint,
+ CaptionButtonBounds,
+ NonClientRtlLayout,
+ ForceIconicRepresentation,
+ Flip3DPolicy,
+ ExtendedFrameBounds,
+ HasIconicBitmap,
+ DisallowPeek,
+ ExcludedFromPeek,
+ Last,
+ }
+
+ struct Win32Rect
+ {
+ public int Left, Top, Right, Bottom;
+
+ public Win32Rect (int left, int top, int right, int bottom)
+ {
+ this.Left = left;
+ this.Top = top;
+ this.Right = right;
+ this.Bottom = bottom;
+ }
+ }
+
+ [DllImport ("dwmapi.dll")]
+ static extern int DwmGetWindowAttribute (IntPtr hwnd, DwmWindowAttribute attribute, out Win32Rect value, int valueSize);
+
+ [DllImport ("dwmapi.dll")]
+ static extern int DwmIsCompositionEnabled (out bool enabled);
+
+ [DllImport (USER32DLL)]
+ static extern bool GetWindowRect (IntPtr hwnd, out Win32Rect rect);
+
+ public static void SetImCursorLocation (Gtk.IMContext ctx, Gdk.Window clientWindow, Gdk.Rectangle cursor)
+ {
+ // work around GTK+ Bug 663096 - Windows IME position is wrong when Aero glass is enabled
+ // https://bugzilla.gnome.org/show_bug.cgi?id=663096
+ if (Platform.IsWindows && System.Environment.OSVersion.Version.Major >= 6) {
+ bool enabled;
+ if (DwmIsCompositionEnabled (out enabled) == 0 && enabled) {
+ var hwnd = gdk_win32_drawable_get_handle (clientWindow.Toplevel.Handle);
+ Win32Rect rect;
+ // this module gets the WINVER=6 version of GetWindowRect, which returns the correct value
+ if (GetWindowRect (hwnd, out rect)) {
+ int x, y;
+ clientWindow.Toplevel.GetPosition (out x, out y);
+ cursor.X = cursor.X - x + rect.Left;
+ cursor.Y = cursor.Y - y + rect.Top - cursor.Height;
+ }
+ }
+ }
+ ctx.CursorLocation = cursor;
+ }
+
+ /// <summary>X coordinate of the pixels inside the right edge of the rectangle</summary>
+ /// <remarks>Workaround for inconsistency of Right property between GTK# versions</remarks>
+ public static int RightInside (this Gdk.Rectangle rect)
+ {
+ return rect.X + rect.Width - 1;
+ }
+
+ /// <summary>Y coordinate of the pixels inside the bottom edge of the rectangle</summary>
+ /// <remarks>Workaround for inconsistency of Bottom property between GTK# versions#</remarks>
+ public static int BottomInside (this Gdk.Rectangle rect)
+ {
+ return rect.Y + rect.Height - 1;
+ }
+
+ /// <summary>
+ /// Shows or hides the shadow of the window rendered by the native toolkit
+ /// </summary>
+ public static void ShowNativeShadow (Gtk.Window window, bool show)
+ {
+ if (Platform.IsMac) {
+ var ptr = gdk_quartz_window_get_nswindow (window.GdkWindow.Handle);
+ objc_msgSend_void_bool (ptr, sel_setHasShadow, show);
+ }
+ }
+
+ public static void UpdateNativeShadow (Gtk.Window window)
+ {
+ if (!Platform.IsMac)
+ return;
+
+ var ptr = gdk_quartz_window_get_nswindow (window.GdkWindow.Handle);
+ objc_msgSend_IntPtr (ptr, sel_invalidateShadow);
+ }
+
+ public static bool HasNSTextFieldFocus (Gdk.Window window)
+ {
+ if (Platform.IsMac) {
+ try {
+ return gdk_window_has_embedded_nsview_focus (window.Handle);
+ } catch (Exception e) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ [DllImport (PangoUtil.LIBGTKGLUE, CallingConvention = CallingConvention.Cdecl)]
+ static extern void gtksharp_container_leak_fixed_marker ();
+
+ static HashSet<Type> fixedContainerTypes;
+ static Dictionary<IntPtr,ForallDelegate> forallCallbacks;
+ static bool containerLeakFixed;
+
+ // Works around BXC #3801 - Managed Container subclasses are incorrectly resurrected, then leak.
+ // It does this by registering an alternative callback for gtksharp_container_override_forall, which
+ // ignores callbacks if the wrapper no longer exists. This means that the objects no longer enter a
+ // finalized->release->dispose->re-wrap resurrection cycle.
+ // We use a dynamic method to access internal/private GTK# API in a performant way without having to track
+ // per-instance delegates.
+ public static void FixContainerLeak (Gtk.Container c)
+ {
+ if (containerLeakFixed) {
+ return;
+ }
+
+ FixContainerLeak (c.GetType ());
+ }
+
+ static void FixContainerLeak (Type t)
+ {
+ if (containerLeakFixed) {
+ return;
+ }
+
+ if (fixedContainerTypes == null) {
+ try {
+ gtksharp_container_leak_fixed_marker ();
+ containerLeakFixed = true;
+ return;
+ } catch (EntryPointNotFoundException) {
+ }
+ fixedContainerTypes = new HashSet<Type>();
+ forallCallbacks = new Dictionary<IntPtr, ForallDelegate> ();
+ }
+
+ if (!fixedContainerTypes.Add (t)) {
+ return;
+ }
+
+ //need to fix the callback for the type and all the managed supertypes
+ var lookupGType = typeof (GLib.Object).GetMethod ("LookupGType", BindingFlags.Static | BindingFlags.NonPublic);
+ do {
+ var gt = (GLib.GType) lookupGType.Invoke (null, new[] { t });
+ var cb = CreateForallCallback (gt.Val);
+ forallCallbacks[gt.Val] = cb;
+ gtksharp_container_override_forall (gt.Val, cb);
+ t = t.BaseType;
+ } while (fixedContainerTypes.Add (t) && t.Assembly != typeof (Gtk.Container).Assembly);
+ }
+
+ static ForallDelegate CreateForallCallback (IntPtr gtype)
+ {
+ var dm = new DynamicMethod (
+ "ContainerForallCallback",
+ typeof(void),
+ new Type[] { typeof(IntPtr), typeof(bool), typeof(IntPtr), typeof(IntPtr) },
+ typeof(GtkWorkarounds).Module,
+ true);
+
+ var invokerType = typeof(Gtk.Container.CallbackInvoker);
+
+ //this was based on compiling a similar method and disassembling it
+ ILGenerator il = dm.GetILGenerator ();
+ var IL_002b = il.DefineLabel ();
+ var IL_003f = il.DefineLabel ();
+ var IL_0060 = il.DefineLabel ();
+ var label_return = il.DefineLabel ();
+
+ var loc_container = il.DeclareLocal (typeof(Gtk.Container));
+ var loc_obj = il.DeclareLocal (typeof(object));
+ var loc_invoker = il.DeclareLocal (invokerType);
+ var loc_ex = il.DeclareLocal (typeof(Exception));
+
+ //check that the type is an exact match
+ // prevent stack overflow, because the callback on a more derived type will handle everything
+ il.Emit (OpCodes.Ldarg_0);
+ il.Emit (OpCodes.Call, typeof(GLib.ObjectManager).GetMethod ("gtksharp_get_type_id", BindingFlags.Static | BindingFlags.NonPublic));
+
+ il.Emit (OpCodes.Ldc_I8, gtype.ToInt64 ());
+ il.Emit (OpCodes.Newobj, typeof (IntPtr).GetConstructor (new Type[] { typeof (Int64) }));
+ il.Emit (OpCodes.Call, typeof (IntPtr).GetMethod ("op_Equality", BindingFlags.Static | BindingFlags.Public));
+ il.Emit (OpCodes.Brfalse, label_return);
+
+ il.BeginExceptionBlock ();
+ il.Emit (OpCodes.Ldnull);
+ il.Emit (OpCodes.Stloc, loc_container);
+ il.Emit (OpCodes.Ldsfld, typeof (GLib.Object).GetField ("Objects", BindingFlags.Static | BindingFlags.NonPublic));
+ il.Emit (OpCodes.Ldarg_0);
+ il.Emit (OpCodes.Box, typeof (IntPtr));
+ il.Emit (OpCodes.Callvirt, typeof (System.Collections.Hashtable).GetProperty ("Item").GetGetMethod ());
+ il.Emit (OpCodes.Stloc, loc_obj);
+ il.Emit (OpCodes.Ldloc, loc_obj);
+ il.Emit (OpCodes.Brfalse, IL_002b);
+
+ var tref = typeof (GLib.Object).Assembly.GetType ("GLib.ToggleRef");
+ il.Emit (OpCodes.Ldloc, loc_obj);
+ il.Emit (OpCodes.Castclass, tref);
+ il.Emit (OpCodes.Callvirt, tref.GetProperty ("Target").GetGetMethod ());
+ il.Emit (OpCodes.Isinst, typeof (Gtk.Container));
+ il.Emit (OpCodes.Stloc, loc_container);
+
+ il.MarkLabel (IL_002b);
+ il.Emit (OpCodes.Ldloc, loc_container);
+ il.Emit (OpCodes.Brtrue, IL_003f);
+
+ il.Emit (OpCodes.Ldarg_0);
+ il.Emit (OpCodes.Ldarg_1);
+ il.Emit (OpCodes.Ldarg_2);
+ il.Emit (OpCodes.Ldarg_3);
+ il.Emit (OpCodes.Call, typeof (Gtk.Container).GetMethod ("gtksharp_container_base_forall", BindingFlags.Static | BindingFlags.NonPublic));
+ il.Emit (OpCodes.Br, IL_0060);
+
+ il.MarkLabel (IL_003f);
+ il.Emit (OpCodes.Ldloca_S, 2);
+ il.Emit (OpCodes.Ldarg_2);
+ il.Emit (OpCodes.Ldarg_3);
+ il.Emit (OpCodes.Call, invokerType.GetConstructor (
+ BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof (IntPtr), typeof (IntPtr) }, null));
+ il.Emit (OpCodes.Ldloc, loc_container);
+ il.Emit (OpCodes.Ldarg_1);
+ il.Emit (OpCodes.Ldloc, loc_invoker);
+ il.Emit (OpCodes.Box, invokerType);
+ il.Emit (OpCodes.Ldftn, invokerType.GetMethod ("Invoke"));
+ il.Emit (OpCodes.Newobj, typeof (Gtk.Callback).GetConstructor (
+ BindingFlags.Instance | BindingFlags.Public, null, new Type[] { typeof (object), typeof (IntPtr) }, null));
+ var forallMeth = typeof (Gtk.Container).GetMethod ("ForAll",
+ BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof (bool), typeof (Gtk.Callback) }, null);
+ il.Emit (OpCodes.Callvirt, forallMeth);
+
+ il.MarkLabel (IL_0060);
+
+ il.BeginCatchBlock (typeof (Exception));
+ il.Emit (OpCodes.Stloc, loc_ex);
+ il.Emit (OpCodes.Ldloc, loc_ex);
+ il.Emit (OpCodes.Ldc_I4_0);
+ il.Emit (OpCodes.Call, typeof (GLib.ExceptionManager).GetMethod ("RaiseUnhandledException"));
+ il.Emit (OpCodes.Leave, label_return);
+ il.EndExceptionBlock ();
+
+ il.MarkLabel (label_return);
+ il.Emit (OpCodes.Ret);
+
+ return (ForallDelegate) dm.CreateDelegate (typeof (ForallDelegate));
+ }
+
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ delegate void ForallDelegate (IntPtr container, bool include_internals, IntPtr cb, IntPtr data);
+
+ [DllImport(PangoUtil.LIBGTKGLUE, CallingConvention = CallingConvention.Cdecl)]
+ static extern void gtksharp_container_override_forall (IntPtr gtype, ForallDelegate cb);
+
+ const string urlRegexStr = @"(http|ftp)s?\:\/\/[\w\d\.,;_/\-~%@()+:?&^=#!]*[\w\d/]";
+ static readonly Regex UrlRegex = new Regex (urlRegexStr, RegexOptions.Compiled | RegexOptions.ExplicitCapture);
+
+ public static string MarkupLinks (string text)
+ {
+ if (GtkMinorVersion < 18)
+ return text;
+ return UrlRegex.Replace (text, MatchToUrl);
+ }
+
+ static string MatchToUrl (System.Text.RegularExpressions.Match m)
+ {
+ var s = m.ToString ();
+ return String.Format ("<a href='{0}'>{1}</a>", s, s.Replace ("_", "__"));
+ }
+
+ public static void SetLinkHandler (this Gtk.Label label, Action<string> urlHandler)
+ {
+ if (GtkMinorVersion >= 18)
+ new UrlHandlerClosure (urlHandler).ConnectTo (label);
+ }
+
+ //create closure manually so we can apply ConnectBefore
+ class UrlHandlerClosure
+ {
+ Action<string> urlHandler;
+
+ public UrlHandlerClosure (Action<string> urlHandler)
+ {
+ this.urlHandler = urlHandler;
+ }
+
+ [GLib.ConnectBefore]
+ void HandleLink (object sender, ActivateLinkEventArgs args)
+ {
+ urlHandler (args.Url);
+ args.RetVal = true;
+ }
+
+ public void ConnectTo (Gtk.Label label)
+ {
+ var signal = GLib.Signal.Lookup (label, "activate-link", typeof(ActivateLinkEventArgs));
+ signal.AddDelegate (new EventHandler<ActivateLinkEventArgs> (HandleLink));
+ }
+
+ class ActivateLinkEventArgs : GLib.SignalArgs
+ {
+ public string Url { get { return (string)base.Args [0]; } }
+ }
+ }
+
+ static bool canSetOverlayScrollbarPolicy = true;
+
+ [DllImport (PangoUtil.LIBQUARTZ)]
+ static extern void gtk_scrolled_window_set_overlay_policy (IntPtr sw, Gtk.PolicyType hpolicy, Gtk.PolicyType vpolicy);
+
+ [DllImport (PangoUtil.LIBQUARTZ)]
+ static extern void gtk_scrolled_window_get_overlay_policy (IntPtr sw, out Gtk.PolicyType hpolicy, out Gtk.PolicyType vpolicy);
+
+ public static void SetOverlayScrollbarPolicy (Gtk.ScrolledWindow sw, Gtk.PolicyType hpolicy, Gtk.PolicyType vpolicy)
+ {
+ if (!canSetOverlayScrollbarPolicy) {
+ return;
+ }
+ try {
+ gtk_scrolled_window_set_overlay_policy (sw.Handle, hpolicy, vpolicy);
+ return;
+ } catch (DllNotFoundException) {
+ } catch (EntryPointNotFoundException) {
+ }
+ }
+
+ public static void GetOverlayScrollbarPolicy (Gtk.ScrolledWindow sw, out Gtk.PolicyType hpolicy, out Gtk.PolicyType vpolicy)
+ {
+ if (!canSetOverlayScrollbarPolicy) {
+ hpolicy = vpolicy = 0;
+ return;
+ }
+ try {
+ gtk_scrolled_window_get_overlay_policy (sw.Handle, out hpolicy, out vpolicy);
+ return;
+ } catch (DllNotFoundException) {
+ } catch (EntryPointNotFoundException) {
+ }
+ hpolicy = vpolicy = 0;
+ canSetOverlayScrollbarPolicy = false;
+ }
+
+ [DllImport (PangoUtil.LIBGTK, CallingConvention = CallingConvention.Cdecl)]
+ static extern bool gtk_tree_view_get_tooltip_context (IntPtr raw, ref int x, ref int y, bool keyboard_tip, out IntPtr model, out IntPtr path, IntPtr iter);
+
+ //the GTK# version of this has 'out' instead of 'ref', preventing passing the x,y values in
+ public static bool GetTooltipContext (this TreeView tree, ref int x, ref int y, bool keyboardTip,
+ out TreeModel model, out TreePath path, out Gtk.TreeIter iter)
+ {
+ IntPtr intPtr = Marshal.AllocHGlobal (Marshal.SizeOf (typeof(TreeIter)));
+ IntPtr handle;
+ IntPtr intPtr2;
+ bool result = gtk_tree_view_get_tooltip_context (tree.Handle, ref x, ref y, keyboardTip, out handle, out intPtr2, intPtr);
+ model = TreeModelAdapter.GetObject (handle, false);
+ path = intPtr2 == IntPtr.Zero ? null : ((TreePath)GLib.Opaque.GetOpaque (intPtr2, typeof(TreePath), false));
+ iter = TreeIter.New (intPtr);
+ Marshal.FreeHGlobal (intPtr);
+ return result;
+ }
+
+ static bool supportsHiResIcons = true;
+
+ [DllImport (PangoUtil.LIBGTK, CallingConvention = CallingConvention.Cdecl)]
+ static extern void gtk_icon_source_set_scale (IntPtr source, double scale);
+
+ [DllImport (PangoUtil.LIBGTK, CallingConvention = CallingConvention.Cdecl)]
+ static extern void gtk_icon_source_set_scale_wildcarded (IntPtr source, bool setting);
+
+ [DllImport (PangoUtil.LIBGTK, CallingConvention = CallingConvention.Cdecl)]
+ static extern double gtk_widget_get_scale_factor (IntPtr widget);
+
+ [DllImport (PangoUtil.LIBGDK, CallingConvention = CallingConvention.Cdecl)]
+ static extern double gdk_screen_get_monitor_scale_factor (IntPtr widget, int monitor);
+
+ [DllImport (PangoUtil.LIBGOBJECT, CallingConvention = CallingConvention.Cdecl)]
+ static extern IntPtr g_object_get_data (IntPtr source, string name);
+
+ [DllImport (PangoUtil.LIBGTK, CallingConvention = CallingConvention.Cdecl)]
+ static extern IntPtr gtk_icon_set_render_icon_scaled (IntPtr handle, IntPtr style, int direction, int state, int size, IntPtr widget, IntPtr intPtr, ref double scale);
+
+ public static bool SetSourceScale (Gtk.IconSource source, double scale)
+ {
+ if (!supportsHiResIcons)
+ return false;
+
+ try {
+ gtk_icon_source_set_scale (source.Handle, scale);
+ return true;
+ } catch (DllNotFoundException) {
+ } catch (EntryPointNotFoundException) {
+ }
+ supportsHiResIcons = false;
+ return false;
+ }
+
+ public static bool SetSourceScaleWildcarded (Gtk.IconSource source, bool setting)
+ {
+ if (!supportsHiResIcons)
+ return false;
+
+ try {
+ gtk_icon_source_set_scale_wildcarded (source.Handle, setting);
+ return true;
+ } catch (DllNotFoundException) {
+ } catch (EntryPointNotFoundException) {
+ }
+ supportsHiResIcons = false;
+ return false;
+ }
+
+ public static Gdk.Pixbuf Get2xVariant (Gdk.Pixbuf px)
+ {
+ if (!supportsHiResIcons)
+ return null;
+
+ try {
+ IntPtr res = g_object_get_data (px.Handle, "gdk-pixbuf-2x-variant");
+ if (res != IntPtr.Zero && res != px.Handle)
+ return (Gdk.Pixbuf) GLib.Object.GetObject (res);
+ else
+ return null;
+ } catch (DllNotFoundException) {
+ } catch (EntryPointNotFoundException) {
+ }
+ supportsHiResIcons = false;
+ return null;
+ }
+
+ public static void Set2xVariant (Gdk.Pixbuf px, Gdk.Pixbuf variant2x)
+ {
+ }
+
+ public static double GetScaleFactor (Gtk.Widget w)
+ {
+ if (!supportsHiResIcons)
+ return 1;
+
+ try {
+ return gtk_widget_get_scale_factor (w.Handle);
+ } catch (DllNotFoundException) {
+ } catch (EntryPointNotFoundException) {
+ }
+ supportsHiResIcons = false;
+ return 1;
+ }
+
+ public static double GetScaleFactor (this Gdk.Screen screen, int monitor)
+ {
+ if (!supportsHiResIcons)
+ return 1;
+
+ try {
+ return gdk_screen_get_monitor_scale_factor (screen.Handle, monitor);
+ } catch (DllNotFoundException) {
+ } catch (EntryPointNotFoundException) {
+ }
+ supportsHiResIcons = false;
+ return 1;
+ }
+
+ public static double GetScaleFactor ()
+ {
+ return GetScaleFactor (Gdk.Screen.Default, 0);
+ }
+
+ public static double GetPixelScale ()
+ {
+ if (Platform.IsWindows)
+ return GetScaleFactor ();
+ else
+ return 1d;
+ }
+
+ 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)
+ {
+ if (scale == 1d)
+ return iconset.RenderIcon (style, direction, state, size, widget, detail);
+
+ if (!supportsHiResIcons)
+ return null;
+
+ try {
+ IntPtr intPtr = GLib.Marshaller.StringToPtrGStrdup (detail);
+ IntPtr o = gtk_icon_set_render_icon_scaled (iconset.Handle, (style != null) ? style.Handle : IntPtr.Zero, (int)direction, (int)state, (int)size, (widget != null) ? widget.Handle : IntPtr.Zero, intPtr, ref scale);
+ Gdk.Pixbuf result = (Gdk.Pixbuf) GLib.Object.GetObject (o);
+ GLib.Marshaller.Free (intPtr);
+ return result;
+ } catch (DllNotFoundException) {
+ } catch (EntryPointNotFoundException) {
+ }
+ supportsHiResIcons = false;
+ return null;
+ }
+ }
+
+ public struct KeyboardShortcut : IEquatable<KeyboardShortcut>
+ {
+ public static readonly KeyboardShortcut Empty = new KeyboardShortcut ((Gdk.Key) 0, (Gdk.ModifierType) 0);
+
+ Gdk.ModifierType modifier;
+ Gdk.Key key;
+
+ public KeyboardShortcut (Gdk.Key key, Gdk.ModifierType modifier)
+ {
+ this.modifier = modifier;
+ this.key = key;
+ }
+
+ public Gdk.Key Key {
+ get { return key; }
+ }
+
+ public Gdk.ModifierType Modifier {
+ get { return modifier; }
+ }
+
+ public bool IsEmpty {
+ get { return Key == (Gdk.Key) 0; }
+ }
+
+ public override bool Equals (object obj)
+ {
+ return obj is KeyboardShortcut && this.Equals ((KeyboardShortcut) obj);
+ }
+
+ public override int GetHashCode ()
+ {
+ //FIXME: we're only using a few bits of mod and mostly the lower bits of key - distribute it better
+ return (int) Key ^ (int) Modifier;
+ }
+
+ public bool Equals (KeyboardShortcut other)
+ {
+ return other.Key == Key && other.Modifier == Modifier;
+ }
+ }
+
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HPanedThin.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HPanedThin.cs
index d1de2f1c9f..a4f1fec7b4 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HPanedThin.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HPanedThin.cs
@@ -37,7 +37,7 @@ namespace MonoDevelop.Components
public HPanedThin ()
{
- Mono.TextEditor.GtkWorkarounds.FixContainerLeak (this);
+ GtkWorkarounds.FixContainerLeak (this);
handle = new CustomPanedHandle (this);
handle.Parent = this;
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HeaderBox.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HeaderBox.cs
index 6edbdf9213..c34e0eda46 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HeaderBox.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HeaderBox.cs
@@ -25,7 +25,6 @@
// THE SOFTWARE.
using System;
using Gtk;
-using Mono.TextEditor;
namespace MonoDevelop.Components
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HelperMethods.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HelperMethods.cs
new file mode 100644
index 0000000000..5b758e5a50
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HelperMethods.cs
@@ -0,0 +1,136 @@
+// HelperMethods.cs
+//
+// Cut & paste from PangoCairoHelper.
+//
+// Author:
+// Aaron Bockover <abockover@novell.com>
+// Mike Krüger <mkrueger@novell.com>
+//
+// Copyright (c) 2008 Novell, Inc (http://www.novell.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.Linq;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+
+namespace MonoDevelop.Components
+{
+ public static class HelperMethods
+ {
+ [DllImport(PangoUtil.LIBPANGOCAIRO, CallingConvention=CallingConvention.Cdecl)]
+ static extern void pango_cairo_show_layout (IntPtr cr, IntPtr layout);
+
+ public static void ShowLayout (this Cairo.Context cr, Pango.Layout layout)
+ {
+ pango_cairo_show_layout (cr == null ? IntPtr.Zero : cr.Handle, layout == null ? IntPtr.Zero : layout.Handle);
+ }
+
+ [DllImport(PangoUtil.LIBPANGOCAIRO, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr pango_cairo_create_layout (IntPtr cr);
+
+ public static Pango.Layout CreateLayout (this Cairo.Context cr)
+ {
+ IntPtr raw_ret = pango_cairo_create_layout (cr == null ? IntPtr.Zero : cr.Handle);
+ return GLib.Object.GetObject (raw_ret) as Pango.Layout;
+ }
+
+ [DllImport(PangoUtil.LIBPANGOCAIRO, CallingConvention=CallingConvention.Cdecl)]
+ static extern void pango_cairo_layout_path (IntPtr cr, IntPtr layout);
+
+ public static void LayoutPath (this Cairo.Context cr, Pango.Layout layout)
+ {
+ pango_cairo_layout_path (cr == null ? IntPtr.Zero : cr.Handle, layout == null ? IntPtr.Zero : layout.Handle);
+ }
+
+ [DllImport(PangoUtil.LIBPANGOCAIRO, CallingConvention=CallingConvention.Cdecl)]
+ static extern void pango_cairo_context_set_resolution (IntPtr pango_context, double dpi);
+
+ public static void ContextSetResolution (this Pango.Context context, double dpi)
+ {
+ pango_cairo_context_set_resolution (context == null ? IntPtr.Zero : context.Handle, dpi);
+ }
+
+ [DllImport(PangoUtil.LIBPANGOCAIRO, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr pango_layout_get_context (IntPtr layout);
+
+ public static string GetColorString (Gdk.Color color)
+ {
+ return string.Format ("#{0:X02}{1:X02}{2:X02}", color.Red / 256, color.Green / 256, color.Blue / 256);
+ }
+
+ public static Pango.Context LayoutGetContext (this Pango.Layout layout)
+ {
+ IntPtr handle = pango_layout_get_context (layout.Handle);
+ return handle.Equals (IntPtr.Zero) ? null : GLib.Object.GetObject (handle) as Pango.Context;
+ }
+
+ public static void DrawLine (this Cairo.Context cr, Cairo.Color color, double x1, double y1, double x2, double y2)
+ {
+ cr.SetSourceColor (color);
+ cr.MoveTo (x1, y1);
+ cr.LineTo (x2, y2);
+ cr.Stroke ();
+ }
+
+ public static void Line (this Cairo.Context cr, double x1, double y1, double x2, double y2)
+ {
+ cr.MoveTo (x1, y1);
+ cr.LineTo (x2, y2);
+ }
+
+ public static void SharpLineX (this Cairo.Context cr, double x1, double y1, double x2, double y2)
+ {
+ cr.MoveTo (x1 + 0.5, y1);
+ cr.LineTo (x2 + 0.5, y2);
+ }
+
+ public static void SharpLineY (this Cairo.Context cr, double x1, double y1, double x2, double y2)
+ {
+ cr.MoveTo (x1, y1 + 0.5);
+ cr.LineTo (x2, y2 + 0.5);
+ }
+
+ public static void SetSourceColor (this Cairo.Context cr, Cairo.Color color)
+ {
+ cr.SetSourceRGBA (color.R, color.G, color.B, color.A);
+ }
+
+ //this is needed for building against old Mono.Cairo versions
+ [Obsolete]
+ public static void SetSource (this Cairo.Context cr, Cairo.Pattern pattern)
+ {
+ cr.Pattern = pattern;
+ }
+
+ [Obsolete]
+ public static Cairo.Surface GetTarget (this Cairo.Context cr)
+ {
+ return cr.Target;
+ }
+
+ [Obsolete]
+ public static void Dispose (this Cairo.Context cr)
+ {
+ ((IDisposable)cr).Dispose ();
+ }
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HslColor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HslColor.cs
new file mode 100644
index 0000000000..7e56d747d1
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/HslColor.cs
@@ -0,0 +1,292 @@
+//
+// HslColor.cs
+//
+// Author:
+// Mike Krüger <mkrueger@novell.com>
+//
+// Copyright (c) 2009 Novell, Inc (http://www.novell.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 Gdk;
+using System.Collections.Generic;
+
+namespace MonoDevelop.Components
+{
+ public struct HslColor
+ {
+ public double H {
+ get;
+ set;
+ }
+
+ public double S {
+ get;
+ set;
+ }
+
+ public double L {
+ get;
+ set;
+ }
+
+ public double Alpha {
+ get;
+ set;
+ }
+
+ void ToRgb(out double r, out double g, out double b)
+ {
+ if (L == 0) {
+ r = g = b = 0;
+ return;
+ }
+
+ if (S == 0) {
+ r = g = b = L;
+ } else {
+ double temp2 = L <= 0.5 ? L * (1.0 + S) : L + S -(L * S);
+ double temp1 = 2.0 * L - temp2;
+
+ double[] t3 = new double[] { H + 1.0 / 3.0, H, H - 1.0 / 3.0};
+ double[] clr= new double[] { 0, 0, 0};
+ for (int i = 0; i < 3; i++) {
+ if (t3[i] < 0)
+ t3[i] += 1.0;
+ if (t3[i] > 1)
+ t3[i]-=1.0;
+ if (6.0 * t3[i] < 1.0)
+ clr[i] = temp1 + (temp2 - temp1) * t3[i] * 6.0;
+ else if (2.0 * t3[i] < 1.0)
+ clr[i] = temp2;
+ else if (3.0 * t3[i] < 2.0)
+ clr[i] = (temp1 + (temp2 - temp1) * ((2.0 / 3.0) - t3[i]) * 6.0);
+ else
+ clr[i] = temp1;
+ }
+
+ r = clr[0];
+ g = clr[1];
+ b = clr[2];
+ }
+ }
+
+ public static implicit operator Color (HslColor hsl)
+ {
+ double r = 0, g = 0, b = 0;
+ hsl.ToRgb (out r, out g, out b);
+ return new Color ((byte)(255 * r),
+ (byte)(255 * g),
+ (byte)(255 * b));
+ }
+
+ public static implicit operator Cairo.Color (HslColor hsl)
+ {
+ double r = 0, g = 0, b = 0;
+ hsl.ToRgb (out r, out g, out b);
+ return new Cairo.Color (r, g, b, hsl.Alpha);
+ }
+
+ public static implicit operator HslColor (Color color)
+ {
+ return new HslColor (color);
+ }
+
+ public static implicit operator HslColor (Cairo.Color color)
+ {
+ return new HslColor (color);
+ }
+
+ #if MAC
+
+ public static implicit operator HslColor (AppKit.NSColor color)
+ {
+ return new HslColor ((double)color.RedComponent, (double)color.GreenComponent, (double)color.BlueComponent);
+ }
+
+ public static implicit operator AppKit.NSColor (HslColor hsl)
+ {
+ double r = 0, g = 0, b = 0;
+ hsl.ToRgb (out r, out g, out b);
+ return AppKit.NSColor.FromDeviceRgba ((nfloat)r, (nfloat)g, (nfloat)b, (nfloat)hsl.Alpha);
+ }
+
+
+ public static implicit operator CoreGraphics.CGColor (HslColor hsl)
+ {
+ double r = 0, g = 0, b = 0;
+ hsl.ToRgb (out r, out g, out b);
+ return new CoreGraphics.CGColor ((nfloat)r, (nfloat)g, (nfloat)b, (nfloat)hsl.Alpha);
+ }
+ #endif
+
+
+ public static HslColor FromHsl (double h, double s, double l)
+ {
+ return new HslColor {
+ H = h,
+ S = s,
+ L = l,
+ Alpha = 1.0d
+ };
+ }
+
+ public uint ToPixel ()
+ {
+ double r, g, b;
+ ToRgb(out r, out g, out b);
+ uint rv = (uint)(r * 255);
+ uint gv = (uint)(g * 255);
+ uint bv = (uint)(b * 255);
+ return rv << 16 | gv << 8 | bv;
+ }
+
+ public static HslColor FromPixel (uint pixel)
+ {
+ var r = ((pixel >> 16) & 0xFF) / 255.0;
+ var g = ((pixel >> 8) & 0xFF) / 255.0;
+ var b = (pixel & 0xFF) / 255.0;
+ return new HslColor (r, g, b);
+ }
+
+ public HslColor (double r, double g, double b, double a = 1.0) : this ()
+ {
+ double v = System.Math.Max (r, g);
+ v = System.Math.Max (v, b);
+
+ double m = System.Math.Min (r, g);
+ m = System.Math.Min (m, b);
+
+ this.L = (m + v) / 2.0;
+ if (this.L <= 0.0)
+ return;
+ double vm = v - m;
+ this.S = vm;
+
+ if (this.S > 0.0) {
+ this.S /= (this.L <= 0.5) ? (v + m) : (2.0 - v - m);
+ } else {
+ return;
+ }
+
+ double r2 = (v - r) / vm;
+ double g2 = (v - g) / vm;
+ double b2 = (v - b) / vm;
+
+ if (r == v) {
+ this.H = (g == m ? 5.0 + b2 : 1.0 - g2);
+ } else if (g == v) {
+ this.H = (b == m ? 1.0 + r2 : 3.0 - b2);
+ } else {
+ this.H = (r == m ? 3.0 + g2 : 5.0 - r2);
+ }
+ this.H /= 6.0;
+
+ this.Alpha = a;
+ }
+
+ public HslColor (Color color) : this (color.Red / (double)ushort.MaxValue, color.Green / (double)ushort.MaxValue, color.Blue / (double)ushort.MaxValue)
+ {
+ Alpha = 1.0;
+ }
+
+ public HslColor (Cairo.Color color) : this (color.R, color.G, color.B, color.A)
+ {
+ }
+
+ public static HslColor Parse (string color)
+ {
+ Gdk.Color col = new Gdk.Color (0, 0, 0);
+ Gdk.Color.Parse (color, ref col);
+ return (HslColor)col;
+ }
+
+ public static double Brightness (HslColor c)
+ {
+ return Brightness ((Cairo.Color)c);
+ }
+
+ public static double Brightness (Cairo.Color c)
+ {
+ double r = c.R;
+ double g = c.G;
+ double b = c.B;
+ return System.Math.Sqrt (r * .241 + g * .691 + b * .068);
+ }
+
+ public static double Brightness (Gdk.Color c)
+ {
+ double r = c.Red / (double)ushort.MaxValue;
+ double g = c.Green / (double)ushort.MaxValue;
+ double b = c.Blue / (double)ushort.MaxValue;
+ return System.Math.Sqrt (r * .241 + g * .691 + b * .068);
+ }
+
+ public static List<HslColor> GenerateHighlightColors (HslColor backGround, HslColor foreGround, int n)
+ {
+ double bgH = (backGround.H == 0 && backGround.S == 0) ? 2 / 3.0 : backGround.H;
+ var result = new List<HslColor> ();
+ for (int i = 0; i < n; i++) {
+ double h = bgH + (i + 1.0) / (double)n;
+
+ // for monochromatic backround the h value doesn't matter
+ if (i + 1 == n && !(backGround.H == 0 && backGround.S == 0))
+ h = bgH + 0.5;
+
+ if (h > 1.0)
+ h -= 1.0;
+
+ double s = 0.85;
+ double l = 0.5;
+ if (backGround.H == 0 && backGround.S == 0 && backGround.L < 0.5)
+ l = 0.8;
+ result.Add (HslColor.FromHsl (h, s, l));
+ }
+ return result;
+ }
+
+ public override string ToString ()
+ {
+ return string.Format ("[HslColor: H={0}, S={1}, L={2}, A={3}]", H, S, L, Alpha);
+ }
+
+ public string ToPangoString ()
+ {
+ var resultColor = (Cairo.Color)this;
+ return string.Format ("#{0:x2}{1:x2}{2:x2}",
+ (int)(resultColor.R * 255),
+ (int)(resultColor.G * 255),
+ (int)(resultColor.B * 255));
+ }
+
+
+ public string ToMarkup ()
+ {
+ if (Alpha == 1.0)
+ return ToPangoString ();
+ var resultColor = (Cairo.Color)this;
+ return string.Format ("#{0:x2}{1:x2}{2:x2}{3:x2}",
+ (int)(resultColor.R * 255),
+ (int)(resultColor.G * 255),
+ (int)(resultColor.B * 255),
+ (int)(resultColor.A * 255));
+ }
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ImageView.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ImageView.cs
index 5851edf92f..8b9bc5a851 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ImageView.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ImageView.cs
@@ -70,7 +70,7 @@ namespace MonoDevelop.Components
}
double IconScale {
- get { return Mono.TextEditor.GtkWorkarounds.GetPixelScale (); }
+ get { return GtkWorkarounds.GetPixelScale (); }
}
protected override void OnSizeRequested (ref Gtk.Requisition requisition)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MiniButton.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MiniButton.cs
index 34a646b8e4..715045bf8c 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MiniButton.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MiniButton.cs
@@ -26,7 +26,6 @@
using System;
using Gtk;
-using Mono.TextEditor;
namespace MonoDevelop.Components
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PangoUtil.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PangoUtil.cs
new file mode 100644
index 0000000000..86de702f7f
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PangoUtil.cs
@@ -0,0 +1,260 @@
+//
+// PangoUtils.cs
+//
+// Author:
+// Michael Hutchinson <mhutchinson@novell.com>
+//
+// Copyright (c) 2010 Novell, Inc. (http://www.novell.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 Gtk;
+using System.Runtime.InteropServices;
+
+namespace MonoDevelop.Components
+{
+ public static class PangoUtil
+ {
+ internal const string LIBGTK = "libgtk-win32-2.0-0.dll";
+ internal const string LIBATK = "libatk-1.0-0.dll";
+ internal const string LIBGLIB = "libglib-2.0-0.dll";
+ internal const string LIBGDK = "libgdk-win32-2.0-0.dll";
+ internal const string LIBGOBJECT = "libgobject-2.0-0.dll";
+ internal const string LIBPANGO = "libpango-1.0-0.dll";
+ internal const string LIBPANGOCAIRO = "libpangocairo-1.0-0.dll";
+ internal const string LIBQUARTZ = "libgtk-quartz-2.0.dylib";
+ internal const string LIBGTKGLUE = "gtksharpglue-2";
+
+ /// <summary>
+ /// This doesn't leak Pango layouts, unlike some other ways to create them in GTK# &lt;= 2.12.11
+ /// </summary>
+ public static Pango.Layout CreateLayout (Widget widget)
+ {
+ var ptr = gtk_widget_create_pango_layout (widget.Handle, IntPtr.Zero);
+ return ptr == IntPtr.Zero? null : new Pango.Layout (ptr);
+ }
+
+ public static Pango.Layout CreateLayout (Widget widget, string text)
+ {
+ IntPtr textPtr = text == null? IntPtr.Zero : GLib.Marshaller.StringToPtrGStrdup (text);
+
+ var ptr = gtk_widget_create_pango_layout (widget.Handle, textPtr);
+
+ if (textPtr != IntPtr.Zero)
+ GLib.Marshaller.Free (textPtr);
+
+ return ptr == IntPtr.Zero? null : new Pango.Layout (ptr);
+ }
+
+ public static Pango.Layout CreateLayout (PrintContext context)
+ {
+ var ptr = gtk_print_context_create_pango_layout (context.Handle);
+ return ptr == IntPtr.Zero? null : new Pango.Layout (ptr);
+ }
+
+ [DllImport (LIBGTK, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr gtk_widget_create_pango_layout (IntPtr widget, IntPtr text);
+
+ [DllImport (LIBGTK, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr gtk_print_context_create_pango_layout (IntPtr context);
+ }
+
+ /// <summary>
+ /// This creates a Pango list and applies attributes to it with *much* less overhead than the GTK# version.
+ /// </summary>
+ class FastPangoAttrList : IDisposable
+ {
+ IntPtr list;
+
+ public FastPangoAttrList ()
+ {
+ list = pango_attr_list_new ();
+ }
+
+ public void AddStyleAttribute (Pango.Style style, uint start, uint end)
+ {
+ Add (pango_attr_style_new (style), start, end);
+ }
+
+ public void AddWeightAttribute (Pango.Weight weight, uint start, uint end)
+ {
+ Add (pango_attr_weight_new (weight), start, end);
+ }
+
+ public void AddForegroundAttribute (Gdk.Color color, uint start, uint end)
+ {
+ Add (pango_attr_foreground_new (color.Red, color.Green, color.Blue), start, end);
+ }
+
+ public void AddBackgroundAttribute (Gdk.Color color, uint start, uint end)
+ {
+ Add (pango_attr_background_new (color.Red, color.Green, color.Blue), start, end);
+ }
+
+ public void AddUnderlineAttribute (Pango.Underline underline, uint start, uint end)
+ {
+ Add (pango_attr_underline_new (underline), start, end);
+ }
+
+ void Add (IntPtr attribute, uint start, uint end)
+ {
+ unsafe {
+ PangoAttribute *attPtr = (PangoAttribute *) attribute;
+ attPtr->start_index = start;
+ attPtr->end_index = end;
+ }
+ pango_attr_list_insert (list, attribute);
+ }
+
+ /// <summary>
+ /// Like Splice, except it only offsets/clamps the inserted items, doesn't affect items already in the list.
+ /// </summary>
+ public void InsertOffsetList (Pango.AttrList atts, uint startOffset, uint endOffset)
+ {
+ //HACK: atts.Iterator.Attrs broken (throws NRE), so manually P/Invoke
+ var iter = pango_attr_list_get_iterator (atts.Handle);
+ try {
+ do {
+ IntPtr list = pango_attr_iterator_get_attrs (iter);
+ try {
+ int len = g_slist_length (list);
+ for (uint i = 0; i < len; i++) {
+ IntPtr val = g_slist_nth_data (list, i);
+ AddOffsetCopy (val, startOffset, endOffset);
+ }
+ } finally {
+ g_slist_free (list);
+ }
+ } while (pango_attr_iterator_next (iter));
+ } finally {
+ pango_attr_iterator_destroy (iter);
+ }
+ }
+
+ void AddOffsetCopy (IntPtr attr, uint startOffset, uint endOffset)
+ {
+ var copy = pango_attribute_copy (attr);
+ unsafe {
+ PangoAttribute *attPtr = (PangoAttribute *) copy;
+ attPtr->start_index = startOffset + attPtr->start_index;
+ attPtr->end_index = System.Math.Min (endOffset, startOffset + attPtr->end_index);
+ }
+ pango_attr_list_insert (list, copy);
+ }
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr pango_attr_style_new (Pango.Style style);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr pango_attr_stretch_new (Pango.Stretch stretch);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr pango_attr_weight_new (Pango.Weight weight);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr pango_attr_foreground_new (ushort red, ushort green, ushort blue);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr pango_attr_background_new (ushort red, ushort green, ushort blue);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr pango_attr_underline_new (Pango.Underline underline);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr pango_attr_list_new ();
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern void pango_attr_list_unref (IntPtr list);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern void pango_attr_list_insert (IntPtr list, IntPtr attr);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern void pango_layout_set_attributes (IntPtr layout, IntPtr attrList);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern void pango_attr_list_splice (IntPtr attr_list, IntPtr other, Int32 pos, Int32 len);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr pango_attribute_copy (IntPtr attr);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr pango_attr_list_get_iterator (IntPtr list);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern bool pango_attr_iterator_next (IntPtr iterator);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern void pango_attr_iterator_destroy (IntPtr iterator);
+
+ [DllImport (PangoUtil.LIBPANGO, CallingConvention=CallingConvention.Cdecl)]
+ static extern IntPtr pango_attr_iterator_get_attrs (IntPtr iterator);
+
+ [DllImport (PangoUtil.LIBGLIB, CallingConvention = CallingConvention.Cdecl)]
+ private static extern int g_slist_length (IntPtr l);
+
+ [DllImport (PangoUtil.LIBGLIB, CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr g_slist_nth_data (IntPtr l, uint n);
+
+ [DllImport (PangoUtil.LIBGLIB, CallingConvention = CallingConvention.Cdecl)]
+ private static extern void g_slist_free (IntPtr l);
+
+ public void Splice (Pango.AttrList attrs, int pos, int len)
+ {
+ pango_attr_list_splice (list, attrs.Handle, pos, len);
+ }
+
+ public void AssignTo (Pango.Layout layout)
+ {
+ pango_layout_set_attributes (layout.Handle, list);
+ }
+
+ [StructLayout (LayoutKind.Sequential)]
+ struct PangoAttribute
+ {
+ public IntPtr klass;
+ public uint start_index;
+ public uint end_index;
+ }
+
+ public void Dispose ()
+ {
+ if (list != IntPtr.Zero) {
+ GC.SuppressFinalize (this);
+ Destroy ();
+ }
+ }
+
+ //NOTE: the list destroys all its attributes when the ref count reaches zero
+ void Destroy ()
+ {
+ pango_attr_list_unref (list);
+ list = IntPtr.Zero;
+ }
+
+ ~FastPangoAttrList ()
+ {
+ GLib.Idle.Add (delegate {
+ Destroy ();
+ return false;
+ });
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PathBar.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PathBar.cs
index 8ff221923e..d90d8d8a81 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PathBar.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PathBar.cs
@@ -25,15 +25,13 @@
// THE SOFTWARE.
using System;
-using System.Collections.Generic;
using System.Linq;
using Gtk;
using Gdk;
using MonoDevelop.Ide;
using MonoDevelop.Ide.Gui;
-using Mono.TextEditor;
-using ICSharpCode.NRefactory;
+using MonoDevelop.Core.Text;
namespace MonoDevelop.Components
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PopoverWindow.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PopoverWindow.cs
index 04d0d9f32b..97423f16c6 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PopoverWindow.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PopoverWindow.cs
@@ -27,7 +27,6 @@ using System;
using Gtk;
using MonoDevelop.Ide;
using MonoDevelop.Ide.Gui;
-using Mono.TextEditor;
using Gdk;
using Xwt.Motion;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PopoverWindowTheme.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PopoverWindowTheme.cs
index d477f4700b..29bf1dcc25 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PopoverWindowTheme.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PopoverWindowTheme.cs
@@ -27,8 +27,9 @@ using System;
using Gtk;
using MonoDevelop.Ide;
using MonoDevelop.Ide.Gui;
-using Mono.TextEditor;
using Gdk;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Ide.Editor.Highlighting;
namespace MonoDevelop.Components
{
@@ -264,7 +265,7 @@ namespace MonoDevelop.Components
Font = Pango.FontDescription.FromString ("Normal");
}
- public void SetSchemeColors (Mono.TextEditor.Highlighting.ColorScheme scheme)
+ public void SetSchemeColors (ColorScheme scheme)
{
TopColor = scheme.TooltipText.Background.AddLight (0.03);
BottomColor = scheme.TooltipText.Background;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SearchEntry.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SearchEntry.cs
index 44bd4e78ed..188f400dd3 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SearchEntry.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SearchEntry.cs
@@ -31,7 +31,6 @@ using System;
using Gtk;
using MonoDevelop.Core;
using MonoDevelop.Ide.Gui;
-using Mono.TextEditor;
namespace MonoDevelop.Components
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SectionList.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SectionList.cs
index 02688602d0..6ea647114b 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SectionList.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SectionList.cs
@@ -29,7 +29,6 @@ using System.Collections.Generic;
using Gtk;
using Gdk;
using Cairo;
-using Mono.TextEditor;
namespace MonoDevelop.Components
{
@@ -91,7 +90,7 @@ namespace MonoDevelop.Components
public SectionList ()
{
- Mono.TextEditor.GtkWorkarounds.FixContainerLeak (this);
+ GtkWorkarounds.FixContainerLeak (this);
this.WidgetFlags |= WidgetFlags.NoWindow;
WidthRequest = 100;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs
index d6c04f907a..a60edb358e 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs
@@ -30,7 +30,6 @@ using System.ComponentModel;
using System.Drawing.Design;
using Cairo;
using Gtk;
-using Mono.TextEditor;
using System.Linq;
namespace MonoDevelop.Components
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/TooltipWindow.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/TooltipWindow.cs
index e5685f27af..95036e0cbe 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/TooltipWindow.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/TooltipWindow.cs
@@ -26,12 +26,10 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-using System;
using MonoDevelop.Ide;
using Gtk;
using Gdk;
-using Mono.TextEditor.PopupWindow;
namespace MonoDevelop.Components
{
@@ -41,7 +39,7 @@ namespace MonoDevelop.Components
public string LinkColor {
get {
- var color = Mono.TextEditor.HslColor.GenerateHighlightColors (Style.Background (State), Style.Text (State), 3)[2];
+ var color = HslColor.GenerateHighlightColors (Style.Background (State), Style.Text (State), 3)[2];
return color.ToPangoString ();
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/VPanedThin.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/VPanedThin.cs
index 838c04f970..ac607fda01 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/VPanedThin.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/VPanedThin.cs
@@ -34,7 +34,7 @@ namespace MonoDevelop.Components
public VPanedThin ()
{
- Mono.TextEditor.GtkWorkarounds.FixContainerLeak (this);
+ GtkWorkarounds.FixContainerLeak (this);
handle = new CustomPanedHandle (this);
handle.Parent = this;
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/WindowTransparencyDecorator.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/WindowTransparencyDecorator.cs
new file mode 100644
index 0000000000..9b8e8526d8
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/WindowTransparencyDecorator.cs
@@ -0,0 +1,116 @@
+//
+// WindowTransparencyDecorator.cs
+//
+// Author:
+// Michael Hutchinson <mhutch@xamarin.com>
+//
+// Based on code derived from Banshee.Widgets.EllipsizeLabel
+// by Aaron Bockover (aaron@aaronbock.net)
+//
+// Copyright (C) 2005-2008 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2012 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.Reflection;
+using System.Runtime.InteropServices;
+
+using Gtk;
+using Gdk;
+
+namespace MonoDevelop.Components
+{
+ public class WindowTransparencyDecorator
+ {
+ Gtk.Window window;
+ bool semiTransparent;
+ bool snooperInstalled;
+ uint snooperID;
+ const double opacity = 0.2;
+
+ WindowTransparencyDecorator (Gtk.Window window)
+ {
+ this.window = window;
+
+ window.Shown += ShownHandler;
+ window.Hidden += HiddenHandler;
+ window.Destroyed += DestroyedHandler;
+ }
+
+ public static WindowTransparencyDecorator Attach (Gtk.Window window)
+ {
+ return new WindowTransparencyDecorator (window);
+ }
+
+ public void Detach ()
+ {
+ if (window == null)
+ return;
+
+ //remove the snooper
+ HiddenHandler (null, null);
+
+ //annul allreferences between this and the window
+ window.Shown -= ShownHandler;
+ window.Hidden -= HiddenHandler;
+ window.Destroyed -= DestroyedHandler;
+ window = null;
+ }
+
+ void ShownHandler (object sender, EventArgs args)
+ {
+ if (!snooperInstalled)
+ snooperID = Gtk.Key.SnooperInstall (TransparencyKeySnooper);
+ snooperInstalled = true;
+
+ //NOTE: we unset transparency when showing, instead of when hiding
+ //because the latter case triggers a metacity+compositing bug that shows the window again
+ SemiTransparent = false;
+ }
+
+ void HiddenHandler (object sender, EventArgs args)
+ {
+ if (snooperInstalled)
+ Gtk.Key.SnooperRemove (snooperID);
+ snooperInstalled = false;
+ }
+
+ void DestroyedHandler (object sender, EventArgs args)
+ {
+ Detach ();
+ }
+
+ int TransparencyKeySnooper (Gtk.Widget widget, EventKey evnt)
+ {
+ if (evnt != null && evnt.Key == Gdk.Key.Control_L || evnt.Key == Gdk.Key.Control_R)
+ SemiTransparent = (evnt.Type == Gdk.EventType.KeyPress);
+ return 0; //FALSE
+ }
+
+ bool SemiTransparent {
+ set {
+ if (semiTransparent != value) {
+ semiTransparent = value;
+ window.Opacity = semiTransparent? opacity : 1.0;
+ }
+ }
+ }
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CodeCompletionContextEventArgs.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CodeCompletionContextEventArgs.cs
index a658f30b05..5d455b0bb3 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CodeCompletionContextEventArgs.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CodeCompletionContextEventArgs.cs
@@ -29,7 +29,7 @@ namespace MonoDevelop.Ide.CodeCompletion
{
public class CodeCompletionContextEventArgs : EventArgs
{
- public ICompletionWidget Widget {
+ internal ICompletionWidget Widget {
get;
set;
}
@@ -44,7 +44,7 @@ namespace MonoDevelop.Ide.CodeCompletion
set;
}
- public CodeCompletionContextEventArgs (ICompletionWidget widget, CodeCompletionContext codeCompletionContext, string completedWord)
+ internal CodeCompletionContextEventArgs (ICompletionWidget widget, CodeCompletionContext codeCompletionContext, string completedWord)
{
this.Widget = widget;
this.CodeCompletionContext = codeCompletionContext;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionCategory.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionCategory.cs
new file mode 100644
index 0000000000..fc88fd62b2
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionCategory.cs
@@ -0,0 +1,50 @@
+//
+// CompletionCategory.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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;
+
+namespace MonoDevelop.Ide.CodeCompletion
+{
+ public abstract class CompletionCategory : IComparable<CompletionCategory>
+ {
+ public string DisplayText { get; set; }
+
+ public string Icon { get; set; }
+
+ protected CompletionCategory ()
+ {
+ }
+
+ protected CompletionCategory (string displayText, string icon)
+ {
+ this.DisplayText = displayText;
+ this.Icon = icon;
+ }
+
+ public abstract int CompareTo (CompletionCategory other);
+ }
+
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionData.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionData.cs
index 2303d06b5e..e93c4687d0 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionData.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionData.cs
@@ -30,11 +30,11 @@ using System;
using System.Collections.Generic;
using System.Linq;
using MonoDevelop.Core;
-using ICSharpCode.NRefactory.Completion;
+using MonoDevelop.Ide.Editor.Extension;
namespace MonoDevelop.Ide.CodeCompletion
{
- public class CompletionData : ICompletionData, IComparable
+ public class CompletionData : IComparable
{
protected CompletionData () {}
@@ -43,6 +43,13 @@ namespace MonoDevelop.Ide.CodeCompletion
public virtual string Description { get; set; }
public virtual string CompletionText { get; set; }
+ /// <summary>
+ /// int.MaxValue == highest prioriy,
+ /// -int.MaxValue == lowest priority
+ /// </summary>
+ /// <value>The priority group.</value>
+ public virtual int PriorityGroup { get { return 0; } }
+
public virtual string GetDisplayDescription (bool isSelected)
{
return null;
@@ -70,13 +77,13 @@ namespace MonoDevelop.Ide.CodeCompletion
}
}
- public virtual IEnumerable<ICompletionData> OverloadedData {
+ public virtual IReadOnlyList<CompletionData> OverloadedData {
get {
throw new InvalidOperationException ();
}
}
- public virtual void AddOverload (ICompletionData data)
+ public virtual void AddOverload (CompletionData data)
{
throw new InvalidOperationException ();
}
@@ -102,7 +109,7 @@ namespace MonoDevelop.Ide.CodeCompletion
return result;
}
- public virtual void InsertCompletionText (CompletionListWindow window, ref KeyActions ka, Gdk.Key closeChar, char keyChar, Gdk.ModifierType modifier)
+ public virtual void InsertCompletionText (CompletionListWindow window, ref KeyActions ka, KeyDescriptor descriptor)
{
var currentWord = GetCurrentWord (window);
window.CompletionWidget.SetCompletionText (window.CodeCompletionContext, currentWord, CompletionText);
@@ -117,12 +124,12 @@ namespace MonoDevelop.Ide.CodeCompletion
public virtual int CompareTo (object obj)
{
- if (!(obj is ICompletionData))
+ if (!(obj is CompletionData))
return 0;
- return Compare (this, (ICompletionData)obj);
+ return Compare (this, (CompletionData)obj);
}
- public static int Compare (ICompletionData a, ICompletionData b)
+ public static int Compare (CompletionData a, CompletionData b)
{
var result = ((a.DisplayFlags & DisplayFlags.Obsolete) == (b.DisplayFlags & DisplayFlags.Obsolete)) ? StringComparer.OrdinalIgnoreCase.Compare (a.DisplayText, b.DisplayText) : (a.DisplayFlags & DisplayFlags.Obsolete) != 0 ? 1 : -1;
if (result == 0) {
@@ -133,7 +140,7 @@ namespace MonoDevelop.Ide.CodeCompletion
if (aIsImport && !bIsImport)
return 1;
if (aIsImport && bIsImport)
- return StringComparer.Ordinal.Compare (a.Description, b.Description);
+ return StringComparer.Ordinal.Compare (((CompletionData)a).Description, ((CompletionData)b).Description);
var ca = a as CompletionData;
var cb = b as CompletionData;
if (ca != null && cb != null && !ca.Icon.IsNull && !cb.Icon.IsNull) {
@@ -144,5 +151,19 @@ namespace MonoDevelop.Ide.CodeCompletion
}
#endregion
+
+ protected string ApplyDiplayFlagsFormatting (string markup)
+ {
+ if (!HasOverloads && (DisplayFlags & DisplayFlags.Obsolete) != 0 || HasOverloads && OverloadedData.All (data => (data.DisplayFlags & DisplayFlags.Obsolete) != 0))
+ return "<s>" + markup + "</s>";
+ if ((DisplayFlags & DisplayFlags.MarkedBold) != 0)
+ return "<b>" + markup + "</b>";
+ return markup;
+ }
+
+ public virtual string GetDisplayTextMarkup ()
+ {
+ return ApplyDiplayFlagsFormatting (GLib.Markup.EscapeText (DisplayText));
+ }
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionDataList.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionDataList.cs
index 2311475497..e0c21b8177 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionDataList.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionDataList.cs
@@ -30,12 +30,14 @@ using System;
using System.Collections.Generic;
using System.Linq;
using MonoDevelop.Core;
-using ICSharpCode.NRefactory.Completion;
+using MonoDevelop.Ide.Editor.Extension;
namespace MonoDevelop.Ide.CodeCompletion
{
- public interface ICompletionDataList : IList<ICompletionData>
+ public interface ICompletionDataList : IList<CompletionData>
{
+ int TriggerWordLength { get; }
+
bool IsSorted { get; }
bool AutoCompleteUniqueMatch { get; }
bool AutoCompleteEmptyMatch { get; }
@@ -44,8 +46,8 @@ namespace MonoDevelop.Ide.CodeCompletion
bool AutoSelect { get; }
string DefaultCompletionString { get; }
CompletionSelectionMode CompletionSelectionMode { get; }
- void Sort (Comparison<ICompletionData> comparison);
- void Sort (IComparer<ICompletionData> comparison);
+ void Sort (Comparison<CompletionData> comparison);
+ void Sort (IComparer<CompletionData> comparison);
IEnumerable<ICompletionKeyHandler> KeyHandler { get; }
@@ -56,8 +58,8 @@ namespace MonoDevelop.Ide.CodeCompletion
public interface ICompletionKeyHandler
{
- bool PreProcessKey (CompletionListWindow listWindow, Gdk.Key key, char keyChar, Gdk.ModifierType modifier, out KeyActions keyAction);
- bool PostProcessKey (CompletionListWindow listWindow, Gdk.Key key, char keyChar, Gdk.ModifierType modifier, out KeyActions keyAction);
+ bool PreProcessKey (CompletionListWindow listWindow, KeyDescriptor descriptor, out KeyActions keyAction);
+ bool PostProcessKey (CompletionListWindow listWindow, KeyDescriptor descriptor, out KeyActions keyAction);
}
public enum CompletionSelectionMode {
@@ -65,10 +67,12 @@ namespace MonoDevelop.Ide.CodeCompletion
OwnTextField
}
- public class CompletionDataList : List<ICompletionData>, ICompletionDataList
+ public class CompletionDataList : List<CompletionData>, ICompletionDataList
{
+ public int TriggerWordLength { get; set; }
+
public bool IsSorted { get; set; }
- public IComparer<ICompletionData> Comparer { get; set; }
+ public IComparer<CompletionData> Comparer { get; set; }
public bool AutoCompleteUniqueMatch { get; set; }
public string DefaultCompletionString { get; set; }
@@ -87,7 +91,7 @@ namespace MonoDevelop.Ide.CodeCompletion
this.AutoSelect = true;
}
- public CompletionDataList (IEnumerable<ICompletionData> data) : base(data)
+ public CompletionDataList (IEnumerable<CompletionData> data) : base(data)
{
this.AutoSelect = true;
}
@@ -144,7 +148,7 @@ namespace MonoDevelop.Ide.CodeCompletion
return false;
}
- public void RemoveWhere (Func<ICompletionData,bool> shouldRemove)
+ public void RemoveWhere (Func<CompletionData,bool> shouldRemove)
{
for (int i = 0; i < this.Count;) {
if (shouldRemove (this[i]))
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionListWindow.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionListWindow.cs
index 224fa14b54..d31732a305 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionListWindow.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionListWindow.cs
@@ -32,8 +32,8 @@ using Gtk;
using MonoDevelop.Core;
using MonoDevelop.Components;
using System.Linq;
-using ICSharpCode.NRefactory.Completion;
-using Mono.TextEditor.PopupWindow;
+using MonoDevelop.Ide.Editor.Extension;
+using System.ComponentModel;
namespace MonoDevelop.Ide.CodeCompletion
{
@@ -42,11 +42,11 @@ namespace MonoDevelop.Ide.CodeCompletion
const int declarationWindowMargin = 3;
TooltipInformationWindow declarationviewwindow;
- ICompletionData currentData;
+ CompletionData currentData;
Widget parsingMessage;
int initialWordLength;
int previousWidth = -1, previousHeight = -1;
-
+
public CodeCompletionContext CodeCompletionContext {
get;
set;
@@ -60,7 +60,6 @@ namespace MonoDevelop.Ide.CodeCompletion
}
IMutableCompletionDataList mutableList;
- ICompletionDataList completionDataList;
public ICompletionDataList CompletionDataList {
get { return completionDataList; }
set {
@@ -93,7 +92,7 @@ namespace MonoDevelop.Ide.CodeCompletion
List.QueueDraw ();
};
previewEntry.KeyPressEvent += delegate(object o, KeyPressEventArgs args) {
- var keyAction = PreProcessKey (args.Event.Key, (char)args.Event.KeyValue, args.Event.State);
+ var keyAction = PreProcessKey (KeyDescriptor.FromGtk (args.Event.Key, (char)args.Event.KeyValue, args.Event.State));
if (keyAction.HasFlag (KeyActions.Complete))
CompleteWord ();
@@ -189,61 +188,81 @@ namespace MonoDevelop.Ide.CodeCompletion
base.OnDestroyed ();
}
- public void PostProcessKeyEvent (Gdk.Key key, char keyChar, Gdk.ModifierType modifier)
+ public void PostProcessKeyEvent (KeyDescriptor descriptor)
{
KeyActions ka = KeyActions.None;
bool keyHandled = false;
- foreach (var handler in CompletionDataList.KeyHandler) {
- if (handler.PostProcessKey (this, key, keyChar, modifier, out ka)) {
- keyHandled = true;
- break;
+ if (CompletionDataList != null) {
+ foreach (var handler in CompletionDataList.KeyHandler) {
+ if (handler.PostProcessKey (this, descriptor, out ka)) {
+ keyHandled = true;
+ break;
+ }
}
}
if (!keyHandled)
- ka = PostProcessKey (key, keyChar, modifier);
+ ka = PostProcessKey (descriptor);
if ((ka & KeyActions.Complete) != 0)
- CompleteWord (ref ka, key, keyChar, modifier);
- if ((ka & KeyActions.CloseWindow) != 0)
+ CompleteWord (ref ka, descriptor);
+ if ((ka & KeyActions.CloseWindow) != 0) {
CompletionWindowManager.HideWindow ();
+ OnWindowClosed (EventArgs.Empty);
+ }
+ }
+
+ /// <summary>
+ /// For unit test purposes.
+ /// </summary>
+ [EditorBrowsableAttribute(EditorBrowsableState.Never)]
+ internal event EventHandler WindowClosed;
+
+ protected virtual void OnWindowClosed (EventArgs e)
+ {
+ var handler = WindowClosed;
+ if (handler != null)
+ handler (this, e);
}
public void ToggleCategoryMode ()
{
- List.InCategoryMode = !List.InCategoryMode;
+ ListWidget.EnableCompletionCategoryMode.Set (!ListWidget.EnableCompletionCategoryMode.Value);
+ List.UpdateCategoryMode ();
ResetSizes ();
List.QueueDraw ();
}
- public bool PreProcessKeyEvent (Gdk.Key key, char keyChar, Gdk.ModifierType modifier)
+ public bool PreProcessKeyEvent (KeyDescriptor descriptor)
{
- if (key == Gdk.Key.Escape) {
+ if (descriptor.SpecialKey == SpecialKey.Escape) {
CompletionWindowManager.HideWindow ();
return true;
}
KeyActions ka = KeyActions.None;
bool keyHandled = false;
- foreach (ICompletionKeyHandler handler in CompletionDataList.KeyHandler) {
- if (handler.PreProcessKey (this, key, keyChar, modifier, out ka)) {
- keyHandled = true;
- break;
+ if (CompletionDataList != null) {
+ foreach (ICompletionKeyHandler handler in CompletionDataList.KeyHandler) {
+ if (handler.PreProcessKey (this, descriptor, out ka)) {
+ keyHandled = true;
+ break;
+ }
}
}
-
if (!keyHandled)
- ka = PreProcessKey (key, keyChar, modifier);
+ ka = PreProcessKey (descriptor);
if ((ka & KeyActions.Complete) != 0)
- CompleteWord (ref ka, key, keyChar, modifier);
+ CompleteWord (ref ka, descriptor);
- if ((ka & KeyActions.CloseWindow) != 0)
+ if ((ka & KeyActions.CloseWindow) != 0) {
CompletionWindowManager.HideWindow ();
+ OnWindowClosed (EventArgs.Empty);
+ }
if ((ka & KeyActions.Ignore) != 0)
return true;
-
if ((ka & KeyActions.Process) != 0) {
- if (key == Gdk.Key.Left || key == Gdk.Key.Right) {
+ if (descriptor.SpecialKey == SpecialKey.Left || descriptor.SpecialKey == SpecialKey.Right) {
// Close if there's a modifier active EXCEPT lock keys and Modifiers
// Makes an exception for Mod1Mask (usually alt), shift, control, meta and super
// This prevents the window from closing if the num/scroll/caps lock are active
@@ -252,19 +271,21 @@ namespace MonoDevelop.Ide.CodeCompletion
// if ((modifier & ~(Gdk.ModifierType.LockMask | (Gdk.ModifierType.ModifierMask & ~(Gdk.ModifierType.ShiftMask | Gdk.ModifierType.Mod1Mask | Gdk.ModifierType.ControlMask | Gdk.ModifierType.MetaMask | Gdk.ModifierType.SuperMask)))) != 0) {
// this version doesn't work for my system - seems that I've a modifier active
// that gdk doesn't know about. How about the 2nd version - should close on left/rigt + shift/mod1/control/meta/super
- if ((modifier & (Gdk.ModifierType.ShiftMask | Gdk.ModifierType.Mod1Mask | Gdk.ModifierType.ControlMask | Gdk.ModifierType.MetaMask | Gdk.ModifierType.SuperMask)) != 0) {
+ if ((descriptor.ModifierKeys & (ModifierKeys.Shift | ModifierKeys.Alt | ModifierKeys.Control | ModifierKeys.Command)) != 0) {
CompletionWindowManager.HideWindow ();
+ OnWindowClosed (EventArgs.Empty);
return false;
}
if (declarationviewwindow != null && declarationviewwindow.Multiple) {
- if (key == Gdk.Key.Left)
+ if (descriptor.SpecialKey == SpecialKey.Left)
declarationviewwindow.OverloadLeft ();
else
declarationviewwindow.OverloadRight ();
UpdateDeclarationView ();
} else {
CompletionWindowManager.HideWindow ();
+ OnWindowClosed (EventArgs.Empty);
return false;
}
return true;
@@ -286,8 +307,8 @@ namespace MonoDevelop.Ide.CodeCompletion
{
if (list == null)
throw new ArgumentNullException ("list");
- if (completionContext == null)
- throw new ArgumentNullException ("completionContext");
+ if (completionWidget == null)
+ throw new ArgumentNullException ("completionWidget");
if (completionContext == null)
throw new ArgumentNullException ("completionContext");
if (mutableList != null) {
@@ -355,9 +376,9 @@ namespace MonoDevelop.Ide.CodeCompletion
return false;
}
- class DataItemComparer : IComparer<ICompletionData>
+ class DataItemComparer : IComparer<CompletionData>
{
- public int Compare (ICompletionData a, ICompletionData b)
+ public int Compare (CompletionData a, CompletionData b)
{
if (a is IComparable && b is IComparable)
return ((IComparable)a).CompareTo (b);
@@ -365,7 +386,7 @@ namespace MonoDevelop.Ide.CodeCompletion
}
}
- IComparer<ICompletionData> GetComparerForCompletionList (ICompletionDataList dataList)
+ IComparer<CompletionData> GetComparerForCompletionList (ICompletionDataList dataList)
{
var concrete = dataList as CompletionDataList;
return concrete != null && concrete.Comparer != null ? concrete.Comparer : new DataItemComparer ();
@@ -443,23 +464,40 @@ namespace MonoDevelop.Ide.CodeCompletion
public bool CompleteWord ()
{
KeyActions ka = KeyActions.None;
- return CompleteWord (ref ka, (Gdk.Key)0, '\0', Gdk.ModifierType.None);
+ return CompleteWord (ref ka, KeyDescriptor.Empty);
}
-
- public bool CompleteWord (ref KeyActions ka, Gdk.Key closeChar, char keyChar, Gdk.ModifierType modifier)
+
+ internal bool IsInCompletion { get; set; }
+
+ public bool CompleteWord (ref KeyActions ka, KeyDescriptor descriptor)
{
if (SelectedItem == -1 || completionDataList == null)
return false;
var item = completionDataList [SelectedItem];
if (item == null)
return false;
- // first close the completion list, then insert the text.
- // this is required because that's the logical event chain, otherwise things could be messed up
- CloseCompletionList ();
- ((CompletionData)item).InsertCompletionText (this, ref ka, closeChar, keyChar, modifier);
- AddWordToHistory (PartialWord, item.CompletionText);
- OnWordCompleted (new CodeCompletionContextEventArgs (CompletionWidget, CodeCompletionContext, item.CompletionText));
- return true;
+ IsInCompletion = true;
+ try {
+ // first close the completion list, then insert the text.
+ // this is required because that's the logical event chain, otherwise things could be messed up
+ CloseCompletionList ();
+ /* var cdItem = (CompletionData)item;
+ cdItem.InsertCompletionText (this, ref ka, closeChar, keyChar, modifier);
+ AddWordToHistory (PartialWord, cdItem.CompletionText);
+ OnWordCompleted (new CodeCompletionContextEventArgs (CompletionWidget, CodeCompletionContext, cdItem.CompletionText));
+ */
+ if (item.HasOverloads && declarationviewwindow.CurrentOverload >= 0 && declarationviewwindow.CurrentOverload < item.OverloadedData.Count) {
+ item.OverloadedData[declarationviewwindow.CurrentOverload].InsertCompletionText (this, ref ka, descriptor);
+ } else {
+ item.InsertCompletionText (this, ref ka, descriptor);
+ }
+ cache.CommitCompletionData (item);
+ OnWordCompleted (new CodeCompletionContextEventArgs (CompletionWidget, CodeCompletionContext, item.DisplayText));
+ } finally {
+ IsInCompletion = false;
+ CompletionWindowManager.HideWindow ();
+ }
+ return true;
}
protected virtual void OnWordCompleted (CodeCompletionContextEventArgs e)
@@ -587,17 +625,17 @@ namespace MonoDevelop.Ide.CodeCompletion
return false;
var data = completionDataList [selectedItem];
- IEnumerable<ICompletionData> filteredOverloads;
+ IEnumerable<CompletionData> filteredOverloads;
if (data.HasOverloads) {
filteredOverloads = data.OverloadedData;
} else {
- filteredOverloads = new ICompletionData[] { data };
+ filteredOverloads = new CompletionData[] { data };
}
EnsureDeclarationViewWindow ();
if (data != currentData) {
declarationviewwindow.Clear ();
- var overloads = new List<ICompletionData> (filteredOverloads);
+ var overloads = new List<CompletionData> (filteredOverloads);
foreach (var overload in overloads) {
declarationviewwindow.AddOverload ((CompletionData)overload);
}
@@ -626,7 +664,7 @@ namespace MonoDevelop.Ide.CodeCompletion
return false;
}
- protected override void ResetState ()
+ protected internal override void ResetState ()
{
StartOffset = 0;
previousWidth = previousHeight = -1;
@@ -663,28 +701,27 @@ namespace MonoDevelop.Ide.CodeCompletion
bool IListDataProvider.HasMarkup (int n)
{
- return (completionDataList [n].DisplayFlags & (DisplayFlags.Obsolete | DisplayFlags.MarkedBold)) != 0;
+ return true;
}
//NOTE: we only ever return markup for items marked as obsolete
string IListDataProvider.GetMarkup (int n)
{
var completionData = completionDataList[n];
- if (!completionData.HasOverloads && (completionData.DisplayFlags & DisplayFlags.Obsolete) != 0 ||
- completionData.HasOverloads && completionData.OverloadedData.All (data => (data.DisplayFlags & DisplayFlags.Obsolete) != 0))
- return "<s>" + GLib.Markup.EscapeText (completionDataList[n].DisplayText) + "</s>";
-
- if ((completionData.DisplayFlags & DisplayFlags.MarkedBold) != 0)
- return "<b>" + GLib.Markup.EscapeText (completionDataList[n].DisplayText) + "</b>";
- return GLib.Markup.EscapeText (completionDataList[n].DisplayText);
+ return completionData.GetDisplayTextMarkup ();
}
string IListDataProvider.GetCompletionText (int n)
{
- return completionDataList[n].CompletionText;
+ return ((CompletionData)completionDataList[n]).CompletionText;
+ }
+
+ CompletionData IListDataProvider.GetCompletionData (int n)
+ {
+ return completionDataList[n];
}
- IComparer<ICompletionData> defaultComparer;
+ IComparer<CompletionData> defaultComparer;
int IListDataProvider.CompareTo (int n, int m)
{
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..b383b7b65d 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionWindowManager.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionWindowManager.cs
@@ -27,6 +27,7 @@
using System;
using MonoDevelop.Core;
using MonoDevelop.Ide.Gui.Content;
+using MonoDevelop.Ide.Editor.Extension;
namespace MonoDevelop.Ide.CodeCompletion
{
@@ -80,20 +81,22 @@ namespace MonoDevelop.Ide.CodeCompletion
}
// ext may be null, but then parameter completion don't work
- public static bool ShowWindow (CompletionTextEditorExtension ext, char firstChar, ICompletionDataList list, ICompletionWidget completionWidget, CodeCompletionContext completionContext)
+ internal static bool ShowWindow (CompletionTextEditorExtension ext, char firstChar, ICompletionDataList list, ICompletionWidget completionWidget, CodeCompletionContext completionContext)
{
try {
if (ext != null) {
- int inserted = ext.document.Editor.EnsureCaretIsNotVirtual ();
+ int inserted = ext.Editor.EnsureCaretIsNotVirtual ();
if (inserted > 0)
- completionContext.TriggerOffset = ext.document.Editor.Caret.Offset;
+ completionContext.TriggerOffset = ext.Editor.CaretOffset;
}
if (wnd == null) {
wnd = new CompletionListWindow ();
wnd.WordCompleted += HandleWndWordCompleted;
}
- if (ext != null)
- wnd.TransientFor = ext.document.Editor.Parent.Toplevel as Gtk.Window;
+ if (ext != null) {
+ var widget = ext.Editor.GetNativeWidget<Gtk.Widget> ();
+ wnd.TransientFor = widget?.Parent?.Toplevel as Gtk.Window;
+ }
wnd.Extension = ext;
try {
if (!wnd.ShowListWindow (firstChar, list, completionWidget, completionContext)) {
@@ -136,21 +139,22 @@ namespace MonoDevelop.Ide.CodeCompletion
OnWindowClosed (EventArgs.Empty);
}
- public static bool PreProcessKeyEvent (Gdk.Key key, char keyChar, Gdk.ModifierType modifier)
+ public static bool PreProcessKeyEvent (KeyDescriptor descriptor)
{
if (!IsVisible)
return false;
- if (keyChar != '\0') {
+ if (descriptor.KeyChar != '\0') {
wnd.EndOffset = wnd.StartOffset + wnd.CurrentPartialWord.Length + 1;
}
- return wnd.PreProcessKeyEvent (key, keyChar, modifier);
+ return wnd.PreProcessKeyEvent (descriptor);
}
public static void UpdateCursorPosition ()
{
if (!IsVisible)
return;
-
+ if (wnd.IsInCompletion)
+ return;
var caretOffset = wnd.CompletionWidget.CaretOffset;
if (caretOffset < wnd.StartOffset || caretOffset > wnd.EndOffset)
HideWindow ();
@@ -164,11 +168,11 @@ namespace MonoDevelop.Ide.CodeCompletion
}
}
- public static void PostProcessKeyEvent (Gdk.Key key, char keyChar, Gdk.ModifierType modifier)
+ public static void PostProcessKeyEvent (KeyDescriptor descriptor)
{
if (!IsVisible)
return;
- wnd.PostProcessKeyEvent (key, keyChar, modifier);
+ wnd.PostProcessKeyEvent (descriptor);
}
public static void RepositionWindow ()
@@ -184,7 +188,7 @@ namespace MonoDevelop.Ide.CodeCompletion
return;
ParameterInformationWindowManager.UpdateWindow (wnd.Extension, wnd.CompletionWidget);
if (wnd.Extension != null)
- wnd.Extension.document.Editor.FixVirtualIndentation ();
+ wnd.Extension.Editor.FixVirtualIndentation ();
wnd.HideWindow ();
OnWindowClosed (EventArgs.Empty);
//DestroyWindow ();
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/IRefactoringContext.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/DisplayFlags.cs
index c14b46e8fc..0450a0f7d2 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/IRefactoringContext.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/DisplayFlags.cs
@@ -1,10 +1,10 @@
//
-// IRefactoringContext.cs
+// DisplayFlags.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
-// Copyright (c) 2013 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
@@ -26,16 +26,17 @@
using System;
-namespace MonoDevelop.Ide.TypeSystem
+namespace MonoDevelop.Ide.CodeCompletion
{
- /// <summary>
- /// Base interface for refactoring contexts
- /// </summary>
- public interface IRefactoringContext
+ [Flags]
+ public enum DisplayFlags
{
- /// <summary>
- /// Creates a refactoring script.
- /// </summary>
- IDisposable CreateScript ();
+ None = 0,
+ Hidden = 1,
+ Obsolete = 2,
+ DescriptionHasMarkup = 4,
+ NamedArgument = 8,
+ IsImportCompletion = 16,
+ MarkedBold = 32
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ICompletionWidget.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ICompletionWidget.cs
index 668359506a..1824432bb9 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ICompletionWidget.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ICompletionWidget.cs
@@ -31,29 +31,33 @@ using Gtk;
namespace MonoDevelop.Ide.CodeCompletion
{
- public interface ICompletionWidget
+ interface ICompletionWidget
{
- CodeCompletionContext CurrentCodeCompletionContext {
+ CodeCompletionContext CurrentCodeCompletionContext
+ {
get;
}
- int CaretOffset { get;}
+ int CaretOffset { get; set; }
int TextLength { get; }
int SelectedLength { get; }
string GetText (int startOffset, int endOffset);
-
+
char GetChar (int offset);
-
+
void Replace (int offset, int count, string text);
-
+
Gtk.Style GtkStyle { get; }
+ double ZoomLevel { get; }
CodeCompletionContext CreateCodeCompletionContext (int triggerOffset);
string GetCompletionText (CodeCompletionContext ctx);
void SetCompletionText (CodeCompletionContext ctx, string partial_word, string complete_word);
-
+
void SetCompletionText (CodeCompletionContext ctx, string partial_word, string complete_word, int completeWordOffset);
-
+
+ void AddSkipChar (int cursorPosition, char c);
+
event EventHandler CompletionContextChanged;
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ListWidget.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ListWidget.cs
index 0b607df034..72367422a9 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ListWidget.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ListWidget.cs
@@ -30,12 +30,14 @@ using System.Linq;
using Gdk;
using Gtk;
using Pango;
-using ICSharpCode.NRefactory.Completion;
-using Mono.TextEditor;
-using Mono.TextEditor.Highlighting;
+using ICSharpCode.NRefactory6.CSharp.Completion;
using MonoDevelop.Components;
using MonoDevelop.Ide.Fonts;
-using MonoDevelop.Ide.Gui.Content;
+using MonoDevelop.Ide.Gui.Content;
+using MonoDevelop.Ide.Editor;
+using System.ComponentModel.Design;
+using MonoDevelop.Ide.Editor.Highlighting;
+using MonoDevelop.Ide.Editor.Extension;
using MonoDevelop.Core;
namespace MonoDevelop.Ide.CodeCompletion
@@ -95,26 +97,27 @@ namespace MonoDevelop.Ide.CodeCompletion
public bool CloseOnSquareBrackets {
get;
set;
- }
-
- public readonly static PropertyWrapper<bool> EnableCompletionCategoryMode = PropertyService.Wrap("EnableCompletionCategoryMode", false);
-
+ }
+
+ public readonly static PropertyWrapper<bool> EnableCompletionCategoryMode = PropertyService.Wrap("EnableCompletionCategoryMode", false);
+
public bool InCategoryMode {
- get { return EnableCompletionCategoryMode; }
- set {
- EnableCompletionCategoryMode.Set(value);
+ get { return EnableCompletionCategoryMode && categories.Count > 1; }
+ }
- CalcVisibleRows ();
- if (value)
- SelectFirstItemInCategory ();
- }
+ internal void UpdateCategoryMode ()
+ {
+ CalcVisibleRows ();
+ if (InCategoryMode)
+ SelectFirstItemInCategory ();
}
+
public int CategoryCount {
get { return this.categories.Count; }
}
ICompletionWidget completionWidget;
- public ICompletionWidget CompletionWidget {
+ internal ICompletionWidget CompletionWidget {
get {
return completionWidget;
}
@@ -141,14 +144,11 @@ namespace MonoDevelop.Ide.CodeCompletion
// TODO: Add font property to ICompletionWidget;
if (itemFont != null)
itemFont.Dispose ();
- itemFont = FontService.GetFontDescription ("Editor").Copy ();
- var provider = CompletionWidget as ITextEditorDataProvider;
- if (provider != null) {
- var newSize = (itemFont.Size * provider.GetTextEditorData ().Options.Zoom);
- if (newSize > 0) {
- itemFont.Size = (int)newSize;
- layout.FontDescription = itemFont;
- }
+ itemFont = FontService.MonospaceFont.Copy ();
+ var newSize = (itemFont.Size * (completionWidget != null ? this.completionWidget.ZoomLevel : 1));
+ if (newSize > 0) {
+ itemFont.Size = (int)newSize;
+ layout.FontDescription = itemFont;
}
}
@@ -380,9 +380,17 @@ namespace MonoDevelop.Ide.CodeCompletion
public bool SelectionEnabled {
get {
- return AutoSelect && (AutoCompleteEmptyMatch || !string.IsNullOrEmpty (CompletionString));
+ return AutoSelect && (AutoCompleteEmptyMatch || !IsEmptyMatch (CompletionString));
}
}
+
+ static bool IsEmptyMatch (string completionString)
+ {
+ if (string.IsNullOrEmpty (completionString))
+ return true;
+ var ch = completionString [0];
+ return char.IsDigit (ch);
+ }
protected override bool OnButtonPressEvent (EventButton e)
{
@@ -656,7 +664,7 @@ namespace MonoDevelop.Ide.CodeCompletion
});
categories = newCategories;
- SelectFirstItemInCategory ();
+ //SelectFirstItemInCategory ();
CalcVisibleRows ();
SetAdjustments ();
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ListWindow.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ListWindow.cs
index 97f12ae487..0a2edce515 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ListWindow.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ListWindow.cs
@@ -25,21 +25,20 @@
//
//
-using Gtk;
-using Gdk;
-using Pango;
using System;
-using System.Xml;
-using System.Linq;
-using System.Text;
using System.Collections.Generic;
using MonoDevelop.Core.Text;
-using ICSharpCode.NRefactory.Completion;
-using Mono.TextEditor;
+using ICSharpCode.NRefactory6.CSharp.Completion;
using MonoDevelop.Ide.Gui.Content;
+using System.Linq;
+using Gdk;
+using Gtk;
+using MonoDevelop.Core.Text;
using MonoDevelop.Components;
-using Mono.TextEditor.Highlighting;
-using MonoDevelop.Core;
+using MonoDevelop.Ide.Gui.Content;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Ide.Editor.Highlighting;
+using MonoDevelop.Ide.Editor.Extension;
namespace MonoDevelop.Ide.CodeCompletion
{
@@ -60,7 +59,9 @@ namespace MonoDevelop.Ide.CodeCompletion
ListWidget list;
Widget footer;
protected VBox vbox;
-
+ internal MruCache cache = new MruCache();
+ protected ICompletionDataList completionDataList;
+
public CompletionTextEditorExtension Extension {
get;
set;
@@ -129,7 +130,7 @@ namespace MonoDevelop.Ide.CodeCompletion
/// This method is used to set the completion window to it's inital state.
/// This is required for re-using the window object.
/// </summary>
- protected virtual void ResetState ()
+ protected internal virtual void ResetState ()
{
HideWhenWordDeleted = false;
lastCommitCharEndoffset = -1;
@@ -226,7 +227,7 @@ namespace MonoDevelop.Ide.CodeCompletion
set;
}
- public ICompletionWidget CompletionWidget {
+ internal ICompletionWidget CompletionWidget {
get {
return list.CompletionWidget;
}
@@ -273,20 +274,21 @@ namespace MonoDevelop.Ide.CodeCompletion
private set;
}
- public KeyActions PostProcessKey (Gdk.Key key, char keyChar, Gdk.ModifierType modifier)
+ public KeyActions PostProcessKey (KeyDescriptor descriptor)
{
- if (StartOffset > CompletionWidget.CaretOffset)
+ if (CompletionWidget == null || StartOffset > CompletionWidget.CaretOffset) // CompletionWidget == null may happen in unit tests.
return KeyActions.CloseWindow | KeyActions.Process;
if (HideWhenWordDeleted && StartOffset >= CompletionWidget.CaretOffset)
return KeyActions.CloseWindow | KeyActions.Process;
- switch (key) {
- case Gdk.Key.BackSpace:
+ switch (descriptor.SpecialKey) {
+ case SpecialKey.BackSpace:
ResetSizes ();
UpdateWordSelection ();
return KeyActions.Process;
}
-
+ var keyChar = descriptor.KeyChar;
+
const string commitChars = " <>()[]{}=+-*/%~&^|!.,;:";
if (keyChar == '[' && CloseOnSquareBrackets)
return KeyActions.Process | KeyActions.CloseWindow;
@@ -306,13 +308,13 @@ namespace MonoDevelop.Ide.CodeCompletion
if (!text.ToUpper ().StartsWith (curword.ToUpper (), StringComparison.Ordinal))
match = -1;
}
- if (match >= 0 && !hasMismatches && keyChar != '<') {
+ if (match >= 0 && !hasMismatches && keyChar != '<' && keyChar != ' ') {
ResetSizes ();
UpdateWordSelection ();
return KeyActions.Process;
}
- if (keyChar == '.')
- list.AutoSelect = list.AutoCompleteEmptyMatch = true;
+// if (keyChar == '.')
+// list.AutoSelect = list.AutoCompleteEmptyMatch = true;
lastCommitCharEndoffset = CompletionWidget.CaretOffset - 1;
if (list.SelectionEnabled && CompletionCharacters.CompleteOn (keyChar)) {
@@ -322,30 +324,47 @@ namespace MonoDevelop.Ide.CodeCompletion
}
return KeyActions.CloseWindow | KeyActions.Process;
}
-
+
+ if (char.IsPunctuation (descriptor.KeyChar) && descriptor.KeyChar != '_') {
+ if (descriptor.KeyChar == ':') {
+ foreach (var item in FilteredItems) {
+ if (DataProvider.GetText (item).EndsWith (descriptor.KeyChar.ToString (), StringComparison.Ordinal)) {
+ list.SelectedItem = item;
+ return KeyActions.Complete | KeyActions.CloseWindow | KeyActions.Ignore;
+ }
+ }
+ } else {
+ var selectedItem = list.SelectedItem;
+ if (selectedItem < 0 || selectedItem >= DataProvider.ItemCount)
+ return KeyActions.CloseWindow;
+ if (!DataProvider.GetText (selectedItem).Substring (0, CurrentPartialWord.Length) .EndsWith (descriptor.KeyChar.ToString (), StringComparison.Ordinal))
+ return KeyActions.Process | KeyActions.CloseWindow;
+ }
+ }
return KeyActions.Process;
}
- public KeyActions PreProcessKey (Gdk.Key key, char keyChar, Gdk.ModifierType modifier)
+ public KeyActions PreProcessKey (KeyDescriptor descriptor)
{
- switch (key) {
- case Gdk.Key.Home:
- if ((modifier & ModifierType.ShiftMask) == ModifierType.ShiftMask)
+ switch (descriptor.SpecialKey) {
+ case SpecialKey.Home:
+ if ((descriptor.ModifierKeys & ModifierKeys.Shift) == ModifierKeys.Shift)
return KeyActions.Process;
List.SelectionFilterIndex = 0;
return KeyActions.Ignore;
- case Gdk.Key.End:
- if ((modifier & ModifierType.ShiftMask) == ModifierType.ShiftMask)
+ case SpecialKey.End:
+ if ((descriptor.ModifierKeys & ModifierKeys.Shift) == ModifierKeys.Shift)
return KeyActions.Process;
List.SelectionFilterIndex = List.filteredItems.Count - 1;
return KeyActions.Ignore;
- case Gdk.Key.Up:
- if ((modifier & Gdk.ModifierType.ShiftMask) == Gdk.ModifierType.ShiftMask) {
+ case SpecialKey.Up:
+ if ((descriptor.ModifierKeys & ModifierKeys.Shift) == ModifierKeys.Shift) {
if (!SelectionEnabled /*&& !CompletionWindowManager.ForceSuggestionMode*/)
AutoCompleteEmptyMatch = AutoSelect = true;
if (!List.InCategoryMode) {
- List.InCategoryMode = true;
+ ListWidget.EnableCompletionCategoryMode.Set (true);
+ List.UpdateCategoryMode ();
return KeyActions.Ignore;
}
List.MoveToCategory (-1);
@@ -360,25 +379,23 @@ namespace MonoDevelop.Ide.CodeCompletion
}
return KeyActions.Ignore;
- case Gdk.Key.Tab:
+ case SpecialKey.Tab:
//tab always completes current item even if selection is disabled
if (!AutoSelect)
AutoSelect = true;
- goto case Gdk.Key.Return;
+ goto case SpecialKey.Return;
- case Gdk.Key.Return:
- case Gdk.Key.ISO_Enter:
- case Gdk.Key.Key_3270_Enter:
- case Gdk.Key.KP_Enter:
+ case SpecialKey.Return:
lastCommitCharEndoffset = CompletionWidget.CaretOffset;
- WasShiftPressed = (modifier & ModifierType.ShiftMask) == ModifierType.ShiftMask;
+ WasShiftPressed = (descriptor.ModifierKeys & ModifierKeys.Shift) == ModifierKeys.Shift;
return KeyActions.Complete | KeyActions.Ignore | KeyActions.CloseWindow;
- case Gdk.Key.Down:
- if ((modifier & Gdk.ModifierType.ShiftMask) == Gdk.ModifierType.ShiftMask) {
+ case SpecialKey.Down:
+ if ((descriptor.ModifierKeys & ModifierKeys.Shift) == ModifierKeys.Shift) {
if (!SelectionEnabled /*&& !CompletionWindowManager.ForceSuggestionMode*/)
AutoCompleteEmptyMatch = AutoSelect = true;
if (!List.InCategoryMode) {
- List.InCategoryMode = true;
+ ListWidget.EnableCompletionCategoryMode.Set (true);
+ List.UpdateCategoryMode ();
return KeyActions.Ignore;
}
List.MoveToCategory (1);
@@ -394,8 +411,8 @@ namespace MonoDevelop.Ide.CodeCompletion
}
return KeyActions.Ignore;
- case Gdk.Key.Page_Up:
- if ((modifier & ModifierType.ShiftMask) == ModifierType.ShiftMask)
+ case SpecialKey.PageUp:
+ if ((descriptor.ModifierKeys & ModifierKeys.Shift) == ModifierKeys.Shift)
return KeyActions.Process;
if (list.filteredItems.Count < 2)
return KeyActions.CloseWindow | KeyActions.Process;
@@ -403,8 +420,8 @@ namespace MonoDevelop.Ide.CodeCompletion
list.MoveCursor (-8);
return KeyActions.Ignore;
- case Gdk.Key.Page_Down:
- if ((modifier & ModifierType.ShiftMask) == ModifierType.ShiftMask)
+ case SpecialKey.PageDown:
+ if ((descriptor.ModifierKeys & ModifierKeys.Shift) == ModifierKeys.Shift)
return KeyActions.Process;
if (list.filteredItems.Count < 2)
return KeyActions.CloseWindow | KeyActions.Process;
@@ -412,42 +429,42 @@ namespace MonoDevelop.Ide.CodeCompletion
list.MoveCursor (8);
return KeyActions.Ignore;
- case Gdk.Key.Left:
+ case SpecialKey.Left:
//if (curPos == 0) return KeyActions.CloseWindow | KeyActions.Process;
//curPos--;
return KeyActions.Process;
- case Gdk.Key.Right:
+ case SpecialKey.Right:
//if (curPos == word.Length) return KeyActions.CloseWindow | KeyActions.Process;
//curPos++;
return KeyActions.Process;
- case Gdk.Key.Caps_Lock:
- case Gdk.Key.Num_Lock:
- case Gdk.Key.Scroll_Lock:
- return KeyActions.Ignore;
-
- case Gdk.Key.Control_L:
- case Gdk.Key.Control_R:
- case Gdk.Key.Alt_L:
- case Gdk.Key.Alt_R:
- case Gdk.Key.Shift_L:
- case Gdk.Key.Shift_R:
- case Gdk.Key.ISO_Level3_Shift:
- // AltGr
- return KeyActions.Process;
+// case Gdk.Key.Caps_Lock:
+// case Gdk.Key.Num_Lock:
+// case Gdk.Key.Scroll_Lock:
+// return KeyActions.Ignore;
+//
+// case Gdk.Key.Control_L:
+// case Gdk.Key.Control_R:
+// case Gdk.Key.Alt_L:
+// case Gdk.Key.Alt_R:
+// case Gdk.Key.Shift_L:
+// case Gdk.Key.Shift_R:
+// case Gdk.Key.ISO_Level3_Shift:
+// // AltGr
+// return KeyActions.Process;
}
- if (keyChar == '\0')
+ if (descriptor.KeyChar == '\0')
return KeyActions.Process;
- if (keyChar == ' ' && (modifier & ModifierType.ShiftMask) == ModifierType.ShiftMask)
+ if (descriptor.KeyChar == ' ' && (descriptor.ModifierKeys & ModifierKeys.Shift) == ModifierKeys.Shift)
return KeyActions.CloseWindow | KeyActions.Process;
// special case end with punctuation like 'param:' -> don't input double punctuation, otherwise we would end up with 'param::'
- if (char.IsPunctuation (keyChar) && keyChar != '_') {
- if (keyChar == ':') {
+ if (char.IsPunctuation (descriptor.KeyChar) && descriptor.KeyChar != '_') {
+ if (descriptor.KeyChar == ':') {
foreach (var item in FilteredItems) {
- if (DataProvider.GetText (item).EndsWith (keyChar.ToString (), StringComparison.Ordinal)) {
+ if (DataProvider.GetText (item).EndsWith (descriptor.KeyChar.ToString (), StringComparison.Ordinal)) {
list.SelectedItem = item;
return KeyActions.Complete | KeyActions.CloseWindow | KeyActions.Ignore;
}
@@ -456,14 +473,12 @@ namespace MonoDevelop.Ide.CodeCompletion
var selectedItem = list.SelectedItem;
if (selectedItem < 0 || selectedItem >= DataProvider.ItemCount)
return KeyActions.CloseWindow;
- if (DataProvider.GetText (selectedItem).EndsWith (keyChar.ToString (), StringComparison.Ordinal)) {
+ if (DataProvider.GetText (selectedItem).EndsWith (descriptor.KeyChar.ToString (), StringComparison.Ordinal)) {
return KeyActions.Complete | KeyActions.CloseWindow | KeyActions.Ignore;
}
}
}
-
-
/* //don't input letters/punctuation etc when non-shift modifiers are active
bool nonShiftModifierActive = ((Gdk.ModifierType.ControlMask | Gdk.ModifierType.MetaMask
| Gdk.ModifierType.Mod1Mask | Gdk.ModifierType.SuperMask)
@@ -544,75 +559,69 @@ namespace MonoDevelop.Ide.CodeCompletion
{
// default - word with highest match rating in the list.
hasMismatches = true;
- if (partialWord == null)
- return -1;
-
int idx = -1;
- var matcher = CompletionMatcher.CreateCompletionMatcher (partialWord);
- string bestWord = null;
- int bestRank = int.MinValue;
- int bestIndex = 0;
+
+ StringMatcher matcher = null;
if (!string.IsNullOrEmpty (partialWord)) {
+ matcher = CompletionMatcher.CreateCompletionMatcher (partialWord);
+ string bestWord = null;
+ int bestRank = int.MinValue;
+ int bestIndex = 0;
+ int bestIndexPriority = int.MinValue;
for (int i = 0; i < list.filteredItems.Count; i++) {
- int index = list.filteredItems[i];
- string text = DataProvider.GetText (index);
+ int index = list.filteredItems [i];
+ var data = DataProvider.GetCompletionData (index);
+ if (bestIndexPriority > data.PriorityGroup)
+ continue;
+ string text = data.DisplayText;
int rank;
if (!matcher.CalcMatchRank (text, out rank))
continue;
- if (rank > bestRank) {
+ if (rank > bestRank || data.PriorityGroup > bestIndexPriority) {
bestWord = text;
bestRank = rank;
bestIndex = i;
+ bestIndexPriority = data.PriorityGroup;
}
}
+
+ if (bestWord != null) {
+ idx = bestIndex;
+ hasMismatches = false;
+ // exact match found.
+ if (string.Compare (bestWord, partialWord ?? "", true) == 0)
+ return idx;
+ }
}
- if (bestWord != null) {
- idx = bestIndex;
- hasMismatches = false;
- // exact match found.
- if (string.Compare (bestWord, partialWord ?? "", true) == 0)
- return idx;
+
+ CompletionData currentData;
+ int bestMruIndex;
+ if (idx >= 0) {
+ currentData = completionDataList [list.filteredItems [idx]];
+ bestMruIndex = cache.GetIndex (currentData);
+ } else {
+ bestMruIndex = int.MaxValue;
+ currentData = null;
}
-
- if (string.IsNullOrEmpty (partialWord) || partialWord.Length <= 2) {
- // Search for history matches.
- string historyWord;
- if (wordHistory.TryGetValue (partialWord, out historyWord)) {
- for (int xIndex = 0; xIndex < list.filteredItems.Count; xIndex++) {
- string currentWord = DataProvider.GetCompletionText (list.filteredItems[xIndex]);
- if (currentWord == historyWord) {
- idx = xIndex;
- break;
+
+ for (int i = 0; i < list.filteredItems.Count; i++) {
+ var mruData = completionDataList [list.filteredItems [i]];
+ int curMruIndex = cache.GetIndex (mruData);
+ if (curMruIndex == 1)
+ continue;
+ if (curMruIndex < bestMruIndex) {
+ int r1 = 0, r2 = 0;
+ if (currentData == null || matcher != null && matcher.CalcMatchRank (mruData.DisplayText, out r1) && matcher.CalcMatchRank (currentData.DisplayText, out r2)) {
+ if (r1 >= r2) {
+ bestMruIndex = curMruIndex;
+ idx = i;
+ currentData = mruData;
}
}
}
}
- return idx;
- }
- static Dictionary<string,string> wordHistory = new Dictionary<string,string> ();
- static List<string> partalWordHistory = new List<string> ();
- const int maxHistoryLength = 500;
- protected void AddWordToHistory (string partialWord, string word)
- {
- if (!wordHistory.ContainsKey (partialWord)) {
- wordHistory.Add (partialWord, word);
- partalWordHistory.Add (partialWord);
- while (partalWordHistory.Count > maxHistoryLength) {
- string first = partalWordHistory [0];
- partalWordHistory.RemoveAt (0);
- wordHistory.Remove (first);
- }
- } else {
- partalWordHistory.Remove (partialWord);
- partalWordHistory.Add (partialWord);
- wordHistory [partialWord] = word;
- }
- }
- public static void ClearHistory ()
- {
- wordHistory.Clear ();
- partalWordHistory.Clear ();
+ return idx;
}
void SelectEntry (int n)
@@ -698,6 +707,7 @@ namespace MonoDevelop.Ide.CodeCompletion
CompletionCategory GetCompletionCategory (int n);
bool HasMarkup (int n);
string GetCompletionText (int n);
+ CompletionData GetCompletionData (int n);
string GetDescription (int n, bool isSelected);
string GetRightSideDescription (int n, bool isSelected);
Xwt.Drawing.Image GetIcon (int n);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/MemberCompletionData.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/MemberCompletionData.cs
index f5c3cdc31e..1d33b4ee7b 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/MemberCompletionData.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/MemberCompletionData.cs
@@ -25,7 +25,6 @@
// THE SOFTWARE.
using System;
-using ICSharpCode.NRefactory.TypeSystem;
namespace MonoDevelop.Ide.CodeCompletion
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/MruCache.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/MruCache.cs
new file mode 100644
index 0000000000..90e679af3f
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/MruCache.cs
@@ -0,0 +1,67 @@
+//
+// MruCache.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 System.Collections.Generic;
+
+namespace MonoDevelop.Ide.CodeCompletion
+{
+ class MruCache
+ {
+ const int MaxItems = 42;
+
+ readonly List<string> lastItems = new List<string> (MaxItems);
+ readonly object mruLock = new object ();
+
+ public void CommitCompletionData (CompletionData item)
+ {
+ lock (mruLock) {
+ var removed = lastItems.Remove (item.DisplayText);
+ if (!removed && lastItems.Count == MaxItems)
+ lastItems.RemoveAt (0);
+
+ lastItems.Add (item.DisplayText);
+ }
+ }
+
+ /// <summary>
+ /// Lower is better. 1 == not in list.
+ /// </summary>
+ public int GetIndex (CompletionData item)
+ {
+ lock (mruLock) {
+ var index = lastItems.IndexOf (item.DisplayText);
+ return -index;
+ }
+ }
+
+ public void Clear ()
+ {
+ lock (mruLock) {
+ lastItems.Clear ();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/MutableCompletionDataList.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/MutableCompletionDataList.cs
index 871134a1c8..69488e2d04 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/MutableCompletionDataList.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/MutableCompletionDataList.cs
@@ -61,32 +61,24 @@ namespace MonoDevelop.Ide.CodeCompletion
public event EventHandler Changing {
add {
- if (changing == null)
- TypeSystemService.ParseOperationStarted += HandleParseOperationStarted;
changing += value;
}
remove {
changing -= value;
- if (changing == null)
- TypeSystemService.ParseOperationStarted -= HandleParseOperationStarted;
}
}
public event EventHandler Changed {
add {
- if (changed == null)
- TypeSystemService.ParseOperationFinished += HandleParseOperationFinished;
changed += value;
}
remove {
changed -= value;
- if (changed == null)
- TypeSystemService.ParseOperationFinished -= HandleParseOperationFinished;
}
}
public bool IsChanging {
- get { return TypeSystemService.IsParsing; }
+ get { return false; }
}
protected virtual void OnChanging ()
@@ -117,10 +109,6 @@ namespace MonoDevelop.Ide.CodeCompletion
{
if (!disposed) {
disposed = true;
- if (changing != null)
- TypeSystemService.ParseOperationStarted -= HandleParseOperationStarted;
- if (changed != null)
- TypeSystemService.ParseOperationFinished -= HandleParseOperationFinished;
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ParameterDataProvider.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ParameterHintingData.cs
index 3d1b0811b9..aa2077c177 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ParameterDataProvider.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ParameterHintingData.cs
@@ -25,54 +25,43 @@
// THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.Completion;
+using ICSharpCode.NRefactory6.CSharp.Completion;
+using Microsoft.CodeAnalysis;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Collections.Generic;
+using System.Threading;
+using MonoDevelop.Ide.TypeSystem;
+using MonoDevelop.Projects;
+using MonoDevelop.Ide.Editor;
namespace MonoDevelop.Ide.CodeCompletion
{
- public abstract class ParameterDataProvider : IParameterDataProvider
+ public abstract class ParameterHintingData
{
- public ParameterDataProvider (int startOffset)
- {
- this.startOffset = startOffset;
- }
-
- public virtual TooltipInformation CreateTooltipInformation (int overload, int currentParameter, bool smartWrap)
- {
- return new TooltipInformation ();
- }
-
- #region IParameterDataProvider implementation
-
- string IParameterDataProvider.GetHeading (int overload, string[] parameterDescription, int currentParameter)
- {
- throw new NotImplementedException ();
+ public ISymbol Symbol {
+ get;
+ private set;
}
- string IParameterDataProvider.GetDescription (int overload, int currentParameter)
+ protected ParameterHintingData (ISymbol symbol)
{
- throw new NotImplementedException ();
+ Symbol = symbol;
}
- string IParameterDataProvider.GetParameterDescription (int overload, int paramIndex)
- {
- throw new NotImplementedException ();
+ public abstract int ParameterCount {
+ get;
}
- public abstract int GetParameterCount (int overload);
- public abstract bool AllowParameterList (int overload);
- public abstract string GetParameterName (int overload, int paramIndex);
-
- public abstract int Count {
+ public abstract bool IsParameterListAllowed {
get;
}
- readonly int startOffset;
- public int StartOffset {
- get {
- return startOffset;
- }
- }
+ public abstract string GetParameterName (int parameter);
- #endregion
+ public virtual TooltipInformation CreateTooltipInformation (TextEditor editor, DocumentContext ctx, int currentParameter, bool smartWrap)
+ {
+ return new TooltipInformation ();
+ }
}
}
-
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ParameterHintingResult.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ParameterHintingResult.cs
new file mode 100644
index 0000000000..dba4aedf0c
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ParameterHintingResult.cs
@@ -0,0 +1,88 @@
+//
+// ParameterHintingResult.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 System.Collections.Generic;
+
+namespace MonoDevelop.Ide.CodeCompletion
+{
+ public class ParameterHintingResult : IReadOnlyList<ParameterHintingData>
+ {
+ public static readonly ParameterHintingResult Empty = new ParameterHintingResult (new List<ParameterHintingData> (), -1);
+
+ protected readonly List<ParameterHintingData> data;
+ /// <summary>
+ /// Gets the start offset of the parameter expression node.
+ /// </summary>
+ public int StartOffset {
+ get;
+ private set;
+ }
+
+ protected ParameterHintingResult (int startOffset)
+ {
+ this.data = new List<ParameterHintingData> ();
+ this.StartOffset = startOffset;
+ }
+
+ public ParameterHintingResult (List<ParameterHintingData> data, int startOffset)
+ {
+ this.data = data;
+ this.StartOffset = startOffset;
+ }
+
+ #region IEnumerable implementation
+ public IEnumerator<ParameterHintingData> GetEnumerator ()
+ {
+ return data.GetEnumerator ();
+ }
+ #endregion
+
+ #region IEnumerable implementation
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator ()
+ {
+ return data.GetEnumerator ();
+ }
+ #endregion
+
+ #region IReadOnlyList implementation
+ public ParameterHintingData this [int index] {
+ get {
+ return data [index];
+ }
+ }
+ #endregion
+
+ #region IReadOnlyCollection implementation
+ public int Count {
+ get {
+ return data.Count;
+ }
+ }
+ #endregion
+ }
+
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ParameterInformationWindow.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ParameterInformationWindow.cs
index 14c2042e07..40278f4734 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ParameterInformationWindow.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ParameterInformationWindow.cs
@@ -25,16 +25,15 @@
//
//
-
using System;
-using System.Text;
using MonoDevelop.Core;
using Gtk;
using MonoDevelop.Components;
-using ICSharpCode.NRefactory.Completion;
using MonoDevelop.Ide.Gui.Content;
-using System.Collections.Generic;
using MonoDevelop.Ide.Fonts;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Ide.Editor.Highlighting;
+using MonoDevelop.Ide.Editor.Extension;
namespace MonoDevelop.Ide.CodeCompletion
{
@@ -74,7 +73,7 @@ namespace MonoDevelop.Ide.CodeCompletion
this.AllowGrow = false;
this.CanFocus = false;
this.CanDefault = false;
- Mono.TextEditor.PopupWindow.WindowTransparencyDecorator.Attach (this);
+ WindowTransparencyDecorator.Attach (this);
headlabel = new MonoDevelop.Components.FixedWidthWrapLabel ();
headlabel.Indent = -20;
@@ -96,7 +95,7 @@ namespace MonoDevelop.Ide.CodeCompletion
vb2.Spacing = 4;
vb2.PackStart (hb, true, true, 0);
ContentBox.Add (vb2);
- var scheme = Mono.TextEditor.Highlighting.SyntaxModeService.GetColorStyle (IdeApp.Preferences.ColorScheme);
+ var scheme = SyntaxModeService.GetColorStyle (IdeApp.Preferences.ColorScheme);
Theme.SetSchemeColors (scheme);
foreColor = scheme.PlainText.Foreground;
@@ -107,22 +106,24 @@ namespace MonoDevelop.Ide.CodeCompletion
}
int lastParam = -2;
- public void ShowParameterInfo (ParameterDataProvider provider, int overload, int _currentParam, int maxSize)
+ TooltipInformation currentTooltipInformation;
+
+ public void ShowParameterInfo (ParameterHintingResult provider, int overload, int _currentParam, int maxSize)
{
if (provider == null)
throw new ArgumentNullException ("provider");
- int numParams = System.Math.Max (0, provider.GetParameterCount (overload));
+ int numParams = System.Math.Max (0, provider[overload].ParameterCount);
var currentParam = System.Math.Min (_currentParam, numParams - 1);
if (numParams > 0 && currentParam < 0)
currentParam = 0;
- if (lastParam == currentParam) {
+ if (lastParam == currentParam && (currentTooltipInformation != null)) {
return;
}
lastParam = currentParam;
ClearDescriptions ();
- var o = provider.CreateTooltipInformation (overload, currentParam, false);
-
+ var parameterHintingData = (ParameterHintingData)provider [overload];
+ currentTooltipInformation = parameterHintingData.CreateTooltipInformation (ext.Editor, ext.DocumentContext, currentParam, false);
Theme.NumPages = provider.Count;
Theme.CurrentPage = overload;
if (provider.Count > 1) {
@@ -130,17 +131,17 @@ namespace MonoDevelop.Ide.CodeCompletion
Theme.PagerVertical = true;
}
- headlabel.Markup = o.SignatureMarkup;
+ headlabel.Markup = currentTooltipInformation.SignatureMarkup;
headlabel.Visible = true;
if (Theme.DrawPager)
headlabel.WidthRequest = headlabel.RealWidth + 70;
- foreach (var cat in o.Categories) {
+ foreach (var cat in currentTooltipInformation.Categories) {
descriptionBox.PackStart (CreateCategory (cat.Item1, cat.Item2), true, true, 4);
}
- if (!string.IsNullOrEmpty (o.SummaryMarkup)) {
- descriptionBox.PackStart (CreateCategory (GettextCatalog.GetString ("Summary"), o.SummaryMarkup), true, true, 4);
+ if (!string.IsNullOrEmpty (currentTooltipInformation.SummaryMarkup)) {
+ descriptionBox.PackStart (CreateCategory (GettextCatalog.GetString ("Summary"), currentTooltipInformation.SummaryMarkup), true, true, 4);
}
descriptionBox.ShowAll ();
QueueResize ();
@@ -185,6 +186,7 @@ namespace MonoDevelop.Ide.CodeCompletion
public void ChangeOverload ()
{
lastParam = -2;
+ currentTooltipInformation = null;
}
public void HideParameterInfo ()
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ParameterInformationWindowManager.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ParameterInformationWindowManager.cs
index 64c53b4f5f..f3de5195a4 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ParameterInformationWindowManager.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/ParameterInformationWindowManager.cs
@@ -31,8 +31,8 @@ using System.Collections;
using System.Collections.Generic;
using Gtk;
using Gdk;
-using ICSharpCode.NRefactory.Completion;
using MonoDevelop.Ide.Gui.Content;
+using MonoDevelop.Ide.Editor.Extension;
namespace MonoDevelop.Ide.CodeCompletion
{
@@ -47,7 +47,8 @@ namespace MonoDevelop.Ide.CodeCompletion
static ParameterInformationWindowManager ()
{
- IdeApp.Workbench.RootWindow.Destroyed += (sender, e) => DestroyWindow ();
+ if (IdeApp.Workbench != null)
+ IdeApp.Workbench.RootWindow.Destroyed += (sender, e) => DestroyWindow ();
}
static void DestroyWindow ()
@@ -60,14 +61,14 @@ namespace MonoDevelop.Ide.CodeCompletion
// Called when a key is pressed in the editor.
// Returns false if the key press has to continue normal processing.
- public static bool ProcessKeyEvent (CompletionTextEditorExtension ext, ICompletionWidget widget, Gdk.Key key, Gdk.ModifierType modifier)
+ internal static bool ProcessKeyEvent (CompletionTextEditorExtension ext, ICompletionWidget widget, KeyDescriptor descriptor)
{
if (methods.Count == 0)
return false;
MethodData cmd = methods [methods.Count - 1];
-
- if (key == Gdk.Key.Down) {
+
+ if (descriptor.SpecialKey == SpecialKey.Down) {
if (cmd.MethodProvider.Count <= 1)
return false;
if (cmd.CurrentOverload < cmd.MethodProvider.Count - 1)
@@ -77,7 +78,7 @@ namespace MonoDevelop.Ide.CodeCompletion
window.ChangeOverload ();
UpdateWindow (ext, widget);
return true;
- } else if (key == Gdk.Key.Up) {
+ } else if (descriptor.SpecialKey == SpecialKey.Up) {
if (cmd.MethodProvider.Count <= 1)
return false;
if (cmd.CurrentOverload > 0)
@@ -88,18 +89,18 @@ namespace MonoDevelop.Ide.CodeCompletion
UpdateWindow (ext, widget);
return true;
}
- else if (key == Gdk.Key.Escape) {
+ else if (descriptor.SpecialKey == SpecialKey.Escape) {
HideWindow (ext, widget);
return true;
}
return false;
}
- public static void PostProcessKeyEvent (CompletionTextEditorExtension ext, ICompletionWidget widget, Gdk.Key key, Gdk.ModifierType modifier)
+ internal static void PostProcessKeyEvent (CompletionTextEditorExtension ext, ICompletionWidget widget, KeyDescriptor descriptor)
{
}
- public static void UpdateCursorPosition (CompletionTextEditorExtension ext, ICompletionWidget widget)
+ internal static void UpdateCursorPosition (CompletionTextEditorExtension ext, ICompletionWidget widget)
{
// Called after the key has been processed by the editor
if (methods.Count == 0)
@@ -124,12 +125,12 @@ namespace MonoDevelop.Ide.CodeCompletion
UpdateWindow (ext, widget);
}
- public static void RepositionWindow (CompletionTextEditorExtension ext, ICompletionWidget widget)
+ internal static void RepositionWindow (CompletionTextEditorExtension ext, ICompletionWidget widget)
{
UpdateWindow (ext, widget);
}
- public static void ShowWindow (CompletionTextEditorExtension ext, ICompletionWidget widget, CodeCompletionContext ctx, ParameterDataProvider provider)
+ internal static void ShowWindow (CompletionTextEditorExtension ext, ICompletionWidget widget, CodeCompletionContext ctx, ParameterHintingResult provider)
{
if (provider.Count == 0)
return;
@@ -147,7 +148,7 @@ namespace MonoDevelop.Ide.CodeCompletion
UpdateWindow (ext, widget);
}
- public static void HideWindow (CompletionTextEditorExtension ext, ICompletionWidget widget)
+ internal static void HideWindow (CompletionTextEditorExtension ext, ICompletionWidget widget)
{
methods.Clear ();
if (window != null)
@@ -162,7 +163,7 @@ namespace MonoDevelop.Ide.CodeCompletion
return methods [methods.Count - 1].CurrentOverload;
}
- public static IParameterDataProvider GetCurrentProvider ()
+ public static ParameterHintingResult GetCurrentProvider ()
{
if (methods.Count == 0)
return null;
@@ -284,7 +285,7 @@ namespace MonoDevelop.Ide.CodeCompletion
class MethodData
{
- public ParameterDataProvider MethodProvider;
+ public ParameterHintingResult MethodProvider;
public CodeCompletionContext CompletionContext;
int currentOverload;
public int CurrentOverload {
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/TooltipInformationWindow.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/TooltipInformationWindow.cs
index d9847fb2b9..528bb4a685 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/TooltipInformationWindow.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/TooltipInformationWindow.cs
@@ -30,7 +30,8 @@ using System.Collections.Generic;
using MonoDevelop.Core;
using MonoDevelop.Ide.Fonts;
using System.Linq;
-using Mono.TextEditor.PopupWindow;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Ide.Editor.Highlighting;
namespace MonoDevelop.Ide.CodeCompletion
{
@@ -225,7 +226,7 @@ namespace MonoDevelop.Ide.CodeCompletion
internal void SetDefaultScheme ()
{
- var scheme = Mono.TextEditor.Highlighting.SyntaxModeService.GetColorStyle (IdeApp.Preferences.ColorScheme);
+ var scheme = SyntaxModeService.GetColorStyle (IdeApp.Preferences.ColorScheme);
Theme.SetSchemeColors (scheme);
foreColor = scheme.PlainText.Foreground;
headLabel.ModifyFg (StateType.Normal, foreColor.ToGdkColor ());
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeFormatting/CodeFormatter.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeFormatting/CodeFormatter.cs
index 6160c8b056..450441cb1a 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeFormatting/CodeFormatter.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeFormatting/CodeFormatter.cs
@@ -26,12 +26,9 @@
using System;
using MonoDevelop.Projects.Policies;
-using Mono.TextEditor;
using System.Collections.Generic;
-using ICSharpCode.NRefactory;
-using ICSharpCode.NRefactory.TypeSystem;
-using ICSharpCode.NRefactory.Semantics;
using MonoDevelop.Core;
+using MonoDevelop.Ide.Editor;
namespace MonoDevelop.Ide.CodeFormatting
{
@@ -96,16 +93,24 @@ namespace MonoDevelop.Ide.CodeFormatting
/// <summary>
/// Formats a text document directly with insert/remove operations.
/// </summary>
- public void OnTheFlyFormat (MonoDevelop.Ide.Gui.Document doc, int startOffset, int endOffset)
+ public void OnTheFlyFormat (TextEditor editor, DocumentContext documentContext, int startOffset, int endOffset)
{
var adv = formatter as IAdvancedCodeFormatter;
if (adv == null || !adv.SupportsOnTheFlyFormatting)
throw new InvalidOperationException ("On the fly formatting not supported");
- adv.OnTheFlyFormat (doc, startOffset, endOffset);
+ adv.OnTheFlyFormat (editor, documentContext, startOffset, endOffset);
}
-
- public void CorrectIndenting (PolicyContainer policyParent, TextEditorData data, int line)
+
+ /// <summary>
+ /// Formats a text document directly with insert/remove operations.
+ /// </summary>
+ public void OnTheFlyFormat (MonoDevelop.Ide.Gui.Document doc, int startOffset, int endOffset)
+ {
+ OnTheFlyFormat (doc.Editor, doc, startOffset, endOffset);
+ }
+
+ public void CorrectIndenting (PolicyContainer policyParent, TextEditor data, int line)
{
var adv = formatter as IAdvancedCodeFormatter;
if (adv == null || !adv.SupportsCorrectingIndent)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeFormatting/CodeFormatterService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeFormatting/CodeFormatterService.cs
index 834881f688..aa483788ef 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeFormatting/CodeFormatterService.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeFormatting/CodeFormatterService.cs
@@ -29,6 +29,8 @@ using System.Linq;
using System.Collections.Generic;
using Mono.Addins;
using MonoDevelop.Projects.Policies;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Core.Text;
namespace MonoDevelop.Ide.CodeFormatting
{
@@ -68,5 +70,23 @@ namespace MonoDevelop.Ide.CodeFormatting
return null;
}
+
+ public static void Format (TextEditor editor, DocumentContext ctx, ISegment segment)
+ {
+ if (editor == null)
+ throw new ArgumentNullException ("editor");
+ if (ctx == null)
+ throw new ArgumentNullException ("ctx");
+ if (segment == null)
+ throw new ArgumentNullException ("segment");
+ var fmt = GetFormatter (editor.MimeType);
+ if (fmt == null)
+ return;
+ if (fmt.SupportsOnTheFlyFormatting) {
+ fmt.OnTheFlyFormat (editor, ctx, segment.Offset, segment.EndOffset);
+ return;
+ }
+ editor.Text = fmt.FormatText (ctx.HasProject ? ctx.Project.Policies : null, editor.Text, segment.Offset, segment.EndOffset);
+ }
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeFormatting/CodeFormattingCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeFormatting/CodeFormattingCommands.cs
index 4ff1fd707a..507f74250a 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeFormatting/CodeFormattingCommands.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeFormatting/CodeFormattingCommands.cs
@@ -28,7 +28,7 @@ using System;
using MonoDevelop.Components.Commands;
using MonoDevelop.Ide.Gui;
using MonoDevelop.Core;
-using Mono.TextEditor;
+using MonoDevelop.Core.Text;
namespace MonoDevelop.Ide.CodeFormatting
{
@@ -66,7 +66,7 @@ namespace MonoDevelop.Ide.CodeFormatting
if (formatter.SupportsOnTheFlyFormatting) {
using (var undo = doc.Editor.OpenUndoGroup ()) {
- formatter.OnTheFlyFormat (doc, 0, doc.Editor.Length);
+ formatter.OnTheFlyFormat (doc.Editor, doc, 0, doc.Editor.Length);
}
} else {
var text = doc.Editor.Text;
@@ -74,9 +74,8 @@ namespace MonoDevelop.Ide.CodeFormatting
if (formattedText == null || formattedText == text)
return;
- doc.Editor.Replace (0, text.Length, formattedText);
+ doc.Editor.ReplaceText (0, text.Length, formattedText);
}
- doc.Editor.Document.CommitUpdateAll ();
}
}
@@ -96,26 +95,26 @@ namespace MonoDevelop.Ide.CodeFormatting
if (formatter == null)
return;
- TextSegment selection;
+ ISegment selection;
var editor = doc.Editor;
if (editor.IsSomethingSelected) {
selection = editor.SelectionRange;
} else {
- selection = editor.GetLine (editor.Caret.Line).Segment;
+ selection = editor.GetLine (editor.CaretLocation.Line);
}
using (var undo = editor.OpenUndoGroup ()) {
var version = editor.Version;
if (formatter.SupportsOnTheFlyFormatting) {
- formatter.OnTheFlyFormat (doc, selection.Offset, selection.EndOffset);
+ formatter.OnTheFlyFormat (doc.Editor, doc, selection.Offset, selection.EndOffset);
} else {
var pol = doc.Project != null ? doc.Project.Policies : null;
try {
var editorText = editor.Text;
string text = formatter.FormatText (pol, editorText, selection.Offset, selection.EndOffset);
if (text != null && editorText.Substring (selection.Offset, selection.Length) != text) {
- editor.Replace (selection.Offset, selection.Length, text);
+ editor.ReplaceText (selection.Offset, selection.Length, text);
}
} catch (Exception e) {
LoggingService.LogError ("Error during format.", e);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeFormatting/IAdvancedCodeFormatter.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeFormatting/IAdvancedCodeFormatter.cs
index 3b5e4321af..42e9cebec8 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeFormatting/IAdvancedCodeFormatter.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeFormatting/IAdvancedCodeFormatter.cs
@@ -26,11 +26,9 @@
using System;
using System.Collections.Generic;
-using Mono.TextEditor;
using MonoDevelop.Projects.Policies;
-using ICSharpCode.NRefactory;
-using ICSharpCode.NRefactory.TypeSystem;
-using ICSharpCode.NRefactory.Semantics;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Ide.Gui;
namespace MonoDevelop.Ide.CodeFormatting
{
@@ -39,10 +37,21 @@ namespace MonoDevelop.Ide.CodeFormatting
bool SupportsOnTheFlyFormatting { get; }
bool SupportsCorrectingIndent { get; }
- void CorrectIndenting (PolicyContainer policyParent, IEnumerable<string> mimeTypeChain, TextEditorData textEditorData, int line);
-
- void OnTheFlyFormat (MonoDevelop.Ide.Gui.Document doc, int startOffset, int endOffset);
+ void CorrectIndenting (PolicyContainer policyParent, IEnumerable<string> mimeTypeChain, TextEditor textEditorData, int line);
+ void OnTheFlyFormat (TextEditor editor, DocumentContext context, int startOffset, int endOffset);
+ }
+
+ public static class AdvancedCodeFormatterExtensions
+ {
+ public static void OnTheFlyFormat (this IAdvancedCodeFormatter formatter, Document document, int startOffset, int endOffset)
+ {
+ if (formatter == null)
+ throw new ArgumentNullException ("formatter");
+ formatter.OnTheFlyFormat (document.Editor, document, startOffset, endOffset);
+ }
+
+
}
public abstract class AbstractAdvancedFormatter : AbstractCodeFormatter, IAdvancedCodeFormatter
@@ -50,13 +59,18 @@ namespace MonoDevelop.Ide.CodeFormatting
public virtual bool SupportsOnTheFlyFormatting { get { return false; } }
public virtual bool SupportsCorrectingIndent { get { return false; } }
- public virtual void OnTheFlyFormat (MonoDevelop.Ide.Gui.Document doc, int startOffset, int endOffset)
+ public virtual void OnTheFlyFormat (TextEditor editor, DocumentContext context, int startOffset, int endOffset)
{
throw new NotSupportedException ();
}
-
+
+ public void OnTheFlyFormat (Document doc, int startOffset, int endOffset)
+ {
+ OnTheFlyFormat (doc.Editor, doc, startOffset, endOffset);
+ }
+
public virtual void CorrectIndenting (PolicyContainer policyParent, IEnumerable<string> mimeTypeChain,
- TextEditorData data, int line)
+ TextEditor data, int line)
{
throw new NotSupportedException ();
}
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..726c3ae0d3 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplate.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplate.cs
@@ -33,9 +33,11 @@ using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using MonoDevelop.Core;
-using Mono.TextEditor;
-using Mono.TextEditor.PopupWindow;
using MonoDevelop.Ide.CodeFormatting;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Core.Text;
+using System.Linq;
+using MonoDevelop.Ide.Gui;
namespace MonoDevelop.Ide.CodeTemplates
{
@@ -134,34 +136,34 @@ namespace MonoDevelop.Ide.CodeTemplates
return string.Format("[CodeTemplate: Group={0}, Shortcut={1}, CodeTemplateType={2}, MimeType={3}, Description={4}, Code={5}]", Group, Shortcut, CodeTemplateType, MimeType, Description, Code);
}
- static int FindPrevWordStart (TextEditorData editor, int offset)
+ static int FindPrevWordStart (TextEditor editor, int offset)
{
while (--offset >= 0 && !Char.IsWhiteSpace (editor.GetCharAt (offset)))
;
return ++offset;
}
- public static string GetWordBeforeCaret (TextEditorData editor)
+ public static string GetWordBeforeCaret (TextEditor editor)
{
- int offset = editor.Caret.Offset;
+ int offset = editor.CaretOffset;
int start = FindPrevWordStart (editor, offset);
return editor.GetTextBetween (start, offset);
}
- static int DeleteWordBeforeCaret (TextEditorData editor)
+ static int DeleteWordBeforeCaret (TextEditor editor)
{
- int offset = editor.Caret.Offset;
+ int offset = editor.CaretOffset;
int start = FindPrevWordStart (editor, offset);
- editor.Remove (start, offset - start);
+ editor.RemoveText (start, offset - start);
return start;
}
- static Regex variableRegEx = new Regex ("\\$([^$]*)\\$", RegexOptions.Compiled);
+ static System.Text.RegularExpressions.Regex variableRegEx = new System.Text.RegularExpressions.Regex ("\\$([^$]*)\\$", RegexOptions.Compiled);
public List<string> ParseVariables (string code)
{
var result = new List<string> ();
- foreach (Match match in variableRegEx.Matches (code)) {
+ foreach (System.Text.RegularExpressions.Match match in variableRegEx.Matches (code)) {
string name = match.Groups[1].Value;
if (name == "end" || name == "selected" || string.IsNullOrEmpty (name) || name.Trim ().Length == 0)
continue;
@@ -211,9 +213,9 @@ namespace MonoDevelop.Ide.CodeTemplates
var result = new TemplateResult ();
var sb = new StringBuilder ();
int lastOffset = 0;
- string code = context.Document.Editor.FormatString (context.InsertPosition, context.TemplateCode);
+ string code = context.Editor.FormatString (context.InsertPosition, context.TemplateCode);
result.TextLinks = new List<TextLink> ();
- foreach (Match match in variableRegEx.Matches (code)) {
+ foreach (System.Text.RegularExpressions.Match match in variableRegEx.Matches (code)) {
string name = match.Groups [1].Value;
sb.Append (code.Substring (lastOffset, match.Index - lastOffset));
lastOffset = match.Index + match.Length;
@@ -230,7 +232,7 @@ namespace MonoDevelop.Ide.CodeTemplates
}
if (!variableDecarations.ContainsKey (name))
continue;
- TextLink link = result.TextLinks.Find (l => l.Name == name);
+ var link = result.TextLinks.Find (l => l.Name == name);
bool isNew = link == null;
if (isNew) {
link = new TextLink (name);
@@ -271,13 +273,13 @@ namespace MonoDevelop.Ide.CodeTemplates
sb.Append (code.Substring (lastOffset, code.Length - lastOffset));
// format & indent template code
- var data = new TextEditorData ();
+ var data = TextEditorFactory.CreateNewDocument ();
data.Text = sb.ToString ();
- data.Document.TextReplaced += delegate(object sender, DocumentChangeEventArgs e) {
- int delta = e.ChangeDelta;
+ data.TextChanged += delegate(object sender, MonoDevelop.Core.Text.TextChangeEventArgs e) {
+ int delta = e.InsertionLength - e.RemovalLength;
foreach (var link in result.TextLinks) {
- link.Links = new List<TextSegment> (link.Links.AdjustSegments (e));
+ link.Links = link.Links.AdjustSegments (e).ToList ();
}
if (result.CaretEndOffset > e.Offset)
result.CaretEndOffset += delta;
@@ -285,7 +287,6 @@ namespace MonoDevelop.Ide.CodeTemplates
IndentCode (data, context.LineIndent);
result.Code = data.Text;
- data.Dispose ();
return result;
}
@@ -319,12 +320,12 @@ namespace MonoDevelop.Ide.CodeTemplates
return result.ToString ();
}
- static void IndentCode (TextEditorData data, string lineIndent)
+ static void IndentCode (ITextDocument data, string lineIndent)
{
for (int i = 1; i < data.LineCount; i++) {
var line = data.GetLine (i + 1);
if (line.Length > 0)
- data.Insert (line.Offset, lineIndent);
+ data.InsertText (line.Offset, lineIndent);
}
}
@@ -345,10 +346,10 @@ namespace MonoDevelop.Ide.CodeTemplates
string RemoveIndent (string text, string indent)
{
- var doc = new TextDocument ();
+ var doc = TextEditorFactory.CreateNewDocument ();
doc.Text = text;
var result = new StringBuilder ();
- foreach (DocumentLine line in doc.Lines) {
+ foreach (var line in doc.GetLines ()) {
string curLineIndent = line.GetIndentation (doc);
int offset = Math.Min (curLineIndent.Length, indent.Length);
result.Append (doc.GetTextBetween (line.Offset + offset, line.EndOffsetIncludingDelimiter));
@@ -358,58 +359,64 @@ namespace MonoDevelop.Ide.CodeTemplates
string Reindent (string text, string indent)
{
- var doc = new TextDocument ();
+ var doc = TextEditorFactory.CreateNewDocument ();
doc.Text = text;
var result = new StringBuilder ();
- foreach (DocumentLine line in doc.Lines) {
+ foreach (var line in doc.GetLines ()) {
if (result.Length > 0)
result.Append (indent);
result.Append (doc.GetTextAt (line.SegmentIncludingDelimiter));
}
return result.ToString ();
}
-
+
public void Insert (MonoDevelop.Ide.Gui.Document document)
{
- var handler = document.GetContent<ICodeTemplateHandler> ();
+ Insert (document.Editor, document);
+ }
+
+ public void Insert (TextEditor editor, DocumentContext context)
+ {
+ var handler = context.GetContent<ICodeTemplateHandler> ();
if (handler != null) {
- handler.InsertTemplate (this, document);
+ handler.InsertTemplate (this, editor, context);
} else {
- InsertTemplateContents (document);
+ InsertTemplateContents (editor, context);
}
}
/// <summary>
/// Don't use this unless you're implementing ICodeTemplateWidget. Use Insert instead.
/// </summary>
- public TemplateResult InsertTemplateContents (MonoDevelop.Ide.Gui.Document document)
+ public TemplateResult InsertTemplateContents (TextEditor editor, DocumentContext context)
{
- Mono.TextEditor.TextEditorData data = document.Editor;
+ var data = editor;
- int offset = data.Caret.Offset;
+ int offset = data.CaretOffset;
// string leadingWhiteSpace = GetLeadingWhiteSpace (editor, editor.CursorLine);
- var context = new TemplateContext {
+ var templateCtx = new TemplateContext {
Template = this,
- Document = document,
- ParsedDocument = document.ParsedDocument != null ? document.ParsedDocument.ParsedFile : null,
- InsertPosition = data.Caret.Location,
- LineIndent = data.Document.GetLineIndent (data.Caret.Line),
+ DocumentContext = context,
+ Editor = editor,
+ //ParsedDocument = context.ParsedDocument != null ? context.ParsedDocument.ParsedFile : null,
+ InsertPosition = data.CaretLocation,
+ LineIndent = data.GetLineIndent (data.CaretLocation.Line),
TemplateCode = Code
};
if (data.IsSomethingSelected) {
int start = data.SelectionRange.Offset;
- while (Char.IsWhiteSpace (data.Document.GetCharAt (start))) {
+ while (Char.IsWhiteSpace (data.GetCharAt (start))) {
start++;
}
int end = data.SelectionRange.EndOffset;
- while (Char.IsWhiteSpace (data.Document.GetCharAt (end - 1))) {
+ while (Char.IsWhiteSpace (data.GetCharAt (end - 1))) {
end--;
}
- context.LineIndent = data.Document.GetLineIndent (data.Document.OffsetToLineNumber (start));
- context.SelectedText = RemoveIndent (data.Document.GetTextBetween (start, end), context.LineIndent);
- data.Remove (start, end - start);
+ templateCtx.LineIndent = data.GetLineIndent (data.OffsetToLineNumber (start));
+ templateCtx.SelectedText = RemoveIndent (data.GetTextBetween (start, end), templateCtx.LineIndent);
+ data.RemoveText (start, end - start);
offset = start;
} else {
string word = GetWordBeforeCaret (data).Trim ();
@@ -417,9 +424,9 @@ namespace MonoDevelop.Ide.CodeTemplates
offset = DeleteWordBeforeCaret (data);
}
- TemplateResult template = FillVariables (context);
+ TemplateResult template = FillVariables (templateCtx);
template.InsertPosition = offset;
- document.Editor.Insert (offset, template.Code);
+ editor.InsertText (offset, template.Code);
int newoffset;
if (template.CaretEndOffset >= 0) {
@@ -428,13 +435,13 @@ namespace MonoDevelop.Ide.CodeTemplates
newoffset = offset + template.Code.Length;
}
- document.Editor.Caret.Location = document.Editor.OffsetToLocation (newoffset) ;
+ editor.CaretLocation = editor.OffsetToLocation (newoffset) ;
var prettyPrinter = CodeFormatterService.GetFormatter (data.MimeType);
if (prettyPrinter != null) {
int endOffset = template.InsertPosition + template.Code.Length;
var oldVersion = data.Version;
- prettyPrinter.OnTheFlyFormat (document, template.InsertPosition, endOffset);
+ prettyPrinter.OnTheFlyFormat (editor, context, template.InsertPosition, endOffset);
foreach (var textLink in template.TextLinks) {
for (int i = 0; i < textLink.Links.Count; i++) {
var segment = textLink.Links [i];
@@ -446,6 +453,12 @@ namespace MonoDevelop.Ide.CodeTemplates
return template;
}
+ public TemplateResult InsertTemplateContents (Document document)
+ {
+ if (document == null)
+ throw new ArgumentNullException ("document");
+ return InsertTemplateContents (document.Editor, document);
+ }
#region I/O
public const string Node = "CodeTemplate";
const string HeaderNode = "Header";
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplateCompletionData.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplateCompletionData.cs
index 3f19b81ce7..6edaa60d6e 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplateCompletionData.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplateCompletionData.cs
@@ -28,20 +28,22 @@ using System;
using MonoDevelop.Ide.Gui;
using MonoDevelop.Ide.CodeCompletion;
using MonoDevelop.Core;
+using MonoDevelop.Ide.Editor.Extension;
+using MonoDevelop.Ide.Editor;
namespace MonoDevelop.Ide.CodeTemplates
{
public interface ICodeTemplateHandler
{
- void InsertTemplate (CodeTemplate template, Document document);
+ void InsertTemplate (CodeTemplate template, TextEditor editor, DocumentContext context);
}
public class CodeTemplateCompletionData : CompletionData
{
- Document doc;
- CodeTemplate template;
+ readonly TextEditorExtension doc;
+ readonly CodeTemplate template;
- public CodeTemplateCompletionData (Document doc, CodeTemplate template)
+ public CodeTemplateCompletionData (TextEditorExtension doc, CodeTemplate template)
{
this.doc = doc;
this.template = template;
@@ -51,9 +53,9 @@ namespace MonoDevelop.Ide.CodeTemplates
this.Description = template.Shortcut + Environment.NewLine + GettextCatalog.GetString (template.Description);
}
- public override void InsertCompletionText (CompletionListWindow window, ref KeyActions ka, Gdk.Key closeChar, char keyChar, Gdk.ModifierType modifier)
+ public override void InsertCompletionText (CompletionListWindow window, ref KeyActions ka, KeyDescriptor descriptor)
{
- template.Insert (doc);
+ template.Insert (doc.Editor, doc.DocumentContext);
}
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplateListDataProvider.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplateListDataProvider.cs
index 1487ce6806..30a94e91ef 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplateListDataProvider.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplateListDataProvider.cs
@@ -24,9 +24,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-using System;
using System.Collections.Generic;
-using Mono.TextEditor.PopupWindow;
namespace MonoDevelop.Ide.CodeTemplates
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplatePanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplatePanel.cs
index f259dfdf67..a454de6047 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplatePanel.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplatePanel.cs
@@ -31,6 +31,7 @@ using Gtk;
using MonoDevelop.Core;
using MonoDevelop.Ide.Gui.Dialogs;
using MonoDevelop.Components;
+using MonoDevelop.Ide.Editor;
namespace MonoDevelop.Ide.CodeTemplates
{
@@ -41,14 +42,15 @@ namespace MonoDevelop.Ide.CodeTemplates
Gtk.TreeStore templateStore;
CellRendererText templateCellRenderer;
CellRendererImage pixbufCellRenderer;
- Mono.TextEditor.TextEditor textEditor = new Mono.TextEditor.TextEditor ();
- Mono.TextEditor.TextEditorOptions options;
+ TextEditor textEditor = TextEditorFactory.CreateNewEditor ();
+ ITextEditorOptions options;
public CodeTemplatePanelWidget (OptionsDialog parent)
{
this.Build();
- scrolledwindow1.Add (textEditor);
- textEditor.ShowAll ();
+ Gtk.Widget control = textEditor;
+ scrolledwindow1.Add (control);
+ control.ShowAll ();
templateStore = new TreeStore (typeof (CodeTemplate), typeof (string), typeof (string));
@@ -73,13 +75,9 @@ namespace MonoDevelop.Ide.CodeTemplates
treeviewCodeTemplates.ExpandAll ();
treeviewCodeTemplates.Selection.Changed += HandleChanged;
-
- options = new MonoDevelop.Ide.Gui.CommonTextEditorOptions ();
- options.ShowLineNumberMargin = false;
- options.ShowFoldMargin = false;
- options.ShowIconMargin = false;
- textEditor.Options = options;
- textEditor.Document.ReadOnly = true;
+
+ textEditor.Options = DefaultSourceEditorOptions.PlainEditor;
+ textEditor.IsReadOnly = true;
this.buttonAdd.Clicked += ButtonAddClicked;
this.buttonEdit.Clicked += ButtonEditClicked;
this.buttonRemove.Clicked += ButtonRemoveClicked;
@@ -188,10 +186,10 @@ namespace MonoDevelop.Ide.CodeTemplates
CodeTemplate template = templateStore.GetValue (iter, 0) as CodeTemplate;
if (template != null) {
textEditor.ClearSelection ();
- textEditor.Document.MimeType = template.MimeType;
- textEditor.Document.Text = template.Code;
+ textEditor.MimeType = template.MimeType;
+ textEditor.Text = template.Code;
} else {
- textEditor.Document.Text = "";
+ textEditor.Text = "";
}
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/EditTemplateDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/EditTemplateDialog.cs
index f81346e749..eedfa7e058 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/EditTemplateDialog.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/EditTemplateDialog.cs
@@ -32,6 +32,8 @@ using Gtk;
using MonoDevelop.Core;
using Gdk;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Core.Text;
namespace MonoDevelop.Ide.CodeTemplates
@@ -41,8 +43,8 @@ namespace MonoDevelop.Ide.CodeTemplates
public partial class EditTemplateDialog : Gtk.Dialog
{
CodeTemplate template;
- Mono.TextEditor.TextEditor textEditor = new Mono.TextEditor.TextEditor ();
- Mono.TextEditor.TextEditorOptions options;
+ TextEditor textEditor = TextEditorFactory.CreateNewEditor ();
+ ITextEditorOptions options;
ListStore variablesListStore;
List<CodeTemplateVariable> variables = new List<CodeTemplateVariable> ();
@@ -59,24 +61,20 @@ namespace MonoDevelop.Ide.CodeTemplates
this.comboboxentryGroups.Entry.Text = template.Group ?? "";
this.comboboxentryMime.Entry.Text = template.MimeType ?? "";
this.entryDescription.Text = template.Description ?? "";
- this.textEditor.Document.MimeType = template.MimeType;
- this.textEditor.Document.Text = template.Code;
+ this.textEditor.MimeType = template.MimeType;
+ this.textEditor.Text = template.Code;
checkbuttonExpansion.Active = (template.CodeTemplateType & CodeTemplateType.Expansion) == CodeTemplateType.Expansion;
checkbuttonSurroundWith.Active = (template.CodeTemplateType & CodeTemplateType.SurroundsWith) == CodeTemplateType.SurroundsWith;
- scrolledwindow1.Child = textEditor;
- textEditor.ShowAll ();
- textEditor.Caret.PositionChanged += CaretPositionChanged;
- options = new Mono.TextEditor.TextEditorOptions ();
- options.ShowLineNumberMargin = false;
- options.ShowFoldMargin = false;
- options.ShowIconMargin = false;
- options.ColorScheme = IdeApp.Preferences.ColorScheme;
- textEditor.Options = options;
-
- HashSet<string> mimeTypes = new HashSet<string> ();
- HashSet<string> groups = new HashSet<string> ();
+ Gtk.Widget control = textEditor;
+ scrolledwindow1.Child = control;
+ control.ShowAll ();
+ textEditor.CaretPositionChanged += CaretPositionChanged;
+ textEditor.Options = DefaultSourceEditorOptions.PlainEditor;
+
+ var mimeTypes = new HashSet<string> ();
+ var groups = new HashSet<string> ();
foreach (CodeTemplate ct in CodeTemplateService.Templates) {
mimeTypes.Add (ct.MimeType);
groups.Add (ct.Group);
@@ -89,7 +87,7 @@ namespace MonoDevelop.Ide.CodeTemplates
foreach (string group in groups) {
comboboxentryGroups.AppendText (group);
}
- textEditor.Document.TextReplaced += DocumentTextReplaced;
+ textEditor.TextChanged += DocumentTextReplaced;
this.buttonOk.Clicked += ButtonOkClicked;
checkbuttonWhiteSpaces.Hide ();
@@ -140,7 +138,7 @@ namespace MonoDevelop.Ide.CodeTemplates
template.Group = this.comboboxentryGroups.Entry.Text;
template.MimeType = this.comboboxentryMime.Entry.Text;
template.Description = this.entryDescription.Text;
- template.Code = this.textEditor.Document.Text;
+ template.Code = this.textEditor.Text;
variables.ForEach (v => template.AddVariable (v));
template.CodeTemplateType = CodeTemplateType.Unknown;
if (checkbuttonExpansion.Active)
@@ -149,9 +147,9 @@ namespace MonoDevelop.Ide.CodeTemplates
template.CodeTemplateType |= CodeTemplateType.SurroundsWith;
}
- void DocumentTextReplaced (object sender, Mono.TextEditor.DocumentChangeEventArgs e)
+ void DocumentTextReplaced (object sender, TextChangeEventArgs e)
{
- List<string> vars = template.ParseVariables (textEditor.Document.Text);
+ List<string> vars = template.ParseVariables (textEditor.Text);
foreach (string var in vars) {
if (!variables.Any (v => v.Name == var) && !template.Variables.Any (v => v.Name == var)) {
variables.Add (new CodeTemplateVariable (var) {
@@ -170,13 +168,13 @@ namespace MonoDevelop.Ide.CodeTemplates
}
- void CaretPositionChanged (object sender, Mono.TextEditor.DocumentLocationEventArgs e)
+ void CaretPositionChanged (object sender, EventArgs e)
{
comboboxVariables.Active = -1;
- int offset = textEditor.Caret.Offset;
+ int offset = textEditor.CaretOffset;
int start = offset;
- while (start >= 0 && start < textEditor.Document.TextLength) { // caret offset may be behind the text
- char ch = textEditor.Document.GetCharAt (start);
+ while (start >= 0 && start < textEditor.Length) { // caret offset may be behind the text
+ char ch = textEditor.GetCharAt (start);
if (ch == '$')
break;
if (!char.IsLetterOrDigit (ch) && ch != '_')
@@ -185,16 +183,16 @@ namespace MonoDevelop.Ide.CodeTemplates
}
int end = offset;
- while (end < textEditor.Document.TextLength) {
- char ch = textEditor.Document.GetCharAt (end);
+ while (end < textEditor.Length) {
+ char ch = textEditor.GetCharAt (end);
if (ch == '$')
break;
if (!char.IsLetterOrDigit (ch) && ch != '_')
return;
end++;
}
- if (start >= 0 && end < textEditor.Document.TextLength) {
- string varName = textEditor.Document.GetTextBetween (start, end).Trim ('$');
+ if (start >= 0 && end < textEditor.Length) {
+ string varName = textEditor.GetTextBetween (start, end).Trim ('$');
TreeIter iter;
if (variablesListStore.GetIterFirst (out iter)) {
int i = -1;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/ExpansionObject.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/ExpansionObject.cs
index 721f645107..9e3fba71fe 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/ExpansionObject.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/ExpansionObject.cs
@@ -26,17 +26,19 @@
using System;
using System.Collections.Generic;
-using System.Text;
using System.Text.RegularExpressions;
using MonoDevelop.Ide.Gui.Content;
-using Mono.TextEditor.PopupWindow;
-using Mono.TextEditor;
-using ICSharpCode.NRefactory.TypeSystem;
using MonoDevelop.Ide.TypeSystem;
-using ICSharpCode.NRefactory.Completion;
using MonoDevelop.Ide.CodeCompletion;
-using ICSharpCode.NRefactory.TypeSystem.Implementation;
+using MonoDevelop.Ide.Tasks;
+using Microsoft.CodeAnalysis;
+using System.Threading.Tasks;
+using System.Linq;
+using ICSharpCode.NRefactory6.CSharp;
+using ICSharpCode.NRefactory6.CSharp.Completion;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Ide.Editor.Extension;
namespace MonoDevelop.Ide.CodeTemplates
{
@@ -47,17 +49,15 @@ namespace MonoDevelop.Ide.CodeTemplates
set;
}
- public ICompilation Compilation {
+ public SemanticModel Compilation {
get {
- return Document.Compilation;
+ var analysisDocument = DocumentContext.ParsedDocument;
+ if (analysisDocument == null)
+ return null;
+ return analysisDocument.GetAst<SemanticModel> ();
}
}
-
- public IUnresolvedFile ParsedDocument {
- get;
- set;
- }
-
+
public DocumentLocation InsertPosition {
get;
set;
@@ -78,7 +78,12 @@ namespace MonoDevelop.Ide.CodeTemplates
set;
}
- public MonoDevelop.Ide.Gui.Document Document {
+ public DocumentContext DocumentContext {
+ get;
+ set;
+ }
+
+ public TextEditor Editor {
get;
set;
}
@@ -93,36 +98,28 @@ namespace MonoDevelop.Ide.CodeTemplates
public string GetCurrentClassName ()
{
- if (CurrentContext.ParsedDocument == null)
- return null;
- IUnresolvedTypeDefinition type = null;
- var provider = CurrentContext.Document.GetContent<ITextEditorMemberPositionProvider>();
- if (provider == null) {
- type = CurrentContext.ParsedDocument.GetInnermostTypeDefinition (CurrentContext.InsertPosition.Line, CurrentContext.InsertPosition.Column);
- } else {
- type = provider.GetTypeAt (CurrentContext.Document.Editor.LocationToOffset (CurrentContext.InsertPosition));
- }
-
- if (type == null)
+ var compilation = CurrentContext.Compilation;
+ if (compilation == null)
return null;
- return type.Name;
+ var enclosingSymbol = compilation.GetEnclosingSymbol (CurrentContext.Editor.CaretOffset);
+
+ if (!(enclosingSymbol is ITypeSymbol))
+ enclosingSymbol = enclosingSymbol.ContainingType;
+
+ return enclosingSymbol != null ? enclosingSymbol.Name : null;
}
public string GetConstructorModifier ()
{
- if (CurrentContext.ParsedDocument == null)
+ var compilation = CurrentContext.Compilation;
+ if (compilation == null)
return null;
- IUnresolvedTypeDefinition type = null;
- var provider = CurrentContext.Document.GetContent<ITextEditorMemberPositionProvider>();
- if (provider == null) {
- type = CurrentContext.ParsedDocument.GetInnermostTypeDefinition (CurrentContext.InsertPosition.Line, CurrentContext.InsertPosition.Column);
- } else {
- type = provider.GetTypeAt (CurrentContext.Document.Editor.LocationToOffset (CurrentContext.InsertPosition));
- }
-
- if (type == null)
- return "";
- return type.IsStatic ? "static " : "public ";
+ var enclosingSymbol = compilation.GetEnclosingSymbol (CurrentContext.Editor.CaretOffset);
+
+ if (!(enclosingSymbol is ITypeSymbol))
+ enclosingSymbol = enclosingSymbol.ContainingType;
+
+ return enclosingSymbol != null && enclosingSymbol.IsStatic ? "static " : "public ";
}
public string GetLengthProperty (Func<string, string> callback, string varName)
@@ -132,29 +129,27 @@ namespace MonoDevelop.Ide.CodeTemplates
string var = callback (varName);
- ITextEditorResolver textEditorResolver = CurrentContext.Document.GetContent <ITextEditorResolver> ();
+ ITextEditorResolver textEditorResolver = CurrentContext.DocumentContext.GetContent <ITextEditorResolver> ();
if (textEditorResolver != null) {
- var result = textEditorResolver.GetLanguageItem (CurrentContext.Document.Editor.Document.LocationToOffset (CurrentContext.InsertPosition), var);
- if (result.Type.IsReferenceType.HasValue && !result.Type.IsReferenceType.Value)
- return "Length";
+ var result = textEditorResolver.GetLanguageItem (CurrentContext.Editor.LocationToOffset (CurrentContext.InsertPosition), var);
+ if (result != null) {
+ var returnType = result.GetReturnType ();
+ if (returnType != null && !returnType.IsReferenceType)
+ return "Length";
+ }
}
return "Count";
}
- IType GetElementType (IType result)
+ ITypeSymbol GetElementType (ITypeSymbol type)
{
- foreach (var baseType in result.GetAllBaseTypes ()) {
- var baseTypeDef = baseType.GetDefinition();
- if (baseTypeDef != null && baseTypeDef.Name == "IEnumerable") {
- if (baseTypeDef.Namespace == "System.Collections.Generic" && baseTypeDef.TypeParameterCount == 1) {
- if (baseType.TypeArguments.Count > 0)
- return baseType.TypeArguments[0];
- } else if (baseTypeDef.Namespace == "System.Collections" && baseTypeDef.TypeParameterCount == 0) {
- return CurrentContext.Compilation.FindType (KnownTypeCode.Object);
- }
+ foreach (var baseType in type.AllInterfaces) {
+ if (baseType != null && baseType.Name == "IEnumerable") {
+ if (baseType.TypeArguments.Length > 0)
+ return baseType.TypeArguments[0];
}
}
- return new UnknownType ("", "", 0);
+ return type;
}
@@ -162,70 +157,59 @@ namespace MonoDevelop.Ide.CodeTemplates
{
if (callback == null)
return "var";
-
+ var compilation = CurrentContext.Compilation;
+ if (compilation == null)
+ return null;
+
string var = callback (varName);
- ITextEditorResolver textEditorResolver = CurrentContext.Document.GetContent <ITextEditorResolver> ();
- if (textEditorResolver != null) {
- var result = textEditorResolver.GetLanguageItem (CurrentContext.Document.Editor.Caret.Offset, var);
- if (result != null) {
- var componentType = GetElementType (result.Type);
- if (componentType.Kind != TypeKind.Unknown) {
- var generator = CodeGenerator.CreateGenerator (CurrentContext.Document);
- if (generator != null)
- return generator.GetShortTypeString (CurrentContext.Document, componentType);
- }
- }
- }
-
+
+ var offset = CurrentContext.Editor.CaretOffset;
+ var sym = compilation.LookupSymbols (offset).First (s => s.Name == var);
+ if (sym == null)
+ return "var";
+ var rt = sym.GetReturnType ();
+ if (rt != null)
+ return rt.ToMinimalDisplayString (compilation, offset);
return "var";
}
- MonoDevelop.Ide.CodeCompletion.ICompletionDataList list;
+
+ ICompletionDataList list;
public IListDataProvider<string> GetCollections ()
{
var result = new List<CodeTemplateVariableValue> ();
- var ext = CurrentContext.Document.GetContent <CompletionTextEditorExtension> ();
+ var ext = CurrentContext.DocumentContext.GetContent <CompletionTextEditorExtension> ();
if (ext != null) {
if (list == null)
list = ext.CodeCompletionCommand (
- CurrentContext.Document.GetContent <MonoDevelop.Ide.CodeCompletion.ICompletionWidget> ().CurrentCodeCompletionContext);
+ CurrentContext.DocumentContext.GetContent <MonoDevelop.Ide.CodeCompletion.ICompletionWidget> ().CurrentCodeCompletionContext);
- foreach (object o in list) {
- var data = o as IEntityCompletionData;
- if (data == null)
- continue;
-
- if (data.Entity is IMember) {
- var m = data.Entity as IMember;
- if (GetElementType (m.ReturnType).Kind != TypeKind.Unknown) {
- if (m is IMethod) {
- if (((IMethod)m).Parameters.Count == 0)
- result.Add (new CodeTemplateVariableValue (m.Name + " ()", ((CompletionData)data).Icon));
- continue;
- }
-
- result.Add (new CodeTemplateVariableValue (m.Name, ((CompletionData)data).Icon));
+ foreach (var data in list.OfType<ISymbolCompletionData> ()) {
+ if (GetElementType (data.Symbol.GetReturnType ()).TypeKind != TypeKind.Error) {
+ var method = data as IMethodSymbol;
+ if (method != null) {
+ if (method.Parameters.Length == 0)
+ result.Add (new CodeTemplateVariableValue (data.Symbol.Name + " ()", ((CompletionData)data).Icon));
+ continue;
}
+
+ result.Add (new CodeTemplateVariableValue (data.Symbol.Name, ((CompletionData)data).Icon));
}
}
- foreach (object o in list) {
- var data = o as IEntityCompletionData;
- if (data == null)
- continue;
- if (data.Entity is IParameter) {
- var m = data.Entity as IParameter;
- if (GetElementType (m.Type).Kind != TypeKind.Unknown)
+ foreach (var data in list.OfType<ISymbolCompletionData> ()) {
+ var m = data.Symbol as IParameterSymbol;
+ if (m != null) {
+ if (GetElementType (m.Type).TypeKind != TypeKind.Error)
result.Add (new CodeTemplateVariableValue (m.Name, ((CompletionData)data).Icon));
}
}
- foreach (object o in list) {
- var data = o as IVariableCompletionData;
- if (data == null)
+ foreach (var sym in list.OfType<ISymbolCompletionData> ()) {
+ var m = sym.Symbol as ILocalSymbol;
+ if (m == null)
continue;
- var m = data.Variable;
- if (GetElementType (m.Type).Kind != TypeKind.Unknown)
- result.Add (new CodeTemplateVariableValue (m.Name, ((CompletionData)data).Icon));
+ if (GetElementType (m.Type).TypeKind != TypeKind.Error)
+ result.Add (new CodeTemplateVariableValue (m.Name, ((CompletionData)m).Icon));
}
}
return new CodeTemplateListDataProvider (result);
@@ -233,7 +217,8 @@ namespace MonoDevelop.Ide.CodeTemplates
public string GetSimpleTypeName (string fullTypeName)
{
- if (CurrentContext.ParsedDocument == null)
+ var compilation = CurrentContext.Compilation;
+ if (compilation == null)
return fullTypeName.Replace ("#", ".");
string ns = "";
string name = "";
@@ -249,31 +234,21 @@ namespace MonoDevelop.Ide.CodeTemplates
idx = name.IndexOf ('.');
if (idx >= 0) {
- member = name.Substring (idx);
+ member = name.Substring (idx + 1);
name = name.Substring (0, idx);
}
- var type = new GetClassTypeReference (ns, name, 0).Resolve (new SimpleTypeResolveContext (CurrentContext.Document.Compilation.MainAssembly));
- bool stripAttribute = false;
- if (type == null || type.Kind == TypeKind.Unknown) {
- type = new GetClassTypeReference (ns, name + "Attribute", 0).Resolve (
- new SimpleTypeResolveContext (CurrentContext.Document.Compilation.MainAssembly)
- );
- stripAttribute = true;
- }
- if (type == null || type.Kind == TypeKind.Unknown)
- return fullTypeName.Replace ("#", ".");
- var generator = CodeGenerator.CreateGenerator (CurrentContext.Document);
- if (generator != null) {
- var result = generator.GetShortTypeString (CurrentContext.Document, type) + member;
- if (stripAttribute && result.EndsWith ("Attribute", StringComparison.Ordinal))
- result = result.Substring (0, result.Length - "Attribute".Length);
- return result;
+ var metadataName = string.IsNullOrEmpty (ns) ? name : ns + "." + name;
+ var type = compilation.Compilation.GetTypeByMetadataName (metadataName);
+ if (type != null) {
+ var minimalName = type.ToMinimalDisplayString (compilation, CurrentContext.Editor.CaretOffset);
+ return string.IsNullOrEmpty (member) ? minimalName : minimalName + "." + member;
}
return fullTypeName.Replace ("#", ".");
}
- static Regex functionRegEx = new Regex ("([^(]*)\\(([^(]*)\\)", RegexOptions.Compiled);
+
+ static System.Text.RegularExpressions.Regex functionRegEx = new System.Text.RegularExpressions.Regex ("([^(]*)\\(([^(]*)\\)", RegexOptions.Compiled);
// We should use reflection here (but for 5 functions it doesn't hurt) !!! - Mike
@@ -294,7 +269,7 @@ namespace MonoDevelop.Ide.CodeTemplates
public virtual IListDataProvider<string> RunFunction (TemplateContext context, Func<string, string> callback, string function)
{
this.CurrentContext = context;
- Match match = functionRegEx.Match (function);
+ var match = functionRegEx.Match (function);
if (!match.Success)
return null;
string name = match.Groups[1].Value;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/ProjectContentEventArgs.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/IListDataProvider.cs
index 54d31aa138..b1d02b8310 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/ProjectContentEventArgs.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/IListDataProvider.cs
@@ -1,10 +1,10 @@
//
-// ProjectContentEventArgs.cs
+// IListDataProvider.cs
//
// Author:
// Mike Krüger <mkrueger@novell.com>
//
-// Copyright (c) 2011 Mike Krüger <mkrueger@novell.com>
+// Copyright (c) 2009 Novell, Inc (http://www.novell.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
@@ -23,30 +23,29 @@
// 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.NRefactory.TypeSystem;
-using MonoDevelop.Projects;
+using System.Collections.Generic;
-namespace MonoDevelop.Ide.TypeSystem
+namespace MonoDevelop.Ide.CodeTemplates
{
- [Serializable]
- public sealed class ProjectContentEventArgs : EventArgs
+ public interface IListDataProvider<T>
{
- public Project Project {
- get;
- private set;
- }
-
- public IProjectContent Content {
+ int Count {
get;
- private set;
}
- public ProjectContentEventArgs (Project project, IProjectContent content)
- {
- this.Project = project;
- this.Content = content;
+ T this[int index] {
+ get;
}
+
+ Xwt.Drawing.Image GetIcon (int index);
+ string GetText (int index);
}
-}
-
+
+ public interface IMarkupListDataProvider<T> : IListDataProvider<T>
+ {
+ bool HasMarkup (int index);
+ string GetMarkup (int index);
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/CustomStringTagProvider.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/CustomStringTagProvider.cs
index b39ae14707..15f096ced4 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/CustomStringTagProvider.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/CustomStringTagProvider.cs
@@ -87,17 +87,17 @@ namespace MonoDevelop.Ide.Commands
case "CURLINE":
if (wb.ActiveDocument != null && wb.ActiveDocument.Editor != null)
- return wb.ActiveDocument.Editor.Caret.Line;
+ return wb.ActiveDocument.Editor.CaretLocation.Line;
return null;
case "CURCOLUMN":
if (wb.ActiveDocument != null && wb.ActiveDocument.Editor != null)
- return wb.ActiveDocument.Editor.Caret.Column;
+ return wb.ActiveDocument.Editor.CaretLocation.Column;
return null;
case "CUROFFSET":
if (wb.ActiveDocument != null && wb.ActiveDocument.Editor != null)
- return wb.ActiveDocument.Editor.Caret.Offset;
+ return wb.ActiveDocument.Editor.CaretOffset;
return null;
case "CURTEXT":
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/EditCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/EditCommands.cs
index 1ebdb497bd..49e2fab704 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/EditCommands.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/EditCommands.cs
@@ -287,7 +287,7 @@ namespace MonoDevelop.Ide.Commands
{
Document doc = IdeApp.Workbench.ActiveDocument;
string header = MonoDevelop.Ide.StandardHeader.StandardHeaderService.GetHeader (doc.Project, doc.Name, false);
- doc.Editor.Insert (0, header + "\n");
+ doc.Editor.InsertText (0, header + "\n");
}
protected override void Update (CommandInfo info)
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 82dab65f80..0c654ba2e9 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileCommands.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileCommands.cs
@@ -38,6 +38,7 @@ using Gtk;
using MonoDevelop.Ide.Projects;
using MonoDevelop.Ide.Desktop;
using System.Linq;
+using MonoDevelop.Components;
namespace MonoDevelop.Ide.Commands
{
@@ -365,7 +366,7 @@ namespace MonoDevelop.Ide.Commands
protected override void Run (object dataItem)
{
string filename = (string)dataItem;
- Gdk.ModifierType mtype = Mono.TextEditor.GtkWorkarounds.GetCurrentKeyModifiers ();
+ Gdk.ModifierType mtype = GtkWorkarounds.GetCurrentKeyModifiers ();
bool inWorkspace = (mtype & Gdk.ModifierType.ControlMask) != 0;
IdeApp.Workspace.OpenWorkspaceItem (filename, !inWorkspace);
}
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 1464202903..8e2fa052bb 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ProjectCommands.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ProjectCommands.cs
@@ -338,7 +338,7 @@ namespace MonoDevelop.Ide.Commands
if (h == null || !IdeApp.ProjectOperations.CurrentRunOperation.IsCompleted)
return;
- IdeApp.ProjectOperations.Execute (target);
+ IdeApp.ProjectOperations.Execute (target, h);
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/TextEditorCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/TextEditorCommands.cs
index fa09268349..eaa9fcd823 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/TextEditorCommands.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/TextEditorCommands.cs
@@ -91,7 +91,11 @@ namespace MonoDevelop.Ide.Commands
DuplicateLine,
ToggleCompletionSuggestionMode,
- ToggleBlockSelectionMode
+ ToggleBlockSelectionMode,
+
+ DynamicAbbrev,
+
+ PulseCaret
}
public class ToggleCompletionSuggestionModeHandler : CommandHandler
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ViewCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ViewCommands.cs
index 9d3d19c798..36d6161f18 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ViewCommands.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ViewCommands.cs
@@ -378,7 +378,7 @@ namespace MonoDevelop.Ide.Commands
protected override void Run ()
{
- IdeApp.Workbench.ActiveDocument.Editor.SetCaretTo (IdeApp.Workbench.ActiveDocument.Editor.Caret.Line, IdeApp.Workbench.ActiveDocument.Editor.Caret.Column);
+ IdeApp.Workbench.ActiveDocument.Editor.StartCaretPulseAnimation ();
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/AbstractUsagesExtension.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/AbstractUsagesExtension.cs
new file mode 100644
index 0000000000..ec5fd72ee1
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/AbstractUsagesExtension.cs
@@ -0,0 +1,246 @@
+//
+// AbstractUsagesExtension.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Ide.Gui.Content;
+using System.Collections.Generic;
+using System.Linq;
+using MonoDevelop.Ide.FindInFiles;
+using System.Threading;
+using System.Threading.Tasks;
+using MonoDevelop.Core;
+using System.Diagnostics.CodeAnalysis;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Core.Text;
+
+namespace MonoDevelop.Ide.Editor.Extension
+{
+ public abstract class UsageProviderEditorExtension : TextEditorExtension
+ {
+ public abstract IEnumerable<Usage> Usages {
+ get;
+ }
+
+ public event EventHandler UsagesUpdated;
+
+ protected void OnUsagesUpdated (EventArgs e)
+ {
+ var handler = UsagesUpdated;
+ if (handler != null)
+ handler (this, e);
+ }
+ }
+
+ /// <summary>
+ /// Provides a base class for implementing highlighting of usages inside the text editor.
+ /// </summary>
+ public abstract class AbstractUsagesExtension<T> : UsageProviderEditorExtension
+ {
+ [SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")]
+ protected static readonly List<MemberReference> EmptyList = new List<MemberReference> ();
+
+ CancellationTokenSource tooltipCancelSrc = new CancellationTokenSource ();
+ List<ITextSegmentMarker> markers = new List<ITextSegmentMarker> ();
+
+ public IList<ITextSegmentMarker> Markers {
+ get {
+ return markers;
+ }
+ }
+
+ uint popupTimer;
+
+ protected override void Initialize ()
+ {
+ Editor.CaretPositionChanged += HandleTextEditorDataCaretPositionChanged;
+ Editor.TextChanged += HandleTextEditorDataDocumentTextReplaced;
+ Editor.SelectionChanged += HandleTextEditorDataSelectionChanged;
+ }
+
+ void HandleTextEditorDataSelectionChanged (object sender, EventArgs e)
+ {
+ if (Editor.IsSomethingSelected)
+ RemoveMarkers ();
+ }
+
+ void HandleTextEditorDataDocumentTextReplaced (object sender, TextChangeEventArgs e)
+ {
+ RemoveMarkers ();
+ }
+
+ public override void Dispose ()
+ {
+ CancelTooltip ();
+
+ Editor.SelectionChanged -= HandleTextEditorDataSelectionChanged;
+ Editor.CaretPositionChanged -= HandleTextEditorDataCaretPositionChanged;
+ Editor.TextChanged -= HandleTextEditorDataDocumentTextReplaced;
+ base.Dispose ();
+ RemoveTimer ();
+ }
+
+ public bool IsTimerOnQueue {
+ get {
+ return popupTimer != 0;
+ }
+ }
+
+ public void ForceUpdate ()
+ {
+ RemoveTimer ();
+ DelayedTooltipShow ();
+ }
+
+ /// <summary>
+ /// Tries to resolve inside the current location inside tho document.
+ /// </summary>
+ /// <returns><c>true</c>, if resolve was successful, <c>false</c> otherwise.</returns>
+ /// <param name="token">A cancellation token to cancel the operation.</param>
+ protected abstract Task<T> ResolveAsync (CancellationToken token);
+
+
+ /// <summary>
+ /// Gets all references from a given resolve result. Note that this method is called on a background thread.
+ /// </summary>
+ /// <returns>The references.</returns>
+ /// <param name="resolveResult">The resolve result given in 'TryResolve'.</param>
+ /// <param name="token">A cancellation token to cancel the operation.</param>
+ protected abstract IEnumerable<MemberReference> GetReferences (T resolveResult, CancellationToken token);
+
+ async void DelayedTooltipShow ()
+ {
+ try {
+ CancelTooltip ();
+
+ var token = tooltipCancelSrc.Token;
+
+ T result = await ResolveAsync (token);
+ if (token.IsCancellationRequested) {
+ ClearQuickTasks ();
+ return;
+ }
+
+ Task.Run (delegate {
+ var list = GetReferences (result, token).ToList ();
+ if (!token.IsCancellationRequested) {
+ Gtk.Application.Invoke (delegate {
+ if (!token.IsCancellationRequested)
+ ShowReferences (list);
+ });
+ }
+ });
+
+ } catch (Exception e) {
+ LoggingService.LogError ("Unhandled Exception in HighlightingUsagesExtension", e);
+ } finally {
+ popupTimer = 0;
+ }
+ }
+
+ void RemoveTimer ()
+ {
+ if (popupTimer != 0) {
+ GLib.Source.Remove (popupTimer);
+ popupTimer = 0;
+ }
+ }
+
+ void HandleTextEditorDataCaretPositionChanged (object sender, EventArgs e)
+ {
+ if (!DefaultSourceEditorOptions.Instance.EnableHighlightUsages)
+ return;
+ if (!Editor.IsSomethingSelected && markers.Any (m => m.Contains (Editor.CaretOffset)))
+ return;
+ RemoveMarkers ();
+ RemoveTimer ();
+ if (!Editor.IsSomethingSelected)
+ popupTimer = GLib.Timeout.Add (1000, () => { DelayedTooltipShow (); return false; } );
+ }
+
+ void ClearQuickTasks ()
+ {
+ //UsagesSegments.Clear ();
+ if (usages.Count > 0) {
+ usages.Clear ();
+ OnUsagesUpdated (EventArgs.Empty);
+ }
+ }
+
+ void CancelTooltip ()
+ {
+ tooltipCancelSrc.Cancel ();
+ tooltipCancelSrc = new CancellationTokenSource ();
+ }
+
+ void RemoveMarkers ()
+ {
+ if (markers.Count == 0)
+ return;
+ // TextEditorData.Parent.TextViewMargin.AlphaBlendSearchResults = false;
+ foreach (var marker in markers) {
+ Editor.RemoveMarker (marker);
+ }
+ markers.Clear ();
+ }
+
+ void ShowReferences (IEnumerable<MemberReference> references)
+ {
+ RemoveMarkers ();
+ var lineNumbers = new HashSet<int> ();
+ usages.Clear ();
+ var editor = Editor;
+ if (editor != null /*&& editor.TextViewMargin != null*/) {
+ if (references != null) {
+ foreach (var r in references) {
+ if (r == null)
+ continue;
+ var start = r.Offset;
+ var end = r.Offset + r.Length;
+ if (end > editor.Length)
+ continue;
+ var usage = new Usage (TextSegment.FromBounds (start, end), r.ReferenceUsageType);
+ usages.Add (usage);
+ var marker = TextMarkerFactory.CreateUsageMarker (editor, usage);
+ markers.Add (marker);
+ lineNumbers.Add (editor.OffsetToLineNumber (start));
+ editor.AddMarker (marker);
+ }
+ }
+ }
+ OnUsagesUpdated (EventArgs.Empty);
+ }
+
+ #region IUsageProvider implementation
+
+ readonly List<Usage> usages = new List<Usage> ();
+ public override IEnumerable<Usage> Usages {
+ get {
+ return usages;
+ }
+ }
+ #endregion
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/CompletionTextEditorExtension.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/CompletionTextEditorExtension.cs
index 87562cd44b..2425d511de 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/CompletionTextEditorExtension.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/CompletionTextEditorExtension.cs
@@ -33,143 +33,177 @@ using MonoDevelop.Components.Commands;
using MonoDevelop.Ide.Commands;
using MonoDevelop.Core;
using MonoDevelop.Ide.CodeTemplates;
-using ICSharpCode.NRefactory.Completion;
+using MonoDevelop.Ide.Editor;
+using System.Threading.Tasks;
+using System.Threading;
+using Gtk;
-namespace MonoDevelop.Ide.Gui.Content
+namespace MonoDevelop.Ide.Editor.Extension
{
- public class CompletionTextEditorExtension: TextEditorExtension
+ public class CompletionTextEditorExtension : TextEditorExtension
{
- CodeCompletionContext currentCompletionContext;
-
- bool autoHideCompletionWindow = true, autoHideParameterWindow = true;
+ protected CodeCompletionContext currentCompletionContext;
+ bool autoHideCompletionWindow = true, autoHideParameterWindow = true;
+
#region Completion related IDE
-// public readonly static PropertyWrapper<bool> EnableCodeCompletion = PropertyService.Wrap ("EnableCodeCompletion", true);
-// public readonly static PropertyWrapper<bool> EnableParameterInsight = PropertyService.Wrap ("EnableParameterInsight", true);
+ // public readonly static PropertyWrapper<bool> EnableCodeCompletion = PropertyService.Wrap ("EnableCodeCompletion", true);
+ // public readonly static PropertyWrapper<bool> EnableParameterInsight = PropertyService.Wrap ("EnableParameterInsight", true);
public readonly static PropertyWrapper<bool> EnableAutoCodeCompletion = PropertyService.Wrap ("EnableAutoCodeCompletion", true);
public readonly static PropertyWrapper<bool> AddImportedItemsToCompletionList = PropertyService.Wrap ("AddImportedItemsToCompletionList", false);
public readonly static PropertyWrapper<bool> IncludeKeywordsInCompletionList = PropertyService.Wrap ("IncludeKeywordsInCompletionList", true);
public readonly static PropertyWrapper<bool> IncludeCodeSnippetsInCompletionList = PropertyService.Wrap ("IncludeCodeSnippetsInCompletionList", true);
public readonly static PropertyWrapper<bool> AddParenthesesAfterCompletion = PropertyService.Wrap ("AddParenthesesAfterCompletion", false);
public readonly static PropertyWrapper<bool> AddOpeningOnly = PropertyService.Wrap ("AddOpeningOnly", false);
- public readonly static PropertyWrapper<int> CompletionListRows = PropertyService.Wrap ("CompletionListRows", 7);
+ public readonly static int CompletionListRows = 7;
public readonly static PropertyWrapper<bool> FilterCompletionListByEditorBrowsable = PropertyService.Wrap ("FilterCompletionListByEditorBrowsable", true);
- public readonly static PropertyWrapper<bool> IncludeEditorBrowsableAdvancedMembers = PropertyService.Wrap ("IncludeEditorBrowsableAdvancedMembers", true);
-
+ public readonly static PropertyWrapper<bool> IncludeEditorBrowsableAdvancedMembers = PropertyService.Wrap ("IncludeEditorBrowsableAdvancedMembers", true);
+
#endregion
-
- public ICompletionWidget CompletionWidget {
+
+ internal ICompletionWidget CompletionWidget
+ {
get;
set;
}
- public virtual string CompletionLanguage {
- get {
+ public virtual string CompletionLanguage
+ {
+ get
+ {
return "Other";
}
}
public void ShowCompletion (ICompletionDataList completionList)
{
- currentCompletionContext = CompletionWidget.CreateCodeCompletionContext (Document.Editor.Caret.Offset);
+ currentCompletionContext = CompletionWidget.CreateCodeCompletionContext (Editor.CaretOffset);
int cpos, wlen;
if (!GetCompletionCommandOffset (out cpos, out wlen)) {
- cpos = Document.Editor.Caret.Offset;
+ cpos = Editor.CaretOffset;
wlen = 0;
}
currentCompletionContext.TriggerOffset = cpos;
currentCompletionContext.TriggerWordLength = wlen;
-
+
CompletionWindowManager.ShowWindow (this, '\0', completionList, CompletionWidget, currentCompletionContext);
}
-
- // When a key is pressed, and before the key is processed by the editor, this method will be invoked.
- // Return true if the key press should be processed by the editor.
- public override bool KeyPress (Gdk.Key key, char keyChar, Gdk.ModifierType modifier)
+ CancellationTokenSource completionTokenSrc = new CancellationTokenSource ();
+ CancellationTokenSource parameterHintingSrc = new CancellationTokenSource ();
+ // When a key is pressed, and before the key is processed by the editor, this method will be invoked.
+ // Return true if the key press should be processed by the editor.
+ public override bool KeyPress (KeyDescriptor descriptor)
{
bool res;
if (currentCompletionContext != null) {
- if (CompletionWindowManager.PreProcessKeyEvent (key, keyChar, modifier)) {
- CompletionWindowManager.PostProcessKeyEvent (key, keyChar, modifier);
- autoHideCompletionWindow = true;
- // in named parameter case leave the parameter window open.
- autoHideParameterWindow = keyChar != ':';
+ if (CompletionWindowManager.PreProcessKeyEvent (descriptor)) {
+ CompletionWindowManager.PostProcessKeyEvent (descriptor);
+ autoHideCompletionWindow = true;
+ // in named parameter case leave the parameter window open.
+ autoHideParameterWindow = descriptor.KeyChar != ':';
if (!autoHideParameterWindow && ParameterInformationWindowManager.IsWindowVisible)
- ParameterInformationWindowManager.PostProcessKeyEvent (this, CompletionWidget, key, modifier);
-
+ ParameterInformationWindowManager.PostProcessKeyEvent (this, CompletionWidget, descriptor);
+
return false;
}
autoHideCompletionWindow = autoHideParameterWindow = false;
}
-
+
if (ParameterInformationWindowManager.IsWindowVisible) {
- if (ParameterInformationWindowManager.ProcessKeyEvent (this, CompletionWidget, key, modifier))
+ if (ParameterInformationWindowManager.ProcessKeyEvent (this, CompletionWidget, descriptor))
return false;
autoHideCompletionWindow = autoHideParameterWindow = false;
- }
-
- // int oldPos = Editor.CursorPosition;
- // int oldLen = Editor.TextLength;
- res = base.KeyPress (key, keyChar, modifier);
-
- CompletionWindowManager.PostProcessKeyEvent (key, keyChar, modifier);
-
- var ignoreMods = Gdk.ModifierType.ControlMask | Gdk.ModifierType.MetaMask
- | Gdk.ModifierType.Mod1Mask | Gdk.ModifierType.SuperMask;
- // Handle parameter completion
+ }
+
+ // int oldPos = Editor.CursorPosition;
+ // int oldLen = Editor.TextLength;
+ res = base.KeyPress (descriptor);
+
+ CompletionWindowManager.PostProcessKeyEvent (descriptor);
+
+ var ignoreMods = ModifierKeys.Control | ModifierKeys.Alt
+ | ModifierKeys.Command;
+ // Handle parameter completion
if (ParameterInformationWindowManager.IsWindowVisible) {
- ParameterInformationWindowManager.PostProcessKeyEvent (this, CompletionWidget, key, modifier);
+ ParameterInformationWindowManager.PostProcessKeyEvent (this, CompletionWidget, descriptor);
}
- if ((modifier & ignoreMods) != 0)
- return res;
-
- // don't complete on block selection
- if (/*!EnableCodeCompletion ||*/ Document.Editor.SelectionMode == Mono.TextEditor.SelectionMode.Block)
- return res;
-
+ if ((descriptor.ModifierKeys & ignoreMods) != 0)
+ return res;
+
+ // don't complete on block selection
+ if (/*!EnableCodeCompletion ||*/ Editor.SelectionMode == MonoDevelop.Ide.Editor.SelectionMode.Block)
+ return res;
+
// Handle code completion
- if (keyChar != '\0' && CompletionWidget != null && !CompletionWindowManager.IsVisible) {
+ if (descriptor.KeyChar != '\0' && CompletionWidget != null && !CompletionWindowManager.IsVisible) {
currentCompletionContext = CompletionWidget.CurrentCodeCompletionContext;
- int triggerWordLength = currentCompletionContext.TriggerWordLength;
- ICompletionDataList completionList = HandleCodeCompletion (currentCompletionContext, keyChar,
- ref triggerWordLength);
- if (triggerWordLength > 0 && (triggerWordLength < Editor.Caret.Offset
- || (triggerWordLength == 1 && Editor.Caret.Offset == 1))) {
- currentCompletionContext
- = CompletionWidget.CreateCodeCompletionContext (Editor.Caret.Offset - triggerWordLength);
- currentCompletionContext.TriggerWordLength = triggerWordLength;
- }
- if (completionList != null) {
- if (!CompletionWindowManager.ShowWindow (this, keyChar, completionList, CompletionWidget, currentCompletionContext))
+ completionTokenSrc.Cancel ();
+ completionTokenSrc = new CancellationTokenSource ();
+ var token = completionTokenSrc.Token;
+ var caretOffset = Editor.CaretOffset;
+ try {
+ var task = HandleCodeCompletionAsync (currentCompletionContext, descriptor.KeyChar, token);
+ if (task != null) {
+ var result = task.Result;
+ if (result != null) {
+ int triggerWordLength = result.TriggerWordLength;
+
+ if (triggerWordLength > 0 && (triggerWordLength < caretOffset
+ || (triggerWordLength == 1 && caretOffset == 1))) {
+ currentCompletionContext = CompletionWidget.CreateCodeCompletionContext (caretOffset - triggerWordLength);
+ currentCompletionContext.TriggerWordLength = triggerWordLength;
+ }
+
+ if (!CompletionWindowManager.ShowWindow (this, descriptor.KeyChar, result, CompletionWidget, currentCompletionContext))
+ currentCompletionContext = null;
+ } else {
+ currentCompletionContext = null;
+ }
+ } else {
currentCompletionContext = null;
- } else {
+ }
+ } catch (TaskCanceledException) {
+ currentCompletionContext = null;
+ } catch (AggregateException) {
currentCompletionContext = null;
}
}
-
- if (/*EnableParameterInsight &&*/ CompletionWidget != null) {
+
+ if (CompletionWidget != null) {
CodeCompletionContext ctx = CompletionWidget.CurrentCodeCompletionContext;
- var paramProvider = HandleParameterCompletion (ctx, keyChar);
- if (paramProvider != null)
- ParameterInformationWindowManager.ShowWindow (this, CompletionWidget, ctx, paramProvider);
- }
-/* autoHideCompletionWindow = true;
- autoHideParameterWindow = keyChar != ':';*/
+ parameterHintingSrc.Cancel ();
+ parameterHintingSrc = new CancellationTokenSource ();
+ var token = parameterHintingSrc.Token;
+ try {
+ var task = HandleParameterCompletionAsync (ctx, descriptor.KeyChar, token);
+ if (task != null) {
+ var result = task.Result;
+ if (result != null) {
+ ParameterInformationWindowManager.ShowWindow (this, CompletionWidget, ctx, result);
+ }
+ }
+ } catch (TaskCanceledException) {
+ } catch (AggregateException) {
+ }
+
+ }
+ /* autoHideCompletionWindow = true;
+ autoHideParameterWindow = keyChar != ':';*/
return res;
}
-
+
protected void ShowCompletion (ICompletionDataList completionList, int triggerWordLength, char keyChar)
{
- if (Document.Editor.SelectionMode == Mono.TextEditor.SelectionMode.Block)
+ if (Editor.SelectionMode == SelectionMode.Block)
return;
if (CompletionWidget != null && currentCompletionContext == null) {
currentCompletionContext = CompletionWidget.CurrentCodeCompletionContext;
- if (triggerWordLength > 0 && triggerWordLength < Editor.Caret.Offset) {
+ if (triggerWordLength > 0 && triggerWordLength < Editor.CaretOffset) {
currentCompletionContext =
- CompletionWidget.CreateCodeCompletionContext (Editor.Caret.Offset - triggerWordLength);
+ CompletionWidget.CreateCodeCompletionContext (Editor.CaretOffset - triggerWordLength);
currentCompletionContext.TriggerWordLength = triggerWordLength;
}
if (completionList != null)
@@ -179,12 +213,12 @@ namespace MonoDevelop.Ide.Gui.Content
}
autoHideCompletionWindow = autoHideParameterWindow = true;
}
-
+
public virtual int GetCurrentParameterIndex (int startOffset)
{
return -1;
}
-
+
protected void OnCompletionContextChanged (object o, EventArgs a)
{
@@ -195,24 +229,24 @@ namespace MonoDevelop.Ide.Gui.Content
ParameterInformationWindowManager.UpdateCursorPosition (this, CompletionWidget);
}
- [CommandUpdateHandler (TextEditorCommands.ShowCompletionWindow)]
+ [CommandUpdateHandler(TextEditorCommands.ShowCompletionWindow)]
internal void OnUpdateCompletionCommand (CommandInfo info)
{
info.Bypass = !CanRunCompletionCommand () && !CompletionWindowManager.IsVisible;
}
-
- [CommandUpdateHandler (TextEditorCommands.ShowParameterCompletionWindow)]
+
+ [CommandUpdateHandler(TextEditorCommands.ShowParameterCompletionWindow)]
internal void OnUpdateParameterCompletionCommand (CommandInfo info)
{
info.Bypass = !CanRunParameterCompletionCommand ();
}
-
- [CommandHandler (TextEditorCommands.ShowCompletionWindow)]
+
+ [CommandHandler(TextEditorCommands.ShowCompletionWindow)]
public virtual void RunCompletionCommand ()
{
- if (Document.Editor.SelectionMode == Mono.TextEditor.SelectionMode.Block)
+ if (Editor.SelectionMode == SelectionMode.Block)
return;
-
+
if (CompletionWindowManager.IsVisible) {
CompletionWindowManager.Wnd.ToggleCategoryMode ();
return;
@@ -220,7 +254,7 @@ namespace MonoDevelop.Ide.Gui.Content
ICompletionDataList completionList = null;
int cpos, wlen;
if (!GetCompletionCommandOffset (out cpos, out wlen)) {
- cpos = Editor.Caret.Offset;
+ cpos = Editor.CaretOffset;
wlen = 0;
}
currentCompletionContext = CompletionWidget.CreateCodeCompletionContext (cpos);
@@ -231,20 +265,20 @@ namespace MonoDevelop.Ide.Gui.Content
else
currentCompletionContext = null;
}
-
- [CommandHandler (TextEditorCommands.ShowCodeTemplateWindow)]
+
+ [CommandHandler(TextEditorCommands.ShowCodeTemplateWindow)]
public virtual void RunShowCodeTemplatesWindow ()
{
ICompletionDataList completionList = null;
int cpos, wlen;
if (!GetCompletionCommandOffset (out cpos, out wlen)) {
- cpos = Editor.Caret.Offset;
+ cpos = Editor.CaretOffset;
wlen = 0;
}
-
+
var ctx = CompletionWidget.CreateCodeCompletionContext (cpos);
ctx.TriggerWordLength = wlen;
- completionList = Document.Editor.IsSomethingSelected ? ShowCodeSurroundingsCommand (ctx) : ShowCodeTemplatesCommand (ctx);
+ completionList = Editor.IsSomethingSelected ? ShowCodeSurroundingsCommand (ctx) : ShowCodeTemplatesCommand (ctx);
if (completionList == null) {
return;
}
@@ -256,74 +290,72 @@ namespace MonoDevelop.Ide.Gui.Content
wnd.Extension = this;
wnd.ShowListWindow ((char)0, completionList, CompletionWidget, ctx);
}
-
- [CommandUpdateHandler (TextEditorCommands.ShowCodeTemplateWindow)]
+
+ [CommandUpdateHandler(TextEditorCommands.ShowCodeTemplateWindow)]
internal void OnUpdateShowCodeTemplatesWindow (CommandInfo info)
{
ICompletionDataList completionList = null;
int cpos, wlen;
if (!GetCompletionCommandOffset (out cpos, out wlen)) {
- cpos = Editor.Caret.Offset;
+ cpos = Editor.CaretOffset;
wlen = 0;
}
try {
var ctx = CompletionWidget.CreateCodeCompletionContext (cpos);
ctx.TriggerWordLength = wlen;
- completionList = Document.Editor.IsSomethingSelected ? ShowCodeSurroundingsCommand (ctx) : ShowCodeTemplatesCommand (ctx);
+ completionList = Editor.IsSomethingSelected ? ShowCodeSurroundingsCommand (ctx) : ShowCodeTemplatesCommand (ctx);
info.Bypass = completionList == null;
- info.Text = Document.Editor.IsSomethingSelected ? GettextCatalog.GetString ("_Surround With...") : GettextCatalog.GetString ("I_nsert Template...");
+ info.Text = Editor.IsSomethingSelected ? GettextCatalog.GetString ("_Surround With...") : GettextCatalog.GetString ("I_nsert Template...");
} catch (Exception e) {
LoggingService.LogError ("Error while update show code templates window", e);
info.Bypass = true;
}
}
-
-
- [CommandHandler (TextEditorCommands.ShowParameterCompletionWindow)]
+
+
+ [CommandHandler(TextEditorCommands.ShowParameterCompletionWindow)]
public virtual void RunParameterCompletionCommand ()
{
- if (Document.Editor.SelectionMode == Mono.TextEditor.SelectionMode.Block || CompletionWidget == null)
+ if (Editor.SelectionMode == SelectionMode.Block || CompletionWidget == null)
return;
- ParameterDataProvider cp = null;
- int cpos;
- if (!GetParameterCompletionCommandOffset (out cpos))
- cpos = Editor.Caret.Offset;
+ ParameterHintingResult cp = null;
+ int cpos = Editor.CaretOffset;
CodeCompletionContext ctx = CompletionWidget.CreateCodeCompletionContext (cpos);
cp = ParameterCompletionCommand (ctx);
if (cp != null) {
ParameterInformationWindowManager.ShowWindow (this, CompletionWidget, ctx, cp);
- ParameterInformationWindowManager.PostProcessKeyEvent (this, CompletionWidget, Gdk.Key.F, Gdk.ModifierType.None);
+ ParameterInformationWindowManager.PostProcessKeyEvent (this, CompletionWidget, KeyDescriptor.FromGtk (Gdk.Key.F, 'f', Gdk.ModifierType.None));
}
}
-
+
public virtual bool CanRunCompletionCommand ()
{
return (CompletionWidget != null && currentCompletionContext == null);
}
-
+
public virtual bool CanRunParameterCompletionCommand ()
{
return (CompletionWidget != null && !ParameterInformationWindowManager.IsWindowVisible);
}
-
-
- public virtual ICompletionDataList HandleCodeCompletion (CodeCompletionContext completionContext,
- char completionChar, ref int triggerWordLength)
+
+ static readonly ICompletionDataList emptyList = new CompletionDataList ();
+
+ public virtual Task<ICompletionDataList> HandleCodeCompletionAsync (CodeCompletionContext completionContext, char completionChar, CancellationToken token = default(CancellationToken))
{
- return null;
+ return Task.FromResult (emptyList);
}
-
- public virtual ParameterDataProvider HandleParameterCompletion (CodeCompletionContext completionContext, char completionChar)
+
+ public virtual Task<ParameterHintingResult> HandleParameterCompletionAsync (CodeCompletionContext completionContext, char completionChar, CancellationToken token = default(CancellationToken))
{
- return null;
- }
-
- // return false if completion can't be shown
+ return Task.FromResult (ParameterHintingResult.Empty);
+ }
+
+ // return false if completion can't be shown
public virtual bool GetCompletionCommandOffset (out int cpos, out int wlen)
{
cpos = wlen = 0;
- int pos = Editor.Caret.Offset - 1;
+ int pos = Editor.CaretOffset - 1;
while (pos >= 0) {
char c = Editor.GetCharAt (pos);
if (!char.IsLetterOrDigit (c) && c != '_')
@@ -332,11 +364,11 @@ namespace MonoDevelop.Ide.Gui.Content
}
if (pos == -1)
return false;
-
+
pos++;
cpos = pos;
int len = Editor.Length;
-
+
while (pos < len) {
char c = Editor.GetCharAt (pos);
if (!char.IsLetterOrDigit (c) && c != '_')
@@ -347,45 +379,40 @@ namespace MonoDevelop.Ide.Gui.Content
return true;
}
- public virtual bool GetParameterCompletionCommandOffset (out int cpos)
- {
- cpos = 0;
- return false;
- }
-
+
public virtual ICompletionDataList ShowCodeSurroundingsCommand (CodeCompletionContext completionContext)
{
CompletionDataList list = new CompletionDataList ();
list.AutoSelect = true;
list.AutoCompleteEmptyMatch = true;
list.CompletionSelectionMode = CompletionSelectionMode.OwnTextField;
- var templateWidget = Document.GetContent<ICodeTemplateContextProvider> ();
+ var templateWidget = DocumentContext.GetContent<ICodeTemplateContextProvider> ();
CodeTemplateContext ctx = CodeTemplateContext.Standard;
if (templateWidget != null)
ctx = templateWidget.GetCodeTemplateContext ();
- foreach (CodeTemplate template in CodeTemplateService.GetCodeTemplatesForFile (Document.FileName)) {
- if ((template.CodeTemplateType & CodeTemplateType.SurroundsWith) == CodeTemplateType.SurroundsWith) {
+ foreach (CodeTemplate template in CodeTemplateService.GetCodeTemplatesForFile (DocumentContext.Name)) {
+ if ((template.CodeTemplateType & CodeTemplateType.SurroundsWith) == CodeTemplateType.SurroundsWith) {
if (ctx == template.CodeTemplateContext)
- list.Add (new CodeTemplateCompletionData (Document, template));
+ list.Add (new CodeTemplateCompletionData (this, template));
}
}
return list;
}
-
+
public virtual ICompletionDataList ShowCodeTemplatesCommand (CodeCompletionContext completionContext)
{
CompletionDataList list = new CompletionDataList ();
list.AutoSelect = true;
list.AutoCompleteEmptyMatch = true;
list.CompletionSelectionMode = CompletionSelectionMode.OwnTextField;
- foreach (CodeTemplate template in CodeTemplateService.GetCodeTemplatesForFile (Document.FileName)) {
- if (template.CodeTemplateType != CodeTemplateType.SurroundsWith) {
- list.Add (new CodeTemplateCompletionData (Document, template));
+ foreach (CodeTemplate template in CodeTemplateService.GetCodeTemplatesForFile (DocumentContext.Name)) {
+ if (template.CodeTemplateType != CodeTemplateType.SurroundsWith) {
+ list.Add (new CodeTemplateCompletionData (this, template));
}
}
return list;
}
-
+ const int CompletionTimeoutInMs = 500;
public virtual ICompletionDataList CodeCompletionCommand (CodeCompletionContext completionContext)
{
@@ -395,15 +422,25 @@ namespace MonoDevelop.Ide.Gui.Content
int pos = completionContext.TriggerOffset;
if (pos > 0) {
char ch = Editor.GetCharAt (pos - 1);
- int triggerWordLength = completionContext.TriggerWordLength;
- ICompletionDataList completionList = HandleCodeCompletion (completionContext, ch, ref triggerWordLength);
- if (completionList != null)
- return completionList;
+ var csc = new CancellationTokenSource (CompletionTimeoutInMs);
+ try {
+ var task = HandleCodeCompletionAsync (completionContext, ch, csc.Token);
+ if (task == null)
+ return null;
+ task.Wait (csc.Token);
+ if (!task.IsCompleted)
+ return null;
+ var completionList = task.Result;
+ if (completionList != null)
+ return completionList;
+ } catch (TaskCanceledException) {
+ } catch (AggregateException) {
+ }
}
return null;
}
- public virtual ParameterDataProvider ParameterCompletionCommand (CodeCompletionContext completionContext)
+ public virtual ParameterHintingResult ParameterCompletionCommand (CodeCompletionContext completionContext)
{
// This default implementation of ParameterCompletionCommand calls HandleParameterCompletion providing
// the char at the cursor position. If it returns a provider, just return it.
@@ -411,22 +448,34 @@ namespace MonoDevelop.Ide.Gui.Content
int pos = completionContext.TriggerOffset;
if (pos <= 0)
return null;
- var cp = HandleParameterCompletion (completionContext, Editor.Document.GetCharAt (pos - 1));
- if (cp != null)
- return cp;
+ var csc = new CancellationTokenSource (CompletionTimeoutInMs);
+ try {
+ var task = HandleParameterCompletionAsync (completionContext, Editor.GetCharAt (pos - 1), csc.Token);
+ if (task == null)
+ return null;
+ task.Wait (csc.Token);
+ if (!task.IsCompleted)
+ return null;
+ var cp = task.Result;
+ if (cp != null)
+ return cp;
+ } catch (TaskCanceledException) {
+ } catch (AggregateException) {
+ }
return null;
}
- public virtual int GuessBestMethodOverload (IParameterDataProvider provider, int currentOverload)
+ public virtual int GuessBestMethodOverload (ParameterHintingResult provider, int currentOverload)
{
int cparam = GetCurrentParameterIndex (provider.StartOffset);
- if (cparam > provider.GetParameterCount (currentOverload) && !provider.AllowParameterList (currentOverload)) {
+ var currentHintingData = provider [currentOverload];
+ if (cparam > currentHintingData.ParameterCount && !currentHintingData.IsParameterListAllowed) {
// Look for an overload which has more parameters
int bestOverload = -1;
int bestParamCount = int.MaxValue;
for (int n=0; n<provider.Count; n++) {
- int pc = provider.GetParameterCount (n);
+ int pc = provider[n].ParameterCount;
if (pc < bestParamCount && pc >= cparam) {
bestOverload = n;
bestParamCount = pc;
@@ -434,7 +483,7 @@ namespace MonoDevelop.Ide.Gui.Content
}
if (bestOverload == -1) {
for (int n=0; n<provider.Count; n++) {
- if (provider.AllowParameterList (n)) {
+ if (provider[n].IsParameterListAllowed) {
bestOverload = n;
break;
}
@@ -445,32 +494,37 @@ namespace MonoDevelop.Ide.Gui.Content
return -1;
}
- void HandlePaste (int insertionOffset, string text, int insertedChars)
- {
- ParameterInformationWindowManager.HideWindow (this, CompletionWidget);
- CompletionWindowManager.HideWindow ();
- }
-
- void HandleFocusOutEvent (object o, Gtk.FocusOutEventArgs args)
- {
- ParameterInformationWindowManager.HideWindow (this, CompletionWidget);
- CompletionWindowManager.HideWindow ();
- }
+// void HandlePaste (int insertionOffset, string text, int insertedChars)
+// {
+// ParameterInformationWindowManager.HideWindow (this, CompletionWidget);
+// CompletionWindowManager.HideWindow ();
+// }
+//
+// void HandleFocusOutEvent (object o, Gtk.FocusOutEventArgs args)
+// {
+// ParameterInformationWindowManager.HideWindow (this, CompletionWidget);
+// CompletionWindowManager.HideWindow ();
+// }
- public override void Initialize ()
+ protected override void Initialize ()
{
base.Initialize ();
CompletionWindowManager.WindowClosed += HandleWindowClosed;
- CompletionWidget = Document.GetContent <ICompletionWidget> ();
+ CompletionWidget = DocumentContext.GetContent <ICompletionWidget> ();
if (CompletionWidget != null)
CompletionWidget.CompletionContextChanged += OnCompletionContextChanged;
- document.Editor.Caret.PositionChanged += HandlePositionChanged;
- document.Editor.Paste += HandlePaste;
- if (document.Editor.Parent != null)
- document.Editor.Parent.TextArea.FocusOutEvent += HandleFocusOutEvent;
+ Editor.CaretPositionChanged += HandlePositionChanged;
+// document.Editor.Paste += HandlePaste;
+// if (document.Editor.Parent != null)
+// document.Editor.Parent.TextArea.FocusOutEvent += HandleFocusOutEvent;
+ }
+
+ internal void InternalInitialize ()
+ {
+ Initialize ();
}
- void HandlePositionChanged (object sender, Mono.TextEditor.DocumentLocationEventArgs e)
+ void HandlePositionChanged (object sender, EventArgs e)
{
CompletionWindowManager.UpdateCursorPosition ();
}
@@ -488,10 +542,10 @@ namespace MonoDevelop.Ide.Gui.Content
ParameterInformationWindowManager.HideWindow (this, CompletionWidget);
disposed = true;
- if (document.Editor.Parent != null)
- document.Editor.Parent.TextArea.FocusOutEvent -= HandleFocusOutEvent;
- document.Editor.Paste -= HandlePaste;
- document.Editor.Caret.PositionChanged -= HandlePositionChanged;
+// if (document.Editor.Parent != null)
+// document.Editor.Parent.TextArea.FocusOutEvent -= HandleFocusOutEvent;
+// document.Editor.Paste -= HandlePaste;
+ Editor.CaretPositionChanged -= HandlePositionChanged;
CompletionWindowManager.WindowClosed -= HandleWindowClosed;
if (CompletionWidget != null)
CompletionWidget.CompletionContextChanged -= OnCompletionContextChanged;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/ParsedFileEventArgs.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/IQuickTaskProvider.cs
index 50300be800..62a4b236d4 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/ParsedFileEventArgs.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/IQuickTaskProvider.cs
@@ -1,10 +1,10 @@
//
-// ParsedFileEventArgs.cs
+// IQuickTaskProvider.cs
//
// Author:
-// Mike Krüger <mkrueger@novell.com>
+// Mike Krüger <mkrueger@xamarin.com>
//
-// Copyright (c) 2011 Mike Krüger <mkrueger@novell.com>
+// Copyright (c) 2012 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,20 +25,16 @@
// THE SOFTWARE.
using System;
-using ICSharpCode.NRefactory.TypeSystem;
+using System.Collections.Generic;
-namespace MonoDevelop.Ide.TypeSystem
+namespace MonoDevelop.Ide.Editor.Extension
{
- public class ParsedFileEventArgs : EventArgs
+ public interface IQuickTaskProvider
{
- public IUnresolvedFile File {
+ IEnumerable<QuickTask> QuickTasks {
get;
- private set;
- }
-
- public ParsedFileEventArgs (IUnresolvedFile file)
- {
- this.File = file;
}
+
+ event EventHandler TasksUpdated;
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/IndentationTracker.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/IndentationTracker.cs
new file mode 100644
index 0000000000..25e47fa9ad
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/IndentationTracker.cs
@@ -0,0 +1,40 @@
+//
+// IndentationTracker.cs
+//
+// Author:
+// Mike Krüger <mkrueger@xamarin.com>
+//
+// Copyright (c) 2012 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.Text;
+
+namespace MonoDevelop.Ide.Editor.Extension
+{
+ /// <summary>
+ /// The indentation tracker is for giving the editor information about virtual line indentations.
+ /// </summary>
+ public abstract class IndentationTracker
+ {
+ /// <summary>
+ /// Gets the indentation string for a given line.
+ /// </summary>
+ public abstract string GetIndentationString (int lineNumber);
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/KeyDescriptor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/KeyDescriptor.cs
new file mode 100644
index 0000000000..743364b33b
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/KeyDescriptor.cs
@@ -0,0 +1,222 @@
+//
+// KeyDescriptor.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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;
+#if MAC
+using AppKit;
+#endif
+
+namespace MonoDevelop.Ide.Editor.Extension
+{
+ public struct KeyDescriptor
+ {
+ public static KeyDescriptor Empty = new KeyDescriptor (SpecialKey.None, '\0', ModifierKeys.None);
+
+ public readonly SpecialKey SpecialKey;
+ public readonly char KeyChar;
+ public readonly ModifierKeys ModifierKeys;
+
+ KeyDescriptor (SpecialKey specialKey, char keyChar, ModifierKeys modifierKeys)
+ {
+ SpecialKey = specialKey;
+ KeyChar = keyChar;
+ ModifierKeys = modifierKeys;
+ }
+
+ public override string ToString ()
+ {
+ return string.Format ("[KeyDescriptor: SpecialKey={0}, KeyChar={1}, ModifierKeys={2}]", SpecialKey, KeyChar, ModifierKeys);
+ }
+
+ #region GTK
+ public static KeyDescriptor FromGtk (Gdk.Key key, char ch, Gdk.ModifierType state)
+ {
+ return new KeyDescriptor (ConvertKey (key), ch, ConvertModifiers (state));
+ }
+
+ static SpecialKey ConvertKey (Gdk.Key key)
+ {
+ switch (key) {
+ case Gdk.Key.BackSpace:
+ return SpecialKey.BackSpace;
+ case Gdk.Key.Tab:
+ case Gdk.Key.KP_Tab:
+ case Gdk.Key.ISO_Left_Tab:
+ return SpecialKey.Tab;
+ case Gdk.Key.Return:
+ case Gdk.Key.KP_Enter:
+ case Gdk.Key.ISO_Enter:
+ return SpecialKey.Return;
+ case Gdk.Key.Escape:
+ return SpecialKey.Escape;
+ case Gdk.Key.space:
+ case Gdk.Key.KP_Space:
+ return SpecialKey.Space;
+ case Gdk.Key.Page_Up:
+ case Gdk.Key.KP_Page_Up:
+ return SpecialKey.PageUp;
+ case Gdk.Key.Page_Down:
+ case Gdk.Key.KP_Page_Down:
+ return SpecialKey.PageDown;
+ case Gdk.Key.End:
+ case Gdk.Key.KP_End:
+ return SpecialKey.End;
+ case Gdk.Key.Begin:
+ case Gdk.Key.KP_Begin:
+ return SpecialKey.Begin;
+ case Gdk.Key.Home:
+ case Gdk.Key.KP_Home:
+ return SpecialKey.Home;
+ case Gdk.Key.Left:
+ case Gdk.Key.KP_Left:
+ return SpecialKey.Left;
+ case Gdk.Key.Up:
+ case Gdk.Key.KP_Up:
+ return SpecialKey.Up;
+ case Gdk.Key.Right:
+ case Gdk.Key.KP_Right:
+ return SpecialKey.Right;
+ case Gdk.Key.Down:
+ case Gdk.Key.KP_Down:
+ return SpecialKey.Down;
+ case Gdk.Key.Delete:
+ case Gdk.Key.KP_Delete:
+ return SpecialKey.Delete;
+ }
+ return SpecialKey.None;
+ }
+
+ static ModifierKeys ConvertModifiers (Gdk.ModifierType s)
+ {
+ ModifierKeys m = ModifierKeys.None;
+ if ((s & Gdk.ModifierType.ShiftMask) != 0)
+ m |= ModifierKeys.Shift;
+ if ((s & Gdk.ModifierType.ControlMask) != 0)
+ m |= ModifierKeys.Control;
+ if ((s & Gdk.ModifierType.Mod1Mask) != 0)
+ m |= ModifierKeys.Alt;
+ if ((s & Gdk.ModifierType.Mod2Mask) != 0)
+ m |= ModifierKeys.Command;
+ return m;
+ }
+ #endregion
+
+ #if MAC
+
+ public static KeyDescriptor FromMac (char ch, NSEventModifierMask state)
+ {
+ var specialKey = ConvertKey (ref ch);
+ var keyDescriptor = new KeyDescriptor (specialKey, ch, ConvertModifiers (state));
+ return keyDescriptor;
+ }
+
+ static SpecialKey ConvertKey (ref char ch)
+ {
+ if (ch == '\n' || ch == '\r') {
+ ch = '\0';
+ return SpecialKey.Return;
+ }
+ if (ch == '\t') {
+ ch = '\0';
+ return SpecialKey.Tab;
+ }
+ if (ch == '\b' || ch == (char)127) {
+ ch = '\0';
+ return SpecialKey.BackSpace;
+ }
+ if (ch == (char)27) {
+ ch = '\0';
+ return SpecialKey.Escape;
+ }
+ switch ((NSKey)ch) {
+ case NSKey.Delete:
+ ch = '\0';
+ return SpecialKey.BackSpace;
+ case NSKey.Tab:
+ ch = '\0';
+ return SpecialKey.Tab;
+ case NSKey.Return:
+ case NSKey.KeypadEnter:
+ ch = '\0';
+ return SpecialKey.Return;
+ case NSKey.Escape:
+ ch = '\0';
+ return SpecialKey.Escape;
+ case NSKey.Space:
+ ch = '\0';
+ return SpecialKey.Space;
+ case NSKey.PageUp:
+ ch = '\0';
+ return SpecialKey.PageUp;
+ case NSKey.PageDown:
+ ch = '\0';
+ return SpecialKey.PageDown;
+ case NSKey.End:
+ ch = '\0';
+ return SpecialKey.End;
+ case NSKey.Begin:
+ ch = '\0';
+ return SpecialKey.Begin;
+ case NSKey.Home:
+ ch = '\0';
+ return SpecialKey.Home;
+ case NSKey.LeftArrow:
+ ch = '\0';
+ return SpecialKey.Left;
+ case NSKey.UpArrow:
+ ch = '\0';
+ return SpecialKey.Up;
+ case NSKey.RightArrow:
+ ch = '\0';
+ return SpecialKey.Right;
+ case NSKey.DownArrow:
+ ch = '\0';
+ return SpecialKey.Down;
+ case NSKey.DeleteChar:
+ ch = '\0';
+ return SpecialKey.Delete;
+ }
+ return SpecialKey.None;
+ }
+
+
+
+ static ModifierKeys ConvertModifiers (NSEventModifierMask e)
+ {
+ var m = ModifierKeys.None;
+ if ((e & NSEventModifierMask.ControlKeyMask) != 0)
+ m |= ModifierKeys.Control;
+ if ((e & NSEventModifierMask.AlternateKeyMask) != 0)
+ m |= ModifierKeys.Alt;
+ if ((e & NSEventModifierMask.CommandKeyMask) != 0)
+ m |= ModifierKeys.Command;
+ if ((e & NSEventModifierMask.ShiftKeyMask) != 0)
+ m |= ModifierKeys.Shift;
+ return m;
+ }
+ #endif
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/ModifierKeys.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/ModifierKeys.cs
new file mode 100644
index 0000000000..4b902cdf0f
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/ModifierKeys.cs
@@ -0,0 +1,40 @@
+//
+// ModifierKeys.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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;
+
+namespace MonoDevelop.Ide.Editor.Extension
+{
+ [Flags]
+ public enum ModifierKeys
+ {
+ None = 0,
+ Alt = 0x1 << 0,
+ Control = 0x1 << 1,
+ Shift = 0x1 << 2,
+ Command = 0x1 << 3
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/QuickTask.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/QuickTask.cs
new file mode 100644
index 0000000000..96162525b1
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/QuickTask.cs
@@ -0,0 +1,76 @@
+//
+// QuickTask.cs
+//
+// Author:
+// Mike Krüger <mkrueger@xamarin.com>
+//
+// Copyright (c) 2012 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 Gtk;
+using System.Collections.Generic;
+using Gdk;
+using MonoDevelop.Core;
+using MonoDevelop.Ide;
+using MonoDevelop.Components.Commands;
+using Microsoft.CodeAnalysis;
+
+namespace MonoDevelop.Ide.Editor.Extension
+{
+ public sealed class QuickTask
+ {
+ Lazy<string> description;
+ public string Description {
+ get {
+ return description.Value;
+ }
+ }
+
+ public int Location {
+ get;
+ private set;
+ }
+
+ public DiagnosticSeverity Severity {
+ get;
+ private set;
+ }
+
+ public QuickTask (Func<string> descriptionFunc, int location, DiagnosticSeverity severity)
+ {
+ this.description = new Lazy<string> (descriptionFunc);
+ this.Location = location;
+ this.Severity = severity;
+ }
+
+ public QuickTask (string description, int location, DiagnosticSeverity severity)
+ {
+ this.description = new Lazy<string> (() => description);
+ this.Location = location;
+ this.Severity = severity;
+ }
+
+ public override string ToString ()
+ {
+ return string.Format ("[QuickTask: Description={0}, Location={1}, Severity={2}]", Description, Location, Severity);
+ }
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/SelectionSurroundingProvider.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/SelectionSurroundingProvider.cs
new file mode 100644
index 0000000000..903e05a6ba
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/SelectionSurroundingProvider.cs
@@ -0,0 +1,57 @@
+//
+// ISelectionSurroundingProvider.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Components.PropertyGrid.PropertyEditors;
+
+namespace MonoDevelop.Ide.Editor.Extension
+{
+ /// <summary>
+ /// A selection surrounding provider handles a special handling how the text editor behaves when the user
+ /// types a key with a selection. The selection can be surrounded instead of beeing replaced.
+ /// </summary>
+ public abstract class SelectionSurroundingProvider
+ {
+ /// <summary>
+ /// Gets the selection surroundings for a given unicode key.
+ /// </summary>
+ /// <returns>
+ /// true, if the key is valid for a surrounding action.
+ /// </returns>
+ /// <param name='unicodeKey'>
+ /// The key to handle.
+ /// </param>
+ /// <param name='start'>
+ /// The start of the surrounding
+ /// </param>
+ /// <param name='end'>
+ /// The end of the surrounding
+ /// </param>
+ public abstract bool GetSelectionSurroundings (uint unicodeKey, out string start, out string end);
+
+ public abstract void HandleSpecialSelectionKey (uint unicodeKey);
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/SpecialKey.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/SpecialKey.cs
new file mode 100644
index 0000000000..5157fec2b5
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/SpecialKey.cs
@@ -0,0 +1,49 @@
+//
+// SpecialKey.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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;
+
+namespace MonoDevelop.Ide.Editor.Extension
+{
+ public enum SpecialKey
+ {
+ None,
+ BackSpace = 0xff08,
+ Tab = 0xff09,
+ Return = 0xff0d,
+ Escape = 0xff1b,
+ Space = 0x20,
+ PageUp = 0xff55,
+ PageDown = 0xff56,
+ End = 0xff57,
+ Begin = 0xff58,
+ Home = 0xff50,
+ Left = 0xff51,
+ Up = 0xff52,
+ Right = 0xff53,
+ Down = 0xff54,
+ Delete = 0xffff
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/TextEditorExtension.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/TextEditorExtension.cs
new file mode 100644
index 0000000000..6dcb523e19
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/TextEditorExtension.cs
@@ -0,0 +1,107 @@
+//
+// AbstractEditorExtension.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Components.Commands;
+using MonoDevelop.Core;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Ide.Gui;
+using MonoDevelop.Ide.TypeSystem;
+
+namespace MonoDevelop.Ide.Editor.Extension
+{
+ public abstract class TextEditorExtension : ICommandRouter, IDisposable
+ {
+ public DocumentContext DocumentContext {
+ get;
+ protected set;
+ }
+
+ public TextEditor Editor {
+ get;
+ protected set;
+ }
+
+ internal TextEditorExtension Next {
+ get;
+ set;
+ }
+
+ protected internal void Initialize (TextEditor editor, DocumentContext context)
+ {
+ if (editor == null)
+ throw new ArgumentNullException ("editor");
+ if (context == null)
+ throw new ArgumentNullException ("context");
+ if (DocumentContext != null)
+ throw new InvalidOperationException ("Extension is already initialized.");
+ DocumentContext = context;
+ Editor = editor;
+ Initialize ();
+ }
+
+ protected virtual void Initialize ()
+ {
+ }
+
+ public virtual bool IsValidInContext (DocumentContext context)
+ {
+ return true;
+ }
+
+ /// <summary>
+ /// Return true if the key press should be processed by the editor.
+ /// When a key is pressed, and before the key is processed by the editor, this method will be invoked.
+ /// </summary>
+ public virtual bool KeyPress (KeyDescriptor descriptor)
+ {
+ return Next == null || Next.KeyPress (descriptor);
+ }
+
+ public virtual void Dispose ()
+ {
+ }
+
+ void CheckInitialized ()
+ {
+ if (DocumentContext == null)
+ throw new InvalidOperationException ("Editor extension not yet initialized");
+ }
+
+ object ICommandRouter.GetNextCommandTarget ()
+ {
+ return Next;
+ }
+ }
+
+ class TextEditorExtensionMarker : TextEditorExtension
+ {
+ public override bool IsValidInContext (DocumentContext context)
+ {
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/TextPasteHandler.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/TextPasteHandler.cs
new file mode 100644
index 0000000000..ee3518ecc0
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/TextPasteHandler.cs
@@ -0,0 +1,64 @@
+//
+// TextPasteHandler.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Core.Text;
+
+namespace MonoDevelop.Ide.Editor.Extension
+{
+ /// <summary>
+ /// The text paste handler can do formattings to a text that is about to be pasted
+ /// into the text document.
+ /// </summary>
+ public abstract class TextPasteHandler
+ {
+ /// <summary>
+ /// Formats plain text that is inserted at a specified offset.
+ /// </summary>
+ /// <returns>
+ /// The text that will get inserted at that position.
+ /// </returns>
+ /// <param name="offset">The offset where the text will be inserted.</param>
+ /// <param name="text">The text to be inserted.</param>
+ /// <param name="copyData">Additional data in case the text was copied from a Mono.TextEditor.</param>
+ public abstract string FormatPlainText(int offset, string text, byte[] copyData);
+
+ /// <summary>
+ /// Gets the copy data for a specific segment inside the document. This can contain meta data about the text pasted.
+ /// For example 'text pasted from string'.
+ /// </summary>
+ /// <param name = "offset">The copy offset.</param>
+ /// <param name = "length">The length of the copied text.</param>
+ public abstract byte[] GetCopyData(int offset, int length);
+
+ /// <summary>
+ /// This is called after text was pasted. This is useful for creating an additional undo step for the paste command.
+ /// </summary>
+ /// <param name="offset">The offset the text was pasted at.</param>
+ /// <param name="length">The length of the text pasted.</param>
+ public abstract void PostFomatPastedText (int offset, int length);
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/Usage.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/Usage.cs
new file mode 100644
index 0000000000..ea8dade4d3
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/Usage.cs
@@ -0,0 +1,49 @@
+//
+// IUsageProvider.cs
+//
+// Author:
+// Mike Krüger <mkrueger@xamarin.com>
+//
+// Copyright (c) 2012 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 System.Collections.Generic;
+using ICSharpCode.NRefactory;
+using MonoDevelop.Core.Text;
+using MonoDevelop.Ide.FindInFiles;
+
+namespace MonoDevelop.Ide.Editor.Extension
+{
+ public sealed class Usage : AbstractSegment
+ {
+ public readonly ReferenceUsageType UsageType;
+
+ public Usage (TextSegment segment, ReferenceUsageType usageType) : base (segment.Offset, segment.Length)
+ {
+ UsageType = usageType;
+ }
+
+ public Usage (int offset, int length, ReferenceUsageType usageType) : base (offset, length)
+ {
+ UsageType = usageType;
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/AmbientColor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/AmbientColor.cs
new file mode 100644
index 0000000000..b65a66a3de
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/AmbientColor.cs
@@ -0,0 +1,188 @@
+//
+// AmbientColor.cs
+//
+// Author:
+// Mike Krüger <mkrueger@xamarin.com>
+//
+// Copyright (c) 2013 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 System.IO;
+using System.Collections.Generic;
+using System.Linq;
+using System.Xml.Linq;
+using System.Xml.XPath;
+using System.Reflection;
+using MonoDevelop.Components;
+
+namespace MonoDevelop.Ide.Editor.Highlighting
+{
+ public sealed class AmbientColor
+ {
+ public string Name { get; private set; }
+ public readonly List<Tuple<string, HslColor>> Colors = new List<Tuple<string, HslColor>> ();
+
+ public HslColor Color {
+ get {
+ return GetColor ("color");
+ }
+ set {
+ for (int i = 0; i < Colors.Count; i++) {
+ var t = Colors [i];
+ if (t.Item1 == "color") {
+ Colors [i] = Tuple.Create ("color", value);
+ return;
+ }
+ }
+ Colors.Add (Tuple.Create ("color", value));
+ }
+ }
+
+ public HslColor SecondColor {
+ get {
+ return GetColor ("secondcolor");
+ }
+ set {
+ for (int i = 0; i < Colors.Count; i++) {
+ var t = Colors [i];
+ if (t.Item1 == "secondcolor") {
+ Colors [i] = Tuple.Create ("secondcolor", value);
+ return;
+ }
+ }
+ Colors.Add (Tuple.Create ("secondcolor", value));
+ }
+ }
+
+ public bool HasSecondColor {
+ get {
+ return Colors.Any (c => c.Item1 == "secondcolor");
+ }
+ }
+
+ public HslColor BorderColor {
+ get {
+ return GetColor ("bordercolor");
+ }
+ set {
+ for (int i = 0; i < Colors.Count; i++) {
+ var t = Colors [i];
+ if (t.Item1 == "bordercolor") {
+ Colors [i] = Tuple.Create ("bordercolor", value);
+ return;
+ }
+ }
+ Colors.Add (Tuple.Create ("bordercolor", value));
+ }
+ }
+
+ public bool HasBorderColor {
+ get {
+ return Colors.Any (c => c.Item1 == "bordercolor");
+ }
+ }
+
+ public HslColor GetColor (string name)
+ {
+ foreach (var color in Colors) {
+ if (color.Item1 == name)
+ return color.Item2;
+ }
+
+ return new HslColor (0, 0, 0);
+ }
+
+ public static AmbientColor Create (XElement element, Dictionary<string, HslColor> palette)
+ {
+ var result = new AmbientColor ();
+ foreach (var node in element.DescendantNodes ()) {
+ if (node.NodeType == System.Xml.XmlNodeType.Element) {
+ var el = (XElement)node;
+ switch (el.Name.LocalName) {
+ case "name":
+ result.Name = el.Value;
+ break;
+ default:
+ result.Colors.Add (Tuple.Create (el.Name.LocalName, ColorScheme.ParsePaletteColor (palette, el.Value)));
+ break;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ public override bool Equals (object obj)
+ {
+ if (obj == null)
+ return false;
+ if (ReferenceEquals (this, obj))
+ return true;
+ if (obj.GetType () != typeof(AmbientColor))
+ return false;
+ AmbientColor other = (AmbientColor)obj;
+ return Colors.Equals (other.Colors) && Name == other.Name;
+ }
+
+ public override int GetHashCode ()
+ {
+ unchecked {
+ return (Colors != null ? Colors.GetHashCode () : 0) ^ (Name != null ? Name.GetHashCode () : 0);
+ }
+ }
+
+
+ public static AmbientColor Import (Dictionary<string, ColorScheme.VSSettingColor> colors, string vsSetting)
+ {
+ var result = new AmbientColor ();
+ var attrs = vsSetting.Split (',');
+ foreach (var attr in attrs) {
+ var info = attr.Split ('=');
+ if (info.Length != 2)
+ continue;
+ var idx = info [1].LastIndexOf ('/');
+ var source = info [1].Substring (0, idx);
+ var dest = info [1].Substring (idx + 1);
+
+ ColorScheme.VSSettingColor color;
+ if (!colors.TryGetValue (source, out color))
+ continue;
+ result.Name = color.Name;
+ string colorString;
+ switch (dest) {
+ case "Foreground":
+ colorString = color.Foreground;
+ break;
+ case "Background":
+ colorString = color.Background;
+ break;
+ default:
+ throw new InvalidDataException ("Invalid attribute source: " + dest);
+ }
+ result.Colors.Add (Tuple.Create (info [0], ColorScheme.ImportVsColor (colorString)));
+ }
+ if (result.Colors.Count == 0)
+ return null;
+ return result;
+ }
+ }
+
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/ChunkStyle.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/ChunkStyle.cs
new file mode 100644
index 0000000000..bed02ad91d
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/ChunkStyle.cs
@@ -0,0 +1,186 @@
+//
+// ChunkStyle.cs
+//
+// Author:
+// Mike Krüger <mkrueger@xamarin.com>
+//
+// Copyright (c) 2013 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 System.IO;
+using System.Collections.Generic;
+using System.Xml.Linq;
+using MonoDevelop.Components;
+
+namespace MonoDevelop.Ide.Editor.Highlighting
+{
+ public sealed class ChunkStyle
+ {
+ public string Name { get; set; }
+ public HslColor Foreground { get; set; }
+ public HslColor Background { get; set; }
+
+ public bool TransparentForeground {
+ get {
+ return Foreground.Alpha == 0.0;
+
+ }
+ }
+ public bool TransparentBackground {
+ get {
+ return Background.Alpha == 0.0;
+ }
+ }
+
+ public Xwt.Drawing.FontWeight FontWeight { get; set; }
+
+ public Xwt.Drawing.FontStyle FontStyle { get; set; }
+
+ [Obsolete("Will be removed - use FontWeight")]
+ public bool Bold {
+ get {
+ return FontWeight == Xwt.Drawing.FontWeight.Bold;
+ }
+ }
+
+ [Obsolete("Will be removed - use FontStyle")]
+ public bool Italic {
+ get {
+ return FontStyle == Xwt.Drawing.FontStyle.Italic;
+ }
+ }
+
+ public bool Underline {
+ get; set;
+ }
+
+ public ChunkStyle ()
+ {
+ Foreground = Background = new HslColor (0, 0, 0, 0);
+ FontWeight = Xwt.Drawing.FontWeight.Normal;
+ FontStyle = Xwt.Drawing.FontStyle.Normal;
+ }
+
+ public ChunkStyle (ChunkStyle baseStyle)
+ {
+ this.Name = baseStyle.Name;
+ this.Foreground = baseStyle.Foreground;
+ this.Background = baseStyle.Background;
+ this.FontWeight = baseStyle.FontWeight;
+ this.FontStyle = baseStyle.FontStyle;
+ this.Underline = baseStyle.Underline;
+ }
+
+ public override bool Equals (object obj)
+ {
+ if (obj == null)
+ return false;
+ if (ReferenceEquals (this, obj))
+ return true;
+ if (obj.GetType () != typeof(ChunkStyle))
+ return false;
+ ChunkStyle other = (ChunkStyle)obj;
+ return Name == other.Name && Foreground.Equals (other.Foreground) && Background.Equals (other.Background) && FontWeight == other.FontWeight && FontStyle == other.FontStyle;
+ }
+
+ public override int GetHashCode ()
+ {
+ unchecked {
+ return (Name != null ? Name.GetHashCode () : 0) ^ Foreground.GetHashCode () ^ Background.GetHashCode () ^ FontWeight.GetHashCode () ^ FontStyle.GetHashCode ();
+ }
+ }
+
+ public static ChunkStyle Create (XElement element, Dictionary<string, HslColor> palette)
+ {
+ var result = new ChunkStyle ();
+
+ foreach (var node in element.DescendantNodes ()) {
+ if (node.NodeType == System.Xml.XmlNodeType.Element) {
+ var el = (XElement)node;
+ switch (el.Name.LocalName) {
+ case "name":
+ result.Name = el.Value;
+ break;
+ case "fore":
+ result.Foreground = ColorScheme.ParsePaletteColor (palette, el.Value);
+ break;
+ case "back":
+ result.Background = ColorScheme.ParsePaletteColor (palette, el.Value);
+ break;
+ case "weight":
+ Xwt.Drawing.FontWeight weight;
+ if (!Enum.TryParse<Xwt.Drawing.FontWeight> (el.Value, true, out weight))
+ throw new InvalidDataException (el.Value + " is no valid text weight values are: " + string.Join (",", Enum.GetNames (typeof(Xwt.Drawing.FontWeight))) );
+ result.FontWeight = weight;
+ break;
+ case "style":
+ Xwt.Drawing.FontStyle style;
+ if (!Enum.TryParse<Xwt.Drawing.FontStyle> (el.Value, true, out style))
+ throw new InvalidDataException (el.Value + " is no valid text weight values are: " + string.Join (",", Enum.GetNames (typeof(Xwt.Drawing.FontStyle))) );
+ result.FontStyle = style;
+ break;
+ default:
+ throw new InvalidDataException ("Invalid element in text color:" + el.Name);
+ }
+ }
+ }
+
+ return result;
+ }
+
+ public Gdk.GC CreateBgGC (Gdk.Drawable drawable)
+ {
+ return new Gdk.GC (drawable) { RgbBgColor = (HslColor)Foreground, RgbFgColor = (HslColor)Background };
+ }
+
+ public Gdk.GC CreateFgGC (Gdk.Drawable drawable)
+ {
+ return new Gdk.GC (drawable) { RgbBgColor = (HslColor)Background, RgbFgColor = (HslColor)Foreground };
+ }
+
+ public override string ToString ()
+ {
+ return string.Format ("[ChunkStyle: Name={0}, CairoColor={1}, CairoBackgroundColor={2}, FontWeight={3}, FontStyle={4}]", Name, Foreground, Background, FontWeight, FontStyle);
+ }
+
+ public static ChunkStyle Import (string name, ColorScheme.VSSettingColor vsc)
+ {
+ var textColor = new ChunkStyle ();
+ textColor.Name = name;
+ if (!string.IsNullOrEmpty (vsc.Foreground) && vsc.Foreground != "0x02000000") {
+ textColor.Foreground = ColorScheme.ImportVsColor (vsc.Foreground);
+ if (textColor.TransparentForeground && name != "Selected Text" && name != "Selected Text(Inactive)")
+ textColor.Foreground = new HslColor (0, 0, 0);
+ }
+ if (!string.IsNullOrEmpty (vsc.Background) && vsc.Background != "0x02000000")
+ textColor.Background = ColorScheme.ImportVsColor (vsc.Background);
+ if (vsc.BoldFont)
+ textColor.FontWeight = Xwt.Drawing.FontWeight.Bold;
+ return textColor;
+ }
+
+ public ChunkStyle Clone ()
+ {
+ return (ChunkStyle)this.MemberwiseClone ();
+ }
+ }
+
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/PreProcessorDefine.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/ColorDescriptionAttribute.cs
index 45f3b48a2d..d69e2013c9 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/PreProcessorDefine.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/ColorDescriptionAttribute.cs
@@ -1,9 +1,10 @@
-// PreProcessorDefine.cs
+//
+// ColorDescriptionAttribute.cs
//
// Author:
-// Mike Krüger <mkrueger@novell.com>
+// Mike Krüger <mkrueger@xamarin.com>
//
-// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
+// Copyright (c) 2013 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
@@ -22,37 +23,25 @@
// 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.NRefactory;
-namespace MonoDevelop.Ide.TypeSystem
+namespace MonoDevelop.Ide.Editor.Highlighting
{
- public class PreProcessorDefine
+ public sealed class ColorDescriptionAttribute : Attribute
{
- public string Define {
- get;
- set;
- }
-
- public TextLocation Location {
- get;
- set;
- }
-
- public PreProcessorDefine ()
- {
- }
-
- public PreProcessorDefine (string define, TextLocation location)
+ public string Name { get; private set; }
+ public string Description { get; set; }
+ public string VSSetting { get; set; }
+
+ public ColorDescriptionAttribute (string name)
{
- this.Define = define;
- this.Location = location;
+ Name = name;
}
-
+
public override string ToString ()
{
- return string.Format ("[PreProcessorDefine: Define={0}, Location={1}]", Define, Location);
+ return string.Format ("[ColorDescriptionAttribute: Name={0}, Description={1}, VSSetting={2}]", Name, Description, VSSetting);
}
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/ColorScheme.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/ColorScheme.cs
new file mode 100644
index 0000000000..6714d9abe9
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/ColorScheme.cs
@@ -0,0 +1,1030 @@
+//
+// ColorScheme.cs
+//
+// Author:
+// Mike Krüger <mkrueger@xamarin.com>
+//
+// Copyright (c) 2013 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 System.IO;
+using System.Collections.Generic;
+using System.Linq;
+using System.Xml.Linq;
+using System.Xml.XPath;
+using System.Reflection;
+using System.Text;
+using System.Xml;
+using MonoDevelop.Components;
+
+namespace MonoDevelop.Ide.Editor.Highlighting
+{
+ public sealed class ColorScheme
+ {
+ public string Name { get; set; }
+ public string Description { get; set; }
+ public string Originator { get; set; }
+ public string BaseScheme { get; set; }
+ public string FileName { get; set; }
+
+ #region Ambient Colors
+
+ [ColorDescription("Background(Read Only)",VSSetting="color=Plain Text/Background")]
+ public AmbientColor BackgroundReadOnly { get; private set; }
+
+ [ColorDescription("Search result background")]
+ public AmbientColor SearchResult { get; private set; }
+
+ [ColorDescription("Search result background (highlighted)")]
+ public AmbientColor SearchResultMain { get; private set; }
+
+ [ColorDescription("Fold Square", VSSetting="color=outlining.verticalrule/Foreground")]
+ public AmbientColor FoldLineColor { get; private set; }
+
+ [ColorDescription("Fold Cross", VSSetting="color=outlining.square/Foreground,secondcolor=outlining.square/Background")]
+ public AmbientColor FoldCross { get; private set; }
+
+ [ColorDescription("Indentation Guide")] // not defined
+ public AmbientColor IndentationGuide { get; private set; }
+
+ [ColorDescription("Indicator Margin", VSSetting="color=Indicator Margin/Background")]
+ public AmbientColor IndicatorMargin { get; private set; }
+
+ [ColorDescription("Indicator Margin(Separator)", VSSetting="color=Indicator Margin/Background")]
+ public AmbientColor IndicatorMarginSeparator { get; private set; }
+
+ [ColorDescription("Tooltip Border")]
+ public AmbientColor TooltipBorder { get; private set; }
+
+ [ColorDescription("Tooltip Pager Top")]
+ public AmbientColor TooltipPagerTop { get; private set; }
+
+ [ColorDescription("Tooltip Pager Bottom")]
+ public AmbientColor TooltipPagerBottom { get; private set; }
+
+ [ColorDescription("Tooltip Pager Triangle")]
+ public AmbientColor TooltipPagerTriangle { get; private set; }
+
+ [ColorDescription("Tooltip Pager Text")]
+ public AmbientColor TooltipPagerText { get; private set; }
+
+ [ColorDescription("Notification Border")]
+ public AmbientColor NotificationBorder { get; private set; }
+
+ [ColorDescription("Bookmarks")]
+ public AmbientColor Bookmarks { get; private set; }
+
+ [ColorDescription("Underline(Error)", VSSetting="color=Syntax Error/Foreground")]
+ public AmbientColor UnderlineError { get; private set; }
+
+ [ColorDescription("Underline(Warning)", VSSetting="color=Warning/Foreground")]
+ public AmbientColor UnderlineWarning { get; private set; }
+
+ [ColorDescription("Underline(Suggestion)", VSSetting="color=Other Error/Foreground")]
+ public AmbientColor UnderlineSuggestion { get; private set; }
+
+ [ColorDescription("Underline(Hint)", VSSetting="color=Other Error/Foreground")]
+ public AmbientColor UnderlineHint { get; private set; }
+
+ [ColorDescription("Quick Diff(Dirty)")]
+ public AmbientColor QuickDiffDirty { get; private set; }
+
+ [ColorDescription("Quick Diff(Changed)")]
+ public AmbientColor QuickDiffChanged { get; private set; }
+
+ [ColorDescription("Brace Matching(Rectangle)", VSSetting="color=Brace Matching (Rectangle)/Background,secondcolor=Brace Matching (Rectangle)/Foreground")]
+ public AmbientColor BraceMatchingRectangle { get; private set; }
+
+ [ColorDescription("Usages(Rectangle)", VSSetting="color=MarkerFormatDefinition/HighlightedReference/Background,secondcolor=MarkerFormatDefinition/HighlightedReference/Background,bordercolor=MarkerFormatDefinition/HighlightedReference/Background")]
+ public AmbientColor UsagesRectangle { get; private set; }
+
+ [ColorDescription("Changing usages(Rectangle)", VSSetting="color=MarkerFormatDefinition/HighlightedReference/Background,secondcolor=MarkerFormatDefinition/HighlightedReference/Background,bordercolor=MarkerFormatDefinition/HighlightedReference/Background")]
+ public AmbientColor ChangingUsagesRectangle { get; private set; }
+
+ [ColorDescription("Breakpoint Marker", VSSetting = "color=Breakpoint (Enabled)/Background")]
+ public AmbientColor BreakpointMarker { get; private set; }
+
+ [ColorDescription("Breakpoint Marker(Invalid)", VSSetting = "color=Breakpoint (Disabled)/Background")]
+ public AmbientColor BreakpointMarkerInvalid { get; private set; }
+
+ [ColorDescription("Breakpoint Marker(Disabled)")]
+ public AmbientColor BreakpointMarkerDisabled { get; private set; }
+
+ [ColorDescription("Debugger Current Line Marker", VSSetting = "color=Current Statement/Background")]
+ public AmbientColor DebuggerCurrentLineMarker { get; private set; }
+
+ [ColorDescription("Debugger Stack Line Marker")]
+ public AmbientColor DebuggerStackLineMarker { get; private set; }
+
+ [ColorDescription("Primary Link", VSSetting = "color=Refactoring Dependent Field/Background" )]
+ public AmbientColor PrimaryTemplate { get; private set; }
+
+ [ColorDescription("Primary Link(Highlighted)", VSSetting = "color=Refactoring Current Field/Background")]
+ public AmbientColor PrimaryTemplateHighlighted { get; private set; }
+
+ [ColorDescription("Secondary Link")] // not defined
+ public AmbientColor SecondaryTemplate { get; private set; }
+
+ [ColorDescription("Secondary Link(Highlighted)")] // not defined
+ public AmbientColor SecondaryTemplateHighlighted { get; private set; }
+
+ [ColorDescription("Current Line Marker", VSSetting = "color=CurrentLineActiveFormat/Background,secondcolor=CurrentLineActiveFormat/Foreground")]
+ public AmbientColor LineMarker { get; private set; }
+
+ [ColorDescription("Current Line Marker(Inactive)", VSSetting = "color=CurrentLineInactiveFormat/Background,secondcolor=CurrentLineInactiveFormat/Foreground")]
+ public AmbientColor LineMarkerInactive { get; private set; }
+
+ [ColorDescription("Column Ruler")] // not defined
+ public AmbientColor Ruler { get; private set; }
+
+ [ColorDescription("Completion Matching Substring")]
+ public AmbientColor CompletionHighlight { get; private set; }
+
+ [ColorDescription("Completion Border")]
+ public AmbientColor CompletionBorder { get; private set; }
+
+ [ColorDescription("Completion Border(Inactive)")]
+ public AmbientColor CompletionInactiveBorder { get; private set; }
+
+ [ColorDescription("Message Bubble Error Marker")]
+ public AmbientColor MessageBubbleErrorMarker { get; private set; }
+
+ [ColorDescription("Message Bubble Error Tag")]
+ public AmbientColor MessageBubbleErrorTag { get; private set; }
+
+ [ColorDescription("Message Bubble Error Tooltip")]
+ public AmbientColor MessageBubbleErrorTooltip { get; private set; }
+
+ [ColorDescription("Message Bubble Error Line")]
+ public AmbientColor MessageBubbleErrorLine { get; private set; }
+
+ [ColorDescription("Message Bubble Error Counter")]
+ public AmbientColor MessageBubbleErrorCounter { get; private set; }
+
+ [ColorDescription("Message Bubble Error IconMargin")]
+ public AmbientColor MessageBubbleErrorIconMargin { get; private set; }
+
+ [ColorDescription("Message Bubble Warning Marker")]
+ public AmbientColor MessageBubbleWarningMarker { get; private set; }
+
+ [ColorDescription("Message Bubble Warning Tag")]
+ public AmbientColor MessageBubbleWarningTag { get; private set; }
+
+ [ColorDescription("Message Bubble Warning Tooltip")]
+ public AmbientColor MessageBubbleWarningTooltip { get; private set; }
+
+ [ColorDescription("Message Bubble Warning Line")]
+ public AmbientColor MessageBubbleWarningLine { get; private set; }
+
+ [ColorDescription("Message Bubble Warning Counter")]
+ public AmbientColor MessageBubbleWarningCounter { get; private set; }
+
+ [ColorDescription("Message Bubble Warning IconMargin")]
+ public AmbientColor MessageBubbleWarningIconMargin { get; private set; }
+
+ #endregion
+
+ #region Text Colors
+
+ public const string PlainTextKey = "Plain Text";
+
+ [ColorDescription(PlainTextKey, VSSetting = "Plain Text")]
+ public ChunkStyle PlainText { get; private set; }
+
+ public const string SelectedTextKey = "Selected Text";
+ [ColorDescription(SelectedTextKey, VSSetting = "Selected Text")]
+ public ChunkStyle SelectedText { get; private set; }
+
+ public const string SelectedInactiveTextKey = "Selected Text(Inactive)";
+ [ColorDescription(SelectedInactiveTextKey, VSSetting = "Inactive Selected Text")]
+ public ChunkStyle SelectedInactiveText { get; private set; }
+
+ public const string CollapsedTextKey = "Collapsed Text";
+ [ColorDescription(CollapsedTextKey, VSSetting = "Collapsible Text")]
+ public ChunkStyle CollapsedText { get; private set; }
+
+ public const string LineNumbersKey = "Line Numbers";
+ [ColorDescription(LineNumbersKey, VSSetting = "Line Numbers")]
+ public ChunkStyle LineNumbers { get; private set; }
+
+ public const string PunctuationKey = "Punctuation";
+ [ColorDescription(PunctuationKey, VSSetting = "Operator")]
+ public ChunkStyle Punctuation { get; private set; }
+
+ public const string PunctuationForBracketsKey = "Punctuation(Brackets)";
+ [ColorDescription(PunctuationForBracketsKey, VSSetting = "Plain Text")]
+ public ChunkStyle PunctuationForBrackets { get; private set; }
+
+ public const string CommentsSingleLineKey = "Comment(Line)";
+ [ColorDescription(CommentsSingleLineKey, VSSetting = "Comment")]
+ public ChunkStyle CommentsSingleLine { get; private set; }
+
+ public const string CommentsBlockKey = "Comment(Block)";
+ [ColorDescription(CommentsBlockKey, VSSetting = "Comment")]
+ public ChunkStyle CommentsBlock { get; private set; }
+
+ public const string CommentsForDocumentationKey = "Comment(Doc)";
+ [ColorDescription(CommentsForDocumentationKey, VSSetting = "XML Doc Comment")]
+ public ChunkStyle CommentsForDocumentation { get; private set; }
+
+ public const string CommentsForDocumentationTagsKey = "Comment(DocTag)";
+ [ColorDescription(CommentsForDocumentationTagsKey, VSSetting = "XML Doc Tag")]
+ public ChunkStyle CommentsForDocumentationTags { get; private set; }
+
+ public const string CommentTagsKey = "Comment Tag";
+ [ColorDescription(CommentTagsKey, VSSetting = "Comment")]
+ public ChunkStyle CommentTags { get; private set; }
+
+ public const string ExcludedCodeKey = "Excluded Code";
+ [ColorDescription(ExcludedCodeKey, VSSetting = "Excluded Code")]
+ public ChunkStyle ExcludedCode { get; private set; }
+
+ public const string StringKey = "String";
+ [ColorDescription(StringKey, VSSetting = "String")]
+ public ChunkStyle String { get; private set; }
+
+ public const string StringEscapeSequenceKey = "String(Escape)";
+ [ColorDescription(StringEscapeSequenceKey, VSSetting = "String")]
+ public ChunkStyle StringEscapeSequence { get; private set; }
+
+ public const string StringVerbatimKey = "String(C# @ Verbatim)";
+ [ColorDescription(StringVerbatimKey, VSSetting = "String(C# @ Verbatim)")]
+ public ChunkStyle StringVerbatim { get; private set; }
+
+ public const string NumberKey = "Number";
+ [ColorDescription(NumberKey, VSSetting = "Number")]
+ public ChunkStyle Number { get; private set; }
+
+ public const string PreprocessorKey = "Preprocessor";
+ [ColorDescription(PreprocessorKey, VSSetting = "Preprocessor Keyword")]
+ public ChunkStyle Preprocessor { get; private set; }
+
+ public const string PreprocessorRegionNameKey = "Preprocessor(Region Name)";
+ [ColorDescription(PreprocessorRegionNameKey, VSSetting = "Plain Text")]
+ public ChunkStyle PreprocessorRegionName { get; private set; }
+
+ public const string XmlTextKey = "Xml Text";
+ [ColorDescription(XmlTextKey, VSSetting = "XML Text")]
+ public ChunkStyle XmlText { get; private set; }
+
+ public const string XmlDelimiterKey = "Xml Delimiter";
+ [ColorDescription(XmlDelimiterKey, VSSetting = "XML Delimiter")]
+ public ChunkStyle XmlDelimiter { get; private set; }
+
+ public const string XmlNameKey = "Xml Name";
+ [ColorDescription(XmlNameKey, VSSetting ="XML Name")]
+ public ChunkStyle XmlName { get; private set; }
+
+ public const string XmlAttributeKey = "Xml Attribute";
+ [ColorDescription(XmlAttributeKey, VSSetting = "XML Attribute")]
+ public ChunkStyle XmlAttribute { get; private set; }
+
+ public const string XmlAttributeQuotesKey = "Xml Attribute Quotes";
+ [ColorDescription(XmlAttributeQuotesKey, VSSetting = "XML Attribute Quotes")]
+ public ChunkStyle XmlAttributeQuotes { get; private set; }
+
+ public const string XmlAttributeValueKey = "Xml Attribute Value";
+ [ColorDescription(XmlAttributeValueKey, VSSetting = "XML Attribute Value")]
+ public ChunkStyle XmlAttributeValue { get; private set; }
+
+ public const string XmlCommentKey = "Xml Comment";
+ [ColorDescription(XmlCommentKey, VSSetting = "XML Comment")]
+ public ChunkStyle XmlComment { get; private set; }
+
+ public const string XmlCDataSectionKey = "Xml CData Section";
+ [ColorDescription(XmlCDataSectionKey, VSSetting = "XML CData Section")]
+ public ChunkStyle XmlCDataSection { get; private set; }
+
+ public const string TooltipTextKey = "Tooltip Text";
+ [ColorDescription(TooltipTextKey)] // not defined in vs.net
+ public ChunkStyle TooltipText { get; private set; }
+
+ public const string NotificationTextKey = "Notification Text";
+ [ColorDescription(NotificationTextKey)] // not defined in vs.net
+ public ChunkStyle NotificationText { get; private set; }
+
+ public const string CompletionTextKey = "Completion Text";
+ [ColorDescription(CompletionTextKey)] //not defined in vs.net
+ public ChunkStyle CompletionText { get; private set; }
+
+ public const string CompletionSelectedTextKey = "Completion Selected Text";
+ [ColorDescription(CompletionSelectedTextKey)] //not defined in vs.net
+ public ChunkStyle CompletionSelectedText { get; private set; }
+
+ public const string CompletionSelectedInactiveTextKey = "Completion Selected Text(Inactive)";
+ [ColorDescription(CompletionSelectedInactiveTextKey)] //not defined in vs.net
+ public ChunkStyle CompletionSelectedInactiveText { get; private set; }
+
+ public const string KeywordAccessorsKey = "Keyword(Access)";
+ [ColorDescription(KeywordAccessorsKey, VSSetting = "Keyword")]
+ public ChunkStyle KeywordAccessors { get; private set; }
+
+ public const string KeywordTypesKey = "Keyword(Type)";
+ [ColorDescription(KeywordTypesKey, VSSetting = "Keyword")]
+ public ChunkStyle KeywordTypes { get; private set; }
+
+ public const string KeywordOperatorsKey = "Keyword(Operator)";
+ [ColorDescription(KeywordOperatorsKey, VSSetting = "Keyword")]
+ public ChunkStyle KeywordOperators { get; private set; }
+
+ public const string KeywordSelectionKey = "Keyword(Selection)";
+ [ColorDescription(KeywordSelectionKey, VSSetting = "Keyword")]
+ public ChunkStyle KeywordSelection { get; private set; }
+
+ public const string KeywordIterationKey = "Keyword(Iteration)";
+ [ColorDescription(KeywordIterationKey, VSSetting = "Keyword")]
+ public ChunkStyle KeywordIteration { get; private set; }
+
+ public const string KeywordJumpKey = "Keyword(Jump)";
+ [ColorDescription(KeywordJumpKey, VSSetting = "Keyword")]
+ public ChunkStyle KeywordJump { get; private set; }
+
+ public const string KeywordContextKey = "Keyword(Context)";
+ [ColorDescription(KeywordContextKey, VSSetting = "Keyword")]
+ public ChunkStyle KeywordContext { get; private set; }
+
+ public const string KeywordExceptionKey = "Keyword(Exception)";
+ [ColorDescription(KeywordExceptionKey, VSSetting = "Keyword")]
+ public ChunkStyle KeywordException { get; private set; }
+
+ public const string KeywordModifiersKey = "Keyword(Modifiers)";
+ [ColorDescription(KeywordModifiersKey, VSSetting = "Keyword")]
+ public ChunkStyle KeywordModifiers { get; private set; }
+
+ public const string KeywordConstantsKey = "Keyword(Constants)";
+ [ColorDescription(KeywordConstantsKey, VSSetting = "Keyword")]
+ public ChunkStyle KeywordConstants { get; private set; }
+
+ public const string KeywordVoidKey = "Keyword(Void)";
+ [ColorDescription(KeywordVoidKey, VSSetting = "Keyword")]
+ public ChunkStyle KeywordVoid { get; private set; }
+
+ public const string KeywordNamespaceKey = "Keyword(Namespace)";
+ [ColorDescription(KeywordNamespaceKey, VSSetting = "Keyword")]
+ public ChunkStyle KeywordNamespace { get; private set; }
+
+ public const string KeywordPropertyKey = "Keyword(Property)";
+ [ColorDescription(KeywordPropertyKey, VSSetting = "Keyword")]
+ public ChunkStyle KeywordProperty { get; private set; }
+
+ public const string KeywordDeclarationKey = "Keyword(Declaration)";
+ [ColorDescription(KeywordDeclarationKey, VSSetting = "Keyword")]
+ public ChunkStyle KeywordDeclaration { get; private set; }
+
+ public const string KeywordParameterKey = "Keyword(Parameter)";
+ [ColorDescription(KeywordParameterKey, VSSetting = "Keyword")]
+ public ChunkStyle KeywordParameter { get; private set; }
+
+ public const string KeywordOperatorDeclarationKey = "Keyword(Operator Declaration)";
+ [ColorDescription(KeywordOperatorDeclarationKey, VSSetting = "Keyword")]
+ public ChunkStyle KeywordOperatorDeclaration { get; private set; }
+
+ public const string KeywordOtherKey = "Keyword(Other)";
+ [ColorDescription(KeywordOtherKey, VSSetting = "Keyword")]
+ public ChunkStyle KeywordOther { get; private set; }
+
+ public const string UserTypesKey = "User Types";
+ [ColorDescription(UserTypesKey, VSSetting = "User Types")]
+ public ChunkStyle UserTypes { get; private set; }
+
+ public const string UserTypesEnumsKey = "User Types(Enums)";
+ [ColorDescription(UserTypesEnumsKey, VSSetting = "User Types(Enums)")]
+ public ChunkStyle UserTypesEnums { get; private set; }
+
+ public const string UserTypesInterfacesKey = "User Types(Interfaces)";
+ [ColorDescription(UserTypesInterfacesKey, VSSetting = "User Types(Interfaces)")]
+ public ChunkStyle UserTypesInterfaces { get; private set; }
+
+ public const string UserTypesDelegatesKey = "User Types(Delegates)";
+ [ColorDescription(UserTypesDelegatesKey, VSSetting = "User Types(Delegates)")]
+ public ChunkStyle UserTypesDelegates { get; private set; }
+
+ public const string UserTypesValueTypesKey = "User Types(Value types)";
+ [ColorDescription(UserTypesValueTypesKey, VSSetting = "User Types(Value types)")]
+ public ChunkStyle UserTypesValueTypes { get; private set; }
+
+ public const string UserTypesTypeParametersKey = "User Types(Type parameters)";
+ [ColorDescription(UserTypesTypeParametersKey, VSSetting = "User Types(Type parameters)")]
+ public ChunkStyle UserTypesTypeParameters { get; private set; }
+
+ public const string UserFieldUsageKey = "User Field Usage";
+ [ColorDescription(UserFieldUsageKey, VSSetting = "Identifier")]
+ public ChunkStyle UserFieldUsage { get; private set; }
+
+ public const string UserFieldDeclarationKey = "User Field Declaration";
+ [ColorDescription(UserFieldDeclarationKey, VSSetting = "Identifier")]
+ public ChunkStyle UserFieldDeclaration { get; private set; }
+
+ public const string UserPropertyUsageKey = "User Property Usage";
+ [ColorDescription(UserPropertyUsageKey, VSSetting = "Identifier")]
+ public ChunkStyle UserPropertyUsage { get; private set; }
+
+ public const string UserPropertyDeclarationKey = "User Property Declaration";
+ [ColorDescription(UserPropertyDeclarationKey, VSSetting = "Identifier")]
+ public ChunkStyle UserPropertyDeclaration { get; private set; }
+
+ public const string UserEventUsageKey = "User Event Usage";
+ [ColorDescription(UserEventUsageKey, VSSetting = "Identifier")]
+ public ChunkStyle UserEventUsage { get; private set; }
+
+ public const string UserEventDeclarationKey = "User Event Declaration";
+ [ColorDescription(UserEventDeclarationKey, VSSetting = "Identifier")]
+ public ChunkStyle UserEventDeclaration { get; private set; }
+
+ public const string UserMethodUsageKey = "User Method Usage";
+ [ColorDescription(UserMethodUsageKey, VSSetting = "Identifier")]
+ public ChunkStyle UserMethodUsage { get; private set; }
+
+ public const string UserMethodDeclarationKey = "User Method Declaration";
+ [ColorDescription(UserMethodDeclarationKey, VSSetting = "Identifier")]
+ public ChunkStyle UserMethodDeclaration { get; private set; }
+
+ public const string UserParameterUsageKey = "User Parameter Usage";
+ [ColorDescription(UserParameterUsageKey, VSSetting = "Identifier")]
+ public ChunkStyle UserParameterUsage { get; private set; }
+
+ public const string UserParameterDeclarationKey = "User Parameter Declaration";
+ [ColorDescription(UserParameterDeclarationKey, VSSetting = "Identifier")]
+ public ChunkStyle UserParameterDeclaration { get; private set; }
+
+ public const string UserVariableUsageKey = "User Variable Usage";
+ [ColorDescription(UserVariableUsageKey, VSSetting = "Identifier")]
+ public ChunkStyle UserVariableUsage { get; private set; }
+
+ public const string UserVariableDeclarationKey = "User Variable Declaration";
+ [ColorDescription(UserVariableDeclarationKey, VSSetting = "Identifier")]
+ public ChunkStyle UserVariableDeclaration { get; private set; }
+
+ public const string SyntaxErrorKey = "Syntax Error";
+ [ColorDescription(SyntaxErrorKey, VSSetting = "Syntax Error")]
+ public ChunkStyle SyntaxError { get; private set; }
+
+ public const string StringFormatItemsKey = "String Format Items";
+ [ColorDescription(StringFormatItemsKey, VSSetting = "String")]
+ public ChunkStyle StringFormatItems { get; private set; }
+
+ public const string BreakpointTextKey = "Breakpoint Text";
+ [ColorDescription(BreakpointTextKey, VSSetting = "Breakpoint (Enabled)")]
+ public ChunkStyle BreakpointText { get; private set; }
+
+ public const string DebuggerCurrentLineKey = "Debugger Current Statement";
+ [ColorDescription(DebuggerCurrentLineKey, VSSetting = "Current Statement")]
+ public ChunkStyle DebuggerCurrentLine { get; private set; }
+
+ public const string DebuggerStackLineKey = "Debugger Stack Line";
+ [ColorDescription(DebuggerStackLineKey)] // not defined
+ public ChunkStyle DebuggerStackLine { get; private set; }
+
+ public const string DiffLineAddedKey = "Diff Line(Added)";
+ [ColorDescription(DiffLineAddedKey)] //not defined
+ public ChunkStyle DiffLineAdded { get; private set; }
+
+ public const string DiffLineRemovedKey = "Diff Line(Removed)";
+ [ColorDescription(DiffLineRemovedKey)] //not defined
+ public ChunkStyle DiffLineRemoved { get; private set; }
+
+ public const string DiffLineChangedKey = "Diff Line(Changed)";
+ [ColorDescription(DiffLineChangedKey)] //not defined
+ public ChunkStyle DiffLineChanged { get; private set; }
+
+ public const string DiffHeaderKey = "Diff Header";
+ [ColorDescription(DiffHeaderKey)] //not defined
+ public ChunkStyle DiffHeader { get; private set; }
+
+ public const string DiffHeaderSeparatorKey = "Diff Header(Separator)";
+ [ColorDescription(DiffHeaderSeparatorKey)] //not defined
+ public ChunkStyle DiffHeaderSeparator { get; private set; }
+
+ public const string DiffHeaderOldKey = "Diff Header(Old)";
+ [ColorDescription(DiffHeaderOldKey)] //not defined
+ public ChunkStyle DiffHeaderOld { get; private set; }
+
+ public const string DiffHeaderNewKey = "Diff Header(New)";
+ [ColorDescription(DiffHeaderNewKey)] //not defined
+ public ChunkStyle DiffHeaderNew { get; private set; }
+
+ public const string DiffLocationKey = "Diff Location";
+ [ColorDescription(DiffLocationKey)] //not defined
+ public ChunkStyle DiffLocation { get; private set; }
+
+ public const string HtmlAttributeNameKey = "Html Attribute Name";
+ [ColorDescription(HtmlAttributeNameKey, VSSetting="HTML Attribute")]
+ public ChunkStyle HtmlAttributeName { get; private set; }
+
+ public const string HtmlAttributeValueKey = "Html Attribute Value";
+ [ColorDescription(HtmlAttributeValueKey, VSSetting="HTML Attribute Value")]
+ public ChunkStyle HtmlAttributeValue { get; private set; }
+
+ public const string HtmlCommentKey = "Html Comment";
+ [ColorDescription(HtmlCommentKey, VSSetting="HTML Comment")]
+ public ChunkStyle HtmlComment { get; private set; }
+
+ public const string HtmlElementNameKey = "Html Element Name";
+ [ColorDescription(HtmlElementNameKey, VSSetting="HTML Element Name")]
+ public ChunkStyle HtmlElementName { get; private set; }
+
+ public const string HtmlEntityKey = "Html Entity";
+ [ColorDescription(HtmlEntityKey, VSSetting="HTML Entity")]
+ public ChunkStyle HtmlEntity { get; private set; }
+
+ public const string HtmlOperatorKey = "Html Operator";
+ [ColorDescription(HtmlOperatorKey, VSSetting="HTML Operator")]
+ public ChunkStyle HtmlOperator { get; private set; }
+
+ public const string HtmlServerSideScriptKey = "Html Server-Side Script";
+ [ColorDescription(HtmlServerSideScriptKey, VSSetting="HTML Server-Side Script")]
+ public ChunkStyle HtmlServerSideScript { get; private set; }
+
+ public const string HtmlTagDelimiterKey = "Html Tag Delimiter";
+ [ColorDescription(HtmlTagDelimiterKey, VSSetting="HTML Tag Delimiter")]
+ public ChunkStyle HtmlTagDelimiter { get; private set; }
+
+ public const string RazorCodeKey = "Razor Code";
+ [ColorDescription(RazorCodeKey, VSSetting="Razor Code")]
+ public ChunkStyle RazorCode { get; private set; }
+
+ public const string CssCommentKey = "Css Comment";
+ [ColorDescription(CssCommentKey, VSSetting="CSS Comment")]
+ public ChunkStyle CssComment { get; private set; }
+
+ public const string CssPropertyNameKey = "Css Property Name";
+ [ColorDescription(CssPropertyNameKey, VSSetting="CSS Property Name")]
+ public ChunkStyle CssPropertyName { get; private set; }
+
+ public const string CssPropertyValueKey = "Css Property Value";
+ [ColorDescription(CssPropertyValueKey, VSSetting="CSS Property Value")]
+ public ChunkStyle CssPropertyValue { get; private set; }
+
+ public const string CssSelectorKey = "Css Selector";
+ [ColorDescription(CssSelectorKey, VSSetting="CSS Selector")]
+ public ChunkStyle CssSelector { get; private set; }
+
+ public const string CssStringValueKey = "Css String Value";
+ [ColorDescription(CssStringValueKey, VSSetting="CSS String Value")]
+ public ChunkStyle CssStringValue { get; private set; }
+
+ public const string CssKeywordKey = "Css Keyword";
+ [ColorDescription(CssKeywordKey, VSSetting="CSS Keyword")]
+ public ChunkStyle CssKeyword { get; private set; }
+
+ public const string ScriptCommentKey = "Script Comment";
+ [ColorDescription(ScriptCommentKey, VSSetting="Script Comment")]
+ public ChunkStyle ScriptComment { get; private set; }
+
+ public const string ScriptIdentifierKey = "Script Identifier";
+ [ColorDescription(ScriptIdentifierKey, VSSetting="Script Identifier")]
+ public ChunkStyle ScriptIdentifier { get; private set; }
+
+ public const string ScriptKeywordKey = "Script Keyword";
+ [ColorDescription(ScriptKeywordKey, VSSetting="Script Keyword")]
+ public ChunkStyle ScriptKeyword { get; private set; }
+
+ public const string ScriptNumberKey = "Script Number";
+ [ColorDescription(ScriptNumberKey, VSSetting="Script Number")]
+ public ChunkStyle ScriptNumber { get; private set; }
+
+ public const string ScriptOperatorKey = "Script Operator";
+ [ColorDescription(ScriptOperatorKey, VSSetting="Script Operator")]
+ public ChunkStyle ScriptOperator { get; private set; }
+
+ public const string ScriptStringKey = "Script String";
+ [ColorDescription(ScriptStringKey, VSSetting="Script String")]
+ public ChunkStyle ScriptString { get; private set; }
+
+ #endregion
+
+ public class PropertyDecsription
+ {
+ public readonly PropertyInfo Info;
+ public readonly ColorDescriptionAttribute Attribute;
+
+ public PropertyDecsription (PropertyInfo info, ColorDescriptionAttribute attribute)
+ {
+ this.Info = info;
+ this.Attribute = attribute;
+ }
+ }
+
+ static Dictionary<string, PropertyDecsription> textColors = new Dictionary<string, PropertyDecsription> ();
+
+ public static IEnumerable<PropertyDecsription> TextColors {
+ get {
+ return textColors.Values;
+ }
+ }
+
+ static Dictionary<string, PropertyDecsription> ambientColors = new Dictionary<string, PropertyDecsription> ();
+
+ public static IEnumerable<PropertyDecsription> AmbientColors {
+ get {
+ return ambientColors.Values;
+ }
+ }
+
+ static ColorScheme ()
+ {
+ foreach (var property in typeof(ColorScheme).GetProperties ()) {
+ var description = property.GetCustomAttributes (false).FirstOrDefault (p => p is ColorDescriptionAttribute) as ColorDescriptionAttribute;
+ if (description == null)
+ continue;
+ if (property.PropertyType == typeof (ChunkStyle)) {
+ textColors.Add (description.Name, new PropertyDecsription (property, description));
+ } else {
+ ambientColors.Add (description.Name, new PropertyDecsription (property, description));
+ }
+ }
+ }
+
+ public ColorScheme Clone ()
+ {
+ var result = new ColorScheme () {
+ Name = this.Name,
+ BaseScheme = this.BaseScheme,
+ Originator = this.Originator,
+ Description = this.Description
+ };
+ result.CopyValues (this);
+ return result;
+ }
+
+ static HslColor ParseColor (string value)
+ {
+ if (value.Length == 9 && value.StartsWith ("#", StringComparison.Ordinal)) {
+ double r = ((double) int.Parse (value.Substring (1,2), System.Globalization.NumberStyles.HexNumber)) / 255;
+ double g = ((double) int.Parse (value.Substring (3,2), System.Globalization.NumberStyles.HexNumber)) / 255;
+ double b = ((double) int.Parse (value.Substring (5,2), System.Globalization.NumberStyles.HexNumber)) / 255;
+ double a = ((double) int.Parse (value.Substring (7,2), System.Globalization.NumberStyles.HexNumber)) / 255;
+ return new HslColor (r, g, b, a);
+ }
+ return HslColor.Parse (value);
+ }
+
+ public static HslColor ParsePaletteColor (Dictionary<string, HslColor> palette, string value)
+ {
+ HslColor result;
+ if (palette.TryGetValue (value, out result))
+ return result;
+ return ParseColor (value);
+ }
+
+ public ChunkStyle GetChunkStyle (string color)
+ {
+ if (color == null)
+ return GetChunkStyle ("Plain Text");
+ PropertyDecsription val;
+ if (!textColors.TryGetValue (color, out val)) {
+ Console.WriteLine ("Chunk style : " + color + " is undefined.");
+ return GetChunkStyle ("Plain Text");
+ }
+ return val.Info.GetValue (this, null) as ChunkStyle;
+ }
+
+ void CopyValues (ColorScheme baseScheme)
+ {
+ foreach (var color in textColors.Values)
+ color.Info.SetValue (this, color.Info.GetValue (baseScheme, null), null);
+ foreach (var color in ambientColors.Values)
+ color.Info.SetValue (this, color.Info.GetValue (baseScheme, null), null);
+ }
+
+ public static ColorScheme LoadFrom (Stream stream)
+ {
+ var result = new ColorScheme ();
+ var reader = System.Runtime.Serialization.Json.JsonReaderWriterFactory.CreateJsonReader (stream, new System.Xml.XmlDictionaryReaderQuotas ());
+
+ var root = XElement.Load(reader);
+
+ // The fields we'd like to extract
+ result.Name = root.XPathSelectElement("name").Value;
+
+ if (result.Name != "Default")
+ result.CopyValues (SyntaxModeService.DefaultColorStyle);
+
+ var version = Version.Parse (root.XPathSelectElement("version").Value);
+ if (version.Major != 1)
+ return null;
+ var el = root.XPathSelectElement ("description");
+ if (el != null)
+ result.Description = el.Value;
+ el = root.XPathSelectElement ("originator");
+ if (el != null)
+ result.Originator = el.Value;
+ el = root.XPathSelectElement ("baseScheme");
+ if (el != null)
+ result.BaseScheme = el.Value;
+
+ if (result.BaseScheme != null) {
+ var baseScheme = SyntaxModeService.GetColorStyle (result.BaseScheme);
+ if (baseScheme != null)
+ result.CopyValues (baseScheme);
+ }
+
+ var palette = new Dictionary<string, HslColor> ();
+ foreach (var color in root.XPathSelectElements("palette/*")) {
+ var name = color.XPathSelectElement ("name").Value;
+ if (palette.ContainsKey (name))
+ throw new InvalidDataException ("Duplicate palette color definition for: " + name);
+ palette.Add (
+ name,
+ ParseColor (color.XPathSelectElement ("value").Value)
+ );
+ }
+
+ foreach (var colorElement in root.XPathSelectElements("//colors/*")) {
+ var color = AmbientColor.Create (colorElement, palette);
+ PropertyDecsription info;
+ if (!ambientColors.TryGetValue (color.Name, out info)) {
+ Console.WriteLine ("Ambient color:" + color.Name + " not found.");
+ continue;
+ }
+ info.Info.SetValue (result, color, null);
+ }
+
+ foreach (var textColorElement in root.XPathSelectElements("//text/*")) {
+ var color = ChunkStyle.Create (textColorElement, palette);
+ PropertyDecsription info;
+ if (!textColors.TryGetValue (color.Name, out info)) {
+ Console.WriteLine ("Text color:" + color.Name + " not found.");
+ continue;
+ }
+ info.Info.SetValue (result, color, null);
+ }
+
+ // Check scheme
+ bool valid = true;
+ foreach (var color in textColors.Values) {
+ if (color.Info.GetValue (result, null) == null) {
+ Console.WriteLine (color.Attribute.Name + " == null");
+ valid = false;
+ }
+ }
+ foreach (var color in ambientColors.Values) {
+ if (color.Info.GetValue (result, null) == null) {
+ Console.WriteLine (color.Attribute.Name + " == null");
+ valid = false;
+ }
+ }
+ if (!valid)
+ throw new InvalidDataException ("Scheme " + result.Name + " is not valid.");
+ return result;
+ }
+
+ public static string ColorToMarkup (HslColor color)
+ {
+ return color.ToMarkup ();
+ }
+
+
+ public void Save (string fileName)
+ {
+ using (var writer = new StreamWriter (fileName)) {
+ writer.WriteLine ("{");
+ writer.WriteLine ("\t\"name\":\"{0}\",", Name);
+ writer.WriteLine ("\t\"version\":\"1.0\",");
+ if (!string.IsNullOrEmpty (Description))
+ writer.WriteLine ("\t\"description\":\"{0}\",", Description);
+ if (!string.IsNullOrEmpty (Originator))
+ writer.WriteLine ("\t\"originator\":\"{0}\",", Originator);
+ if (!string.IsNullOrEmpty (BaseScheme))
+ writer.WriteLine ("\t\"baseScheme\":\"{0}\",", BaseScheme);
+
+ var baseStyle = SyntaxModeService.GetColorStyle (BaseScheme ?? "Default");
+
+ writer.WriteLine ("\t\"colors\":[");
+ bool first = true;
+ foreach (var ambient in ambientColors) {
+ var thisValue = ambient.Value.Info.GetValue (this, null) as AmbientColor;
+ if (thisValue == null)
+ continue;
+ var baseValue = ambient.Value.Info.GetValue (baseStyle, null) as AmbientColor;
+ if (thisValue.Equals (baseValue)) {
+ continue;
+ }
+
+ var colorString = new StringBuilder ();
+ foreach (var color in thisValue.Colors) {
+ if (colorString.Length > 0)
+ colorString.Append (", ");
+ colorString.Append (string.Format ("\"{0}\":\"{1}\"", color.Item1, ColorToMarkup (color.Item2)));
+ }
+ if (colorString.Length == 0) {
+ Console.WriteLine ("Invalid ambient color :" + thisValue);
+ continue;
+ }
+ if (!first) {
+ writer.WriteLine (",");
+ } else {
+ first = false;
+ }
+ writer.Write ("\t\t{");
+ writer.Write ("\"name\": \"{0}\", {1}", ambient.Value.Attribute.Name, colorString);
+ writer.Write (" }");
+ }
+
+ writer.WriteLine ("\t],");
+ first = true;
+ writer.WriteLine ("\t\"text\":[");
+ foreach (var textColor in textColors) {
+ var thisValue = textColor.Value.Info.GetValue (this, null) as ChunkStyle;
+ if (thisValue == null)
+ continue;
+ var baseValue = textColor.Value.Info.GetValue (baseStyle, null) as ChunkStyle;
+ if (thisValue.Equals (baseValue)) {
+ continue;
+ }
+ var colorString = new StringBuilder ();
+ if (!thisValue.TransparentForeground)
+ colorString.Append (string.Format ("\"fore\":\"{0}\"", ColorToMarkup (thisValue.Foreground)));
+ if (!thisValue.TransparentBackground) {
+ if (colorString.Length > 0)
+ colorString.Append (", ");
+ colorString.Append (string.Format ("\"back\":\"{0}\"", ColorToMarkup (thisValue.Background)));
+ }
+ if (thisValue.FontWeight != Xwt.Drawing.FontWeight.Normal) {
+ if (colorString.Length > 0)
+ colorString.Append (", ");
+ colorString.Append (string.Format ("\"weight\":\"{0}\"", thisValue.FontWeight));
+ }
+ if (thisValue.FontStyle != Xwt.Drawing.FontStyle.Normal) {
+ if (colorString.Length > 0)
+ colorString.Append (", ");
+ colorString.Append (string.Format ("\"style\":\"{0}\"", thisValue.FontStyle));
+ }
+ if (!first) {
+ writer.WriteLine (",");
+ } else {
+ first = false;
+ }
+ writer.Write ("\t\t{");
+ if (colorString.Length == 0) {
+ writer.Write ("\"name\": \"{0}\"", textColor.Value.Attribute.Name);
+ } else {
+ writer.Write ("\"name\": \"{0}\", {1}", textColor.Value.Attribute.Name, colorString);
+ }
+ writer.Write (" }");
+ }
+ writer.WriteLine ();
+ writer.WriteLine ("\t]");
+
+ writer.WriteLine ("}");
+ }
+ }
+
+ internal static HslColor ImportVsColor (string colorString)
+ {
+ if (colorString == "0x02000000")
+ return new HslColor (0, 0, 0, 0);
+ string color = "#" + colorString.Substring (8, 2) + colorString.Substring (6, 2) + colorString.Substring (4, 2);
+ return HslColor.Parse (color);
+ }
+
+ public class VSSettingColor
+ {
+ public string Name { get; private set; }
+ public string Foreground { get; private set; }
+ public string Background { get; private set; }
+ public bool BoldFont { get; private set; }
+
+ public static VSSettingColor Create (XmlReader reader)
+ {
+ return new VSSettingColor {
+ Name = reader.GetAttribute ("Name"),
+ Foreground = reader.GetAttribute ("Foreground"),
+ Background = reader.GetAttribute ("Background"),
+ BoldFont = reader.GetAttribute ("BoldFont") == "Yes"
+ };
+ }
+ }
+
+ public static HslColor AlphaBlend (HslColor fore, HslColor back, double alpha)
+ {
+ var fc = (Cairo.Color)fore;
+ var bc = (Cairo.Color)back;
+ return new HslColor (
+ (1.0 - alpha) * bc.R + alpha * fc.R,
+ (1.0 - alpha) * bc.G + alpha * fc.G,
+ (1.0 - alpha) * bc.B + alpha * fc.B);
+ }
+
+ public static ColorScheme Import (string fileName, Stream stream)
+ {
+ var result = new ColorScheme ();
+ result.Name = Path.GetFileNameWithoutExtension (fileName);
+ result.Description = "Imported color scheme";
+ result.Originator = "Imported from " + fileName;
+
+ var colors = new Dictionary<string, VSSettingColor> ();
+ using (var reader = XmlReader.Create (stream)) {
+ while (reader.Read ()) {
+ if (reader.LocalName == "Item") {
+ var color = VSSettingColor.Create (reader);
+ if (colors.ContainsKey (color.Name)) {
+ Console.WriteLine ("Warning: {0} is defined twice in vssettings.", color.Name);
+ continue;
+ }
+ colors[color.Name] = color;
+ }
+ }
+ }
+
+
+ HashSet<string> importedAmbientColors = new HashSet<string> ();
+ // convert ambient colors
+ foreach (var ambient in ambientColors.Values) {
+ if (!string.IsNullOrEmpty (ambient.Attribute.VSSetting)) {
+ var import = AmbientColor.Import (colors, ambient.Attribute.VSSetting);
+ if (import != null) {
+ importedAmbientColors.Add (import.Name);
+ ambient.Info.SetValue (result, import, null);
+ continue;
+ }
+ }
+ }
+
+ // convert text colors
+ foreach (var vsc in colors.Values) {
+ bool found = false;
+ foreach (var color in textColors) {
+ if (color.Value.Attribute.VSSetting == null)
+ continue;
+ var split = color.Value.Attribute.VSSetting.Split ('?');
+ foreach (var s in split) {
+ if (s == vsc.Name) {
+ /* if (vsc.Foreground == "0x02000000" && vsc.Background == "0x02000000") {
+ color.Value.Info.SetValue (result, result.PlainText, null);
+ found = true;
+ continue;
+ }*/
+ var textColor = ChunkStyle.Import (color.Value.Attribute.Name, vsc);
+ if (textColor != null) {
+ color.Value.Info.SetValue (result, textColor, null);
+ found = true;
+ }
+ }
+ }
+ }
+ if (!found && !importedAmbientColors.Contains (vsc.Name))
+ Console.WriteLine (vsc.Name + " not imported!");
+ }
+
+ result.IndentationGuide = new AmbientColor ();
+ result.IndentationGuide.Colors.Add (Tuple.Create ("color", AlphaBlend (result.PlainText.Foreground, result.PlainText.Background, 0.3)));
+
+ result.TooltipText = result.PlainText.Clone ();
+ var h = (HslColor)result.TooltipText.Background;
+ h.L += 0.01;
+ result.TooltipText.Background = h;
+
+ result.TooltipPagerTop = new AmbientColor ();
+ result.TooltipPagerTop.Colors.Add (Tuple.Create ("color", result.TooltipText.Background));
+
+ result.TooltipPagerBottom = new AmbientColor ();
+ result.TooltipPagerBottom.Colors.Add (Tuple.Create ("color", result.TooltipText.Background));
+
+ result.TooltipPagerTriangle = new AmbientColor ();
+ result.TooltipPagerTriangle.Colors.Add (Tuple.Create ("color", AlphaBlend (result.PlainText.Foreground, result.PlainText.Background, 0.8)));
+
+ result.TooltipBorder = new AmbientColor ();
+ result.TooltipBorder.Colors.Add (Tuple.Create ("color", AlphaBlend (result.PlainText.Foreground, result.PlainText.Background, 0.5)));
+
+ var defaultStyle = SyntaxModeService.GetColorStyle (HslColor.Brightness (result.PlainText.Background) < 0.5 ? "Monokai" : "Default");
+
+ foreach (var color in textColors.Values) {
+ if (color.Info.GetValue (result, null) == null)
+ color.Info.SetValue (result, color.Info.GetValue (defaultStyle, null), null);
+ }
+ foreach (var color in ambientColors.Values) {
+ if (color.Info.GetValue (result, null) == null)
+ color.Info.SetValue (result, color.Info.GetValue (defaultStyle, null), null);
+ }
+ if (result.PlainText.TransparentForeground)
+ result.PlainText.Foreground = new HslColor (0, 0, 0);
+ return result;
+ }
+
+ public HslColor GetForeground (ChunkStyle chunkStyle)
+ {
+ if (chunkStyle.TransparentForeground)
+ return PlainText.Foreground;
+ return chunkStyle.Foreground;
+ }
+
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/ColoredSegment.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/ColoredSegment.cs
new file mode 100644
index 0000000000..9f67c54602
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/ColoredSegment.cs
@@ -0,0 +1,59 @@
+//
+// ColoredSegment.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Core.Text;
+using System.Collections.Generic;
+
+namespace MonoDevelop.Ide.Editor.Highlighting
+{
+ /// <summary>
+ /// A colored segment is used in the highlighter to specify a color scheme style to a specfic part of text.
+ /// </summary>
+ public sealed class ColoredSegment : AbstractSegment
+ {
+ readonly string colorStyleKey;
+
+ //// <summary>
+ /// Gets the color style. The style is looked up in the current color scheme.
+ /// </summary>
+ public string ColorStyleKey {
+ get {
+ return colorStyleKey;
+ }
+ }
+
+ public ColoredSegment (int offset, int length, string colorStyleKey) : base (offset, length)
+ {
+ this.colorStyleKey = colorStyleKey;
+ }
+
+ public ColoredSegment (ISegment segment, string colorStyleKey) : base (segment)
+ {
+ this.colorStyleKey = colorStyleKey;
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/IStreamProvider.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/IStreamProvider.cs
new file mode 100644
index 0000000000..97126a1219
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/IStreamProvider.cs
@@ -0,0 +1,97 @@
+// IXmlProvider.cs
+//
+// Author:
+// Mike Krüger <mkrueger@novell.com>
+//
+// Copyright (c) 2008 Novell, Inc (http://www.novell.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.IO;
+using System.Reflection;
+using System.Xml;
+
+namespace MonoDevelop.Ide.Editor.Highlighting
+{
+ public interface IStreamProvider
+ {
+ Stream Open ();
+ }
+
+ [Obsolete("Do not use this anymore. Use ResourceStreamProvider.")]
+ public class ResourceXmlProvider : ResourceStreamProvider
+ {
+ public ResourceXmlProvider (Assembly assembly, string manifestResourceName) : base(assembly, manifestResourceName)
+ {
+
+ }
+ }
+ public class ResourceStreamProvider : IStreamProvider
+ {
+ Assembly assembly;
+ string manifestResourceName;
+
+ public string ManifestResourceName {
+ get {
+ return manifestResourceName;
+ }
+ }
+
+ public Assembly Assembly {
+ get {
+ return assembly;
+ }
+ }
+
+ public ResourceStreamProvider (Assembly assembly, string manifestResourceName)
+ {
+ this.assembly = assembly;
+ this.manifestResourceName = manifestResourceName;
+ }
+
+ public Stream Open ()
+ {
+ return assembly.GetManifestResourceStream (this.ManifestResourceName);
+ }
+ }
+
+ public class UrlStreamProvider : IStreamProvider
+ {
+ string url;
+
+ public string Url {
+ get {
+ return url;
+ }
+ }
+
+ public UrlStreamProvider (string url)
+ {
+ this.url = url;
+ }
+
+ public Stream Open ()
+ {
+ return File.OpenRead (url);
+ }
+ }
+
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/SemanticHighlighting.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/SemanticHighlighting.cs
new file mode 100644
index 0000000000..f0f27f39f6
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/SemanticHighlighting.cs
@@ -0,0 +1,76 @@
+//
+// SemanticHighlighting.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Core.Text;
+using System.Collections.Generic;
+
+namespace MonoDevelop.Ide.Editor.Highlighting
+{
+ /// <summary>
+ /// Semantic highlighting adds the ability to add highlighting for things that require
+ /// a background parser to be colored. For example type names.
+ /// </summary>
+ public abstract class SemanticHighlighting : IDisposable
+ {
+ protected readonly internal TextEditor editor;
+ protected readonly internal DocumentContext documentContext;
+
+ protected SemanticHighlighting (TextEditor editor, DocumentContext documentContext)
+ {
+ this.editor = editor;
+ this.documentContext = documentContext;
+ this.documentContext.DocumentParsed += HandleDocumentParsed;
+ }
+
+ protected abstract void DocumentParsed ();
+
+ public void NotifySemanticHighlightingUpdate ()
+ {
+ var handler = SemanticHighlightingUpdated;
+ if (handler != null)
+ handler (this, EventArgs.Empty);
+ }
+
+ /// <summary>
+ /// Colorize the specified offset, count and colorizeCallback.
+ /// </summary>
+ /// <param name="segment">The area to run the colorizer in.</param>
+ public abstract IEnumerable<ColoredSegment> GetColoredSegments (ISegment segment);
+
+ void HandleDocumentParsed (object sender, EventArgs e)
+ {
+ if (DefaultSourceEditorOptions.Instance.EnableSemanticHighlighting)
+ DocumentParsed ();
+ }
+
+ public void Dispose ()
+ {
+ documentContext.DocumentParsed -= HandleDocumentParsed;
+ }
+
+ internal event EventHandler SemanticHighlightingUpdated;
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/SyntaxModeService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/SyntaxModeService.cs
new file mode 100644
index 0000000000..539bcc5c6a
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/SyntaxModeService.cs
@@ -0,0 +1,216 @@
+// SyntaxModeService.cs
+//
+// Author:
+// Mike Krüger <mkrueger@novell.com>
+//
+// Copyright (c) 2007 Novell, Inc (http://www.novell.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.Collections.ObjectModel;
+using System.IO;
+using System.Reflection;
+using System.Threading;
+using System.Xml;
+using System.Xml.Schema;
+using System.Linq;
+using Mono.Addins;
+using MonoDevelop.Core;
+
+namespace MonoDevelop.Ide.Editor.Highlighting
+{
+ public static class SyntaxModeService
+ {
+ static Dictionary<string, ColorScheme> styles = new Dictionary<string, ColorScheme> ();
+ static Dictionary<string, IStreamProvider> styleLookup = new Dictionary<string, IStreamProvider> ();
+
+ public static string[] Styles {
+ get {
+ List<string> result = new List<string> ();
+ foreach (string style in styles.Keys) {
+ if (!result.Contains (style))
+ result.Add (style);
+ }
+ foreach (string style in styleLookup.Keys) {
+ if (!result.Contains (style))
+ result.Add (style);
+ }
+ return result.ToArray ();
+ }
+ }
+
+ public static ColorScheme GetColorStyle (string name)
+ {
+ if (styles.ContainsKey (name))
+ return styles [name];
+ if (styleLookup.ContainsKey (name)) {
+ LoadStyle (name);
+ return GetColorStyle (name);
+ }
+ return GetColorStyle ("Default");
+ }
+
+ public static IStreamProvider GetProvider (ColorScheme style)
+ {
+ if (styleLookup.ContainsKey (style.Name))
+ return styleLookup[style.Name];
+ 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) {
+ var usp = provider as UrlStreamProvider;
+ if (usp.Url.EndsWith (".vssettings", StringComparison.Ordinal)) {
+ styles [name] = ColorScheme.Import (usp.Url, stream);
+ } else {
+ styles [name] = ColorScheme.LoadFrom (stream);
+ }
+ styles [name].FileName = usp.Url;
+ } else {
+ styles [name] = ColorScheme.LoadFrom (stream);
+ }
+ } catch (Exception e) {
+ throw new IOException ("Error while loading style :" + name, e);
+ } finally {
+ stream.Close ();
+ }
+ }
+
+
+ public static void Remove (ColorScheme style)
+ {
+ if (styleLookup.ContainsKey (style.Name))
+ styleLookup.Remove (style.Name);
+
+ foreach (var kv in styles) {
+ if (kv.Value == style) {
+ styles.Remove (kv.Key);
+ return;
+ }
+ }
+ }
+
+
+ public static List<ValidationEventArgs> ValidateStyleFile (string fileName)
+ {
+ List<ValidationEventArgs> result = new List<ValidationEventArgs> ();
+ return result;
+ }
+
+
+ public static void LoadStylesAndModes (string path)
+ {
+ foreach (string file in Directory.GetFiles (path)) {
+ if (file.EndsWith (".json", StringComparison.Ordinal)) {
+ using (var stream = File.OpenRead (file)) {
+ string styleName = ScanStyle (stream);
+ if (!string.IsNullOrEmpty (styleName)) {
+ styleLookup [styleName] = new UrlStreamProvider (file);
+ } else {
+ Console.WriteLine ("Invalid .json syntax sheme file : " + file);
+ }
+ }
+ } else if (file.EndsWith (".vssettings", StringComparison.Ordinal)) {
+ using (var stream = File.OpenRead (file)) {
+ string styleName = Path.GetFileNameWithoutExtension (file);
+ styleLookup [styleName] = new UrlStreamProvider (file);
+ }
+ }
+ }
+ }
+
+ public static void LoadStylesAndModes (Assembly assembly)
+ {
+ foreach (string resource in assembly.GetManifestResourceNames ()) {
+ if (resource.EndsWith ("Style.json", StringComparison.Ordinal)) {
+ using (Stream stream = assembly.GetManifestResourceStream (resource)) {
+ string styleName = ScanStyle (stream);
+ styleLookup [styleName] = new ResourceStreamProvider (assembly, resource);
+ }
+ }
+ }
+ }
+ static System.Text.RegularExpressions.Regex nameRegex = new System.Text.RegularExpressions.Regex ("\\s*\"name\"\\s*:\\s*\"(.*)\"\\s*,");
+
+ static string ScanStyle (Stream stream)
+ {
+ try {
+ var file = new StreamReader (stream);
+ file.ReadLine ();
+ var nameLine = file.ReadLine ();
+ var match = nameRegex.Match (nameLine);
+ if (!match.Success)
+ return null;
+ return match.Groups[1].Value;
+ } catch (Exception e) {
+ Console.WriteLine ("Error while scanning json:");
+ Console.WriteLine (e);
+ return null;
+ }
+ }
+
+ public static void AddStyle (ColorScheme style)
+ {
+ styles [style.Name] = style;
+ }
+
+ public static void AddStyle (IStreamProvider provider)
+ {
+ using (var stream = provider.Open ()) {
+ string styleName = ScanStyle (stream);
+ styleLookup [styleName] = provider;
+ }
+ }
+
+ public static void RemoveStyle (IStreamProvider provider)
+ {
+ using (var stream = provider.Open ()) {
+ string styleName = ScanStyle (stream);
+ styleLookup.Remove (styleName);
+ }
+ }
+
+ public static ColorScheme DefaultColorStyle {
+ get {
+ return GetColorStyle ("Default");
+ }
+ }
+
+ static SyntaxModeService ()
+ {
+ var textEditorAssembly = Assembly.Load ("Mono.TextEditor");
+ if (textEditorAssembly != null) {
+ LoadStylesAndModes (textEditorAssembly);
+ } else {
+ LoggingService.LogError ("Can't lookup Mono.TextEditor assembly. Default styles won't be loaded.");
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/ConditionalRegion.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/TemplateCodon.cs
index f0d1bb4c98..bd57ac22d0 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/ConditionalRegion.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/TemplateCodon.cs
@@ -1,4 +1,4 @@
-// ConditionalRegion.cs
+// TemplateCodon.cs
//
// Author:
// Mike Krüger <mkrueger@novell.com>
@@ -23,66 +23,42 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
+using System.IO;
using System;
-using System.Collections.Generic;
-using ICSharpCode.NRefactory.TypeSystem;
-using ICSharpCode.NRefactory;
+using System.Xml;
-namespace MonoDevelop.Ide.TypeSystem
+using Mono.Addins;
+
+namespace MonoDevelop.Ide.Editor.Highlighting
{
- [Serializable]
- public class ConditionBlock
+ [ExtensionNode (Description="A template for color and syntax shemes.")]
+ class TemplateCodon : ExtensionNode, IStreamProvider
{
- public string Flag {
- get;
- set;
- }
+ [NodeAttribute("resource", "Name of the resource where the template is stored.")]
+ string resource;
- public DomRegion Region {
- get;
- set;
- }
-
- public TextLocation Start {
- get;
- set;
- }
+ [NodeAttribute("file", "Name of the file where the template is stored.")]
+ string file;
- public TextLocation End {
- get;
- set;
- }
-
- public ConditionBlock (string flag) : this (flag, TextLocation.Empty)
- {
- }
-
- public ConditionBlock (string flag, TextLocation start)
+ public TemplateCodon ()
{
- this.Flag = flag;
- this.Start = start;
- this.Region = DomRegion.Empty;
- }
- }
-
- [Serializable]
- public class ConditionalRegion : ConditionBlock
- {
- public DomRegion ElseBlock {
- get;
- set;
+ resource = file = null;
}
- List<ConditionBlock> conditionBlocks = new List<ConditionBlock> ();
-
- public List<ConditionBlock> ConditionBlocks {
- get {
- return conditionBlocks;
- }
- }
-
- public ConditionalRegion (string flag) : base (flag)
+ public Stream Open ()
{
+ Stream stream;
+ if (!string.IsNullOrEmpty (file)) {
+ stream = File.OpenRead (Addin.GetFilePath (file));
+ } else if (!string.IsNullOrEmpty (resource)) {
+ stream = Addin.GetResource (resource);
+ if (stream == null)
+ throw new ApplicationException ("Template " + resource + " not found");
+ } else {
+ throw new InvalidOperationException ("Template file or resource not provided");
+ }
+
+ return stream;
}
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/TemplateExtensionNodeLoader.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/TemplateExtensionNodeLoader.cs
new file mode 100644
index 0000000000..ddf704e991
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/TemplateExtensionNodeLoader.cs
@@ -0,0 +1,55 @@
+// TemplateExtensionNodeLoader.cs
+//
+// Author:
+// Mike Krüger <mkrueger@novell.com>
+//
+// Copyright (c) 2008 Novell, Inc (http://www.novell.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 Mono.Addins;
+using MonoDevelop.Ide.Editor.Highlighting;
+
+namespace MonoDevelop.Ide.Editor.Highlighting
+{
+ public static class TemplateExtensionNodeLoader
+ {
+ static bool initialized = false;
+
+ public static void Init ()
+ {
+ if (initialized)
+ return;
+ initialized = true;
+ AddinManager.AddExtensionNodeHandler ("/MonoDevelop/SourceEditor2/Styles", OnStylesExtensionChanged);
+ }
+
+ static void OnStylesExtensionChanged (object s, ExtensionNodeEventArgs args)
+ {
+ TemplateCodon codon = (TemplateCodon)args.ExtensionNode;
+ if (args.Change == ExtensionChange.Add) {
+ SyntaxModeService.AddStyle (codon);
+ } else {
+ SyntaxModeService.RemoveStyle (codon);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Util/Diff.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Util/Diff.cs
new file mode 100644
index 0000000000..364b0f2288
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Util/Diff.cs
@@ -0,0 +1,587 @@
+//
+// Diff.cs
+//
+// Author:
+// Matthias Hertel, http://www.mathertel.de//
+// some tweaks made by Mike Krüger <mkrueger@novell.com>
+//
+// Copyright (c) by Matthias Hertel, http://www.mathertel.de//
+//
+// 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.
+//
+// diff.cs: A port of the algorythm to C#
+// Copyright (c) by Matthias Hertel, http://www.mathertel.de
+// This work is licensed under a BSD style license. See http://www.mathertel.de/License.aspx
+//
+// This Class implements the Difference Algorithm published in
+// "An O(ND) Difference Algorithm and its Variations" by Eugene Myers
+// Algorithmica Vol. 1 No. 2, 1986, p 251.
+//
+// There are many C, Java, Lisp implementations public available but they all seem to come
+// from the same source (diffutils) that is under the (unfree) GNU public License
+// and cannot be reused as a sourcecode for a commercial application.
+// There are very old C implementations that use other (worse) algorithms.
+// Microsoft also published sourcecode of a diff-tool (windiff) that uses some tree data.
+// Also, a direct transfer from a C source to C# is not easy because there is a lot of pointer
+// arithmetic in the typical C solutions and i need a managed solution.
+// These are the reasons why I implemented the original published algorithm from the scratch and
+// make it avaliable without the GNU license limitations.
+// I do not need a high performance diff tool because it is used only sometimes.
+// I will do some performace tweaking when needed.
+//
+// The algorithm itself is comparing 2 arrays of numbers so when comparing 2 text documents
+// each line is converted into a (hash) number. See DiffText().
+//
+// Some chages to the original algorithm:
+// The original algorithm was described using a recursive approach and comparing zero indexed arrays.
+// Extracting sub-arrays and rejoining them is very performance and memory intensive so the same
+// (readonly) data arrays are passed arround together with their lower and upper bounds.
+// This circumstance makes the LCS and SMS functions more complicate.
+// I added some code to the LCS function to get a fast response on sub-arrays that are identical,
+// completely deleted or inserted.
+//
+// The result from a comparisation is stored in 2 arrays that flag for modified (deleted or inserted)
+// lines in the 2 data arrays. These bits are then analysed to produce a array of Hunk objects.
+//
+// Further possible optimizations:
+// (first rule: don't do it; second: don't do it yet)
+// The arrays DataA and DataB are passed as parameters, but are never changed after the creation
+// so they can be members of the class to avoid the paramter overhead.
+// In SMS is a lot of boundary arithmetic in the for-D and for-k loops that can be done by increment
+// and decrement of local variables.
+// The DownVector and UpVector arrays are alywas created and destroyed each time the SMS gets called.
+// It is possible to reuse tehm when transfering them to members of the class.
+// See TODO: hints.
+//
+// Changes:
+// 2002.09.20 There was a "hang" in some situations.
+// Now I undestand a little bit more of the SMS algorithm.
+// There have been overlapping boxes; that where analyzed partial differently.
+// One return-point is enough.
+// A assertion was added in CreateDiffs when in debug-mode, that counts the number of equal (no modified) lines in both arrays.
+// They must be identical.
+//
+// 2003.02.07 Out of bounds error in the Up/Down vector arrays in some situations.
+// The two vetors are now accessed using different offsets that are adjusted using the start k-Line.
+// A test case is added.
+//
+// 2006.03.05 Some documentation and a direct Diff entry point.
+//
+// 2006.03.08 Refactored the API to static methods on the Diff class to make usage simpler.
+// 2006.03.10 using the standard Debug class for self-test now.
+// compile with: csc /target:exe /out:diffTest.exe /d:DEBUG /d:TRACE /d:SELFTEST Diff.cs
+// 2007.01.06 license agreement changed to a BSD style license.
+// 2007.06.03 added the Optimize method.
+// 2007.09.23 UpVector and DownVector optimization by Jan Stoklasa ().
+// 2008.05.31 Adjusted the testing code that failed because of the Optimize method (not a bug in the diff algorithm).
+// 2008.10.08 Fixing a test case and adding a new test case.
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace MonoDevelop.Ide.Editor.Util
+{
+ /// <summary>
+ /// A DiffHunk represents a single change in a diff between two files.
+ /// </summary>
+ public struct DiffHunk
+ {
+ public static readonly DiffHunk Empty = new DiffHunk (0, 0, 0, 0);
+
+ /// <summary>
+ /// Gets a value indicating whether this instance is empty.
+ /// </summary>
+ /// <value><c>true</c> if this instance is empty; otherwise, <c>false</c>.</value>
+ public bool IsEmpty {
+ get {
+ return InsertStart <= 0;
+ }
+ }
+
+ // TODO: Add option to change this value.
+ internal readonly int Context;
+
+ /// <summary>
+ /// Line number where the insertion starts.
+ /// </summary>
+ public readonly int InsertStart;
+
+ /// <summary>
+ /// Line number where the removal starts.
+ /// </summary>
+ public readonly int RemoveStart;
+
+ /// <summary>
+ /// Number of lines removed.
+ /// </summary>
+ public readonly int Removed;
+
+ /// <summary>
+ /// Number of lines inserted.
+ /// </summary>
+ public readonly int Inserted;
+
+ public DiffHunk (int removeStart, int insertStart, int removed, int inserted)
+ {
+ this.InsertStart = insertStart;
+ this.RemoveStart = removeStart;
+ this.Removed = removed;
+ this.Inserted = inserted;
+ this.Context = 3;
+ }
+
+ public int DistanceTo(DiffHunk other)
+ {
+ return other.RemoveStart - (this.RemoveStart + this.Removed);
+ }
+
+ public bool Overlaps(DiffHunk other)
+ {
+ return DistanceTo (other) < this.Context * 2;
+ }
+
+ public static bool operator ==(DiffHunk left, DiffHunk right)
+ {
+ return left.InsertStart == right.InsertStart && left.RemoveStart == right.RemoveStart &&
+ left.Removed == right.Removed && left.Inserted == right.Inserted;
+ }
+
+ public static bool operator !=(DiffHunk left, DiffHunk right)
+ {
+ return !(left == right);
+ }
+
+ public override bool Equals (object obj)
+ {
+ if (!(obj is DiffHunk))
+ return false;
+ return ((DiffHunk)obj) == this;
+ }
+
+ public override int GetHashCode ()
+ {
+ return InsertStart ^ RemoveStart ^ Inserted ^ Removed;
+ }
+
+ public override string ToString ()
+ {
+ if (IsEmpty)
+ return"[Hunk: Empty]";
+ return string.Format ("[Hunk: InsertStart={0}, RemoveStart={1}, Removed={2}, Inserted={3}]", InsertStart, RemoveStart, Removed, Inserted);
+ }
+ }
+
+ sealed class Diff
+ {
+ /// <summary>
+ /// Shortest Middle Snake Return Data
+ /// </summary>
+ struct SMSRD
+ {
+ internal int x, y;
+ }
+
+ static void Optimize<T> (DiffData<T> data)
+ {
+ int startPos = 0;
+ while (startPos < data.Length) {
+ while (startPos < data.Length && data.Modified[startPos] == false)
+ startPos++;
+ int endPos = startPos;
+ while (endPos < data.Length && data.Modified[endPos] == true)
+ endPos++;
+
+ if (endPos < data.Length && data.Data[startPos].Equals (data.Data[endPos])) {
+ data.Modified[startPos] = false;
+ data.Modified[endPos] = true;
+ } else {
+ startPos = endPos;
+ }
+ }
+ }
+
+ public static IEnumerable<DiffHunk> CharDiff (string left, string right)
+ {
+ return GetDiff (left != null ? left.ToCharArray () : new char[0], right != null ? right.ToCharArray () : new char[0]);
+ }
+
+ public static IEnumerable<DiffHunk> GetDiff<T> (T[] baseArray, T[] changedArray)
+ {
+ // The A-Version of the data (original data) to be compared.
+ var dataA = new DiffData<T> (baseArray);
+
+ // The B-Version of the data (modified data) to be compared.
+ var dataB = new DiffData<T> (changedArray);
+
+ int MAX = dataA.Length + dataB.Length + 1;
+ // vector for the (0,0) to (x,y) search
+ int[] downVector = new int[2 * MAX + 2];
+ // vector for the (u,v) to (N,M) search
+ int[] upVector = new int[2 * MAX + 2];
+
+ LCS (dataA, 0, dataA.Length, dataB, 0, dataB.Length, downVector, upVector);
+ return CreateDiffs (dataA, dataB);
+ }
+
+ /// <summary>Scan the tables of which lines are inserted and deleted,
+ /// producing an edit script in forward order.
+ /// </summary>
+ /// dynamic array
+ static IEnumerable<DiffHunk> CreateDiffs<T> (DiffData<T> baseData, DiffData<T> changedData)
+ {
+ int lineA = 0;
+ int lineB = 0;
+ while (lineA < baseData.Length || lineB < changedData
+ .Length) {
+ if (lineA < baseData.Length && !baseData.Modified[lineA] && lineB < changedData
+ .Length && !changedData
+ .Modified[lineB]) {
+ // equal lines
+ lineA++;
+ lineB++;
+
+ } else {
+ // maybe deleted and/or inserted lines
+ int startA = lineA;
+ int startB = lineB;
+
+ while (lineA < baseData.Length && (lineB >= changedData
+ .Length || baseData.Modified[lineA]))
+ // while (LineA < DataA.Length && DataA.Modified[LineA])
+ lineA++;
+
+ while (lineB < changedData
+ .Length && (lineA >= baseData.Length || changedData
+ .Modified[lineB]))
+ // while (LineB < DataB.Length && DataB.Modified[LineB])
+ lineB++;
+
+ if (startA < lineA || startB < lineB) {
+ // store a new difference-item
+ yield return new DiffHunk (startA + 1, startB + 1, lineA - startA, lineB - startB);
+ }
+ // if
+ }
+ // if
+ }
+ // while
+ }
+
+ /// <summary>
+ /// This is the algorithm to find the Shortest Middle Snake (SMS).
+ /// </summary>
+ /// <param name="dataA">sequence A</param>
+ /// <param name="lowerA">lower bound of the actual range in DataA</param>
+ /// <param name="upperA">upper bound of the actual range in DataA (exclusive)</param>
+ /// <param name="dataB">sequence B</param>
+ /// <param name="lowerB">lower bound of the actual range in DataB</param>
+ /// <param name="upperB">upper bound of the actual range in DataB (exclusive)</param>
+ /// <param name="downVector">a vector for the (0,0) to (x,y) search. Passed as a parameter for speed reasons.</param>
+ /// <param name="upVector">a vector for the (u,v) to (N,M) search. Passed as a parameter for speed reasons.</param>
+ /// <returns>a MiddleSnakeData record containing x,y and u,v</returns>
+ static SMSRD SMS<T> (DiffData<T> dataA, int lowerA, int upperA, DiffData<T> dataB, int lowerB, int upperB, int[] downVector, int[] upVector)
+ {
+ SMSRD ret;
+ int MAX = dataA.Length + dataB.Length + 1;
+
+ int downK = lowerA - lowerB;
+ // the k-line to start the forward search
+ int upK = upperA - upperB;
+ // the k-line to start the reverse search
+ int delta = (upperA - lowerA) - (upperB - lowerB);
+ bool oddDelta = (delta & 1) != 0;
+
+ // The vectors in the publication accepts negative indexes. the vectors implemented here are 0-based
+ // and are access using a specific offset: UpOffset UpVector and DownOffset for DownVektor
+ int downOffset = MAX - downK;
+ int upOffset = MAX - upK;
+
+ int MaxD = ((upperA - lowerA + upperB - lowerB) / 2) + 1;
+
+ // Debug.Write(2, "SMS", String.Format("Search the box: A[{0}-{1}] to B[{2}-{3}]", LowerA, UpperA, LowerB, UpperB));
+
+ // init vectors
+ downVector[downOffset + downK + 1] = lowerA;
+ upVector[upOffset + upK - 1] = upperA;
+
+ for (int D = 0; D <= MaxD; D++) {
+
+ // Extend the forward path.
+ for (int k = downK - D; k <= downK + D; k += 2) {
+ // Debug.Write(0, "SMS", "extend forward path " + k.ToString());
+
+ // find the only or better starting point
+ int x, y;
+ if (k == downK - D) {
+ x = downVector[downOffset + k + 1];
+ // down
+ } else {
+ x = downVector[downOffset + k - 1] + 1;
+ // a step to the right
+ if (k < downK + D && downVector[downOffset + k + 1] >= x)
+ x = downVector[downOffset + k + 1];
+ // down
+ }
+ y = x - k;
+
+ // find the end of the furthest reaching forward D-path in diagonal k.
+ while (x < upperA && y < upperB && dataA.Data[x].Equals (dataB.Data[y])) {
+ x++;
+ y++;
+ }
+ downVector[downOffset + k] = x;
+
+ // overlap ?
+ if (oddDelta && upK - D < k && k < upK + D) {
+ if (upVector[upOffset + k] <= downVector[downOffset + k]) {
+ ret.x = downVector[downOffset + k];
+ ret.y = downVector[downOffset + k] - k;
+ // ret.u = UpVector[UpOffset + k]; // 2002.09.20: no need for 2 points
+ // ret.v = UpVector[UpOffset + k] - k;
+ return (ret);
+ }
+ // if
+ }
+ // if
+ }
+ // for k
+ // Extend the reverse path.
+ for (int k = upK - D; k <= upK + D; k += 2) {
+ // Debug.Write(0, "SMS", "extend reverse path " + k.ToString());
+
+ // find the only or better starting point
+ int x, y;
+ if (k == upK + D) {
+ x = upVector[upOffset + k - 1];
+ // up
+ } else {
+ x = upVector[upOffset + k + 1] - 1;
+ // left
+ if (k > upK - D && upVector[upOffset + k - 1] < x)
+ x = upVector[upOffset + k - 1];
+ // up
+ }
+ // if
+ y = x - k;
+
+ while (x > lowerA && y > lowerB && dataA.Data[x - 1].Equals (dataB.Data[y - 1])) {
+ x--;
+ y--;
+ // diagonal
+ }
+ upVector[upOffset + k] = x;
+
+ // overlap ?
+ if (!oddDelta && downK - D <= k && k <= downK + D) {
+ if (upVector[upOffset + k] <= downVector[downOffset + k]) {
+ ret.x = downVector[downOffset + k];
+ ret.y = downVector[downOffset + k] - k;
+ // ret.u = UpVector[UpOffset + k]; // 2002.09.20: no need for 2 points
+ // ret.v = UpVector[UpOffset + k] - k;
+ return (ret);
+ }
+ // if
+ }
+ // if
+ }
+ // for k
+ }
+ // for D
+ throw new ApplicationException ("the algorithm should never come here.");
+ }
+ // SMS
+
+ /// <summary>
+ /// This is the divide-and-conquer implementation of the longest common-subsequence (LCS)
+ /// algorithm.
+ /// The published algorithm passes recursively parts of the A and B sequences.
+ /// To avoid copying these arrays the lower and upper bounds are passed while the sequences stay constant.
+ /// </summary>
+ /// <param name="dataA">sequence A</param>
+ /// <param name="lowerA">lower bound of the actual range in DataA</param>
+ /// <param name="upperA">upper bound of the actual range in DataA (exclusive)</param>
+ /// <param name="dataB">sequence B</param>
+ /// <param name="lowerB">lower bound of the actual range in DataB</param>
+ /// <param name="upperB">upper bound of the actual range in DataB (exclusive)</param>
+ /// <param name="downVector">a vector for the (0,0) to (x,y) search. Passed as a parameter for speed reasons.</param>
+ /// <param name="upVector">a vector for the (u,v) to (N,M) search. Passed as a parameter for speed reasons.</param>
+ static void LCS<T> (DiffData<T> dataA, int lowerA, int upperA, DiffData<T> dataB, int lowerB, int upperB, int[] downVector, int[] upVector)
+ {
+ // Fast walkthrough equal lines at the start
+ while (lowerA < upperA && lowerB < upperB && dataA.Data[lowerA].Equals (dataB.Data[lowerB])) {
+ lowerA++;
+ lowerB++;
+ }
+
+ // Fast walkthrough equal lines at the end
+ while (lowerA < upperA && lowerB < upperB && dataA.Data[upperA - 1].Equals (dataB.Data[upperB - 1])) {
+ --upperA;
+ --upperB;
+ }
+
+ if (lowerA == upperA) {
+ // mark as inserted lines.
+ while (lowerB < upperB)
+ dataB.Modified[lowerB++] = true;
+
+ } else if (lowerB == upperB) {
+ // mark as deleted lines.
+ while (lowerA < upperA)
+ dataA.Modified[lowerA++] = true;
+
+ } else {
+ // Find the middle snakea and length of an optimal path for A and B
+ SMSRD smsrd = SMS (dataA, lowerA, upperA, dataB, lowerB, upperB, downVector, upVector);
+ // Debug.Write(2, "MiddleSnakeData", String.Format("{0},{1}", smsrd.x, smsrd.y));
+
+ // The path is from LowerX to (x,y) and (x,y) to UpperX
+ LCS (dataA, lowerA, smsrd.x, dataB, lowerB, smsrd.y, downVector, upVector);
+ LCS (dataA, smsrd.x, upperA, dataB, smsrd.y, upperB, downVector, upVector);
+ // 2002.09.20: no need for 2 points
+ }
+ }
+ // LCS()
+
+ static void WriteHunks (Queue<DiffHunk> qh, IReadonlyTextDocument baseDocument, IReadonlyTextDocument changedDocument, StringBuilder sb)
+ {
+ DiffHunk item;
+ int remStart;
+ int insStart;
+ int distance = 0;
+
+ do {
+ item = qh.Dequeue ();
+ remStart = System.Math.Max (1, item.RemoveStart - (distance != 0 ? distance : item.Context));
+ insStart = System.Math.Max (1, item.InsertStart - (distance != 0 ? distance : item.Context));
+
+ for (int i = System.Math.Min (remStart, insStart); i < item.RemoveStart; i++) {
+ sb.AppendLine (" " + baseDocument.GetLineText (i, false));
+ }
+ for (int i = item.RemoveStart; i < item.RemoveStart + item.Removed; i++) {
+ sb.AppendLine ("-" + baseDocument.GetLineText (i, false));
+ }
+ for (int i = item.InsertStart; i < item.InsertStart + item.Inserted; i++) {
+ sb.AppendLine ("+" + changedDocument.GetLineText (i, false));
+ }
+
+ if (qh.Count != 0)
+ distance = item.DistanceTo (qh.Peek ());
+ } while (qh.Count != 0);
+
+ int remEnd = System.Math.Min (baseDocument.LineCount, item.RemoveStart + item.Removed + item.Context);
+ for (int i = item.RemoveStart + item.Removed; i < remEnd; i++) {
+ sb.AppendLine (" " + baseDocument.GetLineText (i, false));
+ }
+ }
+
+ public static string GetDiffString (IReadonlyTextDocument baseDocument, IReadonlyTextDocument changedDocument)
+ {
+ return GetDiffString (baseDocument.GetDiff (changedDocument), baseDocument, changedDocument, baseDocument.FileName, changedDocument.FileName);
+ }
+
+ public static string GetDiffString (IEnumerable<DiffHunk> diff, IReadonlyTextDocument baseDocument, IReadonlyTextDocument changedDocument, string baseFileName, string changedFileName)
+ {
+ if (diff == null)
+ return "";
+
+ StringBuilder sb = new StringBuilder ();
+ IEnumerator<DiffHunk> he = diff.GetEnumerator ();
+ he.MoveNext ();
+
+ Queue<DiffHunk> qh = new Queue<DiffHunk> ();
+ DiffHunk current;
+ DiffHunk next;
+
+ if (he.Current.IsEmpty)
+ return "";
+
+ sb.AppendLine ("--- " + baseFileName);
+ sb.AppendLine ("+++ " + changedFileName);
+
+ current = he.Current;
+
+ qh.Enqueue (current);
+ int remStart = System.Math.Max (1, current.RemoveStart - current.Context);
+ int remEnd = System.Math.Min (baseDocument.LineCount, current.RemoveStart + current.Removed + current.Context);
+ int insStart = System.Math.Max (1, current.InsertStart - current.Context);
+ int insEnd = System.Math.Min (changedDocument.LineCount, current.InsertStart + current.Inserted + current.Context);
+
+ while (he.MoveNext ()) {
+ next = he.Current;
+
+ if (current.Overlaps (next)) {
+ // Change upper bounds.
+ remEnd = System.Math.Min (baseDocument.LineCount, next.RemoveStart + next.Removed + next.Context);
+ insEnd = System.Math.Min (changedDocument.LineCount, next.InsertStart + next.Inserted + next.Context);
+ } else {
+ sb.AppendLine ("@@ -" + remStart + "," + (remEnd - remStart) + " +" + insStart + "," + (insEnd - insStart) + " @@");
+ WriteHunks (qh, baseDocument, changedDocument, sb);
+
+ remStart = System.Math.Max (1, next.RemoveStart - next.Context);
+ remEnd = System.Math.Min (baseDocument.LineCount, next.RemoveStart + next.Removed + next.Context);
+ insStart = System.Math.Max (1, next.InsertStart - next.Context);
+ insEnd = System.Math.Min (changedDocument.LineCount, next.InsertStart + next.Inserted + next.Context);
+ }
+ qh.Enqueue (next);
+
+ current = next;
+ }
+
+ if (qh.Count != 0) {
+ sb.AppendLine ("@@ -" + remStart + "," + (remEnd - remStart) + " +" + insStart + "," + (insEnd - insStart) + " @@");
+ WriteHunks (qh, baseDocument, changedDocument, sb);
+ }
+ return sb.ToString ();
+ }
+ }
+
+ /// <summary>Data on one input file being compared.
+ /// </summary>
+ class DiffData<T>
+ {
+ /// <summary>Number of elements (lines).</summary>
+ public readonly int Length;
+
+ /// <summary>Buffer of numbers that will be compared.</summary>
+ public readonly T[] Data;
+
+ /// <summary>
+ /// Array of booleans that flag for modified data.
+ /// This is the result of the diff.
+ /// This means deletedA in the first Data or inserted in the second Data.
+ /// </summary>
+ public readonly bool[] Modified;
+
+ /// <summary>
+ /// Initialize the Diff-Data buffer.
+ /// </summary>
+ /// <param name="initData">reference to the buffer</param>
+ public DiffData (T[] initData)
+ {
+ Data = initData;
+ Length = initData.Length;
+ Modified = new bool[Length + 2];
+ }
+ // DiffData
+ }
+ // class DiffData
+}
+// namespace
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Util/SimpleBracketMatcher.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Util/SimpleBracketMatcher.cs
new file mode 100644
index 0000000000..b7cc92bb45
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Util/SimpleBracketMatcher.cs
@@ -0,0 +1,273 @@
+//
+// SimpleBracketMatcher.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 System.Collections.Generic;
+using MonoDevelop.Ide.Editor.Highlighting;
+
+namespace MonoDevelop.Ide.Editor.Util
+{
+ public static class SimpleBracketMatcher
+ {
+ const string openBrackets = "([{<";
+ const string closingBrackets = ")]}>";
+
+
+ public static int GetMatchingBracketOffset (IReadonlyTextDocument document, int offset)
+ {
+ if (offset < 0 || offset >= document.Length)
+ return -1;
+ char ch = document.GetCharAt (offset);
+ int bracket = openBrackets.IndexOf (ch);
+ int result;
+ if (bracket >= 0) {
+ result = SearchMatchingBracketForward (document, offset + 1, closingBrackets [bracket], openBrackets [bracket]);
+ } else {
+ bracket = closingBrackets.IndexOf (ch);
+ if (bracket >= 0) {
+ result = SearchMatchingBracketBackward (document, offset - 1, openBrackets [bracket], closingBrackets [bracket]);
+ } else {
+ result = -1;
+ }
+ }
+ return result;
+ }
+
+ static readonly string [] emptyList = new string [0];
+ static string [] GetList (IReadonlyTextDocument document, string name)
+ {
+ return TextEditorFactory.GetSyntaxProperties (document.MimeType, name) ?? emptyList;
+ }
+
+ static int StartsWithListMember (IReadonlyTextDocument document, IList<string> list, int offset)
+ {
+ if (document == null)
+ throw new ArgumentNullException ("document");
+ if (list == null)
+ throw new ArgumentNullException ("list");
+ for (int i = 0; i < list.Count; i++) {
+ string item = list [i];
+ if (offset + item.Length < document.Length) {
+ if (document.GetTextAt (offset, item.Length) == item)
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ static int SearchMatchingBracketForward (IReadonlyTextDocument document, int offset, char openBracket, char closingBracket)
+ {
+ bool isInBlockComment = false;
+ bool isInLineComment = false;
+ int curStringQuote = -1;
+
+ bool startsInLineComment = StartsInLineComment (document, offset);
+
+ var lineComments = GetList (document, "LineComment");
+ var blockCommentStarts = GetList (document, "BlockCommentStart");
+ var blockCommentEnds = GetList (document, "BlockCommentEnd");
+ var stringQuotes = GetList (document, "StringQuote");
+ int depth = -1;
+ while (offset >= 0 && offset < document.Length) {
+ if (curStringQuote < 0) {
+ // check line comments
+ if (!isInBlockComment && !isInLineComment)
+ isInLineComment = StartsWithListMember (document, lineComments, offset) >= 0;
+
+ // check block comments
+ if (!isInLineComment) {
+ if (!isInBlockComment) {
+ isInBlockComment = StartsWithListMember (document, blockCommentStarts, offset) >= 0;
+ } else {
+ isInBlockComment = StartsWithListMember (document, blockCommentEnds, offset) < 0;
+ }
+ }
+ }
+
+ if (!isInBlockComment && !isInLineComment) {
+ int i = StartsWithListMember (document, stringQuotes, offset);
+ if (i >= 0) {
+ if (curStringQuote >= 0) {
+ if (curStringQuote == i)
+ curStringQuote = -1;
+ } else {
+ curStringQuote = i;
+ }
+ }
+ }
+
+ char ch = document.GetCharAt (offset);
+ switch (ch) {
+ case '\n':
+ case '\r':
+ if (startsInLineComment)
+ return -1;
+ isInLineComment = false;
+ break;
+ default:
+ if (ch == closingBracket) {
+ if (!(isInLineComment || curStringQuote >= 0 || isInBlockComment))
+ --depth;
+ } else if (ch == openBracket) {
+ if (!(isInLineComment || curStringQuote >= 0 || isInBlockComment)) {
+ ++depth;
+ if (depth == 0)
+ return offset;
+ }
+ }
+ break;
+ }
+ offset++;
+ }
+ return -1;
+ }
+
+ static bool StartsInLineComment (IReadonlyTextDocument document, int offset)
+ {
+ IList<string> lineComments = GetList (document, "LineComment");
+ var line = document.GetLineByOffset (offset);
+ for (int i = line.Offset; i < offset; i++) {
+ if (StartsWithListMember (document, lineComments, i) >= 0)
+ return true;
+ }
+ return false;
+ }
+
+ static int GetLastSourceCodePosition (IReadonlyTextDocument document, int lineOffset)
+ {
+ var line = document.GetLineByOffset (lineOffset);
+ bool isInBlockComment = false;
+ bool isInLineComment = false;
+ int curStringQuote = -1;
+
+ IList<string> lineComments = GetList (document, "LineComment");
+ IList<string> blockCommentStarts = GetList (document, "BlockCommentStart");
+ IList<string> blockCommentEnds = GetList (document, "BlockCommentEnd");
+ IList<string> stringQuotes = GetList (document, "StringQuote");
+
+ for (int i = 0; i < line.Length; i++) {
+ int offset = line.Offset + i;
+ // check line comments
+ if (!isInBlockComment && curStringQuote < 0) {
+ isInLineComment = StartsWithListMember (document, lineComments, offset) >= 0;
+ if (isInLineComment)
+ return System.Math.Min (offset, lineOffset);
+ }
+ // check block comments
+ if (!isInLineComment && curStringQuote < 0) {
+ if (!isInBlockComment) {
+ isInBlockComment = StartsWithListMember (document, blockCommentStarts, offset) >= 0;
+ } else {
+ isInBlockComment = StartsWithListMember (document, blockCommentEnds, offset) < 0;
+ }
+ }
+
+ if (!isInBlockComment && !isInLineComment) {
+ int j = StartsWithListMember (document, stringQuotes, offset);
+ if (j >= 0) {
+ if (curStringQuote >= 0) {
+ if (curStringQuote == j)
+ curStringQuote = -1;
+ } else {
+ curStringQuote = j;
+ }
+ }
+ }
+ }
+ return lineOffset;
+ }
+
+ static int SearchMatchingBracketBackward (IReadonlyTextDocument document, int offset, char openBracket, char closingBracket)
+ {
+ bool isInBlockComment = false;
+ bool isInLineComment = false;
+ int curStringQuote = -1;
+
+ IList<string> blockCommentStarts = GetList (document, "BlockCommentStart");
+ IList<string> blockCommentEnds = GetList (document, "BlockCommentEnd");
+ IList<string> stringQuotes = GetList (document, "StringQuote");
+
+ bool startsInLineComment = StartsInLineComment (document, offset);
+ int depth = -1;
+
+ if (!startsInLineComment)
+ offset = GetLastSourceCodePosition (document, offset);
+
+ while (offset >= 0 && offset < document.Length) {
+ char ch = document.GetCharAt (offset);
+
+ // check block comments
+ if (!isInLineComment && curStringQuote < 0) {
+ if (!isInBlockComment) {
+ isInBlockComment = StartsWithListMember (document, blockCommentEnds, offset) >= 0;
+ } else {
+ isInBlockComment = StartsWithListMember (document, blockCommentStarts, offset) < 0;
+ }
+ }
+
+ if (!isInBlockComment && !isInLineComment) {
+ int i = StartsWithListMember (document, stringQuotes, offset);
+ if (i >= 0) {
+ if (curStringQuote >= 0) {
+ if (curStringQuote == i)
+ curStringQuote = -1;
+ } else {
+ curStringQuote = i;
+ }
+ }
+ }
+
+ switch (ch) {
+ case '\n':
+ case '\r':
+ if (startsInLineComment)
+ return -1;
+ offset--;
+ while (offset > 0 && (document.GetCharAt (offset) == '\n' || document.GetCharAt (offset) == '\r')) {
+ offset--;
+ }
+ offset = GetLastSourceCodePosition (document, offset) + 1;
+ break;
+ default:
+ if (ch == closingBracket) {
+ if (!(curStringQuote >= 0 || isInBlockComment))
+ --depth;
+ } else if (ch == openBracket) {
+ if (!(curStringQuote >= 0 || isInBlockComment)) {
+ ++depth;
+ if (depth == 0)
+ return offset;
+ }
+ }
+ break;
+ }
+ offset--;
+ }
+ return -1;
+ }
+ }
+
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Util/SimpleReadonlyDocument.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Util/SimpleReadonlyDocument.cs
new file mode 100644
index 0000000000..2b03c40335
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Util/SimpleReadonlyDocument.cs
@@ -0,0 +1,414 @@
+//
+// SimpleReadonlyDocument.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Core.Text;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using MonoDevelop.Core;
+using System.Threading;
+
+namespace MonoDevelop.Ide.Editor.Util
+{
+ /// <summary>
+ /// A simple and fast implementation for a read only text document.
+ /// </summary>
+ public class SimpleReadonlyDocument : IReadonlyTextDocument
+ {
+ readonly ITextSource textSource;
+ readonly List<Delimiter> delimiters = new List<Delimiter> ();
+
+ SimpleReadonlyDocument (ITextSource readOnlyTextSource, string fileName, string mimeType)
+ {
+ textSource = readOnlyTextSource;
+ FileName = fileName;
+ MimeType = mimeType;
+ Initalize (readOnlyTextSource.Text);
+ }
+
+ /// <summary>
+ /// Creates a new readonly document. Note that the text source is not copied - it needs to be read only.
+ /// </summary>
+ /// <returns>The readonly document async.</returns>
+ /// <param name="readOnlyTextSource">Read only text source.</param>
+ /// <param name="fileName">File name.</param>
+ public static Task<IReadonlyTextDocument> CreateReadonlyDocumentAsync (ITextSource readOnlyTextSource, string fileName = null, string mimeType = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return Task.Run (delegate {
+ return (IReadonlyTextDocument)new SimpleReadonlyDocument (readOnlyTextSource, fileName, mimeType);
+ }, cancellationToken);
+ }
+
+ void Initalize (string text)
+ {
+ int offset = 0;
+ while (true) {
+ var delimiter = NextDelimiter (text, offset);
+ if (delimiter.IsInvalid)
+ break;
+
+ delimiters.Add (delimiter);
+
+ offset = delimiter.EndOffset;
+ }
+ }
+
+ static unsafe Delimiter NextDelimiter (string text, int offset)
+ {
+ fixed (char* start = text) {
+ char* p = start + offset;
+ char* endPtr = start + text.Length;
+
+ while (p < endPtr) {
+ switch (*p) {
+ case NewLine.CR:
+ char* nextp = p + 1;
+ if (nextp < endPtr && *nextp == NewLine.LF)
+ return new Delimiter ((int)(p - start), UnicodeNewline.CRLF);
+ return new Delimiter ((int)(p - start), UnicodeNewline.CR);
+ case NewLine.LF:
+ return new Delimiter ((int)(p - start), UnicodeNewline.LF);
+ case NewLine.NEL:
+ return new Delimiter ((int)(p - start), UnicodeNewline.NEL);
+ case NewLine.VT:
+ return new Delimiter ((int)(p - start), UnicodeNewline.VT);
+ case NewLine.FF:
+ return new Delimiter ((int)(p - start), UnicodeNewline.FF);
+ case NewLine.LS:
+ return new Delimiter ((int)(p - start), UnicodeNewline.LS);
+ case NewLine.PS:
+ return new Delimiter ((int)(p - start), UnicodeNewline.PS);
+ }
+ p++;
+ }
+ return Delimiter.Invalid;
+ }
+ }
+
+ struct Delimiter
+ {
+ public static readonly Delimiter Invalid = new Delimiter (-1, 0);
+
+ public readonly int Offset;
+ public readonly UnicodeNewline UnicodeNewline;
+
+ public int Length {
+ get {
+ return UnicodeNewline == UnicodeNewline.CRLF ? 2 : 1;
+ }
+ }
+
+ public int EndOffset {
+ get { return Offset + Length; }
+ }
+
+ public bool IsInvalid {
+ get {
+ return Offset < 0;
+ }
+ }
+
+ public Delimiter (int offset, UnicodeNewline unicodeNewline)
+ {
+ Offset = offset;
+ UnicodeNewline = unicodeNewline;
+ }
+ }
+
+ int OffsetToLineNumber (int offset)
+ {
+ for (int i = 0; i < delimiters.Count; i++) {
+ var delimiter = delimiters[i];
+ if (offset <= delimiter.Offset)
+ return i + 1;
+ }
+ return delimiters.Count + 1;
+ }
+
+ #region IReadonlyTextDocument implementation
+
+ /// <inheritdoc/>
+ public int LocationToOffset (int line, int column)
+ {
+ if (line > LineCount || line < DocumentLocation.MinLine)
+ return -1;
+ var documentLine = GetLine (line);
+ return Math.Min (Length, documentLine.Offset + Math.Max (0, Math.Min (documentLine.Length, column - 1)));
+ }
+
+ /// <inheritdoc/>
+ public DocumentLocation OffsetToLocation (int offset)
+ {
+ int lineNr = OffsetToLineNumber (offset);
+ if (lineNr < 1)
+ return DocumentLocation.Empty;
+ var line = GetLine (lineNr);
+ var col = Math.Max (1, Math.Min (line.LengthIncludingDelimiter, offset - line.Offset) + 1);
+ return new DocumentLocation (lineNr, col);
+ }
+
+ /// <inheritdoc/>
+ public IDocumentLine GetLine (int number)
+ {
+ number--;
+ if (number < 0)
+ return null;
+ int startOffset = number > 0 ? delimiters[number - 1].EndOffset : 0;
+ int endOffset;
+ UnicodeNewline newLine;
+ if (number < delimiters.Count) {
+ endOffset = delimiters[number].EndOffset;
+ newLine = delimiters[number].UnicodeNewline;
+ } else {
+ endOffset = Length;
+ newLine = UnicodeNewline.Unknown;
+ }
+ return new SimpleLineSegment (this, number + 1, startOffset, endOffset - startOffset, newLine);
+ }
+
+ sealed class SimpleLineSegment : IDocumentLine
+ {
+ readonly SimpleReadonlyDocument splitter;
+
+ public SimpleLineSegment (SimpleReadonlyDocument splitter, int lineNumber, int offset, int length, UnicodeNewline newLine)
+ {
+ this.splitter = splitter;
+ LineNumber = lineNumber;
+ LengthIncludingDelimiter = length;
+ UnicodeNewline = newLine;
+ Offset = offset;
+ }
+
+ #region IDocumentLine implementation
+
+ public int LengthIncludingDelimiter {
+ get;
+ private set;
+ }
+
+ public int EndOffsetIncludingDelimiter {
+ get {
+ return Offset + LengthIncludingDelimiter;
+ }
+ }
+
+ public ISegment SegmentIncludingDelimiter {
+ get {
+ return new TextSegment (Offset, LengthIncludingDelimiter);
+ }
+ }
+
+ public UnicodeNewline UnicodeNewline {
+ get;
+ private set;
+ }
+
+ public int DelimiterLength {
+ get {
+ switch (UnicodeNewline) {
+ case UnicodeNewline.Unknown:
+ return 0;
+ case UnicodeNewline.CRLF:
+ return 2;
+ default:
+ return 1;
+ }
+ }
+ }
+
+ public int LineNumber {
+ get;
+ private set;
+ }
+
+ public IDocumentLine PreviousLine {
+ get {
+ if (LineNumber == 1)
+ return null;
+ return splitter.GetLine (LineNumber - 1);
+ }
+ }
+
+ public IDocumentLine NextLine {
+ get {
+ if (LineNumber >= splitter.LineCount)
+ return null;
+ return splitter.GetLine (LineNumber + 1);
+ }
+ }
+
+ public bool IsDeleted {
+ get {
+ return false;
+ }
+ }
+ #endregion
+
+ #region ISegment implementation
+
+ public int Offset {
+ get;
+ private set;
+ }
+
+ public int Length {
+ get {
+ return LengthIncludingDelimiter - DelimiterLength;
+ }
+ }
+
+ public int EndOffset {
+ get {
+ return Offset + Length;
+ }
+ }
+ #endregion
+ }
+
+ /// <inheritdoc/>
+ public IDocumentLine GetLineByOffset (int offset)
+ {
+ return GetLine (OffsetToLineNumber (offset));
+ }
+
+ /// <inheritdoc/>
+ public bool IsReadOnly {
+ get {
+ return true;
+ }
+ }
+
+ /// <inheritdoc/>
+ public FilePath FileName {
+ get;
+ private set;
+ }
+
+ /// <inheritdoc/>
+ public string MimeType {
+ get;
+ private set;
+ }
+
+ /// <inheritdoc/>
+ public int LineCount {
+ get {
+ return delimiters.Count + 1;
+ }
+ }
+ #endregion
+
+ #region ITextSource implementation
+
+ /// <inheritdoc/>
+ public char GetCharAt (int offset)
+ {
+ return textSource.GetCharAt (offset);
+ }
+
+ public char this [int offset] {
+ get {
+ return textSource.GetCharAt (offset);
+ }
+ }
+
+ /// <inheritdoc/>
+ public string GetTextAt (int offset, int length)
+ {
+ return textSource.GetTextAt (offset, length);
+ }
+
+ /// <inheritdoc/>
+ public System.IO.TextReader CreateReader ()
+ {
+ return textSource.CreateReader ();
+ }
+
+ /// <inheritdoc/>
+ public System.IO.TextReader CreateReader (int offset, int length)
+ {
+ return textSource.CreateReader (offset, length);
+ }
+
+ /// <inheritdoc/>
+ public void WriteTextTo (System.IO.TextWriter writer)
+ {
+ textSource.WriteTextTo (writer);
+ }
+
+ /// <inheritdoc/>
+ public void WriteTextTo (System.IO.TextWriter writer, int offset, int length)
+ {
+ textSource.WriteTextTo (writer, offset, length);
+ }
+
+ /// <inheritdoc/>
+ public ITextSourceVersion Version {
+ get {
+ return textSource.Version;
+ }
+ }
+
+ /// <inheritdoc/>
+ public bool UseBOM {
+ get {
+ return textSource.UseBOM;
+ }
+ }
+
+ /// <inheritdoc/>
+ public System.Text.Encoding Encoding {
+ get {
+ return textSource.Encoding;
+ }
+ }
+
+ /// <inheritdoc/>
+ public int Length {
+ get {
+ return textSource.Length;
+ }
+ }
+
+ /// <inheritdoc/>
+ public string Text {
+ get {
+ return textSource.Text;
+ }
+ }
+
+ public ITextSource CreateSnapshot ()
+ {
+ return this;
+ }
+
+ public ITextSource CreateSnapshot (int offset, int length)
+ {
+ return new StringTextSource (Text.Substring (offset, length));
+ }
+ #endregion
+
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/AutoSave.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/AutoSave.cs
new file mode 100644
index 0000000000..a0eacc97ef
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/AutoSave.cs
@@ -0,0 +1,225 @@
+//
+// AutoSave.cs
+//
+// Author:
+// Mike Krüger <mkrueger@novell.com>
+//
+// Copyright (c) 2009 Novell, Inc (http://www.novell.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.IO;
+using System.Threading;
+using MonoDevelop.Core;
+using Gtk;
+using MonoDevelop.Core.Text;
+
+namespace MonoDevelop.Ide.Editor
+{
+ /// <summary>
+ /// This class handles the auto save mechanism for open files.
+ /// It should only be used by editor implementations.
+ /// </summary>
+ static class AutoSave
+ {
+ //FIXME: is this path a good one? wouldn't it be better to put autosaves beside the files anyway?
+ static string autoSavePath = UserProfile.Current.CacheDir.Combine ("AutoSave");
+ static bool autoSaveEnabled;
+
+ static AutoSave ()
+ {
+ try {
+ if (!Directory.Exists (autoSavePath))
+ Directory.CreateDirectory (autoSavePath);
+ } catch (Exception e) {
+ LoggingService.LogError ("Can't create auto save path:" + autoSavePath +". Auto save is disabled.", e);
+ autoSaveEnabled = false;
+ return;
+ }
+ autoSaveEnabled = true;
+ StartAutoSaveThread ();
+ }
+
+ static string GetAutoSaveFileName (string fileName)
+ {
+ if (fileName == null)
+ return null;
+ string newFileName = Path.Combine (Path.GetDirectoryName (fileName), Path.GetFileNameWithoutExtension (fileName) + Path.GetExtension (fileName) + "~");
+ newFileName = Path.Combine (autoSavePath, newFileName.Replace(',','_').Replace(" ","").Replace (":","").Replace (Path.DirectorySeparatorChar, '_').Replace (Path.AltDirectorySeparatorChar, '_'));
+ return newFileName;
+ }
+
+ /// <summary>
+ /// Returns true if an auto save exists for the given file name.
+ /// </summary>
+ public static bool AutoSaveExists (string fileName)
+ {
+ if (!autoSaveEnabled)
+ return false;
+ try {
+ var autoSaveFilename = GetAutoSaveFileName (fileName);
+ bool autoSaveExists = File.Exists (autoSaveFilename);
+ if (autoSaveExists) {
+ if (File.GetLastWriteTimeUtc (autoSaveFilename) < File.GetLastWriteTimeUtc (fileName)) {
+ File.Delete (autoSaveFilename);
+ return false;
+ }
+ }
+ return autoSaveExists;
+ } catch (Exception e) {
+ LoggingService.LogError ("Error in auto save - disableing.", e);
+ DisableAutoSave ();
+ return false;
+ }
+ }
+
+ static void CreateAutoSave (string fileName, ITextSource content)
+ {
+ if (!autoSaveEnabled)
+ return;
+ try {
+ // Directory may have removed/unmounted. Therefore this operation is not guaranteed to work.
+ var autosaveFileName = GetAutoSaveFileName (fileName);
+ if (File.Exists (autosaveFileName))
+ File.Delete (autosaveFileName);
+ content.WriteTextTo (autosaveFileName);
+ Counters.AutoSavedFiles++;
+ } catch (Exception e) {
+ LoggingService.LogError ("Error in auto save while creating: " + fileName +". Disableing auto save.", e);
+ DisableAutoSave ();
+ }
+ }
+
+ #region AutoSave
+ class FileContent
+ {
+ public string FileName;
+ public ITextSource Content;
+
+ public FileContent (string fileName, ITextSource content)
+ {
+ this.FileName = fileName;
+ this.Content = content;
+ }
+ }
+ static readonly AutoResetEvent resetEvent = new AutoResetEvent (false);
+
+ public static bool Running {
+ get {
+ return autoSaveThreadRunning;
+ }
+ }
+ static bool autoSaveThreadRunning = false;
+ static Thread autoSaveThread;
+ static Queue<FileContent> queue = new Queue<FileContent> ();
+ static object contentLock = new object ();
+
+ static void StartAutoSaveThread ()
+ {
+ autoSaveThreadRunning = true;
+ if (autoSaveThread == null) {
+ autoSaveThread = new Thread (AutoSaveThread);
+ autoSaveThread.Name = "Autosave";
+ autoSaveThread.IsBackground = true;
+ autoSaveThread.Start ();
+ }
+ }
+
+ static void AutoSaveThread ()
+ {
+ while (autoSaveThreadRunning) {
+ resetEvent.WaitOne ();
+ while (queue.Count > 0) {
+ var content = queue.Dequeue ();
+ // Don't create an auto save for unsaved files.
+ if (string.IsNullOrEmpty (content.FileName))
+ continue;
+ CreateAutoSave (content.FileName, content.Content);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Loads the content from an auto save file and removes the auto save file.
+ /// </summary>
+ public static ITextSource LoadAndRemoveAutoSave (string fileName)
+ {
+ string autoSaveFileName = GetAutoSaveFileName (fileName);
+ var result = StringTextSource.ReadFrom (autoSaveFileName);
+ AutoSave.RemoveAutoSaveFile (fileName);
+ return result;
+ }
+
+ /// <summary>
+ /// Loads the content from an auto save file.
+ /// </summary>
+ public static ITextSource LoadAutoSave (string fileName)
+ {
+ string autoSaveFileName = GetAutoSaveFileName (fileName);
+ return StringTextSource.ReadFrom (autoSaveFileName);
+ }
+
+ /// <summary>
+ /// Removes the auto save file.
+ /// </summary>
+ /// <param name="fileName">The file name for which the auto save file should be removed.</param>
+ public static void RemoveAutoSaveFile (string fileName)
+ {
+ if (!autoSaveEnabled)
+ return;
+ if (AutoSaveExists (fileName)) {
+ string autoSaveFileName = GetAutoSaveFileName (fileName);
+ try {
+ lock (contentLock) {
+ File.Delete (autoSaveFileName);
+ }
+ } catch (Exception e) {
+ LoggingService.LogError ("Can't delete auto save file: " + autoSaveFileName +". Disableing auto save.", e);
+ DisableAutoSave ();
+ }
+ }
+ }
+
+ internal static void InformAutoSaveThread (ITextSource content, string fileName, bool isDirty)
+ {
+ if (content == null || !autoSaveEnabled)
+ return;
+ if (isDirty) {
+ queue.Enqueue (new FileContent (fileName, content));
+ resetEvent.Set ();
+ } else {
+ RemoveAutoSaveFile (fileName);
+ }
+ }
+
+ static void DisableAutoSave ()
+ {
+ autoSaveThreadRunning = false;
+ if (autoSaveThread != null) {
+ resetEvent.Set ();
+ autoSaveThread.Join ();
+ autoSaveThread = null;
+ }
+ autoSaveEnabled = false;
+ }
+#endregion
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Commands/DynamicAbbrevHandler.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Commands/DynamicAbbrevHandler.cs
new file mode 100644
index 0000000000..08306da514
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Commands/DynamicAbbrevHandler.cs
@@ -0,0 +1,193 @@
+//
+// DynamicAbbrevHandler.cs
+//
+// Author:
+// Mike Krüger <mkrueger@novell.com>
+//
+// Copyright (c) 2009 Novell, Inc (http://www.novell.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 MonoDevelop.Components.Commands;
+using MonoDevelop.Ide.Gui;
+using System.Collections.Generic;
+using MonoDevelop.Ide;
+
+namespace MonoDevelop.Ide.Editor
+{
+ class DynamicAbbrevHandler : CommandHandler
+ {
+ enum AbbrevState {
+ SearchBackward,
+ SearchForward,
+ SearchOtherBuffers,
+ CycleThroughFoundWords
+ }
+
+ static TextEditor lastView = null;
+ static string lastAbbrev = null;
+ static int lastTriggerOffset = 0;
+ static int lastInsertPos = 0;
+ static List<string> foundWords = new List<string> ();
+ static int lastStartOffset = 0;
+ static AbbrevState curState;
+
+ protected override void Run (object data)
+ {
+ var doc = IdeApp.Workbench.ActiveDocument;
+ if (doc == null)
+ return;
+ var editor = doc.Editor;
+ if (editor == null)
+ return;
+
+ string abbrevWord;
+ int offset;
+ int startOffset;
+
+ if (lastView == editor && editor.CaretOffset == lastTriggerOffset) {
+ abbrevWord = lastAbbrev;
+ offset = lastStartOffset;
+ } else {
+ abbrevWord = GetWordBeforeCaret (editor);
+ lastAbbrev = abbrevWord;
+ offset = editor.CaretOffset - abbrevWord.Length - 1;
+ lastInsertPos = lastTriggerOffset = offset + 1;
+ foundWords.Clear ();
+ foundWords.Add (abbrevWord);
+ curState = AbbrevState.SearchBackward;
+ }
+
+ lastView = editor;
+ switch (curState) {
+ case AbbrevState.SearchBackward:
+ while (offset > 0) {
+ if (IsMatchAt (editor, offset, abbrevWord)) {
+ int endOffset = SearchEndPos (offset, editor);
+ string curWord = editor.GetTextBetween (offset, endOffset);
+ if (foundWords.Contains (curWord)) {
+ offset--;
+ continue;
+ }
+ foundWords.Add (curWord);
+ ReplaceWord (editor, curWord);
+ lastStartOffset = offset - 1;
+ return;
+ }
+ offset--;
+ }
+ offset = editor.CaretOffset;
+ curState = AbbrevState.SearchForward;
+ goto case AbbrevState.SearchForward;
+ case AbbrevState.SearchForward:
+ while (offset < editor.Length) {
+ if (IsMatchAt (editor, offset, abbrevWord)) {
+ int endOffset = SearchEndPos (offset, editor);
+ string curWord = editor.GetTextBetween (offset, endOffset);
+ if (foundWords.Contains (curWord)) {
+ offset++;
+ continue;
+ }
+ foundWords.Add (curWord);
+ ReplaceWord (editor, curWord);
+ lastStartOffset = offset + 1;
+ return;
+ }
+ offset++;
+ }
+ curState = AbbrevState.SearchOtherBuffers;
+ goto case AbbrevState.SearchOtherBuffers;
+ case AbbrevState.SearchOtherBuffers:
+ foreach (Document curDoc in IdeApp.Workbench.Documents) {
+ var otherView = curDoc.GetContent<TextEditor> ();
+ if (curDoc == doc || otherView == null)
+ continue;
+ for (int i = 0; i < otherView.Length; i++) {
+ if (IsMatchAt (otherView, i, abbrevWord)) {
+ int endOffset = SearchEndPos (i, otherView);
+ string curWord = otherView.GetTextBetween (i, endOffset);
+ if (foundWords.Contains (curWord))
+ continue;
+ foundWords.Add (curWord);
+ }
+ }
+ }
+ curState = AbbrevState.CycleThroughFoundWords;
+ goto case AbbrevState.CycleThroughFoundWords;
+ case AbbrevState.CycleThroughFoundWords:
+ int index = foundWords.IndexOf (editor.GetTextAt (lastInsertPos, editor.CaretOffset - lastInsertPos));
+ if (index < 0)
+ break;
+ startOffset = offset;
+ offset = startOffset + foundWords[index].Length;
+ index = (index + foundWords.Count + 1) % foundWords.Count;
+ ReplaceWord (editor, foundWords[index]);
+ break;
+ }
+ }
+
+ public static bool IsIdentifierPart (char ch)
+ {
+ return char.IsLetterOrDigit (ch) || ch == '_';
+ }
+
+ static string GetWordBeforeCaret (TextEditor editor)
+ {
+ int startOffset = editor.CaretOffset;
+ int offset = startOffset - 1;
+ while (offset > 0) {
+ char ch = editor.GetCharAt (offset);
+ if (!IsIdentifierPart (ch)) {
+ offset++;
+ break;
+ }
+ offset--;
+ }
+ if (offset >= startOffset)
+ return "";
+ return editor.GetTextBetween (offset, startOffset);
+ }
+
+ static void ReplaceWord (TextEditor editor, string curWord)
+ {
+ editor.ReplaceText (lastInsertPos, editor.CaretOffset - lastInsertPos, curWord);
+ lastTriggerOffset = editor.CaretOffset;
+ }
+
+ static int SearchEndPos (int offset, TextEditor editor)
+ {
+ while (offset < editor.Length && IsIdentifierPart (editor.GetCharAt (offset))) {
+ offset++;
+ }
+ return offset;
+ }
+
+ static bool IsMatchAt (TextEditor editor, int offset, string abbrevWord)
+ {
+ if (offset + abbrevWord.Length >= editor.Length)
+ return false;
+ if (offset > 0 && IsIdentifierPart (editor.GetCharAt (offset - 1)))
+ return false;
+ if (offset + abbrevWord.Length < editor.Length && !IsIdentifierPart (editor.GetCharAt (offset + abbrevWord.Length)))
+ return false;
+ return editor.GetTextAt (offset, abbrevWord.Length) == abbrevWord;
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/CustomEditorOptions.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/CustomEditorOptions.cs
new file mode 100644
index 0000000000..a3932167e2
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/CustomEditorOptions.cs
@@ -0,0 +1,186 @@
+//
+// ChangeableEditorOptions.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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;
+
+namespace MonoDevelop.Ide.Editor
+{
+ public sealed class CustomEditorOptions : ITextEditorOptions
+ {
+ #region ITextEditorOptions implementation
+ public WordFindStrategy WordFindStrategy {
+ get;
+ set;
+ }
+
+ public bool TabsToSpaces {
+ get;
+ set;
+ }
+
+ public int IndentationSize {
+ get;
+ set;
+ }
+
+ public int TabSize {
+ get;
+ set;
+ }
+
+ public bool ShowIconMargin {
+ get;
+ set;
+ }
+
+ public bool ShowLineNumberMargin {
+ get;
+ set;
+ }
+
+ public bool ShowFoldMargin {
+ get;
+ set;
+ }
+
+ public bool HighlightCaretLine {
+ get;
+ set;
+ }
+
+ public int RulerColumn {
+ get;
+ set;
+ }
+
+ public bool ShowRuler {
+ get;
+ set;
+ }
+
+ public IndentStyle IndentStyle {
+ get;
+ set;
+ }
+
+ public bool OverrideDocumentEolMarker {
+ get;
+ set;
+ }
+
+ public bool EnableSyntaxHighlighting {
+ get;
+ set;
+ }
+
+ public bool RemoveTrailingWhitespaces {
+ get;
+ set;
+ }
+
+ public bool WrapLines {
+ get;
+ set;
+ }
+
+ public string FontName {
+ get;
+ set;
+ }
+
+ public string GutterFontName {
+ get;
+ set;
+ }
+
+ public string ColorScheme {
+ get;
+ set;
+ }
+
+ public string DefaultEolMarker {
+ get;
+ set;
+ }
+
+ public bool GenerateFormattingUndoStep {
+ get;
+ set;
+ }
+
+ public ShowWhitespaces ShowWhitespaces {
+ get;
+ set;
+ }
+
+ public IncludeWhitespaces IncludeWhitespaces {
+ get;
+ set;
+ }
+ #endregion
+
+ public CustomEditorOptions ()
+ {
+ this.ColorScheme = "Default";
+ this.TabSize = this.IndentationSize = 4;
+ this.DefaultEolMarker = "\n";
+ }
+
+ public CustomEditorOptions (ITextEditorOptions initializeFrom)
+ {
+ if (initializeFrom == null)
+ throw new ArgumentNullException (nameof (initializeFrom));
+ WordFindStrategy = initializeFrom.WordFindStrategy;
+ TabsToSpaces = initializeFrom.TabsToSpaces;
+ IndentationSize = initializeFrom.IndentationSize;
+ TabSize = initializeFrom.TabSize;
+ ShowIconMargin = initializeFrom.ShowIconMargin;
+ ShowLineNumberMargin = initializeFrom.ShowLineNumberMargin;
+ ShowFoldMargin = initializeFrom.ShowFoldMargin;
+ HighlightCaretLine = initializeFrom.HighlightCaretLine;
+ RulerColumn = initializeFrom.RulerColumn;
+ ShowRuler = initializeFrom.ShowRuler;
+ IndentStyle = initializeFrom.IndentStyle;
+ OverrideDocumentEolMarker = initializeFrom.OverrideDocumentEolMarker;
+ EnableSyntaxHighlighting = initializeFrom.EnableSyntaxHighlighting;
+ RemoveTrailingWhitespaces = initializeFrom.RemoveTrailingWhitespaces;
+ WrapLines = initializeFrom.WrapLines;
+ FontName = initializeFrom.FontName;
+ GutterFontName = initializeFrom.GutterFontName;
+ ColorScheme = initializeFrom.ColorScheme;
+ DefaultEolMarker = initializeFrom.DefaultEolMarker;
+ GenerateFormattingUndoStep = initializeFrom.GenerateFormattingUndoStep;
+ ShowWhitespaces = initializeFrom.ShowWhitespaces;
+ IncludeWhitespaces = initializeFrom.IncludeWhitespaces;
+ }
+
+ #region IDisposable implementation
+ public void Dispose ()
+ {
+ }
+ #endregion
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/DefaultSourceEditorOptions.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/DefaultSourceEditorOptions.cs
new file mode 100644
index 0000000000..1e83737769
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/DefaultSourceEditorOptions.cs
@@ -0,0 +1,785 @@
+//
+// DefaultSourceEditorOptions.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Core;
+using MonoDevelop.Ide.Gui.Content;
+using MonoDevelop.Ide.Fonts;
+using MonoDevelop.Ide.Editor.Extension;
+
+namespace MonoDevelop.Ide.Editor
+{
+ [Obsolete ("Use WordNavigationStyle")]
+ public enum ControlLeftRightMode
+ {
+ MonoDevelop,
+ Emacs,
+ SharpDevelop
+ }
+
+ public enum WordNavigationStyle
+ {
+ Unix,
+ Windows
+ }
+
+ public enum LineEndingConversion {
+ Ask,
+ LeaveAsIs,
+ ConvertAlways
+ }
+
+ /// <summary>
+ /// This class contains all text editor options from ITextEditorOptions and additional options
+ /// the text editor frontend may use.
+ /// </summary>
+ public sealed class DefaultSourceEditorOptions : ITextEditorOptions
+ {
+ static DefaultSourceEditorOptions instance;
+ //static TextStylePolicy defaultPolicy;
+ static bool inited;
+
+ public static DefaultSourceEditorOptions Instance {
+ get { return instance; }
+ }
+
+ public static ITextEditorOptions PlainEditor {
+ get;
+ private set;
+ }
+
+ static DefaultSourceEditorOptions ()
+ {
+ Init ();
+ }
+
+ public static void Init ()
+ {
+ if (inited)
+ return;
+ inited = true;
+
+ var policy = MonoDevelop.Projects.Policies.PolicyService.GetDefaultPolicy<TextStylePolicy> ("text/plain");
+ instance = new DefaultSourceEditorOptions (policy);
+ MonoDevelop.Projects.Policies.PolicyService.DefaultPolicies.PolicyChanged += instance.HandlePolicyChanged;
+
+ PlainEditor = new PlainEditorOptions ();
+ }
+
+ class PlainEditorOptions : ITextEditorOptions
+ {
+ #region IDisposable implementation
+
+ void IDisposable.Dispose ()
+ {
+ // nothing
+ }
+
+ #endregion
+
+ #region ITextEditorOptions implementation
+
+ WordFindStrategy ITextEditorOptions.WordFindStrategy {
+ get {
+ return DefaultSourceEditorOptions.Instance.WordFindStrategy;
+ }
+ }
+
+ bool ITextEditorOptions.TabsToSpaces {
+ get {
+ return DefaultSourceEditorOptions.Instance.TabsToSpaces;
+ }
+ }
+
+ int ITextEditorOptions.IndentationSize {
+ get {
+ return DefaultSourceEditorOptions.Instance.IndentationSize;
+ }
+ }
+
+ int ITextEditorOptions.TabSize {
+ get {
+ return DefaultSourceEditorOptions.Instance.TabSize;
+ }
+ }
+
+ bool ITextEditorOptions.ShowIconMargin {
+ get {
+ return false;
+ }
+ }
+
+ bool ITextEditorOptions.ShowLineNumberMargin {
+ get {
+ return false;
+ }
+ }
+
+ bool ITextEditorOptions.ShowFoldMargin {
+ get {
+ return false;
+ }
+ }
+
+ bool ITextEditorOptions.HighlightCaretLine {
+ get {
+ return DefaultSourceEditorOptions.Instance.HighlightCaretLine;
+ }
+ }
+
+ int ITextEditorOptions.RulerColumn {
+ get {
+ return DefaultSourceEditorOptions.Instance.RulerColumn;
+ }
+ }
+
+ bool ITextEditorOptions.ShowRuler {
+ get {
+ return false;
+ }
+ }
+
+ IndentStyle ITextEditorOptions.IndentStyle {
+ get {
+ return DefaultSourceEditorOptions.Instance.IndentStyle;
+ }
+ }
+
+ bool ITextEditorOptions.OverrideDocumentEolMarker {
+ get {
+ return false;
+ }
+ }
+
+ bool ITextEditorOptions.EnableSyntaxHighlighting {
+ get {
+ return DefaultSourceEditorOptions.Instance.EnableSyntaxHighlighting;
+ }
+ }
+
+ bool ITextEditorOptions.RemoveTrailingWhitespaces {
+ get {
+ return DefaultSourceEditorOptions.Instance.RemoveTrailingWhitespaces;
+ }
+ }
+
+ bool ITextEditorOptions.WrapLines {
+ get {
+ return DefaultSourceEditorOptions.Instance.WrapLines;
+ }
+ }
+
+ string ITextEditorOptions.FontName {
+ get {
+ return DefaultSourceEditorOptions.Instance.FontName;
+ }
+ }
+
+ string ITextEditorOptions.GutterFontName {
+ get {
+ return DefaultSourceEditorOptions.Instance.GutterFontName;
+ }
+ }
+
+ string ITextEditorOptions.ColorScheme {
+ get {
+ return DefaultSourceEditorOptions.Instance.ColorScheme;
+ }
+ }
+
+ string ITextEditorOptions.DefaultEolMarker {
+ get {
+ return DefaultSourceEditorOptions.Instance.DefaultEolMarker;
+ }
+ }
+
+ bool ITextEditorOptions.GenerateFormattingUndoStep {
+ get {
+ return DefaultSourceEditorOptions.Instance.GenerateFormattingUndoStep;
+ }
+ }
+
+ ShowWhitespaces ITextEditorOptions.ShowWhitespaces {
+ get {
+ return ShowWhitespaces.Never;
+ }
+ }
+
+ IncludeWhitespaces ITextEditorOptions.IncludeWhitespaces {
+ get {
+ return DefaultSourceEditorOptions.Instance.IncludeWhitespaces;
+ }
+ }
+
+ #endregion
+
+
+ }
+
+ void HandlePolicyChanged (object sender, MonoDevelop.Projects.Policies.PolicyChangedEventArgs args)
+ {
+ TextStylePolicy pol = MonoDevelop.Projects.Policies.PolicyService.GetDefaultPolicy<TextStylePolicy> ("text/plain");
+ UpdateStylePolicy (pol);
+ }
+
+ DefaultSourceEditorOptions (TextStylePolicy currentPolicy)
+ {
+ var defaultControlMode = (ControlLeftRightMode)Enum.Parse (typeof(ControlLeftRightMode), DesktopService.DefaultControlLeftRightBehavior);
+ controlLeftRightMode = new PropertyWrapper<ControlLeftRightMode> ("ControlLeftRightMode", defaultControlMode);
+
+ WordNavigationStyle defaultWordNavigation = WordNavigationStyle.Unix;
+ if (Platform.IsWindows || controlLeftRightMode.Value == ControlLeftRightMode.SharpDevelop) {
+ defaultWordNavigation = WordNavigationStyle.Windows;
+ }
+ wordNavigationStyle = new PropertyWrapper<WordNavigationStyle> ("WordNavigationStyle", defaultWordNavigation);
+
+ UpdateStylePolicy (currentPolicy);
+ FontService.RegisterFontChangedCallback ("Editor", UpdateFont);
+ FontService.RegisterFontChangedCallback ("MessageBubbles", UpdateFont);
+ }
+
+ void UpdateFont ()
+ {
+ this.OnChanged (EventArgs.Empty);
+ }
+
+ void UpdateStylePolicy (MonoDevelop.Ide.Gui.Content.TextStylePolicy currentPolicy)
+ {
+ defaultEolMarker = TextStylePolicy.GetEolMarker (currentPolicy.EolMarker);
+ tabsToSpaces = currentPolicy.TabsToSpaces; // PropertyService.Get ("TabsToSpaces", false);
+ indentationSize = currentPolicy.TabWidth; //PropertyService.Get ("TabIndent", 4);
+ rulerColumn = currentPolicy.FileWidth; //PropertyService.Get ("RulerColumn", 80);
+ allowTabsAfterNonTabs = !currentPolicy.NoTabsAfterNonTabs; //PropertyService.Get ("AllowTabsAfterNonTabs", true);
+ removeTrailingWhitespaces = currentPolicy.RemoveTrailingWhitespace; //PropertyService.Get ("RemoveTrailingWhitespaces", true);
+ }
+
+ public ITextEditorOptions WithTextStyle (MonoDevelop.Ide.Gui.Content.TextStylePolicy policy)
+ {
+ if (policy == null)
+ throw new ArgumentNullException ("policy");
+ var result = (DefaultSourceEditorOptions)MemberwiseClone ();
+ result.UpdateStylePolicy (policy);
+ result.Changed = null;
+ return result;
+ }
+
+ #region new options
+
+ public bool EnableAutoCodeCompletion {
+ get { return CompletionTextEditorExtension.EnableAutoCodeCompletion; }
+ set { CompletionTextEditorExtension.EnableAutoCodeCompletion.Set (value); }
+ }
+
+ PropertyWrapper<bool> defaultRegionsFolding = new PropertyWrapper<bool> ("DefaultRegionsFolding", false);
+ public bool DefaultRegionsFolding {
+ get {
+ return defaultRegionsFolding;
+ }
+ set {
+ if (defaultRegionsFolding.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ PropertyWrapper<bool> defaultCommentFolding = new PropertyWrapper<bool> ("DefaultCommentFolding", true);
+ public bool DefaultCommentFolding {
+ get {
+ return defaultCommentFolding;
+ }
+ set {
+ if (defaultCommentFolding.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ PropertyWrapper<bool> enableSemanticHighlighting = new PropertyWrapper<bool> ("EnableSemanticHighlighting", true);
+ public bool EnableSemanticHighlighting {
+ get {
+ return enableSemanticHighlighting;
+ }
+ set {
+ if (enableSemanticHighlighting.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ PropertyWrapper<bool> tabIsReindent = new PropertyWrapper<bool> ("TabIsReindent", false);
+ public bool TabIsReindent {
+ get {
+ return tabIsReindent;
+ }
+ set {
+ if (tabIsReindent.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ PropertyWrapper<bool> autoInsertMatchingBracket = new PropertyWrapper<bool> ("AutoInsertMatchingBracket", false);
+ public bool AutoInsertMatchingBracket {
+ get {
+ return autoInsertMatchingBracket;
+ }
+ set {
+ if (autoInsertMatchingBracket.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ PropertyWrapper<bool> smartSemicolonPlacement = new PropertyWrapper<bool> ("SmartSemicolonPlacement", false);
+ public bool SmartSemicolonPlacement {
+ get {
+ return smartSemicolonPlacement;
+ }
+ set {
+ if (smartSemicolonPlacement.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ PropertyWrapper<bool> underlineErrors = new PropertyWrapper<bool> ("UnderlineErrors", true);
+ public bool UnderlineErrors {
+ get {
+ return underlineErrors;
+ }
+ set {
+ if (underlineErrors.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ PropertyWrapper<IndentStyle> indentStyle = new PropertyWrapper<IndentStyle> ("IndentStyle", IndentStyle.Smart);
+ public IndentStyle IndentStyle {
+ get {
+ return indentStyle;
+ }
+ set {
+ if (indentStyle.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ PropertyWrapper<bool> enableHighlightUsages = new PropertyWrapper<bool> ("EnableHighlightUsages", false);
+ public bool EnableHighlightUsages {
+ get {
+ return enableHighlightUsages;
+ }
+ set {
+ if (enableHighlightUsages.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ PropertyWrapper<LineEndingConversion> lineEndingConversion = new PropertyWrapper<LineEndingConversion> ("LineEndingConversion", LineEndingConversion.Ask);
+ public LineEndingConversion LineEndingConversion {
+ get {
+ return lineEndingConversion;
+ }
+ set {
+ if (lineEndingConversion.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ #endregion
+
+ PropertyWrapper<bool> useViModes = new PropertyWrapper<bool> ("UseViModes", true);
+ public bool UseViModes {
+ get {
+ return useViModes;
+ }
+ set {
+ if (useViModes.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ PropertyWrapper<bool> onTheFlyFormatting = new PropertyWrapper<bool> ("OnTheFlyFormatting", true);
+ public bool OnTheFlyFormatting {
+ get {
+ return onTheFlyFormatting;
+ }
+ set {
+ if (onTheFlyFormatting.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ #region ITextEditorOptions
+ string defaultEolMarker = Environment.NewLine;
+ public string DefaultEolMarker {
+ get {
+ return defaultEolMarker;
+ }
+ set {
+ if (defaultEolMarker != value) {
+ defaultEolMarker = value;
+ OnChanged (EventArgs.Empty);
+ }
+ }
+ }
+
+ PropertyWrapper<ControlLeftRightMode> controlLeftRightMode;
+ [Obsolete("Use WordNavigationStyle")]
+ public ControlLeftRightMode ControlLeftRightMode {
+ get {
+ return controlLeftRightMode;
+ }
+ set {
+ if (controlLeftRightMode.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ PropertyWrapper<WordNavigationStyle> wordNavigationStyle;
+ public WordNavigationStyle WordNavigationStyle {
+ get {
+ return wordNavigationStyle;
+ }
+ set {
+ if (wordNavigationStyle.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ public WordFindStrategy WordFindStrategy {
+ get {
+ if (useViModes) {
+ return WordFindStrategy.Vim;
+ }
+ switch (WordNavigationStyle) {
+ case WordNavigationStyle.Windows:
+ return WordFindStrategy.SharpDevelop;
+ default:
+ return WordFindStrategy.Emacs;
+ }
+ }
+ set {
+ throw new System.NotImplementedException ();
+ }
+ }
+
+ bool allowTabsAfterNonTabs = true;
+ public bool AllowTabsAfterNonTabs {
+ get {
+ return allowTabsAfterNonTabs;
+ }
+ set {
+ if (allowTabsAfterNonTabs != value) {
+ PropertyService.Set ("AllowTabsAfterNonTabs", value);
+ allowTabsAfterNonTabs = value;
+ OnChanged (EventArgs.Empty);
+ }
+ }
+ }
+
+ bool tabsToSpaces = false;
+ public bool TabsToSpaces {
+ get {
+ return tabsToSpaces;
+ }
+ set {
+ if (tabsToSpaces != value) {
+ PropertyService.Set ("TabsToSpaces", value);
+ tabsToSpaces = value;
+ OnChanged (EventArgs.Empty);
+ }
+ }
+ }
+
+ int indentationSize = 4;
+ public int IndentationSize {
+ get {
+ return indentationSize;
+ }
+ set {
+ if (indentationSize != value) {
+ PropertyService.Set ("TabIndent", value);
+ indentationSize = value;
+ OnChanged (EventArgs.Empty);
+ }
+ }
+ }
+
+
+ public string IndentationString {
+ get {
+ return TabsToSpaces ? new string (' ', this.TabSize) : "\t";
+ }
+ }
+
+ public int TabSize {
+ get {
+ return IndentationSize;
+ }
+ set {
+ IndentationSize = value;
+ }
+ }
+
+
+ bool removeTrailingWhitespaces = true;
+ public bool RemoveTrailingWhitespaces {
+ get {
+ return removeTrailingWhitespaces;
+ }
+ set {
+ if (removeTrailingWhitespaces != value) {
+ PropertyService.Set ("RemoveTrailingWhitespaces", value);
+ OnChanged (EventArgs.Empty);
+ removeTrailingWhitespaces = value;
+ }
+ }
+ }
+
+ PropertyWrapper<bool> showLineNumberMargin = new PropertyWrapper<bool> ("ShowLineNumberMargin", true);
+ public bool ShowLineNumberMargin {
+ get {
+ return showLineNumberMargin;
+ }
+ set {
+ if (showLineNumberMargin.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ PropertyWrapper<bool> showFoldMargin = new PropertyWrapper<bool> ("ShowFoldMargin", false);
+ public bool ShowFoldMargin {
+ get {
+ return showFoldMargin;
+ }
+ set {
+ if (showFoldMargin.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ bool showIconMargin = true;
+ public bool ShowIconMargin {
+ get {
+ return showIconMargin;
+ }
+ set {
+ if (showIconMargin != value) {
+ PropertyService.Set ("ShowIconMargin", value);
+ showIconMargin = value;
+ OnChanged (EventArgs.Empty);
+ }
+ }
+ }
+
+ PropertyWrapper<bool> highlightCaretLine = new PropertyWrapper<bool> ("HighlightCaretLine", false);
+ public bool HighlightCaretLine {
+ get {
+ return highlightCaretLine;
+ }
+ set {
+ if (highlightCaretLine.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ PropertyWrapper<bool> enableSyntaxHighlighting = new PropertyWrapper<bool> ("EnableSyntaxHighlighting", true);
+ public bool EnableSyntaxHighlighting {
+ get {
+ return enableSyntaxHighlighting;
+ }
+ set {
+ if (enableSyntaxHighlighting.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ PropertyWrapper<bool> highlightMatchingBracket = new PropertyWrapper<bool> ("HighlightMatchingBracket", true);
+ public bool HighlightMatchingBracket {
+ get {
+ return highlightMatchingBracket;
+ }
+ set {
+ if (highlightMatchingBracket.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ int rulerColumn = 80;
+
+ public int RulerColumn {
+ get {
+ return rulerColumn;
+ }
+ set {
+ if (rulerColumn != value) {
+ PropertyService.Set ("RulerColumn", value);
+ rulerColumn = value;
+ OnChanged (EventArgs.Empty);
+ }
+ }
+ }
+
+ PropertyWrapper<bool> showRuler = new PropertyWrapper<bool> ("ShowRuler", true);
+ public bool ShowRuler {
+ get {
+ return showRuler;
+ }
+ set {
+ if (showRuler.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ PropertyWrapper<bool> enableAnimations = new PropertyWrapper<bool> ("EnableAnimations", true);
+ public bool EnableAnimations {
+ get {
+ return enableAnimations;
+ }
+ set {
+ if (enableAnimations.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ PropertyWrapper<bool> drawIndentationMarkers = new PropertyWrapper<bool> ("DrawIndentationMarkers", false);
+ public bool DrawIndentationMarkers {
+ get {
+ return drawIndentationMarkers;
+ }
+ set {
+ if (drawIndentationMarkers.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ PropertyWrapper<bool> wrapLines = new PropertyWrapper<bool> ("WrapLines", false);
+ public bool WrapLines {
+ get {
+ return wrapLines;
+ }
+ set {
+ if (wrapLines.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ PropertyWrapper<bool> enableQuickDiff = new PropertyWrapper<bool> ("EnableQuickDiff", false);
+ public bool EnableQuickDiff {
+ get {
+ return enableQuickDiff;
+ }
+ set {
+ if (enableQuickDiff.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ public string FontName {
+ get {
+ return FontService.FilterFontName (FontService.GetUnderlyingFontName ("Editor"));
+ }
+ set {
+ throw new InvalidOperationException ("Set font through font service");
+ }
+ }
+
+ public string GutterFontName {
+ get {
+ return FontService.FilterFontName (FontService.GetUnderlyingFontName ("Editor"));
+ }
+ set {
+ throw new InvalidOperationException ("Set font through font service");
+ }
+ }
+
+ PropertyWrapper<string> colorScheme = new PropertyWrapper<string> ("ColorScheme", "Default");
+ public string ColorScheme {
+ get {
+ return colorScheme;
+ }
+ set {
+ if (colorScheme.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ PropertyWrapper<bool> generateFormattingUndoStep = new PropertyWrapper<bool> ("GenerateFormattingUndoStep", false);
+ public bool GenerateFormattingUndoStep {
+ get {
+ return generateFormattingUndoStep;
+ }
+ set {
+ if (generateFormattingUndoStep.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ bool overrideDocumentEolMarker = false;
+ public bool OverrideDocumentEolMarker {
+ get {
+ return overrideDocumentEolMarker;
+ }
+ set {
+ if (overrideDocumentEolMarker != value) {
+ overrideDocumentEolMarker = value;
+ OnChanged (EventArgs.Empty);
+ }
+ }
+ }
+
+ PropertyWrapper<ShowWhitespaces> showWhitespaces = new PropertyWrapper<ShowWhitespaces> ("ShowWhitespaces", ShowWhitespaces.Never);
+ public ShowWhitespaces ShowWhitespaces {
+ get {
+ return showWhitespaces;
+ }
+ set {
+ if (showWhitespaces.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+
+ PropertyWrapper<IncludeWhitespaces> includeWhitespaces = new PropertyWrapper<IncludeWhitespaces> ("IncludeWhitespaces", IncludeWhitespaces.All);
+ public IncludeWhitespaces IncludeWhitespaces {
+ get {
+ return includeWhitespaces;
+ }
+ set {
+ if (includeWhitespaces.Set (value))
+ OnChanged (EventArgs.Empty);
+ }
+ }
+ #endregion
+
+ public void Dispose ()
+ {
+ FontService.RemoveCallback (UpdateFont);
+ }
+
+ protected void OnChanged (EventArgs args)
+ {
+ if (Changed != null)
+ Changed (null, args);
+ }
+
+ public event EventHandler Changed;
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/DocumentContext.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/DocumentContext.cs
new file mode 100644
index 0000000000..58cac26e26
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/DocumentContext.cs
@@ -0,0 +1,158 @@
+//
+// DocumentContext.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Projects;
+using ICSharpCode.NRefactory.TypeSystem;
+using MonoDevelop.Ide.TypeSystem;
+using System.Threading.Tasks;
+using System.Threading;
+using Microsoft.CodeAnalysis.Options;
+using System.Collections.Generic;
+using MonoDevelop.Ide.Editor.Projection;
+
+namespace MonoDevelop.Ide.Editor
+{
+ /// <summary>
+ /// A document context puts a textual document in a semantic context inside a project and gives access
+ /// to the parse information of the textual document.
+ /// </summary>
+ public abstract class DocumentContext
+ {
+ /// <summary>
+ /// The name of the document. It's the file name for files on disc.
+ /// For unsaved files that name is different.
+ /// </summary>
+ public abstract string Name
+ {
+ get;
+ }
+
+ /// <summary>
+ /// Project != null
+ /// </summary>
+ public virtual bool HasProject
+ {
+ get { return Project != null; }
+ }
+
+ /// <summary>
+ /// Gets the project this context is in.
+ /// </summary>
+ public abstract Project Project
+ {
+ get;
+ }
+
+ public Microsoft.CodeAnalysis.Workspace RoslynWorkspace
+ {
+ get;
+ protected set;
+ }
+
+ /// <summary>
+ /// Returns the roslyn document for this document. This may return <c>null</c> if it's no compileable document.
+ /// Even if it's a C# file.
+ /// </summary>
+ public abstract Microsoft.CodeAnalysis.Document AnalysisDocument
+ {
+ get;
+ }
+
+ /// <summary>
+ /// The parsed document. Contains all syntax information about the text.
+ /// </summary>
+ public abstract ParsedDocument ParsedDocument
+ {
+ get;
+ }
+
+ /// <summary>
+ /// If true, the document is part of the ProjectContent.
+ /// </summary>
+ public virtual bool IsCompileableInProject
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ public virtual T GetContent<T>() where T : class
+ {
+ var t = this as T;
+ if (t != null)
+ return t;
+ return null;
+ }
+
+ public virtual IEnumerable<T> GetContents<T>() where T : class
+ {
+ var t = this as T;
+ if (t != null)
+ yield return t;
+ }
+
+ /// <summary>
+ /// This is called after the ParsedDocument updated.
+ /// </summary>
+ public event EventHandler DocumentParsed;
+
+ protected void OnDocumentParsed (EventArgs e)
+ {
+ var handler = DocumentParsed;
+ if (handler != null)
+ handler (this, e);
+ }
+
+ public abstract void AttachToProject (Project project);
+
+ /// <summary>
+ /// Forces a reparse of the document. This call doesn't block the ui thread.
+ /// The next call to ParsedDocument will give always the current parsed document but may block the UI thread.
+ /// </summary>
+ public abstract void ReparseDocument ();
+
+ public abstract OptionSet GetOptionSet ();
+
+ public abstract ParsedDocument UpdateParseDocument ();
+
+ // TODO: IMO that needs to be handled differently (this is atm only used in the ASP.NET binding)
+ // Maybe using the file service. Files can be changed/saved w/o beeing opened.
+ public event EventHandler Saved;
+
+ protected virtual void OnSaved (EventArgs e)
+ {
+ var handler = Saved;
+ if (handler != null)
+ handler (this, e);
+ }
+
+ internal virtual Task<IReadOnlyList<Editor.Projection.Projection>> GetPartialProjectionsAsync (CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return null;
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/DocumentLocation.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/DocumentLocation.cs
new file mode 100644
index 0000000000..7e95e9df8e
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/DocumentLocation.cs
@@ -0,0 +1,241 @@
+//
+// DocumentLocation.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 System.ComponentModel;
+using System.Globalization;
+
+namespace MonoDevelop.Ide.Editor
+{
+ /// <summary>
+ /// A line/column position.
+ /// Text editor lines/columns are counted started from one.
+ /// </summary>
+ /// <remarks>
+ /// The document provides the methods <see cref="Editor.IDocument.GetLocation"/> and
+ /// <see cref="Editor.IDocument.GetOffset(TextLocation)"/> to convert between offsets and TextLocations.
+ /// </remarks>
+ [Serializable]
+ [TypeConverter(typeof(DocumentLocationConverter))]
+ public struct DocumentLocation : IComparable<DocumentLocation>, IEquatable<DocumentLocation>
+ {
+ /// <summary>
+ /// Represents no text location (0, 0).
+ /// </summary>
+ public static readonly DocumentLocation Empty = new DocumentLocation(0, 0);
+
+ /// <summary>
+ /// Constant of the minimum line.
+ /// </summary>
+ public const int MinLine = 1;
+
+ /// <summary>
+ /// Constant of the minimum column.
+ /// </summary>
+ public const int MinColumn = 1;
+
+ /// <summary>
+ /// Creates a TextLocation instance.
+ /// </summary>
+ public DocumentLocation(int line, int column)
+ {
+ this.line = line;
+ this.column = column;
+ }
+
+ int column, line;
+
+ /// <summary>
+ /// Gets the line number.
+ /// </summary>
+ public int Line {
+ get { return line; }
+ }
+
+ /// <summary>
+ /// Gets the column number.
+ /// </summary>
+ public int Column {
+ get { return column; }
+ }
+
+ /// <summary>
+ /// Gets whether the TextLocation instance is empty.
+ /// </summary>
+ public bool IsEmpty {
+ get {
+ return column < MinLine && line < MinColumn;
+ }
+ }
+
+ /// <summary>
+ /// Gets a string representation for debugging purposes.
+ /// </summary>
+ public override string ToString()
+ {
+ return string.Format(CultureInfo.InvariantCulture, "(Line {1}, Col {0})", this.column, this.line);
+ }
+
+ /// <summary>
+ /// Gets a hash code.
+ /// </summary>
+ public override int GetHashCode()
+ {
+ return unchecked (column << 20 ^ line);
+ }
+
+ /// <summary>
+ /// Equality test.
+ /// </summary>
+ public override bool Equals(object obj)
+ {
+ if (!(obj is DocumentLocation)) return false;
+ return (DocumentLocation)obj == this;
+ }
+
+ /// <summary>
+ /// Equality test.
+ /// </summary>
+ public bool Equals(DocumentLocation other)
+ {
+ return this == other;
+ }
+
+ /// <summary>
+ /// Equality test.
+ /// </summary>
+ public static bool operator ==(DocumentLocation left, DocumentLocation right)
+ {
+ return left.column == right.column && left.line == right.line;
+ }
+
+ /// <summary>
+ /// Inequality test.
+ /// </summary>
+ public static bool operator !=(DocumentLocation left, DocumentLocation right)
+ {
+ return left.column != right.column || left.line != right.line;
+ }
+
+ /// <summary>
+ /// Compares two text locations.
+ /// </summary>
+ public static bool operator <(DocumentLocation left, DocumentLocation right)
+ {
+ if (left.line < right.line)
+ return true;
+ else if (left.line == right.line)
+ return left.column < right.column;
+ else
+ return false;
+ }
+
+ /// <summary>
+ /// Compares two text locations.
+ /// </summary>
+ public static bool operator >(DocumentLocation left, DocumentLocation right)
+ {
+ if (left.line > right.line)
+ return true;
+ else if (left.line == right.line)
+ return left.column > right.column;
+ else
+ return false;
+ }
+
+ /// <summary>
+ /// Compares two text locations.
+ /// </summary>
+ public static bool operator <=(DocumentLocation left, DocumentLocation right)
+ {
+ return !(left > right);
+ }
+
+ /// <summary>
+ /// Compares two text locations.
+ /// </summary>
+ public static bool operator >=(DocumentLocation left, DocumentLocation right)
+ {
+ return !(left < right);
+ }
+
+ public static implicit operator Microsoft.CodeAnalysis.Text.LinePosition (DocumentLocation location)
+ {
+ return new Microsoft.CodeAnalysis.Text.LinePosition (location.Line - 1, location.Column - 1);
+ }
+
+ public static implicit operator DocumentLocation(Microsoft.CodeAnalysis.Text.LinePosition location)
+ {
+ return new DocumentLocation (location.Line + 1, location.Character + 1);
+ }
+
+ /// <summary>
+ /// Compares two text locations.
+ /// </summary>
+ public int CompareTo(DocumentLocation other)
+ {
+ if (this == other)
+ return 0;
+ if (this < other)
+ return -1;
+ else
+ return 1;
+ }
+ }
+
+ public class DocumentLocationConverter : TypeConverter
+ {
+ public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
+ {
+ return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
+ }
+
+ public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
+ {
+ return destinationType == typeof(DocumentLocation) || base.CanConvertTo(context, destinationType);
+ }
+
+ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
+ {
+ if (value is string) {
+ string[] parts = ((string)value).Split(';', ',');
+ if (parts.Length == 2) {
+ return new DocumentLocation(int.Parse(parts[0]), int.Parse(parts[1]));
+ }
+ }
+ return base.ConvertFrom(context, culture, value);
+ }
+
+ public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
+ {
+ if (value is DocumentLocation) {
+ var loc = (DocumentLocation)value;
+ return loc.Line + ";" + loc.Column;
+ }
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/DocumentRegion.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/DocumentRegion.cs
new file mode 100644
index 0000000000..ff5863936b
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/DocumentRegion.cs
@@ -0,0 +1,181 @@
+//
+// DocumentRegion.cs
+//
+// Author:
+// Mike Krüger <mkrueger@xamarin.com>
+//
+// Copyright (c) 2012 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.Core.Text;
+using Microsoft.CodeAnalysis;
+
+namespace MonoDevelop.Ide.Editor
+{
+ /// <summary>
+ /// An (Begin, End) pair representing a document span. It's a TextSegment working with lines &amp; columns instead of offsets.
+ /// </summary>
+ public struct DocumentRegion : IEquatable<DocumentRegion>
+ {
+ public static readonly DocumentRegion Empty = new DocumentRegion (0, 0, 0, 0);
+
+ /// <summary>
+ /// Gets a value indicating whether this DocumentRegion is empty.
+ /// </summary>
+ public bool IsEmpty {
+ get {
+ return beginLine < 1;
+ }
+ }
+
+ readonly int beginLine;
+ public int BeginLine {
+ get {
+ return beginLine;
+ }
+ }
+
+ readonly int beginColumn;
+ public int BeginColumn {
+ get {
+ return beginColumn;
+ }
+ }
+
+ readonly int endLine;
+ public int EndLine {
+ get {
+ return endLine;
+ }
+ }
+
+ readonly int endColumn;
+ public int EndColumn {
+ get {
+ return endColumn;
+ }
+ }
+
+ public DocumentLocation Begin {
+ get {
+ return new DocumentLocation (BeginLine, BeginColumn);
+ }
+ }
+
+ public DocumentLocation End {
+ get {
+ return new DocumentLocation (EndLine, EndColumn);
+ }
+ }
+
+ public DocumentRegion (int beginLine, int beginColumn, int endLine, int endColumn)
+ {
+ this.beginLine = beginLine;
+ this.beginColumn = beginColumn;
+ this.endLine = endLine;
+ this.endColumn = endColumn;
+ }
+
+ public DocumentRegion (DocumentLocation begin, DocumentLocation end)
+ {
+ beginLine = begin.Line;
+ beginColumn = begin.Column;
+ endLine = end.Line;
+ endColumn = end.Column;
+ }
+
+ public bool Contains (DocumentLocation location)
+ {
+ return Begin <= location && location < End;
+ }
+
+ public bool Contains (int line, int column)
+ {
+ return Contains (new DocumentLocation (line, column));
+ }
+
+ public bool IsInside (DocumentLocation location)
+ {
+ return Begin <= location && location <= End;
+ }
+
+ public bool IsInside (int line, int column)
+ {
+ return IsInside (new DocumentLocation (line, column));
+ }
+
+ public override bool Equals (object obj)
+ {
+ return obj is DocumentRegion && Equals ((DocumentRegion)obj);
+ }
+
+ public override int GetHashCode ()
+ {
+ return unchecked (Begin.GetHashCode () ^ End.GetHashCode ());
+ }
+
+ public bool Equals (DocumentRegion other)
+ {
+ return Begin == other.Begin && End == other.End;
+ }
+
+ public static bool operator == (DocumentRegion left, DocumentRegion right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator != (DocumentRegion left, DocumentRegion right)
+ {
+ return !left.Equals(right);
+ }
+
+ public TextSegment GetSegment (TextEditor document)
+ {
+ if (document == null)
+ throw new ArgumentNullException ("document");
+ var begin = document.LocationToOffset (Begin);
+ var end = document.LocationToOffset (End);
+ return new TextSegment (begin, end - begin);
+ }
+
+ public static implicit operator Microsoft.CodeAnalysis.Text.LinePositionSpan (DocumentRegion location)
+ {
+ return new Microsoft.CodeAnalysis.Text.LinePositionSpan (location.Begin, location.End);
+ }
+
+ public static implicit operator DocumentRegion(Microsoft.CodeAnalysis.Text.LinePositionSpan location)
+ {
+ return new DocumentRegion (location.Start, location.End);
+ }
+
+
+ public static implicit operator DocumentRegion(FileLinePositionSpan location)
+ {
+ return new DocumentRegion (location.StartLinePosition, location.EndLinePosition);
+ }
+
+
+ public override string ToString ()
+ {
+ return string.Format ("[DocumentRegion: Begin={0}, End={1}]", Begin, End);
+ }
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/EditActions.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/EditActions.cs
new file mode 100644
index 0000000000..a72688c0e2
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/EditActions.cs
@@ -0,0 +1,516 @@
+//
+// EditActions.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 System.Text;
+using MonoDevelop.Core.Text;
+using MonoDevelop.Ide.Editor.Util;
+
+namespace MonoDevelop.Ide.Editor
+{
+ /// <summary>
+ /// This class contains some common actions for the text editor.
+ /// </summary>
+ public static class EditActions
+ {
+ public static void MoveCaretDown (TextEditor editor)
+ {
+ editor.EditorActionHost.MoveCaretDown ();
+ }
+
+ public static void MoveCaretUp (TextEditor editor)
+ {
+ editor.EditorActionHost.MoveCaretUp ();
+ }
+
+ public static void MoveCaretRight (TextEditor editor)
+ {
+ editor.EditorActionHost.MoveCaretRight ();
+ }
+
+ public static void MoveCaretLeft (TextEditor editor)
+ {
+ editor.EditorActionHost.MoveCaretLeft ();
+ }
+
+ public static void MoveCaretToLineEnd (TextEditor editor)
+ {
+ editor.EditorActionHost.MoveCaretToLineEnd ();
+ }
+
+ public static void MoveCaretToLineStart (TextEditor editor)
+ {
+ editor.EditorActionHost.MoveCaretToLineStart ();
+ }
+
+ public static void MoveCaretToDocumentStart (TextEditor editor)
+ {
+ editor.EditorActionHost.MoveCaretToDocumentStart ();
+ }
+
+ public static void MoveCaretToDocumentEnd (TextEditor editor)
+ {
+ editor.EditorActionHost.MoveCaretToDocumentEnd ();
+ }
+
+ public static void Backspace (TextEditor editor)
+ {
+ editor.EditorActionHost.Backspace ();
+ }
+
+ public static void Delete (TextEditor editor)
+ {
+ editor.EditorActionHost.Delete ();
+ }
+
+ public static void ClipboardCopy (TextEditor editor)
+ {
+ editor.EditorActionHost.ClipboardCopy ();
+ }
+
+ public static void ClipboardCut (TextEditor editor)
+ {
+ editor.EditorActionHost.ClipboardCut ();
+ }
+
+ public static void ClipboardPaste (TextEditor editor)
+ {
+ editor.EditorActionHost.ClipboardPaste ();
+ }
+
+
+
+ public static void SelectAll (TextEditor editor)
+ {
+ editor.EditorActionHost.SelectAll ();
+ }
+
+ public static void NewLine (TextEditor editor)
+ {
+ editor.EditorActionHost.NewLine ();
+ }
+
+ public static void PageUp (TextEditor textEditor)
+ {
+ textEditor.EditorActionHost.PageUp ();
+ }
+
+ public static void PageDown (TextEditor textEditor)
+ {
+ textEditor.EditorActionHost.PageDown ();
+ }
+
+ public static void Undo (TextEditor editor)
+ {
+ editor.EditorActionHost.Undo ();
+ }
+
+ public static void Redo (TextEditor editor)
+ {
+ editor.EditorActionHost.Redo ();
+ }
+
+ public static void DeleteCurrentLine (TextEditor textEditor)
+ {
+ textEditor.EditorActionHost.DeleteCurrentLine ();
+ }
+
+ public static void DeleteCurrentLineToEnd (TextEditor textEditor)
+ {
+ textEditor.EditorActionHost.DeleteCurrentLineToEnd ();
+ }
+
+ public static void ScrollLineUp (TextEditor textEditor)
+ {
+ textEditor.EditorActionHost.ScrollLineUp ();
+ }
+
+ public static void ScrollLineDown (TextEditor textEditor)
+ {
+ textEditor.EditorActionHost.ScrollLineDown ();
+ }
+
+ public static void ScrollPageUp (TextEditor textEditor)
+ {
+ textEditor.EditorActionHost.ScrollPageUp ();
+ }
+
+ public static void ScrollPageDown (TextEditor textEditor)
+ {
+ textEditor.EditorActionHost.ScrollPageDown ();
+ }
+
+ public static void GotoMatchingBrace (TextEditor textEditor)
+ {
+ var offset = SimpleBracketMatcher.GetMatchingBracketOffset (textEditor, textEditor.CaretOffset);
+ if (offset > 0)
+ textEditor.CaretOffset = offset;
+ }
+
+ public static void MovePrevWord (TextEditor textEditor)
+ {
+ textEditor.EditorActionHost.MovePrevWord ();
+ }
+
+ public static void MoveNextWord (TextEditor textEditor)
+ {
+ textEditor.EditorActionHost.MoveNextWord ();
+ }
+
+ public static void MovePrevSubWord (TextEditor textEditor)
+ {
+ textEditor.EditorActionHost.MovePrevSubWord ();
+ }
+
+ public static void MoveNextSubWord (TextEditor textEditor)
+ {
+ textEditor.EditorActionHost.MoveNextSubWord ();
+ }
+
+
+ public static void TransposeCharacters (TextEditor textEditor)
+ {
+ // Code from Mono.TextEditor.MiscActions.TransposeCharacters
+ if (textEditor.CaretOffset == 0)
+ return;
+ var line = textEditor.GetLine (textEditor.CaretLine);
+ if (line == null)
+ return;
+ using (var undoGroup = textEditor.OpenUndoGroup ()) {
+ int transposeOffset = textEditor.CaretOffset - 1;
+ char ch;
+ if (textEditor.CaretColumn == 0) {
+ var lineAbove = textEditor.GetLine (textEditor.CaretLine - 1);
+ if (lineAbove.Length == 0 && line.Length == 0)
+ return;
+
+ if (line.Length != 0) {
+ ch = textEditor.GetCharAt (textEditor.CaretOffset);
+ textEditor.RemoveText (textEditor.CaretOffset, 1);
+ textEditor.InsertText (lineAbove.Offset + lineAbove.Length, ch.ToString ());
+ return;
+ }
+
+ int lastCharOffset = lineAbove.Offset + lineAbove.Length - 1;
+ ch = textEditor.GetCharAt (lastCharOffset);
+ textEditor.RemoveText (lastCharOffset, 1);
+ textEditor.InsertAtCaret (ch.ToString ());
+ return;
+ }
+
+ int offset = textEditor.CaretOffset;
+ if (textEditor.CaretColumn >= line.Length + 1) {
+ offset = line.Offset + line.Length - 1;
+ transposeOffset = offset - 1;
+ // case one char in line:
+ if (transposeOffset < line.Offset) {
+ var lineAbove = textEditor.GetLine (textEditor.CaretLine - 1);
+ transposeOffset = lineAbove.Offset + lineAbove.Length;
+ ch = textEditor.GetCharAt (offset);
+ textEditor.RemoveText (offset, 1);
+ textEditor.InsertText (transposeOffset, ch.ToString ());
+ textEditor.CaretOffset = line.Offset;
+ return;
+ }
+ }
+
+ ch = textEditor.GetCharAt (offset);
+ textEditor.ReplaceText (offset, 1, textEditor.GetCharAt (transposeOffset).ToString ());
+ textEditor.ReplaceText (transposeOffset, 1, ch.ToString ());
+ if (textEditor.CaretColumn < line.Length + 1)
+ textEditor.CaretOffset = offset + 1;
+ }
+ }
+
+ public static void DuplicateCurrentLine (TextEditor textEditor)
+ {
+ // Code from Mono.TextEditor.MiscActions.DuplicateLine
+ using (var undoGroup = textEditor.OpenUndoGroup ()) {
+ if (textEditor.IsSomethingSelected) {
+ var selectedText = textEditor.SelectedText;
+ textEditor.ClearSelection ();
+ textEditor.InsertAtCaret (selectedText);
+ } else {
+ var line = textEditor.GetLine (textEditor.CaretLine);
+ if (line == null)
+ return;
+ textEditor.InsertText (line.Offset, textEditor.GetTextAt (line.SegmentIncludingDelimiter));
+ }
+ }
+ }
+
+ public static void JoinLines (TextEditor textEditor)
+ {
+ textEditor.EditorActionHost.JoinLines ();
+ }
+
+ public static void RecenterEditor (TextEditor textEditor)
+ {
+ textEditor.EditorActionHost.RecenterEditor ();
+ }
+
+ public static void StartCaretPulseAnimation (TextEditor textEditor)
+ {
+ textEditor.EditorActionHost.StartCaretPulseAnimation ();
+ }
+
+ public static void DeleteNextSubword (TextEditor textEditor)
+ {
+ textEditor.EditorActionHost.DeleteNextSubword ();
+ }
+
+ public static void DeletePreviousSubword (TextEditor textEditor)
+ {
+ textEditor.EditorActionHost.DeletePreviousSubword ();
+ }
+
+ public static void DeleteNextWord (TextEditor textEditor)
+ {
+ textEditor.EditorActionHost.DeleteNextWord ();
+ }
+
+ public static void DeletePreviousWord (TextEditor textEditor)
+ {
+ textEditor.EditorActionHost.DeletePreviousWord ();
+ }
+
+ public static void InsertNewLinePreserveCaretPosition (TextEditor textEditor)
+ {
+ if (textEditor.IsReadOnly)
+ return;
+ using (var undoGroup = textEditor.OpenUndoGroup ()) {
+ var loc = textEditor.CaretLocation;
+ InsertNewLine (textEditor);
+ textEditor.CaretLocation = loc;
+ }
+ }
+
+ public static void InsertNewLineAtEnd (TextEditor textEditor)
+ {
+ if (textEditor.IsReadOnly)
+ return;
+ using (var undoGroup = textEditor.OpenUndoGroup ()) {
+ MoveCaretToLineEnd (textEditor);
+ InsertNewLine (textEditor);
+ }
+ }
+
+ public static void InsertNewLine (TextEditor textEditor)
+ {
+ textEditor.EditorActionHost.InsertNewLine ();
+ }
+
+ public static void RemoveTab (TextEditor textEditor)
+ {
+ textEditor.EditorActionHost.RemoveTab ();
+ }
+
+ public static void InsertTab (TextEditor textEditor)
+ {
+ textEditor.EditorActionHost.InsertTab ();
+ }
+
+ public static void SwitchCaretMode (TextEditor textEditor)
+ {
+ textEditor.EditorActionHost.SwitchCaretMode ();
+ }
+
+ public static void MoveBlockUp (TextEditor textEditor)
+ {
+ textEditor.EditorActionHost.MoveBlockUp ();
+ }
+
+ public static void MoveBlockDown (TextEditor textEditor)
+ {
+ textEditor.EditorActionHost.MoveBlockDown ();
+ }
+
+ public static void ToggleBlockSelectionMode (TextEditor textEditor)
+ {
+ textEditor.EditorActionHost.ToggleBlockSelectionMode ();
+ }
+
+ public static void IndentSelection (TextEditor editor)
+ {
+ editor.EditorActionHost.IndentSelection ();
+ }
+
+ public static void UnIndentSelection (TextEditor editor)
+ {
+ editor.EditorActionHost.UnIndentSelection ();
+ }
+
+ #region SelectionActions
+
+ static void RunSelectionAction (TextEditor textEditor, Action<TextEditor> action)
+ {
+ using (var undo = textEditor.OpenUndoGroup ()) {
+ var anchor = textEditor.IsSomethingSelected ? textEditor.SelectionAnchorOffset : textEditor.CaretOffset;
+ action (textEditor);
+ textEditor.SetSelection (anchor, textEditor.CaretOffset);
+ }
+ }
+
+ public static void SelectionMoveToDocumentEnd (TextEditor textEditor)
+ {
+ RunSelectionAction (textEditor, MoveCaretToDocumentEnd);
+ }
+
+ public static void ExpandSelectionToLine (TextEditor textEditor)
+ {
+ // from Mono.TextEditor.SelectionActions.ExpandSelectionToLine
+ using (var undoGroup = textEditor.OpenUndoGroup ()) {
+ var curLineSegment = textEditor.GetLine (textEditor.CaretLine).SegmentIncludingDelimiter;
+ var range = textEditor.SelectionRange;
+ var selection = TextSegment.FromBounds (
+ System.Math.Min (range.Offset, curLineSegment.Offset),
+ System.Math.Max (range.EndOffset, curLineSegment.EndOffset));
+ textEditor.CaretOffset = selection.EndOffset;
+ textEditor.SelectionRange = selection;
+ }
+ }
+
+ public static void SelectionMoveToDocumentStart (TextEditor textEditor)
+ {
+ RunSelectionAction (textEditor, MoveCaretToDocumentStart);
+ }
+
+ public static void SelectionMoveLineEnd (TextEditor textEditor)
+ {
+ RunSelectionAction (textEditor, MoveCaretToLineEnd);
+ }
+
+ public static void SelectionMoveLineStart (TextEditor textEditor)
+ {
+ RunSelectionAction (textEditor, MoveCaretToLineStart);
+ }
+
+ public static void SelectionMoveDown (TextEditor textEditor)
+ {
+ RunSelectionAction (textEditor, MoveCaretDown);
+ }
+
+ public static void SelectionMoveUp (TextEditor textEditor)
+ {
+ RunSelectionAction (textEditor, MoveCaretUp);
+ }
+
+ public static void SelectionPageUp (TextEditor textEditor)
+ {
+ RunSelectionAction (textEditor, PageUp);
+ }
+
+ public static void SelectionPageDown (TextEditor textEditor)
+ {
+ RunSelectionAction (textEditor, PageDown);
+ }
+
+ public static void SelectionMovePrevSubWord (TextEditor textEditor)
+ {
+ RunSelectionAction (textEditor, MovePrevSubWord);
+ }
+
+ public static void SelectionMoveNextSubWord (TextEditor textEditor)
+ {
+ RunSelectionAction (textEditor, MoveNextSubWord);
+ }
+
+ public static void SelectionMoveLeft (TextEditor textEditor)
+ {
+ RunSelectionAction (textEditor, MoveCaretLeft);
+ }
+
+ public static void SelectionMoveRight (TextEditor textEditor)
+ {
+ RunSelectionAction (textEditor, MoveCaretRight);
+ }
+
+ public static void SelectionMovePrevWord (TextEditor textEditor)
+ {
+ RunSelectionAction (textEditor, MovePrevWord);
+ }
+
+ public static void SelectionMoveNextWord (TextEditor textEditor)
+ {
+ RunSelectionAction (textEditor, MoveNextWord);
+ }
+
+ public static void SortSelectedLines (TextEditor textEditor)
+ {
+ var selectionRegion = textEditor.SelectionRegion;
+ var start = selectionRegion.Begin;
+ var end = selectionRegion.End;
+ var caret = textEditor.CaretLocation;
+
+ int startLine = start.Line;
+ int endLine = end.Line;
+ if (startLine == endLine)
+ return;
+
+ int length = 0;
+ var lines = new string[endLine - startLine + 1];
+ for (int i = startLine; i <= endLine; i++) {
+ //get lines *with* line endings
+ var lineText = textEditor.GetLineText (i, true);
+ lines [i - startLine] = lineText;
+ length += lineText.Length;
+ }
+
+ var linesUnsorted = new string[lines.Length];
+
+ Array.Sort (lines, StringComparer.Ordinal);
+
+ bool changed = false;
+ for (int i = 0; i <= lines.Length; i++) {
+ //can't simply use reference comparison as Array.Sort is not stable
+ if (string.Equals (lines [i], linesUnsorted [i], StringComparison.Ordinal)) {
+ continue;
+ }
+ changed = true;
+ break;
+ }
+ if (!changed)
+ return;
+
+
+ var sb = new StringBuilder ();
+ for (int i = 0; i < lines.Length; i++) {
+ sb.Append (lines [i]);
+ }
+
+ var startOffset = textEditor.LocationToOffset (startLine, 1);
+ textEditor.ReplaceText (startOffset, length, sb.ToString ());
+
+ textEditor.CaretLocation = LimitColumn (textEditor, caret);
+ textEditor.SetSelection (LimitColumn (textEditor, start), LimitColumn (textEditor, end));
+ }
+
+ static DocumentLocation LimitColumn (TextEditor data, DocumentLocation loc)
+ {
+ return new DocumentLocation (loc.Line, System.Math.Min (loc.Column, data.GetLine (loc.Line).Length + 1));
+ }
+ #endregion
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/FileSettingsStore.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/FileSettingsStore.cs
new file mode 100644
index 0000000000..bec7ddd1b6
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/FileSettingsStore.cs
@@ -0,0 +1,73 @@
+//
+// FileSettingsStore.cs
+//
+// Author:
+// Mike Krüger <mkrueger@xamarin.com>
+//
+// Copyright (c) 2013 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 System.Collections.Generic;
+
+namespace MonoDevelop.Ide.Editor
+{
+ public static class FileSettingsStore
+ {
+ public class Settings
+ {
+ public int CaretOffset { get; set; }
+
+ public double vAdjustment { get; set; }
+
+ public double hAdjustment { get; set; }
+
+ public Dictionary<int, bool> FoldingStates = new Dictionary<int, bool> ();
+
+ public override string ToString ()
+ {
+ return string.Format ("[Settings: CaretOffset={0}, vAdjustment={1}, hAdjustment={2}]", CaretOffset, vAdjustment, hAdjustment);
+ }
+ }
+
+ static Dictionary<string, Settings> settingStore = new Dictionary<string, Settings> ();
+
+ public static bool TryGetValue (string contentName, out Settings settings)
+ {
+ if (contentName == null)
+ throw new ArgumentNullException ("contentName");
+ return settingStore.TryGetValue (contentName, out settings);
+ }
+
+ public static void Store (string contentName, Settings settings)
+ {
+ if (contentName == null)
+ throw new ArgumentNullException ("contentName");
+ if (settings == null)
+ throw new ArgumentNullException ("settings");
+ settingStore [contentName] = settings;
+ }
+
+ public static void Remove (string fileName)
+ {
+ settingStore.Remove (fileName);
+ }
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/FoldSegmentFactory.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/FoldSegmentFactory.cs
new file mode 100644
index 0000000000..468defb00f
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/FoldSegmentFactory.cs
@@ -0,0 +1,86 @@
+//
+// FoldSegmentFactory.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Core.Text;
+
+namespace MonoDevelop.Ide.Editor
+{
+ public static class FoldSegmentFactory
+ {
+ public static IFoldSegment CreateFoldSegment (TextEditor editor, int offset, int length, bool isCollapsed = false, string collapsedText = "...", FoldingType foldingType = FoldingType.Unknown)
+ {
+ if (editor == null)
+ throw new ArgumentNullException ("editor");
+ var result = editor.CreateFoldSegment (offset, length, isCollapsed);
+ result.CollapsedText = collapsedText;
+ result.FoldingType = foldingType;
+ return result;
+ }
+
+ public static IFoldSegment CreateFoldSegment (TextEditor editor, ISegment segment, bool isCollapsed = false, string collapsedText = "...", FoldingType foldingType = FoldingType.Unknown)
+ {
+ if (editor == null)
+ throw new ArgumentNullException ("editor");
+ if (segment == null)
+ throw new ArgumentNullException ("segment");
+ return CreateFoldSegment (editor, segment.Offset, segment.Length, isCollapsed, collapsedText, foldingType);
+ }
+
+ public static IFoldSegment CreateFoldSegment (TextEditor editor, int offset, int length, string collapsedText = "...", FoldingType foldingType = FoldingType.Unknown)
+ {
+ if (editor == null)
+ throw new ArgumentNullException ("editor");
+ return CreateFoldSegment (editor, offset, length, false, collapsedText, foldingType);
+ }
+
+ public static IFoldSegment CreateFoldSegment (TextEditor editor, ISegment segment, string collapsedText = "...", FoldingType foldingType = FoldingType.Unknown)
+ {
+ if (editor == null)
+ throw new ArgumentNullException ("editor");
+ if (segment == null)
+ throw new ArgumentNullException ("segment");
+ return CreateFoldSegment (editor, segment.Offset, segment.Length, false, collapsedText, foldingType);
+ }
+
+ public static IFoldSegment CreateFoldSegment (TextEditor editor, int offset, int length, FoldingType foldingType = FoldingType.Unknown)
+ {
+ if (editor == null)
+ throw new ArgumentNullException ("editor");
+ return CreateFoldSegment (editor, offset, length, false, "...", foldingType);
+ }
+
+ public static IFoldSegment CreateFoldSegment (TextEditor editor, ISegment segment, FoldingType foldingType = FoldingType.Unknown)
+ {
+ if (editor == null)
+ throw new ArgumentNullException ("editor");
+ if (segment == null)
+ throw new ArgumentNullException ("segment");
+ return CreateFoldSegment (editor, segment.Offset, segment.Length, false, "...", foldingType);
+ }
+
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/IDocumentLine.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/IDocumentLine.cs
new file mode 100644
index 0000000000..7135d74dad
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/IDocumentLine.cs
@@ -0,0 +1,118 @@
+//
+// IDocumentLine.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Core.Text;
+using System.Text;
+using MonoDevelop.Ide.Editor.Highlighting;
+
+namespace MonoDevelop.Ide.Editor
+{
+ /// <summary>
+ /// A line inside a <see cref="ITextDocument"/>.
+ /// </summary>
+ public interface IDocumentLine : ISegment
+ {
+ /// <summary>
+ /// Gets the length of the line including the line delimiter.
+ /// </summary>
+ int LengthIncludingDelimiter {
+ get;
+ }
+
+ int EndOffsetIncludingDelimiter {
+ get;
+ }
+
+ /// <summary>
+ /// Gets the text segment of the line including the line delimiter.
+ /// </summary>
+ ISegment SegmentIncludingDelimiter {
+ get;
+ }
+
+ /// <summary>
+ /// Gets the unicode newline for this line. Returns UnicodeNewline.Unknown for no new line (in the last line of the document)
+ /// </summary>EndOffsetIncludingDelimiterEndOffsetIncludingDelimiter
+ UnicodeNewline UnicodeNewline {
+ get;
+ }
+
+ /// <summary>
+ /// Gets the length of the line terminator.
+ /// Returns 1 or 2; or 0 at the end of the document.
+ /// </summary>
+ int DelimiterLength { get; }
+
+ /// <summary>
+ /// Gets the number of this line.
+ /// The first line has the number 1.
+ /// </summary>
+ int LineNumber { get; }
+
+ /// <summary>
+ /// Gets the previous line. Returns null if this is the first line in the document.
+ /// </summary>
+ IDocumentLine PreviousLine { get; }
+
+ /// <summary>
+ /// Gets the next line. Returns null if this is the last line in the document.
+ /// </summary>
+ IDocumentLine NextLine { get; }
+
+ /// <summary>
+ /// Gets whether the line was deleted.
+ /// </summary>
+ bool IsDeleted { get; }
+ }
+
+ public static class DocumentLineExt
+ {
+ /// <summary>
+ /// This method gets the line indentation.
+ /// </summary>
+ /// <param name = "line"></param>
+ /// <param name="doc">
+ /// The <see cref="IReadonlyTextDocument"/> the line belongs to.
+ /// </param>
+ /// <returns>
+ /// The indentation of the line (all whitespace chars up to the first non ws char).
+ /// </returns>
+ public static string GetIndentation (this IDocumentLine line, IReadonlyTextDocument doc)
+ {
+ var result = new StringBuilder ();
+ int offset = line.Offset;
+ int max = Math.Min (offset + line.LengthIncludingDelimiter, doc.Length);
+ for (int i = offset; i < max; i++) {
+ char ch = doc.GetCharAt (i);
+ if (ch != ' ' && ch != '\t')
+ break;
+ result.Append (ch);
+ }
+ return result.ToString ();
+ }
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/IFoldSegment.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/IFoldSegment.cs
new file mode 100644
index 0000000000..d1708faf36
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/IFoldSegment.cs
@@ -0,0 +1,74 @@
+//
+// IFoldSegment.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Core.Text;
+using System.Web.UI.WebControls;
+
+namespace MonoDevelop.Ide.Editor
+{
+ /// <summary>
+ /// Represents the origin for a fold segment
+ /// </summary>
+ public enum FoldingType {
+ Unknown,
+ Region,
+ TypeDefinition,
+ TypeMember,
+ Comment
+ }
+
+ /// <summary>
+ /// A fold segment represents a collapsible region inside the text editor.
+ /// </summary>
+ public interface IFoldSegment : ISegment
+ {
+ /// <summary>
+ /// Gets or sets a value indicating whether this fold segment is collapsed.
+ /// </summary>
+ bool IsCollapsed {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// Gets or sets the collapsed text. This is displayed when the folding is collapsed instead of the collapsed region.
+ /// </summary>
+ string CollapsedText {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// Gets or sets the type of the folding. This type gives some info about where this folding segment
+ /// originates from.
+ /// </summary>
+ FoldingType FoldingType {
+ get;
+ set;
+ }
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/IReadonlyTextDocument.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/IReadonlyTextDocument.cs
new file mode 100644
index 0000000000..616e2fd1d1
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/IReadonlyTextDocument.cs
@@ -0,0 +1,246 @@
+//
+// IReadonlyTextDocument.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Core.Text;
+using System.Collections.Generic;
+using System.Text;
+using MonoDevelop.Core;
+using MonoDevelop.Ide.Editor.Util;
+
+namespace MonoDevelop.Ide.Editor
+{
+ public interface IReadonlyTextDocument : ITextSource
+ {
+ bool IsReadOnly { get; }
+
+ FilePath FileName { get; }
+
+ string MimeType { get; }
+
+ /// <summary>
+ /// Gets the number of lines in the document.
+ /// </summary>
+ int LineCount { get; }
+
+ int LocationToOffset (int line, int column);
+
+ DocumentLocation OffsetToLocation (int offset);
+
+ IDocumentLine GetLine (int lineNumber);
+
+ IDocumentLine GetLineByOffset (int offset);
+ }
+
+ public static class ReadonlyTextDocumentExtensions
+ {
+ /// <summary>
+ /// Retrieves the text for a portion of the document.
+ /// </summary>
+ /// <exception cref="ArgumentOutOfRangeException">offset or length is outside the valid range.</exception>
+ public static string GetTextAt(this IReadonlyTextDocument source, ISegment segment)
+ {
+ if (source == null)
+ throw new ArgumentNullException ("source");
+ return source.GetTextAt (segment.Offset, segment.Length);
+ }
+
+ public static IEnumerable<IDocumentLine> GetLines (this IReadonlyTextDocument document)
+ {
+ if (document == null)
+ throw new ArgumentNullException ("document");
+ return document.GetLinesStartingAt (1);
+ }
+
+ public static IEnumerable<IDocumentLine> GetLinesBetween (this IReadonlyTextDocument document, int startLine, int endLine)
+ {
+ if (document == null)
+ throw new ArgumentNullException ("document");
+ if (startLine < 1 || startLine > document.LineCount)
+ throw new ArgumentOutOfRangeException ("startLine", startLine, string.Format ("value should be between 1 and {0}", document.LineCount));
+ if (endLine < 1 || endLine > document.LineCount)
+ throw new ArgumentOutOfRangeException ("endLine", endLine, string.Format ("value should be between 1 and {0}", document.LineCount));
+
+ var curLine = document.GetLine (startLine);
+ int count = endLine - startLine;
+ while (curLine != null && count --> 0) {
+ yield return curLine;
+ curLine = curLine.NextLine;
+ }
+ }
+
+ public static IEnumerable<IDocumentLine> GetLinesStartingAt (this IReadonlyTextDocument document, int startLine)
+ {
+ if (document == null)
+ throw new ArgumentNullException ("document");
+ if (startLine < 1 || startLine > document.LineCount)
+ throw new ArgumentOutOfRangeException ("startLine", startLine, string.Format ("value should be between 1 and {0}", document.LineCount));
+ var curLine = document.GetLine (startLine);
+ while (curLine != null) {
+ yield return curLine;
+ curLine = curLine.NextLine;
+ }
+ }
+
+ public static IEnumerable<IDocumentLine> GetLinesReverseStartingAt (this IReadonlyTextDocument document, int startLine)
+ {
+ if (startLine < 1 || startLine > document.LineCount)
+ throw new ArgumentOutOfRangeException ("startLine", startLine, string.Format ("value should be between 1 and {0}", document.LineCount));
+ var curLine = document.GetLine (startLine);
+ while (curLine != null) {
+ yield return curLine;
+ curLine = curLine.PreviousLine;
+ }
+ }
+
+ public static string GetTextBetween (this IReadonlyTextDocument document, int startLine, int startColumn, int endLine, int endColumn)
+ {
+ if (document == null)
+ throw new ArgumentNullException ("document");
+ return document.GetTextBetween (new DocumentLocation (startLine, startColumn), new DocumentLocation (endLine, endColumn));
+ }
+
+ public static string GetLineIndent (this IReadonlyTextDocument document, int lineNumber)
+ {
+ if (document == null)
+ throw new ArgumentNullException ("document");
+ return document.GetLineIndent (document.GetLine (lineNumber));
+ }
+
+ public static string GetLineIndent (this IReadonlyTextDocument document, IDocumentLine segment)
+ {
+ if (document == null)
+ throw new ArgumentNullException ("document");
+ if (segment == null)
+ throw new ArgumentNullException ("segment");
+ return segment.GetIndentation (document);
+ }
+
+ public static string GetLineText (this IReadonlyTextDocument document, IDocumentLine line, bool includeDelimiter = false)
+ {
+ if (document == null)
+ throw new ArgumentNullException ("document");
+ if (line == null)
+ throw new ArgumentNullException ("line");
+ return document.GetTextAt (includeDelimiter ? line.SegmentIncludingDelimiter : line);
+ }
+
+ public static string GetLineText (this IReadonlyTextDocument document, int lineNumber, bool includeDelimiter = false)
+ {
+ if (document == null)
+ throw new ArgumentNullException ("document");
+ var line = document.GetLine (lineNumber);
+ return document.GetTextAt (includeDelimiter ? line.SegmentIncludingDelimiter : line);
+ }
+
+ static int[] GetDiffCodes (IReadonlyTextDocument document, ref int codeCounter, Dictionary<string, int> codeDictionary, bool includeEol)
+ {
+ int i = 0;
+ var result = new int[document.LineCount];
+ foreach (var line in document.GetLinesStartingAt (1)) {
+ string lineText = document.GetTextAt (line.Offset, includeEol ? line.LengthIncludingDelimiter : line.Length);
+ int curCode;
+ if (!codeDictionary.TryGetValue (lineText, out curCode)) {
+ codeDictionary[lineText] = curCode = ++codeCounter;
+ }
+ result[i] = curCode;
+ i++;
+ }
+ return result;
+ }
+
+ public static IEnumerable<DiffHunk> GetDiff (this IReadonlyTextDocument document, IReadonlyTextDocument changedDocument, bool includeEol = true)
+ {
+ if (document == null)
+ throw new ArgumentNullException ("document");
+ if (changedDocument == null)
+ throw new ArgumentNullException ("changedDocument");
+ var codeDictionary = new Dictionary<string, int> ();
+ int codeCounter = 0;
+ return Diff.GetDiff<int> (GetDiffCodes (document, ref codeCounter, codeDictionary, includeEol),
+ GetDiffCodes (changedDocument, ref codeCounter, codeDictionary, includeEol));
+ }
+
+ public static string GetDiffAsString (this IReadonlyTextDocument document, IReadonlyTextDocument changedDocument, bool includeEol = true)
+ {
+ if (document == null)
+ throw new ArgumentNullException ("document");
+ if (changedDocument == null)
+ throw new ArgumentNullException ("changedDocument");
+ return Diff.GetDiffString (GetDiff (document, changedDocument, includeEol), document, changedDocument, document.FileName, changedDocument.FileName);
+ }
+
+ public static int OffsetToLineNumber (this IReadonlyTextDocument document, int offset)
+ {
+ if (document == null)
+ throw new ArgumentNullException ("document");
+ if (offset < 0 || offset > document.Length)
+ throw new ArgumentOutOfRangeException ("offset", string.Format ("offset should be between 0 and <={0} but was {1}.", document.Length, offset));
+ return document.OffsetToLocation (offset).Line;
+ }
+
+ public static int LocationToOffset (this IReadonlyTextDocument document, DocumentLocation location)
+ {
+ if (document == null)
+ throw new ArgumentNullException ("document");
+ return document.LocationToOffset (location.Line, location.Column);
+ }
+
+ public static string GetTextBetween (this IReadonlyTextDocument document, int startOffset, int endOffset)
+ {
+ if (document == null)
+ throw new ArgumentNullException ("document");
+ if (startOffset < 0 || startOffset > document.Length)
+ throw new ArgumentNullException ("startOffset");
+ if (endOffset < 0 || endOffset > document.Length)
+ throw new ArgumentNullException ("endOffset");
+ if (startOffset > endOffset)
+ throw new InvalidOperationException ();
+ return document.GetTextAt (startOffset, endOffset - startOffset);
+ }
+
+ public static string GetTextBetween (this IReadonlyTextDocument document, DocumentLocation start, DocumentLocation end)
+ {
+ if (document == null)
+ throw new ArgumentNullException ("document");
+ return document.GetTextBetween (document.LocationToOffset (start), document.LocationToOffset (end));
+ }
+
+ public static string GetEolMarker (this IReadonlyTextDocument document)
+ {
+ if (document == null)
+ throw new ArgumentNullException ("document");
+ string eol = null;
+ if (document.LineCount > 0) {
+ var line = document.GetLine (1);
+ if (line.DelimiterLength > 0)
+ eol = document.GetTextAt (line.Length, line.DelimiterLength);
+ }
+
+ return !string.IsNullOrEmpty (eol) ? eol : DefaultSourceEditorOptions.Instance.DefaultEolMarker;
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/ITextDocument.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/ITextDocument.cs
new file mode 100644
index 0000000000..b2ed856224
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/ITextDocument.cs
@@ -0,0 +1,140 @@
+//
+// ITextDocument.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Core.Text;
+using System.Text;
+using MonoDevelop.Core;
+
+namespace MonoDevelop.Ide.Editor
+{
+ public interface ITextDocument : IReadonlyTextDocument
+ {
+ /// <summary>
+ /// Gets/Sets the text of the whole document..
+ /// </summary>
+ new string Text { get; set; } // hides ITextSource.Text to add the setter
+
+ /// <summary>
+ /// Gets or Sets a character at the specified position in the document.
+ /// </summary>
+ /// <paramref name="offset">The index of the character to get.</paramref>
+ /// <exception cref="ArgumentOutOfRangeException">Offset is outside the valid range (0 to TextLength-1).</exception>
+ /// <returns>The character at the specified position.</returns>
+ /// <remarks>This is the same as Text[offset], but is more efficient because
+ /// it doesn't require creating a String object.</remarks>
+ new char this [int offset] { get; set; }
+
+ new bool IsReadOnly { get; set; }
+
+ new FilePath FileName { get; set; }
+
+ new string MimeType { get; set; }
+
+ new bool UseBOM { get; set; }
+
+ new Encoding Encoding { get; set; }
+
+ void InsertText (int offset, string text);
+
+ void InsertText (int offset, ITextSource text);
+
+ void RemoveText (int offset, int length);
+
+ void ReplaceText (int offset, int length, string value);
+
+ void ReplaceText (int offset, int length, ITextSource value);
+
+ bool IsInAtomicUndo {
+ get;
+ }
+
+ IDisposable OpenUndoGroup();
+
+ /// <summary>
+ /// This event is called directly before a change is applied to the document.
+ /// </summary>
+ /// <remarks>
+ /// It is invalid to modify the document within this event handler.
+ /// Aborting the change (by throwing an exception) is likely to cause corruption of data structures
+ /// that listen to the Changing and Changed events.
+ /// </remarks>
+ event EventHandler<TextChangeEventArgs> TextChanging;
+
+ /// <summary>
+ /// This event is called directly after a change is applied to the document.
+ /// </summary>
+ /// <remarks>
+ /// It is invalid to modify the document within this event handler.
+ /// Aborting the event handler (by throwing an exception) is likely to cause corruption of data structures
+ /// that listen to the Changing and Changed events.
+ /// </remarks>
+ event EventHandler<TextChangeEventArgs> TextChanged;
+
+ event EventHandler FileNameChanged;
+ event EventHandler MimeTypeChanged;
+
+ /// <summary>
+ /// Creates an immutable snapshot of this document.
+ /// </summary>
+ IReadonlyTextDocument CreateDocumentSnapshot();
+
+// event EventHandler<LineEventArgs> LineChanged;
+// event EventHandler<LineEventArgs> LineInserted;
+// event EventHandler<LineEventArgs> LineRemoved;
+ }
+
+ public static class DocumentExtensions
+ {
+ public static void RemoveText (this ITextDocument document, ISegment segment)
+ {
+ if (document == null)
+ throw new ArgumentNullException ("document");
+ document.RemoveText (segment.Offset, segment.Length);
+ }
+
+ public static void ReplaceText (this ITextDocument document, ISegment segment, string value)
+ {
+ if (document == null)
+ throw new ArgumentNullException ("document");
+ document.ReplaceText (segment.Offset, segment.Length, value);
+ }
+
+ public static void ReplaceText (this ITextDocument document, ISegment segment, ITextSource textSource)
+ {
+ if (document == null)
+ throw new ArgumentNullException ("document");
+ document.ReplaceText (segment.Offset, segment.Length, textSource);
+ }
+
+ public static void Save (this ITextDocument document)
+ {
+ if (document == null)
+ throw new ArgumentNullException ("document");
+ document.WriteTextTo (document.FileName);
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/ITextEditorOptions.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/ITextEditorOptions.cs
new file mode 100644
index 0000000000..223f2cf2ec
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/ITextEditorOptions.cs
@@ -0,0 +1,124 @@
+//
+// ITextEditorOptions.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Ide.Editor.Highlighting;
+
+namespace MonoDevelop.Ide.Editor
+{
+ public enum IndentStyle
+ {
+ /// <summary>
+ /// No indentation occurs
+ /// </summary>
+ None,
+
+ /// <summary>
+ /// The indentation from the line above will be
+ /// taken to indent the current line
+ /// </summary>
+ Auto,
+
+ /// <summary>
+ /// Intelligent, context sensitive indentation will occur
+ /// </summary>
+ Smart,
+
+ /// <summary>
+ /// Intelligent, context sensitive indentation that minimizes whitespaces will occur
+ /// </summary>
+ Virtual
+ }
+
+ public enum ShowWhitespaces {
+ Never,
+ Selection,
+ Always
+ }
+
+ [Flags]
+ public enum IncludeWhitespaces {
+ None = 0,
+ Space = 1,
+ Tab = 2,
+ LineEndings = 4,
+ All = Space | Tab | LineEndings
+ }
+
+ public interface ITextEditorOptions : IDisposable
+ {
+ WordFindStrategy WordFindStrategy { get; }
+
+ bool TabsToSpaces { get; }
+ int IndentationSize { get; }
+ int TabSize { get; }
+ bool ShowIconMargin { get; }
+ bool ShowLineNumberMargin { get; }
+ bool ShowFoldMargin { get; }
+ bool HighlightCaretLine { get; }
+ int RulerColumn { get; }
+ bool ShowRuler { get; }
+ IndentStyle IndentStyle { get; }
+ bool OverrideDocumentEolMarker { get; }
+ bool EnableSyntaxHighlighting { get; }
+ bool RemoveTrailingWhitespaces { get; }
+
+ bool WrapLines { get; }
+
+ string FontName { get; }
+
+ string GutterFontName { get; }
+
+ string ColorScheme { get; }
+
+ string DefaultEolMarker { get; }
+
+ bool GenerateFormattingUndoStep { get; }
+
+ ShowWhitespaces ShowWhitespaces { get; }
+
+ IncludeWhitespaces IncludeWhitespaces { get; }
+ }
+
+ public static class TextEditorOptionsExtension
+ {
+ public static ColorScheme GetColorStyle (this ITextEditorOptions options)
+ {
+ if (options == null)
+ throw new ArgumentNullException ("options");
+ return SyntaxModeService.GetColorStyle (options.ColorScheme);
+ }
+
+ /// <summary>
+ /// Gets the indentation string for a single indent.
+ /// </summary>
+ public static string GetIndentationString (this ITextEditorOptions options)
+ {
+ if (options == null)
+ throw new ArgumentNullException ("options");
+ return options.TabsToSpaces ? new string (' ', options.IndentationSize) : "\t";
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/ITextLineMarker.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/ITextLineMarker.cs
new file mode 100644
index 0000000000..982033e951
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/ITextLineMarker.cs
@@ -0,0 +1,80 @@
+//
+// ITextLineMarker.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 System.Collections.Generic;
+
+namespace MonoDevelop.Ide.Editor
+{
+ public interface ITextLineMarker
+ {
+ IDocumentLine Line {
+ get;
+ }
+
+ bool IsVisible {
+ get;
+ set;
+ }
+
+ object Tag {
+ get;
+ set;
+ }
+ }
+
+ public enum UrlType {
+ Unknown,
+ Url,
+ Email
+ }
+
+ public interface IUrlTextLineMarker : ITextLineMarker
+ {
+ UrlType UrlType {
+ get;
+ }
+
+ string Url {
+ get;
+ }
+ }
+
+ public interface ICurrentDebugLineTextMarker : ITextLineMarker
+ {
+
+ }
+
+ public interface IMessageBubbleLineMarker : ITextLineMarker
+ {
+ int TaskCount { get; }
+
+ MonoDevelop.Ide.Tasks.TaskListEntry PrimaryTask { get; set; }
+
+ IEnumerable<MonoDevelop.Ide.Tasks.TaskListEntry> Tasks { get; }
+
+ void AddTask (MonoDevelop.Ide.Tasks.TaskListEntry task);
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/ITextSegmentMarker.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/ITextSegmentMarker.cs
new file mode 100644
index 0000000000..625f960988
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/ITextSegmentMarker.cs
@@ -0,0 +1,86 @@
+//
+// ITextSegmentMarker.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Core.Text;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Components;
+using MonoDevelop.Ide.TypeSystem;
+
+namespace MonoDevelop.Ide.Editor
+{
+ public interface ITextSegmentMarker : ISegment
+ {
+ bool IsVisible {
+ get;
+ set;
+ }
+
+ object Tag {
+ get;
+ set;
+ }
+
+ event EventHandler<TextMarkerMouseEventArgs> MousePressed;
+ event EventHandler<TextMarkerMouseEventArgs> MouseHover;
+ }
+
+ public enum TextSegmentMarkerEffect {
+ /// <summary>
+ /// The region is marked as waved underline.
+ /// </summary>
+ WavedLine,
+
+ /// <summary>
+ /// The region is marked as dotted line.
+ /// </summary>
+ DottedLine,
+
+ /// <summary>
+ /// The text is grayed out.
+ /// </summary>
+ GrayOut
+ }
+
+ public interface IGenericTextSegmentMarker : ITextSegmentMarker
+ {
+ TextSegmentMarkerEffect Effect { get; }
+
+ HslColor Color { get; set; }
+ }
+
+ public interface IErrorMarker : ITextSegmentMarker
+ {
+ Error Error { get; }
+ }
+
+ public interface ISmartTagMarker : ITextSegmentMarker
+ {
+ bool IsInsideSmartTag (double x, double y);
+
+ bool IsInsideWindow (Gtk.MotionNotifyEventArgs args);
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/IUnitTestMarker.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/IUnitTestMarker.cs
new file mode 100644
index 0000000000..0350ff9839
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/IUnitTestMarker.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+
+namespace MonoDevelop.Ide.Editor
+{
+ public interface IUnitTestMarker : ITextLineMarker
+ {
+ UnitTestLocation UnitTest { get; }
+
+ void UpdateState ();
+ }
+
+ public abstract class UnitTestMarkerHost
+ {
+ public abstract Xwt.Drawing.Image GetStatusIcon (string unitTestIdentifier, string caseId = null);
+ public abstract bool IsFailure (string unitTestIdentifier, string caseId = null);
+ public abstract string GetMessage (string unitTestIdentifier, string caseId = null);
+ public abstract bool HasResult (string unitTestIdentifier, string caseId = null);
+
+ public abstract void PopupContextMenu (UnitTestLocation unitTest, int x, int y);
+ }
+
+ public class UnitTestLocation
+ {
+ public int Offset { get; set; }
+ public bool IsFixture { get; set; }
+ public string UnitTestIdentifier { get; set; }
+ public bool IsIgnored { get; set; }
+
+ public List<string> TestCases = new List<string> ();
+
+ public UnitTestLocation (int offset)
+ {
+ Offset = offset;
+ }
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InsertionCursorEventArgs.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InsertionCursorEventArgs.cs
new file mode 100644
index 0000000000..2f5996cc6a
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InsertionCursorEventArgs.cs
@@ -0,0 +1,51 @@
+//
+// InsertionCursorEventArgs.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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;
+
+namespace MonoDevelop.Ide.Editor
+{
+ [Serializable]
+ public sealed class InsertionCursorEventArgs : EventArgs
+ {
+ public bool Success {
+ get;
+ private set;
+ }
+
+ public InsertionPoint InsertionPoint {
+ get;
+ private set;
+ }
+
+ public InsertionCursorEventArgs (bool success, InsertionPoint insertionPoint)
+ {
+ Success = success;
+ InsertionPoint = insertionPoint;
+ }
+ }
+
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InsertionModeOptions.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InsertionModeOptions.cs
new file mode 100644
index 0000000000..c65e4cea08
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InsertionModeOptions.cs
@@ -0,0 +1,88 @@
+//
+// InsertionModeOptions.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 System.Collections.Generic;
+
+namespace MonoDevelop.Ide.Editor
+{
+ /// <summary>
+ /// This class contains information the editor needs to initiate the insertion mode.
+ /// </summary>
+ public sealed class InsertionModeOptions
+ {
+ /// <summary>
+ /// A user visible string describing this operation.
+ /// </summary>
+ public string Operation {
+ get;
+ private set;
+ }
+
+ /// <summary>
+ /// The list of insertion points that are used for the insertion mode. The caret is only able to move between
+ /// the insertion points.
+ /// </summary>
+ public IList<InsertionPoint> InsertionPoints {
+ get;
+ private set;
+ }
+
+ /// <summary>
+ /// That's the action that is started after the insertion mode ended.
+ /// </summary>
+ public Action<InsertionCursorEventArgs> ModeExitedAction {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// Gets or sets the first selected insertion point. The default value is 0.
+ /// </summary>
+ public int FirstSelectedInsertionPoint {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MonoDevelop.Ide.Editor.InsertionModeOptions"/> class.
+ /// </summary>
+ /// <param name="operation">A user visible string describing this operation.</param>
+ /// <param name="insertionPoints">The list of insertion points that are used for the insertion mode.</param>
+ /// <param name="modeExitedAction">The action that is started after the exit mode ended.</param>
+ public InsertionModeOptions (string operation, IList<InsertionPoint> insertionPoints, Action<InsertionCursorEventArgs> modeExitedAction)
+ {
+ if (operation == null)
+ throw new ArgumentNullException ("operation");
+ if (insertionPoints == null)
+ throw new ArgumentNullException ("insertionPoints");
+ if (modeExitedAction == null)
+ throw new ArgumentNullException ("modeExitedAction");
+ Operation = operation;
+ InsertionPoints = insertionPoints;
+ ModeExitedAction = modeExitedAction;
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InsertionPoint.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InsertionPoint.cs
new file mode 100644
index 0000000000..7bf2808146
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InsertionPoint.cs
@@ -0,0 +1,119 @@
+//
+// InsertionPoint.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Core.Text;
+using MonoDevelop.Ide.CodeFormatting;
+
+namespace MonoDevelop.Ide.Editor
+{
+ public enum NewLineInsertion
+ {
+ None,
+ Eol,
+ BlankLine
+ }
+
+ public sealed class InsertionPoint
+ {
+ public DocumentLocation Location {
+ get;
+ set;
+ }
+
+ public NewLineInsertion LineBefore { get; set; }
+ public NewLineInsertion LineAfter { get; set; }
+
+ public InsertionPoint (DocumentLocation location, NewLineInsertion lineBefore, NewLineInsertion lineAfter)
+ {
+ this.Location = location;
+ this.LineBefore = lineBefore;
+ this.LineAfter = lineAfter;
+ }
+
+ public override string ToString ()
+ {
+ return string.Format ("[InsertionPoint: Location={0}, LineBefore={1}, LineAfter={2}]", Location, LineBefore, LineAfter);
+ }
+
+ public void InsertNewLine (ITextDocument editor, NewLineInsertion insertion, ref int offset)
+ {
+ string str = null;
+ switch (insertion) {
+ case NewLineInsertion.Eol:
+ str = editor.GetEolMarker ();
+ break;
+ case NewLineInsertion.BlankLine:
+ str = editor.GetEolMarker () + editor.GetEolMarker ();
+ break;
+ default:
+ return;
+ }
+
+ editor.InsertText (offset, str);
+ offset += str.Length;
+ }
+
+ public int Insert (TextEditor editor, DocumentContext ctx, string text)
+ {
+ int offset = editor.LocationToOffset (Location);
+ using (var undo = editor.OpenUndoGroup ()) {
+
+ var line = editor.GetLineByOffset (offset);
+ int insertionOffset = line.Offset + Location.Column - 1;
+ offset = insertionOffset;
+ InsertNewLine (editor, LineBefore, ref offset);
+ int result = offset - insertionOffset;
+
+ editor.InsertText (offset, text);
+ offset += text.Length;
+ InsertNewLine (editor, LineAfter, ref offset);
+ CodeFormatterService.Format (editor, ctx, TextSegment.FromBounds (insertionOffset - 1, offset));
+ return result;
+ }
+ }
+
+ public int Insert (ITextDocument editor, string text)
+ {
+ int offset = editor.LocationToOffset (Location);
+ using (var undo = editor.OpenUndoGroup ()) {
+
+ // TODO: Run formatter !!!
+ // text = editor.FormatString (Location, text);
+
+ var line = editor.GetLineByOffset (offset);
+ int insertionOffset = line.Offset + Location.Column - 1;
+ offset = insertionOffset;
+ InsertNewLine (editor, LineBefore, ref offset);
+ int result = offset - insertionOffset;
+
+ editor.InsertText (offset, text);
+ offset += text.Length;
+ InsertNewLine (editor, LineAfter, ref offset);
+ return result;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InternalExtensionAPI/IEditorActionHost.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InternalExtensionAPI/IEditorActionHost.cs
new file mode 100644
index 0000000000..f95b0607fe
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InternalExtensionAPI/IEditorActionHost.cs
@@ -0,0 +1,123 @@
+//
+// ITextEditor.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Core.Text;
+
+namespace MonoDevelop.Ide.Editor
+{
+ interface IEditorActionHost
+ {
+ void SwitchCaretMode ();
+
+ void InsertTab ();
+
+ void RemoveTab ();
+
+ void InsertNewLine ();
+
+ void DeletePreviousWord ();
+
+ void DeleteNextWord ();
+
+ void DeletePreviousSubword ();
+
+ void DeleteNextSubword ();
+
+ void StartCaretPulseAnimation ();
+
+ void RecenterEditor ();
+
+ void JoinLines ();
+
+ void MoveNextSubWord ();
+
+ void MovePrevSubWord ();
+
+ void MoveNextWord ();
+
+ void MovePrevWord ();
+
+ void PageUp ();
+
+ void PageDown ();
+
+ void MoveCaretDown ();
+
+ void MoveCaretUp ();
+
+ void MoveCaretRight ();
+
+ void MoveCaretLeft ();
+
+ void MoveCaretToLineEnd ();
+
+ void MoveCaretToLineStart ();
+
+ void MoveCaretToDocumentStart ();
+
+ void MoveCaretToDocumentEnd ();
+
+ void Backspace ();
+
+ void Delete ();
+
+ void ClipboardCopy ();
+
+ void ClipboardCut ();
+
+ void ClipboardPaste ();
+
+ void SelectAll ();
+
+ void NewLine ();
+
+ void Undo ();
+
+ void Redo ();
+
+ void DeleteCurrentLine ();
+
+ void DeleteCurrentLineToEnd ();
+
+ void ScrollLineUp ();
+
+ void ScrollLineDown ();
+
+ void ScrollPageUp ();
+
+ void ScrollPageDown ();
+
+ void MoveBlockUp ();
+
+ void MoveBlockDown ();
+
+ void ToggleBlockSelectionMode ();
+
+ void IndentSelection ();
+
+ void UnIndentSelection ();
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InternalExtensionAPI/ITextEditorFactory.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InternalExtensionAPI/ITextEditorFactory.cs
new file mode 100644
index 0000000000..4b88445dab
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InternalExtensionAPI/ITextEditorFactory.cs
@@ -0,0 +1,44 @@
+//
+// ITextEditorFactory.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Core.Text;
+
+namespace MonoDevelop.Ide.Editor
+{
+ interface ITextEditorFactory
+ {
+ ITextDocument CreateNewDocument ();
+ ITextDocument CreateNewDocument (ITextSource textSource, string fileName, string mimeType);
+
+ IReadonlyTextDocument CreateNewReadonlyDocument (ITextSource textSource, string fileName, string mimeType);
+
+ ITextEditorImpl CreateNewEditor ();
+ ITextEditorImpl CreateNewEditor (IReadonlyTextDocument document);
+
+ string[] GetSyntaxProperties (string mimeType, string name);
+ }
+
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InternalExtensionAPI/ITextEditorImpl.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InternalExtensionAPI/ITextEditorImpl.cs
new file mode 100644
index 0000000000..4b299a40ef
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InternalExtensionAPI/ITextEditorImpl.cs
@@ -0,0 +1,244 @@
+//
+// ITextEditorImpl.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Core.Text;
+using System.Collections.Generic;
+using MonoDevelop.Ide.Gui;
+using MonoDevelop.Ide.Editor.Extension;
+using MonoDevelop.Ide.Editor.Highlighting;
+using MonoDevelop.Components;
+
+namespace MonoDevelop.Ide.Editor
+{
+ public enum EditMode
+ {
+ Edit,
+ TextLink,
+ CursorInsertion
+ }
+
+ /// <summary>
+ /// A skip char is a character in the editor at a defined position that is skipped when this
+ /// exact character is pressed at the character position. That's useful for inserting automatically generated brackets without
+ /// interfering with the typing flow.
+ /// </summary>
+ public struct SkipChar
+ {
+ /// <summary>
+ /// Gets the offset.
+ /// </summary>
+ public readonly int Offset;
+
+ /// <summary>
+ /// Gets the char.
+ /// </summary>
+ public readonly char Char;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MonoDevelop.Ide.Editor.SkipChar"/> struct.
+ /// </summary>
+ /// <param name="offset">The offset of the char.</param>
+ /// <param name="ch">The character</param>
+ public SkipChar (int offset, char ch)
+ {
+ Offset = offset;
+ Char = ch;
+ }
+
+ /// <summary>
+ /// Returns a <see cref="System.String"/> that represents the current <see cref="MonoDevelop.Ide.Editor.SkipChar"/>.
+ /// </summary>
+ /// <returns>A <see cref="System.String"/> that represents the current <see cref="MonoDevelop.Ide.Editor.SkipChar"/>.</returns>
+ public override string ToString ()
+ {
+ return string.Format ("[SkipChar: Offset={0}, Char={1}]", Offset, Char);
+ }
+ }
+
+ interface ITextEditorImpl : IViewContent, IDisposable
+ {
+ EditMode EditMode { get; }
+
+ ITextEditorOptions Options { get; set; }
+
+ IReadonlyTextDocument Document { get; set; }
+
+ DocumentLocation CaretLocation { get; set; }
+
+ SemanticHighlighting SemanticHighlighting { get; set; }
+
+ int CaretOffset { get; set; }
+
+ bool IsSomethingSelected { get; }
+
+ SelectionMode SelectionMode { get; }
+
+ ISegment SelectionRange { get; set; }
+ int SelectionAnchorOffset { get; set; }
+ int SelectionLeadOffset { get; set; }
+
+ DocumentRegion SelectionRegion { get; set; }
+
+ void SetSelection (int anchorOffset, int leadOffset);
+
+ event EventHandler SelectionChanged;
+
+ event EventHandler CaretPositionChanged;
+
+ event EventHandler BeginMouseHover;
+
+ event EventHandler VAdjustmentChanged;
+
+ event EventHandler HAdjustmentChanged;
+
+ void ClearSelection ();
+
+ void CenterToCaret ();
+
+ void StartCaretPulseAnimation ();
+
+ int EnsureCaretIsNotVirtual ();
+
+ void FixVirtualIndentation ();
+
+ IEditorActionHost Actions { get; }
+
+ ITextMarkerFactory TextMarkerFactory { get; }
+
+ event EventHandler BeginAtomicUndoOperation;
+
+ event EventHandler EndAtomicUndoOperation;
+
+ object CreateNativeControl ();
+
+ void RunWhenLoaded (Action action);
+
+ string FormatString (int offset, string code);
+
+ void StartInsertionMode (InsertionModeOptions insertionModeOptions);
+
+ void StartTextLinkMode (TextLinkModeOptions textLinkModeOptions);
+
+ double LineHeight { get; }
+
+ DocumentLocation PointToLocation (double xp, double yp, bool endAtEol = false);
+
+ Xwt.Point LocationToPoint (int line, int column);
+
+ void AddMarker (IDocumentLine line, ITextLineMarker lineMarker);
+
+ void RemoveMarker (ITextLineMarker lineMarker);
+
+ void ScrollTo (int offset);
+
+ void CenterTo (int offset);
+
+ IList<SkipChar> SkipChars
+ {
+ get;
+ }
+
+ void AddSkipChar (int offset, char ch);
+
+ string GetVirtualIndentationString (int lineNumber);
+
+ IEnumerable<ITextLineMarker> GetLineMarkers (IDocumentLine line);
+
+ #region Text segment markers
+
+ IEnumerable<ITextSegmentMarker> GetTextSegmentMarkersAt (ISegment segment);
+
+ IEnumerable<ITextSegmentMarker> GetTextSegmentMarkersAt (int offset);
+
+ /// <summary>
+ /// Adds a marker to the document.
+ /// </summary>
+ void AddMarker (ITextSegmentMarker marker);
+
+ /// <summary>
+ /// Removes a marker from the document.
+ /// </summary>
+ /// <returns><c>true</c>, if marker was removed, <c>false</c> otherwise.</returns>
+ /// <param name="marker">Marker.</param>
+ bool RemoveMarker (ITextSegmentMarker marker);
+
+ #endregion
+
+ IFoldSegment CreateFoldSegment (int offset, int length, bool isFolded = false);
+
+ void SetFoldings (IEnumerable<IFoldSegment> foldings);
+
+ IEnumerable<IFoldSegment> GetFoldingsContaining (int offset);
+
+ IEnumerable<IFoldSegment> GetFoldingsIn (int offset, int length);
+
+ string GetPangoMarkup (int offset, int length);
+
+ void SetIndentationTracker (IndentationTracker indentationTracker);
+ void SetSelectionSurroundingProvider (SelectionSurroundingProvider surroundingProvider);
+ void SetTextPasteHandler (TextPasteHandler textPasteHandler);
+
+ event EventHandler<LineEventArgs> LineChanged;
+ event EventHandler<LineEventArgs> LineInserted;
+ event EventHandler<LineEventArgs> LineRemoved;
+
+ #region Internal use only API (do not mirror in TextEditor)
+
+ TextEditorExtension EditorExtension
+ {
+ get;
+ set;
+ }
+
+ IEnumerable<TooltipProvider> TooltipProvider
+ {
+ get;
+ }
+
+ void ClearTooltipProviders ();
+
+ void AddTooltipProvider (TooltipProvider provider);
+
+ void RemoveTooltipProvider (TooltipProvider provider);
+
+ Xwt.Point GetEditorWindowOrigin ();
+
+ Xwt.Rectangle GetEditorAllocation ();
+
+ void InformLoadComplete ();
+
+ void SetUsageTaskProviders (IEnumerable<UsageProviderEditorExtension> providers);
+
+ void SetQuickTaskProviders (IEnumerable<IQuickTaskProvider> providers);
+ #endregion
+
+ double ZoomLevel { get; set; }
+ event EventHandler ZoomLevelChanged;
+
+ void AddOverlay (Control messageOverlayContent, Func<int> sizeFunc);
+ void RemoveOverlay (Control messageOverlayContent);
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InternalExtensionAPI/ITextMarkerFactory.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InternalExtensionAPI/ITextMarkerFactory.cs
new file mode 100644
index 0000000000..9c870c9874
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InternalExtensionAPI/ITextMarkerFactory.cs
@@ -0,0 +1,58 @@
+//
+// ITextMarkerFactory.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Core.Text;
+using MonoDevelop.Ide.Editor.Extension;
+using MonoDevelop.Ide.TypeSystem;
+
+namespace MonoDevelop.Ide.Editor
+{
+ public enum LinkRequest
+ {
+ SameView,
+ RequestNewView
+ }
+
+ interface ITextMarkerFactory
+ {
+ #region Line marker
+ IUrlTextLineMarker CreateUrlTextMarker (TextEditor editor, IDocumentLine line, string value, UrlType url, string syntax, int startCol, int endCol);
+ ICurrentDebugLineTextMarker CreateCurrentDebugLineTextMarker (TextEditor editor);
+ ITextLineMarker CreateAsmLineMarker (TextEditor editor);
+ IUnitTestMarker CreateUnitTestMarker (TextEditor editor, UnitTestMarkerHost host, UnitTestLocation unitTestLocation);
+ IMessageBubbleLineMarker CreateMessageBubbleLineMarker (TextEditor editor);
+ #endregion
+
+ #region Segment marker
+ ITextSegmentMarker CreateUsageMarker (TextEditor editor, Usage usage);
+ ITextSegmentMarker CreateLinkMarker (TextEditor editor, int offset, int length, Action<LinkRequest> activateLink);
+
+ IGenericTextSegmentMarker CreateGenericTextSegmentMarker (TextEditor editor, TextSegmentMarkerEffect effect, int offset, int length);
+ ISmartTagMarker CreateSmartTagMarker (TextEditor editor, int offset, DocumentLocation realLocation);
+ IErrorMarker CreateErrorMarker (TextEditor editor, Error info, int offset, int length);
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/LineEventArgs.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/LineEventArgs.cs
new file mode 100644
index 0000000000..3dd6e0cc56
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/LineEventArgs.cs
@@ -0,0 +1,48 @@
+//
+// LineEventArgs.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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;
+
+namespace MonoDevelop.Ide.Editor
+{
+ public class LineEventArgs : System.EventArgs
+ {
+ readonly IDocumentLine line;
+
+ public IDocumentLine Line {
+ get {
+ return line;
+ }
+ }
+
+ public LineEventArgs (IDocumentLine line)
+ {
+ if (line == null)
+ throw new ArgumentNullException ("line");
+ this.line = line;
+ }
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/MessageBubbles/MessageBubbleCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/MessageBubbles/MessageBubbleCommands.cs
new file mode 100644
index 0000000000..2e81dbf847
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/MessageBubbles/MessageBubbleCommands.cs
@@ -0,0 +1,77 @@
+//
+// MessageBubbleCommands.cs
+//
+// Author:
+// Mike Krüger <mkrueger@novell.com>
+//
+// Copyright (c) 2010 Novell, Inc (http://www.novell.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.Ide;
+using MonoDevelop.Components.Commands;
+using MonoDevelop.Core;
+
+namespace MonoDevelop.Ide.Editor
+{
+ enum MessageBubbleCommands
+ {
+ Toggle,
+ HideIssues,
+ ToggleIssues
+ }
+
+ class HideIssuesHandler : CommandHandler
+ {
+ protected override void Update (CommandInfo info)
+ {
+ base.Update (info);
+ info.Text = IdeApp.Preferences.DefaultHideMessageBubbles ? GettextCatalog.GetString ("_Show Message Bubbles") : GettextCatalog.GetString ("_Hide Message Bubbles");
+ }
+
+ protected override void Run (object data)
+ {
+ IdeApp.Preferences.DefaultHideMessageBubbles = !IdeApp.Preferences.DefaultHideMessageBubbles;
+ }
+ }
+
+ class ToggleIssuesHandler : CommandHandler
+ {
+ protected override void Run (object data)
+ {
+ Action action = data as Action;
+ if (action != null)
+ action ();
+ }
+
+ protected override void Update (CommandArrayInfo ainfo)
+ {
+ CommandInfo info = ainfo.Add (GettextCatalog.GetString ("_Errors & Warnings"), new Action (delegate {
+ MonoDevelop.Ide.IdeApp.Preferences.ShowMessageBubbles = MonoDevelop.Ide.ShowMessageBubbles.ForErrorsAndWarnings;
+ }));
+ info.Checked = MonoDevelop.Ide.IdeApp.Preferences.ShowMessageBubbles == MonoDevelop.Ide.ShowMessageBubbles.ForErrorsAndWarnings;
+
+ info = ainfo.Add (GettextCatalog.GetString ("E_rrors only"), new Action (delegate {
+ MonoDevelop.Ide.IdeApp.Preferences.ShowMessageBubbles = MonoDevelop.Ide.ShowMessageBubbles.ForErrors;
+ }));
+ info.Checked = MonoDevelop.Ide.IdeApp.Preferences.ShowMessageBubbles == MonoDevelop.Ide.ShowMessageBubbles.ForErrors;
+ }
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/IProjectionExtension.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/IProjectionExtension.cs
new file mode 100644
index 0000000000..b995eaabe1
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/IProjectionExtension.cs
@@ -0,0 +1,39 @@
+//
+// IProjectionExtension.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 System.Collections.Generic;
+
+namespace MonoDevelop.Ide.Editor.Projection
+{
+ interface IProjectionExtension
+ {
+ IReadOnlyList<Projection> Projections {
+ get;
+ set;
+ }
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/ProjectedCompletionExtension.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/ProjectedCompletionExtension.cs
new file mode 100644
index 0000000000..91f4b820a9
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/ProjectedCompletionExtension.cs
@@ -0,0 +1,433 @@
+//
+// ProjectedCompletionExtension.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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.Ide.Editor.Extension;
+using System.Collections.Generic;
+using MonoDevelop.Ide.CodeCompletion;
+
+
+namespace MonoDevelop.Ide.Editor.Projection
+{
+ sealed class ProjectedCompletionExtension : CompletionTextEditorExtension, IProjectionExtension
+ {
+ DocumentContext ctx;
+ IReadOnlyList<Projection> projections;
+
+ public IReadOnlyList<Projection> Projections {
+ get {
+ return projections;
+ }
+ set {
+ projections = value;
+ }
+ }
+
+ public ProjectedCompletionExtension (DocumentContext ctx, IReadOnlyList<Projection> projections)
+ {
+ if (projections == null)
+ throw new ArgumentNullException ("projections");
+ this.ctx = ctx;
+ this.projections = projections;
+ }
+
+ public override bool IsValidInContext (DocumentContext context)
+ {
+ var pctx = context as ProjectedDocumentContext;
+ if (pctx == null)
+ return false;
+ return pctx.ProjectedEditor.GetContent<CompletionTextEditorExtension> () != null;
+ }
+
+ Projection GetProjectionAt (int offset)
+ {
+ foreach (var projection in projections) {
+ foreach (var seg in projection.ProjectedSegments) {
+ if (seg.ContainsOriginal (offset)) {
+ projection.ProjectedEditor.CaretOffset = seg.FromOriginalToProjected (offset);
+ return projection;
+ }
+ }
+ }
+ return null;
+ }
+
+ CompletionTextEditorExtension GetExtensionAt (int offset)
+ {
+ var projection = GetProjectionAt (offset);
+ if (projection != null) {
+ var result = projection.ProjectedEditor.GetContent<CompletionTextEditorExtension> ();
+ if (result != null) {
+ result.CompletionWidget = new ProjectedCompletionWidget (CompletionWidget, projection);
+ }
+ return result;
+ }
+ return null;
+ }
+
+ class ProjectedCompletionWidget : ICompletionWidget
+ {
+ readonly ICompletionWidget completionWidget;
+ readonly Projection projection;
+
+ public ProjectedCompletionWidget (ICompletionWidget completionWidget, Projection projection)
+ {
+ if (completionWidget == null)
+ throw new ArgumentNullException ("completionWidget");
+ if (projection == null)
+ throw new ArgumentNullException ("projection");
+ this.projection = projection;
+ this.completionWidget = completionWidget;
+ }
+
+ #region ICompletionWidget implementation
+ public double ZoomLevel {
+ get {
+ return completionWidget.ZoomLevel;
+ }
+ }
+
+ event EventHandler ICompletionWidget.CompletionContextChanged {
+ add {
+ completionWidget.CompletionContextChanged += value;
+ }
+ remove {
+ completionWidget.CompletionContextChanged -= value;
+ }
+ }
+
+ string ICompletionWidget.GetText (int startOffset, int endOffset)
+ {
+ return projection.ProjectedEditor.GetTextBetween (startOffset, endOffset);
+ }
+
+ char ICompletionWidget.GetChar (int offset)
+ {
+ return projection.ProjectedEditor.GetCharAt (offset);
+ }
+
+ void ICompletionWidget.Replace (int offset, int count, string text)
+ {
+ foreach (var seg in projection.ProjectedSegments) {
+ if (seg.ContainsProjected (offset)) {
+ offset = seg.FromProjectedToOriginal (offset);
+ break;
+ }
+ }
+
+ completionWidget.Replace (offset, count, text);
+ }
+
+ int ConvertOffset (int triggerOffset)
+ {
+ int result = triggerOffset;
+ foreach (var seg in projection.ProjectedSegments) {
+ if (seg.ContainsProjected (result)) {
+ result = seg.FromProjectedToOriginal (result);
+ break;
+ }
+ }
+ return result;
+ }
+
+ int ProjectOffset (int offset)
+ {
+ int result = offset;
+ foreach (var seg in projection.ProjectedSegments) {
+ if (seg.ContainsOriginal (result)) {
+ result = seg.FromOriginalToProjected (result);
+ break;
+ }
+ }
+ return result;
+
+ }
+
+ CodeCompletionContext ICompletionWidget.CreateCodeCompletionContext (int triggerOffset)
+ {
+ var originalTriggerOffset = ConvertOffset (triggerOffset);
+ var completionContext = completionWidget.CreateCodeCompletionContext (originalTriggerOffset);
+ return ConvertContext (completionContext, projection);
+ }
+
+ string ICompletionWidget.GetCompletionText (CodeCompletionContext ctx)
+ {
+ return completionWidget.GetCompletionText (ImportContext (ctx, projection));
+ }
+
+ void ICompletionWidget.SetCompletionText (CodeCompletionContext ctx, string partial_word, string complete_word)
+ {
+ completionWidget.SetCompletionText (ImportContext (ctx, projection), partial_word, complete_word);
+ }
+
+ void ICompletionWidget.SetCompletionText (CodeCompletionContext ctx, string partial_word, string complete_word, int completeWordOffset)
+ {
+ completionWidget.SetCompletionText (ImportContext (ctx, projection), partial_word, complete_word, completeWordOffset);
+ }
+
+ void ICompletionWidget.AddSkipChar (int cursorPosition, char c)
+ {
+ completionWidget.AddSkipChar (ProjectOffset (cursorPosition), c);
+ }
+
+ CodeCompletionContext ICompletionWidget.CurrentCodeCompletionContext {
+ get {
+ return ConvertContext (completionWidget.CurrentCodeCompletionContext, projection);
+ }
+ }
+
+ int ICompletionWidget.CaretOffset {
+ get {
+ return ConvertOffset (completionWidget.CaretOffset);
+ }
+ set {
+ completionWidget.CaretOffset = ProjectOffset (value);
+ }
+ }
+
+ int ICompletionWidget.TextLength {
+ get {
+ return projection.ProjectedEditor.Length;
+ }
+ }
+
+ int ICompletionWidget.SelectedLength {
+ get {
+ return completionWidget.SelectedLength;
+ }
+ }
+
+ Gtk.Style ICompletionWidget.GtkStyle {
+ get {
+ return completionWidget.GtkStyle;
+ }
+ }
+ #endregion
+ }
+
+ CompletionTextEditorExtension GetCurrentExtension ()
+ {
+ return GetExtensionAt (Editor.CaretOffset);
+ }
+
+ public override bool CanRunCompletionCommand ()
+ {
+ var projectedExtension = GetCurrentExtension ();
+ if (projectedExtension == null)
+ return false;
+ return projectedExtension.CanRunCompletionCommand ();
+ }
+
+ public override MonoDevelop.Ide.CodeCompletion.ICompletionDataList CodeCompletionCommand (MonoDevelop.Ide.CodeCompletion.CodeCompletionContext completionContext)
+ {
+ var projectedExtension = GetExtensionAt (completionContext.TriggerOffset);
+ if (projectedExtension == null)
+ return null;
+ return projectedExtension.CodeCompletionCommand (ConvertContext (completionContext));
+ }
+
+ public override bool CanRunParameterCompletionCommand ()
+ {
+ var projectedExtension = GetCurrentExtension ();
+ if (projectedExtension == null)
+ return false;
+ return projectedExtension.CanRunParameterCompletionCommand ();
+ }
+
+ public override string CompletionLanguage {
+ get {
+ var projectedExtension = GetCurrentExtension ();
+ if (projectedExtension == null)
+ return base.CompletionLanguage;
+ return projectedExtension.CompletionLanguage;
+ }
+ }
+
+ public override bool GetCompletionCommandOffset (out int cpos, out int wlen)
+ {
+ var projectedExtension = GetCurrentExtension ();
+ if (projectedExtension == null) {
+ cpos = 0;
+ wlen = 0;
+ return false;
+ }
+ return projectedExtension.GetCompletionCommandOffset (out cpos, out wlen);
+ }
+
+ public override int GetCurrentParameterIndex (int startOffset)
+ {
+ var projectedExtension = GetExtensionAt (startOffset);
+ if (projectedExtension == null)
+ return -1;
+ return projectedExtension.GetCurrentParameterIndex (startOffset);
+ }
+
+ public override int GuessBestMethodOverload (ParameterHintingResult provider, int currentOverload)
+ {
+ var projectedExtension = GetCurrentExtension ();
+ if (projectedExtension == null)
+ return -1;
+ return projectedExtension.GuessBestMethodOverload (provider, currentOverload);
+ }
+
+ public override System.Threading.Tasks.Task<MonoDevelop.Ide.CodeCompletion.ICompletionDataList> HandleCodeCompletionAsync (MonoDevelop.Ide.CodeCompletion.CodeCompletionContext completionContext, char completionChar, System.Threading.CancellationToken token)
+ {
+ var projectedExtension = GetExtensionAt (completionContext.TriggerOffset);
+ if (projectedExtension == null)
+ return null;
+
+ return projectedExtension.HandleCodeCompletionAsync (ConvertContext (completionContext), completionChar, token);
+ }
+
+ public override System.Threading.Tasks.Task<ParameterHintingResult> HandleParameterCompletionAsync (MonoDevelop.Ide.CodeCompletion.CodeCompletionContext completionContext, char completionChar, System.Threading.CancellationToken token)
+ {
+ var projectedExtension = GetExtensionAt (completionContext.TriggerOffset);
+ if (projectedExtension == null)
+ return null;
+ return projectedExtension.HandleParameterCompletionAsync (ConvertContext (completionContext), completionChar, token);
+ }
+
+ public override bool KeyPress (KeyDescriptor descriptor)
+ {
+ projections = ctx.GetPartialProjectionsAsync ().Result;
+ var projectedExtension = GetCurrentExtension();
+ if (projectedExtension != null)
+ return projectedExtension.KeyPress (descriptor);
+ return base.KeyPress (descriptor);
+ }
+
+ public override ParameterHintingResult ParameterCompletionCommand (MonoDevelop.Ide.CodeCompletion.CodeCompletionContext completionContext)
+ {
+ var projectedExtension = GetExtensionAt (completionContext.TriggerOffset);
+ if (projectedExtension == null)
+ return null;
+ return projectedExtension.ParameterCompletionCommand (ConvertContext (completionContext));
+ }
+
+ public override void RunCompletionCommand ()
+ {
+ var projectedExtension = GetCurrentExtension();
+ if (projectedExtension == null)
+ return;
+ projectedExtension.RunCompletionCommand ();
+ }
+
+ public override void RunParameterCompletionCommand ()
+ {
+ var projectedExtension = GetCurrentExtension();
+ if (projectedExtension == null)
+ return;
+
+ projectedExtension.RunParameterCompletionCommand ();
+ }
+
+ public override void RunShowCodeTemplatesWindow ()
+ {
+ var projectedExtension = GetCurrentExtension();
+ if (projectedExtension == null)
+ return;
+ projectedExtension.RunShowCodeTemplatesWindow ();
+ }
+
+ public override MonoDevelop.Ide.CodeCompletion.ICompletionDataList ShowCodeSurroundingsCommand (MonoDevelop.Ide.CodeCompletion.CodeCompletionContext completionContext)
+ {
+ var projectedExtension = GetExtensionAt (completionContext.TriggerOffset);
+ if (projectedExtension == null)
+ return null;
+ return projectedExtension.ShowCodeSurroundingsCommand (ConvertContext (completionContext));
+ }
+
+ public override MonoDevelop.Ide.CodeCompletion.ICompletionDataList ShowCodeTemplatesCommand (MonoDevelop.Ide.CodeCompletion.CodeCompletionContext completionContext)
+ {
+ var projectedExtension = GetExtensionAt (completionContext.TriggerOffset);
+ if (projectedExtension == null)
+ return null;
+ return projectedExtension.ShowCodeTemplatesCommand (ConvertContext (completionContext));
+ }
+
+ CodeCompletionContext ConvertContext (CodeCompletionContext completionContext)
+ {
+ var projection = GetProjectionAt (completionContext.TriggerOffset);
+ return ConvertContext (completionContext, projection);
+ }
+
+ static CodeCompletionContext ConvertContext (CodeCompletionContext completionContext, Projection projection)
+ {
+ int offset = completionContext.TriggerOffset;
+ int line = completionContext.TriggerLine;
+ int lineOffset = completionContext.TriggerLineOffset;
+
+ if (projection != null) {
+ foreach (var seg in projection.ProjectedSegments) {
+ if (seg.ContainsOriginal (offset)) {
+ offset = seg.FromOriginalToProjected (offset);
+ var loc = projection.ProjectedEditor.OffsetToLocation (offset);
+ line = loc.Line;
+ lineOffset = loc.Column - 1;
+ }
+ }
+ }
+
+ return new MonoDevelop.Ide.CodeCompletion.CodeCompletionContext {
+ TriggerOffset = offset,
+ TriggerLine = line,
+ TriggerLineOffset = lineOffset,
+ TriggerXCoord = completionContext.TriggerXCoord,
+ TriggerYCoord = completionContext.TriggerYCoord,
+ TriggerTextHeight = completionContext.TriggerTextHeight,
+ TriggerWordLength = completionContext.TriggerWordLength
+ };
+ }
+
+ static CodeCompletionContext ImportContext (CodeCompletionContext completionContext, Projection projection)
+ {
+ int offset = completionContext.TriggerOffset;
+ int line = completionContext.TriggerLine;
+ int lineOffset = completionContext.TriggerLineOffset;
+
+ if (projection != null) {
+ foreach (var seg in projection.ProjectedSegments) {
+ if (seg.ContainsProjected (offset)) {
+ offset = seg.FromProjectedToOriginal (offset);
+ var loc = projection.ProjectedEditor.OffsetToLocation (offset);
+ line = loc.Line;
+ lineOffset = loc.Column - 1;
+ }
+ }
+ }
+
+ return new MonoDevelop.Ide.CodeCompletion.CodeCompletionContext {
+ TriggerOffset = offset,
+ TriggerLine = line,
+ TriggerLineOffset = lineOffset,
+ TriggerXCoord = completionContext.TriggerXCoord,
+ TriggerYCoord = completionContext.TriggerYCoord,
+ TriggerTextHeight = completionContext.TriggerTextHeight,
+ TriggerWordLength = completionContext.TriggerWordLength
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/ProjectedDocumentContext.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/ProjectedDocumentContext.cs
new file mode 100644
index 0000000000..4571fefeb8
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/ProjectedDocumentContext.cs
@@ -0,0 +1,143 @@
+//
+// ProjectedDocumentContext.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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.Ide.Editor;
+using System.Collections.Immutable;
+using MonoDevelop.Core.Text;
+using MonoDevelop.Ide.Gui;
+using MonoDevelop.Ide.TypeSystem;
+
+namespace MonoDevelop.Ide.Editor.Projection
+{
+
+ class ProjectedDocumentContext : DocumentContext
+ {
+ DocumentContext originalContext;
+ TextEditor projectedEditor;
+ ParsedDocument parsedDocument;
+
+ public TextEditor ProjectedEditor {
+ get {
+ return projectedEditor;
+ }
+ }
+
+ public DocumentContext OriginalContext {
+ get {
+ return originalContext;
+ }
+ }
+
+ Microsoft.CodeAnalysis.Document projectedDocument;
+
+ public ProjectedDocumentContext (TextEditor projectedEditor, DocumentContext originalContext)
+ {
+ if (projectedEditor == null)
+ throw new ArgumentNullException ("projectedEditor");
+ if (originalContext == null)
+ throw new ArgumentNullException ("originalContext");
+ this.projectedEditor = projectedEditor;
+ this.originalContext = originalContext;
+
+ if (originalContext.Project != null) {
+ var originalProjectId = TypeSystemService.GetProjectId (originalContext.Project);
+ if (originalProjectId != null) {
+ var originalProject = TypeSystemService.Workspace.CurrentSolution.GetProject (originalProjectId);
+ if (originalProject != null) {
+ projectedDocument = originalProject.AddDocument (
+ projectedEditor.FileName,
+ projectedEditor
+ );
+ }
+ }
+ }
+
+ projectedEditor.TextChanged += delegate(object sender, TextChangeEventArgs e) {
+ if (projectedDocument != null)
+ projectedDocument = projectedDocument.WithText (projectedEditor);
+ ReparseDocument ();
+ };
+
+ ReparseDocument ();
+ }
+
+ #region implemented abstract members of DocumentContext
+ public override void AttachToProject (MonoDevelop.Projects.Project project)
+ {
+ }
+
+ public override void ReparseDocument ()
+ {
+ var options = new ParseOptions {
+ FileName = projectedEditor.FileName,
+ Content = projectedEditor,
+ Project = Project,
+ RoslynDocument = projectedDocument
+ };
+ parsedDocument = TypeSystemService.ParseFile (options, projectedEditor.MimeType).Result;
+
+ base.OnDocumentParsed (EventArgs.Empty);
+ }
+
+ public override Microsoft.CodeAnalysis.Options.OptionSet GetOptionSet ()
+ {
+ return originalContext.GetOptionSet ();
+ }
+
+ public override MonoDevelop.Ide.TypeSystem.ParsedDocument UpdateParseDocument ()
+ {
+ ReparseDocument ();
+ return parsedDocument;
+ }
+
+ public override string Name {
+ get {
+ return projectedEditor.FileName;
+ }
+ }
+
+ public override MonoDevelop.Projects.Project Project {
+ get {
+ return originalContext.Project;
+ }
+ }
+
+ public override Microsoft.CodeAnalysis.Document AnalysisDocument {
+ get {
+
+ return projectedDocument;
+ }
+ }
+
+ public override MonoDevelop.Ide.TypeSystem.ParsedDocument ParsedDocument {
+ get {
+ return parsedDocument;
+ }
+ }
+ #endregion
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/ProjectedFilterCompletionTextEditorExtension.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/ProjectedFilterCompletionTextEditorExtension.cs
new file mode 100644
index 0000000000..15b3ecfc61
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/ProjectedFilterCompletionTextEditorExtension.cs
@@ -0,0 +1,186 @@
+//
+// ProjectedFilterCompletionTextEditorExtension.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 System.Collections.Generic;
+using MonoDevelop.Ide.Editor.Extension;
+
+namespace MonoDevelop.Ide.Editor.Projection
+{
+ sealed class ProjectedFilterCompletionTextEditorExtension : CompletionTextEditorExtension, IProjectionExtension
+ {
+ CompletionTextEditorExtension completionTextEditorExtension;
+ IReadOnlyList<Projection> projections;
+
+ IReadOnlyList<Projection> IProjectionExtension.Projections {
+ get {
+ return projections;
+ }
+ set {
+ projections = value;
+ }
+ }
+
+ public ProjectedFilterCompletionTextEditorExtension (CompletionTextEditorExtension completionTextEditorExtension, IReadOnlyList<Projection> projections)
+ {
+ this.completionTextEditorExtension = completionTextEditorExtension;
+ this.projections = projections;
+ }
+
+ bool IsInProjection ()
+ {
+ int offset = Editor.CaretOffset;
+ foreach (var p in projections) {
+ foreach (var seg in p.ProjectedSegments) {
+ if (seg.ContainsOriginal (offset))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public override bool KeyPress (KeyDescriptor descriptor)
+ {
+ if (IsInProjection())
+ return Next == null || Next.KeyPress (descriptor);
+ return completionTextEditorExtension.KeyPress (descriptor);
+ }
+
+ public override bool IsValidInContext (DocumentContext context)
+ {
+ if (IsInProjection())
+ return false;
+ return completionTextEditorExtension.IsValidInContext (context);
+ }
+
+ public override int GetCurrentParameterIndex (int startOffset)
+ {
+ if (IsInProjection())
+ return -1;
+ return completionTextEditorExtension.GetCurrentParameterIndex (startOffset);
+ }
+
+ public override string CompletionLanguage {
+ get {
+ return completionTextEditorExtension.CompletionLanguage;
+ }
+ }
+
+ public override void RunCompletionCommand ()
+ {
+ if (IsInProjection ())
+ return;
+ completionTextEditorExtension.RunCompletionCommand ();
+ }
+
+ public override void RunShowCodeTemplatesWindow ()
+ {
+ if (IsInProjection ())
+ return;
+ completionTextEditorExtension.RunShowCodeTemplatesWindow ();
+ }
+
+ public override void RunParameterCompletionCommand ()
+ {
+ if (IsInProjection ())
+ return;
+ completionTextEditorExtension.RunParameterCompletionCommand ();
+ }
+
+ public override bool CanRunCompletionCommand ()
+ {
+ if (IsInProjection ())
+ return false;
+ return completionTextEditorExtension.CanRunCompletionCommand ();
+ }
+
+ public override bool CanRunParameterCompletionCommand ()
+ {
+ if (IsInProjection ())
+ return false;
+ return completionTextEditorExtension.CanRunParameterCompletionCommand ();
+ }
+
+ public override System.Threading.Tasks.Task<CodeCompletion.ICompletionDataList> HandleCodeCompletionAsync (CodeCompletion.CodeCompletionContext completionContext, char completionChar, System.Threading.CancellationToken token)
+ {
+ return completionTextEditorExtension.HandleCodeCompletionAsync (completionContext, completionChar, token);
+ }
+
+ public override System.Threading.Tasks.Task<CodeCompletion.ParameterHintingResult> HandleParameterCompletionAsync (CodeCompletion.CodeCompletionContext completionContext, char completionChar, System.Threading.CancellationToken token)
+ {
+ return completionTextEditorExtension.HandleParameterCompletionAsync (completionContext, completionChar, token);
+ }
+
+ public override bool GetCompletionCommandOffset (out int cpos, out int wlen)
+ {
+ if (IsInProjection ()) {
+ cpos = 0; wlen = 0;
+ return false;
+ }
+ return completionTextEditorExtension.GetCompletionCommandOffset (out cpos, out wlen);
+ }
+
+ public override CodeCompletion.ICompletionDataList ShowCodeSurroundingsCommand (CodeCompletion.CodeCompletionContext completionContext)
+ {
+ if (IsInProjection ()) return null;
+ return completionTextEditorExtension.ShowCodeSurroundingsCommand (completionContext);
+ }
+
+ public override CodeCompletion.ICompletionDataList ShowCodeTemplatesCommand (CodeCompletion.CodeCompletionContext completionContext)
+ {
+ if (IsInProjection ()) return null;
+ return completionTextEditorExtension.ShowCodeTemplatesCommand (completionContext);
+ }
+
+ public override CodeCompletion.ICompletionDataList CodeCompletionCommand (CodeCompletion.CodeCompletionContext completionContext)
+ {
+ if (IsInProjection ()) return null;
+ return completionTextEditorExtension.CodeCompletionCommand (completionContext);
+ }
+
+ public override CodeCompletion.ParameterHintingResult ParameterCompletionCommand (CodeCompletion.CodeCompletionContext completionContext)
+ {
+ if (IsInProjection ()) return null;
+ return completionTextEditorExtension.ParameterCompletionCommand (completionContext);
+ }
+
+ public override int GuessBestMethodOverload (CodeCompletion.ParameterHintingResult provider, int currentOverload)
+ {
+ if (IsInProjection ()) return -1;
+ return completionTextEditorExtension.GuessBestMethodOverload (provider, currentOverload);
+ }
+
+ protected override void Initialize ()
+ {
+ completionTextEditorExtension.InternalInitialize ();
+ }
+
+ public override void Dispose ()
+ {
+ completionTextEditorExtension.Dispose ();
+ }
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/ProjectedSegment.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/ProjectedSegment.cs
new file mode 100644
index 0000000000..8a49d40ca3
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/ProjectedSegment.cs
@@ -0,0 +1,89 @@
+//
+// ProjectedSegment.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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.Core.Text;
+
+namespace MonoDevelop.Ide.Editor.Projection
+{
+ public struct ProjectedSegment
+ {
+ public int Offset {
+ get;
+ private set;
+ }
+
+ public int ProjectedOffset {
+ get;
+ private set;
+ }
+
+ public int Length {
+ get;
+ private set;
+ }
+
+ public ProjectedSegment (int offset, int projectedOffset, int length)
+ : this ()
+ {
+ this.Offset = offset;
+ this.ProjectedOffset = projectedOffset;
+ this.Length = length;
+ }
+
+ public bool ContainsOriginal (int offset)
+ {
+ return Offset <= offset && offset < Offset + Length;
+ }
+
+ public bool ContainsProjected (int offset)
+ {
+ return ProjectedOffset <= offset && offset < ProjectedOffset + Length;
+ }
+
+ public bool IsInOriginal (ISegment segment)
+ {
+ if (segment == null)
+ throw new ArgumentNullException ("segment");
+
+ return segment.Contains(Offset) && segment.Contains (Offset + Length);
+ }
+
+ public ISegment FromOriginalToProjected (ISegment segment)
+ {
+ return new TextSegment (segment.Offset - Offset + ProjectedOffset, segment.Length);
+ }
+
+ public int FromOriginalToProjected (int offset)
+ {
+ return offset - Offset + ProjectedOffset;
+ }
+
+ public int FromProjectedToOriginal (int offset)
+ {
+ return offset + Offset - ProjectedOffset;
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/ProjectedSemanticHighlighting.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/ProjectedSemanticHighlighting.cs
new file mode 100644
index 0000000000..82ceb984a2
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/ProjectedSemanticHighlighting.cs
@@ -0,0 +1,98 @@
+//
+// ProjectedSemanticHighlighting.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 System.Linq;
+using MonoDevelop.Ide.Editor.Highlighting;
+using System.Collections.Generic;
+
+namespace MonoDevelop.Ide.Editor.Projection
+{
+ sealed class ProjectedSemanticHighlighting : SemanticHighlighting
+ {
+ List<Projection> projections;
+
+ public ProjectedSemanticHighlighting (TextEditor editor, DocumentContext documentContext, IEnumerable<Projection> projections) : base (editor, documentContext)
+ {
+ this.projections = new List<Projection> (projections);
+ foreach (var p in this.projections) {
+ if (p.ProjectedEditor.SemanticHighlighting == null)
+ continue;
+ p.ProjectedEditor.SemanticHighlighting.SemanticHighlightingUpdated += HandleSemanticHighlightingUpdated;
+ }
+ }
+
+ public void UpdateProjection (IEnumerable<Projection> projections)
+ {
+ foreach (var p in this.projections) {
+ if (p.ProjectedEditor.SemanticHighlighting == null)
+ continue;
+ p.ProjectedEditor.SemanticHighlighting.SemanticHighlightingUpdated -= HandleSemanticHighlightingUpdated;
+ }
+ this.projections = new List<Projection> (projections);
+ foreach (var p in this.projections) {
+ if (p.ProjectedEditor.SemanticHighlighting == null)
+ continue;
+ p.ProjectedEditor.SemanticHighlighting.SemanticHighlightingUpdated += HandleSemanticHighlightingUpdated;
+ }
+ }
+
+ void HandleSemanticHighlightingUpdated (object sender, EventArgs e)
+ {
+ NotifySemanticHighlightingUpdate ();
+ }
+
+ protected override void DocumentParsed ()
+ {
+ NotifySemanticHighlightingUpdate ();
+ }
+
+ public override IEnumerable<ColoredSegment> GetColoredSegments (MonoDevelop.Core.Text.ISegment segment)
+ {
+ foreach (Projection p in projections) {
+ foreach (var seg in p.ProjectedSegments) {
+ if (seg.IsInOriginal (segment)) {
+ if (p.ProjectedEditor.SemanticHighlighting == null)
+ continue;
+
+ int delta = segment.EndOffset - (seg.Offset + seg.Length);
+ int len = seg.Length;
+ if (delta < 0) {
+ len += delta;
+ }
+ foreach (var cs in p.ProjectedEditor.SemanticHighlighting.GetColoredSegments (new MonoDevelop.Core.Text.TextSegment (seg.ProjectedOffset, len))) {
+ yield return new ColoredSegment (cs.Offset - seg.ProjectedOffset + seg.Offset, cs.Length, cs.ColorStyleKey);
+
+ }
+ foreach (var cs in GetColoredSegments (MonoDevelop.Core.Text.TextSegment.FromBounds (seg.Offset + len, segment.EndOffset)))
+ yield return cs;
+ yield break;
+ }
+ }
+ }
+ }
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/ProjectedTooltipProvider.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/ProjectedTooltipProvider.cs
new file mode 100644
index 0000000000..bb50723ae7
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/ProjectedTooltipProvider.cs
@@ -0,0 +1,95 @@
+//
+// ProjectedTooltipProvider.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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.Components;
+
+namespace MonoDevelop.Ide.Editor.Projection
+{
+ sealed class ProjectedTooltipProvider : TooltipProvider
+ {
+ readonly TextEditor editor;
+ readonly DocumentContext ctx;
+ readonly Projection projection;
+ readonly TooltipProvider projectedTooltipProvider;
+
+ public ProjectedTooltipProvider (TextEditor editor, DocumentContext ctx, Projection projection, TooltipProvider projectedTooltipProvider)
+ {
+ if (editor == null)
+ throw new ArgumentNullException ("editor");
+ if (ctx == null)
+ throw new ArgumentNullException ("ctx");
+ if (projection == null)
+ throw new ArgumentNullException ("projection");
+ if (projectedTooltipProvider == null)
+ throw new ArgumentNullException ("projectedTooltipProvider");
+ this.projectedTooltipProvider = projectedTooltipProvider;
+ this.projection = projection;
+ this.editor = editor;
+ this.ctx = ctx;
+ }
+
+ public override TooltipItem GetItem (TextEditor editor, DocumentContext ctx, int offset)
+ {
+ foreach (var pseg in projection.ProjectedSegments) {
+ if (pseg.ContainsOriginal (offset)) {
+ var result = projectedTooltipProvider.GetItem (projection.ProjectedEditor, projection.ProjectedContext, pseg.FromOriginalToProjected (offset));
+ if (result == null)
+ return null;
+ result.Offset = pseg.FromProjectedToOriginal (result.Offset);
+ return result;
+ }
+ }
+ return null;
+ }
+
+ public override bool IsInteractive (TextEditor editor, Control tipWindow)
+ {
+ return projectedTooltipProvider.IsInteractive (editor, tipWindow);
+ }
+
+ public override void ShowTooltipWindow (TextEditor editor, Control tipWindow, TooltipItem item, Gdk.ModifierType modifierState, int mouseX, int mouseY)
+ {
+ projectedTooltipProvider.ShowTooltipWindow (editor, tipWindow, item, modifierState, mouseX, mouseY);
+ }
+
+ public override void GetRequiredPosition (TextEditor editor, Control tipWindow, out int requiredWidth, out double xalign)
+ {
+ projectedTooltipProvider.GetRequiredPosition (editor, tipWindow, out requiredWidth, out xalign);
+ }
+
+ public override Control CreateTooltipWindow (TextEditor editor, DocumentContext ctx, TooltipItem item, int offset, Gdk.ModifierType modifierState)
+ {
+ foreach (var pseg in projection.ProjectedSegments) {
+ if (pseg.ContainsOriginal (offset)) {
+ return projectedTooltipProvider.CreateTooltipWindow (projection.ProjectedEditor, projection.ProjectedContext, item, pseg.FromOriginalToProjected (offset), modifierState);
+ }
+ }
+ return null;
+ }
+
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/Projection.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/Projection.cs
new file mode 100644
index 0000000000..8698e57c4c
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/Projection/Projection.cs
@@ -0,0 +1,130 @@
+//
+// Projection.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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.Ide.Editor;
+using System.Collections.Immutable;
+using MonoDevelop.Core.Text;
+using MonoDevelop.Ide.Gui;
+using MonoDevelop.Ide.TypeSystem;
+using System.Collections.Generic;
+
+namespace MonoDevelop.Ide.Editor.Projection
+{
+ public sealed class Projection
+ {
+ public ITextDocument Document { get; private set; }
+
+ SegmentTree<ProjectedTreeSegment> originalProjections = new SegmentTree<ProjectedTreeSegment> ();
+ SegmentTree<ProjectedTreeSegment> projectedProjections = new SegmentTree<ProjectedTreeSegment> ();
+
+ class ProjectedTreeSegment : TreeSegment
+ {
+ public ProjectedTreeSegment LinkedTo { get; set; }
+
+ public ProjectedTreeSegment (int offset, int length) : base (offset, length)
+ {
+ }
+ }
+
+ public IEnumerable<ProjectedSegment> ProjectedSegments {
+ get {
+ foreach (var treeSeg in originalProjections) {
+ yield return new ProjectedSegment (treeSeg.Offset, treeSeg.LinkedTo.Offset, treeSeg.Length);
+ }
+ }
+ }
+
+ TextEditor projectedEditor;
+
+ internal TextEditor ProjectedEditor
+ {
+ get
+ {
+ return projectedEditor;
+ }
+ }
+
+ ProjectedDocumentContext projectedDocumentContext;
+ TextEditor attachedEditor;
+
+ internal DocumentContext ProjectedContext {
+ get {
+ return projectedDocumentContext;
+ }
+ }
+
+ public TextEditor CreateProjectedEditor (DocumentContext originalContext)
+ {
+ if (projectedEditor == null) {
+ projectedEditor = TextEditorFactory.CreateNewEditor (Document);
+ projectedDocumentContext = new ProjectedDocumentContext (projectedEditor, originalContext);
+ projectedEditor.InitializeExtensionChain (projectedDocumentContext);
+ projectedProjections.InstallListener (projectedEditor);
+ }
+ return projectedEditor;
+ }
+
+ public Projection (ITextDocument document, IReadOnlyList<ProjectedSegment> projectedSegments)
+ {
+ if (document == null)
+ throw new ArgumentNullException (nameof (document));
+ this.Document = document;
+
+ for (int i = 0; i < projectedSegments.Count; i++) {
+ var p = projectedSegments [i];
+ var original = new ProjectedTreeSegment (p.Offset, p.Length);
+ var projected = new ProjectedTreeSegment (p.ProjectedOffset, p.Length);
+ original.LinkedTo = projected;
+ projected.LinkedTo = original;
+ originalProjections.Add (original);
+ projectedProjections.Add (projected);
+ }
+ }
+
+ internal void Dettach ()
+ {
+ attachedEditor.TextChanged -= HandleTextChanged;
+ }
+
+ internal void Attach (TextEditor textEditor)
+ {
+ attachedEditor = textEditor;
+ attachedEditor.TextChanged += HandleTextChanged;
+ }
+
+ void HandleTextChanged (object sender, TextChangeEventArgs e)
+ {
+ foreach (var segment in originalProjections) {
+ if (segment.Contains (e.Offset)) {
+ var projectedOffset = e.Offset - segment.Offset + segment.LinkedTo.Offset;
+ projectedEditor.ReplaceText (projectedOffset, e.RemovalLength, e.InsertedText);
+ }
+ }
+
+ originalProjections.UpdateOnTextReplace (sender, e);
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/SegmentTree.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/SegmentTree.cs
new file mode 100644
index 0000000000..e22632c0b9
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/SegmentTree.cs
@@ -0,0 +1,801 @@
+//
+// SegmentTree.cs
+//
+// Author:
+// mkrueger <mkrueger@novell.com>
+//
+// Copyright (c) 2011 Novell, Inc (http://www.novell.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.Text;
+using System.Text;
+using System.Web.UI.WebControls;
+using System.Diagnostics;
+
+namespace MonoDevelop.Ide.Editor
+{
+ /// <summary>
+ /// A segment tree contains overlapping segments and get all segments overlapping a segment. It's implemented as a augmented interval tree
+ /// described in Cormen et al. (2001, Section 14.3: Interval trees, pp. 311–317).
+ /// </summary>
+ public class SegmentTree<T> : TextSegmentTree, ICollection<T> where T : TreeSegment
+ {
+ readonly RedBlackTree tree = new RedBlackTree ();
+
+ ITextDocument ownerDocument;
+
+ public int Count {
+ get {
+ return tree.Count;
+ }
+ }
+
+ public IEnumerator<T> GetEnumerator ()
+ {
+ var root = tree.Root;
+ if (root == null)
+ yield break;
+ var node = root.OuterLeft;
+ while (node != null) {
+ yield return (T)node;
+ node = node.NextNode;
+ }
+ }
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator ()
+ {
+ return GetEnumerator ();
+ }
+
+ public bool Contains (T item)
+ {
+ return this.Any (item.Equals);
+ }
+
+ public void CopyTo (T[] array, int arrayIndex)
+ {
+ Debug.Assert (array != null);
+ Debug.Assert (0 <= arrayIndex && arrayIndex < array.Length);
+ int i = arrayIndex;
+ foreach (T value in this)
+ array[i++] = value;
+ }
+
+ bool ICollection<T>.IsReadOnly {
+ get {
+ return false;
+ }
+ }
+
+ public void Add (T item)
+ {
+ InternalAdd (item);
+ }
+
+ public bool Remove (T item)
+ {
+ return InternalRemove (item);
+ }
+
+ public void Clear ()
+ {
+ tree.Clear ();
+ }
+
+ public IEnumerable<T> GetSegmentsAt (int offset)
+ {
+ return GetSegmentsOverlapping (offset, 0);
+ }
+
+ public IEnumerable<T> GetSegmentsOverlapping (ISegment segment)
+ {
+ if (segment.Offset < 0)
+ return Enumerable.Empty<T> ();
+ return GetSegmentsOverlapping (segment.Offset, segment.Length);
+ }
+
+ public IEnumerable<T> GetSegmentsOverlapping (int offset, int length)
+ {
+ if (tree.Root == null)
+ yield break;
+ var intervalStack = new Stack<Interval> ();
+ intervalStack.Push (new Interval (tree.Root, offset, offset + length));
+ while (intervalStack.Count > 0) {
+ var interval = intervalStack.Pop ();
+ if (interval.end < 0)
+ continue;
+
+ var node = interval.node;
+ int nodeStart = interval.start - node.DistanceToPrevNode;
+ int nodeEnd = interval.end - node.DistanceToPrevNode;
+ var leftNode = node.Left;
+ if (leftNode != null) {
+ nodeStart -= leftNode.TotalLength;
+ nodeEnd -= leftNode.TotalLength;
+ }
+
+ if (node.DistanceToMaxEnd < nodeStart)
+ continue;
+
+ if (leftNode != null)
+ intervalStack.Push (new Interval (leftNode, interval.start, interval.end));
+
+ if (nodeEnd < 0)
+ continue;
+
+ if (nodeStart <= node.Length)
+ yield return (T)node;
+
+ var rightNode = node.Right;
+ if (rightNode != null)
+ intervalStack.Push (new Interval (rightNode, nodeStart, nodeEnd));
+ }
+ }
+
+ public void InstallListener (ITextDocument doc)
+ {
+ if (ownerDocument != null)
+ throw new InvalidOperationException ("Segment tree already installed");
+ ownerDocument = doc;
+ doc.TextChanged += UpdateOnTextReplace;
+ }
+
+ public void RemoveListener ()
+ {
+ if (ownerDocument == null)
+ throw new InvalidOperationException ("Segment tree is not installed");
+ ownerDocument.TextChanged -= UpdateOnTextReplace;
+ ownerDocument = null;
+ }
+
+ internal void UpdateOnTextReplace (object sender, TextChangeEventArgs e)
+ {
+ if (e.RemovalLength == 0) {
+ var length = e.InsertionLength;
+ foreach (var segment in GetSegmentsAt (e.Offset).Where (s => s.Offset < e.Offset && e.Offset < s.EndOffset)) {
+ segment.Length += length;
+ segment.UpdateAugmentedData ();
+ }
+ var node = SearchFirstSegmentWithStartAfter (e.Offset);
+ if (node != null) {
+ node.DistanceToPrevNode += length;
+ node.UpdateAugmentedData ();
+ }
+ return;
+ }
+ int delta = e.ChangeDelta;
+ foreach (var segment in new List<T> (GetSegmentsOverlapping (e.Offset, e.RemovalLength))) {
+ if (segment.Offset < e.Offset) {
+ if (segment.EndOffset >= e.Offset + e.RemovalLength) {
+ segment.Length += delta;
+ } else {
+ segment.Length = e.Offset - segment.Offset;
+ }
+ segment.UpdateAugmentedData ();
+ continue;
+ }
+ int remainingLength = segment.EndOffset - (e.Offset + e.RemovalLength);
+ InternalRemove (segment);
+ if (remainingLength > 0) {
+ segment.Offset = e.Offset + e.RemovalLength;
+ segment.Length = remainingLength;
+ InternalAdd (segment);
+ }
+ }
+ var next = SearchFirstSegmentWithStartAfter (e.Offset + 1);
+
+ if (next != null) {
+ next.DistanceToPrevNode += delta;
+ next.UpdateAugmentedData ();
+ }
+ }
+
+ void InternalAdd (TreeSegment node)
+ {
+ if (node == null)
+ throw new ArgumentNullException ("node");
+ if (node.segmentTree != null)
+ throw new InvalidOperationException ("Node already attached.");
+
+ node.segmentTree = this;
+
+
+ int insertionOffset = node.Offset;
+ node.DistanceToMaxEnd = node.Length;
+
+ if (tree.Root == null) {
+ tree.Count = 1;
+ tree.Root = (T)node;
+ node.TotalLength = node.DistanceToPrevNode;
+ return;
+ }
+
+ if (insertionOffset < tree.Root.TotalLength) {
+ var n = SearchNode (ref insertionOffset);
+ node.TotalLength = node.DistanceToPrevNode = insertionOffset;
+ n.DistanceToPrevNode -= insertionOffset;
+ tree.InsertBefore (n, node);
+ return;
+ }
+
+ node.DistanceToPrevNode = node.TotalLength = insertionOffset - tree.Root.TotalLength;
+ tree.InsertRight (tree.Root.OuterRight, node);
+ }
+
+ bool InternalRemove (TreeSegment node)
+ {
+ if (node.segmentTree == null)
+ return false;
+ if (node.segmentTree != this)
+ throw new InvalidOperationException ("Tried to remove tree segment from wrong tree.");
+ var calculatedOffset = node.Offset;
+ var next = node.NextNode;
+ if (next != null)
+ next.DistanceToPrevNode += node.DistanceToPrevNode;
+ tree.Remove (node);
+ if (next != null)
+ next.UpdateAugmentedData ();
+ node.segmentTree = null;
+ node.Parent = node.Left = node.Right = null;
+ node.DistanceToPrevNode = calculatedOffset;
+ return true;
+ }
+
+ TreeSegment SearchFirstSegmentWithStartAfter (int startOffset)
+ {
+ if (tree.Root == null)
+ return null;
+ if (startOffset <= 0)
+ return tree.Root.OuterLeft;
+ var result = SearchNode (ref startOffset);
+ while (startOffset == 0) {
+ var pre = result == null ? tree.Root.OuterRight : result.PrevNode;
+ if (pre == null)
+ return null;
+ startOffset += pre.DistanceToPrevNode;
+ result = pre;
+ }
+ return result;
+ }
+
+ TreeSegment SearchNode (ref int offset)
+ {
+ TreeSegment n = tree.Root;
+ while (true) {
+ if (n.Left != null) {
+ if (offset < n.Left.TotalLength) {
+ n = n.Left;
+ continue;
+ }
+ offset -= n.Left.TotalLength;
+ }
+ if (offset < n.DistanceToPrevNode)
+ return n;
+ offset -= n.DistanceToPrevNode;
+ if (n.Right == null)
+ return null;
+ n = n.Right;
+ }
+ }
+
+ #region TextSegmentTree implementation
+
+ void TextSegmentTree.Add (TreeSegment segment)
+ {
+ InternalAdd (segment);
+ }
+
+ bool TextSegmentTree.Remove (TreeSegment segment)
+ {
+ return InternalRemove (segment);
+ }
+
+ #endregion
+
+ const bool Black = false;
+ const bool Red = true;
+
+ struct Interval
+ {
+ internal TreeSegment node;
+ internal int start, end;
+
+ public Interval (TreeSegment node,int start,int end)
+ {
+ this.node = node;
+ this.start = start;
+ this.end = end;
+ }
+
+ public override string ToString ()
+ {
+ return string.Format ("[Interval: start={0},end={1}]", start, end);
+ }
+ }
+
+ sealed class RedBlackTree
+ {
+ public T Root { get; set; }
+
+ public void InsertBefore (TreeSegment node, TreeSegment newNode)
+ {
+ if (node.Left == null) {
+ InsertLeft (node, newNode);
+ } else {
+ InsertRight (node.Left.OuterRight, newNode);
+ }
+ }
+
+ public void InsertLeft (TreeSegment parentNode, TreeSegment newNode)
+ {
+ parentNode.Left = newNode;
+ newNode.Parent = parentNode;
+ newNode.Color = Red;
+ parentNode.UpdateAugmentedData ();
+ FixTreeOnInsert (newNode);
+ Count++;
+ }
+
+ public void InsertRight (TreeSegment parentNode, TreeSegment newNode)
+ {
+ parentNode.Right = newNode;
+ newNode.Parent = parentNode;
+ newNode.Color = Red;
+ parentNode.UpdateAugmentedData ();
+ FixTreeOnInsert (newNode);
+ Count++;
+ }
+
+ void FixTreeOnInsert (TreeSegment node)
+ {
+ var parent = node.Parent;
+ if (parent == null) {
+ node.Color = Black;
+ return;
+ }
+
+ if (parent.Color == Black)
+ return;
+ var uncle = node.Uncle;
+ TreeSegment grandParent = parent.Parent;
+
+ if (uncle != null && uncle.Color == Red) {
+ parent.Color = Black;
+ uncle.Color = Black;
+ grandParent.Color = Red;
+ FixTreeOnInsert (grandParent);
+ return;
+ }
+
+ if (node == parent.Right && parent == grandParent.Left) {
+ RotateLeft (parent);
+ node = node.Left;
+ } else if (node == parent.Left && parent == grandParent.Right) {
+ RotateRight (parent);
+ node = node.Right;
+ }
+
+ parent = node.Parent;
+ grandParent = parent.Parent;
+
+ parent.Color = Black;
+ grandParent.Color = Red;
+ if (node == parent.Left && parent == grandParent.Left) {
+ RotateRight (grandParent);
+ } else {
+ RotateLeft (grandParent);
+ }
+ }
+
+ void RotateLeft (TreeSegment node)
+ {
+ TreeSegment right = node.Right;
+ Replace (node, right);
+ node.Right = right.Left;
+ if (node.Right != null)
+ node.Right.Parent = node;
+ right.Left = node;
+ node.Parent = right;
+ node.UpdateAugmentedData ();
+ node.Parent.UpdateAugmentedData ();
+ }
+
+ void RotateRight (TreeSegment node)
+ {
+ TreeSegment left = node.Left;
+ Replace (node, left);
+ node.Left = left.Right;
+ if (node.Left != null)
+ node.Left.Parent = node;
+ left.Right = node;
+ node.Parent = left;
+ node.UpdateAugmentedData ();
+ node.Parent.UpdateAugmentedData ();
+ }
+
+ void Replace (TreeSegment oldNode, TreeSegment newNode)
+ {
+ if (newNode != null)
+ newNode.Parent = oldNode.Parent;
+ if (oldNode.Parent == null) {
+ Root = (T)newNode;
+ } else {
+ if (oldNode.Parent.Left == oldNode)
+ oldNode.Parent.Left = newNode;
+ else
+ oldNode.Parent.Right = newNode;
+ oldNode.Parent.UpdateAugmentedData ();
+ }
+ }
+
+ public void Remove (TreeSegment node)
+ {
+ if (node.Left != null && node.Right != null) {
+ var outerLeft = node.Right.OuterLeft;
+ InternalRemove (outerLeft);
+ Replace (node, outerLeft);
+
+ outerLeft.Color = node.Color;
+ outerLeft.Left = node.Left;
+ if (outerLeft.Left != null)
+ outerLeft.Left.Parent = outerLeft;
+
+ outerLeft.Right = node.Right;
+ if (outerLeft.Right != null)
+ outerLeft.Right.Parent = outerLeft;
+ outerLeft.UpdateAugmentedData ();
+ return;
+ }
+ InternalRemove (node);
+ }
+
+ void InternalRemove (TreeSegment node)
+ {
+ if (node.Left != null && node.Right != null) {
+ var outerLeft = node.Right.OuterLeft;
+ InternalRemove (outerLeft);
+ Replace (node, outerLeft);
+
+ outerLeft.Color = node.Color;
+ outerLeft.Left = node.Left;
+ if (outerLeft.Left != null)
+ outerLeft.Left.Parent = outerLeft;
+
+ outerLeft.Right = node.Right;
+ if (outerLeft.Right != null)
+ outerLeft.Right.Parent = outerLeft;
+ outerLeft.UpdateAugmentedData ();
+ return;
+ }
+ Count--;
+ // node has only one child
+ TreeSegment child = node.Left ?? node.Right;
+
+ Replace (node, child);
+
+ if (node.Color == Black && child != null) {
+ if (child.Color == Red) {
+ child.Color = Black;
+ } else {
+ DeleteOneChild (child);
+ }
+ }
+ }
+
+ static bool GetColorSafe (TreeSegment node)
+ {
+ return node != null ? node.Color : Black;
+ }
+
+ void DeleteOneChild (TreeSegment node)
+ {
+ // case 1
+ if (node == null || node.Parent == null)
+ return;
+
+ var parent = node.Parent;
+ var sibling = node.Sibling;
+ if (sibling == null)
+ return;
+
+ // case 2
+ if (sibling.Color == Red) {
+ parent.Color = Red;
+ sibling.Color = Black;
+ if (node == parent.Left) {
+ RotateLeft (parent);
+ } else {
+ RotateRight (parent);
+ }
+ sibling = node.Sibling;
+ if (sibling == null)
+ return;
+ }
+
+ // case 3
+ if (parent.Color == Black && sibling.Color == Black && GetColorSafe (sibling.Left) == Black && GetColorSafe (sibling.Right) == Black) {
+ sibling.Color = Red;
+ DeleteOneChild (parent);
+ return;
+ }
+
+ // case 4
+ if (parent.Color == Red && sibling.Color == Black && GetColorSafe (sibling.Left) == Black && GetColorSafe (sibling.Right) == Black) {
+ sibling.Color = Red;
+ parent.Color = Black;
+ return;
+ }
+
+ // case 5
+ if (node == parent.Left && sibling.Color == Black && GetColorSafe (sibling.Left) == Red && GetColorSafe (sibling.Right) == Black) {
+ sibling.Color = Red;
+ if (sibling.Left != null)
+ sibling.Left.Color = Black;
+ RotateRight (sibling);
+ } else if (node == parent.Right && sibling.Color == Black && GetColorSafe (sibling.Right) == Red && GetColorSafe (sibling.Left) == Black) {
+ sibling.Color = Red;
+ if (sibling.Right != null)
+ sibling.Right.Color = Black;
+ RotateLeft (sibling);
+ }
+
+ // case 6
+ sibling = node.Sibling;
+ if (sibling == null)
+ return;
+ sibling.Color = parent.Color;
+ parent.Color = Black;
+ if (node == parent.Left) {
+ if (sibling.Right != null)
+ sibling.Right.Color = Black;
+ RotateLeft (parent);
+ } else {
+ if (sibling.Left != null)
+ sibling.Left.Color = Black;
+ RotateRight (parent);
+ }
+ }
+
+ public int Count { get; set; }
+
+ public void Clear ()
+ {
+ Root = null;
+ Count = 0;
+ }
+
+ static string GetIndent (int level)
+ {
+ return new String ('\t', level);
+ }
+
+ static void AppendNode (StringBuilder builder, TreeSegment node, int indent)
+ {
+ builder.Append (GetIndent (indent) + "Node (" + (node.Color == Red ? "r" : "b") + "):" + node + Environment.NewLine);
+ builder.Append (GetIndent (indent) + "Left: ");
+ if (node.Left != null) {
+ builder.Append (Environment.NewLine);
+ AppendNode (builder, node.Left, indent + 1);
+ } else {
+ builder.Append ("null");
+ }
+
+ builder.Append (Environment.NewLine);
+ builder.Append (GetIndent (indent) + "Right: ");
+ if (node.Right != null) {
+ builder.Append (Environment.NewLine);
+ AppendNode (builder, node.Right, indent + 1);
+ } else {
+ builder.Append ("null");
+ }
+ }
+
+ public override string ToString ()
+ {
+ if (Root == null)
+ return "<null>";
+ var result = new StringBuilder ();
+ AppendNode (result, Root, 0);
+ return result.ToString ();
+ }
+ }
+ }
+
+ interface TextSegmentTree
+ {
+ void Add (TreeSegment segment);
+ bool Remove (TreeSegment segment);
+ }
+
+ public class TreeSegment : ISegment
+ {
+ public int Offset {
+ get {
+ if (segmentTree == null)
+ return DistanceToPrevNode;
+
+ var curNode = this;
+ int offset = curNode.DistanceToPrevNode;
+ if (curNode.Left != null)
+ offset += curNode.Left.TotalLength;
+ while (curNode.Parent != null) {
+ if (curNode == curNode.Parent.Right) {
+ if (curNode.Parent.Left != null)
+ offset += curNode.Parent.Left.TotalLength;
+ offset += curNode.Parent.DistanceToPrevNode;
+ }
+ curNode = curNode.Parent;
+ }
+ return offset;
+ }
+ set {
+ if (segmentTree != null)
+ segmentTree.Remove (this);
+ DistanceToPrevNode = value;
+ if (segmentTree != null)
+ segmentTree.Add (this);
+ }
+ }
+
+ public int Length {
+ get;
+ set;
+ }
+
+ public int EndOffset {
+ get {
+ return Offset + Length;
+ }
+ }
+
+ protected TreeSegment ()
+ {
+ }
+
+ public TreeSegment (int offset, int length)
+ {
+ Offset = offset;
+ Length = length;
+ }
+
+ public TreeSegment (ISegment segment) : this (segment.Offset, segment.Length)
+ {
+ }
+
+ #region Internal API
+ internal TextSegmentTree segmentTree;
+ internal TreeSegment Parent, Left, Right;
+ internal bool Color;
+
+ // TotalLength = DistanceToPrevNode + Left.DistanceToPrevNode + Right.DistanceToPrevNode
+ internal int TotalLength;
+
+ internal int DistanceToPrevNode;
+
+ // DistanceToMaxEnd = Max (Length, left.DistanceToMaxEnd + Max (left.Offset, right.Offset) - Offset)
+ internal int DistanceToMaxEnd;
+
+ internal void UpdateAugmentedData ()
+ {
+ int totalLength = DistanceToPrevNode;
+ int distanceToMaxEnd = Length;
+
+ if (Left != null) {
+ totalLength += Left.TotalLength;
+ int leftdistance = Left.DistanceToMaxEnd - DistanceToPrevNode;
+ if (Left.Right != null)
+ leftdistance -= Left.Right.TotalLength;
+ if (leftdistance > distanceToMaxEnd)
+ distanceToMaxEnd = leftdistance;
+ }
+
+ if (Right != null) {
+ totalLength += Right.TotalLength;
+ int rightdistance = Right.DistanceToMaxEnd + Right.DistanceToPrevNode;
+ if (Right.Left != null)
+ rightdistance += Right.Left.TotalLength;
+ if (rightdistance > distanceToMaxEnd)
+ distanceToMaxEnd = rightdistance;
+ }
+
+ if (TotalLength != totalLength || DistanceToMaxEnd != distanceToMaxEnd) {
+ TotalLength = totalLength;
+ DistanceToMaxEnd = distanceToMaxEnd;
+ if (Parent != null)
+ Parent.UpdateAugmentedData ();
+ }
+ }
+
+ internal TreeSegment Sibling {
+ get {
+ if (Parent == null)
+ return null;
+ return this == Parent.Left ? Parent.Right : Parent.Left;
+ }
+ }
+
+ internal TreeSegment OuterLeft {
+ get {
+ TreeSegment result = this;
+ while (result.Left != null)
+ result = result.Left;
+ return result;
+ }
+ }
+
+ internal TreeSegment OuterRight {
+ get {
+ TreeSegment result = this;
+ while (result.Right != null) {
+ result = result.Right;
+ }
+ return result;
+ }
+ }
+
+ internal TreeSegment Grandparent {
+ get {
+ return Parent != null ? Parent.Parent : null;
+ }
+ }
+
+ internal TreeSegment Uncle {
+ get {
+ TreeSegment grandparent = Grandparent;
+ if (grandparent == null)
+ return null;
+ return Parent == grandparent.Left ? grandparent.Right : grandparent.Left;
+ }
+ }
+
+ internal TreeSegment NextNode {
+ get {
+ if (Right == null) {
+ TreeSegment curNode = this;
+ TreeSegment oldNode;
+ do {
+ oldNode = curNode;
+ curNode = curNode.Parent;
+ } while (curNode != null && curNode.Right == oldNode);
+ return curNode;
+ }
+ return Right.OuterLeft;
+ }
+ }
+
+ internal TreeSegment PrevNode {
+ get {
+ if (Left == null) {
+ TreeSegment curNode = this;
+ TreeSegment oldNode;
+ do {
+ oldNode = curNode;
+ curNode = curNode.Parent;
+ } while (curNode != null && curNode.Left == oldNode);
+ return curNode;
+ }
+ return Left.OuterRight;
+ }
+ }
+ #endregion
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/SelectionMode.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/SelectionMode.cs
new file mode 100644
index 0000000000..71b981f189
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/SelectionMode.cs
@@ -0,0 +1,33 @@
+//
+// SelectionMode.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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.
+
+namespace MonoDevelop.Ide.Editor
+{
+ public enum SelectionMode {
+ Normal,
+ Block
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextEditor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextEditor.cs
new file mode 100644
index 0000000000..444f64fd04
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextEditor.cs
@@ -0,0 +1,1260 @@
+//
+// ITextEditor.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Core.Text;
+using System.Collections.Generic;
+using System.Text;
+using MonoDevelop.Ide.Gui;
+using MonoDevelop.Ide.Editor.Extension;
+using System.IO;
+using MonoDevelop.Ide.Editor.Highlighting;
+using Mono.Addins;
+using MonoDevelop.Core;
+using MonoDevelop.Ide.Extensions;
+using System.Linq;
+using MonoDevelop.Components;
+using System.ComponentModel;
+using MonoDevelop.Ide.TypeSystem;
+using System.Threading;
+using MonoDevelop.Ide.Editor.Projection;
+
+namespace MonoDevelop.Ide.Editor
+{
+ public sealed class TextEditor : Control, ITextDocument, IDisposable
+ {
+ readonly ITextEditorImpl textEditorImpl;
+ IReadonlyTextDocument ReadOnlyTextDocument { get { return textEditorImpl.Document; } }
+ ITextDocument ReadWriteTextDocument { get { return (ITextDocument)textEditorImpl.Document; } }
+
+ public ITextSourceVersion Version {
+ get {
+ return ReadOnlyTextDocument.Version;
+ }
+ }
+
+ FileTypeCondition fileTypeCondition = new FileTypeCondition ();
+
+ List<TooltipExtensionNode> allProviders = new List<TooltipExtensionNode> ();
+
+ void OnTooltipProviderChanged (object s, ExtensionNodeEventArgs a)
+ {
+ TooltipProvider provider;
+ try {
+ var extensionNode = a.ExtensionNode as TooltipExtensionNode;
+ allProviders.Add (extensionNode);
+ if (extensionNode.IsValidFor (MimeType))
+ return;
+ provider = (TooltipProvider) extensionNode.CreateInstance ();
+ } catch (Exception e) {
+ LoggingService.LogError ("Can't create tooltip provider:"+ a.ExtensionNode, e);
+ return;
+ }
+ if (a.Change == ExtensionChange.Add) {
+ textEditorImpl.AddTooltipProvider (provider);
+ } else {
+ textEditorImpl.RemoveTooltipProvider (provider);
+ }
+ }
+
+ public event EventHandler SelectionChanged {
+ add { textEditorImpl.SelectionChanged += value; }
+ remove { textEditorImpl.SelectionChanged -= value; }
+ }
+
+ public event EventHandler CaretPositionChanged {
+ add { textEditorImpl.CaretPositionChanged += value; }
+ remove { textEditorImpl.CaretPositionChanged -= value; }
+ }
+
+ public event EventHandler BeginAtomicUndoOperation {
+ add { textEditorImpl.BeginAtomicUndoOperation += value; }
+ remove { textEditorImpl.BeginAtomicUndoOperation -= value; }
+ }
+
+ public event EventHandler EndAtomicUndoOperation {
+ add { textEditorImpl.EndAtomicUndoOperation += value; }
+ remove { textEditorImpl.EndAtomicUndoOperation -= value; }
+ }
+
+ public event EventHandler<TextChangeEventArgs> TextChanging {
+ add { ReadWriteTextDocument.TextChanging += value; }
+ remove { ReadWriteTextDocument.TextChanging -= value; }
+ }
+
+ public event EventHandler<TextChangeEventArgs> TextChanged {
+ add { ReadWriteTextDocument.TextChanged += value; }
+ remove { ReadWriteTextDocument.TextChanged -= value; }
+ }
+
+ public event EventHandler BeginMouseHover {
+ add { textEditorImpl.BeginMouseHover += value; }
+ remove { textEditorImpl.BeginMouseHover -= value; }
+ }
+
+ public event EventHandler VAdjustmentChanged {
+ add { textEditorImpl.VAdjustmentChanged += value; }
+ remove { textEditorImpl.VAdjustmentChanged -= value; }
+ }
+
+ public event EventHandler HAdjustmentChanged {
+ add { textEditorImpl.HAdjustmentChanged += value; }
+ remove { textEditorImpl.HAdjustmentChanged -= value; }
+ }
+ public char this[int offset] {
+ get {
+ return ReadOnlyTextDocument [offset];
+ }
+ set {
+ ReadWriteTextDocument [offset] = value;
+ }
+ }
+
+// public event EventHandler<LineEventArgs> LineChanged {
+// add { textEditorImpl.LineChanged += value; }
+// remove { textEditorImpl.LineChanged -= value; }
+// }
+//
+// public event EventHandler<LineEventArgs> LineInserted {
+// add { textEditorImpl.LineInserted += value; }
+// remove { textEditorImpl.LineInserted -= value; }
+// }
+//
+// public event EventHandler<LineEventArgs> LineRemoved {
+// add { textEditorImpl.LineRemoved += value; }
+// remove { textEditorImpl.LineRemoved -= value; }
+// }
+
+ public ITextEditorOptions Options {
+ get {
+ return textEditorImpl.Options;
+ }
+ set {
+ textEditorImpl.Options = value;
+ OnOptionsChanged (EventArgs.Empty);
+ }
+ }
+
+ public event EventHandler OptionsChanged;
+
+ void OnOptionsChanged (EventArgs e)
+ {
+ var handler = OptionsChanged;
+ if (handler != null)
+ handler (this, e);
+ }
+
+ public EditMode EditMode {
+ get {
+ return textEditorImpl.EditMode;
+ }
+ }
+
+ public DocumentLocation CaretLocation {
+ get {
+ return textEditorImpl.CaretLocation;
+ }
+ set {
+ textEditorImpl.CaretLocation = value;
+ }
+ }
+
+ public SemanticHighlighting SemanticHighlighting {
+ get {
+ return textEditorImpl.SemanticHighlighting;
+ }
+ set {
+ textEditorImpl.SemanticHighlighting = value;
+ }
+ }
+
+ public int CaretLine {
+ get {
+ return CaretLocation.Line;
+ }
+ set {
+ CaretLocation = new DocumentLocation (value, CaretColumn);
+ }
+ }
+
+ public int CaretColumn {
+ get {
+ return CaretLocation.Column;
+ }
+ set {
+ CaretLocation = new DocumentLocation (CaretLine, value);
+ }
+ }
+
+ public int CaretOffset {
+ get {
+ return textEditorImpl.CaretOffset;
+ }
+ set {
+ textEditorImpl.CaretOffset = value;
+ }
+ }
+
+ public bool IsReadOnly {
+ get {
+ return ReadOnlyTextDocument.IsReadOnly;
+ }
+ set {
+ ReadWriteTextDocument.IsReadOnly = value;
+ }
+ }
+
+ public bool IsSomethingSelected {
+ get {
+ return textEditorImpl.IsSomethingSelected;
+ }
+ }
+
+ public SelectionMode SelectionMode {
+ get {
+ return textEditorImpl.SelectionMode;
+ }
+ }
+
+ public ISegment SelectionRange {
+ get {
+ return textEditorImpl.SelectionRange;
+ }
+ set {
+ textEditorImpl.SelectionRange = value;
+ }
+ }
+
+ public DocumentRegion SelectionRegion {
+ get {
+ return textEditorImpl.SelectionRegion;
+ }
+ set {
+ textEditorImpl.SelectionRegion = value;
+ }
+ }
+
+ public int SelectionAnchorOffset {
+ get {
+ return textEditorImpl.SelectionAnchorOffset;
+ }
+ set {
+ textEditorImpl.SelectionAnchorOffset = value;
+ }
+ }
+
+ public int SelectionLeadOffset {
+ get {
+ return textEditorImpl.SelectionLeadOffset;
+ }
+ set {
+ textEditorImpl.SelectionLeadOffset = value;
+ }
+ }
+
+ public string SelectedText {
+ get {
+ return IsSomethingSelected ? ReadOnlyTextDocument.GetTextAt (SelectionRange) : null;
+ }
+ set {
+ var selection = SelectionRange;
+ ReplaceText (selection, value);
+ SelectionRange = new TextSegment (selection.Offset, value.Length);
+ }
+ }
+
+ public bool IsInAtomicUndo {
+ get {
+ return ReadWriteTextDocument.IsInAtomicUndo;
+ }
+ }
+
+ public double LineHeight {
+ get {
+ return textEditorImpl.LineHeight;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the type of the MIME.
+ /// </summary>
+ /// <value>The type of the MIME.</value>
+ public string MimeType {
+ get {
+ return ReadOnlyTextDocument.MimeType;
+ }
+ set {
+ ReadWriteTextDocument.MimeType = value;
+ }
+ }
+
+ public event EventHandler MimeTypeChanged {
+ add { ReadWriteTextDocument.MimeTypeChanged += value; }
+ remove { ReadWriteTextDocument.MimeTypeChanged -= value; }
+ }
+
+ public string Text {
+ get {
+ return ReadOnlyTextDocument.Text;
+ }
+ set {
+ ReadWriteTextDocument.Text = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets the eol marker. On a text editor always use that and not GetEolMarker.
+ /// The EOL marker of the document may get overwritten my the one from the options.
+ /// </summary>
+ public string EolMarker {
+ get {
+ if (Options.OverrideDocumentEolMarker)
+ return Options.DefaultEolMarker;
+ return ReadOnlyTextDocument.GetEolMarker ();
+ }
+ }
+
+ public bool UseBOM {
+ get {
+ return ReadOnlyTextDocument.UseBOM;
+ }
+ set {
+ ReadWriteTextDocument.UseBOM = value;
+ }
+ }
+
+ public Encoding Encoding {
+ get {
+ return ReadOnlyTextDocument.Encoding;
+ }
+ set {
+ ReadWriteTextDocument.Encoding = value;
+ }
+ }
+
+ public int LineCount {
+ get {
+ return ReadOnlyTextDocument.LineCount;
+ }
+ }
+
+ /// <summary>
+ /// Gets the name of the file the document is stored in.
+ /// Could also be a non-existent dummy file name or null if no name has been set.
+ /// </summary>
+ public FilePath FileName {
+ get {
+ return ReadOnlyTextDocument.FileName;
+ }
+ set {
+ ReadWriteTextDocument.FileName = value;
+ }
+ }
+
+ public event EventHandler FileNameChanged {
+ add {
+ ReadWriteTextDocument.FileNameChanged += value;
+ }
+ remove {
+ ReadWriteTextDocument.FileNameChanged -= value;
+ }
+ }
+
+ public int Length {
+ get {
+ return ReadOnlyTextDocument.Length;
+ }
+ }
+
+ public double ZoomLevel {
+ get {
+ return textEditorImpl.ZoomLevel;
+ }
+ set {
+ textEditorImpl.ZoomLevel = value;
+ }
+ }
+
+ public event EventHandler ZoomLevelChanged {
+ add {
+ textEditorImpl.ZoomLevelChanged += value;
+ }
+ remove {
+ textEditorImpl.ZoomLevelChanged -= value;
+ }
+ }
+
+ public IDisposable OpenUndoGroup ()
+ {
+ return ReadWriteTextDocument.OpenUndoGroup ();
+ }
+
+ public void SetSelection (int anchorOffset, int leadOffset)
+ {
+ textEditorImpl.SetSelection (anchorOffset, leadOffset);
+ }
+
+ public void SetSelection (DocumentLocation anchor, DocumentLocation lead)
+ {
+ SetSelection (LocationToOffset (anchor), LocationToOffset (lead));
+ }
+
+ public void SetCaretLocation (DocumentLocation location, bool usePulseAnimation = false)
+ {
+ CaretLocation = location;
+ ScrollTo (CaretLocation);
+ if (usePulseAnimation)
+ StartCaretPulseAnimation ();
+ }
+
+ public void SetCaretLocation (int line, int col, bool usePulseAnimation = false)
+ {
+ CaretLocation = new DocumentLocation (line, col);
+ CenterTo (CaretLocation);
+ if (usePulseAnimation)
+ StartCaretPulseAnimation ();
+ }
+
+ public void ClearSelection ()
+ {
+ textEditorImpl.ClearSelection ();
+ }
+
+ public void CenterToCaret ()
+ {
+ textEditorImpl.CenterToCaret ();
+ }
+
+ public void StartCaretPulseAnimation ()
+ {
+ textEditorImpl.StartCaretPulseAnimation ();
+ }
+
+ public int EnsureCaretIsNotVirtual ()
+ {
+ return textEditorImpl.EnsureCaretIsNotVirtual ();
+ }
+
+ public void FixVirtualIndentation ()
+ {
+ textEditorImpl.FixVirtualIndentation ();
+ }
+
+ public void RunWhenLoaded (Action action)
+ {
+ if (action == null)
+ throw new ArgumentNullException ("action");
+ textEditorImpl.RunWhenLoaded (action);
+ }
+
+ public string FormatString (DocumentLocation insertPosition, string code)
+ {
+ return textEditorImpl.FormatString (LocationToOffset (insertPosition), code);
+ }
+
+ public string FormatString (int offset, string code)
+ {
+ return textEditorImpl.FormatString (offset, code);
+ }
+
+ public void StartInsertionMode (InsertionModeOptions insertionModeOptions)
+ {
+ if (insertionModeOptions == null)
+ throw new ArgumentNullException ("insertionModeOptions");
+ textEditorImpl.StartInsertionMode (insertionModeOptions);
+ }
+
+ public void StartTextLinkMode (TextLinkModeOptions textLinkModeOptions)
+ {
+ if (textLinkModeOptions == null)
+ throw new ArgumentNullException ("textLinkModeOptions");
+ textEditorImpl.StartTextLinkMode (textLinkModeOptions);
+ }
+
+ public void InsertAtCaret (string text)
+ {
+ InsertText (CaretOffset, text);
+ }
+
+ public DocumentLocation PointToLocation (double xp, double yp, bool endAtEol = false)
+ {
+ return textEditorImpl.PointToLocation (xp, yp, endAtEol);
+ }
+
+ public Xwt.Point LocationToPoint (DocumentLocation location)
+ {
+ return textEditorImpl.LocationToPoint (location.Line, location.Column);
+ }
+
+ public Xwt.Point LocationToPoint (int line, int column)
+ {
+ return textEditorImpl.LocationToPoint (line, column);
+ }
+
+ public string GetLineText (int line, bool includeDelimiter = false)
+ {
+ var segment = GetLine (line);
+ return GetTextAt (includeDelimiter ? segment.SegmentIncludingDelimiter : segment);
+ }
+
+ public int LocationToOffset (int line, int column)
+ {
+ return ReadOnlyTextDocument.LocationToOffset (new DocumentLocation (line, column));
+ }
+
+ public int LocationToOffset (DocumentLocation location)
+ {
+ return ReadOnlyTextDocument.LocationToOffset (location);
+ }
+
+ public DocumentLocation OffsetToLocation (int offset)
+ {
+ return ReadOnlyTextDocument.OffsetToLocation (offset);
+ }
+
+ public void InsertText (int offset, string text)
+ {
+ ReadWriteTextDocument.InsertText (offset, text);
+ }
+
+ public void InsertText (int offset, ITextSource text)
+ {
+ ReadWriteTextDocument.InsertText (offset, text);
+ }
+
+ public void RemoveText (int offset, int count)
+ {
+ RemoveText (new TextSegment (offset, count));
+ }
+
+ public void RemoveText (ISegment segment)
+ {
+ if (segment == null)
+ throw new ArgumentNullException ("segment");
+ ReadWriteTextDocument.RemoveText (segment);
+ }
+
+ public void ReplaceText (int offset, int count, string value)
+ {
+ ReadWriteTextDocument.ReplaceText (offset, count, value);
+ }
+
+ public void ReplaceText (int offset, int count, ITextSource value)
+ {
+ ReadWriteTextDocument.ReplaceText (offset, count, value);
+ }
+
+ public void ReplaceText (ISegment segment, string value)
+ {
+ if (segment == null)
+ throw new ArgumentNullException ("segment");
+ ReadWriteTextDocument.ReplaceText (segment.Offset, segment.Length, value);
+ }
+
+ public void ReplaceText (ISegment segment, ITextSource value)
+ {
+ if (segment == null)
+ throw new ArgumentNullException ("segment");
+ ReadWriteTextDocument.ReplaceText (segment.Offset, segment.Length, value);
+ }
+
+ public IDocumentLine GetLine (int lineNumber)
+ {
+ return ReadOnlyTextDocument.GetLine (lineNumber);
+ }
+
+ public IDocumentLine GetLineByOffset (int offset)
+ {
+ return ReadOnlyTextDocument.GetLineByOffset (offset);
+ }
+
+ public int OffsetToLineNumber (int offset)
+ {
+ return ReadOnlyTextDocument.OffsetToLineNumber (offset);
+ }
+
+ public void AddMarker (IDocumentLine line, ITextLineMarker lineMarker)
+ {
+ if (line == null)
+ throw new ArgumentNullException ("line");
+ if (lineMarker == null)
+ throw new ArgumentNullException ("lineMarker");
+ textEditorImpl.AddMarker (line, lineMarker);
+ }
+
+ public void AddMarker (int lineNumber, ITextLineMarker lineMarker)
+ {
+ if (lineMarker == null)
+ throw new ArgumentNullException ("lineMarker");
+ AddMarker (GetLine (lineNumber), lineMarker);
+ }
+
+ public void RemoveMarker (ITextLineMarker lineMarker)
+ {
+ if (lineMarker == null)
+ throw new ArgumentNullException ("lineMarker");
+ textEditorImpl.RemoveMarker (lineMarker);
+ }
+
+ public IEnumerable<ITextLineMarker> GetLineMarkers (IDocumentLine line)
+ {
+ if (line == null)
+ throw new ArgumentNullException ("line");
+ return textEditorImpl.GetLineMarkers (line);
+ }
+
+ public IEnumerable<ITextSegmentMarker> GetTextSegmentMarkersAt (ISegment segment)
+ {
+ if (segment == null)
+ throw new ArgumentNullException ("segment");
+ return textEditorImpl.GetTextSegmentMarkersAt (segment);
+ }
+
+ public IEnumerable<ITextSegmentMarker> GetTextSegmentMarkersAt (int offset)
+ {
+ return textEditorImpl.GetTextSegmentMarkersAt (offset);
+ }
+
+ public void AddMarker (ITextSegmentMarker marker)
+ {
+ if (marker == null)
+ throw new ArgumentNullException ("marker");
+ textEditorImpl.AddMarker (marker);
+ }
+
+ public bool RemoveMarker (ITextSegmentMarker marker)
+ {
+ if (marker == null)
+ throw new ArgumentNullException ("marker");
+ return textEditorImpl.RemoveMarker (marker);
+ }
+
+ public void SetFoldings (IEnumerable<IFoldSegment> foldings)
+ {
+ if (foldings == null)
+ throw new ArgumentNullException ("foldings");
+ textEditorImpl.SetFoldings (foldings);
+ }
+
+
+ public IEnumerable<IFoldSegment> GetFoldingsContaining (int offset)
+ {
+ return textEditorImpl.GetFoldingsContaining (offset);
+ }
+
+ public IEnumerable<IFoldSegment> GetFoldingsIn (ISegment segment)
+ {
+ if (segment == null)
+ throw new ArgumentNullException ("segment");
+ return textEditorImpl.GetFoldingsIn (segment.Offset, segment.Length);
+ }
+
+ /// <summary>
+ /// Gets a character at the specified position in the document.
+ /// </summary>
+ /// <paramref name="offset">The index of the character to get.</paramref>
+ /// <exception cref="ArgumentOutOfRangeException">Offset is outside the valid range (0 to TextLength-1).</exception>
+ /// <returns>The character at the specified position.</returns>
+ /// <remarks>This is the same as Text[offset], but is more efficient because
+ /// it doesn't require creating a String object.</remarks>
+ public char GetCharAt (int offset)
+ {
+ return ReadOnlyTextDocument.GetCharAt (offset);
+ }
+
+ public string GetTextAt (int offset, int length)
+ {
+ return ReadOnlyTextDocument.GetTextAt (offset, length);
+ }
+
+ public string GetTextAt (ISegment segment)
+ {
+ if (segment == null)
+ throw new ArgumentNullException ("segment");
+ return ReadOnlyTextDocument.GetTextAt (segment);
+ }
+
+ public IReadonlyTextDocument CreateDocumentSnapshot ()
+ {
+ return ReadWriteTextDocument.CreateDocumentSnapshot ();
+ }
+
+ public string GetVirtualIndentationString (int lineNumber)
+ {
+ if (lineNumber < 1 || lineNumber > LineCount)
+ throw new ArgumentOutOfRangeException ("lineNumber");
+ return textEditorImpl.GetVirtualIndentationString (lineNumber);
+ }
+
+ public string GetVirtualIndentationString (IDocumentLine line)
+ {
+ if (line == null)
+ throw new ArgumentNullException ("line");
+ return textEditorImpl.GetVirtualIndentationString (line.LineNumber);
+ }
+
+ public int GetVirtualIndentationColumn (int lineNumber)
+ {
+ if (lineNumber < 1 || lineNumber > LineCount)
+ throw new ArgumentOutOfRangeException ("lineNumber");
+ return 1 + textEditorImpl.GetVirtualIndentationString (lineNumber).Length;
+ }
+
+ public int GetVirtualIndentationColumn (IDocumentLine line)
+ {
+ if (line == null)
+ throw new ArgumentNullException ("line");
+ return 1 + textEditorImpl.GetVirtualIndentationString (line.LineNumber).Length;
+ }
+
+ public TextReader CreateReader ()
+ {
+ return ReadOnlyTextDocument.CreateReader ();
+ }
+
+ public TextReader CreateReader (int offset, int length)
+ {
+ return ReadOnlyTextDocument.CreateReader (offset, length);
+ }
+
+ public ITextSource CreateSnapshot ()
+ {
+ return ReadOnlyTextDocument.CreateSnapshot ();
+ }
+
+ public ITextSource CreateSnapshot (int offset, int length)
+ {
+ return ReadOnlyTextDocument.CreateSnapshot (offset, length);
+ }
+
+ public ITextSource CreateSnapshot (ISegment segment)
+ {
+ if (segment == null)
+ throw new ArgumentNullException ("segment");
+ return ReadOnlyTextDocument.CreateSnapshot (segment.Offset, segment.Length);
+ }
+
+ public void WriteTextTo (TextWriter writer)
+ {
+ if (writer == null)
+ throw new ArgumentNullException ("writer");
+ ReadOnlyTextDocument.WriteTextTo (writer);
+ }
+
+ public void WriteTextTo (TextWriter writer, int offset, int length)
+ {
+ if (writer == null)
+ throw new ArgumentNullException ("writer");
+ ReadOnlyTextDocument.WriteTextTo (writer, offset, length);
+ }
+
+ public void ScrollTo (int offset)
+ {
+ textEditorImpl.ScrollTo (offset);
+ }
+
+ public void ScrollTo (DocumentLocation loc)
+ {
+ ScrollTo (LocationToOffset (loc));
+ }
+
+ public void CenterTo (int offset)
+ {
+ textEditorImpl.CenterTo (offset);
+ }
+
+ public void CenterTo (DocumentLocation loc)
+ {
+ CenterTo (LocationToOffset (loc));
+ }
+
+ [EditorBrowsable(EditorBrowsableState.Advanced)]
+ public void SetIndentationTracker (IndentationTracker indentationTracker)
+ {
+ textEditorImpl.SetIndentationTracker (indentationTracker);
+ }
+
+ [EditorBrowsable(EditorBrowsableState.Advanced)]
+ public void SetSelectionSurroundingProvider (SelectionSurroundingProvider surroundingProvider)
+ {
+ textEditorImpl.SetSelectionSurroundingProvider (surroundingProvider);
+ }
+
+ [EditorBrowsable(EditorBrowsableState.Advanced)]
+ public void SetTextPasteHandler (TextPasteHandler textPasteHandler)
+ {
+ textEditorImpl.SetTextPasteHandler (textPasteHandler);
+ }
+
+ public IList<SkipChar> SkipChars {
+ get {
+ return textEditorImpl.SkipChars;
+ }
+ }
+
+ /// <summary>
+ /// Skip chars are
+ /// </summary>
+ public void AddSkipChar (int offset, char ch)
+ {
+ textEditorImpl.AddSkipChar (offset, ch);
+ }
+
+ protected override void Dispose (bool disposing)
+ {
+ if (disposing) {
+ DetachExtensionChain ();
+ textEditorImpl.Dispose ();
+ }
+ base.Dispose (disposing);
+ }
+
+ protected override object CreateNativeWidget ()
+ {
+ return textEditorImpl.CreateNativeControl ();
+ }
+
+ #region Internal API
+ ExtensionContext extensionContext;
+
+ internal ExtensionContext ExtensionContext {
+ get {
+ return extensionContext;
+ }
+ set {
+ if (extensionContext != null) {
+ extensionContext.RemoveExtensionNodeHandler ("MonoDevelop/SourceEditor2/TooltipProviders", OnTooltipProviderChanged);
+// textEditorImpl.ClearTooltipProviders ();
+ }
+ extensionContext = value;
+ if (extensionContext != null)
+ extensionContext.AddExtensionNodeHandler ("MonoDevelop/SourceEditor2/TooltipProviders", OnTooltipProviderChanged);
+ }
+ }
+
+ internal IEditorActionHost EditorActionHost {
+ get {
+ return textEditorImpl.Actions;
+ }
+ }
+
+ internal ITextMarkerFactory TextMarkerFactory {
+ get {
+ return textEditorImpl.TextMarkerFactory;
+ }
+ }
+
+ internal TextEditor (ITextEditorImpl textEditorImpl)
+ {
+ if (textEditorImpl == null)
+ throw new ArgumentNullException ("textEditorImpl");
+ this.textEditorImpl = textEditorImpl;
+ commandRouter = new InternalCommandRouter (this);
+ fileTypeCondition.SetFileName (FileName);
+ ExtensionContext = AddinManager.CreateExtensionContext ();
+ ExtensionContext.RegisterCondition ("FileType", fileTypeCondition);
+
+ FileNameChanged += delegate {
+ fileTypeCondition.SetFileName (FileName);
+ };
+
+ MimeTypeChanged += delegate {
+ textEditorImpl.ClearTooltipProviders ();
+ foreach (var extensionNode in allProviders) {
+ if (extensionNode.IsValidFor (MimeType))
+ textEditorImpl.AddTooltipProvider ((TooltipProvider) extensionNode.CreateInstance ());
+ }
+ };
+ }
+
+ TextEditorViewContent viewContent;
+ internal IViewContent GetViewContent ()
+ {
+ if (viewContent == null) {
+ viewContent = new TextEditorViewContent (this, textEditorImpl);
+ }
+
+ return viewContent;
+ }
+
+ internal IFoldSegment CreateFoldSegment (int offset, int length, bool isFolded = false)
+ {
+ return textEditorImpl.CreateFoldSegment (offset, length, isFolded);
+ }
+ #endregion
+
+ #region Editor extensions
+ InternalCommandRouter commandRouter;
+ class InternalCommandRouter : MonoDevelop.Components.Commands.IMultiCastCommandRouter
+ {
+ readonly TextEditor editor;
+
+ public InternalCommandRouter (TextEditor editor)
+ {
+ this.editor = editor;
+ }
+
+ #region IMultiCastCommandRouter implementation
+
+ System.Collections.IEnumerable MonoDevelop.Components.Commands.IMultiCastCommandRouter.GetCommandTargets ()
+ {
+ yield return editor.textEditorImpl;
+ yield return editor.textEditorImpl.EditorExtension;
+ }
+ #endregion
+ }
+
+ internal object CommandRouter {
+ get {
+ return commandRouter;
+ }
+ }
+
+ DocumentContext documentContext;
+ internal DocumentContext DocumentContext {
+ get {
+ return documentContext;
+ }
+ set {
+ documentContext = value;
+ OnDocumentContextChanged (EventArgs.Empty);
+ }
+ }
+
+ public event EventHandler DocumentContextChanged;
+
+ void OnDocumentContextChanged (EventArgs e)
+ {
+ if (DocumentContext != null) {
+ textEditorImpl.SetQuickTaskProviders (DocumentContext.GetContents<IQuickTaskProvider> ());
+ textEditorImpl.SetUsageTaskProviders (DocumentContext.GetContents<UsageProviderEditorExtension> ());
+ } else {
+ textEditorImpl.SetQuickTaskProviders (Enumerable.Empty<IQuickTaskProvider> ());
+ textEditorImpl.SetUsageTaskProviders (Enumerable.Empty<UsageProviderEditorExtension> ());
+ }
+ var handler = DocumentContextChanged;
+ if (handler != null)
+ handler (this, e);
+ }
+
+ internal void InitializeExtensionChain (DocumentContext documentContext)
+ {
+ if (documentContext == null)
+ throw new ArgumentNullException ("documentContext");
+ DetachExtensionChain ();
+ var extensions = ExtensionContext.GetExtensionNodes ("/MonoDevelop/Ide/TextEditorExtensions", typeof(TextEditorExtensionNode));
+ TextEditorExtension last = null;
+ var mimetypeChain = DesktopService.GetMimeTypeInheritanceChainForFile (FileName).ToArray ();
+ foreach (TextEditorExtensionNode extNode in extensions) {
+ if (!extNode.Supports (FileName, mimetypeChain))
+ continue;
+ TextEditorExtension ext;
+ try {
+ var instance = extNode.CreateInstance ();
+ ext = instance as TextEditorExtension;
+ if (ext == null)
+ continue;
+ } catch (Exception e) {
+ LoggingService.LogError ("Error while creating text editor extension :" + extNode.Id + "(" + extNode.Type +")", e);
+ continue;
+ }
+ if (ext.IsValidInContext (documentContext)) {
+ if (last != null) {
+ last.Next = ext;
+ last = ext;
+ } else {
+ textEditorImpl.EditorExtension = last = ext;
+ }
+ ext.Initialize (this, documentContext);
+ }
+ }
+ this.DocumentContext = documentContext;
+ }
+
+ void DetachExtensionChain ()
+ {
+ var editorExtension = textEditorImpl.EditorExtension;
+ while (editorExtension != null) {
+ try {
+ editorExtension.Dispose ();
+ } catch (Exception ex) {
+ LoggingService.LogError ("Exception while disposing extension:" + editorExtension, ex);
+ }
+ editorExtension = editorExtension.Next;
+ }
+ textEditorImpl.EditorExtension = null;
+ }
+
+ public T GetContent<T> () where T : class
+ {
+ T result = textEditorImpl as T;
+ if (result != null)
+ return result;
+ var ext = textEditorImpl.EditorExtension;
+ while (ext != null) {
+ result = ext as T;
+ if (result != null)
+ return result;
+ ext = ext.Next;
+ }
+ return null;
+ }
+
+ public IEnumerable<T> GetContents<T> () where T : class
+ {
+ T result = textEditorImpl as T;
+ if (result != null)
+ yield return result;
+ var ext = textEditorImpl.EditorExtension;
+ while (ext != null) {
+ result = ext as T;
+ if (result != null)
+ yield return result;
+ ext = ext.Next;
+ }
+ }
+ #endregion
+
+ public string GetPangoMarkup (int offset, int length)
+ {
+ return textEditorImpl.GetPangoMarkup (offset, length);
+ }
+
+ public string GetPangoMarkup (ISegment segment)
+ {
+ if (segment == null)
+ throw new ArgumentNullException ("segment");
+ return textEditorImpl.GetPangoMarkup (segment.Offset, segment.Length);
+ }
+
+ public static implicit operator Microsoft.CodeAnalysis.Text.SourceText (TextEditor editor)
+ {
+ return new MonoDevelopSourceText (editor);
+ }
+
+
+ #region Annotations
+ // Annotations: points either null (no annotations), to the single annotation,
+ // or to an AnnotationList.
+ // Once it is pointed at an AnnotationList, it will never change (this allows thread-safety support by locking the list)
+
+ object annotations;
+ sealed class AnnotationList : List<object>, ICloneable
+ {
+ // There are two uses for this custom list type:
+ // 1) it's private, and thus (unlike List<object>) cannot be confused with real annotations
+ // 2) It allows us to simplify the cloning logic by making the list behave the same as a clonable annotation.
+ public AnnotationList (int initialCapacity) : base(initialCapacity)
+ {
+ }
+
+ public object Clone ()
+ {
+ lock (this) {
+ AnnotationList copy = new AnnotationList (this.Count);
+ for (int i = 0; i < this.Count; i++) {
+ object obj = this [i];
+ ICloneable c = obj as ICloneable;
+ copy.Add (c != null ? c.Clone () : obj);
+ }
+ return copy;
+ }
+ }
+ }
+
+ public void AddAnnotation (object annotation)
+ {
+ if (annotation == null)
+ throw new ArgumentNullException ("annotation");
+ retry: // Retry until successful
+ object oldAnnotation = Interlocked.CompareExchange (ref this.annotations, annotation, null);
+ if (oldAnnotation == null) {
+ return; // we successfully added a single annotation
+ }
+ AnnotationList list = oldAnnotation as AnnotationList;
+ if (list == null) {
+ // we need to transform the old annotation into a list
+ list = new AnnotationList (4);
+ list.Add (oldAnnotation);
+ list.Add (annotation);
+ if (Interlocked.CompareExchange (ref this.annotations, list, oldAnnotation) != oldAnnotation) {
+ // the transformation failed (some other thread wrote to this.annotations first)
+ goto retry;
+ }
+ } else {
+ // once there's a list, use simple locking
+ lock (list) {
+ list.Add (annotation);
+ }
+ }
+ }
+
+ public void RemoveAnnotations<T> () where T : class
+ {
+ retry: // Retry until successful
+ object oldAnnotations = this.annotations;
+ var list = oldAnnotations as AnnotationList;
+ if (list != null) {
+ lock (list)
+ list.RemoveAll (obj => obj is T);
+ } else if (oldAnnotations is T) {
+ if (Interlocked.CompareExchange (ref this.annotations, null, oldAnnotations) != oldAnnotations) {
+ // Operation failed (some other thread wrote to this.annotations first)
+ goto retry;
+ }
+ }
+ }
+
+ public T Annotation<T> () where T: class
+ {
+ object annotations = this.annotations;
+ var list = annotations as AnnotationList;
+ if (list != null) {
+ lock (list) {
+ foreach (object obj in list) {
+ T t = obj as T;
+ if (t != null)
+ return t;
+ }
+ return null;
+ }
+ }
+ return annotations as T;
+ }
+
+ /// <summary>
+ /// Gets all annotations stored on this AstNode.
+ /// </summary>
+ public IEnumerable<object> Annotations {
+ get {
+ object annotations = this.annotations;
+ AnnotationList list = annotations as AnnotationList;
+ if (list != null) {
+ lock (list) {
+ return list.ToArray ();
+ }
+ }
+ if (annotations != null)
+ return new [] { annotations };
+ return Enumerable.Empty<object> ();
+ }
+ }
+ #endregion
+
+ List<ProjectedTooltipProvider> projectedProviders = new List<ProjectedTooltipProvider> ();
+ IReadOnlyList<MonoDevelop.Ide.Editor.Projection.Projection> projections = null;
+
+ public void SetOrUpdateProjections (DocumentContext ctx, IReadOnlyList<MonoDevelop.Ide.Editor.Projection.Projection> projections, DisabledProjectionFeatures disabledFeatures = DisabledProjectionFeatures.None)
+ {
+ if (ctx == null)
+ throw new ArgumentNullException ("ctx");
+ if (this.projections != null) {
+ foreach (var projection in this.projections) {
+ projection.Dettach ();
+ }
+ }
+ this.projections = projections;
+ if (projections != null) {
+ foreach (var projection in projections) {
+ projection.Attach (this);
+ }
+ }
+
+ if ((disabledFeatures & DisabledProjectionFeatures.SemanticHighlighting) != DisabledProjectionFeatures.SemanticHighlighting) {
+ if (SemanticHighlighting is ProjectedSemanticHighlighting) {
+ ((ProjectedSemanticHighlighting)SemanticHighlighting).UpdateProjection (projections);
+ } else {
+ SemanticHighlighting = new ProjectedSemanticHighlighting (this, ctx, projections);
+ }
+ }
+
+ if ((disabledFeatures & DisabledProjectionFeatures.Tooltips) != DisabledProjectionFeatures.Tooltips) {
+ projectedProviders.ForEach (textEditorImpl.RemoveTooltipProvider);
+ projectedProviders = new List<ProjectedTooltipProvider> ();
+ foreach (var projection in projections) {
+ foreach (var tp in projection.ProjectedEditor.textEditorImpl.TooltipProvider) {
+ var newProvider = new ProjectedTooltipProvider (this, ctx, projection, tp);
+ projectedProviders.Add (newProvider);
+ textEditorImpl.AddTooltipProvider (newProvider);
+ }
+ }
+ }
+ InitializeProjectionExtensions (ctx, disabledFeatures);
+ }
+
+ bool projectionsAdded = false;
+ void InitializeProjectionExtensions (DocumentContext ctx, DisabledProjectionFeatures disabledFeatures)
+ {
+ if (projectionsAdded) {
+ TextEditorExtension ext = textEditorImpl.EditorExtension;
+ while (ext != null && ext.Next != null) {
+ var pext = ext as IProjectionExtension;
+ if (pext != null) {
+ pext.Projections = projections;
+ }
+ ext = ext.Next;
+ }
+ return;
+ }
+
+ if (projections.Count == 0)
+ return;
+
+ TextEditorExtension lastExtension = textEditorImpl.EditorExtension;
+ while (lastExtension != null && lastExtension.Next != null) {
+ var completionTextEditorExtension = lastExtension.Next as CompletionTextEditorExtension;
+ if (completionTextEditorExtension != null) {
+ var projectedFilterExtension = new ProjectedFilterCompletionTextEditorExtension (completionTextEditorExtension, projections) { Next = completionTextEditorExtension.Next };
+ lastExtension.Next = projectedFilterExtension;
+ projectedFilterExtension.Initialize (this, DocumentContext);
+ }
+ lastExtension = lastExtension.Next;
+ }
+
+ // no extensions -> no projections needed
+ if (textEditorImpl.EditorExtension == null)
+ return;
+
+ if ((disabledFeatures & DisabledProjectionFeatures.Completion) != DisabledProjectionFeatures.Completion) {
+ var projectedCompletionExtension = new ProjectedCompletionExtension (ctx, projections);
+ projectedCompletionExtension.Next = textEditorImpl.EditorExtension;
+
+ textEditorImpl.EditorExtension = projectedCompletionExtension;
+ projectedCompletionExtension.Initialize (this, DocumentContext);
+ }
+ projectionsAdded = true;
+ }
+
+ public void AddOverlay (Control messageOverlayContent, Func<int> sizeFunc)
+ {
+ textEditorImpl.AddOverlay (messageOverlayContent, sizeFunc);
+ }
+
+ public void RemoveOverlay (Control messageOverlayContent)
+ {
+ textEditorImpl.RemoveOverlay (messageOverlayContent);
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextEditorDisplayBinding.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextEditorDisplayBinding.cs
new file mode 100644
index 0000000000..1fe76c43a0
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextEditorDisplayBinding.cs
@@ -0,0 +1,114 @@
+//
+// TextEditorDisplayBinding.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Core;
+using MonoDevelop.Ide.Gui;
+using System.IO;
+using MonoDevelop.Projects;
+using System.ComponentModel;
+using MonoDevelop.Ide.Editor.Highlighting;
+
+namespace MonoDevelop.Ide.Editor
+{
+ public class TextEditorDisplayBinding : IViewDisplayBinding
+ {
+ static bool IsInitialized = false;
+
+ public static FilePath SyntaxModePath {
+ get {
+ return UserProfile.Current.UserDataRoot.Combine ("HighlightingSchemes");
+ }
+ }
+
+ static TextEditorDisplayBinding ()
+ {
+ InitSourceEditor ();
+ }
+
+ public static void InitSourceEditor ()
+ {
+ if (IsInitialized)
+ return;
+ IsInitialized = true;
+
+ // MonoDevelop.SourceEditor.Extension.TemplateExtensionNodeLoader.Init ();
+ DefaultSourceEditorOptions.Init ();
+ // SyntaxModeService.EnsureLoad ();
+ LoadCustomStylesAndModes ();
+ }
+
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static void LoadCustomStylesAndModes ()
+ {
+ bool success = true;
+ if (!Directory.Exists (SyntaxModePath)) {
+ try {
+ Directory.CreateDirectory (SyntaxModePath);
+ } catch (Exception e) {
+ success = false;
+ LoggingService.LogError ("Can't create syntax mode directory", e);
+ }
+ }
+ if (success)
+ SyntaxModeService.LoadStylesAndModes (SyntaxModePath);
+ }
+
+ public string Name {
+ get {
+ return GettextCatalog.GetString ("Source Code Editor");
+ }
+ }
+
+ public bool CanHandle (FilePath fileName, string mimeType, Project ownerProject)
+ {
+ if (fileName != null)
+ return DesktopService.GetFileIsText (fileName, mimeType);
+
+ if (!string.IsNullOrEmpty (mimeType))
+ return DesktopService.GetMimeTypeIsText (mimeType);
+
+ return false;
+ }
+
+ public IViewContent CreateContent (FilePath fileName, string mimeType, Project ownerProject)
+ {
+ var editor = TextEditorFactory.CreateNewEditor ();
+ editor.MimeType = mimeType;
+ editor.GetViewContent ().Project = ownerProject;
+ editor.GetViewContent ().ContentName = fileName;
+ return editor.GetViewContent ();
+ }
+
+ public bool CanHandleFile (string fileName)
+ {
+ return DesktopService.GetFileIsText (fileName);
+ }
+
+ public bool CanUseAsDefault {
+ get { return true; }
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextEditorFactory.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextEditorFactory.cs
new file mode 100644
index 0000000000..6d54b8060b
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextEditorFactory.cs
@@ -0,0 +1,95 @@
+//
+// DocumentFactory.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Core.Text;
+using Mono.Addins;
+
+namespace MonoDevelop.Ide.Editor
+{
+ public static class TextEditorFactory
+ {
+ static ITextEditorFactory currentFactory;
+
+ static TextEditorFactory ()
+ {
+ AddinManager.AddExtensionNodeHandler ("/MonoDevelop/SourceEditor2/EditorFactory", delegate(object sender, ExtensionNodeEventArgs args) {
+ switch (args.Change) {
+ case ExtensionChange.Add:
+ if (currentFactory == null)
+ currentFactory = (ITextEditorFactory)args.ExtensionObject;
+ break;
+ }
+ });
+ }
+
+ public static ITextDocument CreateNewDocument ()
+ {
+ return currentFactory.CreateNewDocument ();
+ }
+
+ public static ITextDocument CreateNewDocument (ITextSource textSource, string fileName, string mimeType = null)
+ {
+ if (textSource == null)
+ throw new System.ArgumentNullException ("textSource");
+ return currentFactory.CreateNewDocument (textSource, fileName, mimeType);
+ }
+
+ public static ITextDocument LoadDocument (string fileName, string mimeType = null)
+ {
+ if (fileName == null)
+ throw new System.ArgumentNullException ("fileName");
+ return currentFactory.CreateNewDocument (StringTextSource.ReadFrom (fileName), fileName, mimeType);
+ }
+
+ public static IReadonlyTextDocument CreateNewReadonlyDocument (ITextSource textSource, string fileName, string mimeType = null)
+ {
+ if (textSource == null)
+ throw new System.ArgumentNullException ("textSource");
+ return currentFactory.CreateNewDocument (textSource, fileName, mimeType);
+ }
+
+ public static TextEditor CreateNewEditor ()
+ {
+ return new TextEditor (currentFactory.CreateNewEditor ());
+ }
+
+ public static TextEditor CreateNewEditor (IReadonlyTextDocument document)
+ {
+ if (document == null)
+ throw new System.ArgumentNullException ("document");
+ return new TextEditor (currentFactory.CreateNewEditor (document));
+ }
+
+ public static string[] GetSyntaxProperties (string mimeType, string name)
+ {
+ if (mimeType == null)
+ throw new System.ArgumentNullException ("mimeType");
+ if (name == null)
+ throw new System.ArgumentNullException ("name");
+ return currentFactory.GetSyntaxProperties (mimeType, name);
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextEditorViewContent.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextEditorViewContent.cs
new file mode 100644
index 0000000000..2305687ba2
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextEditorViewContent.cs
@@ -0,0 +1,1233 @@
+//
+// TextEditorViewContent.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Ide.Gui;
+using MonoDevelop.Projects;
+using MonoDevelop.Ide.Gui.Content;
+using MonoDevelop.Components.Commands;
+using MonoDevelop.Ide.Commands;
+using System.Collections;
+using System.Collections.Generic;
+using MonoDevelop.Ide.TypeSystem;
+using System.IO;
+using MonoDevelop.Core.Text;
+using System.Text;
+using Gtk;
+using ICSharpCode.NRefactory.TypeSystem;
+using System.Linq;
+using MonoDevelop.Ide.Editor.Extension;
+using ICSharpCode.NRefactory.Refactoring;
+using MonoDevelop.Components;
+using MonoDevelop.Core;
+using System.Threading.Tasks;
+using System.Threading;
+using System.Threading;
+using Microsoft.CodeAnalysis;
+using Gdk;
+using MonoDevelop.Ide.CodeFormatting;
+
+namespace MonoDevelop.Ide.Editor
+{
+ /// <summary>
+ /// The TextEditor object needs to be available through IBaseViewContent.GetContent therefore we need to insert a
+ /// decorator in between.
+ /// </summary>
+ class TextEditorViewContent : IViewContent, ICommandRouter, IQuickTaskProvider
+ {
+ readonly TextEditor textEditor;
+ readonly ITextEditorImpl textEditorImpl;
+
+ DocumentContext currentContext;
+ MonoDevelop.Projects.Policies.PolicyContainer policyContainer;
+
+ public TextEditorViewContent (TextEditor textEditor, ITextEditorImpl textEditorImpl)
+ {
+ if (textEditor == null)
+ throw new ArgumentNullException ("textEditor");
+ if (textEditorImpl == null)
+ throw new ArgumentNullException ("textEditorImpl");
+ this.textEditor = textEditor;
+ this.textEditorImpl = textEditorImpl;
+ this.textEditor.MimeTypeChanged += UpdateTextEditorOptions;
+ DefaultSourceEditorOptions.Instance.Changed += UpdateTextEditorOptions;
+ this.textEditor.DocumentContextChanged += delegate {
+ if (currentContext != null)
+ currentContext.DocumentParsed -= HandleDocumentParsed;
+ currentContext = textEditor.DocumentContext;
+ currentContext.DocumentParsed += HandleDocumentParsed;
+ };
+ }
+
+ void HandleDirtyChanged (object sender, EventArgs e)
+ {
+ InformAutoSave ();
+ }
+
+ void HandleTextChanged (object sender, MonoDevelop.Core.Text.TextChangeEventArgs e)
+ {
+ InformAutoSave ();
+ }
+
+ void UpdateTextEditorOptions (object sender, EventArgs e)
+ {
+ UpdateStyleParent (Project, textEditor.MimeType);
+ }
+
+ uint autoSaveTimer = 0;
+
+ void InformAutoSave ()
+ {
+ RemoveAutoSaveTimer ();
+ autoSaveTimer = GLib.Timeout.Add (500, delegate {
+ AutoSave.InformAutoSaveThread (textEditor.CreateSnapshot (), textEditor.FileName, textEditorImpl.IsDirty);
+ autoSaveTimer = 0;
+ return false;
+ });
+ }
+
+
+ void RemoveAutoSaveTimer ()
+ {
+ if (autoSaveTimer == 0)
+ return;
+ GLib.Source.Remove (autoSaveTimer);
+ autoSaveTimer = 0;
+ }
+
+ void RemovePolicyChangeHandler ()
+ {
+ if (policyContainer != null)
+ policyContainer.PolicyChanged -= HandlePolicyChanged;
+ }
+
+ void UpdateStyleParent (MonoDevelop.Projects.Project styleParent, string mimeType)
+ {
+ RemovePolicyChangeHandler ();
+
+ if (string.IsNullOrEmpty (mimeType))
+ mimeType = "text/plain";
+
+ var mimeTypes = DesktopService.GetMimeTypeInheritanceChain (mimeType);
+
+ if (styleParent != null)
+ policyContainer = styleParent.Policies;
+ else
+ policyContainer = MonoDevelop.Projects.Policies.PolicyService.DefaultPolicies;
+ var currentPolicy = policyContainer.Get<TextStylePolicy> (mimeTypes);
+
+ policyContainer.PolicyChanged += HandlePolicyChanged;
+ textEditor.Options = DefaultSourceEditorOptions.Instance.WithTextStyle (currentPolicy);
+ }
+
+ void HandlePolicyChanged (object sender, MonoDevelop.Projects.Policies.PolicyChangedEventArgs args)
+ {
+ var mimeTypes = DesktopService.GetMimeTypeInheritanceChain (textEditor.MimeType);
+ var currentPolicy = policyContainer.Get<TextStylePolicy> (mimeTypes);
+ textEditor.Options = DefaultSourceEditorOptions.Instance.WithTextStyle (currentPolicy);
+ }
+
+ void HandleDocumentParsed (object sender, EventArgs e)
+ {
+ var ctx = (DocumentContext)sender;
+ src.Cancel ();
+ src = new CancellationTokenSource ();
+ var token = src.Token;
+ Task.Run (() => {
+ try {
+ UpdateErrorUndelines (ctx.ParsedDocument, token);
+ UpdateQuickTasks (ctx.ParsedDocument, token);
+ UpdateFoldings (ctx.ParsedDocument, false, token);
+ } catch (OperationCanceledException) {
+ // ignore
+ }
+ }, token);
+ }
+
+ #region Error handling
+ List<IErrorMarker> errors = new List<IErrorMarker> ();
+ uint resetTimerId;
+
+ void RemoveErrorUndelinesResetTimerId ()
+ {
+ if (resetTimerId > 0) {
+ GLib.Source.Remove (resetTimerId);
+ resetTimerId = 0;
+ }
+ }
+
+ void RemoveErrorUnderlines ()
+ {
+ errors.ForEach (err => textEditor.RemoveMarker (err));
+ errors.Clear ();
+ }
+
+ void UnderLineError (MonoDevelop.Ide.TypeSystem.Error info)
+ {
+ var error = TextMarkerFactory.CreateErrorMarker (textEditor, info);
+ textEditor.AddMarker (error);
+ errors.Add (error);
+ }
+
+ async void UpdateErrorUndelines (ParsedDocument parsedDocument, CancellationToken token)
+ {
+ if (!DefaultSourceEditorOptions.Instance.UnderlineErrors || parsedDocument == null)
+ return;
+ try {
+ var errors = await parsedDocument.GetErrorsAsync(token).ConfigureAwait (false);
+ Application.Invoke (delegate {
+ if (token.IsCancellationRequested)
+ return;
+ RemoveErrorUndelinesResetTimerId ();
+ const uint timeout = 500;
+ resetTimerId = GLib.Timeout.Add (timeout, delegate {
+ if (token.IsCancellationRequested) {
+ resetTimerId = 0;
+ return false;
+ }
+ RemoveErrorUnderlines ();
+ // Else we underline the error
+ if (errors != null) {
+ foreach (var error in errors) {
+ UnderLineError (error);
+ }
+ }
+ resetTimerId = 0;
+ return false;
+ });
+ });
+ } catch (OperationCanceledException) {
+ // ignore
+ }
+ }
+ #endregion
+ CancellationTokenSource src = new CancellationTokenSource ();
+ void UpdateFoldings (ParsedDocument parsedDocument, bool firstTime = false, CancellationToken token = default (CancellationToken))
+ {
+ if (parsedDocument == null || !textEditor.Options.ShowFoldMargin)
+ return;
+ // don't update parsed documents that contain errors - the foldings from there may be invalid.
+ if (parsedDocument.HasErrors)
+ return;
+ var caretLocation = textEditor.CaretLocation;
+ try {
+ var foldSegments = new List<IFoldSegment> ();
+
+ foreach (FoldingRegion region in parsedDocument.GetFoldingsAsync(token).Result) {
+ if (token.IsCancellationRequested)
+ return;
+ var type = FoldingType.Unknown;
+ bool setFolded = false;
+ bool folded = false;
+ //decide whether the regions should be folded by default
+ switch (region.Type) {
+ case FoldType.Member:
+ type = FoldingType.TypeMember;
+ break;
+ case FoldType.Type:
+ type = FoldingType.TypeDefinition;
+ break;
+ case FoldType.UserRegion:
+ type = FoldingType.Region;
+ setFolded = DefaultSourceEditorOptions.Instance.DefaultRegionsFolding;
+ folded = true;
+ break;
+ case FoldType.Comment:
+ type = FoldingType.Comment;
+ setFolded = DefaultSourceEditorOptions.Instance.DefaultCommentFolding;
+ folded = true;
+ break;
+ case FoldType.CommentInsideMember:
+ type = FoldingType.Comment;
+ setFolded = DefaultSourceEditorOptions.Instance.DefaultCommentFolding;
+ folded = false;
+ break;
+ case FoldType.Undefined:
+ setFolded = true;
+ folded = region.IsFoldedByDefault;
+ break;
+ }
+ var start = textEditor.LocationToOffset (region.Region.Begin);
+ var end = textEditor.LocationToOffset (region.Region.End);
+ var marker = textEditor.CreateFoldSegment (start, end - start);
+ foldSegments.Add (marker);
+ marker.CollapsedText = region.Name;
+ marker.FoldingType = type;
+ //and, if necessary, set its fold state
+ if (marker != null && setFolded && firstTime) {
+ // only fold on document open, later added folds are NOT folded by default.
+ marker.IsCollapsed = folded;
+ continue;
+ }
+ if (marker != null && region.Region.Contains (caretLocation.Line, caretLocation.Column))
+ marker.IsCollapsed = false;
+ }
+ if (firstTime) {
+ textEditor.SetFoldings (foldSegments);
+ } else {
+ Application.Invoke (delegate {
+ if (!token.IsCancellationRequested)
+ textEditor.SetFoldings (foldSegments);
+ });
+ }
+ } catch (Exception ex) {
+ LoggingService.LogError ("Unhandled exception in ParseInformationUpdaterWorkerThread", ex);
+ }
+ }
+
+ void RunFirstTimeFoldUpdate (string text)
+ {
+ if (string.IsNullOrEmpty (text))
+ return;
+ ParsedDocument parsedDocument = null;
+
+ var foldingParser = TypeSystemService.GetFoldingParser (textEditor.MimeType);
+ if (foldingParser != null) {
+ parsedDocument = foldingParser.Parse (textEditor.FileName, text);
+ } else {
+ var normalParser = TypeSystemService.GetParser (textEditor.MimeType);
+ if (normalParser != null) {
+ parsedDocument = normalParser.Parse (new MonoDevelop.Ide.TypeSystem.ParseOptions { FileName = textEditor.FileName, Content = new StringTextSource (text) }).Result;
+ }
+ }
+ if (parsedDocument != null) {
+ UpdateFoldings (parsedDocument, true);
+ }
+ }
+
+
+ #region IViewFContent implementation
+
+ event EventHandler IViewContent.ContentNameChanged {
+ add {
+ textEditorImpl.ContentNameChanged += value;
+ }
+ remove {
+ textEditorImpl.ContentNameChanged -= value;
+ }
+ }
+
+ event EventHandler IViewContent.ContentChanged {
+ add {
+ textEditorImpl.ContentChanged += value;
+ }
+ remove {
+ textEditorImpl.ContentChanged -= value;
+ }
+ }
+
+ event EventHandler IViewContent.DirtyChanged {
+ add {
+ textEditorImpl.DirtyChanged += value;
+ }
+ remove {
+ textEditorImpl.DirtyChanged -= value;
+ }
+ }
+
+ event EventHandler IViewContent.BeforeSave {
+ add {
+ textEditorImpl.BeforeSave += value;
+ }
+ remove {
+ textEditorImpl.BeforeSave -= value;
+ }
+ }
+
+ void IViewContent.Load (FileOpenInformation fileOpenInformation)
+ {
+ this.textEditorImpl.DirtyChanged -= HandleDirtyChanged;
+ this.textEditor.TextChanged -= HandleTextChanged;
+ textEditorImpl.Load (fileOpenInformation);
+ RunFirstTimeFoldUpdate (textEditor.Text);
+ this.textEditor.TextChanged += HandleTextChanged;
+ this.textEditorImpl.DirtyChanged += HandleDirtyChanged;
+ }
+
+ void IViewContent.Load (string fileName)
+ {
+ this.textEditorImpl.DirtyChanged -= HandleDirtyChanged;
+ this.textEditor.TextChanged -= HandleTextChanged;
+ textEditorImpl.Load (new FileOpenInformation (fileName));
+ RunFirstTimeFoldUpdate (textEditor.Text);
+ this.textEditor.TextChanged += HandleTextChanged;
+ this.textEditorImpl.DirtyChanged += HandleDirtyChanged;
+ }
+
+ void IViewContent.LoadNew (System.IO.Stream content, string mimeType)
+ {
+ textEditor.MimeType = mimeType;
+ string text = null;
+ if (content != null) {
+ Encoding encoding;
+ bool hadBom;
+ text = TextFileUtility.GetText (content, out encoding, out hadBom);
+ textEditor.Text = text;
+ textEditor.Encoding = encoding;
+ textEditor.UseBOM = hadBom;
+ }
+ RunFirstTimeFoldUpdate (text);
+ textEditorImpl.InformLoadComplete ();
+ }
+
+ void IViewContent.Save (FileSaveInformation fileSaveInformation)
+ {
+ if (!string.IsNullOrEmpty (fileSaveInformation.FileName))
+ AutoSave.RemoveAutoSaveFile (fileSaveInformation.FileName);
+ textEditorImpl.Save (fileSaveInformation);
+ }
+
+ void IViewContent.Save (string fileName)
+ {
+ if (!string.IsNullOrEmpty (fileName))
+ AutoSave.RemoveAutoSaveFile (fileName);
+ textEditorImpl.Save (new FileSaveInformation (fileName));
+ }
+
+ void IViewContent.Save ()
+ {
+ if (!string.IsNullOrEmpty (textEditorImpl.ContentName))
+ AutoSave.RemoveAutoSaveFile (textEditorImpl.ContentName);
+ textEditorImpl.Save ();
+ }
+
+ void IViewContent.DiscardChanges ()
+ {
+ if (!string.IsNullOrEmpty (textEditorImpl.ContentName))
+ AutoSave.RemoveAutoSaveFile (textEditorImpl.ContentName);
+ textEditorImpl.DiscardChanges ();
+ }
+
+ public MonoDevelop.Projects.Project Project {
+ get {
+ return textEditorImpl.Project;
+ }
+ set {
+ textEditorImpl.Project = value;
+ UpdateTextEditorOptions (null, null);
+ }
+ }
+
+ string IViewContent.PathRelativeToProject {
+ get {
+ return textEditorImpl.PathRelativeToProject;
+ }
+ }
+
+ string IViewContent.ContentName {
+ get {
+ return textEditorImpl.ContentName;
+ }
+ set {
+ textEditorImpl.ContentName = value;
+ }
+ }
+
+ string IViewContent.UntitledName {
+ get {
+ return textEditorImpl.UntitledName;
+ }
+ set {
+ textEditorImpl.UntitledName = value;
+ }
+ }
+
+ string IViewContent.StockIconId {
+ get {
+ return textEditorImpl.StockIconId;
+ }
+ }
+
+ bool IViewContent.IsUntitled {
+ get {
+ return textEditorImpl.IsUntitled;
+ }
+ }
+
+ bool IViewContent.IsViewOnly {
+ get {
+ return textEditorImpl.IsViewOnly;
+ }
+ }
+
+ bool IViewContent.IsFile {
+ get {
+ return textEditorImpl.IsFile;
+ }
+ }
+
+ bool IViewContent.IsDirty {
+ get {
+ return textEditorImpl.IsDirty;
+ }
+ set {
+ textEditorImpl.IsDirty = value;
+ }
+ }
+
+ bool IViewContent.IsReadOnly {
+ get {
+ return textEditorImpl.IsReadOnly;
+ }
+ }
+
+ #endregion
+
+ #region IBaseViewContent implementation
+ object IBaseViewContent.GetContent (Type type)
+ {
+ if (type.IsAssignableFrom (typeof(TextEditor)))
+ return textEditor;
+ var ext = textEditorImpl.EditorExtension;
+ while (ext != null) {
+ if (type.IsInstanceOfType (ext))
+ return ext;
+ ext = ext.Next;
+ }
+ return textEditorImpl.GetContent (type);
+ }
+
+ public virtual IEnumerable<T> GetContents<T> () where T : class
+ {
+ if (typeof(T) == typeof(TextEditor)) {
+ yield return (T)(object)textEditor;
+ yield break;
+ }
+ var result = this as T;
+ if (result != null) {
+ yield return result;
+ }
+ var ext = textEditorImpl.EditorExtension;
+ while (ext != null) {
+ result = ext as T;
+ if (result != null) {
+ yield return result;
+ }
+ ext = ext.Next;
+ }
+ foreach (var cnt in textEditorImpl.GetContents<T> ()) {
+ yield return cnt;
+ }
+ }
+
+ bool IBaseViewContent.CanReuseView (string fileName)
+ {
+ return textEditorImpl.CanReuseView (fileName);
+ }
+
+ void IBaseViewContent.RedrawContent ()
+ {
+ textEditorImpl.RedrawContent ();
+ }
+
+ IWorkbenchWindow IBaseViewContent.WorkbenchWindow {
+ get {
+ return textEditorImpl.WorkbenchWindow;
+ }
+ set {
+ textEditorImpl.WorkbenchWindow = value;
+ }
+ }
+
+ Gtk.Widget IBaseViewContent.Control {
+ get {
+ return textEditor;
+ }
+ }
+
+ string IBaseViewContent.TabPageLabel {
+ get {
+ return textEditorImpl.TabPageLabel;
+ }
+ }
+
+ #endregion
+
+ #region IDisposable implementation
+
+ void IDisposable.Dispose ()
+ {
+ DefaultSourceEditorOptions.Instance.Changed -= UpdateTextEditorOptions;
+ RemovePolicyChangeHandler ();
+ RemoveAutoSaveTimer ();
+ RemoveErrorUndelinesResetTimerId ();
+ textEditorImpl.Dispose ();
+ }
+
+ #endregion
+
+ #region ICommandRouter implementation
+
+ object ICommandRouter.GetNextCommandTarget ()
+ {
+ return textEditorImpl;
+ }
+
+ #endregion
+
+ #region Commands
+ void ToggleCodeCommentWithBlockComments ()
+ {
+ var blockStarts = TextEditorFactory.GetSyntaxProperties (textEditor.MimeType, "BlockCommentStart");
+ var blockEnds = TextEditorFactory.GetSyntaxProperties (textEditor.MimeType, "BlockCommentEnd");
+ if (blockStarts == null || blockEnds == null || blockStarts.Length == 0 || blockEnds.Length == 0)
+ return;
+
+ string blockStart = blockStarts[0];
+ string blockEnd = blockEnds[0];
+
+ using (var undo = textEditor.OpenUndoGroup ()) {
+ IDocumentLine startLine;
+ IDocumentLine endLine;
+
+ if (textEditor.IsSomethingSelected) {
+ startLine = textEditor.GetLineByOffset (textEditor.SelectionRange.Offset);
+ endLine = textEditor.GetLineByOffset (textEditor.SelectionRange.EndOffset);
+ } else {
+ startLine = endLine = textEditor.GetLine (textEditor.CaretLine);
+ }
+ string startLineText = textEditor.GetTextAt (startLine.Offset, startLine.Length);
+ string endLineText = textEditor.GetTextAt (endLine.Offset, endLine.Length);
+ if (startLineText.StartsWith (blockStart, StringComparison.Ordinal) && endLineText.EndsWith (blockEnd, StringComparison.Ordinal)) {
+ textEditor.RemoveText (endLine.Offset + endLine.Length - blockEnd.Length, blockEnd.Length);
+ textEditor.RemoveText (startLine.Offset, blockStart.Length);
+ if (textEditor.IsSomethingSelected) {
+ textEditor.SelectionAnchorOffset -= blockEnd.Length;
+ }
+ } else {
+ textEditor.InsertText (endLine.Offset + endLine.Length, blockEnd);
+ textEditor.InsertText (startLine.Offset, blockStart);
+ if (textEditor.IsSomethingSelected) {
+ textEditor.SelectionAnchorOffset += blockEnd.Length;
+ }
+ }
+ }
+ }
+
+ bool TryGetLineCommentTag (out string commentTag)
+ {
+ var lineComments = TextEditorFactory.GetSyntaxProperties (textEditor.MimeType, "LineComment");
+ if (lineComments == null || lineComments.Length == 0) {
+ commentTag = null;
+ return false;
+ }
+ commentTag = lineComments [0];
+ return true;
+ }
+
+ [CommandUpdateHandler (EditCommands.AddCodeComment)]
+ [CommandUpdateHandler (EditCommands.RemoveCodeComment)]
+ [CommandUpdateHandler (EditCommands.ToggleCodeComment)]
+ void OnUpdateToggleComment (CommandInfo info)
+ {
+ var lineComments = TextEditorFactory.GetSyntaxProperties (textEditor.MimeType, "LineComment");
+ if (lineComments != null && lineComments.Length > 0) {
+ info.Visible = true;
+ return;
+ }
+ var blockStarts = TextEditorFactory.GetSyntaxProperties (textEditor.MimeType, "BlockCommentStart");
+ var blockEnds = TextEditorFactory.GetSyntaxProperties (textEditor.MimeType, "BlockCommentEnd");
+ info.Visible = blockStarts != null && blockStarts.Length > 0 && blockEnds != null && blockEnds.Length > 0;
+ }
+
+ [CommandHandler (EditCommands.ToggleCodeComment)]
+ internal void ToggleCodeComment ()
+ {
+ string commentTag;
+ if (!TryGetLineCommentTag (out commentTag))
+ return;
+ bool comment = false;
+ foreach (var line in GetSelectedLines (textEditor)) {
+ int startOffset;
+ int offset = line.Offset;
+ if (!StartsWith (textEditor, offset, line.Length, commentTag, out startOffset)) {
+ if (startOffset - offset == line.Length) // case: line consists only of white spaces
+ continue;
+ comment = true;
+ break;
+ }
+ }
+
+ if (comment) {
+ AddCodeComment ();
+ } else {
+ RemoveCodeComment ();
+ }
+ }
+
+ static bool StartsWith (ITextSource text, int offset, int length, string commentTag, out int startOffset)
+ {
+ int max = Math.Min (offset + length, text.Length);
+ int i = offset;
+ for (; i < max; i++) {
+ char ch = text.GetCharAt (i);
+ if (ch != ' ' && ch != '\t')
+ break;
+ }
+ startOffset = i;
+ for (int j = 0; j < commentTag.Length; j++) {
+ if (text.GetCharAt (i) != commentTag [j])
+ return false;
+ i++;
+ }
+
+ return true;
+ }
+
+ static IEnumerable<IDocumentLine> GetSelectedLines (TextEditor textEditor)
+ {
+ var selection = textEditor.SelectionRange;
+ var line = textEditor.GetLineByOffset (selection.EndOffset);
+ do {
+ yield return line;
+ line = line.PreviousLine;
+ } while (line != null && line.EndOffset > selection.Offset);
+ }
+
+ [CommandHandler (EditCommands.AddCodeComment)]
+ internal void AddCodeComment ()
+ {
+ string commentTag;
+ if (!TryGetLineCommentTag (out commentTag))
+ return;
+
+ using (var undo = textEditor.OpenUndoGroup ()) {
+ var wasSelected = textEditor.IsSomethingSelected;
+ var lead = textEditor.SelectionLeadOffset;
+ var anchor = textEditor.SelectionAnchorOffset;
+ var lineAndIndents = new List<Tuple<IDocumentLine, string>>();
+ string indent = null;
+ var oldVersion = textEditor.Version;
+ foreach (var line in GetSelectedLines (textEditor)) {
+ var curIndent = line.GetIndentation (textEditor);
+ if (line.Length == curIndent.Length) {
+ lineAndIndents.Add (Tuple.Create ((IDocumentLine)null, ""));
+ continue;
+ }
+ if (indent == null || curIndent.Length < indent.Length)
+ indent = curIndent;
+ lineAndIndents.Add (Tuple.Create (line, curIndent));
+ }
+
+ foreach (var line in lineAndIndents) {
+ if (line.Item1 == null)
+ continue;
+ textEditor.InsertText (line.Item1.Offset + indent.Length, commentTag);
+ }
+ if (wasSelected) {
+ textEditor.SelectionAnchorOffset = oldVersion.MoveOffsetTo (textEditor.Version, anchor);
+ textEditor.SelectionLeadOffset = oldVersion.MoveOffsetTo (textEditor.Version, lead);
+ }
+ }
+ }
+
+ [CommandHandler (EditCommands.RemoveCodeComment)]
+ internal void RemoveCodeComment ()
+ {
+ string commentTag;
+ if (!TryGetLineCommentTag (out commentTag))
+ return;
+
+ using (var undo = textEditor.OpenUndoGroup ()) {
+ var wasSelected = textEditor.IsSomethingSelected;
+ var lead = textEditor.SelectionLeadOffset;
+ var anchor = textEditor.SelectionAnchorOffset;
+ int lines = 0;
+
+ IDocumentLine first = null;
+ IDocumentLine last = null;
+ var oldVersion = textEditor.Version;
+ foreach (var line in GetSelectedLines (textEditor)) {
+ int startOffset;
+ if (StartsWith (textEditor, line.Offset, line.Length, commentTag, out startOffset)) {
+ textEditor.RemoveText (startOffset, commentTag.Length);
+ lines++;
+ }
+
+ first = line;
+ if (last == null)
+ last = line;
+ }
+
+ if (wasSelected) {
+// if (IdeApp.Workbench != null)
+// CodeFormatterService.Format (textEditor, IdeApp.Workbench.ActiveDocument, TextSegment.FromBounds (first.Offset, last.EndOffset));
+
+ textEditor.SelectionAnchorOffset = oldVersion.MoveOffsetTo (textEditor.Version, anchor);
+ textEditor.SelectionLeadOffset = oldVersion.MoveOffsetTo (textEditor.Version, lead);
+ }
+ }
+ }
+
+ [CommandHandler (EditCommands.InsertGuid)]
+ void InsertGuid ()
+ {
+ textEditor.InsertAtCaret (Guid.NewGuid ().ToString ());
+ }
+
+ [CommandUpdateHandler (MessageBubbleCommands.Toggle)]
+ public void OnUpdateToggleErrorTextMarker (CommandInfo info)
+ {
+ var line = textEditor.GetLine (textEditor.CaretLine);
+ if (line == null) {
+ info.Visible = false;
+ return;
+ }
+
+ var marker = (IMessageBubbleLineMarker)textEditor.GetLineMarkers (line).FirstOrDefault (m => m is IMessageBubbleLineMarker);
+ info.Visible = marker != null;
+ }
+
+ [CommandHandler (MessageBubbleCommands.Toggle)]
+ public void OnToggleErrorTextMarker ()
+ {
+ var line = textEditor.GetLine (textEditor.CaretLine);
+ if (line == null)
+ return;
+ var marker = (IMessageBubbleLineMarker)textEditor.GetLineMarkers (line).FirstOrDefault (m => m is IMessageBubbleLineMarker);
+ if (marker != null) {
+ marker.IsVisible = !marker.IsVisible;
+ }
+ }
+ #endregion
+
+ #region IQuickTaskProvider implementation
+ List<QuickTask> tasks = new List<QuickTask> ();
+
+ public event EventHandler TasksUpdated;
+
+ protected virtual void OnTasksUpdated (EventArgs e)
+ {
+ EventHandler handler = this.TasksUpdated;
+ if (handler != null)
+ handler (this, e);
+ }
+
+ public IEnumerable<QuickTask> QuickTasks {
+ get {
+ return tasks;
+ }
+ }
+
+ async void UpdateQuickTasks (ParsedDocument doc, CancellationToken token)
+ {
+ var newTasks = new List<QuickTask> ();
+ if (doc != null) {
+ foreach (var cmt in await doc.GetTagCommentsAsync(token).ConfigureAwait (false)) {
+ var newTask = new QuickTask (cmt.Text, textEditor.LocationToOffset (cmt.Region.Begin.Line, cmt.Region.Begin.Column), DiagnosticSeverity.Info);
+ newTasks.Add (newTask);
+ }
+
+ foreach (var error in await doc.GetErrorsAsync(token).ConfigureAwait (false)) {
+ var newTask = new QuickTask (error.Message, textEditor.LocationToOffset (error.Region.Begin.Line, error.Region.Begin.Column), error.ErrorType == MonoDevelop.Ide.TypeSystem.ErrorType.Error ? DiagnosticSeverity.Error : DiagnosticSeverity.Warning);
+ newTasks.Add (newTask);
+ }
+ }
+ Application.Invoke (delegate {
+ if (token.IsCancellationRequested)
+ return;
+ tasks = newTasks;
+ OnTasksUpdated (EventArgs.Empty);
+ });
+ }
+ #endregion
+
+ #region Key bindings
+
+ [CommandHandler (TextEditorCommands.LineEnd)]
+ void OnLineEnd ()
+ {
+ EditActions.MoveCaretToLineEnd (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.LineStart)]
+ void OnLineStart ()
+ {
+ EditActions.MoveCaretToLineStart (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.DeleteLeftChar)]
+ void OnDeleteLeftChar ()
+ {
+ EditActions.Backspace (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.DeleteRightChar)]
+ void OnDeleteRightChar ()
+ {
+ EditActions.Delete (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.CharLeft)]
+ void OnCharLeft ()
+ {
+ EditActions.MoveCaretLeft (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.CharRight)]
+ void OnCharRight ()
+ {
+ EditActions.MoveCaretRight (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.LineUp)]
+ void OnLineUp ()
+ {
+ EditActions.MoveCaretUp (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.LineDown)]
+ void OnLineDown ()
+ {
+ EditActions.MoveCaretDown (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.DocumentStart)]
+ void OnDocumentStart ()
+ {
+ EditActions.MoveCaretToDocumentStart (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.DocumentEnd)]
+ void OnDocumentEnd ()
+ {
+ EditActions.MoveCaretToDocumentEnd (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.PageUp)]
+ void OnPageUp ()
+ {
+ EditActions.PageUp (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.PageDown)]
+ void OnPageDown ()
+ {
+ EditActions.PageDown (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.DeleteLine)]
+ void OnDeleteLine ()
+ {
+ EditActions.DeleteCurrentLine (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.DeleteToLineEnd)]
+ void OnDeleteToLineEnd ()
+ {
+ EditActions.DeleteCurrentLineToEnd (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.ScrollLineUp)]
+ void OnScrollLineUp ()
+ {
+ EditActions.ScrollLineUp (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.ScrollLineDown)]
+ void OnScrollLineDown ()
+ {
+ EditActions.ScrollLineDown (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.ScrollPageUp)]
+ void OnScrollPageUp ()
+ {
+ EditActions.ScrollPageUp (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.ScrollPageDown)]
+ void OnScrollPageDown ()
+ {
+ EditActions.ScrollPageDown (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.GotoMatchingBrace)]
+ void OnGotoMatchingBrace ()
+ {
+ EditActions.GotoMatchingBrace (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.SelectionMoveLeft)]
+ void OnSelectionMoveLeft ()
+ {
+ EditActions.SelectionMoveLeft (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.SelectionMoveRight)]
+ void OnSelectionMoveRight ()
+ {
+ EditActions.SelectionMoveRight (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.MovePrevWord)]
+ void OnMovePrevWord ()
+ {
+ EditActions.MovePrevWord (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.MoveNextWord)]
+ void OnMoveNextWord ()
+ {
+ EditActions.MoveNextWord (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.SelectionMovePrevWord)]
+ void OnSelectionMovePrevWord ()
+ {
+ EditActions.SelectionMovePrevWord (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.SelectionMoveNextWord)]
+ void OnSelectionMoveNextWord ()
+ {
+ EditActions.SelectionMoveNextWord (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.MovePrevSubword)]
+ void OnMovePrevSubword ()
+ {
+ EditActions.MovePrevSubWord (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.MoveNextSubword)]
+ void OnMoveNextSubword ()
+ {
+ EditActions.MoveNextSubWord (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.SelectionMovePrevSubword)]
+ void OnSelectionMovePrevSubword ()
+ {
+ EditActions.SelectionMovePrevSubWord (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.SelectionMoveNextSubword)]
+ void OnSelectionMoveNextSubword ()
+ {
+ EditActions.SelectionMoveNextSubWord (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.SelectionMoveUp)]
+ void OnSelectionMoveUp ()
+ {
+ EditActions.SelectionMoveUp (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.SelectionMoveDown)]
+ void OnSelectionMoveDown ()
+ {
+ EditActions.SelectionMoveDown (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.SelectionMoveHome)]
+ void OnSelectionMoveHome ()
+ {
+ EditActions.SelectionMoveLineStart (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.SelectionMoveEnd)]
+ void OnSelectionMoveEnd ()
+ {
+ EditActions.SelectionMoveLineEnd (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.SelectionMoveToDocumentStart)]
+ void OnSelectionMoveToDocumentStart ()
+ {
+ EditActions.SelectionMoveToDocumentStart (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.ExpandSelectionToLine)]
+ void OnExpandSelectionToLine ()
+ {
+ EditActions.ExpandSelectionToLine (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.SelectionMoveToDocumentEnd)]
+ void OnSelectionMoveToDocumentEnd ()
+ {
+ EditActions.SelectionMoveToDocumentEnd (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.SwitchCaretMode)]
+ void OnSwitchCaretMode ()
+ {
+ EditActions.SwitchCaretMode (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.InsertTab)]
+ void OnInsertTab ()
+ {
+ EditActions.InsertTab (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.RemoveTab)]
+ void OnRemoveTab ()
+ {
+ EditActions.RemoveTab (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.InsertNewLine)]
+ void OnInsertNewLine ()
+ {
+ EditActions.InsertNewLine (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.InsertNewLineAtEnd)]
+ void OnInsertNewLineAtEnd ()
+ {
+ EditActions.InsertNewLineAtEnd (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.InsertNewLinePreserveCaretPosition)]
+ void OnInsertNewLinePreserveCaretPosition ()
+ {
+ EditActions.InsertNewLinePreserveCaretPosition (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.CompleteStatement)]
+ void OnCompleteStatement ()
+ {
+ var doc = IdeApp.Workbench.ActiveDocument;
+ var generator = CodeGenerator.CreateGenerator (doc);
+ if (generator != null) {
+ generator.CompleteStatement (doc);
+ }
+ }
+
+ [CommandHandler (TextEditorCommands.DeletePrevWord)]
+ void OnDeletePrevWord ()
+ {
+ EditActions.DeletePreviousWord (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.DeleteNextWord)]
+ void OnDeleteNextWord ()
+ {
+ EditActions.DeleteNextWord (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.DeletePrevSubword)]
+ void OnDeletePrevSubword ()
+ {
+ EditActions.DeletePreviousSubword (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.DeleteNextSubword)]
+ void OnDeleteNextSubword ()
+ {
+ EditActions.DeleteNextSubword (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.SelectionPageDownAction)]
+ void OnSelectionPageDownAction ()
+ {
+ EditActions.SelectionPageDown (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.SelectionPageUpAction)]
+ void OnSelectionPageUpAction ()
+ {
+ EditActions.SelectionPageUp (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.PulseCaret)]
+ void OnPulseCaretCommand ()
+ {
+ EditActions.StartCaretPulseAnimation (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.TransposeCharacters)]
+ void TransposeCharacters ()
+ {
+ EditActions.TransposeCharacters (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.DuplicateLine)]
+ void DuplicateLine ()
+ {
+ EditActions.DuplicateCurrentLine (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.RecenterEditor)]
+ void RecenterEditor ()
+ {
+ EditActions.RecenterEditor (textEditor);
+ }
+
+ [CommandHandler (EditCommands.JoinWithNextLine)]
+ void JoinLines ()
+ {
+ EditActions.JoinLines (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.MoveBlockUp)]
+ void OnMoveBlockUp ()
+ {
+ EditActions.MoveBlockUp (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.MoveBlockDown)]
+ void OnMoveBlockDown ()
+ {
+ EditActions.MoveBlockDown (textEditor);
+ }
+
+ [CommandHandler (TextEditorCommands.ToggleBlockSelectionMode)]
+ void OnToggleBlockSelectionMode ()
+ {
+ EditActions.ToggleBlockSelectionMode (textEditor);
+ }
+
+ [CommandHandler (EditCommands.IndentSelection)]
+ void IndentSelection ()
+ {
+ EditActions.IndentSelection (textEditor);
+ }
+
+ [CommandHandler (EditCommands.UnIndentSelection)]
+ void UnIndentSelection ()
+ {
+ EditActions.UnIndentSelection (textEditor);
+ }
+
+
+ [CommandHandler (EditCommands.SortSelectedLines)]
+ void SortSelectedLines ()
+ {
+ EditActions.SortSelectedLines (textEditor);
+ }
+
+ [CommandUpdateHandler (EditCommands.SortSelectedLines)]
+ void UpdateSortSelectedLines (CommandInfo ci)
+ {
+ var region = textEditor.SelectionRegion;
+ ci.Enabled = region.BeginLine != region.EndLine;
+ }
+ #endregion
+
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextLink.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextLink.cs
new file mode 100644
index 0000000000..f5f25604bb
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextLink.cs
@@ -0,0 +1,136 @@
+//
+// TextLink.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Ide.CodeTemplates;
+using MonoDevelop.Core.Text;
+using System.Collections.Generic;
+
+namespace MonoDevelop.Ide.Editor
+{
+ public sealed class TextLink : IListDataProvider<string>
+ {
+ public ISegment PrimaryLink {
+ get {
+ if (links.Count == 0)
+ return TextSegment.Invalid;
+ return links [0];
+ }
+ }
+
+ List<ISegment> links = new List<ISegment> ();
+
+ public List<ISegment> Links {
+ get {
+ return links;
+ }
+ set {
+ links = value;
+ }
+ }
+
+ public bool IsIdentifier {
+ get;
+ set;
+ }
+
+ public bool IsEditable {
+ get;
+ set;
+ }
+
+ public string Name {
+ get;
+ set;
+ }
+
+ public string CurrentText {
+ get;
+ set;
+ }
+
+ public string Tooltip {
+ get;
+ set;
+ }
+
+ public IListDataProvider<string> Values {
+ get;
+ set;
+ }
+
+ public Func<Func<string, string>, IListDataProvider<string>> GetStringFunc {
+ get;
+ set;
+ }
+
+ public TextLink (string name)
+ {
+ IsEditable = true;
+ this.Name = name;
+ this.IsIdentifier = false;
+ }
+
+ public override string ToString ()
+ {
+ return string.Format ("[TextLink: Name={0}, Links={1}, IsEditable={2}, Tooltip={3}, CurrentText={4}, Values=({5})]",
+ Name,
+ Links.Count,
+ IsEditable,
+ Tooltip,
+ CurrentText,
+ Values.Count);
+ }
+
+ public void AddLink (ISegment segment)
+ {
+ links.Add (segment);
+ }
+ #region IListDataProvider implementation
+ public string GetText (int n)
+ {
+ return Values != null ? Values.GetText (n) : "";
+ }
+
+ public string this [int n] {
+ get {
+ return Values != null ? Values [n] : "";
+ }
+ }
+
+ public Xwt.Drawing.Image GetIcon (int n)
+ {
+ return Values != null ? Values.GetIcon (n) : null;
+ }
+
+ public int Count {
+ get {
+ return Values != null ? Values.Count : 0;
+ }
+ }
+ #endregion
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextLinkModeEventArgs.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextLinkModeEventArgs.cs
new file mode 100644
index 0000000000..f32d8596c9
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextLinkModeEventArgs.cs
@@ -0,0 +1,43 @@
+//
+// TextLinkModeEventArgs.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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;
+
+namespace MonoDevelop.Ide.Editor
+{
+ [Serializable]
+ public sealed class TextLinkModeEventArgs : EventArgs
+ {
+ public bool Success {
+ get;
+ private set;
+ }
+
+ public TextLinkModeEventArgs (bool success)
+ {
+ this.Success = success;
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextLinkModeOptions.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextLinkModeOptions.cs
new file mode 100644
index 0000000000..ef20516cf9
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextLinkModeOptions.cs
@@ -0,0 +1,66 @@
+//
+// ITextEditorImpl.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 System.Collections.Generic;
+
+namespace MonoDevelop.Ide.Editor
+{
+ /// <summary>
+ /// This class contains information the editor needs to initiate the text link mode.
+ /// </summary>
+ public sealed class TextLinkModeOptions
+ {
+ /// <summary>
+ /// The text links. Note that this property will change to IReadOnlyList in future versions.
+ /// </summary>
+ public IList<TextLink> Links {
+ get;
+ private set;
+ }
+
+ /// <summary>
+ /// That's the action that is started after the text link mode ended.
+ /// This may be null (in that case no action is started).
+ /// </summary>
+ public Action<TextLinkModeEventArgs> ModeExitedAction {
+ get;
+ private set;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MonoDevelop.Ide.Editor.TextLinkModeOptions"/> class.
+ /// </summary>
+ /// <param name="links">The text links. </param>
+ /// <param name="modeExitedAction">That's the action that is started after the text link mode ended.</param>
+ public TextLinkModeOptions (IList<TextLink> links, Action<TextLinkModeEventArgs> modeExitedAction = null)
+ {
+ if (links == null)
+ throw new ArgumentNullException ("links");
+ Links = links;
+ ModeExitedAction = modeExitedAction;
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextMarkerFactory.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextMarkerFactory.cs
new file mode 100644
index 0000000000..a185dd93ba
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextMarkerFactory.cs
@@ -0,0 +1,121 @@
+//
+// TextMarkerFactory.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Core.Text;
+using MonoDevelop.Ide.Editor.Extension;
+using MonoDevelop.Ide.TypeSystem;
+
+namespace MonoDevelop.Ide.Editor
+{
+ /// <summary>
+ /// The text marker factory creates line and segment markers for the text editor.
+ /// Note that this is the only valid way of creating markers for the editor.
+ /// </summary>
+ public static class TextMarkerFactory
+ {
+ #region Line marker
+ public static IUrlTextLineMarker CreateUrlTextMarker (TextEditor editor, IDocumentLine line, string value, UrlType url, string syntax, int startCol, int endCol)
+ {
+ return editor.TextMarkerFactory.CreateUrlTextMarker (editor, line, value, url, syntax, startCol, endCol);
+ }
+
+ public static ICurrentDebugLineTextMarker CreateCurrentDebugLineTextMarker (TextEditor editor)
+ {
+ return editor.TextMarkerFactory.CreateCurrentDebugLineTextMarker (editor);
+ }
+
+ public static ITextLineMarker CreateAsmLineMarker (TextEditor editor)
+ {
+ return editor.TextMarkerFactory.CreateAsmLineMarker (editor);
+ }
+
+ public static IUnitTestMarker CreateUnitTestMarker (TextEditor editor, UnitTestMarkerHost host, UnitTestLocation unitTestLocation)
+ {
+ return editor.TextMarkerFactory.CreateUnitTestMarker (editor, host, unitTestLocation);
+ }
+
+ public static IMessageBubbleLineMarker CreateMessageBubbleLineMarker (TextEditor editor)
+ {
+ return editor.TextMarkerFactory.CreateMessageBubbleLineMarker (editor);
+ }
+
+
+ #endregion
+
+ #region Segment marker
+ public static ITextSegmentMarker CreateUsageMarker (TextEditor editor, Usage usage)
+ {
+ return editor.TextMarkerFactory.CreateUsageMarker (editor, usage);
+ }
+
+ public static ITextSegmentMarker CreateLinkMarker (TextEditor editor, int offset, int length, Action<LinkRequest> activateLink)
+ {
+ return editor.TextMarkerFactory.CreateLinkMarker (editor, offset, length, activateLink);
+ }
+
+ public static ITextSegmentMarker CreateLinkMarker (TextEditor editor, ISegment segment, Action<LinkRequest> activateLink)
+ {
+ if (segment == null)
+ throw new ArgumentNullException ("segment");
+ return editor.TextMarkerFactory.CreateLinkMarker (editor, segment.Offset, segment.Length, activateLink);
+ }
+
+ public static IGenericTextSegmentMarker CreateGenericTextSegmentMarker (TextEditor editor, TextSegmentMarkerEffect effect, int offset, int length)
+ {
+ return editor.TextMarkerFactory.CreateGenericTextSegmentMarker (editor, effect, offset, length);
+ }
+
+ public static IGenericTextSegmentMarker CreateGenericTextSegmentMarker (TextEditor editor, TextSegmentMarkerEffect effect, ISegment segment)
+ {
+ if (segment == null)
+ throw new ArgumentNullException ("segment");
+ return editor.TextMarkerFactory.CreateGenericTextSegmentMarker (editor, effect, segment.Offset, segment.Length);
+ }
+
+ public static ISmartTagMarker CreateSmartTagMarker (TextEditor editor, int offset, DocumentLocation realLocation)
+ {
+ return editor.TextMarkerFactory.CreateSmartTagMarker (editor, offset, realLocation);
+ }
+
+ static bool IsIdentifierPart (char ch)
+ {
+ return char.IsLetterOrDigit (ch) || ch == '_';
+ }
+
+ public static IErrorMarker CreateErrorMarker (TextEditor editor, Error info)
+ {
+ int offset = editor.LocationToOffset (info.Region.BeginLine, info.Region.BeginColumn);
+ int endOffset = editor.LocationToOffset (info.Region.EndLine, info.Region.EndColumn);
+ if (endOffset < offset) {
+ endOffset = offset + 1;
+ while (endOffset < editor.Length && IsIdentifierPart (editor.GetCharAt (endOffset)))
+ endOffset++;
+ }
+ return editor.TextMarkerFactory.CreateErrorMarker (editor, info, offset, endOffset - offset);
+ }
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextMarkerMouseEventArgs.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextMarkerMouseEventArgs.cs
new file mode 100644
index 0000000000..7a66ca5924
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextMarkerMouseEventArgs.cs
@@ -0,0 +1,49 @@
+//
+// ITextSegmentMarker.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 MonoDevelop.Core.Text;
+using MonoDevelop.Ide.Editor;
+
+namespace MonoDevelop.Ide.Editor
+{
+ public abstract class TextMarkerMouseEventArgs : EventArgs
+ {
+ public abstract double X {
+ get;
+ }
+
+ public abstract double Y {
+ get;
+ }
+
+ public abstract object OverwriteCursor { get; set; }
+
+ public abstract string TooltipMarkup { get; set; }
+
+ public abstract bool TriggersContextMenu ();
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TooltipExtensionNode.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TooltipExtensionNode.cs
new file mode 100644
index 0000000000..d47513e925
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TooltipExtensionNode.cs
@@ -0,0 +1,49 @@
+//
+// TooltipExtensionNode.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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.Core.Text;
+using MonoDevelop.Components;
+using MonoDevelop.Ide.CodeCompletion;
+using Mono.Addins;
+
+namespace MonoDevelop.Ide.Editor
+{
+ sealed class TooltipExtensionNode : TypeExtensionNode
+ {
+ [NodeAttribute("mimeType", false, "The mimetype that this tooltip provider can handle.")]
+ string mimeType;
+
+ public string MimeType {
+ get { return mimeType; }
+ }
+
+ internal bool IsValidFor (string mimeType)
+ {
+ return string.IsNullOrEmpty (this.mimeType) || this.mimeType == mimeType;
+ }
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TooltipProvider.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TooltipProvider.cs
new file mode 100644
index 0000000000..e397e54664
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TooltipProvider.cs
@@ -0,0 +1,177 @@
+//
+// TooltipProvider.cs
+//
+// Author:
+// Lluis Sanchez <lluis@xamarin.com>
+//
+// Copyright (c) 2012 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.Text;
+using MonoDevelop.Components;
+using MonoDevelop.Ide.CodeCompletion;
+
+namespace MonoDevelop.Ide.Editor
+{
+ public sealed class TooltipItem : ISegment
+ {
+ int offset;
+ int length;
+
+ #region ISegment implementation
+
+ public int Offset {
+ get {
+ return offset;
+ }
+ internal set {
+ offset = value;
+ }
+ }
+
+ public int Length {
+ get {
+ return length;
+ }
+ internal set {
+ length = value;
+ }
+ }
+
+ public int EndOffset {
+ get {
+ return offset + length;
+ }
+ }
+
+ #endregion
+
+ public object Item { get; set; }
+
+ public TooltipItem (object item, ISegment itemSegment)
+ {
+ if (itemSegment == null)
+ throw new ArgumentNullException ("itemSegment");
+ Item = item;
+ this.offset = itemSegment.Offset;
+ this.length = itemSegment.Length;
+ }
+
+ public TooltipItem (object item, int offset, int length)
+ {
+ Item = item;
+ this.offset = offset;
+ this.length = length;
+ }
+ }
+
+ // TODO: Improve tooltip API - that really looks messy
+ public abstract class TooltipProvider
+ {
+ public abstract TooltipItem GetItem (TextEditor editor, DocumentContext ctx, int offset);
+
+ public virtual bool IsInteractive (TextEditor editor, Control tipWindow)
+ {
+ return false;
+ }
+
+ public virtual void GetRequiredPosition (TextEditor editor, Control tipWindow, out int requiredWidth, out double xalign)
+ {
+ requiredWidth = ((Gtk.Widget)tipWindow).SizeRequest ().Width;
+ xalign = 0.5;
+ }
+
+ public virtual Control CreateTooltipWindow (TextEditor editor, DocumentContext ctx, TooltipItem item, int offset, Gdk.ModifierType modifierState)
+ {
+ return null;
+ }
+
+ protected Xwt.Rectangle GetAllocation (TextEditor editor)
+ {
+ return editor.GetContent<ITextEditorImpl> ().GetEditorAllocation ();
+ }
+
+ void ShowTipInfoWindow (TextEditor editor, TooltipInformationWindow tipWindow, TooltipItem item, Gdk.ModifierType modifierState, int mouseX, int mouseY)
+ {
+ Gtk.Widget editorWidget = editor;
+
+ var startLoc = editor.OffsetToLocation (item.Offset);
+ var endLoc = editor.OffsetToLocation (item.EndOffset);
+ var p1 = editor.LocationToPoint (startLoc);
+ var p2 = editor.LocationToPoint (endLoc);
+
+ int w = (int)(p2.X - p1.X);
+
+ var caret = new Gdk.Rectangle (
+ (int)p1.X,
+ (int)p1.Y,
+ (int)w,
+ (int)editor.LineHeight
+ );
+
+ tipWindow.ShowPopup (editorWidget, caret, PopupPosition.Top);
+ }
+
+ public virtual void ShowTooltipWindow (TextEditor editor, Control tipWindow, TooltipItem item, Gdk.ModifierType modifierState, int mouseX, int mouseY)
+ {
+ if (tipWindow == null)
+ return;
+
+ var tipInfoWindow = ((Gtk.Widget)tipWindow) as TooltipInformationWindow;
+ if (tipInfoWindow != null) {
+ ShowTipInfoWindow (editor, tipInfoWindow, item, modifierState, mouseX, mouseY);
+ return;
+ }
+
+ var origin = editor.GetContent<ITextEditorImpl> ().GetEditorWindowOrigin ();
+
+ int w;
+ double xalign;
+ GetRequiredPosition (editor, tipWindow, out w, out xalign);
+ w += 10;
+
+ var allocation = GetAllocation (editor);
+ int x = (int)(mouseX + origin.X + allocation.X);
+ int y = (int)(mouseY + origin.Y + allocation.Y);
+ Gtk.Widget widget = editor;
+ var geometry = widget.Screen.GetUsableMonitorGeometry (widget.Screen.GetMonitorAtPoint (x, y));
+
+ x -= (int) ((double) w * xalign);
+ y += 10;
+
+ if (x + w >= geometry.X + geometry.Width)
+ x = geometry.X + geometry.Width - w;
+ if (x < geometry.Left)
+ x = geometry.Left;
+
+ var gtkWindow = (Gtk.Window)tipWindow;
+ int h = gtkWindow.SizeRequest ().Height;
+ if (y + h >= geometry.Y + geometry.Height)
+ y = geometry.Y + geometry.Height - h;
+ if (y < geometry.Top)
+ y = geometry.Top;
+
+ gtkWindow.Move (x, y);
+
+ gtkWindow.ShowAll ();
+ }
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/WordFindStrategy.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/WordFindStrategy.cs
new file mode 100644
index 0000000000..d850856538
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/WordFindStrategy.cs
@@ -0,0 +1,38 @@
+//
+// WordFindStrategy.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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;
+
+namespace MonoDevelop.Ide.Editor
+{
+ public enum WordFindStrategy
+ {
+ MonoDevelop,
+ Emacs,
+ SharpDevelop,
+ Vim
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FileProvider.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FileProvider.cs
index 4d2ee32f6f..c67934a5d8 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FileProvider.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FileProvider.cs
@@ -31,7 +31,7 @@ using MonoDevelop.Ide.Gui;
using System.Text;
using MonoDevelop.Core;
using System;
-using Mono.TextEditor.Utils;
+using MonoDevelop.Core.Text;
namespace MonoDevelop.Ide.FindInFiles
{
@@ -145,7 +145,7 @@ namespace MonoDevelop.Ide.FindInFiles
buffer.Insert (offset, replacement);
if (document != null) {
Gtk.Application.Invoke (delegate {
- document.Editor.Replace (offset, length, replacement);
+ document.Editor.ReplaceText (offset, length, replacement);
});
return;
}
@@ -159,7 +159,8 @@ namespace MonoDevelop.Ide.FindInFiles
undoGroup.Dispose ();
undoGroup = null;
}
- document.Editor.Document.CommitUpdateAll (); });
+ /*document.Editor.Document.CommitUpdateAll (); */
+ });
return;
}
if (buffer != null && somethingReplaced) {
@@ -167,6 +168,7 @@ namespace MonoDevelop.Ide.FindInFiles
TextFileUtility.WriteText (FileName, buffer.ToString (), encoding, hadBom);
DesktopService.SetFileAttributes (FileName, attributes);
}
+ FileService.NotifyFileChanged (FileName);
buffer = null;
}
}
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 f4e64d6990..451299685d 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindInFilesDialog.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindInFilesDialog.cs
@@ -37,6 +37,11 @@ using MonoDevelop.Ide.Gui.Content;
namespace MonoDevelop.Ide.FindInFiles
{
+ public enum PathMode {
+ Absolute,
+ Hidden
+ }
+
public partial class FindInFilesDialog : Gtk.Dialog
{
readonly bool writeScope = true;
@@ -191,7 +196,7 @@ namespace MonoDevelop.Ide.FindInFiles
toggleFindInFiles.Toggle ();
if (IdeApp.Workbench.ActiveDocument != null) {
- var view = IdeApp.Workbench.ActiveDocument.GetContent<ITextBuffer> ();
+ var view = IdeApp.Workbench.ActiveDocument.Editor;
if (view != null) {
string selectedText = FormatPatternToSelectionOption (view.SelectedText, properties.Get ("RegexSearch", false));
if (!string.IsNullOrEmpty (selectedText)) {
@@ -668,9 +673,17 @@ namespace MonoDevelop.Ide.FindInFiles
switch ((SearchScope) comboboxScope.Active) {
case SearchScope.CurrentDocument:
+ if (IdeApp.Workbench.ActiveDocument == null) {
+ MessageService.ShowError (GettextCatalog.GetString ("Currently there is no open document."));
+ return null;
+ }
scope = new DocumentScope ();
break;
case SearchScope.Selection:
+ if (IdeApp.Workbench.ActiveDocument == null) {
+ MessageService.ShowError (GettextCatalog.GetString ("Currently there is no open document."));
+ return null;
+ }
scope = new SelectionScope ();
break;
case SearchScope.WholeWorkspace:
@@ -699,6 +712,10 @@ namespace MonoDevelop.Ide.FindInFiles
MessageService.ShowError (GettextCatalog.GetString ("Currently there is no open solution."));
return null;
case SearchScope.AllOpenFiles:
+ if (IdeApp.Workbench.Documents.Count == 0) {
+ MessageService.ShowError (GettextCatalog.GetString ("Currently there are no open documents."));
+ return null;
+ }
scope = new AllOpenFilesScope ();
break;
case SearchScope.Directories:
@@ -790,6 +807,9 @@ namespace MonoDevelop.Ide.FindInFiles
ThreadPool.QueueUserWorkItem (delegate {
CancellationTokenSource cancelSource = new CancellationTokenSource ();
using (SearchProgressMonitor searchMonitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, cancellationTokenSource:cancelSource)) {
+
+ searchMonitor.PathMode = scope.PathMode;
+
searchMonitor.ReportStatus (scope.GetDescription (options, pattern, null));
lock (searchesInProgress)
searchesInProgress.Add (cancelSource);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/ISearchProgressMonitor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/ISearchProgressMonitor.cs
index 0dacb70a51..85d7601f9b 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/ISearchProgressMonitor.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/ISearchProgressMonitor.cs
@@ -38,5 +38,6 @@ namespace MonoDevelop.Ide.FindInFiles
void ReportResult (SearchResult result);
void ReportResults (IEnumerable<SearchResult> result);
void ReportStatus (string resultMessage);
+ PathMode PathMode { set; }
}
} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/MemberCollector.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/MemberCollector.cs
index ab63fa2d69..de5119e2be 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/MemberCollector.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/MemberCollector.cs
@@ -1,236 +1,236 @@
-//
-// MemberCollector.cs
-//
-// Author:
-// Mansheng Yang <lightyang0@gmail.com>
-//
-// Copyright (c) 2012 Mansheng Yang
-//
-// 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.Projects;
-using MonoDevelop.Ide.TypeSystem;
-using ICSharpCode.NRefactory.TypeSystem;
-
-namespace MonoDevelop.Ide.FindInFiles
-{
- public static class MemberCollector
- {
- static bool MatchParameters (IMember a, IMember b)
- {
- return MatchParameters (a as IParameterizedMember, b as IParameterizedMember);
- }
-
- static bool MatchParameters (IParameterizedMember a, IParameterizedMember b)
- {
- if (a == null && b == null) return true;
- if (a == null || b == null) return false;
-
- return Equals (a.Compilation, a.Parameters, b.Parameters);
- }
-
- #region Code from NRefactory ParameterListComparer
-
- public static bool Equals(ICompilation comp, IList<IParameter> x, IList<IParameter> y)
- {
- if (x == y)
- return true;
- if (x == null || y == null || x.Count != y.Count)
- return false;
- for (int i = 0; i < x.Count; i++) {
- var a = x[i];
- var b = y[i];
- if (a == null && b == null)
- continue;
- if (a == null || b == null)
- return false;
-
- // We want to consider the parameter lists "Method<T>(T a)" and "Method<S>(S b)" as equal.
- // However, the parameter types are not considered equal, as T is a different type parameter than S.
- // In order to compare the method signatures, we will normalize all method type parameters.
- IType aType = a.Type.AcceptVisitor(normalizationVisitor);
- IType bType = b.Type.AcceptVisitor(normalizationVisitor);
- bType = comp.Import (bType);
- if (!aType.Equals(bType))
- return false;
- }
- return true;
- }
-
- sealed class NormalizeTypeVisitor : TypeVisitor
- {
- public override IType VisitTypeParameter(ITypeParameter type)
- {
- if (type.OwnerType == SymbolKind.Method) {
- return ICSharpCode.NRefactory.TypeSystem.Implementation.DummyTypeParameter.GetMethodTypeParameter(type.Index);
- } else {
- return base.VisitTypeParameter(type);
- }
- }
-
- public override IType VisitTypeDefinition(ITypeDefinition type)
- {
- if (type.KnownTypeCode == KnownTypeCode.Object)
- return SpecialType.Dynamic;
- return base.VisitTypeDefinition(type);
- }
- }
-
- static readonly NormalizeTypeVisitor normalizationVisitor = new NormalizeTypeVisitor();
-
- #endregion
-
- /// <summary>
- /// find all base types(types that are not derived from other types) in the specified types
- /// </summary>
- /// <param name="types"></param>
- /// <returns></returns>
- public static IEnumerable<ITypeDefinition> GetBaseTypes (IEnumerable<ITypeDefinition> types)
- {
- if (types == null)
- yield break;
- types = types.ToList ();
- if (!types.Any ())
- yield break;
-
- var baseType = types.FirstOrDefault ();
- var otherTypes = new List<ITypeDefinition> ();
-
- foreach (var type in types.Skip (1)) {
- if (baseType.IsDerivedFrom (type)) {
- baseType = type;
- } else if (!type.IsDerivedFrom (baseType)) {
- // this type is not directly related to baseType
- otherTypes.Add (type);
- }
- }
- yield return baseType;
- foreach (var type in GetBaseTypes (otherTypes))
- yield return type;
- }
-
- static IEnumerable<IMember> GetMembers (ITypeDefinition type, IMember member, bool ignoreInherited,
- Func<IMember, bool> filter)
- {
- var options = ignoreInherited ? GetMemberOptions.IgnoreInheritedMembers : GetMemberOptions.None;
- var members = type.GetMembers (m => m.Name == member.Name, options);
-
-/* // Filter out shadowed members.
- // class A { public string Foo { get; set; } } class B : A { public string Foo { get; set; } }
- if (member.SymbolKind == SymbolKind.Property || !(member is IParameterizedMember)) {
- members = members.Where (m => m == member || m.DeclaringType.Kind == TypeKind.Interface);
- }*/
- if (filter != null)
- members = members.Where (filter);
- return members;
- }
-
- static IEnumerable<ITypeDefinition> Import (ICompilation compilation, IEnumerable<ITypeDefinition> types)
- {
- return types.Select (t => compilation.Import (t));
- }
-
- /// <summary>
- /// collect members with the same signature/name(if overloads are included) as the specified member
- /// in the inheritance tree
- /// </summary>
- public static IEnumerable<IMember> CollectMembers (Solution solution, IMember member, ReferenceFinder.RefactoryScope scope,
- bool includeOverloads = true, bool matchDeclaringType = false)
- {
- if (solution == null || member.SymbolKind == SymbolKind.Destructor || member.SymbolKind == SymbolKind.Operator)
- return new [] { member };
-
- if (member.SymbolKind == SymbolKind.Constructor) {
- if (includeOverloads)
- return member.DeclaringType.GetMembers (m => m.SymbolKind == SymbolKind.Constructor, GetMemberOptions.IgnoreInheritedMembers);
- return new [] { member };
- }
-
- Func<IMember, bool> memberFilter = null;
- if (member is IParameterizedMember && !includeOverloads)
- memberFilter = m => MatchParameters (m, member);
-
- var declaringType = member.DeclaringTypeDefinition;
- if (declaringType == null)
- return new [] { member };
- // only collect members in declaringType
- if (matchDeclaringType)
- return GetMembers (declaringType, member, true, memberFilter);
-
- if (declaringType.Kind != TypeKind.Class && declaringType.Kind != TypeKind.Interface)
- return GetMembers (declaringType, member, false, memberFilter);
-
- var searchTypes = new List<ITypeDefinition> ();
- if (includeOverloads) {
- var interfaces = from t in declaringType.GetAllBaseTypeDefinitions ()
- where t.Kind == TypeKind.Interface && GetMembers (t, member, true, memberFilter).Any ()
- select t;
- searchTypes.AddRange (GetBaseTypes (interfaces));
- }
-
- if (member.DeclaringType.Kind == TypeKind.Class) {
- var members = GetMembers (declaringType, member, false, memberFilter).ToList ();
- if (members.Any (m => m.IsOverridable))
- searchTypes.AddRange (GetBaseTypes (members.Select (m => m.DeclaringTypeDefinition)));
- else if (searchTypes.Count == 0)
- return members;
- }
-
- IList<ICompilation> compilations;
- if (scope == ReferenceFinder.RefactoryScope.Solution || scope == ReferenceFinder.RefactoryScope.Unknown) {
- var projects = SearchCollector.CollectProjects (solution, searchTypes);
- compilations = projects.Select (TypeSystemService.GetCompilation).ToList ();
- } else {
- compilations = new [] { member.Compilation };
- }
-
- var result = new List<IMember> ();
- var mainAssemblies = new HashSet<string> (compilations.Select (c => c.MainAssembly.AssemblyName));
- var searchedAssemblies = new HashSet<string> ();
- var searchedTypes = new HashSet<string> ();
-
- foreach (var compilation in compilations) {
- var baseTypeImports = Import(compilation, searchTypes).Where (t => t != null).ToList ();
- if (!baseTypeImports.Any ()) continue;
-
- foreach (var assembly in compilation.Assemblies) {
- // search main assemblies in their projects' own compilation, to avoid possible resolving problems
- if ((mainAssemblies.Contains(assembly.AssemblyName) && assembly != compilation.MainAssembly) ||
- !searchedAssemblies.Add (assembly.AssemblyName))
- continue;
-
- foreach (var type in assembly.GetAllTypeDefinitions ()) {
- // members in base types will also be added
- // because IsDerivedFrom return true for a type itself
- if (!searchedTypes.Add (type.ReflectionName) || !baseTypeImports.Any (type.IsDerivedFrom))
- continue;
- result.AddRange (GetMembers (type, member, true, memberFilter));
- }
- }
- }
- if (!result.Contains (member))
- result.Add (member);
- return result;
- }
-
- }
-}
-
+////
+//// MemberCollector.cs
+////
+//// Author:
+//// Mansheng Yang <lightyang0@gmail.com>
+////
+//// Copyright (c) 2012 Mansheng Yang
+////
+//// 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.Projects;
+//using MonoDevelop.Ide.TypeSystem;
+//using ICSharpCode.NRefactory.TypeSystem;
+//
+//namespace MonoDevelop.Ide.FindInFiles
+//{
+// public static class MemberCollector
+// {
+// static bool MatchParameters (IMember a, IMember b)
+// {
+// return MatchParameters (a as IParameterizedMember, b as IParameterizedMember);
+// }
+//
+// static bool MatchParameters (IParameterizedMember a, IParameterizedMember b)
+// {
+// if (a == null && b == null) return true;
+// if (a == null || b == null) return false;
+//
+// return Equals (a.Compilation, a.Parameters, b.Parameters);
+// }
+//
+// #region Code from NRefactory ParameterListComparer
+//
+// public static bool Equals(ICompilation comp, IList<IParameter> x, IList<IParameter> y)
+// {
+// if (x == y)
+// return true;
+// if (x == null || y == null || x.Count != y.Count)
+// return false;
+// for (int i = 0; i < x.Count; i++) {
+// var a = x[i];
+// var b = y[i];
+// if (a == null && b == null)
+// continue;
+// if (a == null || b == null)
+// return false;
+//
+// // We want to consider the parameter lists "Method<T>(T a)" and "Method<S>(S b)" as equal.
+// // However, the parameter types are not considered equal, as T is a different type parameter than S.
+// // In order to compare the method signatures, we will normalize all method type parameters.
+// IType aType = a.Type.AcceptVisitor(normalizationVisitor);
+// IType bType = b.Type.AcceptVisitor(normalizationVisitor);
+// bType = comp.Import (bType);
+// if (!aType.Equals(bType))
+// return false;
+// }
+// return true;
+// }
+//
+// sealed class NormalizeTypeVisitor : TypeVisitor
+// {
+// public override IType VisitTypeParameter(ITypeParameter type)
+// {
+// if (type.OwnerType == SymbolKind.Method) {
+// return ICSharpCode.NRefactory.TypeSystem.Implementation.DummyTypeParameter.GetMethodTypeParameter(type.Index);
+// } else {
+// return base.VisitTypeParameter(type);
+// }
+// }
+//
+// public override IType VisitTypeDefinition(ITypeDefinition type)
+// {
+// if (type.KnownTypeCode == KnownTypeCode.Object)
+// return SpecialType.Dynamic;
+// return base.VisitTypeDefinition(type);
+// }
+// }
+//
+// static readonly NormalizeTypeVisitor normalizationVisitor = new NormalizeTypeVisitor();
+//
+// #endregion
+//
+// /// <summary>
+// /// find all base types(types that are not derived from other types) in the specified types
+// /// </summary>
+// /// <param name="types"></param>
+// /// <returns></returns>
+// public static IEnumerable<ITypeDefinition> GetBaseTypes (IEnumerable<ITypeDefinition> types)
+// {
+// if (types == null)
+// yield break;
+// types = types.ToList ();
+// if (!types.Any ())
+// yield break;
+//
+// var baseType = types.FirstOrDefault ();
+// var otherTypes = new List<ITypeDefinition> ();
+//
+// foreach (var type in types.Skip (1)) {
+// if (baseType.IsDerivedFrom (type)) {
+// baseType = type;
+// } else if (!type.IsDerivedFrom (baseType)) {
+// // this type is not directly related to baseType
+// otherTypes.Add (type);
+// }
+// }
+// yield return baseType;
+// foreach (var type in GetBaseTypes (otherTypes))
+// yield return type;
+// }
+//
+// static IEnumerable<IMember> GetMembers (ITypeDefinition type, IMember member, bool ignoreInherited,
+// Func<IMember, bool> filter)
+// {
+// var options = ignoreInherited ? GetMemberOptions.IgnoreInheritedMembers : GetMemberOptions.None;
+// var members = type.GetMembers (m => m.Name == member.Name, options);
+//
+///* // Filter out shadowed members.
+// // class A { public string Foo { get; set; } } class B : A { public string Foo { get; set; } }
+// if (member.SymbolKind == SymbolKind.Property || !(member is IParameterizedMember)) {
+// members = members.Where (m => m == member || m.DeclaringType.Kind == TypeKind.Interface);
+// }*/
+// if (filter != null)
+// members = members.Where (filter);
+// return members;
+// }
+//
+// static IEnumerable<ITypeDefinition> Import (ICompilation compilation, IEnumerable<ITypeDefinition> types)
+// {
+// return types.Select (t => compilation.Import (t));
+// }
+//
+// /// <summary>
+// /// collect members with the same signature/name(if overloads are included) as the specified member
+// /// in the inheritance tree
+// /// </summary>
+// public static IEnumerable<IMember> CollectMembers (Solution solution, IMember member, ReferenceFinder.RefactoryScope scope,
+// bool includeOverloads = true, bool matchDeclaringType = false)
+// {
+// if (solution == null || member.SymbolKind == SymbolKind.Destructor || member.SymbolKind == SymbolKind.Operator)
+// return new [] { member };
+//
+// if (member.SymbolKind == SymbolKind.Constructor) {
+// if (includeOverloads)
+// return member.DeclaringType.GetMembers (m => m.SymbolKind == SymbolKind.Constructor, GetMemberOptions.IgnoreInheritedMembers);
+// return new [] { member };
+// }
+//
+// Func<IMember, bool> memberFilter = null;
+// if (member is IParameterizedMember && !includeOverloads)
+// memberFilter = m => MatchParameters (m, member);
+//
+// var declaringType = member.DeclaringTypeDefinition;
+// if (declaringType == null)
+// return new [] { member };
+// // only collect members in declaringType
+// if (matchDeclaringType)
+// return GetMembers (declaringType, member, true, memberFilter);
+//
+// if (declaringType.Kind != TypeKind.Class && declaringType.Kind != TypeKind.Interface)
+// return GetMembers (declaringType, member, false, memberFilter);
+//
+// var searchTypes = new List<ITypeDefinition> ();
+// if (includeOverloads) {
+// var interfaces = from t in declaringType.GetAllBaseTypeDefinitions ()
+// where t.Kind == TypeKind.Interface && GetMembers (t, member, true, memberFilter).Any ()
+// select t;
+// searchTypes.AddRange (GetBaseTypes (interfaces));
+// }
+//
+// if (member.DeclaringType.Kind == TypeKind.Class) {
+// var members = GetMembers (declaringType, member, false, memberFilter).ToList ();
+// if (members.Any (m => m.IsOverridable))
+// searchTypes.AddRange (GetBaseTypes (members.Select (m => m.DeclaringTypeDefinition)));
+// else if (searchTypes.Count == 0)
+// return members;
+// }
+//
+// IList<ICompilation> compilations;
+// if (scope == ReferenceFinder.RefactoryScope.Solution || scope == ReferenceFinder.RefactoryScope.Unknown) {
+// var projects = SearchCollector.CollectProjects (solution, searchTypes);
+// compilations = projects.Select (TypeSystemService.GetCompilation).ToList ();
+// } else {
+// compilations = new [] { member.Compilation };
+// }
+//
+// var result = new List<IMember> ();
+// var mainAssemblies = new HashSet<string> (compilations.Select (c => c.MainAssembly.AssemblyName));
+// var searchedAssemblies = new HashSet<string> ();
+// var searchedTypes = new HashSet<string> ();
+//
+// foreach (var compilation in compilations) {
+// var baseTypeImports = Import(compilation, searchTypes).Where (t => t != null).ToList ();
+// if (!baseTypeImports.Any ()) continue;
+//
+// foreach (var assembly in compilation.Assemblies) {
+// // search main assemblies in their projects' own compilation, to avoid possible resolving problems
+// if ((mainAssemblies.Contains(assembly.AssemblyName) && assembly != compilation.MainAssembly) ||
+// !searchedAssemblies.Add (assembly.AssemblyName))
+// continue;
+//
+// foreach (var type in assembly.GetAllTypeDefinitions ()) {
+// // members in base types will also be added
+// // because IsDerivedFrom return true for a type itself
+// if (!searchedTypes.Add (type.ReflectionName) || !baseTypeImports.Any (type.IsDerivedFrom))
+// continue;
+// result.AddRange (GetMembers (type, member, true, memberFilter));
+// }
+// }
+// }
+// if (!result.Contains (member))
+// result.Add (member);
+// return result;
+// }
+//
+// }
+//}
+//
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/MemberReference.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/MemberReference.cs
index 44936f27f4..0e1b3915ae 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/MemberReference.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/MemberReference.cs
@@ -25,16 +25,18 @@
// THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.TypeSystem;
-using Mono.TextEditor.Highlighting;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Ide.Editor.Highlighting;
namespace MonoDevelop.Ide.FindInFiles
{
[Flags]
public enum ReferenceUsageType {
- Unknown = 0,
- Read = 1,
- Write = 2,
- ReadWrite = Read | Write
+ Unknown = 0,
+ Read = 1,
+ Write = 2,
+ Declariton = 4,
+ ReadWrite = Read | Write
}
public class MemberReference : SearchResult
@@ -44,23 +46,24 @@ namespace MonoDevelop.Ide.FindInFiles
return new MonoDevelop.Ide.FindInFiles.FileProvider (FileName);
}
}
-
- public override string FileName {
+ readonly string fileName;
+ public override string FileName {
get {
- return Region.FileName;
+ return fileName;
}
}
public ReferenceUsageType ReferenceUsageType { get; set; }
public object EntityOrVariable { get; private set;}
- public DomRegion Region { get; private set;}
- public MemberReference (object entity, DomRegion region, int offset, int length) : base (offset, length)
+ public MemberReference (object entity, string fileName, int offset, int length) : base (offset, length)
{
if (entity == null)
throw new System.ArgumentNullException ("entity");
+ if (fileName == null)
+ throw new ArgumentNullException ("fileName");
EntityOrVariable = entity;
- Region = region;
+ this.fileName = fileName;
}
public string GetName ()
@@ -79,7 +82,8 @@ namespace MonoDevelop.Ide.FindInFiles
public override AmbientColor GetBackgroundMarkerColor (ColorScheme style)
{
- return (ReferenceUsageType & ReferenceUsageType.Write) != 0 ?
+ return (ReferenceUsageType & ReferenceUsageType.Write) != 0 ||
+ (ReferenceUsageType & ReferenceUsageType.Declariton) != 0?
style.ChangingUsagesRectangle :
style.UsagesRectangle;
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/ReferencesFinder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/ReferencesFinder.cs
index 9691a93978..c69477eb13 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/ReferencesFinder.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/ReferencesFinder.cs
@@ -1,321 +1,323 @@
-//
-// ReferenceFinder.cs
-//
-// Author:
-// Mike Krüger <mkrueger@novell.com>
-//
-// Copyright (c) 2011 Novell, Inc (http://www.novell.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 Mono.Addins;
-using MonoDevelop.Core;
-using MonoDevelop.Projects;
-using ICSharpCode.NRefactory.TypeSystem;
-using MonoDevelop.Ide.TypeSystem;
-using System.Threading.Tasks;
-
-namespace MonoDevelop.Ide.FindInFiles
-{
- public abstract class ReferenceFinder
- {
- public bool IncludeDocumentation {
- get;
- set;
- }
-
- /*
- Project project;
- protected Project Project {
- get {
- if (project == null)
- project = Content.GetProject ();
- return project;
- }
- }*/
-
- static List<ReferenceFinderCodon> referenceFinderCodons = new List<ReferenceFinderCodon> ();
-
- static ReferenceFinder ()
- {
- AddinManager.AddExtensionNodeHandler ("/MonoDevelop/Ide/ReferenceFinder", delegate(object sender, ExtensionNodeEventArgs args) {
- var codon = (ReferenceFinderCodon)args.ExtensionNode;
- switch (args.Change) {
- case ExtensionChange.Add:
- referenceFinderCodons.Add (codon);
- break;
- case ExtensionChange.Remove:
- referenceFinderCodons.Remove (codon);
- break;
- }
- });
- }
-
- static ReferenceFinder GetReferenceFinder (string mimeType)
- {
- var codon = referenceFinderCodons.FirstOrDefault (c => c.SupportedMimeTypes.Any (mt => mt == mimeType));
- return codon != null ? codon.CreateFinder () : null;
- }
-
- public static IEnumerable<MemberReference> FindReferences (object member, bool searchForAllOverloads, ProgressMonitor monitor = null)
- {
- return FindReferences (IdeApp.ProjectOperations.CurrentSelectedSolution, member, searchForAllOverloads, RefactoryScope.Unknown, monitor);
- }
-
- public static IEnumerable<MemberReference> FindReferences (object member, bool searchForAllOverloads, RefactoryScope scope, ProgressMonitor monitor = null)
- {
- return FindReferences (IdeApp.ProjectOperations.CurrentSelectedSolution, member, searchForAllOverloads, scope, monitor);
- }
-
- static SearchCollector.FileList GetFileList (string fileName)
- {
- var doc = IdeApp.Workbench.GetDocument (fileName);
- if (doc != null)
- return new SearchCollector.FileList (doc.Project, doc.ProjectContent, new [] { (FilePath)fileName });
- return null;
- }
-
- static IEnumerable<SearchCollector.FileList> GetFileNames (Solution solution, object node, RefactoryScope scope,
- ProgressMonitor monitor, IEnumerable<object> searchNodes)
- {
- if (!(node is IField) && !(node is IParameter) && node is IVariable || scope == RefactoryScope.File) {
- string fileName;
- if (node is IEntity) {
- fileName = ((IEntity)node).Region.FileName;
- } else if (node is ITypeParameter) {
- fileName = ((ITypeParameter)node).Region.FileName;
- } else {
- fileName = ((IVariable)node).Region.FileName;
- }
- var fileList = GetFileList (fileName);
- if (fileList != null)
- yield return fileList;
- yield break;
- }
-
- if (node is ITypeParameter) {
- var typeParameter = node as ITypeParameter;
- if (typeParameter.Owner != null) {
- yield return SearchCollector.CollectDeclaringFiles (typeParameter.Owner);
- yield break;
- }
- var fileList = GetFileList (typeParameter.Region.FileName);
- if (fileList != null)
- yield return fileList;
- yield break;
- }
- var par = node as IParameter;
- if (par != null) {
- node = par.Owner;
- }
-
- var compilationProvider = (ICompilationProvider)node;
- switch (scope) {
- case RefactoryScope.DeclaringType:
- var entity = (IEntity)compilationProvider;
- if (entity.DeclaringTypeDefinition != null)
- yield return SearchCollector.CollectDeclaringFiles (entity.DeclaringTypeDefinition);
- else
- yield return SearchCollector.CollectDeclaringFiles (entity);
- break;
- case RefactoryScope.Project:
- var sourceProject = TypeSystemService.GetProject (compilationProvider.Compilation.MainAssembly.UnresolvedAssembly.Location);
- foreach (var file in SearchCollector.CollectFiles (sourceProject, searchNodes))
- yield return file;
- break;
- default:
- var files = SearchCollector.CollectFiles (solution, searchNodes).ToList ();
- if (monitor != null)
- monitor.BeginTask (GettextCatalog.GetString ("Searching for references in solution..."), files.Count);
- foreach (var file in files) {
- if (monitor != null && monitor.CancellationToken.IsCancellationRequested)
- yield break;
- yield return file;
- if (monitor != null)
- monitor.Step (1);
- }
- if (monitor != null)
- monitor.EndTask ();
- break;
- }
- }
-
- public static List<Project> GetAllReferencingProjects (Solution solution, Project sourceProject)
- {
- var projects = new List<Project> ();
- projects.Add (sourceProject);
- foreach (var project in solution.GetAllProjects ()) {
- if (project.GetReferencedItems (ConfigurationSelector.Default).Any (prj => prj == sourceProject))
- projects.Add (project);
- }
- return projects;
- }
-
- public static IEnumerable<MemberReference> FindReferences (Solution solution, object member, bool searchForAllOverloads, RefactoryScope scope = RefactoryScope.Unknown, ProgressMonitor monitor = null)
- {
- if (member == null)
- yield break;
- if (solution == null && member is IEntity) {
- var project = TypeSystemService.GetProject ((member as IEntity).Compilation.MainAssembly.UnresolvedAssembly.Location);
- if (project == null)
- yield break;
- solution = project.ParentSolution;
- }
-
- IList<object> searchNodes = new [] { member };
- if (member is ITypeParameter) {
- // nothing
- } else if (member is IType) {
- searchNodes = CollectMembers ((IType)member).ToList<object> ();
- } else if (member is IEntity) {
- var e = (IEntity)member;
- if (e.SymbolKind == SymbolKind.Destructor) {
- foreach (var r in FindReferences (solution, e.DeclaringType, searchForAllOverloads, scope, monitor)) {
- yield return r;
- }
- yield break;
- }
- if (member is IMember)
- searchNodes = CollectMembers (solution, (IMember)member, scope, searchForAllOverloads).ToList<object> ();
- }
- // prepare references finder
- var preparedFinders = new List<Tuple<ReferenceFinder, Project, IProjectContent, List<FilePath>>> ();
- var curList = new List<FilePath> ();
- int totalFiles = 0;
- foreach (var info in GetFileNames (solution, member, scope, monitor, searchNodes)) {
- string oldMime = null;
- foreach (var file in info.Files) {
- if (monitor != null && monitor.CancellationToken.IsCancellationRequested)
- yield break;
-
- string mime = DesktopService.GetMimeTypeForUri (file);
- if (mime != oldMime) {
- var finder = GetReferenceFinder (mime);
- if (finder == null)
- continue;
-
- oldMime = mime;
-
- curList = new List<FilePath> ();
- preparedFinders.Add (Tuple.Create (finder, info.Project, info.Content, curList));
- }
- curList.Add (file);
- totalFiles++;
- }
- }
-
- // execute search
- if (monitor != null)
- monitor.BeginTask (GettextCatalog.GetString ("Analyzing files..."), totalFiles);
- var foundOccurrences = new HashSet<Tuple<string, DomRegion>> ();
- foreach (var tuple in preparedFinders) {
- var finder = tuple.Item1;
- foreach (var foundReference in finder.FindReferences (tuple.Item2, tuple.Item3, tuple.Item4, monitor, searchNodes)) {
- if (monitor != null && monitor.CancellationToken.IsCancellationRequested)
- yield break;
- var tag = Tuple.Create (foundReference.FileName, foundReference.Region);
- if (foundOccurrences.Contains (tag))
- continue;
- foundOccurrences.Add (tag);
- yield return foundReference;
- }
- }
- if (monitor != null)
- monitor.EndTask ();
- }
-
- public abstract IEnumerable<MemberReference> FindReferences (Project project, IProjectContent content, IEnumerable<FilePath> files, ProgressMonitor monitor, IEnumerable<object> searchedMembers);
-
- internal static IEnumerable<IMember> CollectMembers (Solution solution, IMember member, RefactoryScope scope, bool includeOverloads = true)
- {
- return MemberCollector.CollectMembers (solution, member, scope, includeOverloads);
- }
-
- internal static IEnumerable<IEntity> CollectMembers (IType type)
- {
- var typeDefinition = type.GetDefinition ();
- if (typeDefinition == null)
- yield break;
- yield return (IEntity)typeDefinition;
- foreach (var c in typeDefinition.GetMembers (m => m.SymbolKind == SymbolKind.Constructor, GetMemberOptions.IgnoreInheritedMembers)) {
- if (!c.IsSynthetic)
- yield return c;
- }
-
- foreach (var m in type.GetMethods (m => m.IsDestructor, GetMemberOptions.IgnoreInheritedMembers)) {
- yield return m;
- }
- }
-
-
- public enum RefactoryScope{ Unknown, File, DeclaringType, Solution, Project}
-// static RefactoryScope GetScope (object o)
+////
+//// ReferenceFinder.cs
+////
+//// Author:
+//// Mike Krüger <mkrueger@novell.com>
+////
+//// Copyright (c) 2011 Novell, Inc (http://www.novell.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 Mono.Addins;
+//using MonoDevelop.Core;
+//using MonoDevelop.Projects;
+//using ICSharpCode.NRefactory.TypeSystem;
+//using MonoDevelop.Ide.TypeSystem;
+//using System.Threading.Tasks;
+//
+//namespace MonoDevelop.Ide.FindInFiles
+//{
+// public abstract class ReferenceFinder
+// {
+// public bool IncludeDocumentation {
+// get;
+// set;
+// }
+//
+// /*
+// Project project;
+// protected Project Project {
+// get {
+// if (project == null)
+// project = Content.GetProject ();
+// return project;
+// }
+// }*/
+//
+// static List<ReferenceFinderCodon> referenceFinderCodons = new List<ReferenceFinderCodon> ();
+//
+// static ReferenceFinder ()
+// {
+// AddinManager.AddExtensionNodeHandler ("/MonoDevelop/Ide/ReferenceFinder", delegate(object sender, ExtensionNodeEventArgs args) {
+// var codon = (ReferenceFinderCodon)args.ExtensionNode;
+// switch (args.Change) {
+// case ExtensionChange.Add:
+// referenceFinderCodons.Add (codon);
+// break;
+// case ExtensionChange.Remove:
+// referenceFinderCodons.Remove (codon);
+// break;
+// }
+// });
+// }
+//
+// static ReferenceFinder GetReferenceFinder (string mimeType)
+// {
+// var codon = referenceFinderCodons.FirstOrDefault (c => c.SupportedMimeTypes.Any (mt => mt == mimeType));
+// return codon != null ? codon.CreateFinder () : null;
+// }
+//
+// public static IEnumerable<MemberReference> FindReferences (object member, bool searchForAllOverloads, IProgressMonitor monitor = null)
+// {
+// return FindReferences (IdeApp.ProjectOperations.CurrentSelectedSolution, member, searchForAllOverloads, RefactoryScope.Unknown, monitor);
+// }
+//
+// public static IEnumerable<MemberReference> FindReferences (object member, bool searchForAllOverloads, RefactoryScope scope, IProgressMonitor monitor = null)
// {
-// IEntity node = o as IEntity;
-// if (node == null)
-// return RefactoryScope.File;
+// return FindReferences (IdeApp.ProjectOperations.CurrentSelectedSolution, member, searchForAllOverloads, scope, monitor);
+// }
+//
+// static SearchCollector.FileList GetFileList (string fileName)
+// {
+// var doc = IdeApp.Workbench.GetDocument (fileName);
+// if (doc != null)
+// return new SearchCollector.FileList (doc.Project, null, new [] { (FilePath)fileName });
+// return null;
+// }
+//
+// static IEnumerable<SearchCollector.FileList> GetFileNames (Solution solution, object node, RefactoryScope scope,
+// IProgressMonitor monitor, IEnumerable<object> searchNodes)
+// {
+// if (!(node is IField) && !(node is IParameter) && node is IVariable || scope == RefactoryScope.File) {
+// string fileName;
+// if (node is IEntity) {
+// fileName = ((IEntity)node).Region.FileName;
+// } else if (node is ITypeParameter) {
+// fileName = ((ITypeParameter)node).Region.FileName;
+// } else {
+// fileName = ((IVariable)node).Region.FileName;
+// }
+// var fileList = GetFileList (fileName);
+// if (fileList != null)
+// yield return fileList;
+// yield break;
+// }
//
-// // TODO: RefactoringsScope.Hierarchy
-// switch (node.Accessibility) {
-// case Accessibility.Public:
-// case Accessibility.Protected:
-// case Accessibility.ProtectedOrInternal:
-// if (node.DeclaringTypeDefinition != null) {
-// var scope = GetScope (node.DeclaringTypeDefinition);
-// if (scope != RefactoryScope.Solution)
-// return RefactoryScope.Project;
-// }
-// return RefactoryScope.Solution;
-// case Accessibility.Internal:
-// case Accessibility.ProtectedAndInternal:
-// return RefactoryScope.Project;
+// if (node is ITypeParameter) {
+// var typeParameter = node as ITypeParameter;
+// if (typeParameter.Owner != null) {
+// yield return SearchCollector.CollectDeclaringFiles (typeParameter.Owner);
+// yield break;
+// }
+// var fileList = GetFileList (typeParameter.Region.FileName);
+// if (fileList != null)
+// yield return fileList;
+// yield break;
+// }
+// var par = node as IParameter;
+// if (par != null) {
+// node = par.Owner;
+// }
+//
+// var compilationProvider = (ICompilationProvider)node;
+// switch (scope) {
+// case RefactoryScope.DeclaringType:
+// var entity = (IEntity)compilationProvider;
+// if (entity.DeclaringTypeDefinition != null)
+// yield return SearchCollector.CollectDeclaringFiles (entity.DeclaringTypeDefinition);
+// else
+// yield return SearchCollector.CollectDeclaringFiles (entity);
+// break;
+// case RefactoryScope.Project:
+// var sourceProject = TypeSystemService.GetProject (compilationProvider.Compilation.MainAssembly.UnresolvedAssembly.Location);
+// foreach (var file in SearchCollector.CollectFiles (sourceProject, searchNodes))
+// yield return file;
+// break;
+// default:
+// var files = SearchCollector.CollectFiles (solution, searchNodes).ToList ();
+// if (monitor != null)
+// monitor.BeginTask (GettextCatalog.GetString ("Searching for references in solution..."), files.Count);
+// foreach (var file in files) {
+// if (monitor != null && monitor.IsCancelRequested)
+// yield break;
+// yield return file;
+// if (monitor != null)
+// monitor.Step (1);
+// }
+// if (monitor != null)
+// monitor.EndTask ();
+// break;
+// }
+// }
+//
+// public static List<Project> GetAllReferencingProjects (Solution solution, Project sourceProject)
+// {
+// var projects = new List<Project> ();
+// projects.Add (sourceProject);
+// foreach (var project in solution.GetAllProjects ()) {
+// if (project.GetReferencedItems (ConfigurationSelector.Default).Any (prj => prj == sourceProject))
+// projects.Add (project);
+// }
+// return projects;
+// }
+//
+// public static IEnumerable<MemberReference> FindReferences (Solution solution, object member, bool searchForAllOverloads, RefactoryScope scope = RefactoryScope.Unknown, IProgressMonitor monitor = null)
+// {
+// yield break;
+//
+//// if (member == null)
+//// yield break;
+//// if (solution == null && member is IEntity) {
+//// var project = TypeSystemService.GetProject ((member as IEntity).Compilation.MainAssembly.UnresolvedAssembly.Location);
+//// if (project == null)
+//// yield break;
+//// solution = project.ParentSolution;
+//// }
+////
+//// IList<object> searchNodes = new [] { member };
+//// if (member is ITypeParameter) {
+//// // nothing
+//// } else if (member is IType) {
+//// searchNodes = CollectMembers ((IType)member).ToList<object> ();
+//// } else if (member is IEntity) {
+//// var e = (IEntity)member;
+//// if (e.SymbolKind == SymbolKind.Destructor) {
+//// foreach (var r in FindReferences (solution, e.DeclaringType, searchForAllOverloads, scope, monitor)) {
+//// yield return r;
+//// }
+//// yield break;
+//// }
+//// if (member is IMember)
+//// searchNodes = CollectMembers (solution, (IMember)member, scope, searchForAllOverloads).ToList<object> ();
+//// }
+//// // prepare references finder
+//// var preparedFinders = new List<Tuple<ReferenceFinder, Project, IProjectContent, List<FilePath>>> ();
+//// var curList = new List<FilePath> ();
+//// int totalFiles = 0;
+//// foreach (var info in GetFileNames (solution, member, scope, monitor, searchNodes)) {
+//// string oldMime = null;
+//// foreach (var file in info.Files) {
+//// if (monitor != null && monitor.IsCancelRequested)
+//// yield break;
+////
+//// string mime = DesktopService.GetMimeTypeForUri (file);
+//// if (mime != oldMime) {
+//// var finder = GetReferenceFinder (mime);
+//// if (finder == null)
+//// continue;
+////
+//// oldMime = mime;
+////
+//// curList = new List<FilePath> ();
+//// preparedFinders.Add (Tuple.Create (finder, info.Project, info.Content, curList));
+//// }
+//// curList.Add (file);
+//// totalFiles++;
+//// }
+//// }
+////
+//// // execute search
+//// if (monitor != null)
+//// monitor.BeginTask (GettextCatalog.GetString ("Analyzing files..."), totalFiles);
+//// var foundOccurrences = new HashSet<Tuple<string, DomRegion>> ();
+//// foreach (var tuple in preparedFinders) {
+//// var finder = tuple.Item1;
+//// foreach (var foundReference in finder.FindReferences (tuple.Item2, tuple.Item3, tuple.Item4, monitor, searchNodes)) {
+//// if (monitor != null && monitor.IsCancelRequested)
+//// yield break;
+//// var tag = Tuple.Create (foundReference.FileName, foundReference.Region);
+//// if (foundOccurrences.Contains (tag))
+//// continue;
+//// foundOccurrences.Add (tag);
+//// yield return foundReference;
+//// }
+//// }
+//// if (monitor != null)
+//// monitor.EndTask ();
+// }
+//
+// public abstract IEnumerable<MemberReference> FindReferences (Project project, IProjectContent content, IEnumerable<FilePath> files, IProgressMonitor monitor, IEnumerable<object> searchedMembers);
+//
+// internal static IEnumerable<IMember> CollectMembers (Solution solution, IMember member, RefactoryScope scope, bool includeOverloads = true)
+// {
+// return MemberCollector.CollectMembers (solution, member, scope, includeOverloads);
+// }
+//
+// internal static IEnumerable<IEntity> CollectMembers (IType type)
+// {
+// var typeDefinition = type.GetDefinition ();
+// if (typeDefinition == null)
+// yield break;
+// yield return (IEntity)typeDefinition;
+// foreach (var c in typeDefinition.GetMembers (m => m.SymbolKind == SymbolKind.Constructor, GetMemberOptions.IgnoreInheritedMembers)) {
+// if (!c.IsSynthetic)
+// yield return c;
// }
-// return RefactoryScope.DeclaringType;
+//
+// foreach (var m in type.GetMethods (m => m.IsDestructor, GetMemberOptions.IgnoreInheritedMembers)) {
+// yield return m;
+// }
+// }
+//
+//
+// public enum RefactoryScope{ Unknown, File, DeclaringType, Solution, Project}
+//// static RefactoryScope GetScope (object o)
+//// {
+//// IEntity node = o as IEntity;
+//// if (node == null)
+//// return RefactoryScope.File;
+////
+//// // TODO: RefactoringsScope.Hierarchy
+//// switch (node.Accessibility) {
+//// case Accessibility.Public:
+//// case Accessibility.Protected:
+//// case Accessibility.ProtectedOrInternal:
+//// if (node.DeclaringTypeDefinition != null) {
+//// var scope = GetScope (node.DeclaringTypeDefinition);
+//// if (scope != RefactoryScope.Solution)
+//// return RefactoryScope.Project;
+//// }
+//// return RefactoryScope.Solution;
+//// case Accessibility.Internal:
+//// case Accessibility.ProtectedAndInternal:
+//// return RefactoryScope.Project;
+//// }
+//// return RefactoryScope.DeclaringType;
+//// }
+// }
+//
+// [ExtensionNode (Description="A reference finder. The specified class needs to inherit from MonoDevelop.Projects.CodeGeneration.ReferenceFinder")]
+// internal class ReferenceFinderCodon : TypeExtensionNode
+// {
+// [NodeAttribute("supportedmimetypes", "Mime types supported by this binding (to be shown in the Open File dialog)")]
+// string[] supportedMimetypes;
+//
+// public string[] SupportedMimeTypes {
+// get {
+// return supportedMimetypes;
+// }
+// set {
+// supportedMimetypes = value;
+// }
+// }
+//
+// public ReferenceFinder CreateFinder ()
+// {
+// return (ReferenceFinder)CreateInstance ();
+// }
+//
+// public override string ToString ()
+// {
+// return string.Format ("[ReferenceFinderCodon: SupportedMimeTypes={0}]", SupportedMimeTypes);
// }
- }
-
- [ExtensionNode (Description="A reference finder. The specified class needs to inherit from MonoDevelop.Projects.CodeGeneration.ReferenceFinder")]
- internal class ReferenceFinderCodon : TypeExtensionNode
- {
- [NodeAttribute("supportedmimetypes", "Mime types supported by this binding (to be shown in the Open File dialog)")]
- string[] supportedMimetypes;
-
- public string[] SupportedMimeTypes {
- get {
- return supportedMimetypes;
- }
- set {
- supportedMimetypes = value;
- }
- }
-
- public ReferenceFinder CreateFinder ()
- {
- return (ReferenceFinder)CreateInstance ();
- }
-
- public override string ToString ()
- {
- return string.Format ("[ReferenceFinderCodon: SupportedMimeTypes={0}]", SupportedMimeTypes);
- }
- }
-}
+// }
+//}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/Scope.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/Scope.cs
index 68f55a9f4f..2ddc9dd417 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/Scope.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/Scope.cs
@@ -44,6 +44,10 @@ namespace MonoDevelop.Ide.FindInFiles
set;
}
+ public virtual PathMode PathMode {
+ get { return PathMode.Absolute; }
+ }
+
public abstract int GetTotalWork (FilterOptions filterOptions);
public abstract IEnumerable<FileProvider> GetFiles (ProgressMonitor monitor, FilterOptions filterOptions);
public abstract string GetDescription (FilterOptions filterOptions, string pattern, string replacePattern);
@@ -51,6 +55,10 @@ namespace MonoDevelop.Ide.FindInFiles
public class DocumentScope : Scope
{
+ public override PathMode PathMode {
+ get { return PathMode.Hidden; }
+ }
+
public override int GetTotalWork (FilterOptions filterOptions)
{
return 1;
@@ -73,6 +81,10 @@ namespace MonoDevelop.Ide.FindInFiles
public class SelectionScope : Scope
{
+ public override PathMode PathMode {
+ get { return PathMode.Hidden; }
+ }
+
public override int GetTotalWork (FilterOptions filterOptions)
{
return 1;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchCollector.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchCollector.cs
index e33d6099f4..053d55449f 100755
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchCollector.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchCollector.cs
@@ -1,272 +1,272 @@
-//
-// SearchCollector.cs
-//
-// Author:
-// Mansheng Yang <lightyang0@gmail.com>
-//
-// Copyright (c) 2012 Mansheng Yang
-//
-// 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 ICSharpCode.NRefactory.TypeSystem;
-using MonoDevelop.Core;
-using MonoDevelop.Projects;
-using MonoDevelop.Ide.TypeSystem;
-
-namespace MonoDevelop.Ide.FindInFiles
-{
- public class SearchCollector
- {
-
- public class FileList
- {
- public Project Project
- {
- get;
- private set;
- }
-
- public IProjectContent Content
- {
- get;
- private set;
- }
-
- public IEnumerable<FilePath> Files
- {
- get;
- private set;
- }
-
- public FileList (Project project, IProjectContent content, IEnumerable<FilePath> files)
- {
- Project = project;
- Content = content;
- Files = files;
- }
- }
-
- public static IEnumerable<Project> CollectProjects (Solution solution, IEnumerable<object> entities)
- {
- return new SearchCollector (solution, null, entities).CollectProjects ();
- }
-
- public static IEnumerable<FileList> CollectFiles (Project project, IEnumerable<object> entities)
- {
- return new SearchCollector (project.ParentSolution, project, entities).CollectFiles ();
- }
-
- public static IEnumerable<FileList> CollectFiles (Solution solution, IEnumerable<object> entities)
- {
- return new SearchCollector (solution, null, entities).CollectFiles ();
- }
-
- static IEnumerable<Project> GetAllReferencingProjects (Solution solution, string assemblyName)
- {
- return solution.GetAllProjects ().Where (
- project => TypeSystemService.GetCompilation (project).Assemblies.Any (a => a.AssemblyName == assemblyName));
- }
-
- static FileList CollectDeclaringFiles (IEntity entity, IEnumerable<string> fileNames)
- {
- var project = TypeSystemService.GetProject (entity);
- var paths = fileNames.Distinct().Select (p => (FilePath)p);
- return new SearchCollector.FileList (project, TypeSystemService.GetProjectContext (project), paths);
- }
-
- public static FileList CollectDeclaringFiles (IEntity entity)
- {
- if (entity is ITypeDefinition)
- return CollectDeclaringFiles (entity, (entity as ITypeDefinition).Parts.Select (p => p.Region.FileName));
- if (entity is IMethod)
- return CollectDeclaringFiles (entity, (entity as IMethod).Parts.Select (p => p.Region.FileName));
- return CollectDeclaringFiles (entity, new [] { entity.Region.FileName });
- }
-
- Project searchProject;
- bool searchProjectAdded; // if the searchProject is added, we can stop collecting
- Solution solution;
- IEnumerable<object> entities;
- bool projectOnly; // only collect projects
-
- IDictionary<Project, ISet<string>> collectedFiles = new Dictionary<Project, ISet<string>> ();
- ISet<Project> collectedProjects = new HashSet<Project> ();
-
- ISet<string> searchedAssemblies = new HashSet<string> ();
- ISet<Project> searchedProjects = new HashSet<Project> ();
-
- /// <param name="searchProject">the project to search. use to null to search the whole solution</param>
- SearchCollector (Solution solution, Project searchProject, IEnumerable<object> entities)
- {
- this.solution = solution;
- this.searchProject = searchProject;
- this.entities = entities;
- }
-
- IEnumerable<Project> CollectProjects ()
- {
- projectOnly = true;
- foreach (var o in entities) {
- var entity = o as IEntity;
- if (entity != null) {
- Collect (TypeSystemService.GetProject (entity), entity);
- continue;
- }
- var par = o as IParameter;
- if (par != null) {
- Collect (TypeSystemService.GetProject (par.Owner), par.Owner);
- continue;
- }
- }
- return collectedProjects;
- }
-
- IEnumerable<FileList> CollectFiles ()
- {
- projectOnly = false;
- foreach (var o in entities) {
- if (o is INamespace) {
- Collect (null, null);
- continue;
- }
-
- var par = o as IParameter;
- if (par != null) {
- if (par.Owner != null) {
- Collect (TypeSystemService.GetProject (par.Owner), par.Owner);
- } else {
- Collect (IdeApp.Workbench.ActiveDocument.Project, null);
- }
- } else {
- var entity = o as IEntity;
- if (entity == null)
- continue;
- Collect (TypeSystemService.GetProject (entity), entity);
- }
-
- if (searchProjectAdded) break;
- }
- foreach (var project in collectedProjects)
- yield return new FileList (project, TypeSystemService.GetProjectContext (project), project.Files.Where (f => f.BuildAction == BuildAction.Compile).Select (f => f.FilePath));
-
- foreach (var files in collectedFiles)
- yield return new FileList (files.Key, TypeSystemService.GetProjectContext (files.Key), files.Value.Select (f => (FilePath)f));
- }
-
- void AddProject (Project project)
- {
- if (project == null)
- throw new ArgumentNullException ("project");
-
- searchProjectAdded = (project == searchProject);
-
- // remove duplicate files
- if (collectedProjects.Add (project))
- collectedFiles.Remove (project);
- }
-
- void AddFiles (Project project, IEnumerable<string> files)
- {
- if (project == null)
- throw new ArgumentNullException ("project");
-
- if (collectedProjects.Contains (project))
- return;
-
- ISet<string> fileSet;
- if (!collectedFiles.TryGetValue (project, out fileSet)) {
- fileSet = new HashSet<string> ();
- collectedFiles[project] = fileSet;
- }
-
- foreach (var file in files)
- fileSet.Add (file);
- }
-
- void Collect (Project sourceProject, IEntity entity, bool searchInProject = false)
- {
- if (searchedProjects.Contains(sourceProject))
- return;
-
- if (searchProject != null && sourceProject != searchProject) {
- // searching for a entity not defined in the project
- AddProject (searchProject);
- return;
- }
-
- if (sourceProject == null) {
- if (entity == null) {
- foreach (var project in solution.GetAllProjects ())
- AddProject (project);
- return;
- }
- // entity is defined in a referenced assembly
- var assemblyName = entity.ParentAssembly.AssemblyName;
- if (!searchedAssemblies.Add (assemblyName))
- return;
- foreach (var project in GetAllReferencingProjects (solution, assemblyName))
- AddProject (project);
-
- return;
- }
-
- if (entity == null) {
- AddProject (sourceProject);
- return;
- }
-
- var declaringType = entity.DeclaringTypeDefinition;
- // TODO: possible optimization for protected
- switch (entity.Accessibility) {
- case Accessibility.Public:
- case Accessibility.Protected:
- case Accessibility.ProtectedOrInternal:
- case Accessibility.Internal:
- case Accessibility.ProtectedAndInternal:
-
- if (declaringType != null)
- Collect (sourceProject, entity.DeclaringTypeDefinition, searchInProject);
- else if (searchProject != null || searchInProject)
- AddProject (sourceProject);
- else {
- foreach (var project in ReferenceFinder.GetAllReferencingProjects (solution, sourceProject)) {
- if (entity.Accessibility == Accessibility.Internal || entity.Accessibility == Accessibility.ProtectedAndInternal) {
- var wrapper = TypeSystemService.GetProjectContentWrapper (project);
- if (wrapper == null)
- continue;
- if (!entity.ParentAssembly.InternalsVisibleTo (wrapper.Compilation.MainAssembly))
- continue;
- }
- AddProject (project);
- }
- }
- break;
- default: // private
- if (projectOnly)
- AddProject (sourceProject);
- else if (declaringType != null)
- AddFiles (sourceProject, declaringType.Parts.Select (p => p.Region.FileName));
- break;
- }
- }
- }
-}
-
+////
+//// SearchCollector.cs
+////
+//// Author:
+//// Mansheng Yang <lightyang0@gmail.com>
+////
+//// Copyright (c) 2012 Mansheng Yang
+////
+//// 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 ICSharpCode.NRefactory.TypeSystem;
+//using MonoDevelop.Core;
+//using MonoDevelop.Projects;
+//using MonoDevelop.Ide.TypeSystem;
+//
+//namespace MonoDevelop.Ide.FindInFiles
+//{
+// public class SearchCollector
+// {
+//
+// public class FileList
+// {
+// public Project Project
+// {
+// get;
+// private set;
+// }
+//
+// public IProjectContent Content
+// {
+// get;
+// private set;
+// }
+//
+// public IEnumerable<FilePath> Files
+// {
+// get;
+// private set;
+// }
+//
+// public FileList (Project project, IProjectContent content, IEnumerable<FilePath> files)
+// {
+// Project = project;
+// Content = content;
+// Files = files;
+// }
+// }
+//
+// public static IEnumerable<Project> CollectProjects (Solution solution, IEnumerable<object> entities)
+// {
+// return new SearchCollector (solution, null, entities).CollectProjects ();
+// }
+//
+// public static IEnumerable<FileList> CollectFiles (Project project, IEnumerable<object> entities)
+// {
+// return new SearchCollector (project.ParentSolution, project, entities).CollectFiles ();
+// }
+//
+// public static IEnumerable<FileList> CollectFiles (Solution solution, IEnumerable<object> entities)
+// {
+// return new SearchCollector (solution, null, entities).CollectFiles ();
+// }
+//
+// static IEnumerable<Project> GetAllReferencingProjects (Solution solution, string assemblyName)
+// {
+// return solution.GetAllProjects ().Where (
+// project => TypeSystemService.GetCompilation (project).Assemblies.Any (a => a.AssemblyName == assemblyName));
+// }
+//
+// static FileList CollectDeclaringFiles (IEntity entity, IEnumerable<string> fileNames)
+// {
+// var project = TypeSystemService.GetProject (entity);
+// var paths = fileNames.Distinct().Select (p => (FilePath)p);
+// return new SearchCollector.FileList (project, TypeSystemService.GetProjectContext (project), paths);
+// }
+//
+// public static FileList CollectDeclaringFiles (IEntity entity)
+// {
+// if (entity is ITypeDefinition)
+// return CollectDeclaringFiles (entity, (entity as ITypeDefinition).Parts.Select (p => p.Region.FileName));
+// if (entity is IMethod)
+// return CollectDeclaringFiles (entity, (entity as IMethod).Parts.Select (p => p.Region.FileName));
+// return CollectDeclaringFiles (entity, new [] { entity.Region.FileName });
+// }
+//
+// Project searchProject;
+// bool searchProjectAdded; // if the searchProject is added, we can stop collecting
+// Solution solution;
+// IEnumerable<object> entities;
+// bool projectOnly; // only collect projects
+//
+// IDictionary<Project, ISet<string>> collectedFiles = new Dictionary<Project, ISet<string>> ();
+// ISet<Project> collectedProjects = new HashSet<Project> ();
+//
+// ISet<string> searchedAssemblies = new HashSet<string> ();
+// ISet<Project> searchedProjects = new HashSet<Project> ();
+//
+// /// <param name="searchProject">the project to search. use to null to search the whole solution</param>
+// SearchCollector (Solution solution, Project searchProject, IEnumerable<object> entities)
+// {
+// this.solution = solution;
+// this.searchProject = searchProject;
+// this.entities = entities;
+// }
+//
+// IEnumerable<Project> CollectProjects ()
+// {
+// projectOnly = true;
+// foreach (var o in entities) {
+// var entity = o as IEntity;
+// if (entity != null) {
+// Collect (TypeSystemService.GetProject (entity), entity);
+// continue;
+// }
+// var par = o as IParameter;
+// if (par != null) {
+// Collect (TypeSystemService.GetProject (par.Owner), par.Owner);
+// continue;
+// }
+// }
+// return collectedProjects;
+// }
+//
+// IEnumerable<FileList> CollectFiles ()
+// {
+// projectOnly = false;
+// foreach (var o in entities) {
+// if (o is INamespace) {
+// Collect (null, null);
+// continue;
+// }
+//
+// var par = o as IParameter;
+// if (par != null) {
+// if (par.Owner != null) {
+// Collect (TypeSystemService.GetProject (par.Owner), par.Owner);
+// } else {
+// Collect (IdeApp.Workbench.ActiveDocument.Project, null);
+// }
+// } else {
+// var entity = o as IEntity;
+// if (entity == null)
+// continue;
+// Collect (TypeSystemService.GetProject (entity), entity);
+// }
+//
+// if (searchProjectAdded) break;
+// }
+// foreach (var project in collectedProjects)
+// yield return new FileList (project, TypeSystemService.GetProjectContext (project), project.Files.Where (f => f.BuildAction == BuildAction.Compile).Select (f => f.FilePath));
+//
+// foreach (var files in collectedFiles)
+// yield return new FileList (files.Key, TypeSystemService.GetProjectContext (files.Key), files.Value.Select (f => (FilePath)f));
+// }
+//
+// void AddProject (Project project)
+// {
+// if (project == null)
+// throw new ArgumentNullException ("project");
+//
+// searchProjectAdded = (project == searchProject);
+//
+// // remove duplicate files
+// if (collectedProjects.Add (project))
+// collectedFiles.Remove (project);
+// }
+//
+// void AddFiles (Project project, IEnumerable<string> files)
+// {
+// if (project == null)
+// throw new ArgumentNullException ("project");
+//
+// if (collectedProjects.Contains (project))
+// return;
+//
+// ISet<string> fileSet;
+// if (!collectedFiles.TryGetValue (project, out fileSet)) {
+// fileSet = new HashSet<string> ();
+// collectedFiles[project] = fileSet;
+// }
+//
+// foreach (var file in files)
+// fileSet.Add (file);
+// }
+//
+// void Collect (Project sourceProject, IEntity entity, bool searchInProject = false)
+// {
+// if (searchedProjects.Contains(sourceProject))
+// return;
+//
+// if (searchProject != null && sourceProject != searchProject) {
+// // searching for a entity not defined in the project
+// AddProject (searchProject);
+// return;
+// }
+//
+// if (sourceProject == null) {
+// if (entity == null) {
+// foreach (var project in solution.GetAllProjects ())
+// AddProject (project);
+// return;
+// }
+// // entity is defined in a referenced assembly
+// var assemblyName = entity.ParentAssembly.AssemblyName;
+// if (!searchedAssemblies.Add (assemblyName))
+// return;
+// foreach (var project in GetAllReferencingProjects (solution, assemblyName))
+// AddProject (project);
+//
+// return;
+// }
+//
+// if (entity == null) {
+// AddProject (sourceProject);
+// return;
+// }
+//
+// var declaringType = entity.DeclaringTypeDefinition;
+// // TODO: possible optimization for protected
+// switch (entity.Accessibility) {
+// case Accessibility.Public:
+// case Accessibility.Protected:
+// case Accessibility.ProtectedOrInternal:
+// case Accessibility.Internal:
+// case Accessibility.ProtectedAndInternal:
+//
+// if (declaringType != null)
+// Collect (sourceProject, entity.DeclaringTypeDefinition, searchInProject);
+// else if (searchProject != null || searchInProject)
+// AddProject (sourceProject);
+// else {
+// foreach (var project in ReferenceFinder.GetAllReferencingProjects (solution, sourceProject)) {
+// if (entity.Accessibility == Accessibility.Internal || entity.Accessibility == Accessibility.ProtectedAndInternal) {
+// var wrapper = TypeSystemService.GetProjectContentWrapper (project);
+// if (wrapper == null)
+// continue;
+// if (!entity.ParentAssembly.InternalsVisibleTo (wrapper.Compilation.MainAssembly))
+// continue;
+// }
+// AddProject (project);
+// }
+// }
+// break;
+// default: // private
+// if (projectOnly)
+// AddProject (sourceProject);
+// else if (declaringType != null)
+// AddFiles (sourceProject, declaringType.Parts.Select (p => p.Region.FileName));
+// break;
+// }
+// }
+// }
+//}
+//
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchProgressMonitor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchProgressMonitor.cs
index 69abc8f88f..aeed4d6e8d 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchProgressMonitor.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchProgressMonitor.cs
@@ -52,7 +52,11 @@ namespace MonoDevelop.Ide.FindInFiles
{
outputPad.BasePath = path;
}
-
+
+ public PathMode PathMode {
+ set { outputPad.PathMode = value; }
+ }
+
public void ReportResult (SearchResult result)
{
DispatchService.GuiDispatch (delegate {
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResult.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResult.cs
index 0c70cd1b08..651aed9054 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResult.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResult.cs
@@ -26,19 +26,21 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-using Mono.TextEditor.Highlighting;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Ide.Editor.Highlighting;
+using System.Collections.Generic;
using MonoDevelop.Projects;
using System.Collections.Generic;
-using System;
-
+using System;
+
namespace MonoDevelop.Ide.FindInFiles
{
public class SearchResult
{
public virtual FileProvider FileProvider { get; private set; }
- public int Offset { get; set; }
- public int Length { get; set; }
+ public int Offset { get; set; }
+ public int Length { get; set; }
public virtual string FileName {
get {
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResultPad.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResultPad.cs
index 0a9fe845e0..ad0acbb87e 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResultPad.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResultPad.cs
@@ -82,6 +82,12 @@ namespace MonoDevelop.Ide.FindInFiles
widget.BasePath = value;
}
}
+
+ internal PathMode PathMode {
+ set {
+ widget.PathMode = value;
+ }
+ }
public SearchResultPad (int instanceNum)
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResultWidget.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResultWidget.cs
index d485a97a06..3a7b9b932f 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResultWidget.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResultWidget.cs
@@ -30,9 +30,7 @@ using System.Linq;
using Gdk;
using Gtk;
-using Mono.TextEditor;
-using Mono.TextEditor.Highlighting;
using System.Collections.Generic;
using MonoDevelop.Core;
using System.Text;
@@ -43,6 +41,10 @@ using MonoDevelop.Ide.Navigation;
using MonoDevelop.Ide.Gui.Components;
using MonoDevelop.Components;
using System.Threading;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Core.Text;
+using MonoDevelop.Ide.Editor.Highlighting;
+
namespace MonoDevelop.Ide.FindInFiles
{
@@ -57,23 +59,30 @@ namespace MonoDevelop.Ide.FindInFiles
const int SearchResultColumn = 0;
const int DidReadColumn = 1;
- Mono.TextEditor.Highlighting.ColorScheme highlightStyle;
+ ColorScheme highlightStyle;
ScrolledWindow scrolledwindowLogView;
PadTreeView treeviewSearchResults;
Label labelStatus;
TextView textviewLog;
-
+ TreeViewColumn pathColumn;
+
public string BasePath {
get;
set;
}
-
+
public CancellationTokenSource CancellationTokenSource {
get;
set;
}
-
+
+ internal PathMode PathMode {
+ set {
+ pathColumn.Visible = (value != PathMode.Hidden);
+ }
+ }
+
public bool AllowReuse {
get {
return !buttonStop.Sensitive && !buttonPin.Active;
@@ -160,8 +169,7 @@ namespace MonoDevelop.Ide.FindInFiles
textColumn.Sizing = TreeViewColumnSizing.Fixed;
textColumn.FixedWidth = 300;
-
- TreeViewColumn pathColumn = treeviewSearchResults.AppendColumn (GettextCatalog.GetString ("Path"),
+ pathColumn = treeviewSearchResults.AppendColumn (GettextCatalog.GetString ("Path"),
renderer, ResultPathDataFunc);
pathColumn.SortColumnId = 3;
pathColumn.Resizable = true;
@@ -281,7 +289,10 @@ namespace MonoDevelop.Ide.FindInFiles
treeviewSearchResults.ScrollToPoint (0, 0);
ResultCount = 0;
- documents = new Dictionary<string, TextDocument> ();
+ foreach (var doc in documents) {
+ doc.Value.Dispose ();
+ }
+ documents = new Dictionary<string, TextEditor> ();
store.Clear ();
labelStatus.Text = "";
textviewLog.Buffer.Clear ();
@@ -295,13 +306,13 @@ namespace MonoDevelop.Ide.FindInFiles
static Color AdjustColor (Color baseColor, Color color)
{
- double b1 = Mono.TextEditor.HslColor.Brightness (color);
- double b2 = Mono.TextEditor.HslColor.Brightness (baseColor);
+ double b1 = HslColor.Brightness (color);
+ double b2 = HslColor.Brightness (baseColor);
double delta = Math.Abs (b1 - b2);
if (delta < 0.1) {
- Mono.TextEditor.HslColor color1 = color;
+ HslColor color1 = color;
color1.L -= 0.5;
- if (Math.Abs (Mono.TextEditor.HslColor.Brightness (color1) - b2) < delta) {
+ if (Math.Abs (HslColor.Brightness (color1) - b2) < delta) {
color1 = color;
color1.L += 0.5;
}
@@ -335,7 +346,7 @@ namespace MonoDevelop.Ide.FindInFiles
Color color = Color.Zero;
if (Color.Parse(colorStr, ref color))
- colorStr = SyntaxMode.ColorToPangoMarkup(AdjustColor(baseColor, color));
+ colorStr = ColorToPangoMarkup(AdjustColor(baseColor, color));
result.Append (colorStr);
idx = markup.IndexOf ("foreground=\"", idx, StringComparison.Ordinal);
@@ -343,8 +354,11 @@ namespace MonoDevelop.Ide.FindInFiles
result.Append (markup.Substring (offset, markup.Length - offset));
return result.ToString ();
}
-
- void DoPopupMenu (EventButton evt)
+ public static string ColorToPangoMarkup (Gdk.Color color)
+ {
+ return string.Format ("#{0:X2}{1:X2}{2:X2}", color.Red >> 8, color.Green >> 8, color.Blue >> 8);
+ }
+ void DoPopupMenu (Gdk.EventButton evt)
{
IdeApp.CommandService.ShowContextMenu (this.treeviewSearchResults, evt, new CommandEntrySet {
new CommandEntry (ViewCommands.Open),
@@ -493,6 +507,12 @@ namespace MonoDevelop.Ide.FindInFiles
pathRenderer.Markup = projectNameMarkup;
}
+ static int TranslateIndexToUTF8 (string text, int index)
+ {
+ byte[] bytes = Encoding.UTF8.GetBytes (text);
+ return Encoding.UTF8.GetString (bytes, 0, index).Length;
+ }
+
void ResultTextDataFunc (TreeViewColumn column, CellRenderer cell, TreeModel model, TreeIter iter)
{
if (TreeIter.Zero.Equals (iter))
@@ -516,31 +536,28 @@ namespace MonoDevelop.Ide.FindInFiles
if (searchResult.Markup == null) {
if (searchResult.LineNumber <= 0)
searchResult.LineNumber = doc.OffsetToLineNumber (searchResult.Offset);
- DocumentLine line = doc.GetLine (searchResult.LineNumber);
+ var line = doc.GetLine (searchResult.LineNumber);
if (line == null) {
textMarkup = "Invalid line number " + searchResult.LineNumber + " from offset: " + searchResult.Offset;
goto end;
}
int indent = line.GetIndentation (doc).Length;
- var data = new Mono.TextEditor.TextEditorData (doc);
- data.ColorStyle = highlightStyle;
+ var data =TextEditorFactory.CreateNewEditor (doc);
var lineText = doc.GetTextAt (line.Offset + indent, line.Length - indent);
int col = searchResult.Offset - line.Offset - indent;
// search result contained part of the indent.
if (col + searchResult.Length < lineText.Length)
lineText = doc.GetTextAt (line.Offset, line.Length);
- var markup = doc.SyntaxMode != null ?
- data.GetMarkup (line.Offset + indent, line.Length - indent, true, !isSelected, false) :
- GLib.Markup.EscapeText (lineText);
- searchResult.Markup = AdjustColors (markup.Replace ("\t", new string (' ', TextEditorOptions.DefaultOptions.TabSize)));
+ var markup = data.GetPangoMarkup (line.Offset + indent, line.Length - indent);
+ searchResult.Markup = AdjustColors (markup.Replace ("\t", new string (' ', data.Options.TabSize)));
if (col >= 0) {
uint start;
uint end;
try {
- start = (uint)TextViewMargin.TranslateIndexToUTF8 (lineText, col);
- end = (uint)TextViewMargin.TranslateIndexToUTF8 (lineText, Math.Min (lineText.Length, col + searchResult.Length));
+ start = (uint)TranslateIndexToUTF8 (lineText, col);
+ end = (uint)TranslateIndexToUTF8 (lineText, Math.Min (lineText.Length, col + searchResult.Length));
} catch (Exception e) {
LoggingService.LogError ("Exception while translating index to utf8 (column was:" + col + " search result length:" + searchResult.Length + " line text:" + lineText + ")", e);
return;
@@ -550,17 +567,16 @@ namespace MonoDevelop.Ide.FindInFiles
}
}
-
try {
textMarkup = searchResult.Markup;
if (!isSelected) {
var searchColor = searchResult.GetBackgroundMarkerColor (highlightStyle).Color;
- double b1 = Mono.TextEditor.HslColor.Brightness (searchColor);
- double b2 = Mono.TextEditor.HslColor.Brightness (AdjustColor (Style.Base (StateType.Normal), (Mono.TextEditor.HslColor)highlightStyle.PlainText.Foreground));
+ double b1 = HslColor.Brightness (searchColor);
+ double b2 = HslColor.Brightness (AdjustColor (Style.Base (StateType.Normal), (HslColor)highlightStyle.PlainText.Foreground));
double delta = Math.Abs (b1 - b2);
if (delta < 0.1) {
- Mono.TextEditor.HslColor color1 = highlightStyle.SearchResult.Color;
+ var color1 = highlightStyle.SearchResult.Color;
if (color1.L + 0.5 > 1.0) {
color1.L -= 0.5;
} else {
@@ -626,18 +642,18 @@ namespace MonoDevelop.Ide.FindInFiles
- Dictionary<string, TextDocument> documents = new Dictionary<string, TextDocument> ();
+ Dictionary<string, TextEditor> documents = new Dictionary<string, TextEditor> ();
- TextDocument GetDocument (SearchResult result)
+ TextEditor GetDocument (SearchResult result)
{
- TextDocument doc;
+ TextEditor doc;
if (!documents.TryGetValue (result.FileName, out doc)) {
var content = result.FileProvider.ReadString ();
if (content == null)
return null;
- doc = TextDocument.CreateImmutableDocument (content);
- doc.MimeType = DesktopService.GetMimeTypeForUri (result.FileName);
-
+
+ doc = TextEditorFactory.CreateNewEditor (TextEditorFactory.CreateNewReadonlyDocument (new StringTextSource (content), result.FileName, DesktopService.GetMimeTypeForUri (result.FileName)));
+
documents [result.FileName] = doc;
}
return doc;
@@ -672,7 +688,7 @@ namespace MonoDevelop.Ide.FindInFiles
{
var result = store.GetValue (iter, SearchResultColumn) as SearchResult;
if (result != null) {
- DocumentLocation loc = GetLocation (result);
+ var loc = GetLocation (result);
store.SetValue (iter, DidReadColumn, true);
IdeApp.Workbench.OpenDocument (result.FileName, loc.Line, loc.Column);
}
@@ -684,7 +700,7 @@ namespace MonoDevelop.Ide.FindInFiles
if (doc == null)
return DocumentLocation.Empty;
int lineNr = doc.OffsetToLineNumber (searchResult.Offset);
- DocumentLine line = doc.GetLine (lineNr);
+ var line = doc.GetLine (lineNr);
if (line == null)
return DocumentLocation.Empty;
return new DocumentLocation (lineNr, searchResult.Offset - line.Offset + 1);
@@ -717,11 +733,11 @@ namespace MonoDevelop.Ide.FindInFiles
var result = store.GetValue (iter, SearchResultColumn) as SearchResult;
if (result == null)
continue;
- DocumentLocation loc = GetLocation (result);
+ var loc = GetLocation (result);
var doc = GetDocument (result);
if (doc == null)
continue;
- DocumentLine line = doc.GetLine (loc.Line);
+ var line = doc.GetLine (loc.Line);
sb.AppendFormat ("{0} ({1}, {2}):{3}", result.FileName, loc.Line, loc.Column, doc.GetTextAt (line.Offset, line.Length));
sb.AppendLine ();
@@ -789,7 +805,7 @@ namespace MonoDevelop.Ide.FindInFiles
var doc = GetDocument (searchResult);
if (doc == null)
return null;
- DocumentLocation location = doc.OffsetToLocation (searchResult.Offset);
+ var location = doc.OffsetToLocation (searchResult.Offset);
return new SearchTextFileNavigationPoint (searchResult.FileName, location.Line, location.Column);
}
@@ -805,11 +821,11 @@ namespace MonoDevelop.Ide.FindInFiles
if (doc == null)
return null;
- var buf = doc.GetContent<IEditableTextBuffer> ();
+ var buf = doc.Editor;
if (buf != null) {
doc.DisableAutoScroll ();
buf.RunWhenLoaded (() => {
- buf.SetCaretTo (Math.Max (Line, 1), Math.Max (Column, 1));
+ buf.SetCaretLocation (Math.Max (Line, 1), Math.Max (Column, 1));
});
}
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 6d767b6f30..8ac94124be 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
@@ -30,15 +30,8 @@
//#define TREE_VERIFY_INTEGRITY
using System;
-using System.IO;
-using System.ComponentModel;
-using System.Drawing;
-using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
-using System.Collections.Specialized;
-using System.Xml;
-using System.Resources;
using System.Text;
using Mono.Addins;
@@ -48,7 +41,6 @@ using MonoDevelop.Ide.Commands;
using MonoDevelop.Components.Commands;
using MonoDevelop.Ide.Gui.Pads;
using MonoDevelop.Projects.Extensions;
-using Mono.TextEditor;
using System.Linq;
using MonoDevelop.Ide.Tasks;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/PadTreeView.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/PadTreeView.cs
index fed5414ad4..42da610592 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/PadTreeView.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/PadTreeView.cs
@@ -26,7 +26,6 @@
using System;
using Gtk;
-using Mono.TextEditor;
namespace MonoDevelop.Ide.Gui.Components
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/DocumentStateTracker.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/DocumentStateTracker.cs
index 45303e9457..b254fac993 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/DocumentStateTracker.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/DocumentStateTracker.cs
@@ -30,7 +30,8 @@
using System;
using System.Collections.Generic;
-using Mono.TextEditor;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Core.Text;
namespace MonoDevelop.Ide.Gui.Content
{
@@ -40,25 +41,25 @@ namespace MonoDevelop.Ide.Gui.Content
T currentEngine;
Stack<T> cachedEngines = new Stack<T> ();
- TextEditorData editor;
+ TextEditor editor;
- public DocumentStateTracker (T engine, TextEditorData editor)
+ public DocumentStateTracker (T engine, TextEditor editor)
{
this.currentEngine = engine;
this.editor = editor;
- editor.Document.TextReplaced += textChanged;
+ editor.TextChanged += textChanged;
}
public void Dispose ()
{
- editor.Document.TextReplaced -= textChanged;
+ editor.TextChanged -= textChanged;
}
public T Engine {
get { return currentEngine; }
}
- void textChanged (object sender, DocumentChangeEventArgs args)
+ void textChanged (object sender, TextChangeEventArgs args)
{
if (args.Offset< currentEngine.Position)
ResetEngineToPosition (args.Offset);
@@ -85,7 +86,7 @@ namespace MonoDevelop.Ide.Gui.Content
}
public void UpdateEngine ()
{
- UpdateEngine (editor.Caret.Offset);
+ UpdateEngine (editor.CaretOffset);
}
//Makes sure that the smart indent engine's cursor has caught up with the
@@ -112,7 +113,7 @@ namespace MonoDevelop.Ide.Gui.Content
// get the engine caught up
int nextSave = (cachedEngines.Count == 0)? BUFFER_SIZE : cachedEngines.Peek ().Position + BUFFER_SIZE;
if (currentEngine.Position + 1 == position) {
- char ch = editor.Document.GetCharAt (currentEngine.Position);
+ char ch = editor.GetCharAt (currentEngine.Position);
currentEngine.Push (ch);
ConsoleWrite ("pushing character '{0}'", ch);
if (currentEngine.Position == nextSave)
@@ -124,7 +125,7 @@ namespace MonoDevelop.Ide.Gui.Content
int endCut = currentEngine.Position + BUFFER_SIZE;
if (endCut > position)
endCut = position;
- string buffer = editor.Document.GetTextBetween (currentEngine.Position, endCut);
+ string buffer = editor.GetTextBetween (currentEngine.Position, endCut);
ConsoleWrite ("getting buffer between {0} and {1}" /* '{2}'"*/, currentEngine.Position, endCut - 1, buffer);
foreach (char ch in buffer) {
currentEngine.Push (ch);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/IEditableTextBuffer.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/IEditableTextBuffer.cs
deleted file mode 100644
index c606819800..0000000000
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/IEditableTextBuffer.cs
+++ /dev/null
@@ -1,70 +0,0 @@
-//
-// IEditableTextBuffer.cs
-//
-// Author:
-// Mike Krüger <mkrueger@novell.com>
-//
-// Copyright (C) 2008 Novell, Inc (http://www.novell.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.Projects.Text;
-
-namespace MonoDevelop.Ide.Gui.Content
-{
- public interface IEditableTextBuffer : ITextBuffer, IEditableTextFile, IUndoHandler
- {
- int LineCount { get; }
- void SetCaretTo (int line, int column);
- void SetCaretTo (int line, int column, bool highlightLine);
- void SetCaretTo (int line, int column, bool highlightLine, bool centerCaret);
- bool HasInputFocus { get; }
-
- void RunWhenLoaded (System.Action action);
-
- event EventHandler CaretPositionSet;
- event EventHandler<TextChangedEventArgs> TextChanged;
- }
-
- public class TextChangedEventArgs : System.EventArgs
- {
- int startIndex;
- public int StartIndex {
- get {
- return startIndex;
- }
- }
-
- int endIndex;
- public int EndIndex {
- get {
- return endIndex;
- }
- }
-
- public TextChangedEventArgs (int startIndex, int endIndex)
- {
- this.startIndex = startIndex;
- this.endIndex = endIndex;
- }
- }
-}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/IEncodedTextContent.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/IEncodedTextContent.cs
deleted file mode 100644
index 53f2e681e5..0000000000
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/IEncodedTextContent.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-// IEncodedTextContent.cs
-//
-// Author:
-// Lluis Sanchez Gual
-//
-// Copyright (C) 2006 Novell, Inc (http://www.novell.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.Text;
-
-namespace MonoDevelop.Ide.Gui.Content
-{
- public interface IEncodedTextContent
- {
- void Load (string fileName, Encoding encoding);
- void Save (string fileName, Encoding encoding);
-
- Encoding SourceEncoding { get; }
- }
-}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/IFoldable.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/IFoldable.cs
index 2e163bc941..2775cfd06e 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/IFoldable.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/IFoldable.cs
@@ -30,7 +30,7 @@ using System;
namespace MonoDevelop.Ide.Gui.Content
{
- public interface IFoldable
+ interface IFoldable
{
void ToggleAllFoldings ();
void FoldDefinitions ();
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/IOpenNamedElementHandler.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/IOpenNamedElementHandler.cs
index 306e4b4fab..e7b6c33768 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/IOpenNamedElementHandler.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/IOpenNamedElementHandler.cs
@@ -30,8 +30,9 @@ using System;
namespace MonoDevelop.Ide.Gui.Content
{
- public interface IOpenNamedElementHandler
+ interface IOpenNamedElementHandler
{
- void Open (ICSharpCode.NRefactory.TypeSystem.INamedElement element);
+ void Open (Microsoft.CodeAnalysis.ISymbol element);
+ void Open (string documentationCommentId);
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/ISmartIndenter.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/ISmartIndenter.cs
deleted file mode 100644
index dfeb37a083..0000000000
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/ISmartIndenter.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-//
-// ISmartIndenter.cs
-//
-// Author:
-// Michael Hutchinson <mhutchinson@novell.com>
-//
-// Copyright (C) 2008 Novell, Inc (http://www.novell.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;
-
-namespace MonoDevelop.Ide.Gui.Content
-{
-
- public interface ISmartIndenter
- {
- Indent GetIndent (int line);
- Indent GetAutoTriggeredReindent (int insertionOffset, int length);
- }
-
- public struct Indent
- {
- int depth, alignment;
- bool isRelative;
-
- public Indent (int depth, int alignment)
- : this (depth, alignment, false)
- {
- }
-
- public Indent (int depth, int alignment, bool isRelative)
- {
- this.depth = depth;
- this.alignment = alignment;
- this.isRelative = isRelative;
- }
-
- public int Depth { get { return depth; } }
- public int Alignment { get { return alignment; } }
- public bool IsRelativeToPreviousLine { get { return isRelative; } }
-
- public bool IsZero { get { return Depth == 0 && Alignment == 0; } }
- }
-}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/ITextBuffer.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/ITextBuffer.cs
deleted file mode 100644
index 02c2834d25..0000000000
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/ITextBuffer.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-//
-// ITextBuffer.cs
-//
-// Author:
-// Lluis Sanchez Gual
-//
-// Copyright (C) 2005 Novell, Inc (http://www.novell.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.Projects.Text;
-
-namespace MonoDevelop.Ide.Gui.Content
-{
- public interface ITextBuffer: ITextFile
- {
- //FIXME: this should be a method, it's relatively expensive
- string SelectedText { get; set; }
-
- int CursorPosition { get; set; }
-
- int SelectionStartPosition { get; }
- int SelectionEndPosition { get; }
-
- void Select (int startPosition, int endPosition);
- void ShowPosition (int position);
- }
-}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/ITextEditorResolver.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/ITextEditorResolver.cs
index 5c1006a192..6d6ec4ab16 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/ITextEditorResolver.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/ITextEditorResolver.cs
@@ -26,39 +26,26 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-using System;
using System.Collections.Generic;
using System.Linq;
-using Mono.TextEditor;
using Mono.Addins;
-using ICSharpCode.NRefactory.TypeSystem;
-using ICSharpCode.NRefactory.Semantics;
-using MonoDevelop.Ide.TypeSystem;
+using Microsoft.CodeAnalysis;
+using MonoDevelop.Ide.Editor;
namespace MonoDevelop.Ide.Gui.Content
{
public interface ITextEditorResolver
{
- ResolveResult GetLanguageItem (int offset);
- ResolveResult GetLanguageItem (int offset, string expression);
+ ISymbol GetLanguageItem (int offset);
+ ISymbol GetLanguageItem (int offset, string expression);
}
public interface ITextEditorResolverProvider
{
- ResolveResult GetLanguageItem (MonoDevelop.Ide.Gui.Document document, int offset, out DomRegion expressionRegion);
- ResolveResult GetLanguageItem (MonoDevelop.Ide.Gui.Document document, int offset, string identifier);
-
- string CreateTooltip (MonoDevelop.Ide.Gui.Document document, int offset, ResolveResult result, string errorInformations, Gdk.ModifierType modifierState);
-
- }
-
- public interface ITextEditorMemberPositionProvider
- {
- IUnresolvedTypeDefinition GetTypeAt (int offset);
- IUnresolvedMember GetMemberAt (int offset);
+ ISymbol GetLanguageItem (Document document, int offset, out DocumentRegion expressionRegion);
+ ISymbol GetLanguageItem (Document document, int offset, string identifier);
}
-
-
+
public static class TextEditorResolverService
{
static List<TextEditorResolverProviderCodon> providers = new List<TextEditorResolverProviderCodon> ();
@@ -85,16 +72,16 @@ namespace MonoDevelop.Ide.Gui.Content
return codon.CreateResolver ();
}
- public static ResolveResult GetLanguageItem (this MonoDevelop.Ide.Gui.Document document, int offset, out DomRegion expressionRegion)
- {
- if (document == null)
+ public static ISymbol GetLanguageItem (this Document document, int offset, out DocumentRegion expressionRegion)
+ {
+ if (document == null)
throw new System.ArgumentNullException ("document");
- var textEditorResolver = TextEditorResolverService.GetProvider (document.Editor.Document.MimeType);
+ var textEditorResolver = TextEditorResolverService.GetProvider (document.Editor.MimeType);
if (textEditorResolver != null) {
return textEditorResolver.GetLanguageItem (document, offset, out expressionRegion);
}
- expressionRegion = DomRegion.Empty;
+ expressionRegion = DocumentRegion.Empty;
return null;
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/TextEditorExtension.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/TextEditorExtension.cs
deleted file mode 100644
index 276c61db99..0000000000
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/TextEditorExtension.cs
+++ /dev/null
@@ -1,181 +0,0 @@
-// TextEditorExtension.cs
-//
-// Author:
-// Lluis Sanchez Gual
-//
-// Copyright (c) 2007 Novell, Inc (http://www.novell.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.Projects;
-using MonoDevelop.Ide.CodeCompletion;
-using MonoDevelop.Components.Commands;
-using MonoDevelop.Ide.Commands;
-using MonoDevelop.Core;
-using Mono.TextEditor;
-using ICSharpCode.NRefactory.TypeSystem;
-using MonoDevelop.Ide.TypeSystem;
-
-namespace MonoDevelop.Ide.Gui.Content
-{
- public class TextEditorExtension : ITextEditorExtension, ICommandRouter
- {
- internal protected Document document;
-
- public void Initialize (Document document)
- {
- if (this.document != null)
- throw new InvalidOperationException ("Extension is already initialized.");
- this.document = document;
- Initialize ();
- }
-
- public ITextEditorExtension Next {
- get;
- set;
- }
-
- protected Document Document {
- get { return document; }
- }
-
- protected TextEditorData Editor {
- get { return document != null ? document.Editor : null; }
- }
-
- protected FilePath FileName {
- get {
- IViewContent view = document.Window.ViewContent;
- return view.IsUntitled ? view.UntitledName : view.ContentName;
- }
- }
-
- protected IProjectContent GetParserContext ()
- {
- CheckInitialized ();
-
- IViewContent view = document.Window.ViewContent;
- string file = view.IsUntitled ? view.UntitledName : view.ContentName;
- Project project = view.Project;
-
- if (project != null)
- return TypeSystemService.GetProjectContext (project);
- return TypeSystemService.GetContext (file, Document.Editor.Document.MimeType, Document.Editor.Text);
- }
-
- protected Ambience GetAmbience ()
- {
- CheckInitialized ();
-
- IViewContent view = document.Window.ViewContent;
- string file = view.IsUntitled ? view.UntitledName : view.ContentName;
- return AmbienceService.GetAmbienceForFile (file);
- }
-
- public virtual bool ExtendsEditor (Document doc, IEditableTextBuffer editor)
- {
- return true;
- }
-
- // When a key is pressed, and before the key is processed by the editor, this method will be invoked.
- // Return true if the key press should be processed by the editor.
- public virtual bool KeyPress (Gdk.Key key, char keyChar, Gdk.ModifierType modifier)
- {
- CheckInitialized ();
-
- if (Next == null)
- return true;
- else
- return Next.KeyPress (key, keyChar, modifier);
- }
-
- public virtual void CursorPositionChanged ()
- {
- CheckInitialized ();
-
- if (Next != null)
- Next.CursorPositionChanged ();
- }
-
- public virtual void TextChanged (int startIndex, int endIndex)
- {
- if (Next != null)
- Next.TextChanged (startIndex, endIndex);
- }
-
- public virtual void Initialize ()
- {
- CheckInitialized ();
-
- TextEditorExtension next = Next as TextEditorExtension;
- if (next != null)
- next.Initialize ();
- }
-
- public virtual void Dispose ()
- {
- }
-
- void CheckInitialized ()
- {
- if (document == null)
- throw new InvalidOperationException ("Editor extension not yet initialized");
- }
-
- object ITextEditorExtension.GetExtensionCommandTarget ()
- {
- return this;
- }
-
- object ICommandRouter.GetNextCommandTarget ()
- {
- if (Next != null)
- return Next.GetExtensionCommandTarget ();
- else
- return null;
- }
- }
-
- public interface ITextEditorExtension : IDisposable
- {
- ITextEditorExtension Next {
- get;
- }
-
- bool KeyPress (Gdk.Key key, char keyChar, Gdk.ModifierType modifier);
- void CursorPositionChanged ();
- void TextChanged (int startIndex, int endIndex);
-
- // Return the object that is going to process commands, or null
- // if commands don't need custom processing
- object GetExtensionCommandTarget ();
- }
-
- class TextEditorExtensionMarker: TextEditorExtension
- {
- public override bool ExtendsEditor (Document doc, IEditableTextBuffer editor)
- {
- return false;
- }
- }
-}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/ClassNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/ClassNodeBuilder.cs
index 033a61ac81..a84c2b17c3 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/ClassNodeBuilder.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/ClassNodeBuilder.cs
@@ -61,9 +61,9 @@ namespace MonoDevelop.Ide.Gui.Pads.ClassPad
public override void BuildNode (ITreeBuilder treeBuilder, object dataObject, NodeInfo nodeInfo)
{
- ClassData classData = dataObject as ClassData;
- nodeInfo.Label = AmbienceService.DefaultAmbience.GetString (classData.Class.GetDefinition (), OutputFlags.ClassBrowserEntries | OutputFlags.IncludeMarkup);
- nodeInfo.Icon = Context.GetIcon (classData.Class.GetStockIcon ());
+ // ClassData classData = dataObject as ClassData;
+ // nodeInfo.Label = Ambience.DefaultAmbience.GetString (classData.Class.GetDefinition (), OutputFlags.ClassBrowserEntries | OutputFlags.IncludeMarkup);
+ // nodeInfo.Icon = Context.GetIcon (classData.Class.GetStockIcon ());
}
/*
private string GetNameWithGenericParameters (IType c)
@@ -137,8 +137,8 @@ namespace MonoDevelop.Ide.Gui.Pads.ClassPad
{
public override void ActivateItem ()
{
- ClassData cls = CurrentNode.DataItem as ClassData;
- IdeApp.ProjectOperations.JumpToDeclaration (cls.Class, true);
+// ClassData cls = CurrentNode.DataItem as ClassData;
+// IdeApp.ProjectOperations.JumpToDeclaration (cls.Class, true);
}
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/EventNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/EventNodeBuilder.cs
index 425527694a..9f5a0a5910 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/EventNodeBuilder.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/EventNodeBuilder.cs
@@ -49,9 +49,9 @@ namespace MonoDevelop.Ide.Gui.Pads.ClassPad
public override void BuildNode (ITreeBuilder treeBuilder, object dataObject, NodeInfo nodeInfo)
{
- IEvent data = dataObject as IEvent;
- nodeInfo.Label = Ambience.GetString (data, OutputFlags.ClassBrowserEntries | OutputFlags.IncludeMarkup);
- nodeInfo.Icon = Context.GetIcon (data.GetStockIcon ());
+ // IEvent data = dataObject as IEvent;
+ // nodeInfo.Label = Ambience.GetString (data, OutputFlags.ClassBrowserEntries | OutputFlags.IncludeMarkup);
+ // nodeInfo.Icon = Context.GetIcon (data.GetStockIcon ());
}
public override int CompareObjects (ITreeNavigator thisNode, ITreeNavigator otherNode)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/FieldNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/FieldNodeBuilder.cs
index 21e4f8d5e5..8573d9ac85 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/FieldNodeBuilder.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/FieldNodeBuilder.cs
@@ -49,9 +49,9 @@ namespace MonoDevelop.Ide.Gui.Pads.ClassPad
public override void BuildNode (ITreeBuilder treeBuilder, object dataObject, NodeInfo nodeInfo)
{
- IField data = dataObject as IField;
- nodeInfo.Label = Ambience.GetString (data, OutputFlags.ClassBrowserEntries | OutputFlags.IncludeMarkup);
- nodeInfo.Icon = Context.GetIcon (data.GetStockIcon ());
+ // IField data = dataObject as IField;
+ // nodeInfo.Label = Ambience.GetString (data, OutputFlags.ClassBrowserEntries | OutputFlags.IncludeMarkup);
+ // nodeInfo.Icon = Context.GetIcon (data.GetStockIcon ());
}
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/MemberNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/MemberNodeBuilder.cs
index bbe1f25eff..35c0151faf 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/MemberNodeBuilder.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/MemberNodeBuilder.cs
@@ -43,13 +43,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ClassPad
{
return ((IMember)dataObject).Name;
}
-
- protected Ambience Ambience {
- get {
- return AmbienceService.DefaultAmbience;
- }
- }
-
+
public override Type CommandHandlerType {
get { return typeof(MemberNodeCommandHandler); }
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/MemberNodeCommandHandler.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/MemberNodeCommandHandler.cs
index 241ec93aec..b5a8c88505 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/MemberNodeCommandHandler.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/MemberNodeCommandHandler.cs
@@ -40,8 +40,8 @@ namespace MonoDevelop.Ide.Gui.Pads.ClassPad
{
public override void ActivateItem ()
{
- var member = CurrentNode.DataItem as IEntity;
- IdeApp.ProjectOperations.JumpToDeclaration(member);
+// var member = CurrentNode.DataItem as IEntity;
+// IdeApp.ProjectOperations.JumpToDeclaration(member);
}
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/MethodNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/MethodNodeBuilder.cs
index 8a25619430..2253d6973e 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/MethodNodeBuilder.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/MethodNodeBuilder.cs
@@ -49,9 +49,9 @@ namespace MonoDevelop.Ide.Gui.Pads.ClassPad
public override void BuildNode (ITreeBuilder treeBuilder, object dataObject, NodeInfo nodeInfo)
{
- IMethod data = dataObject as IMethod;
- nodeInfo.Label = Ambience.GetString (data, OutputFlags.ClassBrowserEntries | OutputFlags.IncludeMarkup);
- nodeInfo.Icon = Context.GetIcon (data.GetStockIcon ());
+ // IMethod data = dataObject as IMethod;
+ // nodeInfo.Label = Ambience.GetString (data, OutputFlags.ClassBrowserEntries | OutputFlags.IncludeMarkup);
+ // nodeInfo.Icon = Context.GetIcon (data.GetStockIcon ());
}
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/ProjectNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/ProjectNodeBuilder.cs
index ad71ba09d4..285cca7e17 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/ProjectNodeBuilder.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/ProjectNodeBuilder.cs
@@ -97,23 +97,24 @@ namespace MonoDevelop.Ide.Gui.Pads.ClassPad
builder.AddChild (((DotNetProject)project).References);
}
bool publicOnly = builder.Options ["PublicApiOnly"];
- var dom = TypeSystemService.GetCompilation (project);
- bool nestedNamespaces = builder.Options ["NestedNamespaces"];
- HashSet<string> addedNames = new HashSet<string> ();
- foreach (var ns in dom.MainAssembly.RootNamespace.ChildNamespaces) {
- if (nestedNamespaces) {
- if (!addedNames.Contains (ns.Name)) {
- builder.AddChild (new ProjectNamespaceData (project, ns));
- addedNames.Add (ns.Name);
- }
- } else {
- FillNamespaces (builder, project, ns);
- }
- }
- foreach (var type in dom.MainAssembly.RootNamespace.Types) {
- if (!publicOnly || type.IsPublic)
- builder.AddChild (new ClassData (project, type));
- }
+ // TODO: Roslyn port.
+// var dom = TypeSystemService.GetCompilation (project);
+// bool nestedNamespaces = builder.Options ["NestedNamespaces"];
+// HashSet<string> addedNames = new HashSet<string> ();
+// foreach (var ns in dom.MainAssembly.RootNamespace.ChildNamespaces) {
+// if (nestedNamespaces) {
+// if (!addedNames.Contains (ns.Name)) {
+// builder.AddChild (new ProjectNamespaceData (project, ns));
+// addedNames.Add (ns.Name);
+// }
+// } else {
+// FillNamespaces (builder, project, ns);
+// }
+// }
+// foreach (var type in dom.MainAssembly.RootNamespace.Types) {
+// if (!publicOnly || type.IsPublic)
+// builder.AddChild (new ClassData (project, type));
+// }
}
public static void FillNamespaces (ITreeBuilder builder, Project project, INamespace ns)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/PropertyNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/PropertyNodeBuilder.cs
index 2d8c5bb73f..19ebd06aeb 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/PropertyNodeBuilder.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/PropertyNodeBuilder.cs
@@ -49,9 +49,9 @@ namespace MonoDevelop.Ide.Gui.Pads.ClassPad
public override void BuildNode (ITreeBuilder treeBuilder, object dataObject, NodeInfo nodeInfo)
{
- IProperty data = dataObject as IProperty;
- nodeInfo.Label = Ambience.GetString (data, OutputFlags.ClassBrowserEntries | OutputFlags.IncludeMarkup);
- nodeInfo.Icon = Context.GetIcon (data.GetStockIcon ());
+ // IProperty data = dataObject as IProperty;
+ // nodeInfo.Label = Ambience.GetString (data, OutputFlags.ClassBrowserEntries | OutputFlags.IncludeMarkup);
+ // nodeInfo.Icon = Context.GetIcon (data.GetStockIcon ());
}
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/AbstractBaseViewContent.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/AbstractBaseViewContent.cs
index 392f2e6744..8c441c2e52 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/AbstractBaseViewContent.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/AbstractBaseViewContent.cs
@@ -69,6 +69,14 @@ namespace MonoDevelop.Ide.Gui
return null;
}
+ public virtual IEnumerable<T> GetContents<T> () where T : class
+ {
+ var t = this as T;
+ if (t != null)
+ yield return t;
+ }
+
+
#endregion
#region IDisposable Members
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/AbstractViewContent.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/AbstractViewContent.cs
index 00eb11bfa8..620ca00313 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/AbstractViewContent.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/AbstractViewContent.cs
@@ -100,8 +100,13 @@ namespace MonoDevelop.Ide.Gui
OnBeforeSave (EventArgs.Empty);
this.Save (contentName);
}
-
- public virtual void Save (string fileName)
+
+ public void Save (string fileName)
+ {
+ Save (new FileSaveInformation (fileName));
+ }
+
+ public virtual void Save (FileSaveInformation fileSaveInformation)
{
throw new NotImplementedException ();
}
@@ -110,7 +115,12 @@ namespace MonoDevelop.Ide.Gui
{
}
- public abstract void Load (string fileName);
+ public abstract void Load (FileOpenInformation fileOpenInformation);
+
+ public void Load (string fileName)
+ {
+ Load (new FileOpenInformation (fileName, null));
+ }
public virtual void LoadNew (System.IO.Stream content, string mimeType)
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/CommonTextEditorOptions.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/CommonTextEditorOptions.cs
deleted file mode 100644
index e04a6f9d14..0000000000
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/CommonTextEditorOptions.cs
+++ /dev/null
@@ -1,90 +0,0 @@
-//
-// CommonTextEditorOptions.cs
-//
-// Author:
-// Michael Hutchinson <mhutch@xamarin.com>
-//
-// Copyright (c) 2011 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.Core;
-using MonoDevelop.Ide.Fonts;
-
-namespace MonoDevelop.Ide.Gui
-{
- /// <summary>
- /// Text editor options that subscribe to MonoDevelop common settings.
- /// </summary>
- public class CommonTextEditorOptions : Mono.TextEditor.TextEditorOptions
- {
- bool disposed = false;
-
- public CommonTextEditorOptions ()
- {
- PropertyService.PropertyChanged += PropertyServiceChanged;
- base.FontName = PropertyService.Get ("FontName", FontService.MonospaceFontName);
- base.ColorScheme = IdeApp.Preferences.ColorScheme;
- FontService.RegisterFontChangedCallback ("Editor", UpdateFont);
- }
-
- public override void Dispose ()
- {
- if (disposed)
- return;
- disposed = true;
- PropertyService.PropertyChanged -= PropertyServiceChanged;
- FontService.RemoveCallback (UpdateFont);
- }
-
- void UpdateFont ()
- {
- base.FontName = FontName;
- base.GutterFontName = GutterFontName;
- this.OnChanged (EventArgs.Empty);
- }
-
- void PropertyServiceChanged (object sender, PropertyChangedEventArgs e)
- {
- switch (e.Key) {
- case "ColorScheme": {
- string val = (string) e.NewValue;
- if (string.IsNullOrEmpty (val))
- val = "Default";
- base.ColorScheme = val;
- break;
- }
- }
- }
-
- public override string ColorScheme {
- set { throw new InvalidOperationException ("Set via global source editor options"); }
- }
-
- public override string FontName {
- get {
- return FontService.FilterFontName (FontService.GetUnderlyingFontName ("Editor"));
- }
- set {
- throw new InvalidOperationException ("Set via global source editor options");
- }
- }
- }
-} \ No newline at end of file
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 bc7bf6f75c..f52c5526e9 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DefaultWorkbench.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DefaultWorkbench.cs
@@ -25,7 +25,6 @@
using System;
using System.IO;
-using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Drawing;
using System.Diagnostics;
@@ -39,12 +38,10 @@ using MonoDevelop.Ide.Codons;
using MonoDevelop.Components.Commands;
using MonoDevelop.Components.Docking;
-using GLib;
using MonoDevelop.Components.DockToolbars;
using Gtk;
using MonoDevelop.Components;
using MonoDevelop.Ide.Extensions;
-using Mono.TextEditor;
using MonoDevelop.Components.MainToolbar;
using MonoDevelop.Components.DockNotebook;
@@ -368,7 +365,7 @@ namespace MonoDevelop.Ide.Gui
return mimeimage;
}
- public virtual void ShowView (IViewContent content, bool bringToFront, DockNotebook notebook = null)
+ public virtual void ShowView (IViewContent content, bool bringToFront, IViewDisplayBinding binding = null, DockNotebook notebook = null)
{
bool isFile = content.IsFile;
if (!isFile) {
@@ -404,6 +401,10 @@ namespace MonoDevelop.Ide.Gui
sdiWorkspaceWindow.TitleChanged += delegate { SetWorkbenchTitle (); };
sdiWorkspaceWindow.Closed += CloseWindowEvent;
sdiWorkspaceWindow.Show ();
+ if (binding != null)
+ DisplayBindingService.AttachSubWindows (sdiWorkspaceWindow, binding);
+
+ sdiWorkspaceWindow.CreateCommandHandler ();
tab.Content = sdiWorkspaceWindow;
if (mimeimage != null)
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 eff3218cc9..c96d9fb360 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Document.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Document.cs
@@ -47,23 +47,25 @@ using MonoDevelop.Ide.Extensions;
using System.Linq;
using System.Threading;
using MonoDevelop.Ide.TypeSystem;
-using ICSharpCode.NRefactory;
-using ICSharpCode.NRefactory.TypeSystem;
-using ICSharpCode.NRefactory.TypeSystem.Implementation;
using System.Text;
using System.Collections.ObjectModel;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis.Options;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Ide.Editor.Highlighting;
+using MonoDevelop.Core.Text;
namespace MonoDevelop.Ide.Gui
{
- public class Document : ICSharpCode.NRefactory.AbstractAnnotatable
+
+ public class Document : DocumentContext
{
internal object MemoryProbe = Counters.DocumentsInMemory.CreateMemoryProbe ();
IWorkbenchWindow window;
- TextEditorExtension editorExtension;
ParsedDocument parsedDocument;
- IProjectContent singleFileContext;
- Mono.TextEditor.ITextEditorDataProvider provider = null;
+ FilePath analysisDocumentFileName;
+ Microsoft.CodeAnalysis.DocumentId analysisDocument;
const int ParseDelay = 600;
@@ -75,12 +77,20 @@ namespace MonoDevelop.Ide.Gui
get;
set;
}
-
- public TextEditorExtension EditorExtension {
- get { return this.editorExtension; }
+
+ /// <summary>
+ /// Returns the roslyn document for this document. This may return <c>null</c> if it's no compileable document.
+ /// Even if it's a C# file.
+ /// </summary>
+ public override Microsoft.CodeAnalysis.Document AnalysisDocument {
+ get {
+ if (analysisDocument == null)
+ return null;
+ return TypeSystemService.GetCodeAnalysisDocument (analysisDocument);
+ }
}
- public T GetContent<T> () where T : class
+ public override T GetContent<T> ()
{
if (window == null)
return null;
@@ -97,39 +107,30 @@ namespace MonoDevelop.Ide.Gui
return ret;
}
- //no, so look through the TexteditorExtensions as well
- TextEditorExtension nextExtension = editorExtension;
- while (nextExtension != null) {
- if (typeof(T).IsAssignableFrom (nextExtension.GetType ()))
- return nextExtension as T;
- nextExtension = nextExtension.Next as TextEditorExtension;
+ //If we didn't find in ActiveView or ViewContent... Try in SubViews
+ foreach (var subView in window.SubViewContents) {
+ foreach (var cnt in subView.GetContents<T> ()) {
+ return cnt;
+ }
}
+
return null;
}
- public IEnumerable<T> GetContents<T> () where T : class
+ public override IEnumerable<T> GetContents<T> ()
{
- //check whether the ViewContent can return the type directly
- T ret = (T) Window.ActiveViewContent.GetContent (typeof(T));
- if (ret != null)
- yield return ret;
-
- //check the primary viewcontent
- //not sure if this is the right thing to do, but things depend on this behaviour
- if (Window.ViewContent != Window.ActiveViewContent) {
- ret = (T) Window.ViewContent.GetContent (typeof(T));
- if (ret != null)
- yield return ret;
+ foreach (var cnt in window.ViewContent.GetContents<T> ()) {
+ yield return cnt;
}
-
- //no, so look through the TexteditorExtensions as well
- TextEditorExtension nextExtension = editorExtension;
- while (nextExtension != null) {
- if (typeof(T).IsAssignableFrom (nextExtension.GetType ()))
- yield return nextExtension as T;
- nextExtension = nextExtension.Next as TextEditorExtension;
+
+ foreach (var subView in window.SubViewContents) {
+ foreach (var cnt in subView.GetContents<T> ()) {
+ yield return cnt;
+ }
}
}
+
+
static Document ()
{
if (IdeApp.Workbench != null) {
@@ -155,6 +156,19 @@ namespace MonoDevelop.Ide.Gui
if (window.ViewContent.Project != null)
window.ViewContent.Project.Modified += HandleProjectModified;
window.ViewsChanged += HandleViewsChanged;
+ window.ViewContent.ContentNameChanged += delegate {
+ analysisDocument = null;
+ };
+ MonoDevelopWorkspace.LoadingFinished += TypeSystemService_WorkspaceItemLoaded;
+ }
+
+ void TypeSystemService_WorkspaceItemLoaded (object sender, EventArgs e)
+ {
+ if (adhocProject == null)
+ analysisDocument = null;
+ EnsureAnalysisDocumentIsOpen ();
+ if (analysisDocument != null)
+ StartReparseThread ();
}
/* void UpdateRegisteredDom (object sender, ProjectDomEventArgs e)
@@ -182,13 +196,12 @@ namespace MonoDevelop.Ide.Gui
get { return !Window.ViewContent.IsViewOnly && (Window.ViewContent.ContentName == null || Window.ViewContent.IsDirty); }
set { Window.ViewContent.IsDirty = value; }
}
-
- public bool HasProject {
- get { return Window != null ? Window.ViewContent.Project != null : false; }
- }
-
- public Project Project {
- get { return Window != null ? Window.ViewContent.Project : null; }
+
+ FilePath adHocFile;
+ Project adhocProject;
+
+ public override Project Project {
+ get { return (Window != null ? Window.ViewContent.Project : null); }
/* set {
Window.ViewContent.Project = value;
if (value != null)
@@ -199,7 +212,7 @@ namespace MonoDevelop.Ide.Gui
}*/
}
- public bool IsCompileableInProject {
+ public override bool IsCompileableInProject {
get {
var project = Project;
if (project == null)
@@ -220,19 +233,15 @@ namespace MonoDevelop.Ide.Gui
}
}
- public IProjectContent ProjectContent {
- get {
- return Project != null ? TypeSystemService.GetProjectContext (Project) : GetProjectContext ();
- }
- }
-
- public virtual ICompilation Compilation {
- get {
- return Project != null ? TypeSystemService.GetCompilation (Project) : GetProjectContext ().CreateCompilation ();
- }
+ public Task<Microsoft.CodeAnalysis.Compilation> GetCompilationAsync(CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var project = TypeSystemService.GetCodeAnalysisProject (Project ?? adhocProject);
+ if (project == null)
+ return new Task<Microsoft.CodeAnalysis.Compilation> (() => null);
+ return project.GetCompilationAsync (cancellationToken);
}
-
- public virtual ParsedDocument ParsedDocument {
+
+ public override ParsedDocument ParsedDocument {
get {
return parsedDocument;
}
@@ -300,21 +309,16 @@ namespace MonoDevelop.Ide.Gui
return new DocumentView (this, content);
}
- public string Name {
+ public override string Name {
get {
IViewContent view = Window.ViewContent;
return view.IsUntitled ? view.UntitledName : view.ContentName;
}
}
- public Mono.TextEditor.TextEditorData Editor {
+ public TextEditor Editor {
get {
- if (provider == null) {
- provider = GetContent <Mono.TextEditor.ITextEditorDataProvider> ();
- if (provider == null)
- return null;
- }
- return provider.GetTextEditorData ();
+ return GetContent <TextEditor> ();
}
}
@@ -378,21 +382,21 @@ namespace MonoDevelop.Ide.Gui
// Set the file time of the current document after the file time of the written file, to prevent double file updates.
// Note that the parsed document may be overwritten by a background thread to a more recent one.
var doc = parsedDocument;
- if (doc != null && doc.ParsedFile != null) {
+ if (doc != null) {
string fileName = Window.ViewContent.ContentName;
try {
// filename could be null if the user cancelled SaveAs and this is a new & unsaved file
if (fileName != null)
- doc.ParsedFile.LastWriteTime = File.GetLastWriteTimeUtc (fileName);
+ doc.LastWriteTimeUtc = File.GetLastWriteTimeUtc (fileName);
} catch (Exception e) {
- doc.ParsedFile.LastWriteTime = DateTime.UtcNow;
+ doc.LastWriteTimeUtc = DateTime.UtcNow;
LoggingService.LogWarning ("Exception while getting the write time from " + fileName, e);
}
}
TypeSystemService.TrackFileChanges = true;
}
}
-
+
public void SaveAs ()
{
SaveAs (null);
@@ -406,11 +410,11 @@ namespace MonoDevelop.Ide.Gui
Encoding encoding = null;
- IEncodedTextContent tbuffer = GetContent <IEncodedTextContent> ();
+ var tbuffer = GetContent <ITextSource> ();
if (tbuffer != null) {
- encoding = tbuffer.SourceEncoding;
+ encoding = tbuffer.Encoding;
if (encoding == null)
- encoding = Encoding.Default;
+ encoding = Encoding.UTF8;
}
if (filename == null) {
@@ -446,16 +450,13 @@ namespace MonoDevelop.Ide.Gui
// save backup first
if ((bool)PropertyService.Get ("SharpDevelop.CreateBackupCopy", false)) {
if (tbuffer != null && encoding != null)
- tbuffer.Save (filename + "~", encoding);
+ TextFileUtility.WriteText (filename + "~", tbuffer.Text, encoding, tbuffer.UseBOM);
else
- Window.ViewContent.Save (filename + "~");
+ Window.ViewContent.Save (new FileSaveInformation (filename + "~", encoding));
}
TypeSystemService.RemoveSkippedfile (FileName);
// do actual save
- if (tbuffer != null && encoding != null)
- tbuffer.Save (filename, encoding);
- else
- Window.ViewContent.Save (filename);
+ Window.ViewContent.Save (new FileSaveInformation (filename + "~", encoding));
FileService.NotifyFileChanged (filename);
DesktopService.RecentFiles.AddFile (filename, (Project)null);
@@ -468,12 +469,11 @@ namespace MonoDevelop.Ide.Gui
{
return ((SdiWorkspaceWindow)Window).CloseWindow (false, true);
}
-
- void OnSaved (EventArgs args)
+
+ protected override void OnSaved (EventArgs e)
{
IdeApp.Workbench.SaveFileStatus ();
- if (Saved != null)
- Saved (this, args);
+ base.OnSaved (e);
}
public void CancelParseTimeout ()
@@ -518,8 +518,14 @@ namespace MonoDevelop.Ide.Gui
internal void DisposeDocument ()
{
- DetachExtensionChain ();
- RemoveAnnotations (typeof(System.Object));
+ if (analysisDocument != null) {
+ TypeSystemService.InformDocumentClose (analysisDocument, FileName);
+ analysisDocument = null;
+ }
+ UnloadAdhocProject ();
+ if (Editor != null) {
+ Editor.Dispose ();
+ }
if (window is SdiWorkspaceWindow)
((SdiWorkspaceWindow)window).DetachFromPathedDocument ();
window.Closed -= OnClosed;
@@ -531,11 +537,12 @@ namespace MonoDevelop.Ide.Gui
if (window.ViewContent.Project != null)
window.ViewContent.Project.Modified -= HandleProjectModified;
window.ViewsChanged += HandleViewsChanged;
+ TypeSystemService.Workspace.WorkspaceChanged -= HandleWorkspaceChanged;
+ MonoDevelopWorkspace.LoadingFinished -= TypeSystemService_WorkspaceItemLoaded;
+
window = null;
parsedDocument = null;
- singleFileContext = null;
- provider = null;
views = null;
viewsRO = null;
}
@@ -587,84 +594,44 @@ namespace MonoDevelop.Ide.Gui
void InitializeExtensionChain ()
{
- DetachExtensionChain ();
- var editor = GetContent<IExtensibleTextEditor> ();
-
- ExtensionNodeList extensions = window.ExtensionContext.GetExtensionNodes ("/MonoDevelop/Ide/TextEditorExtensions", typeof(TextEditorExtensionNode));
- editorExtension = null;
- TextEditorExtension last = null;
- var mimetypeChain = DesktopService.GetMimeTypeInheritanceChainForFile (FileName).ToArray ();
- foreach (TextEditorExtensionNode extNode in extensions) {
- if (!extNode.Supports (FileName, mimetypeChain))
- continue;
- TextEditorExtension ext;
- try {
- ext = (TextEditorExtension)extNode.CreateInstance ();
- } catch (Exception e) {
- LoggingService.LogError ("Error while creating text editor extension :" + extNode.Id + "(" + extNode.Type +")", e);
- continue;
- }
- if (ext.ExtendsEditor (this, editor)) {
- if (last != null) {
- ext.Next = last.Next;
- last.Next = ext;
- last = ext;
- } else {
- editorExtension = last = ext;
- last.Next = editor.AttachExtension (editorExtension);
- }
- ext.Initialize (this);
- }
- }
+ Editor.InitializeExtensionChain (this);
+
if (window is SdiWorkspaceWindow)
((SdiWorkspaceWindow)window).AttachToPathedDocument (GetContent<MonoDevelop.Ide.Gui.Content.IPathedDocument> ());
- }
- void DetachExtensionChain ()
- {
- while (editorExtension != null) {
- try {
- editorExtension.Dispose ();
- } catch (Exception ex) {
- LoggingService.LogError ("Exception while disposing extension:" + editorExtension, ex);
- }
- editorExtension = editorExtension.Next as TextEditorExtension;
- }
- editorExtension = null;
}
- void InitializeEditor (IExtensibleTextEditor editor)
+ void InitializeEditor ()
{
- Editor.Document.TextReplaced += (o, a) => {
+ Editor.TextChanged += (o, a) => {
if (parsedDocument != null)
parsedDocument.IsInvalid = true;
- if (Editor.Document.IsInAtomicUndo) {
+ if (Editor.IsInAtomicUndo) {
wasEdited = true;
} else {
StartReparseThread ();
}
};
- Editor.Document.BeginUndo += delegate {
+ Editor.BeginAtomicUndoOperation += delegate {
wasEdited = false;
};
- Editor.Document.EndUndo += delegate {
+ Editor.EndAtomicUndoOperation += delegate {
if (wasEdited)
StartReparseThread ();
};
- Editor.Document.Undone += (o, a) => StartReparseThread ();
- Editor.Document.Redone += (o, a) => StartReparseThread ();
+// Editor.Undone += (o, a) => StartReparseThread ();
+// Editor.Redone += (o, a) => StartReparseThread ();
InitializeExtensionChain ();
}
internal void OnDocumentAttached ()
{
- IExtensibleTextEditor editor = GetContent<IExtensibleTextEditor> ();
- if (editor != null) {
- InitializeEditor (editor);
+ if (Editor != null) {
+ InitializeEditor ();
RunWhenLoaded (delegate { ListenToProjectLoad (Project); });
}
@@ -680,24 +647,25 @@ namespace MonoDevelop.Ide.Gui
public void RunWhenLoaded (System.Action action)
{
var e = Editor;
- if (e == null || e.Document == null) {
+ if (e == null) {
action ();
return;
}
- e.Document.RunWhenLoaded (action);
+ e.RunWhenLoaded (action);
}
- public void AttachToProject (Project project)
+ public override void AttachToProject (Project project)
{
SetProject (project);
}
- TypeSystemService.ProjectContentWrapper currentWrapper;
internal void SetProject (Project project)
{
if (Window == null || Window.ViewContent == null || Window.ViewContent.Project == project)
return;
- DetachExtensionChain ();
+ UnloadAdhocProject ();
+ if (adhocProject == null)
+ analysisDocument = null;
ISupportsProjectReload pr = GetContent<ISupportsProjectReload> ();
if (pr != null) {
// Unsubscribe project events
@@ -709,22 +677,19 @@ namespace MonoDevelop.Ide.Gui
if (project != null)
project.Modified += HandleProjectModified;
InitializeExtensionChain ();
-
+ TypeSystemService.Workspace.WorkspaceChanged += HandleWorkspaceChanged;
ListenToProjectLoad (project);
}
- void ListenToProjectLoad (Project project)
+ void HandleWorkspaceChanged (object sender, Microsoft.CodeAnalysis.WorkspaceChangeEventArgs e)
{
- if (currentWrapper != null) {
- currentWrapper.Loaded -= HandleInLoadChanged;
- currentWrapper = null;
- }
- if (project != null) {
- var wrapper = TypeSystemService.GetProjectContentWrapper (project);
- wrapper.Loaded += HandleInLoadChanged;
- currentWrapper = wrapper;
- currentWrapper.RequestLoad ();
+ if (e.Kind == Microsoft.CodeAnalysis.WorkspaceChangeKind.DocumentChanged && e.DocumentId == analysisDocument) {
+ OnDocumentParsed (EventArgs.Empty);
}
+ }
+
+ void ListenToProjectLoad (Project project)
+ {
StartReparseThread ();
}
@@ -746,18 +711,30 @@ namespace MonoDevelop.Ide.Gui
/// <returns>
/// A <see cref="ParsedDocument"/> that contains the current dom.
/// </returns>
- public ParsedDocument UpdateParseDocument ()
+ public override ParsedDocument UpdateParseDocument ()
{
try {
+ EnsureAnalysisDocumentIsOpen ();
string currentParseFile = FileName;
var editor = Editor;
if (editor == null || string.IsNullOrEmpty (currentParseFile))
return null;
TypeSystemService.AddSkippedFile (currentParseFile);
- string currentParseText = editor.Text;
- this.parsedDocument = TypeSystemService.ParseFile (Project, currentParseFile, editor.Document.MimeType, currentParseText);
- if (Project == null && this.parsedDocument != null) {
- singleFileContext = GetProjectContext ().AddOrUpdateFiles (parsedDocument.ParsedFile);
+ var currentParseText = editor.CreateDocumentSnapshot ();
+ CancelOldParsing();
+ var project = Project ?? adhocProject;
+ if (project != null && TypeSystemService.CanParseProjections (project, Editor.MimeType, FileName)) {
+ var task = TypeSystemService.ParseProjection (project, currentParseFile, editor.MimeType, currentParseText);
+ if (task.Result != null) {
+ var p = task.Result;
+ this.parsedDocument = p.ParsedDocument;
+ var projections = p.Projections;
+ foreach (var p2 in projections)
+ p2.CreateProjectedEditor (this);
+ Editor.SetOrUpdateProjections (this, projections, p.DisabledProjectionFeatures);
+ }
+ } else {
+ this.parsedDocument = TypeSystemService.ParseFile (project, currentParseFile, editor.MimeType, currentParseText).Result ?? this.parsedDocument;
}
} finally {
@@ -765,89 +742,136 @@ namespace MonoDevelop.Ide.Gui
}
return this.parsedDocument;
}
+
+ uint parseTimeout = 0;
- static readonly Lazy<IUnresolvedAssembly> mscorlib = new Lazy<IUnresolvedAssembly> ( () => new IkvmLoader ().LoadAssemblyFile (typeof (object).Assembly.Location));
- static readonly Lazy<IUnresolvedAssembly> systemCore = new Lazy<IUnresolvedAssembly>( () => new IkvmLoader ().LoadAssemblyFile (typeof (System.Linq.Enumerable).Assembly.Location));
- static readonly Lazy<IUnresolvedAssembly> system = new Lazy<IUnresolvedAssembly>( () => new IkvmLoader ().LoadAssemblyFile (typeof (System.Uri).Assembly.Location));
-
- static IUnresolvedAssembly Mscorlib { get { return mscorlib.Value; } }
- static IUnresolvedAssembly SystemCore { get { return systemCore.Value; } }
- static IUnresolvedAssembly System { get { return system.Value; } }
-
- public bool IsProjectContextInUpdate {
- get {
- if (currentWrapper == null)
- return false;
- return !currentWrapper.IsLoaded;
+ void EnsureAnalysisDocumentIsOpen ()
+ {
+ if (analysisDocument != null)
+ return;
+ if (Editor == null) {
+ analysisDocument = null;
+ return;
+ }
+ analysisDocumentFileName = FileName;
+ if (Project != null) {
+ RoslynWorkspace = TypeSystemService.GetWorkspace (this.Project.ParentSolution);
+ analysisDocument = TypeSystemService.GetDocumentId (this.Project, this.FileName);
+ if (analysisDocument != null) {
+ TypeSystemService.InformDocumentOpen (analysisDocument, Editor);
+ }
+ } else {
+ lock (adhocProjectLock) {
+ if (adhocProject != null) {
+ return;
+ }
+ if (Editor != null && Editor.MimeType == "text/x-csharp") {
+ var newProject = new DotNetAssemblyProject (Microsoft.CodeAnalysis.LanguageNames.CSharp);
+ this.adhocProject = newProject;
+
+ newProject.Name = "InvisibleProject";
+ newProject.References.Add (new ProjectReference (ReferenceType.Package, "mscorlib"));
+ newProject.References.Add (new ProjectReference (ReferenceType.Package, "System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"));
+ newProject.References.Add (new ProjectReference (ReferenceType.Package, "System.Core"));
+
+ newProject.FileName = "test.csproj";
+ adHocFile = Platform.IsWindows ? "C:\\a.cs" : "/a.cs";
+ newProject.Files.Add (new ProjectFile (adHocFile, BuildAction.Compile));
+
+ var solution = new Solution ();
+ solution.AddConfiguration ("", true);
+ solution.DefaultSolutionFolder.AddItem (newProject);
+ using (var monitor = new MonoDevelop.Core.ProgressMonitoring.NullProgressMonitor ())
+ RoslynWorkspace = TypeSystemService.Load (solution, monitor, false);
+ analysisDocument = TypeSystemService.GetDocumentId (RoslynWorkspace, adhocProject, adHocFile);
+ TypeSystemService.InformDocumentOpen (RoslynWorkspace, analysisDocument, Editor);
+ }
+ }
}
}
+ object adhocProjectLock = new object();
- public virtual IProjectContent GetProjectContext ()
+ void UnloadAdhocProject ()
{
- if (Project == null) {
- if (singleFileContext == null) {
- singleFileContext = new ICSharpCode.NRefactory.CSharp.CSharpProjectContent ();
- singleFileContext = singleFileContext.AddAssemblyReferences (new [] { Mscorlib, System, SystemCore });
- }
- if (parsedDocument != null)
- return singleFileContext.AddOrUpdateFiles (parsedDocument.ParsedFile);
- return singleFileContext;
+ lock (adhocProjectLock) {
+ if (adhocProject == null)
+ return;
+ TypeSystemService.Unload (adhocProject.ParentSolution.ParentWorkspace);
+ adhocProject = null;
}
-
- return TypeSystemService.GetProjectContext (Project);
}
-
- uint parseTimeout = 0;
+
object reparseLock = new object();
- internal void StartReparseThread ()
+ CancellationTokenSource parseTokenSource = new CancellationTokenSource();
+ int reparseQueue;
+ void CancelOldParsing()
{
- lock (reparseLock) {
- if (currentWrapper != null)
- currentWrapper.EnsureReferencesAreLoaded ();
+ parseTokenSource.Cancel ();
+ parseTokenSource = new CancellationTokenSource ();
+ }
+ internal void StartReparseThread ()
+ {
+ string currentParseFile = adhocProject != null ? adHocFile : FileName;
+ if (string.IsNullOrEmpty (currentParseFile))
+ return;
+ Interlocked.Increment (ref reparseQueue);
+ Application.Invoke (delegate {
+ if (Interlocked.Decrement (ref reparseQueue) != 0) {
+ return;
+ }
// Don't directly parse the document because doing it at every key press is
// very inefficient. Do it after a small delay instead, so several changes can
// be parsed at the same time.
- string currentParseFile = FileName;
- if (string.IsNullOrEmpty (currentParseFile))
- return;
+ EnsureAnalysisDocumentIsOpen ();
CancelParseTimeout ();
- if (IsProjectContextInUpdate) {
- return;
- }
- parseTimeout = GLib.Timeout.Add (ParseDelay, delegate {
- var editor = Editor;
- if (editor == null || IsProjectContextInUpdate) {
- parseTimeout = 0;
- return false;
- }
- string currentParseText = editor.Text;
- string mimeType = editor.Document.MimeType;
- ThreadPool.QueueUserWorkItem (delegate {
- if (IsProjectContextInUpdate) {
- return;
- }
- TypeSystemService.AddSkippedFile (currentParseFile);
- var currentParsedDocument = TypeSystemService.ParseFile (Project, currentParseFile, mimeType, currentParseText);
- Application.Invoke (delegate {
- // this may be called after the document has closed, in that case the OnDocumentParsed event shouldn't be invoked.
- if (isClosed)
+ var currentParseText = Editor.CreateSnapshot ();
+ string mimeType = Editor.MimeType;
+ CancelOldParsing ();
+ var token = parseTokenSource.Token;
+ var project = Project ?? adhocProject;
+ ThreadPool.QueueUserWorkItem (delegate {
+ TypeSystemService.AddSkippedFile (currentParseFile);
+ if (project != null && TypeSystemService.CanParseProjections (project, mimeType, currentParseFile)) {
+ TypeSystemService.ParseProjection (project, currentParseFile, mimeType, currentParseText, token).ContinueWith (task => {
+ if (token.IsCancellationRequested)
return;
- this.parsedDocument = currentParsedDocument;
- OnDocumentParsed (EventArgs.Empty);
- });
- });
+ Application.Invoke (delegate {
+ // this may be called after the document has closed, in that case the OnDocumentParsed event shouldn't be invoked.
+ var taskResult = task.Result;
+ if (isClosed || taskResult == null || token.IsCancellationRequested)
+ return;
+ this.parsedDocument = taskResult.ParsedDocument;
+ var projections = taskResult.Projections;
+ foreach (var p2 in projections)
+ p2.CreateProjectedEditor (this);
+ Editor.SetOrUpdateProjections (this, projections, taskResult.DisabledProjectionFeatures);
+ OnDocumentParsed (EventArgs.Empty);
+ });
+ }, TaskContinuationOptions.OnlyOnRanToCompletion);
+ } else {
+ TypeSystemService.ParseFile (project, currentParseFile, mimeType, currentParseText, token).ContinueWith (task => {
+ if (token.IsCancellationRequested)
+ return;
+ Application.Invoke (delegate {
+ // this may be called after the document has closed, in that case the OnDocumentParsed event shouldn't be invoked.
+ if (isClosed || task.Result == null || token.IsCancellationRequested)
+ return;
+ this.parsedDocument = task.Result;
+ OnDocumentParsed (EventArgs.Empty);
+ });
+ }, TaskContinuationOptions.OnlyOnRanToCompletion);
+ }
parseTimeout = 0;
- return false;
});
- }
+ });
}
/// <summary>
/// This method kicks off an async document parser and should be used instead of
/// <see cref="UpdateParseDocument"/> unless you need the parsed document immediately.
/// </summary>
- public void ReparseDocument ()
+ public override void ReparseDocument ()
{
StartReparseThread ();
}
@@ -855,8 +879,8 @@ namespace MonoDevelop.Ide.Gui
internal object ExtendedCommandTargetChain {
get {
// Only go through the text editor chain, if the text editor is selected as subview
- if (Window != null && Window.ActiveViewContent.GetContent (typeof(IExtensibleTextEditor)) != null)
- return editorExtension;
+ if (Window != null && Window.ActiveViewContent.GetContent (typeof(TextEditor)) != null)
+ return Editor.CommandRouter;
return null;
}
}
@@ -867,19 +891,10 @@ namespace MonoDevelop.Ide.Gui
window.ViewContent.Project = null;
}
- protected virtual void OnDocumentParsed (EventArgs e)
- {
- EventHandler handler = this.DocumentParsed;
- if (handler != null)
- handler (this, e);
- }
-
public event EventHandler Closed;
- public event EventHandler Saved;
public event EventHandler ViewChanged;
- public event EventHandler DocumentParsed;
-
+
public string[] CommentTags {
get {
if (IsFile)
@@ -893,30 +908,16 @@ namespace MonoDevelop.Ide.Gui
{
//Document doc = IdeApp.Workbench.ActiveDocument;
string loadedMimeType = DesktopService.GetMimeTypeForUri (fileName);
-
- Mono.TextEditor.Highlighting.SyntaxMode mode = null;
- foreach (string mt in DesktopService.GetMimeTypeInheritanceChain (loadedMimeType)) {
- mode = Mono.TextEditor.Highlighting.SyntaxModeService.GetSyntaxMode (null, mt);
- if (mode != null)
- break;
- }
-
- if (mode == null)
- return null;
-
- List<string> ctags;
- if (mode.Properties.TryGetValue ("LineComment", out ctags) && ctags.Count > 0) {
- return new string [] { ctags [0] };
- }
- List<string> tags = new List<string> ();
- if (mode.Properties.TryGetValue ("BlockCommentStart", out ctags))
- tags.Add (ctags [0]);
- if (mode.Properties.TryGetValue ("BlockCommentEnd", out ctags))
- tags.Add (ctags [0]);
- if (tags.Count == 2)
- return tags.ToArray ();
- else
- return null;
+
+ var result = TextEditorFactory.GetSyntaxProperties (loadedMimeType, "LineComment");
+ if (result != null)
+ return result;
+
+ var start = TextEditorFactory.GetSyntaxProperties (loadedMimeType, "BlockCommentStart");
+ var end = TextEditorFactory.GetSyntaxProperties (loadedMimeType, "BlockCommentEnd");
+ if (start != null && end != null)
+ return new [] { start[0], end[0] };
+ return null;
}
// public MonoDevelop.Projects.CodeGeneration.CodeGenerator CreateCodeGenerator ()
@@ -932,7 +933,29 @@ namespace MonoDevelop.Ide.Gui
public void DisableAutoScroll ()
{
if (IsFile)
- Mono.TextEditor.Utils.FileSettingsStore.Remove (FileName);
+ FileSettingsStore.Remove (FileName);
+ }
+
+ public override OptionSet GetOptionSet ()
+ {
+ return TypeSystemService.Workspace.Options;
+ }
+
+ internal override Task<IReadOnlyList<Editor.Projection.Projection>> GetPartialProjectionsAsync (CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var parser = TypeSystemService.GetParser (Editor.MimeType);
+ if (parser == null)
+ return null;
+ var projectFile = Project.GetProjectFile (Editor.FileName);
+ if (projectFile == null)
+ return null;
+ if (!parser.CanGenerateProjection (Editor.MimeType, projectFile.BuildAction, Project.SupportedLanguages))
+ return null;
+ try {
+ return parser.GetPartialProjectionsAsync (this, Editor, parsedDocument, cancellationToken);
+ } catch (NotSupportedException) {
+ return null;
+ }
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DocumentSwitcher.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DocumentSwitcher.cs
index 46edebf535..82fa7c413f 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DocumentSwitcher.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DocumentSwitcher.cs
@@ -34,7 +34,6 @@ using Gdk;
using Gtk;
using MonoDevelop.Ide.Gui;
using MonoDevelop.Core;
-using Mono.TextEditor;
using MonoDevelop.Components;
namespace MonoDevelop.Ide
@@ -262,8 +261,8 @@ namespace MonoDevelop.Ide
{
Gdk.Key key;
Gdk.ModifierType mod;
- Mono.TextEditor.KeyboardShortcut[] accels;
- Mono.TextEditor.GtkWorkarounds.MapKeys (evnt, out key, out mod, out accels);
+ KeyboardShortcut[] accels;
+ GtkWorkarounds.MapKeys (evnt, out key, out mod, out accels);
switch (accels [0].Key) {
case Gdk.Key.Left:
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DocumentToolbar.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DocumentToolbar.cs
index 1a2536782a..5dfd8bdaf1 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DocumentToolbar.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DocumentToolbar.cs
@@ -26,8 +26,6 @@
using System;
using Gtk;
using MonoDevelop.Components;
-using Mono.TextEditor;
-
namespace MonoDevelop.Ide.Gui
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/HiddenTextEditorViewContent.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/HiddenTextEditorViewContent.cs
index b070b93358..cbd23e5ea3 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/HiddenTextEditorViewContent.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/HiddenTextEditorViewContent.cs
@@ -27,13 +27,20 @@
using System;
using MonoDevelop.Ide.Gui.Content;
using MonoDevelop.Core;
-using Mono.TextEditor;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Core.Text;
namespace MonoDevelop.Ide.Gui
{
- public class HiddenTextEditorViewContent : MonoDevelop.Ide.Gui.AbstractViewContent, IEditableTextBuffer, Mono.TextEditor.ITextEditorDataProvider
+ public class HiddenTextEditorViewContent : MonoDevelop.Ide.Gui.AbstractViewContent, IServiceProvider
{
- Mono.TextEditor.TextEditorData data;
+ readonly TextEditor editor;
+
+ public TextEditor Editor {
+ get {
+ return editor;
+ }
+ }
public override Gtk.Widget Control {
get {
@@ -43,12 +50,17 @@ namespace MonoDevelop.Ide.Gui
public HiddenTextEditorViewContent ()
{
- document = new Mono.TextEditor.TextDocument ();
- data = new Mono.TextEditor.TextEditorData (document);
+ editor = TextEditorFactory.CreateNewEditor ();
Name = "";
}
-
- public override void Load (string fileName)
+
+ public HiddenTextEditorViewContent (TextEditor editor)
+ {
+ this.editor = editor;
+ Name = editor.FileName;
+ }
+
+ public override void Load (FileOpenInformation fileOpenInformation)
{
}
@@ -63,54 +75,53 @@ namespace MonoDevelop.Ide.Gui
public int LineCount {
get {
- return document.LineCount;
+ return editor.LineCount;
}
}
- Mono.TextEditor.TextDocument document;
public string Text {
get {
- return document.Text;
+ return editor.Text;
}
set {
- document.Text = value;
+ editor.Text = value;
}
}
public int InsertText (int position, string text)
{
- document.Insert (position, text);
+ editor.InsertText (position, text);
return text.Length;
}
public void DeleteText (int position, int length)
{
- document.Replace (position, length, "");
+ editor.ReplaceText (position, length, "");
}
public int Length {
get {
- return document.TextLength;
+ return editor.Length;
}
}
public string GetText (int startPosition, int endPosition)
{
- return document.GetTextBetween (startPosition, endPosition);
+ return editor.GetTextBetween (startPosition, endPosition);
}
public char GetCharAt (int position)
{
- return document.GetCharAt (position);
+ return editor.GetCharAt (position);
}
public int GetPositionFromLineColumn (int line, int column)
{
- return document.LocationToOffset (line, column);
+ return editor.LocationToOffset (line, column);
}
public void GetLineColumnFromPosition (int position, out int line, out int column)
{
- Mono.TextEditor.DocumentLocation loc = document.OffsetToLocation (position);
+ var loc = editor.OffsetToLocation (position);
line = loc.Line;
column = loc.Column;
}
@@ -119,32 +130,32 @@ namespace MonoDevelop.Ide.Gui
public int CursorPosition {
get {
- return data.Caret.Offset;
+ return editor.CaretOffset;
}
set {
- data.Caret.Offset = value;
+ editor.CaretOffset = value;
}
}
public int SelectionStartPosition {
get {
- if (!data.IsSomethingSelected)
- return data.Caret.Offset;
- return data.SelectionRange.Offset;
+ if (!editor.IsSomethingSelected)
+ return editor.CaretOffset;
+ return editor.SelectionRange.Offset;
}
}
public int SelectionEndPosition {
get {
- if (!data.IsSomethingSelected)
- return data.Caret.Offset;
- return data.SelectionRange.EndOffset;
+ if (!editor.IsSomethingSelected)
+ return editor.CaretOffset;
+ return editor.SelectionRange.EndOffset;
}
}
public void Select (int startPosition, int endPosition)
{
- data.SelectionRange = new TextSegment (startPosition, endPosition - startPosition);
+ editor.SelectionRange = new TextSegment (startPosition, endPosition - startPosition);
}
public void ShowPosition (int position)
@@ -195,12 +206,18 @@ namespace MonoDevelop.Ide.Gui
{
return new DisposeStub ();
}
-
- public Mono.TextEditor.TextEditorData GetTextEditorData ()
+
+ #region IServiceProvider implementation
+
+ object IServiceProvider.GetService (Type serviceType)
{
- return data;
+ if (serviceType.IsInstanceOfType (editor))
+ return editor;
+ return null;
}
+
+ #endregion
+
public event EventHandler CaretPositionSet;
- public event EventHandler<TextChangedEventArgs> TextChanged;
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/IBaseViewContent.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/IBaseViewContent.cs
index c40c6f8525..ad246af631 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/IBaseViewContent.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/IBaseViewContent.cs
@@ -27,6 +27,7 @@
using System;
using Gtk;
+using System.Collections.Generic;
namespace MonoDevelop.Ide.Gui
{
@@ -41,7 +42,8 @@ namespace MonoDevelop.Ide.Gui
string TabPageLabel { get; }
object GetContent (Type type);
-
+ IEnumerable<T> GetContents<T> () where T : class;
+
bool CanReuseView (string fileName);
void RedrawContent ();
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/IViewContent.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/IViewContent.cs
index 2fbc0c618e..0c76d3cc02 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/IViewContent.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/IViewContent.cs
@@ -30,7 +30,7 @@ using MonoDevelop.Projects;
namespace MonoDevelop.Ide.Gui
{
- public interface IViewContent : IBaseViewContent
+ public interface IViewContent : IBaseViewContent
{
Project Project { get; set; }
@@ -45,9 +45,11 @@ namespace MonoDevelop.Ide.Gui
bool IsDirty { get; set; }
bool IsReadOnly { get; }
- void Load (string fileName);
+ void Load (FileOpenInformation fileOpenInformation);
+ void Load (string fileName);
void LoadNew (System.IO.Stream content, string mimeType);
- void Save (string fileName);
+ void Save (FileSaveInformation fileSaveInformation);
+ void Save (string fileName);
void Save ();
/// <summary>
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/SdiWorkspaceWindow.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/SdiWorkspaceWindow.cs
index c5468e9ee5..05aba59465 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/SdiWorkspaceWindow.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/SdiWorkspaceWindow.cs
@@ -121,7 +121,10 @@ namespace MonoDevelop.Ide.Gui
Add (box);
SetTitleEvent(null, null);
+ }
+ internal void CreateCommandHandler ()
+ {
commandHandler = new ViewCommandHandlers (this);
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Styles.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Styles.cs
index 8705e7258f..23fa36eb7b 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Styles.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Styles.cs
@@ -115,7 +115,7 @@ namespace MonoDevelop.Ide.Gui
public static int ProgressBarInnerPadding { get { return (int)(4 * PixelScale); } }
public static int ProgressBarOuterPadding { get { return (int)(4 * PixelScale); } }
- static readonly double PixelScale = Mono.TextEditor.GtkWorkarounds.GetPixelScale ();
+ static readonly double PixelScale = GtkWorkarounds.GetPixelScale ();
// Toolbar
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ViewCommandHandlers.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ViewCommandHandlers.cs
index 46a5e9712c..da50ac8bc1 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ViewCommandHandlers.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ViewCommandHandlers.cs
@@ -35,6 +35,7 @@ using MonoDevelop.Core;
using MonoDevelop.Ide.Gui.Content;
using MonoDevelop.Components.Commands;
using MonoDevelop.Ide.Commands;
+using MonoDevelop.Ide.Editor;
namespace MonoDevelop.Ide.Gui
{
@@ -240,33 +241,33 @@ namespace MonoDevelop.Ide.Gui
[CommandHandler (EditCommands.UppercaseSelection)]
public void OnUppercaseSelection ()
{
- IEditableTextBuffer buffer = GetContent <IEditableTextBuffer> ();
+ var buffer = GetContent <TextEditor> ();
if (buffer == null)
return;
string selectedText = buffer.SelectedText;
if (string.IsNullOrEmpty (selectedText)) {
- int pos = buffer.CursorPosition;
- string ch = buffer.GetText (pos, pos + 1);
+ int pos = buffer.CaretOffset;
+ string ch = buffer.GetTextAt (pos, pos + 1);
string upper = ch.ToUpper ();
if (upper == ch) {
- buffer.CursorPosition = pos + 1;
+ buffer.CaretOffset = pos + 1;
return;
}
using (var undo = buffer.OpenUndoGroup ()) {
- buffer.DeleteText (pos, 1);
+ buffer.RemoveText (pos, 1);
buffer.InsertText (pos, upper);
- buffer.CursorPosition = pos + 1;
+ buffer.CaretOffset = pos + 1;
}
} else {
string newText = selectedText.ToUpper ();
if (newText == selectedText)
return;
- int startPos = buffer.SelectionStartPosition;
+ int startPos = buffer.SelectionRange.Offset;
using (var undo = buffer.OpenUndoGroup ()) {
- buffer.DeleteText (startPos, selectedText.Length);
+ buffer.RemoveText (startPos, selectedText.Length);
buffer.InsertText (startPos, newText);
- buffer.Select (startPos, startPos + newText.Length);
+ buffer.SetSelection (startPos, startPos + newText.Length);
}
}
}
@@ -274,40 +275,40 @@ namespace MonoDevelop.Ide.Gui
[CommandUpdateHandler (EditCommands.UppercaseSelection)]
protected void OnUppercaseSelection (CommandInfo info)
{
- IEditableTextBuffer buffer = GetContent <IEditableTextBuffer> ();
+ var buffer = GetContent <TextEditor> ();
info.Enabled = buffer != null;
}
[CommandHandler (EditCommands.LowercaseSelection)]
public void OnLowercaseSelection ()
{
- IEditableTextBuffer buffer = GetContent <IEditableTextBuffer> ();
+ var buffer = GetContent <TextEditor> ();
if (buffer == null)
return;
string selectedText = buffer.SelectedText;
if (string.IsNullOrEmpty (selectedText)) {
- int pos = buffer.CursorPosition;
- string ch = buffer.GetText (pos, pos + 1);
+ int pos = buffer.CaretOffset;
+ string ch = buffer.GetTextAt (pos, pos + 1);
string lower = ch.ToLower ();
if (lower == ch) {
- buffer.CursorPosition = pos + 1;
+ buffer.CaretOffset = pos + 1;
return;
};
using (var undo = buffer.OpenUndoGroup ()) {
- buffer.DeleteText (pos, 1);
+ buffer.RemoveText (pos, 1);
buffer.InsertText (pos, lower);
- buffer.CursorPosition = pos + 1;
+ buffer.CaretOffset = pos + 1;
}
} else {
string newText = selectedText.ToLower ();
if (newText == selectedText)
return;
- int startPos = buffer.SelectionStartPosition;
+ int startPos = buffer.SelectionRange.Offset;
using (var undo = buffer.OpenUndoGroup ()) {
- buffer.DeleteText (startPos, selectedText.Length);
+ buffer.RemoveText (startPos, selectedText.Length);
buffer.InsertText (startPos, newText);
- buffer.Select (startPos, startPos + newText.Length);
+ buffer.SetSelection (startPos, startPos + newText.Length);
}
}
}
@@ -315,7 +316,7 @@ namespace MonoDevelop.Ide.Gui
[CommandUpdateHandler (EditCommands.LowercaseSelection)]
protected void OnLowercaseSelection (CommandInfo info)
{
- IEditableTextBuffer buffer = GetContent <IEditableTextBuffer> ();
+ var buffer = GetContent <TextEditor> ();
info.Enabled = buffer != null;
}
@@ -346,69 +347,68 @@ namespace MonoDevelop.Ide.Gui
[CommandHandler (TextEditorCommands.LineEnd)]
protected void OnLineEnd ()
{
- Mono.TextEditor.CaretMoveActions.LineEnd (doc.Editor);
+ doc.Editor.EditorActionHost.MoveCaretToLineEnd ();
}
[CommandHandler (TextEditorCommands.LineStart)]
protected void OnLineStart ()
{
- Mono.TextEditor.CaretMoveActions.LineStart (doc.Editor);
+ doc.Editor.EditorActionHost.MoveCaretToLineStart ();
}
[CommandHandler (TextEditorCommands.DeleteLeftChar)]
protected void OnDeleteLeftChar ()
{
- Mono.TextEditor.CaretMoveActions.Left (doc.Editor);
- Mono.TextEditor.DeleteActions.Delete (doc.Editor);
+ doc.Editor.EditorActionHost.Backspace ();
}
[CommandHandler (TextEditorCommands.DeleteRightChar)]
protected void OnDeleteRightChar ()
{
- Mono.TextEditor.DeleteActions.Delete (doc.Editor);
+ doc.Editor.EditorActionHost.Delete ();
}
[CommandHandler (TextEditorCommands.CharLeft)]
protected void OnCharLeft ()
{
- Mono.TextEditor.CaretMoveActions.Left (doc.Editor);
+ doc.Editor.EditorActionHost.MoveCaretLeft ();
}
[CommandHandler (TextEditorCommands.CharRight)]
protected void OnCharRight ()
{
- Mono.TextEditor.CaretMoveActions.Right (doc.Editor);
+ doc.Editor.EditorActionHost.MoveCaretRight ();
}
[CommandHandler (TextEditorCommands.LineUp)]
protected void OnLineUp ()
{
- Mono.TextEditor.CaretMoveActions.Up (doc.Editor);
+ doc.Editor.EditorActionHost.MoveCaretUp ();
}
[CommandHandler (TextEditorCommands.LineDown)]
protected void OnLineDown ()
{
- Mono.TextEditor.CaretMoveActions.Down (doc.Editor);
+ doc.Editor.EditorActionHost.MoveCaretDown ();
}
[CommandHandler (TextEditorCommands.DocumentStart)]
protected void OnDocumentStart ()
{
- Mono.TextEditor.CaretMoveActions.ToDocumentStart (doc.Editor);
+ doc.Editor.EditorActionHost.MoveCaretToDocumentStart ();
}
[CommandHandler (TextEditorCommands.DocumentEnd)]
protected void OnDocumentEnd ()
{
- Mono.TextEditor.CaretMoveActions.ToDocumentEnd (doc.Editor);
+ doc.Editor.EditorActionHost.MoveCaretToDocumentEnd ();
}
[CommandHandler (TextEditorCommands.DeleteLine)]
protected void OnDeleteLine ()
{
- var line = doc.Editor.Document.GetLine (doc.Editor.Caret.Line);
- doc.Editor.Remove (line.Offset, line.LengthIncludingDelimiter);
+ var line = doc.Editor.GetLine (doc.Editor.CaretLocation.Line);
+ doc.Editor.RemoveText (line.Offset, line.LengthIncludingDelimiter);
}
struct RemoveInfo
@@ -435,7 +435,7 @@ namespace MonoDevelop.Ide.Gui
return ch == ' ' || ch == '\t' || ch == '\v';
}
- public static RemoveInfo GetRemoveInfo (Mono.TextEditor.TextDocument document, ref int pos)
+ public static RemoveInfo GetRemoveInfo (TextEditor document, ref int pos)
{
int len = 0;
while (pos > 0 && IsWhiteSpace (document.GetCharAt (pos))) {
@@ -458,22 +458,22 @@ namespace MonoDevelop.Ide.Gui
[CommandHandler (EditCommands.RemoveTrailingWhiteSpaces)]
public void OnRemoveTrailingWhiteSpaces ()
{
- Mono.TextEditor.TextEditorData data = doc.Editor;
+ var data = doc.Editor;
if (data == null)
return;
System.Collections.Generic.List<RemoveInfo> removeList = new System.Collections.Generic.List<RemoveInfo> ();
- int pos = data.Document.TextLength - 1;
- RemoveInfo removeInfo = RemoveInfo.GetRemoveInfo (data.Document, ref pos);
+ int pos = data.Length - 1;
+ RemoveInfo removeInfo = RemoveInfo.GetRemoveInfo (data, ref pos);
if (!removeInfo.IsEmpty)
removeList.Add (removeInfo);
while (pos >= 0) {
- char ch = data.Document.GetCharAt (pos);
+ char ch = data.GetCharAt (pos);
if (ch == '\n' || ch == '\r') {
- if (RemoveInfo.IsWhiteSpace (data.Document.GetCharAt (pos - 1))) {
+ if (RemoveInfo.IsWhiteSpace (data.GetCharAt (pos - 1))) {
--pos;
- removeInfo = RemoveInfo.GetRemoveInfo (data.Document, ref pos);
+ removeInfo = RemoveInfo.GetRemoveInfo (data, ref pos);
if (!removeInfo.IsEmpty)
removeList.Add (removeInfo);
}
@@ -482,8 +482,7 @@ namespace MonoDevelop.Ide.Gui
}
using (var undo = data.OpenUndoGroup ()) {
foreach (var info in removeList) {
- data.Document.Remove (info.Position, info.Length);
- data.Document.CommitLineUpdate (data.Document.OffsetToLineNumber (info.Position));
+ data.RemoveText (info.Position, info.Length);
}
}
}
@@ -491,7 +490,7 @@ namespace MonoDevelop.Ide.Gui
[CommandUpdateHandler (EditCommands.RemoveTrailingWhiteSpaces)]
protected void OnRemoveTrailingWhiteSpaces (CommandInfo info)
{
- info.Enabled = GetContent <IEditableTextBuffer> () != null;
+ info.Enabled = GetContent <TextEditor> () != null;
}
#region Folding
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 d53c7c1c9c..ff8260efa1 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs
@@ -51,6 +51,7 @@ using MonoDevelop.Ide.Navigation;
using MonoDevelop.Components.Docking;
using MonoDevelop.Components.DockNotebook;
using System.Text;
+using MonoDevelop.Ide.Editor;
namespace MonoDevelop.Ide.Gui
{
@@ -441,6 +442,25 @@ namespace MonoDevelop.Ide.Gui
return OpenDocument (openFileInfo);
}
+ static void ScrollToRequestedCaretLocation (Document doc, FileOpenInformation info)
+ {
+ var ipos = doc.Editor;
+ if ((info.Line >= 1 || info.Offset >= 0) && ipos != null) {
+ doc.DisableAutoScroll ();
+ doc.RunWhenLoaded (() => {
+ var loc = new DocumentLocation (info.Line, info.Column >= 1 ? info.Column : 1);
+ if (info.Offset >= 0) {
+ loc = ipos.OffsetToLocation (info.Offset);
+ }
+ if (loc.IsEmpty)
+ return;
+ ipos.SetCaretLocation (loc, info.Options.HasFlag (OpenDocumentOptions.HighlightCaretLine));
+ if (info.Options.HasFlag (OpenDocumentOptions.CenterCaretLine))
+ ipos.CenterToCaret ();
+ });
+ }
+ }
+
internal Document OpenDocument (FilePath fileName, Project project, int line, int column, OpenDocumentOptions options, Encoding Encoding, IViewDisplayBinding binding, DockNotebook dockNotebook)
{
var openFileInfo = new FileOpenInformation (fileName, project) {
@@ -455,7 +475,6 @@ namespace MonoDevelop.Ide.Gui
return OpenDocument (openFileInfo);
}
-
public Document OpenDocument (FileOpenInformation info)
{
if (string.IsNullOrEmpty (info.FileName))
@@ -481,18 +500,7 @@ namespace MonoDevelop.Ide.Gui
doc.SetProject (info.Project);
}
- IEditableTextBuffer ipos = (IEditableTextBuffer) vcFound.GetContent (typeof(IEditableTextBuffer));
- if (info.Line >= 1 && ipos != null) {
- doc.DisableAutoScroll ();
- doc.RunWhenLoaded (() =>
- ipos.SetCaretTo (
- info.Line,
- info.Column >= 1 ? info.Column : 1,
- info.Options.HasFlag (OpenDocumentOptions.HighlightCaretLine),
- info.Options.HasFlag (OpenDocumentOptions.CenterCaretLine)
- )
- );
- }
+ ScrollToRequestedCaretLocation (doc, info);
if (info.Options.HasFlag (OpenDocumentOptions.BringToFront)) {
doc.Select ();
@@ -518,6 +526,9 @@ namespace MonoDevelop.Ide.Gui
if (info.NewContent != null) {
Counters.OpenDocumentTimer.Trace ("Wrapping document");
Document doc = WrapDocument (info.NewContent.WorkbenchWindow);
+
+ ScrollToRequestedCaretLocation (doc, info);
+
if (doc != null && info.Options.HasFlag (OpenDocumentOptions.BringToFront)) {
doc.RunWhenLoaded (() => {
if (doc.Window != null)
@@ -577,7 +588,7 @@ namespace MonoDevelop.Ide.Gui
if (binding == null)
throw new ApplicationException("Can't create display binding for mime type: " + mimeType);
- IViewContent newContent = binding.CreateContent (null, mimeType, null);
+ IViewContent newContent = binding.CreateContent (defaultName, mimeType, null);
using (content) {
newContent.LoadNew (content, mimeType);
}
@@ -588,9 +599,8 @@ namespace MonoDevelop.Ide.Gui
newContent.UntitledName = defaultName;
newContent.IsDirty = true;
- workbench.ShowView (newContent, true);
- DisplayBindingService.AttachSubWindows (newContent.WorkbenchWindow, binding);
-
+ workbench.ShowView (newContent, true, binding);
+
var document = WrapDocument (newContent.WorkbenchWindow);
document.StartReparseThread ();
return document;
@@ -979,8 +989,8 @@ namespace MonoDevelop.Ide.Gui
var dp = new DocumentUserPrefs ();
dp.FileName = FileService.AbsoluteToRelativePath (args.Item.BaseDirectory, document.FileName);
if (document.Editor != null) {
- dp.Line = document.Editor.Caret.Line;
- dp.Column = document.Editor.Caret.Column;
+ dp.Line = document.Editor.CaretLine;
+ dp.Column = document.Editor.CaretColumn;
}
return dp;
}
@@ -1161,6 +1171,7 @@ namespace MonoDevelop.Ide.Gui
ThreadPool.QueueUserWorkItem (delegate {
lock (fileStatusLock) {
// DateTime t = DateTime.Now;
+
if (fileStatus == null)
return;
List<FilePath> modified = new List<FilePath> (fileStatus.Count);
@@ -1257,7 +1268,30 @@ namespace MonoDevelop.Ide.Gui
}
}
}
-
+
+ public class FileSaveInformation
+ {
+ FilePath fileName;
+ public FilePath FileName {
+ get {
+ return fileName;
+ }
+ set {
+ fileName = value.CanonicalPath;
+ if (fileName.IsNullOrEmpty)
+ LoggingService.LogError ("FileName == null\n" + Environment.StackTrace);
+ }
+ }
+
+ public Encoding Encoding { get; set; }
+
+ public FileSaveInformation (FilePath fileName, Encoding encoding = null)
+ {
+ this.FileName = fileName;
+ this.Encoding = encoding;
+ }
+ }
+
public class FileOpenInformation
{
FilePath fileName;
@@ -1266,19 +1300,29 @@ namespace MonoDevelop.Ide.Gui
return fileName;
}
set {
- fileName = FileService.ResolveFullPath (value.CanonicalPath);
+ fileName = value.CanonicalPath.ResolveLinks ();
if (fileName.IsNullOrEmpty)
LoggingService.LogError ("FileName == null\n" + Environment.StackTrace);
}
}
public OpenDocumentOptions Options { get; set; }
+ int offset = -1;
+ public int Offset {
+ get {
+ return offset;
+ }
+ set {
+ offset = value;
+ }
+ }
public int Line { get; set; }
public int Column { get; set; }
public IViewDisplayBinding DisplayBinding { get; set; }
public IViewContent NewContent { get; set; }
public Encoding Encoding { get; set; }
public Project Project { get; set; }
+
internal DockNotebook DockNotebook { get; set; }
[Obsolete("Use FileOpenInformation (FilePath filePath, Project project, int line, int column, OpenDocumentOptions options)")]
@@ -1291,7 +1335,7 @@ namespace MonoDevelop.Ide.Gui
}
- public FileOpenInformation (FilePath filePath, Project project)
+ public FileOpenInformation (FilePath filePath, Project project = null)
{
this.FileName = filePath;
this.Project = project;
@@ -1393,12 +1437,8 @@ namespace MonoDevelop.Ide.Gui
Counters.OpenDocumentTimer.Trace ("Loading file");
- IEncodedTextContent etc = (IEncodedTextContent) newContent.GetContent (typeof(IEncodedTextContent));
try {
- if (fileInfo.Encoding != null && etc != null)
- etc.Load (fileName, fileInfo.Encoding);
- else
- newContent.Load (fileName);
+ newContent.Load (fileInfo);
} catch (InvalidEncodingException iex) {
monitor.ReportError (GettextCatalog.GetString ("The file '{0}' could not opened. {1}", fileName, iex.Message), null);
return;
@@ -1420,14 +1460,14 @@ namespace MonoDevelop.Ide.Gui
Counters.OpenDocumentTimer.Trace ("Showing view");
- workbench.ShowView (newContent, fileInfo.Options.HasFlag (OpenDocumentOptions.BringToFront), fileInfo.DockNotebook);
+ workbench.ShowView (newContent, fileInfo.Options.HasFlag (OpenDocumentOptions.BringToFront), binding, fileInfo.DockNotebook);
- DisplayBindingService.AttachSubWindows (newContent.WorkbenchWindow, binding);
newContent.WorkbenchWindow.DocumentType = binding.Name;
- IEditableTextBuffer ipos = (IEditableTextBuffer) newContent.GetContent (typeof(IEditableTextBuffer));
+
+ var ipos = (TextEditor) newContent.GetContent (typeof(TextEditor));
if (fileInfo.Line > 0 && ipos != null) {
- Mono.TextEditor.Utils.FileSettingsStore.Remove (fileName);
+ FileSettingsStore.Remove (fileName);
ipos.RunWhenLoaded (JumpToLine);
}
@@ -1436,8 +1476,12 @@ namespace MonoDevelop.Ide.Gui
void JumpToLine ()
{
- IEditableTextBuffer ipos = (IEditableTextBuffer) newContent.GetContent (typeof(IEditableTextBuffer));
- ipos.SetCaretTo (Math.Max(1, fileInfo.Line), Math.Max(1, fileInfo.Column), fileInfo.Options.HasFlag (OpenDocumentOptions.HighlightCaretLine));
+ var ipos = (TextEditor) newContent.GetContent (typeof(TextEditor));
+ var loc = new DocumentLocation (Math.Max(1, fileInfo.Line), Math.Max(1, fileInfo.Column));
+ if (fileInfo.Offset >= 0) {
+ loc = ipos.OffsetToLocation (fileInfo.Offset);
+ }
+ ipos.SetCaretLocation (loc, fileInfo.Options.HasFlag (OpenDocumentOptions.HighlightCaretLine));
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/WorkbenchWindow.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/WorkbenchWindow.cs
index 92ed672f84..06098c686c 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/WorkbenchWindow.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/WorkbenchWindow.cs
@@ -26,6 +26,7 @@
using System;
using System.Collections.Generic;
+using MonoDevelop.Components;
namespace MonoDevelop.Ide.Gui
{
@@ -35,7 +36,7 @@ namespace MonoDevelop.Ide.Gui
public WorkbenchWindow (): base (Gtk.WindowType.Toplevel)
{
- Mono.TextEditor.GtkWorkarounds.FixContainerLeak (this);
+ GtkWorkarounds.FixContainerLeak (this);
this.Role = "workbench";
}
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..934c975f87 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/NavigationHistoryService.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/NavigationHistoryService.cs
@@ -159,7 +159,7 @@ namespace MonoDevelop.Ide.Navigation
return point;
}
- IEditableTextBuffer editBuf = doc.GetContent<IEditableTextBuffer> ();
+ var editBuf = doc.Editor;
if (editBuf != null) {
point = new TextFileNavigationPoint (doc, editBuf);
if (point != null)
@@ -291,8 +291,8 @@ namespace MonoDevelop.Ide.Navigation
currentDoc.Closed += HandleCurrentDocClosed;
if (currentDoc.Editor != null) {
- currentDoc.Editor.Document.TextReplaced += BufferTextChanged;
- currentDoc.Editor.Caret.PositionChanged += BufferCaretPositionChanged;
+ currentDoc.Editor.TextChanged += BufferTextChanged;
+ currentDoc.Editor.CaretPositionChanged += BufferCaretPositionChanged;
}
}
@@ -308,8 +308,8 @@ namespace MonoDevelop.Ide.Navigation
currentDoc.Closed -= HandleCurrentDocClosed;
if (currentDoc.Editor != null) {
- currentDoc.Editor.Document.TextReplaced -= BufferTextChanged;
- currentDoc.Editor.Caret.PositionChanged -= BufferCaretPositionChanged;
+ currentDoc.Editor.TextChanged -= BufferTextChanged;
+ currentDoc.Editor.CaretPositionChanged -= BufferCaretPositionChanged;
}
currentDoc = null;
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/TextFileNavigationPoint.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/TextFileNavigationPoint.cs
index 82087312c9..d17c03e0c9 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/TextFileNavigationPoint.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/TextFileNavigationPoint.cs
@@ -31,6 +31,7 @@ using System;
using MonoDevelop.Ide.Gui.Content;
using MonoDevelop.Core;
using MonoDevelop.Ide.Gui;
+using MonoDevelop.Ide.Editor;
namespace MonoDevelop.Ide.Navigation
{
@@ -39,10 +40,12 @@ namespace MonoDevelop.Ide.Navigation
int line;
int column;
- public TextFileNavigationPoint (Document doc, IEditableTextBuffer buffer)
+ public TextFileNavigationPoint (Document doc, TextEditor buffer)
: base (doc)
{
- buffer.GetLineColumnFromPosition (buffer.CursorPosition, out line, out column);
+ var location = buffer.CaretLocation;
+ line = location.Line;
+ column = location.Column;
}
public TextFileNavigationPoint (FilePath file, int line, int column)
@@ -79,11 +82,11 @@ namespace MonoDevelop.Ide.Navigation
{
Document doc = base.DoShow ();
if (doc != null) {
- IEditableTextBuffer buf = doc.GetContent<IEditableTextBuffer> ();
+ var buf = doc.Editor;
if (buf != null) {
doc.DisableAutoScroll ();
buf.RunWhenLoaded (() => {
- buf.SetCaretTo (Math.Max (line, 1), Math.Max (column, 1));
+ buf.SetCaretLocation (Math.Max (line, 1), Math.Max (column, 1));
});
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.ProgressMonitoring/MultiTaskDialogProgressMonitor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.ProgressMonitoring/MultiTaskDialogProgressMonitor.cs
index ac66b89aef..2cd7be2053 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.ProgressMonitoring/MultiTaskDialogProgressMonitor.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.ProgressMonitoring/MultiTaskDialogProgressMonitor.cs
@@ -34,6 +34,7 @@ using MonoDevelop.Core;
using MonoDevelop.Core.ProgressMonitoring;
using MonoDevelop.Ide.Gui.Dialogs;
using MonoDevelop.Ide.Gui;
+using MonoDevelop.Components;
namespace MonoDevelop.Ide.ProgressMonitoring
{
@@ -74,7 +75,7 @@ namespace MonoDevelop.Ide.ProgressMonitoring
TransientFor = parent,
};
MessageService.PlaceDialog (dialog, parent);
- Mono.TextEditor.GtkWorkarounds.PresentWindowWithNotification (dialog);
+ GtkWorkarounds.PresentWindowWithNotification (dialog);
dialog.CancellationTokenSource = CancellationTokenSource;
DispatchService.RunPendingEvents ();
this.showDetails = showDetails;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ApplyPolicyDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ApplyPolicyDialog.cs
index e5d8570872..876fd4dc31 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ApplyPolicyDialog.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ApplyPolicyDialog.cs
@@ -30,6 +30,7 @@ using MonoDevelop.Ide;
using MonoDevelop.Core;
using System.Collections.Generic;
using System.Text;
+using MonoDevelop.Components;
namespace MonoDevelop.Ide.Projects
{
@@ -206,7 +207,7 @@ namespace MonoDevelop.Ide.Projects
return true;
}
- using (var layout = Mono.TextEditor.PangoUtil.CreateLayout (this)) {
+ using (var layout = PangoUtil.CreateLayout (this)) {
layout.SetMarkup ("<i>" + GLib.Markup.EscapeText (message) + "</i>");
int w, h;
layout.GetPixelSize (out w, out h);
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 4d2ea70c0d..3a19b8397c 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AssemblyReferencePanel.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AssemblyReferencePanel.cs
@@ -283,7 +283,7 @@ namespace MonoDevelop.Ide.Projects
{
StringBuilder result = new StringBuilder ();
int lastPos = 0;
- var color = Mono.TextEditor.HslColor.GenerateHighlightColors (widget.Style.Base (StateType.Normal),
+ var color = HslColor.GenerateHighlightColors (widget.Style.Base (StateType.Normal),
widget.Style.Text (StateType.Normal), 3)[2];
for (int n=0; n < matches.Length; n++) {
int pos = matches[n] - startIndex;
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 c1b7cfd6b7..a6477cfad3 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
@@ -75,7 +75,6 @@ namespace MonoDevelop.Ide.Projects
WidthRequest = 901;
HeightRequest = 632;
- Modal = true;
Name = "wizard_dialog";
Title = GettextCatalog.GetString ("New Project");
WindowPosition = WindowPosition.CenterOnParent;
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 155bfca65d..473abc0799 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewProjectController.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewProjectController.cs
@@ -195,7 +195,7 @@ namespace MonoDevelop.Ide.Projects
if (BasePath == null)
BasePath = IdeApp.ProjectOperations.ProjectsDefaultPath;
- projectConfiguration.Location = FileService.ResolveFullPath (BasePath);
+ projectConfiguration.Location = new FilePath (BasePath).ResolveLinks ();
}
void SetDefaultGitSettings ()
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/PackageReferencePanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/PackageReferencePanel.cs
index ad2aa73f1a..81850c4eb2 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/PackageReferencePanel.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/PackageReferencePanel.cs
@@ -240,7 +240,7 @@ namespace MonoDevelop.Ide.Projects
{
StringBuilder result = new StringBuilder ();
int lastPos = 0;
- var color = Mono.TextEditor.HslColor.GenerateHighlightColors (widget.Style.Base (StateType.Normal),
+ var color = HslColor.GenerateHighlightColors (widget.Style.Base (StateType.Normal),
widget.Style.Text (StateType.Normal), 3)[2];
for (int n=0; n < matches.Length; n++) {
int pos = matches[n] - startIndex;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/SelectReferenceDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/SelectReferenceDialog.cs
index c8a995266b..6504bf4fc7 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/SelectReferenceDialog.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/SelectReferenceDialog.cs
@@ -30,15 +30,12 @@ using System.Linq;
using MonoDevelop.Projects;
using MonoDevelop.Core;
-using MonoDevelop.Core.Assemblies;
using Gtk;
using System.Collections.Generic;
using MonoDevelop.Components;
-using MonoDevelop.Ide.Commands;
using MonoDevelop.Components.Commands;
using System.IO;
-using Mono.TextEditor;
namespace MonoDevelop.Ide.Projects
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/CommentTasksChangedEventHandler.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/CommentTasksChangedEventHandler.cs
index 514601b9f1..945cd9a5fb 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/CommentTasksChangedEventHandler.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/CommentTasksChangedEventHandler.cs
@@ -33,11 +33,11 @@ namespace MonoDevelop.Ide.Tasks
{
public class CommentTasksChangedEventArgs : EventArgs
{
- string filename;
- IList<Tag> tagComments;
- Project project;
+ readonly string filename;
+ readonly IReadOnlyList<Tag> tagComments;
+ readonly Project project;
- public CommentTasksChangedEventArgs (string filename, IList<Tag> tagComments, Project project)
+ public CommentTasksChangedEventArgs (string filename, IReadOnlyList<Tag> tagComments, Project project)
{
this.filename = filename;
this.tagComments = tagComments;
@@ -46,7 +46,7 @@ namespace MonoDevelop.Ide.Tasks
public string FileName { get { return filename; } }
- public IList<Tag> TagComments { get { return tagComments; } }
+ public IReadOnlyList<Tag> TagComments { get { return tagComments; } }
public Project Project { get { return project; } }
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/CommentTasksView.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/CommentTasksView.cs
index b01e917033..509f2998b7 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/CommentTasksView.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/CommentTasksView.cs
@@ -36,10 +36,11 @@ using MonoDevelop.Core;
using MonoDevelop.Projects;
using MonoDevelop.Ide;
using MonoDevelop.Ide.Gui;
-using MonoDevelop.Projects.Text;
using MonoDevelop.Ide.TypeSystem;
-using ICSharpCode.NRefactory.TypeSystem;
using System.Linq;
+using MonoDevelop.Ide.Editor;
+using System.Threading;
+using System.Threading.Tasks;
namespace MonoDevelop.Ide.Tasks
{
@@ -83,9 +84,12 @@ namespace MonoDevelop.Ide.Tasks
TaskService.CommentTasksChanged += OnCommentTasksChanged;
CommentTag.SpecialCommentTagsChanged += OnCommentTagsChanged;
- IdeApp.Workspace.WorkspaceItemLoaded += OnWorkspaceItemLoaded;
+
+ MonoDevelopWorkspace.LoadingFinished += OnWorkspaceItemLoaded;
IdeApp.Workspace.WorkspaceItemUnloaded += OnWorkspaceItemUnloaded;
-
+ IdeApp.Workbench.DocumentOpened += WorkbenchDocumentOpened;
+ IdeApp.Workbench.DocumentClosed += WorkbenchDocumentClosed;;
+
highPrioColor = StringToColor ((string)PropertyService.Get ("Monodevelop.UserTasksHighPrioColor", ""));
normalPrioColor = StringToColor ((string)PropertyService.Get ("Monodevelop.UserTasksNormalPrioColor", ""));
lowPrioColor = StringToColor ((string)PropertyService.Get ("Monodevelop.UserTasksLowPrioColor", ""));
@@ -124,15 +128,8 @@ namespace MonoDevelop.Ide.Tasks
col.Resizable = true;
LoadColumnsVisibility ();
-
- comments.BeginTaskUpdates ();
- try {
- foreach (var item in IdeApp.Workspace.Items) {
- LoadWorkspaceItemContents (item);
- }
- } finally {
- comments.EndTaskUpdates ();
- }
+
+ OnWorkspaceItemLoaded (null, EventArgs.Empty);
comments.TasksAdded += GeneratedTaskAdded;
comments.TasksRemoved += GeneratedTaskRemoved;
@@ -147,7 +144,7 @@ namespace MonoDevelop.Ide.Tasks
view.RowActivated -= OnRowActivated;
TaskService.CommentTasksChanged -= OnCommentTasksChanged;
CommentTag.SpecialCommentTagsChanged -= OnCommentTagsChanged;
- IdeApp.Workspace.WorkspaceItemLoaded -= OnWorkspaceItemLoaded;
+ MonoDevelopWorkspace.LoadingFinished -= OnWorkspaceItemLoaded;
IdeApp.Workspace.WorkspaceItemUnloaded -= OnWorkspaceItemUnloaded;
comments.TasksAdded -= GeneratedTaskAdded;
comments.TasksRemoved -= GeneratedTaskRemoved;
@@ -156,6 +153,38 @@ namespace MonoDevelop.Ide.Tasks
};
}
+ void WorkbenchDocumentClosed (object sender, DocumentEventArgs e)
+ {
+ e.Document.DocumentParsed -= HandleDocumentParsed;
+ }
+
+ void WorkbenchDocumentOpened (object sender, DocumentEventArgs e)
+ {
+ e.Document.DocumentParsed += HandleDocumentParsed;
+ }
+
+ void HandleDocumentParsed (object sender, EventArgs e)
+ {
+ var doc = (Document)sender;
+ var pd = doc.ParsedDocument;
+ var project = doc.Project;
+ if (pd == null || project == null)
+ return;
+ ProjectCommentTags tags;
+ if (!projectTags.TryGetValue (project, out tags))
+ return;
+ var token = src.Token;
+ var file = doc.FileName;
+ Task.Run (async () => {
+ try {
+ tags.UpdateTags (project, file, await pd.GetTagCommentsAsync (token));
+ } catch (TaskCanceledException) {
+ } catch (AggregateException ae) {
+ ae.Flatten ().Handle (x => x is TaskCanceledException);
+ }
+ });
+ }
+
void LoadColumnsVisibility ()
{
string columns = (string)PropertyService.Get ("Monodevelop.CommentTasksColumns", "TRUE;TRUE;TRUE;TRUE");
@@ -181,76 +210,66 @@ namespace MonoDevelop.Ide.Tasks
PropertyService.Set ("Monodevelop.CommentTasksColumns", columns);
}
- void OnWorkspaceItemLoaded (object sender, WorkspaceItemEventArgs e)
+ void OnWorkspaceItemLoaded (object sender, EventArgs e)
{
comments.BeginTaskUpdates ();
try {
- LoadWorkspaceItemContents (e.Item);
+ foreach (var sln in IdeApp.Workspace.GetAllSolutions ())
+ LoadSolutionContents (sln);
}
finally {
comments.EndTaskUpdates ();
}
}
-
- void LoadWorkspaceItemContents (WorkspaceItem wob)
- {
- foreach (var sln in wob.GetAllItems<Solution> ())
- LoadSolutionContents (sln);
- }
- void UpdateCommentTagsForProject (Solution solution, Project project)
+ Dictionary<Project, ProjectCommentTags> projectTags = new Dictionary<Project, ProjectCommentTags> ();
+ CancellationTokenSource src = new CancellationTokenSource ();
+ void UpdateCommentTagsForProject (Solution solution, Project project, CancellationToken token)
{
- var ctx = TypeSystemService.GetProjectContentWrapper (project);
- if (ctx == null)
+ if (token.IsCancellationRequested)
return;
- var tags = ctx.GetExtensionObject<ProjectCommentTags> ();
- if (tags == null) {
+ ProjectCommentTags tags;
+ if (!projectTags.TryGetValue (project, out tags)) {
tags = new ProjectCommentTags ();
- ctx.UpdateExtensionObject (tags);
- tags.Update (ctx.Project);
- } else {
- foreach (var kv in tags.Tags) {
- UpdateCommentTags (solution, kv.Key, kv.Value);
- }
+ projectTags [project] = tags;
}
- }
-
- void HandleSolutionItemAdded (object sender, SolutionItemChangeEventArgs e)
- {
- var newProject = e.SolutionItem as Project;
- if (newProject == null)
- return;
- UpdateCommentTagsForProject (e.Solution, newProject);
+ var files = project.Files.ToArray ();
+ Task.Run (async () => {
+ try {
+ await tags.UpdateAsync (project, files, token);
+ } catch (TaskCanceledException) {
+ } catch (AggregateException ae) {
+ ae.Flatten ().Handle (x => x is TaskCanceledException);
+ } catch (Exception e) {
+ LoggingService.LogError ("Error while updating comment tags.", e);
+ }
+ });
}
void LoadSolutionContents (Solution sln)
{
+ src.Cancel ();
+ src = new CancellationTokenSource ();
+ var token = src.Token;
+
loadedSlns.Add (sln);
- System.Threading.ThreadPool.QueueUserWorkItem (delegate {
- sln.SolutionItemAdded += HandleSolutionItemAdded;
+ Task.Run (delegate {
+ sln.SolutionItemAdded += delegate(object sender, SolutionItemChangeEventArgs e) {
+ var newProject = e.SolutionItem as Project;
+ if (newProject == null)
+ return;
+ UpdateCommentTagsForProject (sln, newProject, token);
+ };
// Load all tags that are stored in pidb files
foreach (Project p in sln.GetAllProjects ()) {
- UpdateCommentTagsForProject (sln, p);
+ UpdateCommentTagsForProject (sln, p, token);
}
});
}
-
- static IEnumerable<Tag> GetSpecialComments (IProjectContent ctx, string name)
- {
- var doc = ctx.GetFile (name) as ParsedDocument;
- if (doc == null)
- return Enumerable.Empty<Tag> ();
- return (IEnumerable<Tag>)doc.TagComments;
- }
-
void OnWorkspaceItemUnloaded (object sender, WorkspaceItemEventArgs e)
{
- foreach (var sln in e.Item.GetAllItems<Solution>()) {
- if (loadedSlns.Remove (sln))
- sln.SolutionItemAdded -= HandleSolutionItemAdded;
- }
comments.RemoveItemTasks (e.Item, true);
}
@@ -506,7 +525,7 @@ namespace MonoDevelop.Ide.Tasks
{
TaskListEntry task = SelectedTask;
if (task != null && ! String.IsNullOrEmpty (task.FileName)) {
- Document doc = IdeApp.Workbench.OpenDocument (task.FileName, Math.Max (1, task.Line), Math.Max (1, task.Column));
+ var doc = IdeApp.Workbench.OpenDocument (task.FileName, Math.Max (1, task.Line), Math.Max (1, task.Column));
if (doc != null && doc.HasProject && doc.Project is DotNetProject) {
string[] commentTags = doc.CommentTags;
if (commentTags != null && commentTags.Length == 1) {
@@ -515,10 +534,11 @@ namespace MonoDevelop.Ide.Tasks
string line = doc.Editor.GetLineText (task.Line);
int index = line.IndexOf (commentTags[0]);
if (index != -1) {
- doc.Editor.SetCaretTo (task.Line, task.Column);
+ doc.Editor.CaretLocation = new DocumentLocation (task.Line, task.Column);
+ doc.Editor.StartCaretPulseAnimation ();
line = line.Substring (0, index);
- var ls = doc.Editor.Document.GetLine (task.Line);
- doc.Editor.Replace (ls.Offset, ls.Length, line);
+ var ls = doc.Editor.GetLine (task.Line);
+ doc.Editor.ReplaceText (ls.Offset, ls.Length, line);
comments.Remove (task);
}
});
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/ProjectCommentTags.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/ProjectCommentTags.cs
index c2b33ee0b0..9f9fcb9476 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/ProjectCommentTags.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/ProjectCommentTags.cs
@@ -29,11 +29,13 @@ using System.Collections.Generic;
using System.Collections.Concurrent;
using MonoDevelop.Projects;
using MonoDevelop.Ide.Tasks;
+using System.Threading;
+using MonoDevelop.Ide.TypeSystem;
+using System.Threading.Tasks;
-namespace MonoDevelop.Ide.TypeSystem
+namespace MonoDevelop.Ide.Tasks
{
- [Serializable]
- public class ProjectCommentTags
+ class ProjectCommentTags
{
readonly Dictionary<string, List<Tag>> tags = new Dictionary<string, List<Tag>> ();
@@ -43,7 +45,7 @@ namespace MonoDevelop.Ide.TypeSystem
}
}
- public void UpdateTags (Project project, string fileName, IList<Tag> tagComments)
+ public void UpdateTags (Project project, string fileName, IReadOnlyList<Tag> tagComments)
{
var list = tagComments == null || tagComments.Count == 0 ? null : new List<Tag> (tagComments);
lock (tags) {
@@ -67,14 +69,15 @@ namespace MonoDevelop.Ide.TypeSystem
TaskService.InformCommentTasks (new CommentTasksChangedEventArgs (fileName, null, project));
}
- internal void Update (Project project)
+ internal async Task UpdateAsync (Project project, ProjectFile[] files, CancellationToken token = default (CancellationToken))
{
- foreach (var file in project.Files) {
+ foreach (var file in files) {
if (file.BuildAction == BuildAction.None)
continue;
- TypeSystemService.ParseFile (project, file.FilePath);
+ var pd = await TypeSystemService.ParseFile (project, file.FilePath, token).ConfigureAwait (false);
+ if (pd != null)
+ UpdateTags (project, file.FilePath, await pd.GetTagCommentsAsync (token));
}
}
}
-}
-
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/UserTask.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/TaskListEntry.cs
index 9ddda8db4d..fb8db5ea77 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/UserTask.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/TaskListEntry.cs
@@ -1,5 +1,5 @@
//
-// Task.cs
+// TaskListEntry.cs
//
// Author:
// Lluis Sanchez Gual <lluis@novell.com>
@@ -31,7 +31,7 @@ using System.CodeDom.Compiler;
using MonoDevelop.Projects;
using MonoDevelop.Ide.Gui;
using MonoDevelop.Ide.Gui.Components;
-using MonoDevelop.Ide.Gui.Pads.ProjectPad;
+using MonoDevelop.Ide.Gui.Pads.ProjectPad;
using MonoDevelop.Core;
using MonoDevelop.Core.Serialization;
@@ -64,7 +64,7 @@ namespace MonoDevelop.Ide.Tasks
bool completed;
object owner;
- WorkspaceObject parentObject;
+ IWorkspaceObject parentObject;
internal int SavedLine;
public TaskListEntry (FilePath file, string description, int column, int line, TaskSeverity severity)
@@ -77,12 +77,12 @@ namespace MonoDevelop.Ide.Tasks
{
}
- public TaskListEntry (FilePath file, string description, int column, int line, TaskSeverity severity, TaskPriority priority, WorkspaceObject parent)
+ public TaskListEntry (FilePath file, string description, int column, int line, TaskSeverity severity, TaskPriority priority, IWorkspaceObject parent)
: this (file, description, column, line, severity, priority, parent, null)
{
}
- public TaskListEntry (FilePath file, string description, int column, int line, TaskSeverity severity, TaskPriority priority, WorkspaceObject parent, object owner)
+ public TaskListEntry (FilePath file, string description, int column, int line, TaskSeverity severity, TaskPriority priority, IWorkspaceObject parent, object owner)
{
this.file = file;
this.description = description;
@@ -106,7 +106,7 @@ namespace MonoDevelop.Ide.Tasks
public TaskListEntry (BuildError error, object owner)
{
- parentObject = error.SourceTarget as WorkspaceObject;
+ parentObject = error.SourceTarget;
file = error.FileName;
this.owner = owner;
description = error.ErrorText;
@@ -179,7 +179,7 @@ namespace MonoDevelop.Ide.Tasks
}
}
- public WorkspaceObject WorkspaceObject {
+ public IWorkspaceObject WorkspaceObject {
get {
return parentObject;
}
@@ -224,17 +224,17 @@ namespace MonoDevelop.Ide.Tasks
TaskService.InformJumpToTask (this);
}
- public bool BelongsToItem (WorkspaceObject item, bool checkHierarchy)
+ public bool BelongsToItem (IWorkspaceObject item, bool checkHierarchy)
{
if (!checkHierarchy)
return item == parentObject;
- WorkspaceObject cit = parentObject;
+ IWorkspaceObject cit = parentObject;
do {
if (cit == item)
return true;
- if (cit is SolutionFolderItem) {
- SolutionFolderItem si = (SolutionFolderItem) cit;
+ if (cit is SolutionItem) {
+ SolutionItem si = (SolutionItem) cit;
if (si.ParentFolder != null)
cit = si.ParentFolder;
else
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/TaskService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/TaskService.cs
index a00767d569..408d4189cb 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/TaskService.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/TaskService.cs
@@ -54,8 +54,10 @@ namespace MonoDevelop.Ide.Tasks
static TaskService ()
{
- IdeApp.Workspace.WorkspaceItemLoaded += OnWorkspaceItemLoaded;
- IdeApp.Workspace.WorkspaceItemUnloaded += OnWorkspaceItemUnloaded;
+ if (IdeApp.Workspace != null) {
+ IdeApp.Workspace.WorkspaceItemLoaded += OnWorkspaceItemLoaded;
+ IdeApp.Workspace.WorkspaceItemUnloaded += OnWorkspaceItemUnloaded;
+ }
errors.ItemName = GettextCatalog.GetString ("Warning/Error");
userTasks.ItemName = GettextCatalog.GetString ("User Task");
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/TaskStore.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/TaskStore.cs
index 5bc6c0215d..7db2b7aef8 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/TaskStore.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Tasks/TaskStore.cs
@@ -23,17 +23,17 @@
// 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.
-//------------------------------------------------------------------------------
-// <auto-generated>
-// This code was generated by a tool.
-// Runtime Version:2.0.50727.3074
-//
-// Changes to this file may cause incorrect behavior and will be lost if
-// the code is regenerated.
-// </auto-generated>
-//------------------------------------------------------------------------------
-
-using System;
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.3074
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+using System;
using System.Collections;
using System.Collections.Generic;
using MonoDevelop.Core;
@@ -42,12 +42,12 @@ using MonoDevelop.Ide.Gui;
using MonoDevelop.Ide.Gui.Content;
using MonoDevelop.Ide.Navigation;
using MonoDevelop.Ide.TextEditing;
-using MonoDevelop.Ide.Desktop;
-
-namespace MonoDevelop.Ide.Tasks
-{
- public class TaskStore: IEnumerable<TaskListEntry>, ILocationList
- {
+using MonoDevelop.Ide.Desktop;
+
+namespace MonoDevelop.Ide.Tasks
+{
+ public class TaskStore: IEnumerable<TaskListEntry>, ILocationList
+ {
int taskUpdateCount;
List<TaskListEntry> tasks = new List<TaskListEntry> ();
Dictionary<FilePath,TaskListEntry[]> taskIndex = new Dictionary<FilePath, TaskListEntry[]> ();
@@ -59,11 +59,13 @@ namespace MonoDevelop.Ide.Tasks
List<TaskListEntry> tasksAdded;
List<TaskListEntry> tasksRemoved;
- public TaskStore ()
- {
- IdeApp.Workspace.FileRenamedInProject += ProjectFileRenamed;
- IdeApp.Workspace.FileRemovedFromProject += ProjectFileRemoved;
-
+ public TaskStore ()
+ {
+ if (IdeApp.Workspace != null) {
+ IdeApp.Workspace.FileRenamedInProject += ProjectFileRenamed;
+ IdeApp.Workspace.FileRemovedFromProject += ProjectFileRemoved;
+ }
+
TextEditorService.LineCountChangesCommitted += delegate (object sender, TextFileEventArgs args) {
foreach (TaskListEntry task in GetFileTasks (args.TextFile.Name.FullPath))
task.SavedLine = -1;
@@ -198,7 +200,7 @@ namespace MonoDevelop.Ide.Tasks
yield return t;
}
}
-
+
public TaskListEntry[] GetFileTasks (FilePath file)
{
TaskListEntry[] ta;
@@ -523,7 +525,7 @@ namespace MonoDevelop.Ide.Tasks
}
#endregion
- }
+ }
public delegate void TaskEventHandler (object sender, TaskEventArgs e);
@@ -545,4 +547,4 @@ namespace MonoDevelop.Ide.Tasks
get { return tasks; }
}
}
-}
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/CodeDomFileDescriptionTemplate.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/CodeDomFileDescriptionTemplate.cs
index 3a57928536..964f13b1eb 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/CodeDomFileDescriptionTemplate.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/CodeDomFileDescriptionTemplate.cs
@@ -35,8 +35,8 @@ using System.CodeDom.Compiler;
using MonoDevelop.Projects;
-using MonoDevelop.Ide.Gui.Content;
using MonoDevelop.Core;
+using MonoDevelop.Ide.Editor;
namespace MonoDevelop.Ide.Templates
{
@@ -89,7 +89,7 @@ namespace MonoDevelop.Ide.Templates
static string StripHeaderAndBlankLines (string text, CodeDomProvider provider)
{
- Mono.TextEditor.TextDocument doc = new Mono.TextEditor.TextDocument ();
+ var doc = TextEditorFactory.CreateNewDocument ();
doc.Text = text;
int realStartLine = 0;
for (int i = 1; i <= doc.LineCount; i++) {
@@ -106,20 +106,20 @@ namespace MonoDevelop.Ide.Templates
// We reformat the C# generated output to the user's coding style anyway, but the reformatter preserves blank lines
if (provider is Microsoft.CSharp.CSharpCodeProvider) {
for (int i = 1; i <= doc.LineCount; i++) {
- Mono.TextEditor.DocumentLine line = doc.GetLine (i);
+ var line = doc.GetLine (i);
if (IsBlankLine (doc, line) && line.LengthIncludingDelimiter > 0) {
- doc.Remove (line.Offset, line.LengthIncludingDelimiter);
+ doc.RemoveText (line.Offset, line.LengthIncludingDelimiter);
i--;
continue;
}
}
}
- int offset = doc.GetLine (Math.Max(Mono.TextEditor.DocumentLocation.MinLine, realStartLine)).Offset;
- return doc.GetTextAt (offset, doc.TextLength - offset);
+ int offset = doc.GetLine (realStartLine).Offset;
+ return doc.GetTextAt (offset, doc.Length - offset);
}
- static bool IsBlankLine (Mono.TextEditor.TextDocument doc, Mono.TextEditor.DocumentLine line)
+ static bool IsBlankLine (IReadonlyTextDocument doc, IDocumentLine line)
{
for (int i = 0; i < line.Length; i++) {
if (!Char.IsWhiteSpace (doc.GetCharAt (line.Offset + i)))
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectTemplatingProvider.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectTemplatingProvider.cs
index d23660ee33..b47ae8a685 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectTemplatingProvider.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectTemplatingProvider.cs
@@ -76,8 +76,8 @@ namespace MonoDevelop.Ide.Templates
ProjectCreateInformation CreateProjectCreateInformation (NewProjectConfiguration config, SolutionFolder parentFolder)
{
ProjectCreateInformation cinfo = new ProjectCreateInformation ();
- cinfo.SolutionPath = FileService.ResolveFullPath (config.SolutionLocation);
- cinfo.ProjectBasePath = FileService.ResolveFullPath (config.ProjectLocation);
+ cinfo.SolutionPath = new FilePath (config.SolutionLocation).ResolveLinks ();
+ cinfo.ProjectBasePath = new FilePath (config.ProjectLocation).ResolveLinks ();
cinfo.ProjectName = config.ProjectName;
cinfo.SolutionName = config.SolutionName;
cinfo.ParentFolder = parentFolder;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/SingleFileDescriptionTemplate.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/SingleFileDescriptionTemplate.cs
index 62332a28b5..6c334b9185 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/SingleFileDescriptionTemplate.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/SingleFileDescriptionTemplate.cs
@@ -40,6 +40,7 @@ using MonoDevelop.Ide.StandardHeader;
using System.Text;
using MonoDevelop.Ide.Gui.Content;
using MonoDevelop.Ide.CodeFormatting;
+using MonoDevelop.Ide.Editor;
using MonoDevelop.Projects.SharedAssetsProjects;
using MonoDevelop.Core.StringParsing;
@@ -317,7 +318,7 @@ namespace MonoDevelop.Ide.Templates
ms.Write (data, 0, data.Length);
}
- Mono.TextEditor.TextDocument doc = new Mono.TextEditor.TextDocument ();
+ var doc = TextEditorFactory.CreateNewDocument ();
doc.Text = content;
TextStylePolicy textPolicy = policyParent != null ? policyParent.Policies.Get<TextStylePolicy> ("text/plain")
@@ -327,7 +328,7 @@ namespace MonoDevelop.Ide.Templates
var tabToSpaces = textPolicy.TabsToSpaces? new string (' ', textPolicy.TabWidth) : null;
- foreach (Mono.TextEditor.DocumentLine line in doc.Lines) {
+ foreach (var line in doc.GetLines ()) {
var lineText = doc.GetTextAt (line.Offset, line.Length);
if (tabToSpaces != null)
lineText = lineText.Replace ("\t", tabToSpaces);
@@ -400,8 +401,8 @@ namespace MonoDevelop.Ide.Templates
}
}
- tags ["Namespace"] = ns;
- if (policyParent != null)
+ tags ["Namespace"] = ns;
+ if (policyParent != null)
tags ["SolutionName"] = policyParent.Name;
if (project != null) {
tags ["ProjectName"] = project.Name;
@@ -418,7 +419,7 @@ namespace MonoDevelop.Ide.Templates
if (languageExtension.Length > 0)
tags ["LanguageExtension"] = languageExtension;
- if (fileName != FilePath.Null) {
+ if (fileName != FilePath.Null) {
FilePath fileDirectory = Path.GetDirectoryName (fileName);
if (project != null && project.BaseDirectory != FilePath.Null && fileDirectory.IsChildPathOf (project.BaseDirectory))
tags ["ProjectRelativeDirectory"] = fileDirectory.ToRelative (project.BaseDirectory);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/FileExtension.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/FileExtension.cs
index 03ea1cb117..d0ccd99bc7 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/FileExtension.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/FileExtension.cs
@@ -28,7 +28,6 @@
using System;
using System.Linq;
using MonoDevelop.Core;
-using Mono.TextEditor;
using System.Collections.Generic;
using MonoDevelop.Projects.Text;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/FileExtensionEventArgs.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/FileExtensionEventArgs.cs
index 876a9d2581..79d246e707 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/FileExtensionEventArgs.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/FileExtensionEventArgs.cs
@@ -27,7 +27,6 @@
using System;
using System.Linq;
using MonoDevelop.Core;
-using Mono.TextEditor;
using System.Collections.Generic;
using MonoDevelop.Projects.Text;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/FileLineExtension.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/FileLineExtension.cs
index ec22e90aff..b5278f365a 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/FileLineExtension.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/FileLineExtension.cs
@@ -27,7 +27,6 @@
using System;
using System.Linq;
using MonoDevelop.Core;
-using Mono.TextEditor;
using System.Collections.Generic;
using MonoDevelop.Projects.Text;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/HorizontalAlignment.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/HorizontalAlignment.cs
index 3863a5ea86..f124f748c7 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/HorizontalAlignment.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/HorizontalAlignment.cs
@@ -27,7 +27,6 @@
using System;
using System.Linq;
using MonoDevelop.Core;
-using Mono.TextEditor;
using System.Collections.Generic;
using MonoDevelop.Projects.Text;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/LineCountEventArgs.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/LineCountEventArgs.cs
index bf252a697c..95eb469c54 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/LineCountEventArgs.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/LineCountEventArgs.cs
@@ -27,7 +27,6 @@
using System;
using System.Linq;
using MonoDevelop.Core;
-using Mono.TextEditor;
using System.Collections.Generic;
using MonoDevelop.Projects.Text;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/TextEditorService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/TextEditorService.cs
index 595db9c80a..74385431b9 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/TextEditorService.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/TextEditorService.cs
@@ -27,7 +27,6 @@
using System;
using System.Linq;
using MonoDevelop.Core;
-using Mono.TextEditor;
using System.Collections.Generic;
using MonoDevelop.Projects.Text;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/TextFileEventArgs.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/TextFileEventArgs.cs
index d2c3a245c5..53c4ed6e41 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/TextFileEventArgs.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/TextFileEventArgs.cs
@@ -27,7 +27,6 @@
using System;
using System.Linq;
using MonoDevelop.Core;
-using Mono.TextEditor;
using System.Collections.Generic;
using MonoDevelop.Projects.Text;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/TextLineMarkerExtension.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/TextLineMarkerExtension.cs
index 6126390e80..67dee58ab2 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/TextLineMarkerExtension.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/TextLineMarkerExtension.cs
@@ -27,16 +27,14 @@
using System;
using System.Linq;
using MonoDevelop.Core;
-using Mono.TextEditor;
using System.Collections.Generic;
using MonoDevelop.Projects.Text;
+using MonoDevelop.Ide.Editor;
namespace MonoDevelop.Ide.TextEditing
{
-
public abstract class TextLineMarkerExtension: FileLineExtension
{
- public abstract TextLineMarker CreateMarker ();
- }
-
+ public abstract ITextLineMarker CreateMarker ();
}
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/VerticalAlignment.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/VerticalAlignment.cs
index 47f318f92e..d72bfb9e71 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/VerticalAlignment.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TextEditing/VerticalAlignment.cs
@@ -27,7 +27,6 @@
using System;
using System.Linq;
using MonoDevelop.Core;
-using Mono.TextEditor;
using System.Collections.Generic;
using MonoDevelop.Projects.Text;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/Ambience.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/Ambience.cs
index 65621369b2..07849bbe88 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/Ambience.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/Ambience.cs
@@ -30,51 +30,74 @@ using System;
using System.Text;
using System.Collections.Generic;
using MonoDevelop.Core;
-using ICSharpCode.NRefactory.TypeSystem;
using Mono.Cecil;
using System.Linq;
using MonoDevelop.Ide.CodeCompletion;
+using Microsoft.CodeAnalysis;
+using System.Threading;
+using System.Xml;
+using Mono.Addins;
+using MonoDevelop.Ide.Extensions;
namespace MonoDevelop.Ide.TypeSystem
{
- public abstract class Ambience
- {
- public string Name {
- get;
- private set;
- }
-
-
- public Ambience (string name)
- {
- this.Name = name;
- }
-
- #region To implement
- public abstract string GetIntrinsicTypeName (string reflectionName);
-
- public abstract string SingleLineComment (string text);
- public abstract string GetString (string nameSpace, OutputSettings settings);
-
- protected abstract string GetTypeReferenceString (IType reference, OutputSettings settings);
- protected abstract string GetTypeString (IType type, OutputSettings settings);
- protected abstract string GetMethodString (IMethod method, OutputSettings settings);
- protected abstract string GetConstructorString (IMethod constructor, OutputSettings settings);
- protected abstract string GetDestructorString (IMethod destructor, OutputSettings settings);
- protected abstract string GetOperatorString (IMethod op, OutputSettings settings);
-
- protected abstract string GetFieldString (IField field, OutputSettings settings);
- protected abstract string GetEventString (IEvent evt, OutputSettings settings);
- protected abstract string GetPropertyString (IProperty property, OutputSettings settings);
- protected abstract string GetIndexerString (IProperty property, OutputSettings settings);
- protected abstract string GetParameterString (IParameterizedMember member, IParameter parameter, OutputSettings settings);
-
- #endregion
-
- public virtual TooltipInformation GetTooltip (IEntity entity)
+ public static class Ambience
+ {
+ public static readonly SymbolDisplayFormat LabelFormat =
+ new SymbolDisplayFormat(
+ globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Omitted,
+ typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,
+ propertyStyle: SymbolDisplayPropertyStyle.NameOnly,
+ genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters | SymbolDisplayGenericsOptions.IncludeVariance,
+ memberOptions: SymbolDisplayMemberOptions.IncludeParameters | SymbolDisplayMemberOptions.IncludeExplicitInterface,
+ parameterOptions:
+ SymbolDisplayParameterOptions.IncludeDefaultValue |
+ SymbolDisplayParameterOptions.IncludeExtensionThis |
+ SymbolDisplayParameterOptions.IncludeType |
+ SymbolDisplayParameterOptions.IncludeName |
+ SymbolDisplayParameterOptions.IncludeParamsRefOut,
+ miscellaneousOptions:
+ SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers |
+ SymbolDisplayMiscellaneousOptions.UseSpecialTypes
+ );
+ /// <summary>
+ /// Standard format for displaying to the user.
+ /// </summary>
+ /// <remarks>
+ /// No return type.
+ /// </remarks>
+ public static readonly SymbolDisplayFormat NameFormat =
+ new SymbolDisplayFormat(
+ globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Omitted,
+ typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,
+ propertyStyle: SymbolDisplayPropertyStyle.NameOnly,
+ genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters | SymbolDisplayGenericsOptions.IncludeVariance,
+ memberOptions: SymbolDisplayMemberOptions.IncludeParameters | SymbolDisplayMemberOptions.IncludeExplicitInterface,
+ parameterOptions:
+ SymbolDisplayParameterOptions.IncludeParamsRefOut |
+ SymbolDisplayParameterOptions.IncludeExtensionThis |
+ SymbolDisplayParameterOptions.IncludeType |
+ SymbolDisplayParameterOptions.IncludeName,
+ miscellaneousOptions:
+ SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers |
+ SymbolDisplayMiscellaneousOptions.UseSpecialTypes);
+ static Ambience ()
{
- return null;
+ // may not have been initialized in testing environment.
+ if (AddinManager.IsInitialized) {
+ AddinManager.AddExtensionNodeHandler ("/MonoDevelop/TypeSystem/AmbienceTooltipProviders", delegate(object sender, ExtensionNodeEventArgs args) {
+ var node = args.ExtensionNode as MimeTypeExtensionNode;
+ switch (args.Change) {
+ case ExtensionChange.Add:
+ tooltipProviders.Add ((AmbienceTooltipProvider)node.CreateInstance ());
+ break;
+ case ExtensionChange.Remove:
+ tooltipProviders.Remove ((AmbienceTooltipProvider)node.CreateInstance ());
+ break;
+ }
+ });
+ }
}
public static string Format (string str)
@@ -86,104 +109,490 @@ namespace MonoDevelop.Ide.TypeSystem
MarkupUtilities.AppendEscapedString (sb, str);
return sb.ToString ();
}
+
+ #region Documentation
- protected static OutputFlags GetFlags (object settings)
+ public class DocumentationFormatOptions
{
- if (settings is OutputFlags)
- return (OutputFlags)settings;
- return ((OutputSettings)settings).OutputFlags;
+ public static readonly DocumentationFormatOptions Empty = new DocumentationFormatOptions ();
+ public string HighlightParameter {
+ get;
+ set;
+ }
+
+ public int MaxLineLength {
+ get;
+ set;
+ }
+
+ public bool BigHeadings {
+ get;
+ set;
+ }
+
+ public bool BoldHeadings {
+ get;
+ set;
+ }
+
+ public bool SmallText {
+ get;
+ set;
+ }
+
+
+ public DocumentationFormatOptions ()
+ {
+ BoldHeadings = true;
+ }
+
+ public string FormatHeading (string heading)
+ {
+ string result = heading;
+ if (BigHeadings)
+ result = "<big>" + result + "</big>";
+ if (BoldHeadings)
+ result = "<b>" + result + "</b>";
+ return result;
+ }
+
+ public string FormatBody (string body)
+ {
+ var str = body.Trim ();
+ if (string.IsNullOrEmpty (str))
+ return "";
+ return SmallText ? "<small>" + str + Environment.NewLine + "</small>" : str + Environment.NewLine;
+ }
+ }
+
+ public static string GetSummaryMarkup (ISymbol member, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (member == null)
+ return null;
+ string documentation = GetDocumentation (member);
+ if (string.IsNullOrEmpty (documentation))
+ return null;
+
+ if (!string.IsNullOrEmpty (documentation)) {
+ int idx1 = documentation.IndexOf ("<summary>", StringComparison.Ordinal);
+ int idx2 = documentation.LastIndexOf ("</summary>", StringComparison.Ordinal);
+ string result;
+ if (idx1 >= 0 && idx2 > idx1) {
+ try {
+ var xmlText = documentation.Substring (idx1, idx2 - idx1 + "</summary>".Length);
+ return ParseBody (member,
+ new XmlTextReader (xmlText, XmlNodeType.Element, null),
+ "summary",
+ DocumentationFormatOptions.Empty
+ );
+ } catch (Exception e) {
+ LoggingService.LogWarning ("Malformed documentation xml detected:" + documentation, e);
+ // may happen on malformed xml.
+ var len = idx2 - idx1 - "</summary>".Length;
+ result = len > 0 ? documentation.Substring (idx1 + "<summary>".Length, len) : documentation;
+ }
+ } else if (idx1 >= 0) {
+ result = documentation.Substring (idx1 + "<summary>".Length);
+ } else if (idx2 >= 0) {
+ result = documentation.Substring (0, idx2 - 1);
+ } else {
+ result = documentation;
+ }
+ return GetDocumentationMarkup (member, CleanEmpty (result));
+ }
+
+ return GetDocumentationMarkup (member, CleanEmpty (documentation));
}
- protected static OutputSettings GetSettings (object settings)
+ static string CleanEmpty (string doc)
+ {
+ return IsEmptyDocumentation (doc)? null : doc;
+ }
+
+ static bool IsEmptyDocumentation (string documentation)
{
- if (settings is OutputFlags)
- return new OutputSettings ((OutputFlags)settings);
- return (OutputSettings)settings;
+ return string.IsNullOrWhiteSpace (documentation) || documentation.StartsWith ("To be added") || documentation == "we have not entered docs yet";
}
- public string GetString (string nameSpace, OutputFlags flags)
+ public static string GetDocumentation (ISymbol member)
{
- return GetString (nameSpace, new OutputSettings (flags));
+ if (member == null)
+ return null;
+ var documentation = member.GetDocumentationCommentXml ();
+ if (string.IsNullOrEmpty (documentation))
+ documentation = MonoDocDocumentationProvider.GetDocumentation (member);
+ if (documentation != null)
+ return CleanEmpty (documentation);
+ return null;
}
- public string GetString (IEntity entity, OutputSettings settings)
- {
- if (entity == null) {
- string[] trace = Environment.StackTrace.Split (new [] { Environment.NewLine }, StringSplitOptions.None);
- return "null entity: " + (trace != null && trace.Length > 2 ? trace [2] : "unknown location");
- }
- string result = null;
- switch (entity.SymbolKind) {
- case SymbolKind.Constructor:
- result = GetConstructorString ((IMethod)entity, settings);
- break;
- case SymbolKind.Destructor:
- result = GetDestructorString ((IMethod)entity, settings);
- break;
- case SymbolKind.Event:
- result = GetEventString ((IEvent)entity, settings);
- break;
- case SymbolKind.Field:
- result = GetFieldString ((IField)entity, settings);
- break;
- case SymbolKind.Indexer:
- result = GetPropertyString ((IProperty)entity, settings);
- break;
- case SymbolKind.Method:
- result = GetMethodString ((IMethod)entity, settings);
- break;
- case SymbolKind.Operator:
- result = GetMethodString ((IMethod)entity, settings);
- break;
- case SymbolKind.Property:
- result = GetPropertyString ((IProperty)entity, settings);
- break;
- case SymbolKind.TypeDefinition:
- result = GetTypeString ((ITypeDefinition)entity, settings);
- break;
- default:
- throw new ArgumentOutOfRangeException ("SymbolKind", "Unknown entity type:" + entity.SymbolKind);
- }
- result = settings.PostProcess (entity, result);
- return result;
+ static string GetCref (ICSharpCode.NRefactory.TypeSystem.ITypeResolveContext ctx, string cref)
+ {
+ if (cref == null)
+ return "";
+
+ if (cref.Length < 2)
+ return cref;
+ try {
+ var entity = new ICSharpCode.NRefactory.Documentation.DocumentationComment ("", ctx).ResolveCref (cref.Replace("<", "{").Replace(">", "}"));
+
+ if (entity != null) {
+ var ambience = new ICSharpCode.NRefactory.CSharp.CSharpAmbience ();
+ ambience.ConversionFlags = ICSharpCode.NRefactory.TypeSystem.ConversionFlags.ShowParameterList | ICSharpCode.NRefactory.TypeSystem.ConversionFlags.ShowParameterNames | ICSharpCode.NRefactory.TypeSystem.ConversionFlags.ShowTypeParameterList;
+ return ambience.ConvertEntity (entity);
+ }
+ } catch (Exception e) {
+ LoggingService.LogWarning ("Invalid cref:" + cref, e);
+ }
+
+ if (cref.Substring (1, 1) == ":")
+ return cref.Substring (2, cref.Length - 2);
+
+ return cref;
}
- public string GetString (IType type, OutputSettings settings)
+ static bool IsSpecialChar (int charValue)
{
- var result = GetTypeString (type, settings);
- return settings.PostProcess (type, result);
+ return
+ 0x01 <= charValue && charValue <= 0x08 ||
+ 0x0B <= charValue && charValue <= 0x0C ||
+ 0x0E <= charValue && charValue <= 0x1F ||
+ 0x7F <= charValue && charValue <= 0x84 ||
+ 0x86 <= charValue && charValue <= 0x9F;
}
-
-/* public string GetString (ITypeReference reference, OutputSettings settings)
+
+ public static string BreakLines (string text, int maxLineLength)
{
- var result = GetTypeReferenceString (reference, settings);
- return settings.PostProcess (reference, result);
- }*/
+ if (maxLineLength <= 0)
+ return text;
+ StringBuilder result = new StringBuilder ();
+ int lineLength = 0;
+ bool inTag = false;
+ bool inAmp = false;
+ foreach (char ch in text) {
+ switch (ch) {
+ case '<':
+ inTag = true;
+ break;
+ case '>':
+ inTag = false;
+ break;
+ case '&':
+ inAmp = true;
+ break;
+ case ';':
+ inAmp = false;
+ break;
+ case '\n':
+ lineLength = 0;
+ break;
+ case '\r':
+ lineLength = 0;
+ break;
+ }
+
+ result.Append (ch);
+ if (!inTag && !inAmp)
+ lineLength++;
+ if (!Char.IsLetterOrDigit (ch) && lineLength > maxLineLength) {
+ result.AppendLine ();
+ lineLength = 0;
+ }
+ }
+ return result.ToString ();
+ }
- public string GetString (IEntity entity, OutputFlags flags)
+ public static string EscapeText (string text)
{
- return GetString (entity, new OutputSettings (flags));
+ if (text == null)
+ return null;
+ StringBuilder result = new StringBuilder ();
+ foreach (char ch in text) {
+ switch (ch) {
+ case '<':
+ result.Append ("&lt;");
+ break;
+ case '>':
+ result.Append ("&gt;");
+ break;
+ case '&':
+ result.Append ("&amp;");
+ break;
+ case '\'':
+ result.Append ("&apos;");
+ break;
+ case '"':
+ result.Append ("&quot;");
+ break;
+ default:
+ int charValue = (int)ch;
+ if (IsSpecialChar (charValue)) {
+ result.AppendFormat ("&#x{0:X};", charValue);
+ } else {
+ result.Append (ch);
+ }
+ break;
+ }
+ }
+ return result.ToString ();
}
- public string GetString (IType type, OutputFlags flags)
+ public static string UnescapeText (string text)
{
- return GetString (type, new OutputSettings (flags));
+ var sb = new StringBuilder ();
+ for (int i = 0; i < text.Length; i++) {
+ char ch = text[i];
+ if (ch == '&') {
+ int end = text.IndexOf (';', i);
+ if (end == -1)
+ break;
+ string entity = text.Substring (i + 1, end - i - 1);
+ switch (entity) {
+ case "lt":
+ sb.Append ('<');
+ break;
+ case "gt":
+ sb.Append ('>');
+ break;
+ case "amp":
+ sb.Append ('&');
+ break;
+ case "apos":
+ sb.Append ('\'');
+ break;
+ case "quot":
+ sb.Append ('"');
+ break;
+ }
+ i = end;
+ } else {
+ sb.Append (ch);
+ }
+ }
+ return sb.ToString ();
}
- public string GetString (ITypeDefinition type, OutputFlags flags)
+
+ public static string GetDocumentationMarkup (ISymbol member, string doc)
{
- return GetString ((IEntity)type, new OutputSettings (flags));
+ return GetDocumentationMarkup (member, doc, DocumentationFormatOptions.Empty);
}
+ static string ParseBody (ISymbol member, XmlTextReader xml, string endTagName, DocumentationFormatOptions options)
+ {
+ StringBuilder result = new StringBuilder ();
+ bool wasWhiteSpace = true;
+ bool appendSpace = false;
+ //ITypeResolveContext ctx = member.Compilation.TypeResolveContext;
+ while (xml.Read ()) {
+ switch (xml.NodeType) {
+ case XmlNodeType.EndElement:
+ if (xml.Name == endTagName)
+ goto end;
+ break;
+ case XmlNodeType.Element:
+ switch (xml.Name.ToLower ()) {
+ case "para":
+ result.AppendLine (ParseBody (member, xml, xml.Name, options));
+ wasWhiteSpace = true;
+ break;
+ case "see":
+ if (!wasWhiteSpace) {
+ result.Append (' ');
+ wasWhiteSpace = true;
+ }
+ result.Append ("<i>");
+ string name = (xml ["cref"] + xml ["langword"]).Trim ();
+ // if (options.Ambience != null)
+ // name = options.Ambience.GetIntrinsicTypeName (name);
+ result.Append (EscapeText (name));
+ result.Append ("</i>");
+ wasWhiteSpace = false;
+ appendSpace = true;
+ break;
+ case "paramref":
+ if (!wasWhiteSpace) {
+ result.Append (' ');
+ wasWhiteSpace = true;
+ }
+ result.Append ("<i>");
+ result.Append (EscapeText (xml ["name"].Trim ()));
+ result.Append ("</i>");
+ appendSpace = true;
+ wasWhiteSpace = false;
+ break;
+ }
+ break;
+ case XmlNodeType.Text:
+ if (IsEmptyDocumentation (xml.Value))
+ break;
+ foreach (char ch in xml.Value) {
+ if (!Char.IsWhiteSpace (ch) && appendSpace) {
+ result.Append (' ');
+ appendSpace = false;
+ }
+ if (Char.IsWhiteSpace (ch) || ch == '\n' || ch == '\r') {
+ if (!wasWhiteSpace) {
+ result.Append (' ');
+ wasWhiteSpace = true;
+ }
+ continue;
+ }
+ wasWhiteSpace = false;
+ result.Append (EscapeText (ch.ToString ()));
+ }
+ break;
+ }
+ }
+ end:
+ return result.ToString ().Trim ();
+ }
- public string GetString (IParameterizedMember member, IParameter parameter, OutputFlags flags)
+ public static string GetDocumentationMarkup (ISymbol member, string doc, DocumentationFormatOptions options)
{
- return GetParameterString (member, parameter, new OutputSettings (flags));
+ if (string.IsNullOrEmpty (doc))
+ return null;
+ System.IO.StringReader reader = new System.IO.StringReader ("<docroot>" + doc + "</docroot>");
+ XmlTextReader xml = new XmlTextReader (reader);
+ StringBuilder ret = new StringBuilder (70);
+ StringBuilder parameterBuilder = new StringBuilder ();
+ StringBuilder exceptions = new StringBuilder ();
+ exceptions.AppendLine (options.FormatHeading (GettextCatalog.GetString ("Exceptions:")));
+ // ret.Append ("<small>");
+ int paramCount = 0, exceptionCount = 0, summaryEnd = -1;
+ try {
+ xml.Read ();
+ do {
+ if (xml.NodeType == XmlNodeType.Element) {
+ switch (xml.Name.ToLower ()) {
+ case "para":
+ ret.Append (options.FormatBody (ParseBody (member, xml, xml.Name, options)));
+ if (summaryEnd < 0)
+ summaryEnd = ret.Length;
+ break;
+ case "summary":
+ var summary = options.FormatBody (ParseBody (member, xml, xml.Name, options));
+ if (!IsEmptyDocumentation (summary)) {
+ // ret.AppendLine (GetHeading ("Summary:", options));
+ ret.Append (summary);
+ if (summaryEnd < 0)
+ summaryEnd = ret.Length;
+ }
+ break;
+ case "remarks":
+ if (string.IsNullOrEmpty (options.HighlightParameter)) {
+ ret.AppendLine (options.FormatHeading (GettextCatalog.GetString ("Remarks:")));
+ ret.Append (options.FormatBody (ParseBody (member, xml, xml.Name, options)));
+ if (summaryEnd < 0)
+ summaryEnd = ret.Length;
+ } else {
+ options.FormatBody (ParseBody (member, xml, xml.Name, options));
+ }
+ break;
+ // skip <example>-nodes
+ case "example":
+ xml.Skip ();
+ xml.Skip ();
+ break;
+ case "exception":
+ exceptionCount++;
+ if (options.SmallText)
+ exceptions.Append ("<small>");
+ exceptions.Append ("<b>");
+ exceptions.Append (EscapeText (xml ["cref"]));
+ exceptions.Append (": ");
+ exceptions.Append ("</b>");
+ if (options.SmallText)
+ exceptions.Append ("</small>");
+
+ exceptions.AppendLine (options.FormatBody (ParseBody (member, xml, xml.Name, options)));
+ break;
+ case "returns":
+ if (string.IsNullOrEmpty (options.HighlightParameter)) {
+ ret.AppendLine (options.FormatHeading (GettextCatalog.GetString ("Returns:")));
+ ret.Append (options.FormatBody (ParseBody (member, xml, xml.Name, options)));
+ } else {
+ options.FormatBody (ParseBody (member, xml, xml.Name, options));
+ }
+ break;
+ case "param":
+ string paramName = xml.GetAttribute ("name") != null ? xml ["name"].Trim () : "";
+
+ var body = options.FormatBody (ParseBody (member, xml, xml.Name, options));
+ if (!IsEmptyDocumentation (body)) {
+ paramCount++;
+ parameterBuilder.Append ("<i>");
+ if (options.HighlightParameter == paramName)
+ parameterBuilder.Append ("<b>");
+ if (options.SmallText)
+ parameterBuilder.Append ("<small>");
+ parameterBuilder.Append (EscapeText (paramName));
+ if (options.SmallText)
+ parameterBuilder.Append ("</small>");
+ if (options.HighlightParameter == paramName)
+ parameterBuilder.Append ("</b>");
+ parameterBuilder.Append (":</i> ");
+ parameterBuilder.Append (body);
+ } else {
+ return null;
+ }
+ break;
+ case "value":
+ ret.AppendLine (options.FormatHeading (GettextCatalog.GetString ("Value:")));
+ ret.AppendLine (options.FormatBody (ParseBody (member, xml, xml.Name, options)));
+ break;
+ case "seealso":
+ if (string.IsNullOrEmpty (options.HighlightParameter)) {
+ ret.Append (options.FormatHeading (GettextCatalog.GetString ("See also:")));
+ ret.Append (" " + EscapeText (xml ["cref"] + xml ["langword"]));
+ }
+ break;
+ }
+ }
+ } while (xml.Read ());
+
+ } catch (Exception ex) {
+ MonoDevelop.Core.LoggingService.LogError (ex.ToString ());
+ return EscapeText (doc);
+ }
+
+ if (IsEmptyDocumentation (ret.ToString ()) && IsEmptyDocumentation (parameterBuilder.ToString ()))
+ return EscapeText (doc);
+ if (string.IsNullOrEmpty (options.HighlightParameter) && exceptionCount > 0)
+ ret.Append (exceptions.ToString ());
+
+ string result = ret.ToString ();
+ if (summaryEnd < 0)
+ summaryEnd = result.Length;
+ if (paramCount > 0) {
+ var paramSb = new StringBuilder ();
+ if (result.Length > 0)
+ paramSb.AppendLine ();/*
+ paramSb.Append ("<small>");
+ paramSb.AppendLine (options.FormatHeading (GettextCatalog.GetPluralString ("Parameter:", "Parameters:", paramCount)));
+ paramSb.Append ("</small>");*/
+ paramSb.Append (parameterBuilder.ToString ());
+ result = result.Insert (summaryEnd, paramSb.ToString ());
+ }
+ result = result.Trim ();
+ if (result.EndsWith (Environment.NewLine + "</small>"))
+ result = result.Substring (0, result.Length - (Environment.NewLine + "</small>").Length) + "</small>";
+ return result;
}
- /*
- public string GetString (ITypeReference reference, OutputFlags flags)
+ #endregion
+
+ #region Tooltips
+ static List<AmbienceTooltipProvider> tooltipProviders = new List<AmbienceTooltipProvider>();
+
+ public static TooltipInformation GetTooltip(ISymbol symbol)
{
- return GetString (reference, new OutputSettings (flags));
- }*/
+ foreach (var tp in tooltipProviders) {
+ var result = tp.GetTooltip (symbol);
+ if (result != null)
+ return result;
+ }
+ return null;
+ }
+ #endregion
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/AmbienceService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/AmbienceService.cs
deleted file mode 100644
index 794144d931..0000000000
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/AmbienceService.cs
+++ /dev/null
@@ -1,559 +0,0 @@
-//
-// AmbienceService.cs
-//
-// Author:
-// Mike Krüger <mkrueger@novell.com>
-//
-// Copyright (C) 2008 Novell, Inc (http://www.novell.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 Mono.Addins;
-using System.Xml;
-using System.Text;
-using ICSharpCode.NRefactory.TypeSystem;
-using MonoDevelop.Ide;
-using MonoDevelop.Projects;
-using MonoDevelop.Core;
-using MonoDevelop.Ide.Extensions;
-using ICSharpCode.NRefactory.Documentation;
-
-namespace MonoDevelop.Ide.TypeSystem
-{
- public static class AmbienceService
- {
- static Dictionary <string, Ambience> ambiences = new Dictionary <string, Ambience> ();
-
- static AmbienceService ()
- {
- // may not have been initialized in testing environment.
- if (AddinManager.IsInitialized) {
- AddinManager.AddExtensionNodeHandler ("/MonoDevelop/TypeSystem/Ambiences", delegate(object sender, ExtensionNodeEventArgs args) {
- var ambience = args.ExtensionNode as MimeTypeExtensionNode;
- switch (args.Change) {
- case ExtensionChange.Add:
- ambiences[ambience.MimeType] = (Ambience) ambience.CreateInstance ();
- break;
- case ExtensionChange.Remove:
- ambiences.Remove (ambience.MimeType);
- break;
- }
- });
- }
- }
-
- public static Ambience GetAmbience (IMember member)
- {
- return GetAmbienceForFile (member.DeclaringTypeDefinition.Region.FileName) ?? new NetAmbience ();
- }
-
- public static Ambience GetAmbienceForFile (string fileName)
- {
- if (string.IsNullOrEmpty (fileName))
- return DefaultAmbience;
- return GetAmbience (DesktopService.GetMimeTypeForUri (fileName));
- }
-
- public static Ambience GetAmbience (string mimeType)
- {
- Ambience result;
- if (!string.IsNullOrEmpty (mimeType) && ambiences.TryGetValue (mimeType, out result))
- return result;
- return defaultAmbience;
- }
-
- static Ambience defaultAmbience = new NetAmbience ();
-
- public static Ambience DefaultAmbience { get { return defaultAmbience; } }
- #region Documentation
-
- public class DocumentationFormatOptions
- {
- public static readonly DocumentationFormatOptions Empty = new DocumentationFormatOptions ();
- public string HighlightParameter {
- get;
- set;
- }
-
- public int MaxLineLength {
- get;
- set;
- }
-
- public bool BigHeadings {
- get;
- set;
- }
-
- public bool BoldHeadings {
- get;
- set;
- }
-
- public bool SmallText {
- get;
- set;
- }
-
- public Ambience Ambience {
- get;
- set;
- }
-
-
- public DocumentationFormatOptions ()
- {
- BoldHeadings = true;
- }
-
- public string FormatHeading (string heading)
- {
- string result = heading;
- if (BigHeadings)
- result = "<big>" + result + "</big>";
- if (BoldHeadings)
- result = "<b>" + result + "</b>";
- return result;
- }
-
- public string FormatBody (string body)
- {
- var str = body.Trim ();
- if (string.IsNullOrEmpty (str))
- return "";
- return SmallText ? "<small>" + str + Environment.NewLine + "</small>" : str + Environment.NewLine;
- }
- }
-
- public static string GetSummaryMarkup (IEntity member)
- {
- if (member == null || member.Documentation == null)
- return null;
- string documentation = member.Documentation.Xml.Text;
- if (!string.IsNullOrEmpty (documentation)) {
- int idx1 = documentation.IndexOf ("<summary>", StringComparison.Ordinal);
- int idx2 = documentation.LastIndexOf ("</summary>", StringComparison.Ordinal);
- string result;
- if (idx1 >= 0 && idx2 > idx1) {
- try {
- var xmlText = documentation.Substring (idx1, idx2 - idx1 + "</summary>".Length);
- return ParseBody (member,
- new XmlTextReader (xmlText, XmlNodeType.Element, null),
- "summary",
- DocumentationFormatOptions.Empty
- );
- } catch (Exception e) {
- LoggingService.LogWarning ("Malformed documentation xml detected:" + documentation, e);
- // may happen on malformed xml.
- var len = idx2 - idx1 - "</summary>".Length;
- result = len > 0 ? documentation.Substring (idx1 + "<summary>".Length, len) : documentation;
- }
- } else if (idx1 >= 0) {
- result = documentation.Substring (idx1 + "<summary>".Length);
- } else if (idx2 >= 0) {
- result = documentation.Substring (0, idx2 - 1);
- } else {
- result = documentation;
- }
- return GetDocumentationMarkup (member, CleanEmpty (result));
- }
-
- return GetDocumentationMarkup (member, CleanEmpty (documentation));
- }
-
- static string CleanEmpty (string doc)
- {
- return IsEmptyDocumentation (doc)? null : doc;
- }
-
- static bool IsEmptyDocumentation (string documentation)
- {
- return string.IsNullOrWhiteSpace (documentation) || documentation.StartsWith ("To be added") || documentation == "we have not entered docs yet";
- }
-
- public static string GetDocumentation (IEntity member)
- {
- if (member == null)
- return null;
- if (member.Documentation != null)
- return CleanEmpty (member.Documentation);
- return null;
- }
-
- static string GetCref (ITypeResolveContext ctx, string cref)
- {
- if (cref == null)
- return "";
-
- if (cref.Length < 2)
- return cref;
- try {
- var entity = new DocumentationComment ("", ctx).ResolveCref (cref.Replace("<", "{").Replace(">", "}"));
-
- if (entity != null) {
- var ambience = new ICSharpCode.NRefactory.CSharp.CSharpAmbience ();
- ambience.ConversionFlags = ConversionFlags.ShowParameterList | ConversionFlags.ShowParameterNames | ConversionFlags.ShowTypeParameterList;
- return ambience.ConvertSymbol (entity);
- }
- } catch (Exception e) {
- LoggingService.LogWarning ("Invalid cref:" + cref, e);
- }
-
- if (cref.Substring (1, 1) == ":")
- return cref.Substring (2, cref.Length - 2);
-
- return cref;
- }
-
- static bool IsSpecialChar (int charValue)
- {
- return
- 0x01 <= charValue && charValue <= 0x08 ||
- 0x0B <= charValue && charValue <= 0x0C ||
- 0x0E <= charValue && charValue <= 0x1F ||
- 0x7F <= charValue && charValue <= 0x84 ||
- 0x86 <= charValue && charValue <= 0x9F;
- }
-
- public static string BreakLines (string text, int maxLineLength)
- {
- if (maxLineLength <= 0)
- return text;
- StringBuilder result = new StringBuilder ();
- int lineLength = 0;
- bool inTag = false;
- bool inAmp = false;
- foreach (char ch in text) {
- switch (ch) {
- case '<':
- inTag = true;
- break;
- case '>':
- inTag = false;
- break;
- case '&':
- inAmp = true;
- break;
- case ';':
- inAmp = false;
- break;
- case '\n':
- lineLength = 0;
- break;
- case '\r':
- lineLength = 0;
- break;
- }
-
- result.Append (ch);
- if (!inTag && !inAmp)
- lineLength++;
- if (!Char.IsLetterOrDigit (ch) && lineLength > maxLineLength) {
- result.AppendLine ();
- lineLength = 0;
- }
- }
- return result.ToString ();
- }
-
- public static string EscapeText (string text)
- {
- if (text == null)
- return null;
- StringBuilder result = new StringBuilder ();
- foreach (char ch in text) {
- switch (ch) {
- case '<':
- result.Append ("&lt;");
- break;
- case '>':
- result.Append ("&gt;");
- break;
- case '&':
- result.Append ("&amp;");
- break;
- case '\'':
- result.Append ("&apos;");
- break;
- case '"':
- result.Append ("&quot;");
- break;
- default:
- int charValue = (int)ch;
- if (IsSpecialChar (charValue)) {
- result.AppendFormat ("&#x{0:X};", charValue);
- } else {
- result.Append (ch);
- }
- break;
- }
- }
- return result.ToString ();
- }
-
- public static string UnescapeText (string text)
- {
- var sb = new StringBuilder ();
- for (int i = 0; i < text.Length; i++) {
- char ch = text[i];
- if (ch == '&') {
- int end = text.IndexOf (';', i);
- if (end == -1)
- break;
- string entity = text.Substring (i + 1, end - i - 1);
- switch (entity) {
- case "lt":
- sb.Append ('<');
- break;
- case "gt":
- sb.Append ('>');
- break;
- case "amp":
- sb.Append ('&');
- break;
- case "apos":
- sb.Append ('\'');
- break;
- case "quot":
- sb.Append ('"');
- break;
- }
- i = end;
- } else {
- sb.Append (ch);
- }
- }
- return sb.ToString ();
- }
-
-
- public static string GetDocumentationMarkup (IEntity member, string doc)
- {
- return GetDocumentationMarkup (member, doc, DocumentationFormatOptions.Empty);
- }
-
- static string ParseBody (IEntity member, XmlTextReader xml, string endTagName, DocumentationFormatOptions options)
- {
- StringBuilder result = new StringBuilder ();
- bool wasWhiteSpace = true;
- bool appendSpace = false;
- ITypeResolveContext ctx = member.Compilation.TypeResolveContext;
- while (xml.Read ()) {
- switch (xml.NodeType) {
- case XmlNodeType.EndElement:
- if (xml.Name == endTagName)
- goto end;
- break;
- case XmlNodeType.Element:
- switch (xml.Name.ToLower ()) {
- case "para":
- result.AppendLine (ParseBody (member, xml, xml.Name, options));
- wasWhiteSpace = true;
- break;
- case "see":
- if (!wasWhiteSpace) {
- result.Append (' ');
- wasWhiteSpace = true;
- }
- result.Append ("<i>");
- string name = (GetCref (ctx, xml ["cref"]) + xml ["langword"]).Trim ();
- if (options.Ambience != null)
- name = options.Ambience.GetIntrinsicTypeName (name);
- result.Append (EscapeText (name));
- result.Append ("</i>");
- wasWhiteSpace = false;
- appendSpace = true;
- break;
- case "paramref":
- if (!wasWhiteSpace) {
- result.Append (' ');
- wasWhiteSpace = true;
- }
- result.Append ("<i>");
- result.Append (EscapeText (xml ["name"].Trim ()));
- result.Append ("</i>");
- appendSpace = true;
- wasWhiteSpace = false;
- break;
- }
- break;
- case XmlNodeType.Text:
- if (IsEmptyDocumentation (xml.Value))
- break;
- foreach (char ch in xml.Value) {
- if (!Char.IsWhiteSpace (ch) && appendSpace) {
- result.Append (' ');
- appendSpace = false;
- }
- if (Char.IsWhiteSpace (ch) || ch == '\n' || ch == '\r') {
- if (!wasWhiteSpace) {
- result.Append (' ');
- wasWhiteSpace = true;
- }
- continue;
- }
- wasWhiteSpace = false;
- result.Append (EscapeText (ch.ToString ()));
- }
- break;
- }
- }
- end:
- return result.ToString ().Trim ();
- }
-
- public static string GetDocumentationMarkup (IEntity member, string doc, DocumentationFormatOptions options)
- {
- if (string.IsNullOrEmpty (doc))
- return null;
- System.IO.StringReader reader = new System.IO.StringReader ("<docroot>" + doc + "</docroot>");
- XmlTextReader xml = new XmlTextReader (reader);
- StringBuilder ret = new StringBuilder (70);
- StringBuilder parameterBuilder = new StringBuilder ();
- StringBuilder exceptions = new StringBuilder ();
- exceptions.AppendLine (options.FormatHeading (GettextCatalog.GetString ("Exceptions:")));
- // ret.Append ("<small>");
- int paramCount = 0, exceptionCount = 0, summaryEnd = -1;
- try {
- xml.Read ();
- do {
- if (xml.NodeType == XmlNodeType.Element) {
- switch (xml.Name.ToLower ()) {
- case "para":
- ret.Append (options.FormatBody (ParseBody (member, xml, xml.Name, options)));
- if (summaryEnd < 0)
- summaryEnd = ret.Length;
- break;
- case "summary":
- var summary = options.FormatBody (ParseBody (member, xml, xml.Name, options));
- if (!IsEmptyDocumentation (summary)) {
- // ret.AppendLine (GetHeading ("Summary:", options));
- ret.Append (summary);
- if (summaryEnd < 0)
- summaryEnd = ret.Length;
- }
- break;
- case "remarks":
- if (string.IsNullOrEmpty (options.HighlightParameter)) {
- ret.AppendLine (options.FormatHeading (GettextCatalog.GetString ("Remarks:")));
- ret.Append (options.FormatBody (ParseBody (member, xml, xml.Name, options)));
- if (summaryEnd < 0)
- summaryEnd = ret.Length;
- } else {
- options.FormatBody (ParseBody (member, xml, xml.Name, options));
- }
- break;
- // skip <example>-nodes
- case "example":
- xml.Skip ();
- xml.Skip ();
- break;
- case "exception":
- exceptionCount++;
- if (options.SmallText)
- exceptions.Append ("<small>");
- exceptions.Append ("<b>");
- exceptions.Append (EscapeText (GetCref (member.Compilation.TypeResolveContext, xml ["cref"])));
- exceptions.Append (": ");
- exceptions.Append ("</b>");
- if (options.SmallText)
- exceptions.Append ("</small>");
-
- exceptions.AppendLine (options.FormatBody (ParseBody (member, xml, xml.Name, options)));
- break;
- case "returns":
- if (string.IsNullOrEmpty (options.HighlightParameter)) {
- ret.AppendLine (options.FormatHeading (GettextCatalog.GetString ("Returns:")));
- ret.Append (options.FormatBody (ParseBody (member, xml, xml.Name, options)));
- } else {
- options.FormatBody (ParseBody (member, xml, xml.Name, options));
- }
- break;
- case "param":
- string paramName = xml.GetAttribute ("name") != null ? xml ["name"].Trim () : "";
-
- var body = options.FormatBody (ParseBody (member, xml, xml.Name, options));
- if (!IsEmptyDocumentation (body)) {
- paramCount++;
- parameterBuilder.Append ("<i>");
- if (options.HighlightParameter == paramName)
- parameterBuilder.Append ("<b>");
- if (options.SmallText)
- parameterBuilder.Append ("<small>");
- parameterBuilder.Append (EscapeText (paramName));
- if (options.SmallText)
- parameterBuilder.Append ("</small>");
- if (options.HighlightParameter == paramName)
- parameterBuilder.Append ("</b>");
- parameterBuilder.Append (":</i> ");
- parameterBuilder.Append (body);
- } else {
- return null;
- }
- break;
- case "value":
- ret.AppendLine (options.FormatHeading (GettextCatalog.GetString ("Value:")));
- ret.AppendLine (options.FormatBody (ParseBody (member, xml, xml.Name, options)));
- break;
- case "seealso":
- if (string.IsNullOrEmpty (options.HighlightParameter)) {
- ret.Append (options.FormatHeading (GettextCatalog.GetString ("See also:")));
- ret.Append (" " + EscapeText (GetCref (member.Compilation.TypeResolveContext, xml ["cref"]) + xml ["langword"]));
- }
- break;
- }
- }
- } while (xml.Read ());
-
- } catch (Exception ex) {
- MonoDevelop.Core.LoggingService.LogError (ex.ToString ());
- return EscapeText (doc);
- }
-
- if (IsEmptyDocumentation (ret.ToString ()) && IsEmptyDocumentation (parameterBuilder.ToString ()))
- return EscapeText (doc);
- if (string.IsNullOrEmpty (options.HighlightParameter) && exceptionCount > 0)
- ret.Append (exceptions.ToString ());
-
- string result = ret.ToString ();
- if (summaryEnd < 0)
- summaryEnd = result.Length;
- if (paramCount > 0) {
- var paramSb = new StringBuilder ();
- if (result.Length > 0)
- paramSb.AppendLine ();/*
- paramSb.Append ("<small>");
- paramSb.AppendLine (options.FormatHeading (GettextCatalog.GetPluralString ("Parameter:", "Parameters:", paramCount)));
- paramSb.Append ("</small>");*/
- paramSb.Append (parameterBuilder.ToString ());
- result = result.Insert (summaryEnd, paramSb.ToString ());
- }
- result = result.Trim ();
- if (result.EndsWith (Environment.NewLine + "</small>"))
- result = result.Substring (0, result.Length - (Environment.NewLine + "</small>").Length) + "</small>";
- return result;
- }
- #endregion
- }
-}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/IExtensibleTextEditor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/AmbienceTooltipProvider.cs
index 94df5d0c11..4fd10c0a32 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Content/IExtensibleTextEditor.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/AmbienceTooltipProvider.cs
@@ -1,9 +1,10 @@
-// IExtensibleTextEditor.cs
+//
+// AmbienceTooltipProvider.cs
//
// Author:
-// Lluis Sanchez Gual <lluis@novell.com>
+// Mike Krüger <mkrueger@xamarin.com>
//
-// Copyright (c) 2007 Novell, Inc (http://www.novell.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
@@ -22,22 +23,18 @@
// 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.Ide.CodeCompletion;
+using Microsoft.CodeAnalysis;
-namespace MonoDevelop.Ide.Gui.Content
+namespace MonoDevelop.Ide.TypeSystem
{
- public interface IExtensibleTextEditor: IEditableTextBuffer
+ /// <summary>
+ /// Provides tooltips for a roslyn symbol.
+ /// Note: Intentionally part of internal extension API.
+ /// </summary>
+ abstract class AmbienceTooltipProvider
{
- ITextEditorExtension Extension {
- get;
- }
- // The provided parameter is the first object of the extension chain
- // This method should return the terminator ITextEditorExtension that
- // will execute the default behavior (if any)
- ITextEditorExtension AttachExtension (ITextEditorExtension extension);
+ public abstract TooltipInformation GetTooltip (ISymbol symbol);
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/CodeGenerationService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/CodeGenerationService.cs
deleted file mode 100644
index 4c857af7d9..0000000000
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/CodeGenerationService.cs
+++ /dev/null
@@ -1,563 +0,0 @@
-//
-// CodeGenerationService.cs
-//
-// Author:
-// mkrueger <mkrueger@novell.com>
-//
-// Copyright (c) 2011 Novell, Inc (http://www.novell.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.IO;
-using System.Linq;
-using System.Text;
-using Mono.TextEditor;
-using MonoDevelop.Core;
-using System.CodeDom;
-using MonoDevelop.Projects;
-using System.CodeDom.Compiler;
-using ICSharpCode.NRefactory.TypeSystem;
-using ICSharpCode.NRefactory;
-using MonoDevelop.Ide.TypeSystem;
-using MonoDevelop.Ide;
-using ICSharpCode.NRefactory.CSharp.TypeSystem;
-using System.Threading.Tasks;
-
-namespace MonoDevelop.Ide.TypeSystem
-{
- public static class CodeGenerationService
- {
- public static IUnresolvedMember AddCodeDomMember (Project project, IUnresolvedTypeDefinition type, CodeTypeMember newMember)
- {
- bool isOpen;
- var data = TextFileProvider.Instance.GetTextEditorData (type.Region.FileName, out isOpen);
- var parsedDocument = TypeSystemService.ParseFile (data.Document.FileName, data.Document.MimeType, data.Text);
-
- var insertionPoints = GetInsertionPoints (data, parsedDocument, type);
-
- var suitableInsertionPoint = GetSuitableInsertionPoint (insertionPoints, type, newMember);
-
- var dotNetProject = project as DotNetProject;
- if (dotNetProject == null) {
- LoggingService.LogError ("Only .NET projects are supported.");
- return null;
- }
-
- var generator = dotNetProject.LanguageBinding.GetCodeDomProvider ();
- StringWriter sw = new StringWriter ();
- var options = new CodeGeneratorOptions ();
- options.IndentString = data.GetLineIndent (type.Region.BeginLine) + "\t";
- if (newMember is CodeMemberMethod)
- options.BracingStyle = "C";
- generator.GenerateCodeFromMember (newMember, sw, options);
-
- var code = sw.ToString ();
- if (!string.IsNullOrEmpty (code))
- suitableInsertionPoint.Insert (data, code);
- if (!isOpen) {
- try {
- File.WriteAllText (type.Region.FileName, data.Text);
- } catch (Exception e) {
- LoggingService.LogError (string.Format ("Failed to write file '{0}'.", type.Region.FileName), e);
- MessageService.ShowError (GettextCatalog.GetString ("Failed to write file '{0}'.", type.Region.FileName));
- }
- }
- var newDocument = TypeSystemService.ParseFile (data.FileName, data.MimeType, data.Text);
- return newDocument.ParsedFile.GetMember (suitableInsertionPoint.Location.Line, int.MaxValue);
- }
-
- public static void AddNewMember (ITypeDefinition type, IUnresolvedTypeDefinition part, IUnresolvedMember newMember, bool implementExplicit = false)
- {
- bool isOpen;
- var data = TextFileProvider.Instance.GetTextEditorData (part.Region.FileName, out isOpen);
- var parsedDocument = TypeSystemService.ParseFile (data.FileName, data.MimeType, data.Text);
-
- var insertionPoints = GetInsertionPoints (data, parsedDocument, part);
-
- var suitableInsertionPoint = GetSuitableInsertionPoint (insertionPoints, part, newMember);
-
- var generator = CreateCodeGenerator (data, type.Compilation);
-
- generator.IndentLevel = CalculateBodyIndentLevel (parsedDocument.GetInnermostTypeDefinition (type.Region.Begin));
- var generatedCode = generator.CreateMemberImplementation (type, part, newMember, implementExplicit);
- suitableInsertionPoint.Insert (data, generatedCode.Code);
- if (!isOpen) {
- try {
- File.WriteAllText (type.Region.FileName, data.Text);
- } catch (Exception e) {
- LoggingService.LogError (GettextCatalog.GetString ("Failed to write file '{0}'.", type.Region.FileName), e);
- MessageService.ShowError (GettextCatalog.GetString ("Failed to write file '{0}'.", type.Region.FileName));
- }
- }
- }
-
- public static Task<bool> InsertMemberWithCursor (
- string operation, ITypeDefinition parentType, IUnresolvedTypeDefinition part,
- IUnresolvedMember newMember, bool implementExplicit = false)
- {
- var tcs = new TaskCompletionSource<bool>();
- if (parentType == null)
- return tcs.Task;
- part = part ?? parentType.Parts.FirstOrDefault ();
- if (part == null)
- return tcs.Task;
- var loadedDocument = IdeApp.Workbench.OpenDocument (part.Region.FileName);
- loadedDocument.RunWhenLoaded (delegate {
- var editor = loadedDocument.Editor;
- var loc = part.Region.Begin;
- var parsedDocument = loadedDocument.UpdateParseDocument ();
- var declaringType = parsedDocument.GetInnermostTypeDefinition (loc);
- var mode = new InsertionCursorEditMode (
- editor.Parent,
- CodeGenerationService.GetInsertionPoints (loadedDocument, declaringType));
- if (mode.InsertionPoints.Count == 0) {
- MessageService.ShowError (
- GettextCatalog.GetString ("No valid insertion point can be found in type '{0}'.", declaringType.Name)
- );
- return;
- }
- var suitableInsertionPoint = GetSuitableInsertionPoint (mode.InsertionPoints, part, newMember);
- if (suitableInsertionPoint != null)
- mode.CurIndex = mode.InsertionPoints.IndexOf (suitableInsertionPoint);
- else
- mode.CurIndex = 0;
-
- var helpWindow = new Mono.TextEditor.PopupWindow.InsertionCursorLayoutModeHelpWindow () {
- TitleText = operation
- };
- mode.HelpWindow = helpWindow;
-
- mode.StartMode ();
- mode.Exited += delegate(object s, InsertionCursorEventArgs iCArgs) {
- if (!iCArgs.Success) {
- tcs.SetResult (false);
- return;
- }
- var generator = CreateCodeGenerator (editor, parentType.Compilation);
- generator.IndentLevel = CalculateBodyIndentLevel (declaringType);
- var generatedCode = generator.CreateMemberImplementation (parentType, part, newMember, implementExplicit);
- mode.InsertionPoints[mode.CurIndex].Insert (editor, generatedCode.Code);
- tcs.SetResult (true);
- };
- });
-
- return tcs.Task;
- }
-
- public static Task<bool> InsertMember (
- ITypeDefinition parentType, IUnresolvedTypeDefinition part,
- IUnresolvedMember newMember, bool implementExplicit = false)
- {
- var tcs = new TaskCompletionSource<bool>();
- if (parentType == null)
- return tcs.Task;
- part = part ?? parentType.Parts.FirstOrDefault ();
- if (part == null)
- return tcs.Task;
-
- var loadedDocument = IdeApp.Workbench.OpenDocument (part.Region.FileName);
- loadedDocument.RunWhenLoaded (delegate {
- var editor = loadedDocument.Editor;
- var loc = part.Region.Begin;
- var parsedDocument = loadedDocument.UpdateParseDocument ();
- var declaringType = parsedDocument.GetInnermostTypeDefinition (loc);
- var insertionPoints = CodeGenerationService.GetInsertionPoints (loadedDocument, declaringType);
- if (insertionPoints.Count == 0) {
- MessageService.ShowError (
- GettextCatalog.GetString ("No valid insertion point can be found in type '{0}'.", declaringType.Name)
- );
- return;
- }
- var suitableInsertionPoint = GetSuitableInsertionPoint (insertionPoints, part, newMember) ?? insertionPoints.First ();
-
- var generator = CreateCodeGenerator (editor, parentType.Compilation);
- generator.IndentLevel = CalculateBodyIndentLevel (declaringType);
- var generatedCode = generator.CreateMemberImplementation (parentType, part, newMember, implementExplicit);
- suitableInsertionPoint.Insert (editor, generatedCode.Code);
- });
-
- return tcs.Task;
- }
-
- public static int CalculateBodyIndentLevel (IUnresolvedTypeDefinition declaringType)
- {
- if (declaringType == null)
- return 0;
- int indentLevel = 1;
- while (declaringType.DeclaringTypeDefinition != null) {
- indentLevel++;
- declaringType = declaringType.DeclaringTypeDefinition;
- }
- var file = declaringType.UnresolvedFile as CSharpUnresolvedFile;
- if (file == null)
- return indentLevel;
- var scope = file.GetUsingScope (declaringType.Region.Begin);
- while (scope != null && !string.IsNullOrEmpty (scope.NamespaceName)) {
- indentLevel++;
- // skip virtual scopes.
- while (scope.Parent != null && scope.Parent.Region == scope.Region)
- scope = scope.Parent;
- scope = scope.Parent;
- }
- return indentLevel;
- }
-
- public static void AddNewMembers (Project project, ITypeDefinition type, IUnresolvedTypeDefinition part, IEnumerable<IUnresolvedMember> newMembers, string regionName = null, Func<IUnresolvedMember, bool> implementExplicit = null)
- {
- IUnresolvedMember firstNewMember = newMembers.FirstOrDefault ();
- if (firstNewMember == null)
- return;
- bool isOpen;
- var data = TextFileProvider.Instance.GetTextEditorData (part.Region.FileName, out isOpen);
- var parsedDocument = TypeSystemService.ParseFile (project, data);
-
- var insertionPoints = GetInsertionPoints (data, parsedDocument, part);
-
-
- var suitableInsertionPoint = GetSuitableInsertionPoint (insertionPoints, part, firstNewMember);
-
- var generator = CreateCodeGenerator (data, type.Compilation);
- generator.IndentLevel = CalculateBodyIndentLevel (parsedDocument.GetInnermostTypeDefinition (part.Region.Begin));
- StringBuilder sb = new StringBuilder ();
- foreach (var newMember in newMembers) {
- if (sb.Length > 0) {
- sb.AppendLine ();
- sb.AppendLine ();
- }
- sb.Append (generator.CreateMemberImplementation (type, part, newMember, implementExplicit != null ? implementExplicit (newMember) : false).Code);
- }
- suitableInsertionPoint.Insert (data, string.IsNullOrEmpty (regionName) ? sb.ToString () : generator.WrapInRegions (regionName, sb.ToString ()));
- if (!isOpen) {
- try {
- File.WriteAllText (type.Region.FileName, data.Text);
- } catch (Exception e) {
- LoggingService.LogError (GettextCatalog.GetString ("Failed to write file '{0}'.", type.Region.FileName), e);
- MessageService.ShowError (GettextCatalog.GetString ("Failed to write file '{0}'.", type.Region.FileName));
- }
- }
- }
-
- public static CodeGenerator CreateCodeGenerator (this Ide.Gui.Document doc)
- {
- return CodeGenerator.CreateGenerator (doc);
- }
-
- public static CodeGenerator CreateCodeGenerator (this TextEditorData data, ICompilation compilation)
- {
- return CodeGenerator.CreateGenerator (data, compilation);
- }
-
- static IUnresolvedTypeDefinition GetMainPart (IType t)
- {
- return t.GetDefinition ().Parts.First ();
- }
-
- #region Insertion Points
- public static List<InsertionPoint> GetInsertionPoints (MonoDevelop.Ide.Gui.Document document, IUnresolvedTypeDefinition type)
- {
- if (document == null)
- throw new ArgumentNullException ("document");
- if (document.ParsedDocument == null)
- return new List<InsertionPoint> ();
- return GetInsertionPoints (document.Editor, document.ParsedDocument, type);
- }
-
- public static List<InsertionPoint> GetInsertionPoints (TextEditorData data, ParsedDocument parsedDocument, IUnresolvedTypeDefinition type)
- {
- if (data == null)
- throw new ArgumentNullException ("data");
- if (parsedDocument == null)
- throw new ArgumentNullException ("parsedDocument");
- if (type == null)
- throw new ArgumentNullException ("type");
-
- // update type from parsed document, since this is always newer.
- //type = parsedDocument.GetInnermostTypeDefinition (type.GetLocation ()) ?? type;
- List<InsertionPoint> result = new List<InsertionPoint> ();
- int offset = data.LocationToOffset (type.Region.Begin);
- if (offset < 0 || type.BodyRegion.IsEmpty)
- return result;
- while (offset < data.Length && data.GetCharAt (offset) != '{') {
- offset++;
- }
- var realStartLocation = data.OffsetToLocation (offset);
- result.Add (GetInsertionPosition (data.Document, realStartLocation.Line, realStartLocation.Column));
- result [0].LineBefore = NewLineInsertion.None;
-
- foreach (var member in type.Members) {
- TextLocation domLocation = member.BodyRegion.End;
- if (domLocation.Line <= 0) {
- DocumentLine lineSegment = data.GetLine (member.Region.BeginLine);
- if (lineSegment == null)
- continue;
- domLocation = new TextLocation (member.Region.BeginLine, lineSegment.Length + 1);
- }
- result.Add (GetInsertionPosition (data.Document, domLocation.Line, domLocation.Column));
- }
-
- foreach (var nestedType in type.NestedTypes) {
- TextLocation domLocation = nestedType.BodyRegion.End;
- if (domLocation.Line <= 0) {
- DocumentLine lineSegment = data.GetLine (nestedType.Region.BeginLine);
- if (lineSegment == null)
- continue;
- domLocation = new TextLocation (nestedType.Region.BeginLine, lineSegment.Length + 1);
- }
- result.Add (GetInsertionPosition (data.Document, domLocation.Line, domLocation.Column));
- }
-
- result [result.Count - 1].LineAfter = NewLineInsertion.None;
- CheckStartPoint (data.Document, result [0], result.Count == 1);
- if (result.Count > 1) {
- result.RemoveAt (result.Count - 1);
- NewLineInsertion insertLine;
- var lineBefore = data.GetLine (type.BodyRegion.EndLine - 1);
- if (lineBefore != null && lineBefore.Length == lineBefore.GetIndentation (data.Document).Length) {
- insertLine = NewLineInsertion.None;
- } else {
- insertLine = NewLineInsertion.Eol;
- }
- // search for line start
- int col = type.BodyRegion.EndColumn - 1;
- var line = data.GetLine (type.BodyRegion.EndLine);
- if (line != null) {
- var lineOffset = line.Offset;
- col = Math.Min (line.Length, col);
- while (lineOffset + col - 2 >= 0 && col > 1 && char.IsWhiteSpace (data.GetCharAt (lineOffset + col - 2)))
- col--;
- }
- result.Add (new InsertionPoint (new DocumentLocation (type.BodyRegion.EndLine, col), insertLine, NewLineInsertion.Eol));
- CheckEndPoint (data.Document, result [result.Count - 1], result.Count == 1);
- }
-
- foreach (var region in parsedDocument.UserRegions.Where (r => type.BodyRegion.IsInside (r.Region.Begin))) {
- result.Add (new InsertionPoint (new DocumentLocation (region.Region.BeginLine + 1, 1), NewLineInsertion.Eol, NewLineInsertion.Eol));
- result.Add (new InsertionPoint (new DocumentLocation (region.Region.EndLine, 1), NewLineInsertion.Eol, NewLineInsertion.Eol));
- result.Add (new InsertionPoint (new DocumentLocation (region.Region.EndLine + 1, 1), NewLineInsertion.Eol, NewLineInsertion.Eol));
- }
- result.Sort ((left, right) => left.Location.CompareTo (right.Location));
-// foreach (var res in result)
-// Console.WriteLine (res);
- return result;
- }
-
- static void CheckEndPoint (TextDocument doc, InsertionPoint point, bool isStartPoint)
- {
- DocumentLine line = doc.GetLine (point.Location.Line);
- if (line == null)
- return;
-
- if (doc.GetLineIndent (line).Length + 1 < point.Location.Column)
- point.LineBefore = NewLineInsertion.BlankLine;
- if (point.Location.Column < line.Length + 1)
- point.LineAfter = NewLineInsertion.Eol;
- }
-
- static void CheckStartPoint (TextDocument doc, InsertionPoint point, bool isEndPoint)
- {
- DocumentLine line = doc.GetLine (point.Location.Line);
- if (line == null)
- return;
- if (doc.GetLineIndent (line).Length + 1 == point.Location.Column) {
- int lineNr = point.Location.Line;
- while (lineNr > 1 && doc.GetLineIndent (lineNr - 1).Length == doc.GetLine (lineNr - 1).Length) {
- lineNr--;
- }
- line = doc.GetLine (lineNr);
- point.Location = new DocumentLocation (lineNr, doc.GetLineIndent (line).Length + 1);
- }
-
- if (doc.GetLineIndent (line).Length + 1 < point.Location.Column)
- point.LineBefore = NewLineInsertion.Eol;
- if (point.Location.Column < line.Length + 1)
- point.LineAfter = isEndPoint ? NewLineInsertion.Eol : NewLineInsertion.BlankLine;
- }
-
- static InsertionPoint GetInsertionPosition (TextDocument doc, int line, int column)
- {
- int bodyEndOffset = doc.LocationToOffset (line, column) + 1;
- DocumentLine curLine = doc.GetLine (line);
- if (curLine != null) {
- if (bodyEndOffset < curLine.Offset + curLine.Length) {
- // case1: positition is somewhere inside the start line
- return new InsertionPoint (new DocumentLocation (line, column + 1), NewLineInsertion.Eol, NewLineInsertion.BlankLine);
- }
- }
-
- // -> if position is at line end check next line
- DocumentLine nextLine = doc.GetLine (line + 1);
- if (nextLine == null) // check for 1 line case.
- return new InsertionPoint (new DocumentLocation (line, column + 1), NewLineInsertion.BlankLine, NewLineInsertion.BlankLine);
-
- for (int i = nextLine.Offset; i < nextLine.EndOffset; i++) {
- char ch = doc.GetCharAt (i);
- if (!char.IsWhiteSpace (ch)) {
- // case2: next line contains non ws chars.
- return new InsertionPoint (new DocumentLocation (line + 1, 1), NewLineInsertion.Eol, NewLineInsertion.BlankLine);
- }
- }
-
- DocumentLine nextLine2 = doc.GetLine (line + 2);
- if (nextLine2 != null) {
- for (int i = nextLine2.Offset; i < nextLine2.EndOffset; i++) {
- char ch = doc.GetCharAt (i);
- if (!char.IsWhiteSpace (ch)) {
- // case3: one blank line
- return new InsertionPoint (new DocumentLocation (line + 1, 1), NewLineInsertion.Eol, NewLineInsertion.Eol);
- }
- }
- }
- // case4: more than 1 blank line
- return new InsertionPoint (new DocumentLocation (line + 1, 1), NewLineInsertion.Eol, NewLineInsertion.None);
- }
-
- static InsertionPoint GetSuitableInsertionPoint (IEnumerable<InsertionPoint> points, IUnresolvedTypeDefinition cls, IUnresolvedMember member)
- {
- var mainPart = cls;
- switch (member.SymbolKind) {
- case SymbolKind.Field:
- return GetNewFieldPosition (points, mainPart);
- case SymbolKind.Method:
- case SymbolKind.Constructor:
- case SymbolKind.Destructor:
- case SymbolKind.Operator:
- return GetNewMethodPosition (points, mainPart);
- case SymbolKind.Event:
- return GetNewEventPosition (points, mainPart);
- case SymbolKind.Property:
- return GetNewPropertyPosition (points, mainPart);
- }
- throw new InvalidOperationException ("Invalid member type: " + member.SymbolKind);
- }
-
- static InsertionPoint GetSuitableInsertionPoint (IEnumerable<InsertionPoint> points, IUnresolvedTypeDefinition cls, CodeTypeMember mem)
- {
- var mainPart = cls;
- if (mem is System.CodeDom.CodeMemberEvent)
- return GetNewEventPosition (points, mainPart);
- if (mem is System.CodeDom.CodeMemberProperty)
- return GetNewPropertyPosition (points, mainPart);
- if (mem is System.CodeDom.CodeMemberField)
- return GetNewFieldPosition (points, mainPart);
- if (mem is System.CodeDom.CodeMemberMethod)
- return GetNewMethodPosition (points, mainPart);
- return GetNewFieldPosition (points, mainPart);
- }
-
- static InsertionPoint GetNewFieldPosition (IEnumerable<InsertionPoint> points, IUnresolvedTypeDefinition cls)
- {
- if (!cls.Fields.Any ())
- return points.FirstOrDefault ();
- var lastField = cls.Fields.Last ();
- return points.FirstOrDefault (p => p.Location.Convert () > lastField.Region.Begin);
- }
-
- static InsertionPoint GetNewMethodPosition (IEnumerable<InsertionPoint> points, IUnresolvedTypeDefinition cls)
- {
- if (!cls.Methods.Any ())
- return GetNewPropertyPosition (points, cls);
- var lastMember = cls.Members.Last ();
- return points.FirstOrDefault (p => p.Location.Convert () > lastMember.Region.Begin);
- }
-
- static InsertionPoint GetNewPropertyPosition (IEnumerable<InsertionPoint> points, IUnresolvedTypeDefinition cls)
- {
- if (!cls.Properties.Any ())
- return GetNewFieldPosition (points, cls);
- var lastProperty = cls.Properties.Last ();
- return points.FirstOrDefault (p => p.Location.Convert () > lastProperty.Region.Begin);
- }
-
- static InsertionPoint GetNewEventPosition (IEnumerable<InsertionPoint> points, IUnresolvedTypeDefinition cls)
- {
- if (!cls.Events.Any ())
- return GetNewMethodPosition (points, cls);
- var lastEvent = cls.Events.Last ();
- return points.FirstOrDefault (p => p.Location.Convert () > lastEvent.Region.Begin);
- }
- #endregion
-
- public static void AddAttribute (ITypeDefinition cls, string name, params object[] parameters)
- {
- bool isOpen;
- string fileName = cls.Region.FileName;
- var buffer = TextFileProvider.Instance.GetTextEditorData (fileName, out isOpen);
-
- var attr = new CodeAttributeDeclaration (name);
- foreach (var parameter in parameters) {
- attr.Arguments.Add (new CodeAttributeArgument (new CodePrimitiveExpression (parameter)));
- }
-
- var type = new CodeTypeDeclaration ("temp");
- type.CustomAttributes.Add (attr);
- Project project;
- if (!cls.TryGetSourceProject (out project)) {
- LoggingService.LogError ("Error can't get source project for:" + cls.FullName);
- }
-
- var provider = ((DotNetProject)project).LanguageBinding.GetCodeDomProvider ();
- var sw = new StringWriter ();
- provider.GenerateCodeFromType (type, sw, new CodeGeneratorOptions ());
- string code = sw.ToString ();
- int start = code.IndexOf ('[');
- int end = code.LastIndexOf (']');
- code = code.Substring (start, end - start + 1) + Environment.NewLine;
-
- int pos = buffer.LocationToOffset (cls.Region.BeginLine, cls.Region.BeginColumn);
-
- code = buffer.GetLineIndent (cls.Region.BeginLine) + code;
- buffer.Insert (pos, code);
- if (!isOpen) {
- File.WriteAllText (fileName, buffer.Text);
- buffer.Dispose ();
- }
-
- }
-
- public static IUnresolvedTypeDefinition AddType (DotNetProject project, string folder, string namspace, CodeTypeDeclaration type)
- {
-
- var unit = new CodeCompileUnit ();
- var ns = new CodeNamespace (namspace);
- ns.Types.Add (type);
- unit.Namespaces.Add (ns);
-
- string fileName = project.LanguageBinding.GetFileName (Path.Combine (folder, type.Name));
- using (var sw = new StreamWriter (fileName)) {
- var provider = project.LanguageBinding.GetCodeDomProvider ();
- var options = new CodeGeneratorOptions ();
- options.IndentString = "\t";
- options.BracingStyle = "C";
-
- provider.GenerateCodeFromCompileUnit (unit, sw, options);
- }
- return TypeSystemService.ParseFile (project, fileName).TopLevelTypeDefinitions.FirstOrDefault ();
- }
-
- }
-
- public static class HelperMethods
- {
- public static TextLocation Convert (this DocumentLocation location)
- {
- return new TextLocation (location.Line, location.Column);
- }
- }
-}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/CodeGenerator.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/CodeGenerator.cs
index 1b1d6e1310..760496caed 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/CodeGenerator.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/CodeGenerator.cs
@@ -29,12 +29,12 @@ using System.Collections.Generic;
using System.Linq;
using Mono.Addins;
using ICSharpCode.NRefactory.TypeSystem;
-using Mono.TextEditor;
using MonoDevelop.Core.AddIns;
using MonoDevelop.Ide.TypeSystem;
using ICSharpCode.NRefactory;
using MonoDevelop.Projects.Policies;
using MonoDevelop.Ide.Extensions;
+using MonoDevelop.Ide.Editor;
namespace MonoDevelop.Ide.TypeSystem
{
@@ -67,36 +67,39 @@ namespace MonoDevelop.Ide.TypeSystem
set;
}
- public ICompilation Compilation {
- get;
- set;
- }
-
- public static CodeGenerator CreateGenerator (Ide.Gui.Document doc)
+ public static CodeGenerator CreateGenerator (TextEditor editor, DocumentContext documentContext)
{
MimeTypeExtensionNode node;
- if (!generators.TryGetValue (doc.Editor.MimeType, out node))
+ if (!generators.TryGetValue (editor.MimeType, out node))
return null;
var result = (CodeGenerator)node.CreateInstance ();
- result.UseSpaceIndent = doc.Editor.TabsToSpaces;
- result.EolMarker = doc.Editor.EolMarker;
- result.TabSize = doc.Editor.Options.TabSize;
- result.Compilation = doc.Compilation;
+
+ result.UseSpaceIndent = editor.Options.TabsToSpaces;
+ result.EolMarker = editor.EolMarker;
+ result.TabSize = editor.Options.TabSize;
+
return result;
}
-
- public static CodeGenerator CreateGenerator (TextEditorData editor, ICompilation compilation)
+
+ public static CodeGenerator CreateGenerator (Ide.Gui.Document doc)
+ {
+ return CreateGenerator (doc.Editor, doc);
+ }
+
+ public static CodeGenerator CreateGenerator (ITextDocument editor, ICompilation compilation)
{
MimeTypeExtensionNode node;
if (!generators.TryGetValue (editor.MimeType, out node))
return null;
var result = (CodeGenerator)node.CreateInstance ();
- result.UseSpaceIndent = editor.TabsToSpaces;
- result.EolMarker = editor.EolMarker;
- result.TabSize = editor.Options.TabSize;
- result.Compilation = compilation;
+
+ //result.UseSpaceIndent = editor.Options.TabsToSpaces;
+ result.EolMarker = editor.GetEolMarker ();
+ //result.TabSize = editor.Options.TabSize;
+ //result.Compilation = compilation;
+
return result;
}
@@ -154,12 +157,6 @@ namespace MonoDevelop.Ide.TypeSystem
generators.Remove (node.MimeType);
}
- protected void SetIndentTo (IUnresolvedTypeDefinition implementingType)
- {
- if (IndentLevel < 0)
- IndentLevel = AutoIndent ? CodeGenerationService.CalculateBodyIndentLevel (implementingType) : 0;
- }
-
static bool CompareMethods (IMethod interfaceMethod, IMethod typeMethod)
{
if (typeMethod.IsExplicitInterfaceImplementation)
@@ -168,15 +165,26 @@ namespace MonoDevelop.Ide.TypeSystem
}
public abstract string WrapInRegions (string regionName, string text);
- public abstract CodeGeneratorMemberResult CreateMemberImplementation (ITypeDefinition implementingType, IUnresolvedTypeDefinition part, IUnresolvedMember member, bool explicitDeclaration);
- public abstract CodeGeneratorMemberResult CreateMemberImplementation (ITypeDefinition implementingType, IUnresolvedTypeDefinition part, IMember member, bool explicitDeclaration);
- public abstract string CreateFieldEncapsulation (IUnresolvedTypeDefinition implementingType, IField field, string propertyName, Accessibility modifiers, bool readOnly);
+ public abstract void AddGlobalNamespaceImport (TextEditor editor, DocumentContext context, string nsName);
+ public abstract void AddLocalNamespaceImport (TextEditor editor, DocumentContext context, string nsName, TextLocation caretLocation);
+
+ public void AddGlobalNamespaceImport (MonoDevelop.Ide.Gui.Document doc, string nsName)
+ {
+ if (doc == null)
+ throw new ArgumentNullException ("doc");
+ AddGlobalNamespaceImport (doc.Editor, doc, nsName);
+ }
+
+ public void AddLocalNamespaceImport (MonoDevelop.Ide.Gui.Document doc, string nsName, TextLocation caretLocation)
+ {
+ if (doc == null)
+ throw new ArgumentNullException ("doc");
+ AddLocalNamespaceImport (doc.Editor, doc, nsName, caretLocation);
+ }
- public abstract void AddGlobalNamespaceImport (MonoDevelop.Ide.Gui.Document doc, string nsName);
- public abstract void AddLocalNamespaceImport (MonoDevelop.Ide.Gui.Document doc, string nsName, TextLocation caretLocation);
- public abstract string GetShortTypeString (MonoDevelop.Ide.Gui.Document doc, IType type);
+ //public abstract string GetShortTypeString (TextEditor editor, DocumentContext context, IType type);
public abstract void CompleteStatement (MonoDevelop.Ide.Gui.Document doc);
}
@@ -230,4 +238,4 @@ namespace MonoDevelop.Ide.TypeSystem
}
}
}
-} \ No newline at end of file
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/Comment.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/Comment.cs
index 6f615285ba..01eceed24a 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/Comment.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/Comment.cs
@@ -26,7 +26,8 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
-using ICSharpCode.NRefactory.TypeSystem;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Core.Text;
namespace MonoDevelop.Ide.TypeSystem
{
@@ -55,7 +56,13 @@ namespace MonoDevelop.Ide.TypeSystem
set;
}
- public DomRegion Region {
+ public bool HasRegion {
+ get {
+ return !Region.IsEmpty;
+ }
+ }
+
+ public DocumentRegion Region {
get;
set;
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/Error.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/Error.cs
new file mode 100644
index 0000000000..ca6a00634b
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/Error.cs
@@ -0,0 +1,216 @@
+//
+// Error.cs
+//
+// Author:
+// Mike Krüger <mkrueger@xamarin.com>
+//
+// Copyright (c) 2015 mkrueger
+//
+// 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.Text;
+using MonoDevelop.Ide.Editor;
+
+namespace MonoDevelop.Ide.TypeSystem
+{
+ /// <summary>
+ /// Enum that describes the type of an error.
+ /// </summary>
+ public enum ErrorType
+ {
+ Unknown,
+ Error,
+ Warning
+ }
+
+ /// <summary>
+ /// Descibes an error during parsing.
+ /// </summary>
+ [Serializable]
+ public class Error
+ {
+ readonly ErrorType errorType;
+ readonly string message;
+ readonly DocumentRegion region;
+
+ /// <summary>
+ /// The type of the error.
+ /// </summary>
+ public ErrorType ErrorType { get { return errorType; } }
+
+ /// <summary>
+ /// The error description.
+ /// </summary>
+ public string Message { get { return message; } }
+
+ /// <summary>
+ /// The id of the error.
+ /// </summary>
+ public string Id { get; private set; }
+
+ /// <summary>
+ /// The region of the error.
+ /// </summary>
+ public DocumentRegion Region { get { return region; } }
+
+ /// <summary>
+ /// Gets or sets the tag.
+ /// </summary>
+ public object Tag { get; set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ICSharpCode.NRefactory.TypeSystem.Error"/> class.
+ /// </summary>
+ /// <param name='errorType'>
+ /// The error type.
+ /// </param>
+ /// <param name='message'>
+ /// The description of the error.
+ /// </param>
+ /// <param name='region'>
+ /// The region of the error.
+ /// </param>
+ public Error (ErrorType errorType, string message, DocumentRegion region)
+ {
+ this.errorType = errorType;
+ this.message = message;
+ this.region = region;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ICSharpCode.NRefactory.TypeSystem.Error"/> class.
+ /// </summary>
+ /// <param name='errorType'>
+ /// The error type.
+ /// </param>
+ /// <param name='message'>
+ /// The description of the error.
+ /// </param>
+ /// <param name='location'>
+ /// The location of the error.
+ /// </param>
+ public Error (ErrorType errorType, string message, DocumentLocation location)
+ {
+ this.errorType = errorType;
+ this.message = message;
+ this.region = new DocumentRegion (location, location);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ICSharpCode.NRefactory.TypeSystem.Error"/> class.
+ /// </summary>
+ /// <param name='errorType'>
+ /// The error type.
+ /// </param>
+ /// <param name='message'>
+ /// The description of the error.
+ /// </param>
+ public Error (ErrorType errorType, string message, int line, int column) : this (errorType, message, new DocumentLocation (line, column))
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ICSharpCode.NRefactory.TypeSystem.Error"/> class.
+ /// </summary>
+ /// <param name='errorType'>
+ /// The error type.
+ /// </param>
+ /// <param name='message'>
+ /// The description of the error.
+ /// </param>
+ public Error (ErrorType errorType, string message)
+ {
+ this.errorType = errorType;
+ this.message = message;
+ this.region = DocumentRegion.Empty;
+ }
+
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ICSharpCode.NRefactory.TypeSystem.Error"/> class.
+ /// </summary>
+ /// <param name='errorType'>
+ /// The error type.
+ /// </param>
+ /// <param name='message'>
+ /// The description of the error.
+ /// </param>
+ /// <param name='region'>
+ /// The region of the error.
+ /// </param>
+ public Error (ErrorType errorType, string id, string message, DocumentRegion region)
+ {
+ this.errorType = errorType;
+ this.Id = id;
+ this.message = message;
+ this.region = region;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ICSharpCode.NRefactory.TypeSystem.Error"/> class.
+ /// </summary>
+ /// <param name='errorType'>
+ /// The error type.
+ /// </param>
+ /// <param name='message'>
+ /// The description of the error.
+ /// </param>
+ /// <param name='location'>
+ /// The location of the error.
+ /// </param>
+ public Error (ErrorType errorType, string id, string message, DocumentLocation location)
+ {
+ this.errorType = errorType;
+ this.Id = id;
+ this.message = message;
+ this.region = new DocumentRegion (location, location);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ICSharpCode.NRefactory.TypeSystem.Error"/> class.
+ /// </summary>
+ /// <param name='errorType'>
+ /// The error type.
+ /// </param>
+ /// <param name='message'>
+ /// The description of the error.
+ /// </param>
+ public Error (ErrorType errorType, string id, string message, int line, int column) : this (errorType, id, message, new DocumentLocation (line, column))
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ICSharpCode.NRefactory.TypeSystem.Error"/> class.
+ /// </summary>
+ /// <param name='errorType'>
+ /// The error type.
+ /// </param>
+ /// <param name='message'>
+ /// The description of the error.
+ /// </param>
+ public Error (ErrorType errorType, string id, string message)
+ {
+ this.errorType = errorType;
+ this.Id = id;
+ this.message = message;
+ this.region = DocumentRegion.Empty;
+ }
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/FoldingRegion.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/FoldingRegion.cs
index 46f0ffcfea..91f5b99b93 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/FoldingRegion.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/FoldingRegion.cs
@@ -24,7 +24,7 @@
// THE SOFTWARE.
//
using System;
-using ICSharpCode.NRefactory.TypeSystem;
+using MonoDevelop.Ide.Editor;
namespace MonoDevelop.Ide.TypeSystem
{
@@ -38,37 +38,37 @@ namespace MonoDevelop.Ide.TypeSystem
//NOTE: thsi is only respected if the FoldType is set to "Undefined"
public bool IsFoldedByDefault { get; set; }
- public DomRegion Region { get; set; }
+ public DocumentRegion Region { get; set; }
public FoldType Type { get; set; }
- public FoldingRegion (DomRegion region) : this (null, region)
+ public FoldingRegion (DocumentRegion region) : this (null, region)
{
}
- public FoldingRegion (string name, DomRegion region)
+ public FoldingRegion (string name, DocumentRegion region)
{
this.Name = name ?? defaultName;
this.Region = region;
}
- public FoldingRegion (string name, DomRegion region, bool isFoldedByDefault) : this (name, region)
+ public FoldingRegion (string name, DocumentRegion region, bool isFoldedByDefault) : this (name, region)
{
this.IsFoldedByDefault = isFoldedByDefault;
}
- public FoldingRegion (string name, DomRegion region, FoldType type) : this (name, region)
+ public FoldingRegion (string name, DocumentRegion region, FoldType type) : this (name, region)
{
this.Type = type;
}
- public FoldingRegion (string name, DomRegion region, FoldType type, bool isFoldedByDefault) : this (name, region)
+ public FoldingRegion (string name, DocumentRegion region, FoldType type, bool isFoldedByDefault) : this (name, region)
{
this.Type = type;
this.IsFoldedByDefault = isFoldedByDefault;
}
- public FoldingRegion (DomRegion region, FoldType type) : this (null, region, type)
+ public FoldingRegion (DocumentRegion region, FoldType type) : this (null, region, type)
{
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/IFoldingParser.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/IFoldingParser.cs
new file mode 100644
index 0000000000..66ea540bed
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/IFoldingParser.cs
@@ -0,0 +1,41 @@
+//
+// IFoldingParser.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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.
+
+
+namespace MonoDevelop.Ide.TypeSystem
+{
+ /// <summary>
+ /// The folding parser is used for generating a preliminary parsed document that does not
+ /// contain a full dom - only some basic lexical constructs like comments or pre processor directives.
+ ///
+ /// This is useful for opening a document the first time to have some folding regions as start that are folded by default.
+ /// Otherwise an irritating screen update will occur.
+ /// </summary>
+ public interface IFoldingParser
+ {
+ ParsedDocument Parse (string fileName, string content);
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MetadataReferenceCache.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MetadataReferenceCache.cs
new file mode 100644
index 0000000000..77d8e818eb
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MetadataReferenceCache.cs
@@ -0,0 +1,166 @@
+//
+// MetadataReferenceCache.cs
+//
+// Author:
+// David Karlaš <david.karlas@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 Microsoft.CodeAnalysis;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using System.IO;
+using MonoDevelop.Core;
+using System.Threading;
+
+namespace MonoDevelop.Ide.TypeSystem
+{
+ static class MetadataReferenceCache
+ {
+ static Dictionary<string, MetadataReferenceCacheItem> cache = new Dictionary<string, MetadataReferenceCacheItem> ();
+
+ public static MetadataReference LoadReference (ProjectId projectId, string path)
+ {
+ lock (cache) {
+ MetadataReferenceCacheItem result;
+ if (!cache.TryGetValue (path, out result)) {
+ result = new MetadataReferenceCacheItem (path);
+ cache.Add (path, result);
+ }
+ result.InUseBy.Add (projectId);
+ return result.Reference;
+ }
+ }
+
+ //TODO: This should be called when reference is actually removed and not on
+ //project reload because if this is only project that has this reference... Cache will be
+ //invalidated and when reload comes back in few miliseconds it will need to reload reference again
+ public static void RemoveReference (ProjectId projectId, string path)
+ {
+ lock (cache) {
+ MetadataReferenceCacheItem result;
+ if (cache.TryGetValue (path, out result)) {
+ result.InUseBy.Remove (projectId);
+ if (result.InUseBy.Count == 0) {
+ cache.Remove (path);
+ }
+ }
+ }
+ }
+
+ public static void RemoveReferences (ProjectId id)
+ {
+ lock (cache) {
+ var toRemove = new List<string> ();
+ foreach (var val in cache) {
+ val.Value.InUseBy.Remove (id);
+ if (val.Value.InUseBy.Count == 0) {
+ toRemove.Add (val.Key);
+ }
+ }
+ toRemove.ForEach ((k) => cache.Remove (k));
+ }
+ }
+
+ static Timer timer;
+
+ static MetadataReferenceCache ()
+ {
+ timer = new Timer ((o) => CheckForChanges (), null, 10000, 10000);
+ }
+
+ //TODO: Call this method when focus returns to MD or even better use FileSystemWatcher
+ public static void CheckForChanges ()
+ {
+ lock (cache) {
+ foreach (var value in cache.Values) {
+ value.CheckForChange ();
+ }
+ }
+ }
+
+ class MetadataReferenceCacheItem
+ {
+ public HashSet<ProjectId> InUseBy { get; private set; }
+
+ public MetadataReference Reference { get; private set; }
+
+ readonly string path;
+
+ DateTime timeStamp;
+
+ public MetadataReferenceCacheItem (string path)
+ {
+ this.path = path;
+ CreateNewReference ();
+ InUseBy = new HashSet<ProjectId> ();
+ }
+
+ public void CheckForChange ()
+ {
+ if (timeStamp != File.GetLastWriteTimeUtc (path)) {
+ if (Reference != null) {
+ foreach (var solution in IdeApp.Workspace.GetAllSolutions ()) {
+ var workspace = TypeSystemService.GetWorkspace (solution);
+ foreach (var projId in InUseBy) {
+ while (true) {
+ var project = workspace.CurrentSolution.GetProject (projId);
+ if (project == null)
+ break;
+ if (workspace.TryApplyChanges (project.RemoveMetadataReference (Reference).Solution))
+ break;
+ }
+ }
+ }
+ }
+ CreateNewReference ();
+ if (Reference != null) {
+ foreach (var solution in IdeApp.Workspace.GetAllSolutions ()) {
+ var workspace = TypeSystemService.GetWorkspace (solution);
+ foreach (var projId in InUseBy) {
+ while (true) {
+ var project = workspace.CurrentSolution.GetProject (projId);
+ if (project == null)
+ break;
+ if (workspace.TryApplyChanges (project.AddMetadataReference (Reference).Solution))
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ readonly static DateTime NonExistentFile = new DateTime (1601, 1, 1);
+
+ void CreateNewReference ()
+ {
+ timeStamp = File.GetLastWriteTimeUtc (path);
+ if (timeStamp == NonExistentFile) {
+ Reference = null;
+ } else {
+ Reference = MetadataReference.CreateFromFile (path, MetadataReferenceProperties.Assembly);
+ }
+ }
+ }
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopProjectContent.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopProjectContent.cs
deleted file mode 100644
index bc77935929..0000000000
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopProjectContent.cs
+++ /dev/null
@@ -1,109 +0,0 @@
-//
-// MonoDevelopProjectContent.cs
-//
-// Author:
-// Mike Krüger <mkrueger@xamarin.com>
-//
-// Copyright (c) 2012 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.NRefactory.CSharp;
-using ICSharpCode.NRefactory.TypeSystem;
-using ICSharpCode.NRefactory.TypeSystem.Implementation;
-using System.Collections.Generic;
-using MonoDevelop.Projects;
-
-namespace MonoDevelop.Ide.TypeSystem
-{
- [Serializable]
- class MonoDevelopProjectContent : CSharpProjectContent
- {
- [NonSerialized]
- Project project;
-
- public Project Project {
- get {
- return project;
- }
- internal set {
- project = value;
- }
- }
-
- public MonoDevelopProjectContent (Project project)
- {
- this.project = project;
- }
-
- MonoDevelopProjectContent (MonoDevelopProjectContent pc) : base (pc)
- {
- this.project = pc.project;
- }
-
- public override ICompilation CreateCompilation()
- {
- var solutionSnapshot = new DefaultSolutionSnapshot();
- ICompilation compilation = new MonoDevelopCompilation(solutionSnapshot, this, AssemblyReferences);
- solutionSnapshot.AddCompilation(this, compilation);
- return compilation;
- }
-
- protected override CSharpProjectContent Clone()
- {
- return new MonoDevelopProjectContent(this);
- }
-
- public override ICompilation CreateCompilation(ISolutionSnapshot solutionSnapshot)
- {
- return new MonoDevelopCompilation(solutionSnapshot, this, AssemblyReferences);
- }
- }
-
- class MonoDevelopCompilation : SimpleCompilation
- {
- readonly MonoDevelopProjectContent content;
-
- public MonoDevelopCompilation (ISolutionSnapshot solutionSnapshot, MonoDevelopProjectContent content, IEnumerable<IAssemblyReference> assemblyReferences) : base (solutionSnapshot, content, assemblyReferences)
- {
- this.content = content;
- }
-
- public override INamespace GetNamespaceForExternAlias (string alias)
- {
- var netProject = content.Project as DotNetProject;
- if (netProject == null)
- return null;
- foreach (var r in netProject.References) {
- if (r.Aliases == alias) {
- foreach (var refAsm in ReferencedAssemblies) {
- if (refAsm.FullAssemblyName == r.StoredReference) {
- return refAsm.RootNamespace;
- }
-
- }
- }
- }
-
-
- return null;
- }
- }
-}
-
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopSourceTextContainer.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopSourceTextContainer.cs
new file mode 100644
index 0000000000..fa3c9b7192
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopSourceTextContainer.cs
@@ -0,0 +1,123 @@
+//
+// RoslynTypeSystemService.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 Microsoft.CodeAnalysis;
+using System.Linq;
+using System.IO;
+using MonoDevelop.Core;
+using System.Collections.Generic;
+using System.Threading;
+using System.Reflection;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Core.Text;
+using Microsoft.CodeAnalysis.Text;
+
+namespace MonoDevelop.Ide.TypeSystem
+{
+ class MonoDevelopSourceText : SourceText
+ {
+ readonly ITextSource doc;
+
+ public override System.Text.Encoding Encoding {
+ get {
+ return doc.Encoding;
+ }
+ }
+
+ public MonoDevelopSourceText (ITextSource doc)
+ {
+ if (doc == null)
+ throw new ArgumentNullException ("doc");
+ this.doc = doc;
+ }
+
+ #region implemented abstract members of SourceText
+ public override void CopyTo (int sourceIndex, char[] destination, int destinationIndex, int count)
+ {
+ while (count --> 0) {
+ destination[destinationIndex++] = doc.GetCharAt (sourceIndex++);
+ }
+ }
+
+ public override int Length {
+ get {
+ return doc.Length;
+ }
+ }
+
+ public override char this [int index] {
+ get {
+ return doc.GetCharAt (index);
+ }
+ }
+ #endregion
+ }
+
+ class MonoDevelopSourceTextContainer : SourceTextContainer
+ {
+ readonly ITextDocument document;
+ public DocumentId Id {
+ get;
+ private set;
+ }
+
+ public MonoDevelopSourceTextContainer (DocumentId documentId, ITextDocument document) : this (document)
+ {
+ this.Id = documentId;
+ }
+
+ public MonoDevelopSourceTextContainer (ITextDocument document)
+ {
+ this.document = document;
+ this.document.TextChanging += HandleTextReplacing;
+ }
+
+ ~MonoDevelopSourceTextContainer ()
+ {
+ document.TextChanging -= HandleTextReplacing;
+ }
+
+ void HandleTextReplacing (object sender, MonoDevelop.Core.Text.TextChangeEventArgs e)
+ {
+ var handler = TextChanged;
+ if (handler != null) {
+ var oldText = CurrentText;
+ var newText = oldText.Replace (e.Offset, e.RemovalLength, e.InsertedText.Text);
+ handler (this, new Microsoft.CodeAnalysis.Text.TextChangeEventArgs (oldText, newText, new TextChangeRange(TextSpan.FromBounds (e.Offset, e.Offset + e.RemovalLength), e.InsertionLength)));
+ }
+
+ }
+ #region implemented abstract members of SourceTextContainer
+ public override SourceText CurrentText {
+ get {
+ return new MonoDevelopSourceText (document.CreateSnapshot ());
+ }
+ }
+
+ public override event EventHandler<Microsoft.CodeAnalysis.Text.TextChangeEventArgs> TextChanged;
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopTextLoader.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopTextLoader.cs
new file mode 100644
index 0000000000..d81a4d16a7
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopTextLoader.cs
@@ -0,0 +1,69 @@
+//
+// MonoDevelopTextLoader.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 Microsoft.CodeAnalysis;
+using System.Threading.Tasks;
+using System.Threading;
+using Microsoft.CodeAnalysis.Text;
+using MonoDevelop.Core.Text;
+
+namespace MonoDevelop.Ide.TypeSystem
+{
+ class MonoDevelopTextLoader : TextLoader
+ {
+ readonly string fileName;
+
+ public MonoDevelopTextLoader (string fileName)
+ {
+ this.fileName = fileName;
+ }
+
+ #region implemented abstract members of TextLoader
+ TextAndVersion GetTextAndVersion (Workspace workspace, DocumentId documentId)
+ {
+ SourceText text;
+ if (workspace.IsDocumentOpen (documentId)) {
+ text = SourceText.From (TextFileProvider.Instance.GetTextEditorData (fileName).Text);
+ }
+ else {
+ text = SourceText.From (MonoDevelop.Core.Text.TextFileUtility.GetText (fileName));
+ }
+ return TextAndVersion.Create (text, VersionStamp.Create ());
+ }
+
+ public override Task<TextAndVersion> LoadTextAndVersionAsync (Workspace workspace, DocumentId documentId, CancellationToken cancellationToken)
+ {
+ return Task.FromResult (GetTextAndVersion (workspace, documentId));
+ }
+ #endregion
+
+ public static TextLoader CreateFromText (string text)
+ {
+ if (text == null)
+ throw new System.ArgumentNullException ("text");
+ return TextLoader.From (TextAndVersion.Create (SourceText.From (text), VersionStamp.Create ()));
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspace.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspace.cs
new file mode 100644
index 0000000000..e7ce3ef053
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspace.cs
@@ -0,0 +1,848 @@
+//
+// MonoDevelopWorkspace.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 Microsoft.CodeAnalysis;
+using System.Linq;
+using System.IO;
+using MonoDevelop.Core;
+using System.Collections.Generic;
+using System.Threading;
+using Microsoft.CodeAnalysis.Text;
+using System.Threading.Tasks;
+using MonoDevelop.Ide.Editor;
+using Microsoft.CodeAnalysis.Host;
+using MonoDevelop.Core.Text;
+using System.Collections.Concurrent;
+using MonoDevelop.Ide.CodeFormatting;
+using MonoDevelop.Core.ProgressMonitoring;
+using Gtk;
+
+namespace MonoDevelop.Ide.TypeSystem
+{
+ class MonoDevelopWorkspace : Workspace
+ {
+ readonly static HostServices services = Microsoft.CodeAnalysis.Host.Mef.MefHostServices.DefaultHost;
+ CancellationTokenSource src = new CancellationTokenSource ();
+ MonoDevelop.Projects.Solution currentMonoDevelopSolution;
+ object addLock = new object();
+ bool added;
+ bool internalChanges;
+
+ public MonoDevelop.Projects.Solution MonoDevelopSolution {
+ get {
+ return currentMonoDevelopSolution;
+ }
+ }
+
+ public MonoDevelopWorkspace () : base (services, "MonoDevelopWorkspace")
+ {
+ if (IdeApp.Workspace != null) {
+ IdeApp.Workspace.ActiveConfigurationChanged += HandleActiveConfigurationChanged;
+ }
+ }
+
+ protected override void Dispose (bool finalize)
+ {
+ base.Dispose (finalize);
+ if (IdeApp.Workspace != null) {
+ IdeApp.Workspace.ActiveConfigurationChanged -= HandleActiveConfigurationChanged;
+ }
+
+ }
+
+ internal void InformDocumentTextChange (DocumentId id, SourceText text)
+ {
+ base.ApplyDocumentTextChanged (id, text);
+ }
+
+ void CancelLoad ()
+ {
+ src.Cancel ();
+ src = new CancellationTokenSource ();
+ }
+
+ static StatusBarIcon statusIcon = null;
+ static int workspacesLoading = 0;
+
+ internal static event EventHandler LoadingFinished;
+
+ static void OnLoadingFinished (EventArgs e)
+ {
+ var handler = LoadingFinished;
+ if (handler != null)
+ handler (null, e);
+ }
+
+ internal void HideStatusIcon ()
+ {
+ Gtk.Application.Invoke (delegate {
+ workspacesLoading--;
+ if (workspacesLoading == 0 && statusIcon != null) {
+ statusIcon.Dispose ();
+ statusIcon = null;
+ OnLoadingFinished (EventArgs.Empty);
+ }
+ });
+ }
+
+ internal void ShowStatusIcon ()
+ {
+ Gtk.Application.Invoke (delegate {
+ workspacesLoading++;
+ if (statusIcon != null)
+ return;
+ statusIcon = IdeApp.Workbench?.StatusBar.ShowStatusIcon (ImageService.GetIcon ("md-parser"));
+ });
+ }
+
+ void HandleActiveConfigurationChanged (object sender, EventArgs e)
+ {
+ if (currentMonoDevelopSolution == null)
+ return;
+ ShowStatusIcon ();
+ CancelLoad ();
+ var token = src.Token;
+ Task.Run (() => {
+ try {
+ return CreateSolutionInfo (currentMonoDevelopSolution, token);
+ } catch (Exception ex) {
+ LoggingService.LogError ("Error while reloading solution.", ex);
+ return null;
+ }
+ }).ContinueWith ((Task<SolutionInfo> t) => {
+ try {
+ if (t.Status == TaskStatus.RanToCompletion) {
+ if (t.Result == null)
+ return;
+ OnSolutionReloaded (t.Result);
+ }
+ } finally {
+ HideStatusIcon ();
+ }
+ });
+ }
+
+ SolutionInfo CreateSolutionInfo (MonoDevelop.Projects.Solution solution, CancellationToken token)
+ {
+ var projects = new ConcurrentBag<ProjectInfo> ();
+ var mdProjects = solution.GetAllProjects ();
+ Parallel.ForEach (mdProjects, proj => {
+ if (token.IsCancellationRequested)
+ return;
+ projects.Add (LoadProject (proj, token));
+ });
+ if (token.IsCancellationRequested)
+ return null;
+ var solutionInfo = SolutionInfo.Create (GetSolutionId (solution), VersionStamp.Create (), solution.FileName, projects);
+ lock (addLock) {
+ if (!added) {
+ added = true;
+ OnSolutionAdded (solutionInfo);
+ }
+ }
+ return solutionInfo;
+ }
+
+ public void TryLoadSolution (MonoDevelop.Projects.Solution solution/*, IProgressMonitor progressMonitor*/)
+ {
+ this.currentMonoDevelopSolution = solution;
+ CancelLoad ();
+ CreateSolutionInfo (solution, src.Token);
+ }
+
+ public void UnloadSolution ()
+ {
+ OnSolutionRemoved ();
+ }
+
+ Dictionary<MonoDevelop.Projects.Solution, SolutionId> solutionIdMap = new Dictionary<MonoDevelop.Projects.Solution, SolutionId> ();
+
+ internal SolutionId GetSolutionId (MonoDevelop.Projects.Solution solution)
+ {
+ if (solution == null)
+ throw new ArgumentNullException ("solution");
+ lock (solutionIdMap) {
+ SolutionId result;
+ if (!solutionIdMap.TryGetValue (solution, out result)) {
+ result = SolutionId.CreateNewId (solution.Name);
+ solutionIdMap [solution] = result;
+ }
+ return result;
+ }
+ }
+
+ ConcurrentDictionary<MonoDevelop.Projects.Project, ProjectId> projectIdMap = new ConcurrentDictionary<MonoDevelop.Projects.Project, ProjectId> ();
+ ConcurrentDictionary<ProjectId, ProjectData> projectDataMap = new ConcurrentDictionary<ProjectId, ProjectData> ();
+
+ internal MonoDevelop.Projects.Project GetMonoProject (Project project)
+ {
+ return GetMonoProject (project.Id);
+ }
+
+ internal MonoDevelop.Projects.Project GetMonoProject (ProjectId projectId)
+ {
+ foreach (var kv in projectIdMap) {
+ if (kv.Value == projectId)
+ return kv.Key;
+ }
+ return null;
+ }
+
+ public bool Contains (ProjectId projectId)
+ {
+ return projectDataMap.ContainsKey (projectId);
+ }
+
+ internal ProjectId GetProjectId (MonoDevelop.Projects.Project p)
+ {
+ lock (projectIdMap) {
+ ProjectId result;
+ if (projectIdMap.TryGetValue (p, out result))
+ return result;
+ return null;
+ }
+ }
+
+ internal ProjectId GetOrCreateProjectId (MonoDevelop.Projects.Project p)
+ {
+ lock (projectIdMap) {
+ ProjectId result;
+ if (!projectIdMap.TryGetValue (p, out result)) {
+ result = ProjectId.CreateNewId (p.Name);
+ projectIdMap [p] = result;
+ }
+ return result;
+ }
+ }
+
+ ProjectData GetProjectData (ProjectId id)
+ {
+ lock (projectIdMap) {
+ ProjectData result;
+ if (projectDataMap.TryGetValue (id, out result)) {
+ return result;
+ }
+ return null;
+ }
+ }
+
+ ProjectData GetOrCreateProjectData (ProjectId id)
+ {
+ lock (projectIdMap) {
+ ProjectData result;
+ if (!projectDataMap.TryGetValue (id, out result)) {
+ result = new ProjectData (id);
+ projectDataMap [id] = result;
+ }
+ return result;
+ }
+ }
+
+ class ProjectData
+ {
+ readonly ProjectId projectId;
+ readonly Dictionary<string, DocumentId> documentIdMap;
+
+ public ProjectInfo Info {
+ get;
+ set;
+ }
+
+ public ProjectData (ProjectId projectId)
+ {
+ this.projectId = projectId;
+ documentIdMap = new Dictionary<string, DocumentId> (FilePath.PathComparer);
+ }
+
+ internal DocumentId GetOrCreateDocumentId (string name)
+ {
+ lock (documentIdMap) {
+ DocumentId result;
+ if (!documentIdMap.TryGetValue (name, out result)) {
+ result = DocumentId.CreateNewId (projectId, name);
+ documentIdMap [name] = result;
+ }
+ return result;
+ }
+ }
+
+ public DocumentId GetDocumentId (string name)
+ {
+ DocumentId result;
+ if (!documentIdMap.TryGetValue (name, out result))
+ return null;
+ return result;
+ }
+
+ internal void RemoveDocument (string name)
+ {
+ documentIdMap.Remove (name);
+ }
+ }
+
+ internal DocumentId GetDocumentId (ProjectId projectId, string name)
+ {
+ var data = GetProjectData (projectId);
+ if (data == null)
+ return null;
+ return data.GetDocumentId (name);
+ }
+
+ public override bool CanApplyChange (ApplyChangesKind feature)
+ {
+ return true;
+ }
+
+ ProjectInfo LoadProject (MonoDevelop.Projects.Project p, CancellationToken token)
+ {
+ if (!projectIdMap.ContainsKey (p)) {
+ p.FileAddedToProject += OnFileAdded;
+ p.FileRemovedFromProject += OnFileRemoved;
+ p.FileRenamedInProject += OnFileRenamed;
+ p.Modified += OnProjectModified;
+ }
+
+ var projectId = GetOrCreateProjectId (p);
+ var projectData = GetOrCreateProjectData (projectId);
+ var config = IdeApp.Workspace != null ? p.GetConfiguration (IdeApp.Workspace.ActiveConfiguration) as MonoDevelop.Projects.DotNetProjectConfiguration : null;
+ MonoDevelop.Projects.DotNetConfigurationParameters cp = null;
+ if (config != null)
+ cp = config.CompilationParameters as MonoDevelop.Projects.DotNetConfigurationParameters;
+ FilePath fileName = IdeApp.Workspace != null ? p.GetOutputFileName (IdeApp.Workspace.ActiveConfiguration) : new FilePath (p.Name + ".dll");
+ var info = ProjectInfo.Create (
+ projectId,
+ VersionStamp.Create (),
+ p.Name,
+ fileName.FileNameWithoutExtension,
+ LanguageNames.CSharp,
+ p.FileName,
+ fileName,
+ cp != null ? cp.CreateCompilationOptions () : null,
+ cp != null ? cp.CreateParseOptions () : null,
+ CreateDocuments (projectData, p, token),
+ CreateProjectReferences (p, token),
+ CreateMetadataReferences (p, projectId, token)
+ );
+
+ projectData.Info = info;
+ return info;
+ }
+
+ internal static Func<string, TextLoader> CreateTextLoader = fileName => new MonoDevelopTextLoader (fileName);
+
+ static DocumentInfo CreateDocumentInfo (string projectName, ProjectData id, MonoDevelop.Projects.ProjectFile f)
+ {
+ var sourceCodeKind = f.FilePath.Extension == ".sketchcs" ? SourceCodeKind.Interactive : SourceCodeKind.Regular;
+ return DocumentInfo.Create (
+ id.GetOrCreateDocumentId (f.Name),
+ f.FilePath,
+ new [] { projectName }.Concat (f.ProjectVirtualPath.ParentDirectory.ToString ().Split (Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)),
+ sourceCodeKind,
+ CreateTextLoader (f.Name),
+ f.Name,
+ false
+ );
+ }
+
+ IEnumerable<DocumentInfo> CreateDocuments (ProjectData id, MonoDevelop.Projects.Project p, CancellationToken token)
+ {
+ var duplicates = new HashSet<DocumentId> ();
+ foreach (var f in p.Files) {
+ if (token.IsCancellationRequested)
+ yield break;
+ if (TypeSystemParserNode.IsCompileBuildAction (f.BuildAction)) {
+ if (!duplicates.Add (id.GetOrCreateDocumentId (f.Name)))
+ continue;
+ yield return CreateDocumentInfo (p.Name, id, f);
+ continue;
+ }
+ var mimeType = DesktopService.GetMimeTypeForUri (f.FilePath);
+ var node = TypeSystemService.GetTypeSystemParserNode (mimeType, f.BuildAction);
+ if (node == null || !node.Parser.CanGenerateProjection (mimeType, f.BuildAction, p.SupportedLanguages))
+ continue;
+ if (!duplicates.Add (id.GetOrCreateDocumentId (f.Name)))
+ continue;
+ var options = new ParseOptions {
+ FileName = f.FilePath,
+ Project = p,
+ Content = StringTextSource.ReadFrom (f.FilePath),
+ };
+ var projections = node.Parser.GenerateProjections (options);
+ foreach (var projection in projections.Result) {
+ yield return DocumentInfo.Create (
+ id.GetOrCreateDocumentId (projection.Document.FileName),
+ projection.Document.FileName,
+ null,
+ SourceCodeKind.Regular,
+ TextLoader.From (TextAndVersion.Create (new MonoDevelopSourceText (projection.Document), VersionStamp.Create (), projection.Document.FileName)),
+ f.Name,
+ false
+ );
+ }
+ }
+ }
+
+ static IEnumerable<MetadataReference> CreateMetadataReferences (MonoDevelop.Projects.Project p, ProjectId projectId, CancellationToken token)
+ {
+ var netProject = p as MonoDevelop.Projects.DotNetProject;
+ if (netProject == null)
+ yield break;
+ var configurationSelector = IdeApp.Workspace?.ActiveConfiguration ?? MonoDevelop.Projects.ConfigurationSelector.Default;
+ var hashSet = new HashSet<string> (FilePath.PathComparer);
+
+ bool addFacadeAssemblies = false;
+
+ foreach (string file in netProject.GetReferencedAssemblies (configurationSelector, false)) {
+ if (token.IsCancellationRequested)
+ yield break;
+ string fileName;
+ if (!Path.IsPathRooted (file)) {
+ fileName = Path.Combine (Path.GetDirectoryName (netProject.FileName), file);
+ } else {
+ fileName = Path.GetFullPath (file);
+ }
+ if (hashSet.Contains (fileName))
+ continue;
+ hashSet.Add (fileName);
+ yield return MetadataReferenceCache.LoadReference (projectId, fileName);
+ addFacadeAssemblies |= MonoDevelop.Core.Assemblies.SystemAssemblyService.ContainsReferenceToSystemRuntime (fileName);
+ }
+
+ // HACK: Facade assemblies should be added by the project system. Remove that when the project system can do that.
+ if (addFacadeAssemblies) {
+ if (netProject != null) {
+ var runtime = netProject.TargetRuntime ?? MonoDevelop.Core.Runtime.SystemAssemblyService.DefaultRuntime;
+ var facades = runtime.FindFacadeAssembliesForPCL (netProject.TargetFramework);
+ foreach (var facade in facades)
+ yield return MetadataReferenceCache.LoadReference (projectId, facade);
+ }
+ }
+
+ foreach (var pr in p.GetReferencedItems (configurationSelector)) {
+ if (token.IsCancellationRequested)
+ yield break;
+ var referencedProject = pr as MonoDevelop.Projects.DotNetProject;
+ if (referencedProject == null)
+ continue;
+ if (TypeSystemService.IsOutputTrackedProject (referencedProject)) {
+ var fileName = referencedProject.GetOutputFileName (configurationSelector);
+ yield return MetadataReferenceCache.LoadReference (projectId, fileName);
+ }
+ }
+ }
+
+ IEnumerable<ProjectReference> CreateProjectReferences (MonoDevelop.Projects.Project p, CancellationToken token)
+ {
+ foreach (var pr in p.GetReferencedItems (MonoDevelop.Projects.ConfigurationSelector.Default)) {
+ if (token.IsCancellationRequested)
+ yield break;
+ var referencedProject = pr as MonoDevelop.Projects.DotNetProject;
+ if (referencedProject == null)
+ continue;
+ if (TypeSystemService.IsOutputTrackedProject (referencedProject))
+ continue;
+ yield return new ProjectReference (GetOrCreateProjectId (referencedProject));
+ }
+ }
+
+ #region Open documents
+ public override bool CanOpenDocuments {
+ get {
+ return true;
+ }
+ }
+
+ public override void OpenDocument (DocumentId documentId, bool activate = true)
+ {
+ var document = GetDocument (documentId);
+ if (document == null)
+ return;
+ MonoDevelop.Projects.Project prj = null;
+ foreach (var curPrj in IdeApp.Workspace.GetAllProjects ()) {
+ if (GetProjectId (curPrj) == documentId.ProjectId) {
+ prj = curPrj;
+ break;
+ }
+ }
+ IdeApp.Workbench.OpenDocument (new MonoDevelop.Ide.Gui.FileOpenInformation (
+ DetermineFilePath(document.Id, document.Name, document.FilePath, document.Folders),
+ prj,
+ activate
+ ));
+ }
+
+ List<MonoDevelopSourceTextContainer> openDocuments = new List<MonoDevelopSourceTextContainer>();
+ internal void InformDocumentOpen (DocumentId documentId, ITextDocument editor)
+ {
+ var document = this.GetDocument (documentId);
+ if (document == null) {
+ return;
+ }
+ if (IsDocumentOpen (documentId))
+ InformDocumentClose (documentId, document.FilePath);
+ var monoDevelopSourceTextContainer = new MonoDevelopSourceTextContainer (documentId, editor);
+ lock (openDocuments) {
+ openDocuments.Add (monoDevelopSourceTextContainer);
+ }
+ OnDocumentOpened (documentId, monoDevelopSourceTextContainer);
+ }
+
+ Solution newSolution;
+ public override bool TryApplyChanges (Solution newSolution)
+ {
+ this.newSolution = newSolution;
+ return base.TryApplyChanges (newSolution);
+ }
+
+ protected override void ApplyProjectChanges (ProjectChanges projectChanges)
+ {
+ try {
+ internalChanges = true;
+ base.ApplyProjectChanges (projectChanges);
+ var data = GetMonoProject (projectChanges.NewProject);
+ if (data != null) {
+ Application.Invoke (delegate {
+ data.Save (new NullProgressMonitor ());
+ });
+ }
+ } finally {
+ internalChanges = false;
+ }
+ }
+
+ protected override void ApplyAdditionalDocumentAdded (DocumentInfo info, SourceText text)
+ {
+ base.ApplyAdditionalDocumentAdded (info, text);
+ }
+
+ protected override void OnDocumentTextChanged (Document document)
+ {
+ base.OnDocumentTextChanged (document);
+ }
+
+ protected override void OnDocumentClosing (DocumentId documentId)
+ {
+ base.OnDocumentClosing (documentId);
+ lock (openDocuments) {
+ var openDoc = openDocuments.FirstOrDefault (d => d.Id == documentId);
+ if (openDoc != null) {
+// openDoc.TextChanged -= HandleTextChanged;
+ openDocuments.Remove (openDoc);
+ }
+ }
+ }
+
+// internal override bool CanChangeActiveContextDocument {
+// get {
+// return true;
+// }
+// }
+
+ public void InformDocumentClose (DocumentId analysisDocument, string filePath)
+ {
+ try {
+ OnDocumentClosed (analysisDocument, new MonoDevelopTextLoader (filePath));
+ } catch (Exception e) {
+ LoggingService.LogError ("Exception while closing document.", e);
+ }
+ }
+
+ public override void CloseDocument (DocumentId documentId)
+ {
+ }
+
+ protected override void ApplyDocumentTextChanged (DocumentId id, SourceText text)
+ {
+ var document = GetDocument (id);
+
+ if (document == null)
+ return;
+ bool isOpen;
+ var data = TextFileProvider.Instance.GetTextEditorData (document.FilePath, out isOpen);
+ var changes = text.GetTextChanges (document.GetTextAsync ().Result).OrderByDescending (c => c.Span.Start).ToList ();
+
+ int delta = 0;
+ foreach (var change in changes) {
+ data.ReplaceText (change.Span.Start, change.Span.Length, change.NewText);
+ delta += change.Span.Length - change.NewText.Length;
+ }
+
+ if (!isOpen) {
+ var formatter = CodeFormatterService.GetFormatter (data.MimeType);
+ var mp = GetMonoProject (CurrentSolution.GetProject (id.ProjectId));
+ string currentText = data.Text;
+ foreach (var change in changes) {
+ delta -= change.Span.Length - change.NewText.Length;
+ var startOffset = change.Span.Start - delta;
+ var str = formatter.FormatText (mp.Policies, currentText, startOffset, startOffset + change.NewText.Length);
+ data.ReplaceText (startOffset, change.NewText.Length, str);
+ }
+ data.Save ();
+ FileService.NotifyFileChanged (document.FilePath);
+ } else {
+ var formatter = CodeFormatterService.GetFormatter (data.MimeType);
+ var documentContext = IdeApp.Workbench.Documents.FirstOrDefault (d => FilePath.PathComparer.Compare (d.FileName, document.FilePath) == 0);
+ if (documentContext != null) {
+ foreach (var change in changes) {
+ delta -= change.Span.Length - change.NewText.Length;
+ var startOffset = change.Span.Start - delta;
+ formatter.OnTheFlyFormat ((TextEditor)data, documentContext, startOffset, startOffset + change.NewText.Length);
+ }
+ }
+ }
+ OnDocumentTextChanged (id, new MonoDevelopSourceText(data), PreservationMode.PreserveValue);
+ }
+
+ protected override void ApplyDocumentAdded (DocumentInfo info, SourceText text)
+ {
+ var id = info.Id;
+ var path = DetermineFilePath (info.Id, info.Name, info.FilePath, info.Folders, true);
+
+ MonoDevelop.Projects.Project mdProject = null;
+
+ if (id.ProjectId != null) {
+ var project = CurrentSolution.GetProject (id.ProjectId);
+ mdProject = GetMonoProject (project);
+ if (mdProject == null)
+ LoggingService.LogWarning ("Couldn't find project for newly generated file {0} (Project {1}).", path, info.Id.ProjectId);
+ }
+
+ string formattedText;
+ var formatter = CodeFormatterService.GetFormatter (DesktopService.GetMimeTypeForUri (path));
+ if (formatter != null && mdProject != null) {
+ formattedText = formatter.FormatText (mdProject.Policies, text.ToString ());
+ } else {
+ formattedText = text.ToString ();
+ }
+
+ var textSource = new StringTextSource (formattedText, text.Encoding ?? System.Text.Encoding.UTF8);
+ try {
+ textSource.WriteTextTo (path);
+ } catch (Exception e) {
+ LoggingService.LogError ("Exception while saving file to " + path, e);
+ }
+
+ if (mdProject != null) {
+ var file = new MonoDevelop.Projects.ProjectFile (path);
+ Application.Invoke (delegate {
+ mdProject.Files.Add (file);
+ IdeApp.ProjectOperations.Save (mdProject);
+ });
+ }
+
+ OnDocumentAdded (info.WithTextLoader (new MonoDevelopTextLoader (path)));
+ }
+
+ string DetermineFilePath (DocumentId id, string name, string filePath, IReadOnlyList<string> docFolders, bool createDirectory = false)
+ {
+ var path = filePath;
+
+ if (string.IsNullOrEmpty (path)) {
+ var monoProject = GetMonoProject (id.ProjectId);
+
+ // If the first namespace name matches the name of the project, then we don't want to
+ // generate a folder for that. The project is implicitly a folder with that name.
+ IEnumerable<string> folders;
+ if (docFolders.FirstOrDefault () == monoProject.Name) {
+ folders = docFolders.Skip (1);
+ } else {
+ folders = docFolders;
+ }
+
+ if (folders.Any ()) {
+ string baseDirectory = Path.Combine (monoProject.BaseDirectory, Path.Combine (folders.ToArray ()));
+ try {
+ if (createDirectory && !Directory.Exists (baseDirectory))
+ Directory.CreateDirectory (baseDirectory);
+ } catch (Exception e) {
+ LoggingService.LogError ("Error while creating directory for a new file : " + baseDirectory, e);
+ }
+ path = Path.Combine (baseDirectory, name);
+ }
+ }
+ return path;
+ }
+ #endregion
+
+ public Document GetDocument (DocumentId documentId, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var project = CurrentSolution.GetProject (documentId.ProjectId);
+ if (project == null)
+ return null;
+ return project.GetDocument (documentId);
+ }
+
+ public void UpdateFileContent (string fileName, string text)
+ {
+ SourceText newText = SourceText.From (text);
+ foreach (var project in this.projectDataMap.Keys) {
+ var docId = this.GetDocumentId (project, fileName);
+ if (docId == null)
+ continue;
+ base.OnDocumentTextChanged (docId, newText, PreservationMode.PreserveIdentity);
+ }
+ }
+
+ public void AddProject (MonoDevelop.Projects.Project project)
+ {
+ var info = LoadProject (project, default(CancellationToken));
+ OnProjectAdded (info);
+ }
+
+ public void RemoveProject (MonoDevelop.Projects.Project project)
+ {
+ var id = GetProjectId (project);
+ if (id != null) {
+ foreach (var docId in GetOpenDocumentIds (id).ToList ()) {
+ ClearOpenDocument (docId);
+ }
+ OnProjectRemoved (id);
+ ProjectId val;
+ projectIdMap.TryRemove (project, out val);
+ ProjectData val2;
+ projectDataMap.TryRemove (id, out val2);
+ MetadataReferenceCache.RemoveReferences (id);
+
+ project.FileAddedToProject -= OnFileAdded;
+ project.FileRemovedFromProject -= OnFileRemoved;
+ project.FileRenamedInProject -= OnFileRenamed;
+ project.Modified -= OnProjectModified;
+ }
+ }
+
+ #region Project modification handlers
+
+ void OnFileAdded (object sender, MonoDevelop.Projects.ProjectFileEventArgs args)
+ {
+ if (internalChanges)
+ return;
+ var project = (MonoDevelop.Projects.Project)sender;
+ foreach (MonoDevelop.Projects.ProjectFileEventInfo fargs in args) {
+ if (!TypeSystemParserNode.IsCompileBuildAction (fargs.ProjectFile.BuildAction))
+ continue;
+ var projectId = GetProjectId (project);
+ var newDocument = CreateDocumentInfo (project.Name, GetProjectData (projectId), fargs.ProjectFile);
+ OnDocumentAdded (newDocument);
+ }
+ }
+
+ void OnFileRemoved (object sender, MonoDevelop.Projects.ProjectFileEventArgs args)
+ {
+ if (internalChanges)
+ return;
+ var project = (MonoDevelop.Projects.Project)sender;
+ foreach (MonoDevelop.Projects.ProjectFileEventInfo fargs in args) {
+ var projectId = GetProjectId (project);
+ var data = GetProjectData (projectId);
+ var id = data.GetDocumentId (fargs.ProjectFile.FilePath);
+ if (id != null) {
+ ClearDocumentData (id);
+ OnDocumentRemoved (id);
+ data.RemoveDocument (fargs.ProjectFile.FilePath);
+ }
+ }
+ }
+
+ void OnFileRenamed (object sender, MonoDevelop.Projects.ProjectFileRenamedEventArgs args)
+ {
+ if (internalChanges)
+ return;
+ var project = (MonoDevelop.Projects.Project)sender;
+ foreach (MonoDevelop.Projects.ProjectFileRenamedEventInfo fargs in args) {
+ if (!TypeSystemParserNode.IsCompileBuildAction (fargs.ProjectFile.BuildAction))
+ continue;
+
+ var projectId = GetProjectId (project);
+ var data = GetProjectData (projectId);
+
+ var id = data.GetDocumentId (fargs.OldName);
+ if (id != null) {
+ if (this.IsDocumentOpen (id)) {
+ this.InformDocumentClose (id, fargs.OldName);
+ }
+ OnDocumentRemoved (id);
+ data.RemoveDocument (fargs.OldName);
+ }
+
+ var newDocument = CreateDocumentInfo (project.Name, GetProjectData (projectId), fargs.ProjectFile);
+ OnDocumentAdded (newDocument);
+ }
+ }
+
+ void OnProjectModified (object sender, MonoDevelop.Projects.SolutionItemModifiedEventArgs args)
+ {
+ if (internalChanges)
+ return;
+ if (!args.Any (x => x.Hint == "TargetFramework" || x.Hint == "References"))
+ return;
+ var project = (MonoDevelop.Projects.Project)sender;
+ var projectId = GetProjectId (project);
+ OnProjectReloaded (LoadProject (project, default(CancellationToken)));
+ }
+
+ #endregion
+
+ }
+
+// static class MonoDevelopWorkspaceFeatures
+// {
+// static FeaturePack pack;
+//
+// public static FeaturePack Features {
+// get {
+// if (pack == null)
+// Interlocked.CompareExchange (ref pack, ComputePack (), null);
+// return pack;
+// }
+// }
+//
+// static FeaturePack ComputePack ()
+// {
+// var assemblies = new List<Assembly> ();
+// var workspaceCoreAssembly = typeof(Workspace).Assembly;
+// assemblies.Add (workspaceCoreAssembly);
+//
+// LoadAssembly (assemblies, "Microsoft.CodeAnalysis.CSharp.Workspaces");
+// //LoadAssembly (assemblies, "Microsoft.CodeAnalysis.VisualBasic.Workspaces");
+//
+// var catalogs = assemblies.Select (a => new System.ComponentModel.Composition.Hosting.AssemblyCatalog (a));
+//
+// return new MefExportPack (catalogs);
+// }
+//
+// static void LoadAssembly (List<Assembly> assemblies, string assemblyName)
+// {
+// try {
+// var loadedAssembly = Assembly.Load (assemblyName);
+// assemblies.Add (loadedAssembly);
+// } catch (Exception e) {
+// LoggingService.LogWarning ("Couldn't load assembly:" + assemblyName, e);
+// }
+// }
+// }
+
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDocDocumentationProvider.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDocDocumentationProvider.cs
index 67e8fd2bf2..9d98c1beb5 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDocDocumentationProvider.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDocDocumentationProvider.cs
@@ -26,29 +26,18 @@
using System;
using System.Collections.Generic;
using System.Xml;
-using ICSharpCode.NRefactory.TypeSystem;
-using ICSharpCode.NRefactory.TypeSystem.Implementation;
using MonoDevelop.Core;
-using ICSharpCode.NRefactory.Documentation;
using System.Text;
+using Microsoft.CodeAnalysis;
namespace MonoDevelop.Ide.TypeSystem
{
- [Serializable]
- public class MonoDocDocumentationProvider : IDocumentationProvider
+ static class MonoDocDocumentationProvider
{
- [NonSerialized]
- bool hadError;
-
- public MonoDocDocumentationProvider ()
- {
- }
+ static bool hadError;
+ static Dictionary<string, string> commentCache = new Dictionary<string, string> ();
- #region IDocumentationProvider implementation
- [NonSerialized]
- readonly Dictionary<string, DocumentationComment> commentCache = new Dictionary<string, DocumentationComment> ();
-
- public DocumentationComment GetDocumentation (IEntity entity)
+ public static string GetDocumentation (ISymbol entity)
{
if (entity == null)
throw new System.ArgumentNullException ("entity");
@@ -57,8 +46,10 @@ namespace MonoDevelop.Ide.TypeSystem
// shouldn't try it again. A corrupt .zip file could cause long tooltip delays otherwise.
if (hadError)
return null;
- var idString = entity.GetIdString ();
- DocumentationComment result;
+ var idString = entity.GetDocumentationCommentId ();
+ if (string.IsNullOrEmpty (idString))
+ return null;
+ string result;
if (commentCache.TryGetValue (idString, out result))
return result;
XmlDocument doc = null;
@@ -66,21 +57,20 @@ namespace MonoDevelop.Ide.TypeSystem
var helpTree = MonoDevelop.Projects.HelpService.HelpTree;
if (helpTree == null)
return null;
- if (entity.SymbolKind == SymbolKind.TypeDefinition) {
+ if (entity.Kind == SymbolKind.NamedType) {
doc = helpTree.GetHelpXml (idString);
} else {
- var parentId = entity.DeclaringTypeDefinition.GetIdString ();
-
+ var containingType = entity.ContainingType;
+ if (containingType == null)
+ return null;
+ var parentId = containingType.GetDocumentationCommentId ();
doc = helpTree.GetHelpXml (parentId);
if (doc == null)
return null;
XmlNode node = SelectNode (doc, entity);
-
if (node != null)
- return commentCache [idString] = new DocumentationComment (node.OuterXml, new SimpleTypeResolveContext (entity));
+ return commentCache [idString] = node.OuterXml;
return null;
-// var node = doc.SelectSingleNode ("/Type/Members/Member")
-// return new DocumentationComment (doc.OuterXml, new SimpleTypeResolveContext (entity));
}
} catch (Exception e) {
hadError = true;
@@ -90,33 +80,34 @@ namespace MonoDevelop.Ide.TypeSystem
commentCache [idString] = null;
return null;
}
- return commentCache [idString] = new DocumentationComment (doc.OuterXml, new SimpleTypeResolveContext (entity));
+ return commentCache [idString] = doc.OuterXml;
}
- public XmlNode SelectNode (XmlDocument doc, IEntity entity)
+ internal static void ClearCommentCache ()
{
- switch (entity.SymbolKind) {
- case SymbolKind.None:
- case SymbolKind.TypeDefinition:
+ commentCache = new Dictionary<string, string> ();
+ }
+
+ static XmlNode SelectNode (XmlDocument doc, ISymbol entity)
+ {
+ switch (entity.Kind) {
+ case SymbolKind.NamedType:
case SymbolKind.Field:
case SymbolKind.Property:
- case SymbolKind.Indexer:
case SymbolKind.Event:
return doc.SelectSingleNode ("/Type/Members/Member[@MemberName='" + entity.Name + "']");
case SymbolKind.Method:
- case SymbolKind.Operator:
- case SymbolKind.Destructor:
- return SelectOverload (doc.SelectNodes ("/Type/Members/Member[@MemberName='" + entity.Name + "']"), (IParameterizedMember)entity);
- case SymbolKind.Constructor:
- return SelectOverload (doc.SelectNodes ("/Type/Members/Member[@MemberName='.ctor']"), (IParameterizedMember)entity);
-
+ var method = (IMethodSymbol)entity;
+ if (method.MethodKind == MethodKind.Constructor)
+ return SelectOverload (doc.SelectNodes ("/Type/Members/Member[@MemberName='.ctor']"), method);
+ return SelectOverload (doc.SelectNodes ("/Type/Members/Member[@MemberName='" + entity.Name + "']"), method);
default:
throw new ArgumentOutOfRangeException ();
}
-
}
- public XmlNode SelectOverload (XmlNodeList nodes, IParameterizedMember entity)
+
+ static XmlNode SelectOverload (XmlNodeList nodes, IMethodSymbol entity)
{
XmlNode node = null;
if (nodes.Count == 1) {
@@ -125,12 +116,12 @@ namespace MonoDevelop.Ide.TypeSystem
var p = entity.Parameters;
foreach (XmlNode curNode in nodes) {
var paramList = curNode.SelectNodes ("Parameters/*");
- if (p.Count == 0 && paramList.Count == 0)
+ if (p.Length == 0 && paramList.Count == 0)
return curNode;
- if (p.Count != paramList.Count)
+ if (p.Length != paramList.Count)
continue;
bool matched = true;
- for (int i = 0; i < p.Count; i++) {
+ for (int i = 0; i < p.Length; i++) {
var idString = GetTypeString (p [i].Type);
if (idString != paramList [i].Attributes ["Type"].Value) {
matched = false;
@@ -148,69 +139,20 @@ namespace MonoDevelop.Ide.TypeSystem
}
return null;
}
-
- static string GetTypeString (IType t)
+ static string GetTypeString (ITypeSymbol t)
{
- if (t.Kind == TypeKind.Unknown)
- return t.Name;
-
- if (t.Kind == TypeKind.TypeParameter)
- return t.FullName;
-
- var typeWithElementType = t as TypeWithElementType;
- if (typeWithElementType != null) {
- var sb = new StringBuilder ();
-
- if (typeWithElementType is PointerType) {
- sb.Append ("*");
- }
- sb.Append (GetTypeString (typeWithElementType.ElementType));
-
- if (typeWithElementType is ArrayType) {
- sb.Append ("[");
- sb.Append (new string (',', ((ArrayType)t).Dimensions - 1));
- sb.Append ("]");
- }
- return sb.ToString ();
- }
-
- ITypeDefinition typeDef = t.GetDefinition ();
- if (typeDef == null)
- return "";
-
- var result = new StringBuilder ();
-
- result.Append (typeDef.Namespace + ".");
-
- if (typeDef.DeclaringTypeDefinition != null) {
- string typeString = GetTypeString (typeDef.DeclaringTypeDefinition);
- result.Append (typeString);
- result.Append (".");
- }
-
- result.Append (typeDef.Name);
-
- if (typeDef.TypeParameterCount > 0) {
- result.Append ("<");
- for (int i = 0; i < typeDef.TypeParameterCount; i++) {
- if (i > 0)
- result.Append (",");
- if (t.TypeArguments.Count > 0) {
- result.Append (GetTypeString (t.TypeArguments [i]));
- } else {
- result.Append (typeDef.TypeParameters [i].FullName);
- }
- }
- result.Append (">");
+ switch (t.TypeKind) {
+ case TypeKind.Array:
+ var arr = (IArrayTypeSymbol)t;
+ return GetTypeString (arr.ElementType) + "[" + new string (',', arr.Rank - 1) + "]";
+ case TypeKind.Pointer:
+ var ptr = (IPointerTypeSymbol)t;
+ return "*" + GetTypeString (ptr.PointedAtType);
+ default:
+ var docComment = t.GetDocumentationCommentId ();
+ return docComment != null && docComment.Length > 2 ? docComment.Substring (2) : t.Name;
}
-
- return result.ToString ();
}
-
- #endregion
-
-
}
}
-
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/NetAmbience.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/NetAmbience.cs
deleted file mode 100755
index 28b35bc9bb..0000000000
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/NetAmbience.cs
+++ /dev/null
@@ -1,367 +0,0 @@
-//
-// NetAmbience.cs
-//
-// Author:
-// Mike Krüger <mkrueger@novell.com>
-//
-// Copyright (C) 2008 Novell, Inc (http://www.novell.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.Linq;
-using System.Text;
-using ICSharpCode.NRefactory.TypeSystem;
-using System.Collections.Generic;
-
-namespace MonoDevelop.Ide.TypeSystem
-{
- public class NetAmbience : Ambience
- {
- public NetAmbience () : base ("NET")
- {
- classTypes [TypeKind.Class] = "Class";
- classTypes [TypeKind.Enum] = "Enumeration";
- classTypes [TypeKind.Interface] = "Interface";
- classTypes [TypeKind.Struct] = "Structure";
- classTypes [TypeKind.Delegate] = "Delegate";
- }
-
- public override string SingleLineComment (string text)
- {
- return "// " + text;
- }
-
- #region Type system output
- public override string GetIntrinsicTypeName (string reflectionName)
- {
- return reflectionName;
- }
-
- protected override string GetTypeReferenceString (IType reference, OutputSettings settings)
- {
- return reference.ToString ();
- }
-
- protected override string GetTypeString (IType t, OutputSettings settings)
- {
- ITypeDefinition type = t.GetDefinition ();
- var result = new StringBuilder ();
- if (settings.IncludeModifiers)
- AppendModifiers (result, settings, type);
- if (settings.IncludeKeywords)
- result.Append (settings.EmitKeyword (GetString (type.Kind)));
-
- result.Append (settings.EmitName (type, settings.UseFullName ? type.FullName : type.Name));
-
- int parameterCount = type.TypeParameters.Count;
-
- if (settings.IncludeGenerics && parameterCount > 0) {
- result.Append (settings.Markup ("<"));
- if (!settings.HideGenericParameterNames) {
- for (int i = 0; i < parameterCount; i++) {
- if (i > 0)
- result.Append (settings.Markup (", "));
- result.Append (type.TypeParameters [i].Name);
- }
- }
- result.Append (settings.Markup (">"));
- }
-
- if (settings.IncludeBaseTypes && type.DirectBaseTypes.Any ()) {
- result.Append (settings.Markup (" : "));
- bool first = true;
- foreach (var baseType in type.DirectBaseTypes) {
- if (baseType.Equals (type.Compilation.FindType (KnownTypeCode.Object)))
- continue;
- if (!first)
- result.Append (settings.Markup (", "));
- first = false;
- result.Append (GetTypeReferenceString (baseType, settings));
- }
-
- }
- return result.ToString ();
- }
-
- protected override string GetMethodString (IMethod method, OutputSettings settings)
- {
- var result = new StringBuilder ();
-
- if (settings.IncludeModifiers)
- AppendModifiers (result, settings, method);
-
- result.Append (settings.EmitKeyword ("Method"));
- result.Append (settings.EmitName (method, settings.UseFullName ? method.FullName : method.Name));
-
- if (settings.IncludeParameters) {
- result.Append (settings.Markup ("("));
- bool first = true;
- foreach (var parameter in method.Parameters) {
- if (!first)
- result.Append (settings.Markup (", "));
- result.Append (GetParameterString (method, parameter, settings));
- first = false;
- }
- result.Append (settings.Markup (")"));
- }
-
- if (settings.IncludeReturnType) {
- result.Append (settings.Markup (" : "));
- result.Append (GetTypeReferenceString (method.ReturnType, settings));
- }
- return result.ToString ();
- }
-
- protected override string GetConstructorString (IMethod method, OutputSettings settings)
- {
- var result = new StringBuilder ();
-
- if (settings.IncludeModifiers)
- AppendModifiers (result, settings, method);
-
- result.Append (settings.EmitKeyword ("Constructor"));
- result.Append (settings.EmitName (method, method.DeclaringType.Name));
-
- if (settings.IncludeParameters) {
- result.Append (settings.Markup ("("));
- bool first = true;
- foreach (var parameter in method.Parameters) {
- if (!first)
- result.Append (settings.Markup (", "));
- result.Append (GetParameterString (method, parameter, settings));
- first = false;
- }
- result.Append (settings.Markup (")"));
- }
- return result.ToString ();
- }
-
- protected override string GetDestructorString (IMethod method, OutputSettings settings)
- {
- var result = new StringBuilder ();
- result.Append (settings.EmitKeyword ("Destructor"));
- result.Append (settings.EmitName (method, method.DeclaringType.Name));
- return result.ToString ();
- }
-
- protected override string GetOperatorString (IMethod method, OutputSettings settings)
- {
- var result = new StringBuilder ();
-
- if (settings.IncludeModifiers)
- AppendModifiers (result, settings, method);
-
- result.Append (settings.EmitKeyword ("Operator"));
- result.Append (settings.EmitName (method, settings.UseFullName ? method.FullName : method.Name));
-
- if (settings.IncludeParameters) {
- result.Append (settings.Markup ("("));
- bool first = true;
- foreach (var parameter in method.Parameters) {
- if (!first)
- result.Append (settings.Markup (", "));
- result.Append (GetParameterString (method, parameter, settings));
- first = false;
- }
- result.Append (settings.Markup (")"));
- }
-
- if (settings.IncludeReturnType) {
- result.Append (settings.Markup (" : "));
- result.Append (GetTypeReferenceString (method.ReturnType, settings));
- }
- return result.ToString ();
- }
-
- protected override string GetFieldString (IField field, OutputSettings settings)
- {
- var result = new StringBuilder ();
-
- if (settings.IncludeModifiers)
- AppendModifiers (result, settings, field);
-
- result.Append (settings.EmitKeyword ("Field"));
- result.Append (settings.EmitName (field, field.Name));
-
- if (settings.IncludeReturnType) {
- result.Append (settings.Markup (" : "));
- result.Append (GetTypeReferenceString (field.ReturnType, settings));
- }
- return result.ToString ();
- }
-
- protected override string GetEventString (IEvent evt, OutputSettings settings)
- {
- var result = new StringBuilder ();
-
- if (settings.IncludeModifiers)
- AppendModifiers (result, settings, evt);
-
- result.Append (settings.EmitKeyword ("Event"));
- result.Append (settings.EmitName (evt, evt.Name));
-
- if (settings.IncludeReturnType) {
- result.Append (settings.Markup (" : "));
- result.Append (GetTypeReferenceString (evt.ReturnType, settings));
- }
- return result.ToString ();
- }
-
- protected override string GetPropertyString (IProperty property, OutputSettings settings)
- {
- var result = new StringBuilder ();
- if (settings.IncludeModifiers)
- AppendModifiers (result, settings, property);
- result.Append (settings.EmitKeyword ("Property"));
- result.Append (settings.EmitName (property, property.Name));
- if (settings.IncludeReturnType) {
- result.Append (settings.Markup (" : "));
- result.Append (GetTypeReferenceString (property.ReturnType, settings));
- }
- return result.ToString ();
- }
-
- protected override string GetIndexerString (IProperty property, OutputSettings settings)
- {
- var result = new StringBuilder ();
- if (settings.IncludeModifiers)
- AppendModifiers (result, settings, property);
- result.Append (settings.EmitKeyword ("Indexer"));
- result.Append (settings.EmitName (property, property.Name));
-
- if (settings.IncludeParameters && property.Parameters.Count > 0) {
- result.Append (settings.Markup ("("));
- bool first = true;
- foreach (var parameter in property.Parameters) {
- if (!first)
- result.Append (settings.Markup (", "));
- result.Append (GetParameterString (property, parameter, settings));
- first = false;
- }
- result.Append (settings.Markup (")"));
- }
- if (settings.IncludeReturnType) {
- result.Append (settings.Markup (" : "));
- result.Append (GetTypeReferenceString (property.ReturnType, settings));
- }
- return result.ToString ();
- }
-
- protected override string GetParameterString (IParameterizedMember member, IParameter parameter, OutputSettings settings)
- {
- var result = new StringBuilder ();
- if (settings.IncludeParameterName) {
- result.Append (Format (parameter.Name));
- if (settings.IncludeReturnType) {
- result.Append (settings.Markup (" : "));
- result.Append (GetTypeReferenceString (parameter.Type, settings));
- }
- } else {
- result.Append (GetTypeReferenceString (parameter.Type, settings));
- }
- if (parameter.IsRef || parameter.IsOut)
- result.Append (settings.Markup ("&"));
- return result.ToString ();
- }
- #endregion
-
- void AppendModifiers (StringBuilder result, OutputSettings settings, IEntity entity)
- {
- if (entity.IsStatic)
- result.Append (settings.EmitModifiers ("Static"));
- if (entity.IsSealed)
- result.Append (settings.EmitModifiers ("Sealed"));
- if (entity.IsAbstract)
- result.Append (settings.EmitModifiers ("Abstract"));
- if (entity.IsShadowing)
- result.Append (settings.EmitModifiers ("Shadows"));
- if (entity.IsSynthetic)
- result.Append (settings.EmitModifiers ("Synthetic"));
-
- switch (entity.Accessibility) {
- case Accessibility.Internal:
- result.Append (settings.EmitModifiers ("Internal"));
- break;
- case Accessibility.ProtectedAndInternal:
- result.Append (settings.EmitModifiers ("Protected And Internal"));
- break;
- case Accessibility.ProtectedOrInternal:
- result.Append (settings.EmitModifiers ("Protected Or Internal"));
- break;
- case Accessibility.Protected:
- result.Append (settings.EmitModifiers ("Protected"));
- break;
- case Accessibility.Private:
- result.Append (settings.EmitModifiers ("Private"));
- break;
- case Accessibility.Public:
- result.Append (settings.EmitModifiers ("Public"));
- break;
- }
- }
-
- public override string GetString (string nameSpace, OutputSettings settings)
- {
- var result = new StringBuilder ();
- result.Append (settings.EmitKeyword ("Namespace"));
- result.Append (Format (nameSpace));
- return result.ToString ();
- }
-
- Dictionary<TypeKind, string> classTypes = new Dictionary<TypeKind, string> ();
-
- string GetString (TypeKind classType)
- {
- string res;
- if (classTypes.TryGetValue (classType, out res))
- return res;
- return string.Empty;
- }
-// public string Visit (IAttribute attribute, OutputSettings settings)
-// {
-// StringBuilder result = new StringBuilder ();
-// result.Append (settings.Markup ("["));
-// result.Append (GetString (attribute.AttributeType, settings));
-// result.Append (settings.Markup ("("));
-// bool first = true;
-// if (attribute.PositionalArguments != null) {
-// foreach (object o in attribute.PositionalArguments) {
-// if (!first)
-// result.Append (settings.Markup (", "));
-// first = false;
-// if (o is string) {
-// result.Append (settings.Markup ("\""));
-// result.Append (o);
-// result.Append (settings.Markup ("\""));
-// } else if (o is char) {
-// result.Append (settings.Markup ("\""));
-// result.Append (o);
-// result.Append (settings.Markup ("\""));
-// } else
-// result.Append (o);
-// }
-// }
-// result.Append (settings.Markup (")]"));
-// return result.ToString ();
-// }
- }
-}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/OutputFlags.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/OutputFlags.cs
deleted file mode 100644
index 6ef2920d6d..0000000000
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/OutputFlags.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-//
-// OutputFlags.cs
-//
-// Author:
-// Mike Krüger <mkrueger@novell.com>
-//
-// Copyright (C) 2008 Novell, Inc (http://www.novell.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;
-
-namespace MonoDevelop.Ide.TypeSystem
-{
- [Flags]
- public enum OutputFlags {
- None = 0,
-
- // Flags
- UseFullName = 0x0001,
- IncludeReturnType = 0x0002,
- IncludeParameters = 0x0004,
- IncludeParameterName = 0x0008,
- IncludeMarkup = 0x0010,
- IncludeKeywords = 0x0020,
- IncludeModifiers = 0x0040,
- IncludeBaseTypes = 0x0080,
- IncludeGenerics = 0x0100,
- UseIntrinsicTypeNames = 0x0200,
- HighlightName = 0x0400,
- HideExtensionsParameter = 0x0800,
- HideGenericParameterNames= 0x1000,
- HideArrayBrackets = 0x2000,
- UseNETTypeNames = 0x4000, // print 'System.Int32' intead of 'int'
- UseFullInnerTypeName = 0x8000,
- ReformatDelegates = 0x10000,
- GeneralizeGenerics = 0x20000,
- StaticUsage = 0x40000, // to distinguish static usage for extension methods.
- IncludeConstraints = 0x80000,
- ReturnTypesLast = 0x100000,
- CompletionListFomat = 0x200000, // print "Name : type" instead of "type : Name"
- IncludeAccessor = 0x400000, // print {get;set;} after property name.
-
- ClassBrowserEntries = IncludeReturnType | IncludeParameters | IncludeGenerics,
- AssemblyBrowserDescription = IncludeGenerics | IncludeBaseTypes | IncludeReturnType | IncludeParameters | IncludeParameterName | IncludeMarkup | IncludeKeywords | IncludeModifiers
- }
-}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/OutputSettings.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/OutputSettings.cs
deleted file mode 100644
index 0071f2b4ac..0000000000
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/OutputSettings.cs
+++ /dev/null
@@ -1,268 +0,0 @@
-// OutputSettings.cs
-//
-// Author:
-// Mike Krüger <mkrueger@novell.com>
-//
-// Copyright (c) 2008 Novell, Inc (http://www.novell.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.Text;
-using MonoDevelop.Projects.Policies;
-using System.Collections.Generic;
-using ICSharpCode.NRefactory.TypeSystem;
-
-namespace MonoDevelop.Ide.TypeSystem
-{
- public class OutputSettings
- {
- public OutputFlags OutputFlags {
- get;
- set;
- }
-
- public PolicyContainer PolicyParent {
- get;
- set;
- }
-
- public OutputSettings (OutputFlags outputFlags)
- {
- this.OutputFlags = outputFlags;
- }
-
- public string Markup (string text)
- {
- if (MarkupCallback != null)
- return MarkupCallback (text);
- return IncludeMarkup ? PangoFormat (text) : text;
- }
-
- public string EmitName (object domVisitable, string text)
- {
- if (EmitNameCallback != null)
- return EmitNameCallback (domVisitable, text);
- return text;
- }
-
- public string EmitModifiers (string text)
- {
- if (!IncludeModifiers)
- return string.Empty;
- if (EmitModifiersCallback != null)
- return EmitModifiersCallback (text) + " ";
- if (IncludeMarkup)
- return "<b>" + PangoFormat (text) + "</b> ";
- return text + " ";
- }
-
- public string EmitKeyword (string text)
- {
- if (EmitKeywordCallback != null)
- return EmitKeywordCallback (text) + " ";
- if (!IncludeKeywords)
- return "";
- if (IncludeMarkup)
- return "<b>" + PangoFormat (text) + "</b> ";
- return text + " ";
- }
-
- public string Highlight (string text)
- {
- if (HighlightCallback != null)
- return HighlightCallback (text);
- if (IncludeMarkup)
- return "<b>" + PangoFormat (text) + "</b>";
- return text;
- }
-
- public string PostProcess (object domVisitable, string outString)
- {
- if (PostProcessCallback != null)
- return PostProcessCallback (domVisitable, outString);
- return outString;
- }
-
- static string PangoFormat (string input)
- {
- StringBuilder result = new StringBuilder ();
- foreach (char ch in input) {
- switch (ch) {
- case '<':
- result.Append ("&lt;");
- break;
- case '>':
- result.Append ("&gt;");
- break;
- case '&':
- result.Append ("&amp;");
- break;
- default:
- result.Append (ch);
- break;
- }
- }
- return result.ToString ();
- }
-
- public bool IncludeMarkup {
- get {
- return (OutputFlags & OutputFlags.IncludeMarkup) == OutputFlags.IncludeMarkup;
- }
- }
-
- public bool IncludeKeywords {
- get {
- return (OutputFlags & OutputFlags.IncludeKeywords) == OutputFlags.IncludeKeywords;
- }
- }
-
- public bool IncludeModifiers {
- get {
- return (OutputFlags & OutputFlags.IncludeModifiers) == OutputFlags.IncludeModifiers;
- }
- }
-
- public bool UseFullName {
- get {
- return (OutputFlags & OutputFlags.UseFullName) == OutputFlags.UseFullName;
- }
- }
-
- public bool UseFullInnerTypeName {
- get {
- return (OutputFlags & OutputFlags.UseFullInnerTypeName) == OutputFlags.UseFullInnerTypeName;
- }
- }
-
- public bool IncludeParameters {
- get {
- return (OutputFlags & OutputFlags.IncludeParameters) == OutputFlags.IncludeParameters;
- }
- }
-
- public bool IncludeReturnType {
- get {
- return (OutputFlags & OutputFlags.IncludeReturnType) == OutputFlags.IncludeReturnType;
- }
- }
-
- public bool IncludeParameterName {
- get {
- return (OutputFlags & OutputFlags.IncludeParameterName) == OutputFlags.IncludeParameterName;
- }
- }
-
- public bool IncludeBaseTypes {
- get {
- return (OutputFlags & OutputFlags.IncludeBaseTypes) == OutputFlags.IncludeBaseTypes;
- }
- }
-
- public bool IncludeGenerics {
- get {
- return (OutputFlags & OutputFlags.IncludeGenerics) == OutputFlags.IncludeGenerics;
- }
- }
-
- public bool HideArrayBrackets {
- get {
- return (OutputFlags & OutputFlags.HideArrayBrackets) == OutputFlags.HideArrayBrackets;
- }
- }
-
- public bool HighlightName {
- get {
- return (OutputFlags & OutputFlags.HighlightName) == OutputFlags.HighlightName;
- }
- }
-
- public bool HideExtensionsParameter {
- get {
- return (OutputFlags & OutputFlags.HideExtensionsParameter) == OutputFlags.HideExtensionsParameter;
- }
- }
-
- public bool HideGenericParameterNames {
- get {
- return (OutputFlags & OutputFlags.HideGenericParameterNames) != 0;
- }
- }
-
- public bool GeneralizeGenerics {
- get {
- return (OutputFlags & OutputFlags.GeneralizeGenerics) != 0;
- }
- }
-
- public bool UseNETTypeNames {
- get {
- return (OutputFlags & OutputFlags.UseNETTypeNames) != 0;
- }
- }
-
- public bool ReformatDelegates {
- get {
- return (OutputFlags & OutputFlags.ReformatDelegates) != 0;
- }
- }
-
- public bool StaticUsage {
- get {
- return (OutputFlags & OutputFlags.StaticUsage) != 0;
- }
- }
-
- public bool IncludeConstraints {
- get {
- return (OutputFlags & OutputFlags.IncludeConstraints) != 0;
- }
- }
-
- public bool CompletionListFomat {
- get {
- return (OutputFlags & OutputFlags.CompletionListFomat) != 0;
- }
- }
-
- public bool ReturnTypesLast {
- get {
- return (OutputFlags & OutputFlags.ReturnTypesLast) != 0;
- }
- }
-
- public bool IncludeAccessor {
- get {
- return (OutputFlags & OutputFlags.IncludeAccessor) == OutputFlags.IncludeAccessor;
- }
- }
-
- public MarkupText EmitModifiersCallback;
- public MarkupText EmitKeywordCallback;
- public MarkupText MarkupCallback;
- public MarkupText HighlightCallback;
- public Func<object, string, string> EmitNameCallback;
-
- public delegate string MarkupText (string text);
-
- public Func<object, string, string> PostProcessCallback;
- }
-}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/ParsedDocument.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/ParsedDocument.cs
index 0fdb4a13cd..dddd7641f3 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/ParsedDocument.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/ParsedDocument.cs
@@ -29,10 +29,8 @@ using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Threading;
-using ICSharpCode.NRefactory;
-using ICSharpCode.NRefactory.Semantics;
-using Mono.TextEditor;
-
+using MonoDevelop.Ide.Editor;
+using System.Threading.Tasks;
namespace MonoDevelop.Ide.TypeSystem
{
@@ -43,7 +41,6 @@ namespace MonoDevelop.Ide.TypeSystem
NonSerializable = 1
}
-
public abstract class ParsedDocument
{
DateTime lastWriteTimeUtc = DateTime.UtcNow;
@@ -51,63 +48,8 @@ namespace MonoDevelop.Ide.TypeSystem
get { return lastWriteTimeUtc; }
set { lastWriteTimeUtc = value; }
}
-
- [NonSerialized]
- List<Comment> comments = new List<Comment> ();
-
- public virtual IUnresolvedFile ParsedFile {
- get { return null; }
- set { throw new InvalidOperationException (); }
- }
- public IList<Comment> Comments {
- get {
- return comments;
- }
- }
- /// <summary>
- /// Gets or sets a value indicating whether this instance is invalid and needs to be reparsed.
- /// </summary>
- public bool IsInvalid {
- get;
- set;
- }
-
- List<Tag> tagComments = new List<Tag> ();
- public IList<Tag> TagComments {
- get {
- return tagComments;
- }
- }
-
- IEnumerable<FoldingRegion> foldings = null;
- public virtual IEnumerable<FoldingRegion> Foldings {
- get {
- return foldings ?? Enumerable.Empty<FoldingRegion> ();
- }
- }
-
- public IEnumerable<FoldingRegion> UserRegions {
- get {
- return Foldings.Where (f => f.Type == FoldType.UserRegion);
- }
- }
-
- List<PreProcessorDefine> defines = new List<PreProcessorDefine> ();
- public IList<PreProcessorDefine> Defines {
- get {
- return defines;
- }
- }
-
- List<ConditionalRegion> conditionalRegions = new List<ConditionalRegion> ();
- public IList<ConditionalRegion> ConditionalRegions {
- get {
- return conditionalRegions;
- }
- }
-
[NonSerialized]
ParsedDocumentFlags flags;
public ParsedDocumentFlags Flags {
@@ -128,16 +70,30 @@ namespace MonoDevelop.Ide.TypeSystem
fileName = value;
}
}
-
- public virtual IList<Error> Errors {
- get {
- return new Error[0];
- }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance is invalid and needs to be reparsed.
+ /// </summary>
+ public bool IsInvalid {
+ get;
+ set;
}
-
+
+ public abstract Task<IReadOnlyList<Comment>> GetCommentsAsync (CancellationToken cancellationToken = default(CancellationToken));
+ public abstract Task<IReadOnlyList<Tag>> GetTagCommentsAsync (CancellationToken cancellationToken = default(CancellationToken));
+ public abstract Task<IReadOnlyList<FoldingRegion>> GetFoldingsAsync (CancellationToken cancellationToken = default(CancellationToken));
+
+ public async Task<IEnumerable<FoldingRegion>> GetUserRegionsAsync (CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var foldings = await GetFoldingsAsync (cancellationToken).ConfigureAwait (false);
+ return foldings.Where (f => f.Type == FoldType.UserRegion);
+ }
+
+ public abstract Task<IReadOnlyList<Error>> GetErrorsAsync (CancellationToken cancellationToken = default(CancellationToken));
+
public bool HasErrors {
get {
- return Errors.Any (e => e.ErrorType == ErrorType.Error);
+ return GetErrorsAsync ().Result.Any (e => e.ErrorType == ErrorType.Error);
}
}
@@ -162,236 +118,84 @@ namespace MonoDevelop.Ide.TypeSystem
{
this.fileName = fileName;
}
-
-
- public void Add (Comment comment)
- {
- comments.Add (comment);
- }
-
- public void Add (Tag tagComment)
- {
- tagComments.Add (tagComment);
- }
-
- public void Add (PreProcessorDefine define)
- {
- defines.Add (define);
- }
-
- public void Add (ConditionalRegion region)
+ }
+
+ public class DefaultParsedDocument : ParsedDocument
+ {
+ public DefaultParsedDocument (string fileName) : base (fileName)
{
- conditionalRegions.Add (region);
+ Flags |= ParsedDocumentFlags.NonSerializable;
}
- List<FoldingRegion> EnsureFoldingList ()
- {
- if (this.foldings == null || !(foldings is List<FoldingRegion>))
- this.foldings = new List<FoldingRegion> ();
- return (List<FoldingRegion>)foldings;
- }
-
- public void Add (FoldingRegion region)
+ List<Comment> comments = new List<Comment> ();
+
+ public void Add (Comment comment)
{
- EnsureFoldingList ().Add (region);
+ comments.Add (comment);
}
-
- public void Add (IEnumerable<Comment> comments)
+
+ public void AddRange (IEnumerable<Comment> comments)
{
this.comments.AddRange (comments);
}
-
- public void Add (IEnumerable<Tag> tagComments)
- {
- this.tagComments.AddRange (tagComments);
- }
-
- public void Add (IEnumerable<PreProcessorDefine> defines)
- {
- this.defines.AddRange (defines);
- }
-
- public void Add (IEnumerable<FoldingRegion> folds)
- {
- if (foldings == null) {
- this.foldings = folds;
- return;
- }
- if (foldings != null && !(foldings is List<FoldingRegion>))
- EnsureFoldingList ().AddRange (foldings);
- EnsureFoldingList ().AddRange (folds);
- }
-
- public void Add (IEnumerable<ConditionalRegion> conditionalRegions)
- {
- this.conditionalRegions.AddRange (conditionalRegions);
- }
-
- #region IUnresolvedFile delegation
- public virtual IUnresolvedTypeDefinition GetTopLevelTypeDefinition (TextLocation location)
+
+ public override Task<IReadOnlyList<Comment>> GetCommentsAsync (CancellationToken cancellationToken = default(CancellationToken))
{
- return null;
+ return Task.FromResult<IReadOnlyList<Comment>> (comments);
}
-
- public virtual IUnresolvedTypeDefinition GetInnermostTypeDefinition (TextLocation location)
+
+ List<Tag> tagComments = new List<Tag> ();
+
+ public void Add (Tag tagComment)
{
- return null;
+ tagComments.Add (tagComment);
}
- public virtual IUnresolvedMember GetMember (TextLocation location)
+ public void AddRange (IEnumerable<Tag> tagComments)
{
- return null;
+ this.tagComments.AddRange (tagComments);
}
- public virtual IList<IUnresolvedTypeDefinition> TopLevelTypeDefinitions {
- get {
- return new List<IUnresolvedTypeDefinition> ();
- }
+ public override Task<IReadOnlyList<Tag>> GetTagCommentsAsync (CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return Task.FromResult<IReadOnlyList<Tag>> (tagComments);
}
- #endregion
+ List<FoldingRegion> foldingRegions = new List<FoldingRegion> ();
- public Func<MonoDevelop.Ide.Gui.Document, CancellationToken, IRefactoringContext> CreateRefactoringContext;
- public Func<TextEditorData, object, CancellationToken, IRefactoringContext> CreateRefactoringContextWithEditor;
- }
-
- public class DefaultParsedDocument : ParsedDocument, IUnresolvedFile
- {
-
- public override IUnresolvedFile ParsedFile {
- get { return this; }
- }
-
- List<Error> errors = new List<Error> ();
-
- public override IList<Error> Errors {
- get {
- return errors;
- }
- }
-
- public DefaultParsedDocument (string fileName) : base (fileName)
+ public void Add (FoldingRegion foldingRegion)
{
- Flags |= ParsedDocumentFlags.NonSerializable;
- }
-
- #region IUnresolvedFile implementation
- public override IUnresolvedTypeDefinition GetTopLevelTypeDefinition(TextLocation location)
- {
- return TopLevelTypeDefinitions.FirstOrDefault (t => t.Region.IsInside (location));
+ foldingRegions.Add (foldingRegion);
}
-
- public override IUnresolvedTypeDefinition GetInnermostTypeDefinition(TextLocation location)
+
+ public void AddRange (IEnumerable<FoldingRegion> foldingRegions)
{
- IUnresolvedTypeDefinition parent = null;
- var type = GetTopLevelTypeDefinition(location);
- while (type != null) {
- parent = type;
- type = parent.NestedTypes.FirstOrDefault (t => t.Region.IsInside (location));
- }
- return parent;
+ this.foldingRegions.AddRange (foldingRegions);
}
-
- public override IUnresolvedMember GetMember(TextLocation location)
+
+ public override Task<IReadOnlyList<FoldingRegion>> GetFoldingsAsync (CancellationToken cancellationToken = default(CancellationToken))
{
- var type = GetInnermostTypeDefinition(location);
- if (type == null)
- return null;
- return type.Members.FirstOrDefault (e => e.Region.IsInside(location));
- }
-
- List<IUnresolvedTypeDefinition> types = new List<IUnresolvedTypeDefinition> ();
- public override IList<IUnresolvedTypeDefinition> TopLevelTypeDefinitions {
- get {
- return types;
- }
- }
-
- List<IUnresolvedAttribute> attributes = new List<IUnresolvedAttribute> ();
- public IList<IUnresolvedAttribute> AssemblyAttributes {
- get {
- return attributes;
- }
+ return Task.FromResult<IReadOnlyList<FoldingRegion>> (foldingRegions);
}
- public IList<IUnresolvedAttribute> ModuleAttributes {
- get {
- return new List<IUnresolvedAttribute> ();
- }
- }
- #endregion
-
+ List<Error> errors = new List<Error> ();
+
public void Add (Error error)
{
errors.Add (error);
}
-
- public void Add (IEnumerable<Error> errors)
- {
- this.errors.AddRange (errors);
- }
-
- #region IUnresolvedFile implementation
- DateTime? IUnresolvedFile.LastWriteTime {
- get {
- return LastWriteTimeUtc;
- }
- set {
- LastWriteTimeUtc = value.HasValue ? value.Value : DateTime.UtcNow;
- }
- }
- #endregion
- }
-
- [Serializable]
- public class ParsedDocumentDecorator : ParsedDocument
- {
- IUnresolvedFile parsedFile;
-
- public override IUnresolvedFile ParsedFile {
- get { return parsedFile; }
- set { parsedFile = value; FileName = parsedFile.FileName; }
- }
-
- public override IList<Error> Errors {
- get {
- return parsedFile.Errors;
- }
- }
-
- public ParsedDocumentDecorator (IUnresolvedFile parsedFile) : base (parsedFile.FileName)
- {
- this.parsedFile = parsedFile;
- }
-
- public ParsedDocumentDecorator () : base ("")
- {
- }
-
- #region IUnresolvedFile implementation
- public override IUnresolvedTypeDefinition GetTopLevelTypeDefinition (TextLocation location)
- {
- return parsedFile.GetTopLevelTypeDefinition (location);
- }
- public override IUnresolvedTypeDefinition GetInnermostTypeDefinition (TextLocation location)
+ public void AddRange (IEnumerable<Error> errors)
{
- return parsedFile.GetInnermostTypeDefinition (location);
+ this.errors.AddRange (errors);
}
- public override IUnresolvedMember GetMember (TextLocation location)
+ public override Task<IReadOnlyList<Error>> GetErrorsAsync (CancellationToken cancellationToken = default(CancellationToken))
{
- return parsedFile.GetMember (location);
- }
-
- public override IList<IUnresolvedTypeDefinition> TopLevelTypeDefinitions {
- get {
- return parsedFile.TopLevelTypeDefinitions;
- }
+ return Task.FromResult<IReadOnlyList<Error>> (errors);
}
- #endregion
}
-
+
public static class FoldingUtilities
{
static bool IncompleteOrSingleLine (DomRegion region)
@@ -399,7 +203,7 @@ namespace MonoDevelop.Ide.TypeSystem
return region.BeginLine <= 0 || region.EndLine <= region.BeginLine;
}
- public static IEnumerable<FoldingRegion> ToFolds (this IList<Comment> comments)
+ public static IEnumerable<FoldingRegion> ToFolds (this IReadOnlyList<Comment> comments)
{
for (int i = 0; i < comments.Count; i++) {
Comment comment = comments [i];
@@ -449,7 +253,7 @@ namespace MonoDevelop.Ide.TypeSystem
curLine = curComment.Region.BeginLine;
}
- if (j - i > 1) {
+ if (j - i > 1 || (comment.IsDocumentation && comment.Region.BeginLine < comment.Region.EndLine)) {
string txt;
if (comment.IsDocumentation) {
txt = "/// ...";
@@ -483,7 +287,7 @@ namespace MonoDevelop.Ide.TypeSystem
}
yield return new FoldingRegion (txt,
- new DomRegion (comment.Region.Begin, end),
+ new DocumentRegion (comment.Region.Begin, end),
FoldType.Comment);
i = j - 1;
}
@@ -550,6 +354,23 @@ namespace MonoDevelop.Ide.TypeSystem
}
return false;
}
+
+ static bool IsInsideMember (this DocumentRegion region, IUnresolvedTypeDefinition cl)
+ {
+ if (region.IsEmpty || cl == null || !cl.BodyRegion.IsInside (region.Begin.Line, region.Begin.Column))
+ return false;
+ foreach (var member in cl.Members) {
+ if (member.BodyRegion.IsEmpty)
+ continue;
+ if (member.BodyRegion.IsInside (region.Begin.Line, region.Begin.Column) && member.BodyRegion.IsInside (region.End.Line, region.End.Column))
+ return true;
+ }
+ foreach (var inner in cl.NestedTypes) {
+ if (region.IsInsideMember (inner))
+ return true;
+ }
+ return false;
+ }
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/StockIcons.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/StockIcons.cs
index bd7eea162b..d52111e65f 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/StockIcons.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/StockIcons.cs
@@ -25,8 +25,8 @@
// THE SOFTWARE.
using System;
using MonoDevelop.Core;
-using ICSharpCode.NRefactory.TypeSystem;
using Mono.Cecil;
+using ICSharpCode.NRefactory6.CSharp;
namespace MonoDevelop.Ide.TypeSystem
{
@@ -122,149 +122,175 @@ namespace MonoDevelop.Ide.TypeSystem
Stock.Event, Stock.PrivateEvent, Stock.Event, Stock.ProtectedEvent, Stock.InternalEvent, Stock.ProtectedOrInternalEvent, Stock.InternalAndProtectedEvent
};
- public static string GetStockIcon (this INamedElement element)
- {
- if (element is IType)
- return ((IType)element).GetStockIcon ();
- if (element is ITypeParameter)
- return ((ITypeParameter)element).GetStockIcon ();
- if (element is IUnresolvedEntity)
- return ((IUnresolvedEntity)element).GetStockIcon ();
- return ((IEntity)element).GetStockIcon ();
- }
-
- public static string GetStockIcon (this ITypeDefinition entity)
- {
- return GetStockIcon ((IType)entity);
- }
-
- public static string GetStockIcon (this IType entity)
+// public static IconId GetStockIcon (this INamedElement element)
+// {
+// if (element is IType)
+// return ((IType)element).GetStockIcon ();
+// if (element is ITypeParameter)
+// return ((ITypeParameter)element).GetStockIcon ();
+// if (element is IUnresolvedEntity)
+// return ((IUnresolvedEntity)element).GetStockIcon ();
+// return ((IEntity)element).GetStockIcon ();
+// }
+//
+// public static IconId GetStockIcon (this ITypeDefinition entity)
+// {
+// return GetStockIcon ((IType)entity);
+// }
+//
+// public static IconId GetStockIcon (this IType entity)
+// {
+// var def = entity.GetDefinition ();
+// if (def == null)
+// return Class;
+// switch (def.Kind) {
+// case TypeKind.Class:
+// return typeIconTable [0, (int)def.Accessibility];
+// case TypeKind.Enum:
+// return typeIconTable [1, (int)def.Accessibility];
+// case TypeKind.Interface:
+// return typeIconTable [2, (int)def.Accessibility];
+// case TypeKind.Struct:
+// return typeIconTable [3, (int)def.Accessibility];
+// case TypeKind.Delegate:
+// return typeIconTable [4, (int)def.Accessibility];
+// default:
+// return typeIconTable [0, (int)def.Accessibility];
+// }
+// }
+
+ static int GetIndex (Microsoft.CodeAnalysis.Accessibility accessibility)
{
- var def = entity.GetDefinition ();
- if (def == null)
- return Class;
- switch (def.Kind) {
- case TypeKind.Class:
- return typeIconTable [0, (int)def.Accessibility];
- case TypeKind.Enum:
- return typeIconTable [1, (int)def.Accessibility];
- case TypeKind.Interface:
- return typeIconTable [2, (int)def.Accessibility];
- case TypeKind.Struct:
- return typeIconTable [3, (int)def.Accessibility];
- case TypeKind.Delegate:
- return typeIconTable [4, (int)def.Accessibility];
+ switch (accessibility) {
+ case Microsoft.CodeAnalysis.Accessibility.NotApplicable:
+ return 0;
+ case Microsoft.CodeAnalysis.Accessibility.Private:
+ return 1;
+ case Microsoft.CodeAnalysis.Accessibility.ProtectedAndInternal:
+ return 5;
+ case Microsoft.CodeAnalysis.Accessibility.Protected:
+ return 3;
+ case Microsoft.CodeAnalysis.Accessibility.Internal:
+ return 4;
+ case Microsoft.CodeAnalysis.Accessibility.ProtectedOrInternal:
+ return 5;
+ case Microsoft.CodeAnalysis.Accessibility.Public:
+ return 2;
default:
- return typeIconTable [0, (int)def.Accessibility];
+ throw new ArgumentOutOfRangeException ();
}
}
-
- public static string GetStockIcon (this IUnresolvedTypeDefinition def)
+
+ public static IconId GetStockIcon (this Microsoft.CodeAnalysis.ISymbol symbol)
{
- switch (def.Kind) {
- case TypeKind.Class:
- return typeIconTable [0, (int)def.Accessibility];
- case TypeKind.Enum:
- return typeIconTable [1, (int)def.Accessibility];
- case TypeKind.Interface:
- return typeIconTable [2, (int)def.Accessibility];
- case TypeKind.Struct:
- return typeIconTable [3, (int)def.Accessibility];
- case TypeKind.Delegate:
- return typeIconTable [4, (int)def.Accessibility];
+ switch (symbol.Kind) {
+ case Microsoft.CodeAnalysis.SymbolKind.Alias:
+ case Microsoft.CodeAnalysis.SymbolKind.ArrayType:
+ case Microsoft.CodeAnalysis.SymbolKind.Assembly:
+ case Microsoft.CodeAnalysis.SymbolKind.DynamicType:
+ case Microsoft.CodeAnalysis.SymbolKind.ErrorType:
+ case Microsoft.CodeAnalysis.SymbolKind.Label:
+ case Microsoft.CodeAnalysis.SymbolKind.Local:
+ case Microsoft.CodeAnalysis.SymbolKind.NetModule:
+ case Microsoft.CodeAnalysis.SymbolKind.PointerType:
+ return Field;
+ case Microsoft.CodeAnalysis.SymbolKind.NamedType:
+ var namedTypeSymbol = (Microsoft.CodeAnalysis.INamedTypeSymbol)symbol;
+ return typeIconTable [GetTypeIndex(namedTypeSymbol.TypeKind ), GetIndex (namedTypeSymbol.DeclaredAccessibility)];
+ case Microsoft.CodeAnalysis.SymbolKind.Event:
+ var evtSymbol = (Microsoft.CodeAnalysis.IEventSymbol)symbol;
+ return eventIconTable [GetIndex (evtSymbol.DeclaredAccessibility)];
+ case Microsoft.CodeAnalysis.SymbolKind.Field:
+ var fieldSymbol = (Microsoft.CodeAnalysis.IFieldSymbol)symbol;
+ return fieldIconTable [GetIndex (fieldSymbol.DeclaredAccessibility)];
+ case Microsoft.CodeAnalysis.SymbolKind.Method:
+ var methodSymbol = (Microsoft.CodeAnalysis.IMethodSymbol)symbol;
+ return methodIconTable [GetIndex (methodSymbol.DeclaredAccessibility)];
+ case Microsoft.CodeAnalysis.SymbolKind.Namespace:
+ return Namespace;
+ case Microsoft.CodeAnalysis.SymbolKind.Parameter:
+ return Field;
+ case Microsoft.CodeAnalysis.SymbolKind.Property:
+ var propertySymbol = (Microsoft.CodeAnalysis.IPropertySymbol)symbol;
+ return propertyIconTable [GetIndex (propertySymbol.DeclaredAccessibility)];
+ case Microsoft.CodeAnalysis.SymbolKind.RangeVariable:
+ return Field;
+ case Microsoft.CodeAnalysis.SymbolKind.TypeParameter:
+ return Stock.typeIconTable [0, 0];
+ case Microsoft.CodeAnalysis.SymbolKind.Preprocessing:
+ return Field;
default:
- return typeIconTable [0, (int)def.Accessibility];
+ throw new ArgumentOutOfRangeException ();
}
}
-
- public static string GetStockIcon (this IField field)
- {
- return GetStockIcon ((IEntity)field);
- }
-
- public static string GetStockIcon (this IVariable variable)
- {
- return Field;
- }
-
- public static string GetStockIcon (this IParameter parameter)
- {
- return Field;
- }
-
- public static string GetStockIcon (this IUnresolvedTypeParameter parameter)
- {
- return Field;
- }
-
- public static string GetStockIcon (this IEntity entity, bool showAccessibility = true)
+
+ static int GetTypeIndex (Microsoft.CodeAnalysis.TypeKind typeKind)
{
- switch (entity.SymbolKind) {
- case SymbolKind.TypeDefinition:
- return GetStockIcon ((IType)entity);
- case SymbolKind.Field:
- if (showAccessibility)
- return fieldIconTable [(int)entity.Accessibility];
- else
- return fieldIconTable [0];
- case SymbolKind.Method:
- case SymbolKind.Constructor:
- case SymbolKind.Destructor:
- case SymbolKind.Operator:
- if (showAccessibility) {
- if (((IMethod)entity).IsExtensionMethod)
- return extensionMethodIconTable [(int)entity.Accessibility];
- return methodIconTable [(int)entity.Accessibility];
- } else {
- if (((IMethod)entity).IsExtensionMethod)
- return extensionMethodIconTable [0];
- return methodIconTable [0];
- }
- case SymbolKind.Property:
- case SymbolKind.Indexer:
- if (showAccessibility)
- return propertyIconTable [(int)entity.Accessibility];
- else
- return propertyIconTable [0];
- case SymbolKind.Event:
- if (showAccessibility)
- return eventIconTable [(int)entity.Accessibility];
- else
- return eventIconTable [0];
+ switch (typeKind) {
+ case Microsoft.CodeAnalysis.TypeKind.Unknown:
+ case Microsoft.CodeAnalysis.TypeKind.Array:
+ return 0;
+ case Microsoft.CodeAnalysis.TypeKind.Class:
+ return 0;
+ case Microsoft.CodeAnalysis.TypeKind.Delegate:
+ return 4;
+ case Microsoft.CodeAnalysis.TypeKind.Dynamic:
+ return 0;
+ case Microsoft.CodeAnalysis.TypeKind.Enum:
+ return 1;
+ case Microsoft.CodeAnalysis.TypeKind.Error:
+ return 0;
+ case Microsoft.CodeAnalysis.TypeKind.Interface:
+ return 2;
+ case Microsoft.CodeAnalysis.TypeKind.Module:
+ return 0;
+ case Microsoft.CodeAnalysis.TypeKind.Pointer:
+ return 0;
+ case Microsoft.CodeAnalysis.TypeKind.Struct:
+ return 3;
+ case Microsoft.CodeAnalysis.TypeKind.TypeParameter:
+ return 0;
+ case Microsoft.CodeAnalysis.TypeKind.Submission:
+ return 0;
+ default:
+ throw new ArgumentOutOfRangeException ();
}
- return "";
}
- public static string GetStockIcon (this IUnresolvedEntity entity, bool showAccessibility = true)
+
+ internal static IconId GetStockIconForSymbolInfo (this DeclaredSymbolInfo symbol)
{
- switch (entity.SymbolKind) {
- case SymbolKind.TypeDefinition:
- return GetStockIcon ((IUnresolvedTypeDefinition)entity);
- case SymbolKind.Field:
- if (showAccessibility)
- return fieldIconTable [(int)entity.Accessibility];
- else
- return fieldIconTable [0];
- case SymbolKind.Method:
- case SymbolKind.Constructor:
- case SymbolKind.Destructor:
- case SymbolKind.Operator:
- if (showAccessibility)
- return methodIconTable [(int)entity.Accessibility];
- else
- return methodIconTable [0];
- case SymbolKind.Property:
- case SymbolKind.Indexer:
- if (showAccessibility)
- return propertyIconTable [(int)entity.Accessibility];
- else
- return propertyIconTable [0];
- case SymbolKind.Event:
- if (showAccessibility)
- return eventIconTable [(int)entity.Accessibility];
- else
- return eventIconTable [0];
+ switch (symbol.Kind) {
+ case DeclaredSymbolInfoKind.Class:
+ return Stock.Class;
+ case DeclaredSymbolInfoKind.Constant:
+ return Stock.Field;
+ case DeclaredSymbolInfoKind.Constructor:
+ return Stock.Method;
+ case DeclaredSymbolInfoKind.Delegate:
+ return Stock.Delegate;
+ case DeclaredSymbolInfoKind.Enum:
+ return Stock.Enum;
+ case DeclaredSymbolInfoKind.EnumMember:
+ return Stock.Field;
+ case DeclaredSymbolInfoKind.Event:
+ return Stock.Event;
+ case DeclaredSymbolInfoKind.Field:
+ return Stock.Field;
+ case DeclaredSymbolInfoKind.Indexer:
+ return Stock.Method;
+ case DeclaredSymbolInfoKind.Interface:
+ return Stock.Interface;
+ case DeclaredSymbolInfoKind.Method:
+ return Stock.Method;
+ case DeclaredSymbolInfoKind.Module:
+ return Stock.Method;
+ case DeclaredSymbolInfoKind.Property:
+ return Stock.Property;
+ case DeclaredSymbolInfoKind.Struct:
+ return Stock.Struct;
+ default:
+ throw new ArgumentOutOfRangeException ();
}
- return "";
}
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/Tag.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/Tag.cs
index f45231144b..9f6924a2d0 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/Tag.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/Tag.cs
@@ -51,7 +51,8 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
-using ICSharpCode.NRefactory.TypeSystem;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Core.Text;
namespace MonoDevelop.Ide.TypeSystem
{
@@ -66,16 +67,16 @@ namespace MonoDevelop.Ide.TypeSystem
}
}
- public Tag (string key, DomRegion region)
+ public Tag (string key, DocumentRegion region)
{
this.key = key;
base.Region = region;
}
-
- public Tag (string key, string comment, DomRegion region) : base (comment)
+
+ public Tag (string key, string comment, DocumentRegion region) : base (comment)
{
this.key = key;
base.Region = region;
}
}
-}
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemParser.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemParser.cs
index 7470e8c358..62ca819303 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemParser.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemParser.cs
@@ -27,9 +27,53 @@ using System;
using System.IO;
using ICSharpCode.NRefactory.TypeSystem;
using MonoDevelop.Projects;
+using MonoDevelop.Core.Text;
+using Microsoft.CodeAnalysis;
+using System.Threading.Tasks;
+using System.Threading;
+using MonoDevelop.Ide.Editor.Projection;
+using MonoDevelop.Ide.Editor;
+using System.Collections.Generic;
namespace MonoDevelop.Ide.TypeSystem
{
+ public sealed class ParseOptions
+ {
+ public string FileName { get; set; }
+
+ public ITextSource Content { get; set; }
+
+ public MonoDevelop.Projects.Project Project { get; set; }
+
+ public Document RoslynDocument { get; set; }
+ }
+
+ [Flags]
+ public enum DisabledProjectionFeatures {
+ None = 0,
+ Completion = 1 << 0,
+ SemanticHighlighting = 1 << 1,
+ Tooltips = 1 << 2,
+
+ All = Completion | SemanticHighlighting | Tooltips
+ }
+
+ public class ParsedDocumentProjection
+ {
+ public ParsedDocument ParsedDocument { get; private set; }
+
+ public IReadOnlyList<Projection> Projections { get; private set;}
+
+ public DisabledProjectionFeatures DisabledProjectionFeatures { get; private set;}
+
+ public ParsedDocumentProjection (ParsedDocument parsedDocument, IReadOnlyList<Projection> projections, DisabledProjectionFeatures disabledProjectionFeatures = DisabledProjectionFeatures.None)
+ {
+ this.ParsedDocument = parsedDocument;
+ this.Projections = projections;
+ this.DisabledProjectionFeatures = disabledProjectionFeatures;
+ }
+ }
+
/// <summary>
/// A type system parser provides a ParsedDocument (which just adds some more information to a IUnresolvedFile) for
/// a given file. This is required for adding information to the type system service to make the file contents available
@@ -52,24 +96,51 @@ namespace MonoDevelop.Ide.TypeSystem
/// <param name='project'>
/// The project the file belongs to.
/// </param>
- public abstract ParsedDocument Parse (bool storeAst, string fileName, TextReader content, Project project = null);
+ public abstract Task<ParsedDocument> Parse (ParseOptions options, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
- /// Parse the specified file. The file content should be read by the type system parser.
+ /// If true projections are possible. A projection transforms a source to a target language and maps certain parts of the file to parts in the projected file.
+ /// That's used for embedded languages for example.
/// </summary>
- /// <param name='storeAst'>
- /// If set to <c>true</c> the ast should be stored in the parsed document.
- /// </param>
- /// <param name='fileName'>
- /// The name of the file.
- /// </param>
- /// <param name='project'>
- /// The project the file belongs to.
- /// </param>
- public virtual ParsedDocument Parse (bool storeAst, string fileName, Project project = null)
+ /// <returns><c>true</c> if this instance can generate projection the specified mimeType buildAction supportedLanguages;
+ /// otherwise, <c>false</c>.</returns>
+ /// <param name="mimeType">MIME type.</param>
+ /// <param name="buildAction">Build action.</param>
+ /// <param name="supportedLanguages">Supported languages.</param>
+ public virtual bool CanGenerateProjection (string mimeType, string buildAction, string[] supportedLanguages)
+ {
+ return false;
+ }
+
+ /// <summary>
+ /// Generates the plain projection. This is used for type system services.
+ /// </summary>
+ /// <returns>The projection.</returns>
+ /// <param name="options">Options.</param>
+ /// <param name="cancellationToken">Cancellation token.</param>
+ public virtual Task<IReadOnlyList<Projection>> GenerateProjections (ParseOptions options, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ throw new NotSupportedException ();
+ }
+
+ /// <summary>
+ /// Generates the parsed document projection. That contains the parsed document and the projection. This is used inside the IDE for the editor.
+ /// That's usually more efficient than calling Parse/GenerateProjection separately.
+ /// </summary>
+ /// <returns>The parsed document projection.</returns>
+ /// <param name="options">Options.</param>
+ /// <param name="cancellationToken">Cancellation token.</param>
+ public virtual Task<ParsedDocumentProjection> GenerateParsedDocumentProjection (ParseOptions options, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ throw new NotSupportedException ();
+ }
+
+ /// <summary>
+ /// Gets an up to date partial projection used by code completion.
+ /// </summary>
+ public virtual Task<IReadOnlyList<Projection>> GetPartialProjectionsAsync (DocumentContext ctx, TextEditor editor, ParsedDocument currentParsedDocument, CancellationToken cancellationToken = default(CancellationToken))
{
- using (var stream = Mono.TextEditor.Utils.TextFileUtility.OpenStream (fileName))
- return Parse (storeAst, fileName, stream, project);
+ throw new NotSupportedException ();
}
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemParserNode.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemParserNode.cs
index 1cb27e418a..1a58e50598 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemParserNode.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemParserNode.cs
@@ -113,6 +113,4 @@ namespace MonoDevelop.Ide.TypeSystem
}
}
}
-
}
-
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 e18c2c603c..8a5bf71552 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService.cs
@@ -28,138 +28,24 @@ using System.Collections.Generic;
using System.Linq;
using System.IO;
using MonoDevelop.Projects;
-using ICSharpCode.NRefactory.TypeSystem.Implementation;
-using ICSharpCode.NRefactory.TypeSystem;
using Mono.Addins;
using MonoDevelop.Core;
using MonoDevelop.Ide;
-using Mono.TextEditor;
using System.Threading;
-using MonoDevelop.Core.ProgressMonitoring;
using System.Xml;
using ICSharpCode.NRefactory.Utils;
-using ICSharpCode.NRefactory;
using System.Threading.Tasks;
-using ICSharpCode.NRefactory.Documentation;
-using ICSharpCode.NRefactory.CSharp;
using MonoDevelop.Ide.Extensions;
using MonoDevelop.Core.Assemblies;
using System.Text;
-using ICSharpCode.NRefactory.Completion;
-using System.Diagnostics;
-using MonoDevelop.Projects.SharedAssetsProjects;
-using Mono.CSharp.Nullable;
-using MonoDevelop.Ide.Templates;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Core.Text;
+using Microsoft.CodeAnalysis.Text;
+using Mono.Posix;
namespace MonoDevelop.Ide.TypeSystem
{
- public static class TypeSystemServiceExt
- {
- /// <summary>
- /// Tries to the get source project for a given type definition. This operation may fall if it was called on an outdated
- /// compilation unit or the correspondening project was unloaded.
- /// </summary>
- /// <returns><c>true</c>, if get source project was found, <c>false</c> otherwise.</returns>
- /// <param name="type">The type definition.</param>
- /// <param name="project">The project or null if it wasn't found.</param>
- public static bool TryGetSourceProject (this ITypeDefinition type, out Project project)
- {
- var location = type.Compilation.MainAssembly.UnresolvedAssembly.Location;
- if (string.IsNullOrEmpty (location)) {
- project = null;
- return false;
- }
- project = TypeSystemService.GetProject (location);
- return project != null;
- }
-
- /// <summary>
- /// Tries to the get source project for a given type. This operation may fall if it was called on an outdated
- /// compilation unit or the correspondening project was unloaded.
- /// </summary>
- /// <returns><c>true</c>, if get source project was found, <c>false</c> otherwise.</returns>
- /// <param name="type">The type.</param>
- /// <param name="project">The project or null if it wasn't found.</param>
- public static bool TryGetSourceProject (this IType type, out Project project)
- {
- var def = type.GetDefinition ();
- if (def == null) {
- project = null;
- return false;
- }
- return def.TryGetSourceProject (out project);
- }
-
-
- internal static Project GetProjectWhereTypeIsDefined (this ITypeDefinition type)
- {
- var location = type.ParentAssembly.UnresolvedAssembly.Location;
- if (string.IsNullOrEmpty (location))
- return null;
- return TypeSystemService.GetProject (location);
- }
-
- internal static Project GetProjectWhereTypeIsDefined (this IType type)
- {
- Project project;
- TryGetSourceProject (type, out project);
- return project;
- }
-
- public static TextLocation GetLocation (this IType type)
- {
- return type.GetDefinition ().Region.Begin;
- }
-
- public static bool IsBaseType (this IType type, IType potentialBase)
- {
- return type.GetAllBaseTypes ().Any (t => t.Equals (potentialBase));
- }
-
- public static bool IsObsolete (this IEntity member)
- {
- return member != null && member.Attributes.Any (a => a.AttributeType.FullName == "System.ObsoleteAttribute");
- }
-
- public static bool IsObsolete (this IEntity member, out string reason)
- {
- if (member == null) {
- reason = null;
- return false;
- }
- var attr = member.Attributes.FirstOrDefault (a => a.AttributeType.FullName == "System.ObsoleteAttribute");
- if (attr == null) {
- reason = null;
- return false;
- }
- reason = attr.PositionalArguments.Count > 0 ? attr.PositionalArguments [0].ConstantValue.ToString () : null;
- return true;
- }
-
- public static IType Resolve (this IUnresolvedTypeDefinition def, Project project)
- {
- if (project == null)
- throw new ArgumentNullException ("project");
- var compilation = TypeSystemService.GetCompilation (project);
- var ctx = new SimpleTypeResolveContext (compilation.MainAssembly);
- var resolvedType = def.Resolve (ctx);
- return resolvedType;
- }
- }
-
- /// <summary>
- /// The folding parser is used for generating a preliminary parsed document that does not
- /// contain a full dom - only some basic lexical constructs like comments or pre processor directives.
- ///
- /// This is useful for opening a document the first time to have some folding regions as start that are folded by default.
- /// Otherwise an irritating screen update will occur.
- /// </summary>
- public interface IFoldingParser
- {
- ParsedDocument Parse (string fileName, string content);
- }
-
- public static class TypeSystemService
+ public static partial class TypeSystemService
{
const string CurrentVersion = "1.1.8";
static readonly List<TypeSystemParserNode> parsers;
@@ -171,6 +57,11 @@ namespace MonoDevelop.Ide.TypeSystem
}
}
+ public static bool TrackFileChanges {
+ get;
+ set;
+ }
+
public static void RemoveSkippedfile (FilePath fileName)
{
filesSkippedInParseThread = filesSkippedInParseThread.Where (f => f != fileName).ToArray ();
@@ -196,7 +87,33 @@ namespace MonoDevelop.Ide.TypeSystem
break;
}
});
+ try {
+ emptyWorkspace = new MonoDevelopWorkspace ();
+ } catch (Exception e) {
+ LoggingService.LogFatalError ("Can't create roslyn workspace", e);
+ }
+ FileService.FileChanged += delegate(object sender, FileEventArgs e) {
+ // if (!TrackFileChanges)
+ // return;
+ foreach (var file in e) {
+ // Open documents are handled by the Document class itself.
+ if (IdeApp.Workbench != null && IdeApp.Workbench.GetDocument (file.FileName) != null)
+ continue;
+ try {
+ var text = MonoDevelop.Core.Text.StringTextSource.ReadFrom (file.FileName).Text;
+ foreach (var w in Workspaces)
+ w.UpdateFileContent (file.FileName, text);
+ } catch (FileNotFoundException) {}
+ }
+ if (IdeApp.Workbench != null)
+ foreach (var w in IdeApp.Workbench.Documents)
+ w.StartReparseThread ();
+ };
+
+ IntitializeTrackedProjectHandling ();
+ }
+/*
AddinManager.AddExtensionNodeHandler ("/MonoDevelop/TypeSystem/OutputTracking", delegate (object sender, ExtensionNodeEventArgs args) {
var node = (TypeSystemOutputTrackingNode)args.ExtensionNode;
switch (args.Change) {
@@ -209,63 +126,11 @@ namespace MonoDevelop.Ide.TypeSystem
}
});
- FileService.FileChanged += delegate(object sender, FileEventArgs e) {
- if (!TrackFileChanges)
- return;
- foreach (var file in e) {
- // Open documents are handled by the Document class itself.
- if (IdeApp.Workbench != null && IdeApp.Workbench.GetDocument (file.FileName) != null)
- continue;
- //
- lock (projectWrapperUpdateLock) {
- foreach (var wrapper in projectContents.Values) {
- var projectFile = wrapper.Project.Files.GetFile (file.FileName);
- if (projectFile != null)
- QueueParseJob (wrapper, new [] { projectFile });
- }
- UnresolvedAssemblyProxy ctx;
- if (cachedAssemblyContents.TryGetValue (file.FileName, out ctx))
- CheckModifiedFile (ctx);
- }
- }
-
- foreach (var content in projectContents.Values.ToArray ()) {
- var files = new List<ProjectFile> ();
- foreach (var file in e) {
- var f = content.Project.GetProjectFile (file.FileName);
- if (f == null || f.BuildAction == BuildAction.None)
- continue;
- files.Add (f);
- }
- if (files.Count > 0)
- QueueParseJob (content, files);
- }
-
- };
- if (IdeApp.ProjectOperations != null) {
- IdeApp.ProjectOperations.EndBuild += HandleEndBuild;
- }
- if (IdeApp.Workspace != null) {
- IdeApp.Workspace.ActiveConfigurationChanged += HandleActiveConfigurationChanged;
- }
- }
-
- static void HandleActiveConfigurationChanged (object sender, EventArgs e)
- {
- foreach (var pr in projectContents.ToArray ()) {
- var project = pr.Key as DotNetProject;
- if (project != null)
- CheckProjectOutput (project, true);
-
- pr.Value.referencesConnected = false;
- }
- }
-
static readonly List<TypeSystemOutputTrackingNode> outputTrackedProjects = new List<TypeSystemOutputTrackingNode> ();
static bool IsOutputTracked (DotNetProject project)
{
- foreach (var projectType in project.GetTypeTags ()) {
+ foreach (var projectType in project.GetProjectTypes ()) {
if (outputTrackedProjects.Any (otp => otp.ProjectType != null && string.Equals (otp.ProjectType, projectType, StringComparison.OrdinalIgnoreCase))) {
return true;
}
@@ -273,35 +138,7 @@ namespace MonoDevelop.Ide.TypeSystem
return outputTrackedProjects.Any (otp => otp.LanguageName != null && string.Equals (otp.LanguageName, project.LanguageName, StringComparison.OrdinalIgnoreCase));
}
- static void CheckProjectOutput (DotNetProject project, bool autoUpdate)
- {
- if (project == null)
- throw new ArgumentNullException ("project");
- if (IsOutputTracked (project)) {
- var fileName = project.GetOutputFileName (IdeApp.Workspace.ActiveConfiguration);
-
- var wrapper = GetProjectContentWrapper (project);
- if (wrapper == null)
- return;
- bool update = wrapper.UpdateTrackedOutputAssembly (fileName);
- if (autoUpdate && update) {
- wrapper.ReconnectAssemblyReferences ();
-
- // update documents
- foreach (var openDocument in IdeApp.Workbench.Documents) {
- openDocument.ReparseDocument ();
- }
- }
- }
- }
-
- static void HandleEndBuild (object sender, BuildEventArgs args)
- {
- var project = args.SolutionItem as DotNetProject;
- if (project == null)
- return;
- CheckProjectOutput (project, true);
- }
+*/
public static TypeSystemParser GetParser (string mimeType, string buildAction = BuildAction.Compile)
{
@@ -309,7 +146,7 @@ namespace MonoDevelop.Ide.TypeSystem
return n != null ? n.Parser : null;
}
- static TypeSystemParserNode GetTypeSystemParserNode (string mimeType, string buildAction)
+ internal static TypeSystemParserNode GetTypeSystemParserNode (string mimeType, string buildAction)
{
foreach (var mt in DesktopService.GetMimeTypeInheritanceChain (mimeType)) {
var provider = Parsers.FirstOrDefault (p => p.CanParse (mt, buildAction));
@@ -319,172 +156,157 @@ namespace MonoDevelop.Ide.TypeSystem
return null;
}
- static List<MimeTypeExtensionNode> foldingParsers;
-
- static IEnumerable<MimeTypeExtensionNode> FoldingParsers {
- get {
- if (foldingParsers == null) {
- foldingParsers = new List<MimeTypeExtensionNode> ();
- AddinManager.AddExtensionNodeHandler ("/MonoDevelop/TypeSystem/FoldingParser", delegate (object sender, ExtensionNodeEventArgs args) {
- switch (args.Change) {
- case ExtensionChange.Add:
- foldingParsers.Add ((MimeTypeExtensionNode)args.ExtensionNode);
- break;
- case ExtensionChange.Remove:
- foldingParsers.Remove ((MimeTypeExtensionNode)args.ExtensionNode);
- break;
- }
- });
- }
- return foldingParsers;
- }
- }
-
- public static IFoldingParser GetFoldingParser (string mimeType)
+ public static Task<ParsedDocument> ParseFile (Project project, string fileName, CancellationToken cancellationToken = default(CancellationToken))
{
- foreach (var mt in DesktopService.GetMimeTypeInheritanceChain (mimeType)) {
- var node = FoldingParsers.FirstOrDefault (n => n.MimeType == mt);
- if (node != null)
- return node.CreateInstance () as IFoldingParser;
- }
- return null;
- }
+ StringTextSource text;
- public static ParsedDocument ParseFile (Project project, string fileName)
- {
- string text;
-
try {
if (!File.Exists (fileName))
return null;
- text = Mono.TextEditor.Utils.TextFileUtility.ReadAllText (fileName);
+ text = StringTextSource.ReadFrom (fileName);
} catch (Exception) {
return null;
}
-
- return ParseFile (project, fileName, DesktopService.GetMimeTypeForUri (fileName), text);
+
+ return ParseFile (project, fileName, DesktopService.GetMimeTypeForUri (fileName), text, cancellationToken);
}
- static readonly object projectWrapperUpdateLock = new object ();
-
- public static ParsedDocument ParseFile (Project project, string fileName, string mimeType, string content)
+ public static Task<ParsedDocument> ParseFile (ParseOptions options, string mimeType, CancellationToken cancellationToken = default(CancellationToken))
{
- if (fileName == null)
- throw new ArgumentNullException ("fileName");
+ if (options == null)
+ throw new ArgumentNullException ("options");
+ if (options.FileName == null)
+ throw new ArgumentNullException ("options.FileName");
+
var parser = GetParser (mimeType);
if (parser == null)
- return null;
+ return Task.FromResult ((ParsedDocument)null);
- var t = Counters.ParserService.FileParsed.BeginTiming (fileName);
+ var t = Counters.ParserService.FileParsed.BeginTiming (options.FileName);
try {
- var result = parser.Parse (true, fileName, new StringReader (content), project);
- lock (projectWrapperUpdateLock) {
- ProjectContentWrapper wrapper;
- if (project != null) {
- projectContents.TryGetValue (project, out wrapper);
- } else {
- wrapper = null;
- }
- if (wrapper != null && (result.Flags & ParsedDocumentFlags.NonSerializable) != ParsedDocumentFlags.NonSerializable) {
- var oldFile = wrapper._content.GetFile (fileName);
- wrapper.UpdateContent (c => c.AddOrUpdateFiles (result.ParsedFile));
- UpdateProjectCommentTasks (wrapper, result);
- if (oldFile != null)
- wrapper.InformFileRemoved (new ParsedFileEventArgs (oldFile));
- wrapper.InformFileAdded (new ParsedFileEventArgs (result.ParsedFile));
- }
-
- // The parsed file could be included in other projects as well, therefore
- // they need to be updated.
- foreach (var cnt in projectContents.ToArray ()) {
- if (cnt.Key == project)
- continue;
- // Use the project context because file lookup is faster there than in the project class.
- var pcnt = cnt.Value;
- var file = pcnt._content.GetFile (fileName);
- if (file != null) {
- var newResult = parser.Parse (false, fileName, new StringReader (content), pcnt.Project);
- if ((newResult.Flags & ParsedDocumentFlags.NonSerializable) != ParsedDocumentFlags.NonSerializable) {
- pcnt.UpdateContent (c => c.AddOrUpdateFiles (newResult.ParsedFile));
- pcnt.InformFileRemoved (new ParsedFileEventArgs (file));
- pcnt.InformFileAdded (new ParsedFileEventArgs (newResult.ParsedFile));
- }
- }
- }
- }
+ var result = parser.Parse (options, cancellationToken);
return result;
+ } catch (OperationCanceledException) {
+ return Task.FromResult ((ParsedDocument)null);
} catch (Exception e) {
LoggingService.LogError ("Exception while parsing: " + e);
- return null;
+ return Task.FromResult ((ParsedDocument)null);
} finally {
t.Dispose ();
}
}
- public static ParsedDocument ParseFile (Project project, string fileName, string mimeType, TextReader content)
+ internal static bool CanParseProjections (Project project, string mimeType, string fileName)
+ {
+ var parser = GetParser (mimeType);
+ if (parser == null)
+ return false;
+ var projectFile = project.GetProjectFile (fileName);
+ if (projectFile == null)
+ return false;
+
+ return parser.CanGenerateProjection (mimeType, projectFile.BuildAction, project.SupportedLanguages);
+ }
+
+ public static Task<ParsedDocument> ParseFile (Project project, string fileName, string mimeType, ITextSource content, CancellationToken cancellationToken = default(CancellationToken))
{
- return ParseFile (project, fileName, mimeType, content.ReadToEnd ());
+ return ParseFile (new ParseOptions { FileName = fileName, Project = project, Content = content }, mimeType, cancellationToken);
}
- public static ParsedDocument ParseFile (Project project, TextEditorData data)
+ public static Task<ParsedDocument> ParseFile (Project project, string fileName, string mimeType, TextReader content, CancellationToken cancellationToken = default(CancellationToken))
{
- return ParseFile (project, data.FileName, data.MimeType, data.Text);
+ return ParseFile (project, fileName, mimeType, new StringTextSource (content.ReadToEnd ()), cancellationToken);
}
- public static ParsedDocument ParseFile (string fileName, string mimeType, string text, ProjectContentWrapper wrapper = null)
+ public static Task<ParsedDocument> ParseFile (Project project, IReadonlyTextDocument data, CancellationToken cancellationToken = default(CancellationToken))
{
- using (var reader = new StringReader (text))
- return ParseFile (fileName, mimeType, reader, wrapper);
+ return ParseFile (project, data.FileName, data.MimeType, data, cancellationToken);
}
- public static ParsedDocument ParseFile (string fileName, string mimeType, TextReader content, ProjectContentWrapper wrapper = null)
+ internal static Task<ParsedDocumentProjection> ParseProjection (ParseOptions options, string mimeType, CancellationToken cancellationToken = default(CancellationToken))
{
+ if (options == null)
+ throw new ArgumentNullException ("options");
+ if (options.FileName == null)
+ throw new ArgumentNullException ("fileName");
+
var parser = GetParser (mimeType);
if (parser == null)
- return null;
- var t = Counters.ParserService.FileParsed.BeginTiming (fileName);
+ return Task.FromResult ((ParsedDocumentProjection)null);
+
+ var t = Counters.ParserService.FileParsed.BeginTiming (options.FileName);
try {
- var result = parser.Parse (true, fileName, content);
- lock (projectWrapperUpdateLock) {
- if (wrapper != null && (result.Flags & ParsedDocumentFlags.NonSerializable) != ParsedDocumentFlags.NonSerializable) {
- var oldFile = wrapper._content.GetFile (fileName);
- wrapper.UpdateContent (c => c.AddOrUpdateFiles (result.ParsedFile));
- UpdateProjectCommentTasks (wrapper, result);
- if (oldFile != null)
- wrapper.InformFileRemoved (new ParsedFileEventArgs (oldFile));
- wrapper.InformFileAdded (new ParsedFileEventArgs (result.ParsedFile));
+ var result = parser.GenerateParsedDocumentProjection (options, cancellationToken);
+ if (options.Project != null) {
+ var Workspace = Workspaces.First () ;
+ var projectId = Workspace.GetProjectId (options.Project);
+ if (projectId != null) {
+ foreach (var projection in result.Result.Projections) {
+ var docId = Workspace.GetDocumentId (projectId, projection.Document.FileName);
+ if (docId != null)
+ Workspace.InformDocumentTextChange (docId, new MonoDevelopSourceText (projection.Document));
+ }
}
}
return result;
+ } catch (OperationCanceledException) {
+ return Task.FromResult ((ParsedDocumentProjection)null);
} catch (Exception e) {
- LoggingService.LogError ("Exception while parsing :" + e);
- return null;
+ LoggingService.LogError ("Exception while parsing: " + e);
+ return Task.FromResult ((ParsedDocumentProjection)null);
} finally {
t.Dispose ();
}
}
- public static event EventHandler ParseOperationStarted;
+ internal static Task<ParsedDocumentProjection> ParseProjection (Project project, string fileName, string mimeType, ITextSource content, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return ParseProjection (new ParseOptions { FileName = fileName, Project = project, Content = content }, mimeType, cancellationToken);
+ }
+
+ internal static Task<ParsedDocumentProjection> ParseProjection (Project project, string fileName, string mimeType, TextReader content, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return ParseProjection (project, fileName, mimeType, new StringTextSource (content.ReadToEnd ()), cancellationToken);
+ }
- internal static void StartParseOperation ()
+ internal static Task<ParsedDocumentProjection> ParseProjection (Project project, IReadonlyTextDocument data, CancellationToken cancellationToken = default(CancellationToken))
{
- if ((parseStatus++) == 0) {
- if (ParseOperationStarted != null)
- ParseOperationStarted (null, EventArgs.Empty);
- }
+ return ParseProjection (project, data.FileName, data.MimeType, data, cancellationToken);
}
- public static event EventHandler ParseOperationFinished;
+
+ #region Folding parsers
+ static List<MimeTypeExtensionNode> foldingParsers;
- internal static void EndParseOperation ()
+ static IEnumerable<MimeTypeExtensionNode> FoldingParsers {
+ get {
+ if (foldingParsers == null) {
+ foldingParsers = new List<MimeTypeExtensionNode> ();
+ AddinManager.AddExtensionNodeHandler ("/MonoDevelop/TypeSystem/FoldingParser", delegate (object sender, ExtensionNodeEventArgs args) {
+ switch (args.Change) {
+ case ExtensionChange.Add:
+ foldingParsers.Add ((MimeTypeExtensionNode)args.ExtensionNode);
+ break;
+ case ExtensionChange.Remove:
+ foldingParsers.Remove ((MimeTypeExtensionNode)args.ExtensionNode);
+ break;
+ }
+ });
+ }
+ return foldingParsers;
+ }
+ }
+
+ public static IFoldingParser GetFoldingParser (string mimeType)
{
- if (parseStatus == 0)
- return;
- if (--parseStatus == 0) {
- if (ParseOperationFinished != null)
- ParseOperationFinished (null, EventArgs.Empty);
+ foreach (var mt in DesktopService.GetMimeTypeInheritanceChain (mimeType)) {
+ var node = FoldingParsers.FirstOrDefault (n => n.MimeType == mt);
+ if (node != null)
+ return node.CreateInstance () as IFoldingParser;
}
+ return null;
}
+ #endregion
#region Parser Database Handling
@@ -702,7 +524,7 @@ namespace MonoDevelop.Ide.TypeSystem
{
var t = Counters.ParserService.ObjectDeserialized.BeginTiming (path);
try {
- using (var fs = new FileStream (path, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.SequentialScan)) {
+ using (var fs = new FileStream (path, System.IO.FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.SequentialScan)) {
using (var reader = new BinaryReaderWith7BitEncodedInts (fs)) {
lock (sharedSerializer) {
return (T)sharedSerializer.Deserialize (reader);
@@ -724,7 +546,7 @@ namespace MonoDevelop.Ide.TypeSystem
var t = Counters.ParserService.ObjectSerialized.BeginTiming (path);
try {
- using (var fs = new FileStream (path, FileMode.Create, FileAccess.Write)) {
+ using (var fs = new FileStream (path, System.IO.FileMode.Create, FileAccess.Write)) {
using (var writer = new BinaryWriterWith7BitEncodedInts (fs)) {
lock (sharedSerializer) {
sharedSerializer.Serialize (writer, obj);
@@ -805,2230 +627,86 @@ namespace MonoDevelop.Ide.TypeSystem
}
}
- static void StoreProjectCache (Project project, ProjectContentWrapper wrapper)
- {
- if (!wrapper.WasChanged)
- return;
- string cacheDir = GetCacheDirectory (project, true);
- string fileName = Path.GetTempFileName ();
-
- SerializeObject (fileName, wrapper.Content.RemoveAssemblyReferences (wrapper.Content.AssemblyReferences));
-
- string cacheFile = Path.Combine (cacheDir, "completion.cache");
-
- try {
- if (File.Exists (cacheFile))
- File.Delete (cacheFile);
- File.Move (fileName, cacheFile);
- } catch (Exception e) {
- LoggingService.LogError ("Error whil saving cache " + cacheFile, e);
- }
-
- foreach (var extensionObject in wrapper.ExtensionObjects) {
- StoreExtensionObject (cacheDir, extensionObject);
- }
- }
-
#endregion
-
- #region Project loading
-
- public static void Load (WorkspaceItem item)
- {
- using (Counters.ParserService.WorkspaceItemLoaded.BeginTiming ()) {
- InternalLoad (item);
- CleanupCache ();
- }
- }
- static CancellationTokenSource loadCancellationSource = new CancellationTokenSource ();
- static bool loadWs = false;
- static void InternalLoad (WorkspaceItem item)
- {
- var ws = item as Workspace;
- if (ws != null) {
- loadWs = true;
- loadCancellationSource.Cancel ();
- loadCancellationSource = new CancellationTokenSource ();
- foreach (WorkspaceItem it in ws.Items)
- InternalLoad (it);
- ws.ItemAdded += OnWorkspaceItemAdded;
- ws.ItemRemoved += OnWorkspaceItemRemoved;
- } else {
- if (!loadWs) {
- loadCancellationSource.Cancel ();
- loadCancellationSource = new CancellationTokenSource ();
- }
- var solution = item as Solution;
- if (solution != null) {
- Parallel.ForEach (solution.GetAllProjects (), project => LoadProject (project));
- var list = projectContents.Values.ToList ();
- Task.Run (delegate {
- foreach (var wrapper in list) {
- CheckModifiedFiles (wrapper.Project, wrapper.Project.Files.ToArray (), wrapper, loadCancellationSource.Token);
- }
- });
-
- solution.SolutionItemAdded += OnSolutionItemAdded;
- solution.SolutionItemRemoved += OnSolutionItemRemoved;
- OnSolutionLoaded (new SolutionEventArgs (solution));
- }
- }
- }
-
- public static event EventHandler<SolutionEventArgs> SolutionLoaded;
-
- static void OnSolutionLoaded (SolutionEventArgs e)
- {
- var handler = SolutionLoaded;
- if (handler != null)
- handler (null, e);
- }
-
- [Serializable]
- public class UnresolvedAssemblyDecorator : IUnresolvedAssembly
- {
- readonly ProjectContentWrapper wrapper;
-
- IUnresolvedAssembly assembly {
- get {
- if (wrapper.OutputAssembly != null)
- return wrapper.OutputAssembly;
- return wrapper.Compilation.MainAssembly.UnresolvedAssembly;
- }
- }
-
- public UnresolvedAssemblyDecorator (ProjectContentWrapper wrapper)
- {
- this.wrapper = wrapper;
- }
-
- #region IUnresolvedAssembly implementation
-
- public string AssemblyName {
- get {
- return assembly.AssemblyName;
- }
- }
-
- public string FullAssemblyName {
- get {
- return assembly.FullAssemblyName;
- }
- }
-
- public string Location {
- get {
- return assembly.Location;
- }
- }
-
- public IEnumerable<IUnresolvedAttribute> AssemblyAttributes {
- get {
- return assembly.AssemblyAttributes;
- }
- }
-
- public IEnumerable<IUnresolvedAttribute> ModuleAttributes {
- get {
- return assembly.ModuleAttributes;
- }
- }
-
- public IEnumerable<IUnresolvedTypeDefinition> TopLevelTypeDefinitions {
- get {
- return assembly.TopLevelTypeDefinitions;
- }
- }
-
- #endregion
-
- #region IAssemblyReference implementation
-
- public IAssembly Resolve (ITypeResolveContext context)
- {
- return assembly.Resolve (context);
- }
-
- #endregion
-
- }
-
- [Serializable]
- public class ProjectContentWrapper
- {
- readonly Dictionary<Type, object> extensionObjects = new Dictionary<Type, object> ();
- List<ProjectContentWrapper> referencedWrappers = new List<ProjectContentWrapper>();
- List<UnresolvedAssemblyProxy> referencedAssemblies = new List<UnresolvedAssemblyProxy>();
- internal IProjectContent _content;
- internal bool referencesConnected;
-
- /*
- static bool GetReferencesConnected (ProjectContentWrapper pcw, HashSet<ProjectContentWrapper> wrapper)
- {
- if (wrapper.Contains (pcw))
- return true;
- wrapper.Add (pcw);
- return pcw.referencesConnected && pcw.referencedWrappers.All (w => GetReferencesConnected (w, wrapper));
- }*/
-
- public IProjectContent Content {
- get {
- if (!referencesConnected) {
- EnsureReferencesAreLoaded ();
- }
- return _content;
- }
- private set {
- if (value == null)
- throw new InvalidOperationException ("Project content can't be null");
- _content = value;
- }
- }
-
- /// <summary>
- /// Gets the extension objects attached to the content wrapper.
- /// </summary>
- public IEnumerable<object> ExtensionObjects {
- get {
- return extensionObjects.Values;
- }
- }
-
- /// <summary>
- /// Updates an extension object for the wrapper. Note that only one extension object of a certain
- /// type may be stored inside the project content wrapper.
- ///
- /// The extension objects need to be serializable and are stored in the project cache on project unload.
- /// </summary>
- public void UpdateExtensionObject (object ext)
- {
- if (ext == null)
- throw new ArgumentNullException ("ext");
- extensionObjects [ext.GetType ()] = ext;
- }
-
- /// <summary>
- /// Gets a specific extension object. This may lazy load an existing extension object from disk,
- /// if called the first time and a serialized extension object exists.
- /// </summary>
- /// <returns>
- /// The extension object. Or null, if no extension object of the specified type was registered.
- /// </returns>
- /// <typeparam name='T'>
- /// The type of the extension object.
- /// </typeparam>
- public T GetExtensionObject<T> () where T : class
- {
- object result;
- if (extensionObjects.TryGetValue (typeof(T), out result))
- return (T)result;
-
- string cacheDir = GetCacheDirectory (Project);
- if (cacheDir == null)
- return default(T);
-
- try {
- string fileName = Path.Combine (cacheDir, typeof(T).FullName + ".cache");
- if (File.Exists (fileName)) {
- var deserialized = DeserializeObject<T> (fileName);
- extensionObjects [typeof(T)] = deserialized;
- return deserialized;
- }
- } catch (Exception) {
- Console.WriteLine ("Can't deserialize :" + typeof(T).FullName);
- }
-
- return default (T);
- }
-
- List<Action<IProjectContent>> loadActions = new List<Action<IProjectContent>> ();
-
- public void RunWhenLoaded (Action<IProjectContent> act)
- {
- lock (updateContentLock) {
- var lazyProjectLoader = _content as LazyProjectLoader;
- if (loadActions != null) {
- lock (loadActions) {
- if (lazyProjectLoader != null && !lazyProjectLoader.ContextTask.IsCompleted) {
- loadActions.Add (act);
- return;
- }
- }
- }
- }
- act (Content);
- }
-
- void ClearCachedCompilations ()
- {
- // Need to clear this compilation & all compilations that reference this directly or indirectly
- var stack = new Stack<ProjectContentWrapper> ();
- stack.Push (this);
- var cleared = new HashSet<ProjectContentWrapper> ();
- while (stack.Count > 0) {
- var cur = stack.Pop ();
- if (cleared.Contains (cur))
- continue;
- cleared.Add (cur);
- cur.compilation = null;
- foreach (var project in cur.ReferencedProjects) {
- var projectContentWrapper = GetProjectContentWrapper (project);
- if (projectContentWrapper != null)
- stack.Push (projectContentWrapper);
- }
- }
- }
-
- readonly object updateContentLock = new object ();
-
- void RunLoadActions ()
- {
- if (loadActions == null)
- return;
- Action<IProjectContent>[] actions;
- lock (loadActions) {
- actions = loadActions.ToArray ();
- loadActions = null;
- }
- foreach (var action in actions)
- action (Content);
- }
-
- public void UpdateContent (Func<IProjectContent, IProjectContent> updateFunc)
- {
- LazyProjectLoader lazyProjectLoader;
- lock (updateContentLock) {
- lazyProjectLoader = _content as LazyProjectLoader;
- if (lazyProjectLoader != null) {
- lazyProjectLoader.ContextTask.Wait ();
- }
- _content = updateFunc (_content);
- ClearCachedCompilations ();
- WasChanged = true;
- if (lazyProjectLoader != null && !(_content is LazyProjectLoader)) {
- RunLoadActions ();
- }
- }
- }
-
- public void InformFileRemoved (ParsedFileEventArgs e)
- {
- var handler = FileRemoved;
- if (handler != null)
- handler (this, e);
- }
-
- public void InformFileAdded (ParsedFileEventArgs e)
- {
- var handler = FileAdded;
- if (handler != null)
- handler (this, e);
- }
-
- public EventHandler<ParsedFileEventArgs> FileAdded;
- public EventHandler<ParsedFileEventArgs> FileRemoved;
- public bool WasChanged;
- [NonSerialized]
- ICompilation compilation;
-
- public ICompilation Compilation {
- get {
- lock (updateContentLock) {
- if (compilation == null) {
- compilation = Content.CreateCompilation ();
- }
- return compilation;
- }
- }
- }
-
- public Project Project {
- get;
- private set;
- }
-
- [NonSerialized]
- int loadOperationDepth = 0;
- [NonSerialized]
- readonly object loadOperationLocker = new object ();
-
- internal void BeginLoadOperation ()
- {
- lock (loadOperationLocker) {
- loadOperationDepth++;
- if (loadOperationDepth == 1)
- UpdateLoadState ();
- }
- }
-
- internal void EndLoadOperation ()
- {
- lock (loadOperationLocker) {
- if (loadOperationDepth > 0) {
- loadOperationDepth--;
- }
- if (loadOperationDepth == 0)
- UpdateLoadState ();
- }
- }
-
- bool isLoaded;
- public bool IsLoaded {
- get {
- return isLoaded;
- }
- }
-
- [NonSerialized]
- CancellationTokenSource src;
-
- internal void CancelLoad ()
- {
- if (src != null)
- src.Cancel ();
- }
-
- void UpdateLoadState ()
- {
- bool wasLoaded = isLoaded;
- isLoaded = loadOperationDepth == 0 && referencesConnected && !referencedAssemblies.Any (a => a.InLoad);
- if (isLoaded && !wasLoaded)
- OnLoad (EventArgs.Empty);
- }
-
- internal void RequestLoad ()
- {
- BeginLoadOperation ();
- EnsureReferencesAreLoaded ();
- CancelLoad ();
- src = new CancellationTokenSource ();
- var token = src.Token;
- //Task.Factory.StartNew (delegate {
- try {
- foreach (var asm in referencedAssemblies.ToArray ()) {
- if (token.IsCancellationRequested)
- break;
- var ctxLoader = asm.CtxLoader;
- if (ctxLoader != null)
- ctxLoader.EnsureAssemblyLoaded ();
- }
- } finally {
- EndLoadOperation ();
- }
- //});
- }
-
- public event EventHandler Loaded;
-
- protected virtual void OnLoad (EventArgs e)
- {
- var handler = Loaded;
- if (handler != null)
- handler (this, e);
- }
-
- [NonSerialized]
- internal LazyAssemblyLoader OutputAssembly;
-
- internal bool UpdateTrackedOutputAssembly (FilePath fileName)
- {
- if (File.Exists (fileName)) {
- OutputAssembly = new LazyAssemblyLoader (fileName, null);
- // a clean operation could remove the assembly, thefore we need to load it.
- OutputAssembly.EnsureAssemblyLoaded ();
- return true;
- }
- return false;
- }
-
- public ProjectContentWrapper (Project project)
- {
- if (project == null)
- throw new ArgumentNullException ("project");
- this.Project = project;
- var lazyProjectLoader = new LazyProjectLoader (this);
- this.Content = lazyProjectLoader;
- }
-
- public IEnumerable<Project> ReferencedProjects {
- get {
- return Project.GetReferencedItems (ConfigurationSelector.Default).OfType<DotNetProject> ();
- }
- }
-
- class LazyProjectLoader : IProjectContent
- {
- readonly ProjectContentWrapper wrapper;
- readonly Task<IProjectContent> contextTask;
-
- public Task<IProjectContent> ContextTask {
- get {
- return contextTask;
- }
- }
- object contentLock = new object ();
- IProjectContent contentWithReferences;
- public IProjectContent Content {
- get {
- lock (contentLock) {
- if (References != null) {
- return contentWithReferences ?? (contentWithReferences = contextTask.Result.AddAssemblyReferences (References));
- }
- return contextTask.Result;
- }
- }
- }
-
- List<IAssemblyReference> references;
- public List<IAssemblyReference> References {
- get {
- return references;
- }
- set {
- lock (contentLock) {
- references = value;
- }
- }
- }
-
- public LazyProjectLoader (ProjectContentWrapper wrapper)
- {
- this.wrapper = wrapper;
- contextTask = Task.Factory.StartNew (delegate {
- try {
- this.wrapper.BeginLoadOperation ();
- var p = this.wrapper.Project;
- var context = LoadProjectCache (p);
-
- var assemblyName = p.ParentSolution != null ? p.GetOutputFileName (p.ParentSolution.DefaultConfigurationSelector).FileNameWithoutExtension : p.Name;
- if (string.IsNullOrEmpty (assemblyName))
- assemblyName = p.Name;
-
- if (context != null) {
- return context.SetAssemblyName (assemblyName) ?? context;
- }
-
- context = new MonoDevelopProjectContent (p);
- context = context.SetLocation (p.FileName);
- context = context.SetAssemblyName (assemblyName);
-
- QueueParseJob (this.wrapper);
- return context;
- } finally {
- this.wrapper.EndLoadOperation ();
- }
- });
- }
-
- static IProjectContent LoadProjectCache (Project project)
- {
- string cacheDir = GetCacheDirectory (project);
- if (cacheDir == null)
- return null;
-
- var cacheFile = Path.Combine (cacheDir, "completion.cache");
- if (!File.Exists (cacheFile))
- return null;
- try {
- var cache = DeserializeObject<IProjectContent> (cacheFile);
- var monoDevelopProjectContent = cache as MonoDevelopProjectContent;
- if (monoDevelopProjectContent != null)
- monoDevelopProjectContent.Project = project;
- return cache;
- } catch (Exception e) {
- LoggingService.LogWarning ("Error while reading completion cache, regenerating", e);
- Directory.Delete (cacheDir, true);
- return null;
- }
- }
-
- #region IAssemblyReference implementation
-
- IAssembly IAssemblyReference.Resolve (ITypeResolveContext context)
- {
- return Content.Resolve (context);
- }
-
- #endregion
-
- #region IUnresolvedAssembly implementation
-
- string IUnresolvedAssembly.AssemblyName {
- get {
- return Content.AssemblyName;
- }
- }
-
- string IUnresolvedAssembly.FullAssemblyName {
- get {
- return Content.FullAssemblyName;
- }
- }
-
- string IUnresolvedAssembly.Location {
- get {
- return Content.Location;
- }
- }
-
- IEnumerable<IUnresolvedAttribute> IUnresolvedAssembly.AssemblyAttributes {
- get {
- return Content.AssemblyAttributes;
- }
- }
-
- IEnumerable<IUnresolvedAttribute> IUnresolvedAssembly.ModuleAttributes {
- get {
- return Content.ModuleAttributes;
- }
- }
-
- IEnumerable<IUnresolvedTypeDefinition> IUnresolvedAssembly.TopLevelTypeDefinitions {
- get {
- return Content.TopLevelTypeDefinitions;
- }
- }
-
- #endregion
-
- #region IProjectContent implementation
-
- string IProjectContent.ProjectFileName { get { return Content.ProjectFileName; } }
-
- IUnresolvedFile IProjectContent.GetFile (string fileName)
- {
- return Content.GetFile (fileName);
- }
-
- ICompilation IProjectContent.CreateCompilation ()
- {
- return Content.CreateCompilation ();
- }
-
- public ICompilation CreateCompilation (ISolutionSnapshot solutionSnapshot)
- {
- return Content.CreateCompilation (solutionSnapshot);
- }
-
- IProjectContent IProjectContent.SetAssemblyName (string newAssemblyName)
- {
- return Content.SetAssemblyName (newAssemblyName);
- }
-
- IProjectContent IProjectContent.SetLocation (string newLocation)
- {
- return Content.SetLocation (newLocation);
- }
-
- IProjectContent IProjectContent.AddAssemblyReferences (IEnumerable<IAssemblyReference> references)
- {
- return Content.AddAssemblyReferences (references);
- }
-
- IProjectContent IProjectContent.AddAssemblyReferences (params IAssemblyReference[] references)
- {
- return Content.AddAssemblyReferences (references);
- }
-
- IProjectContent IProjectContent.RemoveAssemblyReferences (IEnumerable<IAssemblyReference> references)
- {
- return Content.RemoveAssemblyReferences (references);
- }
-
- IProjectContent IProjectContent.RemoveAssemblyReferences (params IAssemblyReference[] references)
- {
- return Content.RemoveAssemblyReferences (references);
- }
- #pragma warning disable 618
- IProjectContent IProjectContent.UpdateProjectContent (IUnresolvedFile oldFile, IUnresolvedFile newFile)
- {
- return Content.UpdateProjectContent (oldFile, newFile);
- }
-
- public IProjectContent UpdateProjectContent (IEnumerable<IUnresolvedFile> oldFiles, IEnumerable<IUnresolvedFile> newFiles)
- {
- return Content.UpdateProjectContent (oldFiles, newFiles);
- }
- #pragma warning restore 618
-
- public IProjectContent AddOrUpdateFiles (IEnumerable<IUnresolvedFile> newFiles)
- {
- return Content.AddOrUpdateFiles (newFiles);
- }
-
- public IProjectContent AddOrUpdateFiles (params IUnresolvedFile[] newFiles)
- {
- return Content.AddOrUpdateFiles (newFiles);
- }
-
- IEnumerable<IUnresolvedFile> IProjectContent.Files {
- get {
- return Content.Files;
- }
- }
-
- IEnumerable<IAssemblyReference> IProjectContent.AssemblyReferences {
- get {
- return Content.AssemblyReferences;
- }
- }
-
- IProjectContent IProjectContent.SetProjectFileName (string newProjectFileName)
- {
- return Content.SetProjectFileName (newProjectFileName);
- }
-
- IProjectContent IProjectContent.RemoveFiles (IEnumerable<string> fileNames)
- {
- return Content.RemoveFiles (fileNames);
- }
-
- IProjectContent IProjectContent.RemoveFiles (params string[] fileNames)
- {
- return Content.RemoveFiles (fileNames);
- }
-
- #endregion
-
- object compilerSettings;
-
- public IProjectContent SetCompilerSettings (object compilerSettings)
- {
- this.compilerSettings = compilerSettings;
- return this;
- }
-
- public object CompilerSettings {
- get {
- return compilerSettings;
- }
- }
- }
-
- bool HasCyclicRefs (ProjectContentWrapper wrapper, HashSet<Project> nonCyclicCache)
- {
- if (nonCyclicCache.Contains (wrapper.Project))
- return false;
- nonCyclicCache.Add (wrapper.Project);
- foreach (var referencedProject in wrapper.ReferencedProjects) {
- ProjectContentWrapper w;
- if (referencedProject == Project || referencedProject == wrapper.Project || projectContents.TryGetValue (referencedProject, out w) && HasCyclicRefs (w, nonCyclicCache)) {
- return true;
- }
- }
- return false;
- }
-
- List<UnresolvedAssemblyProxy> LoadReferencedAssemblies (DotNetProject netProject)
- {
- var newReferencedAssemblies = new List<UnresolvedAssemblyProxy> ();
- try {
- foreach (string file in netProject.GetReferencedAssemblies (IdeApp.IsInitialized ? IdeApp.Workspace.ActiveConfiguration : ConfigurationSelector.Default, false)) {
- string fileName;
- if (!Path.IsPathRooted (file)) {
- fileName = Path.Combine (Path.GetDirectoryName (netProject.FileName), file);
- }
- else {
- fileName = Path.GetFullPath (file);
- }
- var ctx = LoadAssemblyContext (fileName);
- if (ctx != null) {
- newReferencedAssemblies.Add (ctx);
- ctx.Loaded += HandleReferencedProjectInLoadChange;
- }
- else {
- LoggingService.LogWarning ("TypeSystemService: Can't load assembly context for:" + file);
- }
- }
- }
- catch (Exception e) {
- LoggingService.LogError ("Error while getting assembly references", e);
- }
- return newReferencedAssemblies;
- }
-
- public void EnsureReferencesAreLoaded ()
- {
- lock (projectContentLock) {
- if (referencesConnected)
- return;
- compilation = null;
- referencesConnected = true;
- var netProject = Project as DotNetProject;
- if (netProject == null)
- return;
- try {
- var contexts = new List<IAssemblyReference> ();
- var nonCyclicCache = new HashSet<Project> ();
- foreach (var referencedWrapper in referencedWrappers) {
- referencedWrapper.Loaded -= HandleReferencedProjectInLoadChange;
- }
- var newReferencedWrappers = new List<ProjectContentWrapper> ();
- foreach (var referencedProject in ReferencedProjects) {
- ProjectContentWrapper wrapper;
- if (projectContents.TryGetValue (referencedProject, out wrapper)) {
- if (HasCyclicRefs (wrapper, nonCyclicCache))
- continue;
- wrapper.Loaded += HandleReferencedProjectInLoadChange;
- newReferencedWrappers.Add (wrapper);
- contexts.Add (new UnresolvedAssemblyDecorator (wrapper));
- }
- }
- this.referencedWrappers = newReferencedWrappers;
- UnresolvedAssemblyProxy ctx;
- // Add mscorlib reference
- var config = IdeApp.Workspace != null ? netProject.GetConfiguration (IdeApp.Workspace.ActiveConfiguration) as DotNetProjectConfiguration : null;
- bool noStdLib = false;
- if (config != null) {
- var parameters = config.CompilationParameters as DotNetCompilerParameters;
- if (parameters != null) {
- noStdLib = parameters.NoStdLib;
- }
- }
- if (!noStdLib && netProject.TargetRuntime != null && netProject.TargetRuntime.AssemblyContext != null) {
- var corLibRef = netProject.TargetRuntime.AssemblyContext.GetAssemblyForVersion (typeof(object).Assembly.FullName, null, netProject.TargetFramework);
- if (corLibRef != null) {
- ctx = LoadAssemblyContext (corLibRef.Location);
- if (ctx != null)
- contexts.Add (ctx);
- }
- }
- // Get the assembly references throught the project, since it may have custom references
- foreach (var asm in referencedAssemblies) {
- asm.Loaded += HandleReferencedProjectInLoadChange;
- }
- var newReferencedAssemblies = LoadReferencedAssemblies (netProject);
- contexts.AddRange (newReferencedAssemblies);
- referencedAssemblies = newReferencedAssemblies;
- bool changed = WasChanged;
- var lazyProjectLoader = Content as LazyProjectLoader;
- if (lazyProjectLoader != null) {
- lazyProjectLoader.References = contexts;
- }
- else {
- UpdateContent (c => c.RemoveAssemblyReferences (Content.AssemblyReferences).AddAssemblyReferences (contexts));
- }
- WasChanged = changed;
- } catch (Exception e) {
- if (netProject.TargetRuntime == null) {
- LoggingService.LogError ("Target runtime was null: " + Project.Name);
- } else if (netProject.TargetRuntime.AssemblyContext == null) {
- LoggingService.LogError ("Target runtime assembly context was null: " + Project.Name);
- }
- LoggingService.LogError ("Error while reloading all references of project: " + Project.Name, e);
- } finally {
- UpdateLoadState ();
- }
- }
- }
- static readonly object reconnectLock = new object();
- public void ReconnectAssemblyReferences ()
- {
- var netProject = Project as DotNetProject;
- if (netProject == null)
- return;
- lock (reconnectLock) {
- CancelLoad ();
- this.referencesConnected = false;
- RequestLoad ();
- }
- }
-
- void HandleReferencedProjectInLoadChange (object sender, EventArgs e)
- {
- UpdateLoadState ();
- }
-
- internal void Unload ()
- {
- CancelLoad ();
- foreach (var asm in referencedAssemblies) {
- asm.Loaded -= HandleReferencedProjectInLoadChange;
- }
- foreach (var wrapper in referencedWrappers) {
- wrapper.Loaded -= HandleReferencedProjectInLoadChange;
- }
- loadActions = null;
- foreach (var wrapper in referencedWrappers) {
- wrapper.Loaded -= HandleReferencedProjectInLoadChange;
- }
- referencedWrappers.Clear ();
- referencedAssemblies.Clear ();
- Loaded = null;
- Content = new CSharpProjectContent ();
- }
- }
-
- static readonly object projectContentLock = new object ();
- static readonly Dictionary<Project, ProjectContentWrapper> projectContents = new Dictionary<Project, ProjectContentWrapper> ();
-
- public static ProjectContentWrapper LoadProject (Project project)
+
+ internal static Microsoft.CodeAnalysis.Document GetCodeAnalysisDocument (Microsoft.CodeAnalysis.DocumentId analysisDocument, CancellationToken cancellationToken = default (CancellationToken))
{
- if (IncLoadCount (project) != 1)
- return null;
- lock (projectContentLock) {
- if (projectContents.ContainsKey (project))
- return null;
- try {
- Counters.ParserService.ProjectsLoaded++;
- ProjectContentWrapper wrapper;
- projectContents [project] = wrapper = new ProjectContentWrapper (project);
- var dotNetProject = project as DotNetProject;
- if (dotNetProject != null)
- CheckProjectOutput (dotNetProject, false);
-
- project.FileAddedToProject += OnFileAdded;
- project.FileRemovedFromProject += OnFileRemoved;
- project.FileRenamedInProject += OnFileRenamed;
- project.Modified += OnProjectModified;
-
- if (dotNetProject != null) {
- StartFrameworkLookup (dotNetProject);
- }
- return wrapper;
- } catch (Exception ex) {
- LoggingService.LogError ("Parser database for project '" + project.Name + " could not be loaded", ex);
- }
- return null;
+ foreach (var w in Workspaces) {
+ var doc = w.GetDocument (analysisDocument, cancellationToken);
+ if (doc != null)
+ return doc;
}
- }
-
- public static Project GetProject (IEntity entity)
- {
- if (entity == null)
- throw new ArgumentNullException ("entity");
- return GetProject (entity.ParentAssembly.UnresolvedAssembly.Location);
- }
-
- public static Project GetProject (string location)
- {
- foreach (var wrapper in projectContents)
- if (wrapper.Value.Compilation.MainAssembly.UnresolvedAssembly.Location == location)
- return wrapper.Key;
return null;
}
- #region Project modification handlers
-
- static void OnFileAdded (object sender, ProjectFileEventArgs args)
- {
- var project = (Project)sender;
- foreach (ProjectFileEventInfo fargs in args) {
- QueueParseJob (projectContents [project], new [] { fargs.ProjectFile });
- }
- }
-
- static void OnFileRemoved (object sender, ProjectFileEventArgs args)
- {
- var project = (Project)sender;
- foreach (ProjectFileEventInfo fargs in args) {
- var wrapper = projectContents [project];
- var fileName = fargs.ProjectFile.Name;
- var file = wrapper._content.GetFile (fileName);
- if (file == null)
- continue;
- wrapper.UpdateContent (c => c.RemoveFiles (fileName));
- wrapper.InformFileRemoved (new ParsedFileEventArgs (file));
-
- var tags = wrapper.GetExtensionObject <ProjectCommentTags> ();
- if (tags != null)
- tags.RemoveFile (wrapper.Project, fileName);
- }
- }
-
- static void OnFileRenamed (object sender, ProjectFileRenamedEventArgs args)
- {
- var project = (Project)sender;
- foreach (ProjectFileRenamedEventInfo fargs in args) {
- var content = projectContents [project];
- var file = content._content.GetFile (fargs.OldName);
- if (file == null)
- continue;
- content.UpdateContent (c => c.RemoveFiles (fargs.OldName));
- content.InformFileRemoved (new ParsedFileEventArgs (file));
-
- var tags = content.GetExtensionObject <ProjectCommentTags> ();
- if (tags != null)
- tags.RemoveFile (project, fargs.OldName);
-
- QueueParseJob (content, new [] { fargs.ProjectFile });
- }
- }
-
- static void OnProjectModified (object sender, SolutionItemModifiedEventArgs args)
+ internal static void InformDocumentClose (Microsoft.CodeAnalysis.DocumentId analysisDocument, FilePath fileName)
{
- if (!args.Any (x => x.Hint == "TargetFramework" || x.Hint == "References"))
- return;
- var project = (Project)sender;
-
- ProjectContentWrapper wrapper;
- projectContents.TryGetValue (project, out wrapper);
- if (wrapper == null)
- return;
- wrapper.ReconnectAssemblyReferences ();
- }
-
- #endregion
-
- internal static void Unload (WorkspaceItem item)
- {
- var ws = item as Workspace;
- TrackFileChanges = false;
- loadCancellationSource.Cancel ();
- if (ws != null) {
- foreach (WorkspaceItem it in ws.Items)
- Unload (it);
- ws.ItemAdded -= OnWorkspaceItemAdded;
- ws.ItemRemoved -= OnWorkspaceItemRemoved;
- projectContents.Clear ();
- loadWs = false;
- } else {
- var solution = item as Solution;
- if (solution != null) {
- foreach (var project in solution.GetAllProjects ()) {
- UnloadProject (project);
- }
- solution.SolutionItemAdded -= OnSolutionItemAdded;
- solution.SolutionItemRemoved -= OnSolutionItemRemoved;
- }
- }
+ foreach (var w in Workspaces) {
+ if (w.GetOpenDocumentIds ().Contains (analysisDocument) )
+ w.InformDocumentClose (analysisDocument, fileName);
- cachedAssemblyContents.Clear ();
- lock (parseQueueLock) {
- parseQueueIndex.Clear ();
- parseQueue.Clear ();
}
- TrackFileChanges = true;
}
- internal static void UnloadProject (Project project, bool skipProjectSerialization = false)
+ internal static void InformDocumentOpen (Microsoft.CodeAnalysis.DocumentId analysisDocument, TextEditor editor)
{
- if (DecLoadCount (project) != 0)
- return;
- Counters.ParserService.ProjectsLoaded--;
- project.FileAddedToProject -= OnFileAdded;
- project.FileRemovedFromProject -= OnFileRemoved;
- project.FileRenamedInProject -= OnFileRenamed;
- project.Modified -= OnProjectModified;
-
- ProjectContentWrapper wrapper;
- lock (projectWrapperUpdateLock) {
- if (!projectContents.TryGetValue (project, out wrapper))
+ foreach (var w in Workspaces) {
+ if (w.Contains (analysisDocument.ProjectId)) {
+ w.InformDocumentOpen (analysisDocument, editor);
return;
- projectContents.Remove (project);
- }
- if (!skipProjectSerialization)
- StoreProjectCache (project, wrapper);
- OnProjectUnloaded (new ProjectUnloadEventArgs (project, wrapper));
- wrapper.Unload ();
- }
-
- public static event EventHandler<ProjectUnloadEventArgs> ProjectUnloaded;
-
- static void OnProjectUnloaded (ProjectUnloadEventArgs e)
- {
- var handler = ProjectUnloaded;
- if (handler != null)
- handler (null, e);
- }
-
- static void OnWorkspaceItemAdded (object s, WorkspaceItemEventArgs args)
- {
- Load (args.Item);
- }
-
- static void OnWorkspaceItemRemoved (object s, WorkspaceItemEventArgs args)
- {
- Unload (args.Item);
- }
-
- static void OnSolutionItemAdded (object sender, SolutionItemChangeEventArgs args)
- {
- var project = args.SolutionItem as Project;
- if (project != null) {
- var wrapper = LoadProject (project);
- if (wrapper != null) {
- var files = wrapper.Project.Files.ToArray ();
- Task.Run (delegate {
- CheckModifiedFiles (wrapper.Project, files, wrapper);
- wrapper.RequestLoad ();
- });
}
}
- }
-
- static void OnSolutionItemRemoved (object sender, SolutionItemChangeEventArgs args)
- {
- var project = args.SolutionItem as Project;
- if (project != null)
- UnloadProject (project);
- }
-
- #endregion
-
- #region Reference Counting
-
- static readonly Dictionary<Project,int> loadCount = new Dictionary<Project,int> ();
- static readonly object rwLock = new object ();
-
- static int DecLoadCount (Project ob)
- {
- lock (rwLock) {
- int c;
- if (loadCount.TryGetValue (ob, out c)) {
- c--;
- if (c == 0)
- loadCount.Remove (ob);
- else
- loadCount [ob] = c;
- return c;
- }
- LoggingService.LogError ("DecLoadCount: Object not registered.");
- return 0;
- }
- }
-
- static int IncLoadCount (Project ob)
- {
- lock (rwLock) {
- int c;
- if (loadCount.TryGetValue (ob, out c)) {
- c++;
- loadCount [ob] = c;
- return c;
- }
- loadCount [ob] = 1;
- return 1;
- }
- }
-
- #endregion
-
- static bool GetXml (string baseName, TargetRuntime runtime, out FilePath xmlFileName)
- {
- try {
- xmlFileName = LookupLocalizedXmlDoc (baseName);
- if (!xmlFileName.IsNull)
- return true;
- } catch (Exception e) {
- LoggingService.LogError ("Error while looking up XML docs.", e);
- }
-
- if (MonoDevelop.Core.Platform.IsWindows) {
- string windowsFileName = FindWindowsXmlDocumentation (baseName, runtime);
- if (File.Exists (windowsFileName)) {
- xmlFileName = windowsFileName;
- return true;
- }
- }
-
- xmlFileName = "";
- return false;
- }
-
- #region Lookup XML documentation
-
- // ProgramFilesX86 is broken on 32-bit WinXP, this is a workaround
- static string GetProgramFilesX86 ()
- {
- return Environment.GetFolderPath (IntPtr.Size == 8 ?
- Environment.SpecialFolder.ProgramFilesX86 : Environment.SpecialFolder.ProgramFiles);
- }
-
- static readonly string referenceAssembliesPath = Path.Combine (GetProgramFilesX86 (), @"Reference Assemblies\Microsoft\\Framework");
- static readonly string frameworkPath = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.Windows), @"Microsoft.NET\Framework");
-
- static string FindWindowsXmlDocumentation (string assemblyFileName, TargetRuntime runtime)
- {
- string fileName;
- ClrVersion version = runtime != null && runtime.CustomFrameworks.Any () ? runtime.CustomFrameworks.First ().ClrVersion : ClrVersion.Default;
- switch (version) {
-// case "1.0":
-// fileName = LookupLocalizedXmlDoc (Path.Combine (frameworkPath, "v1.0.3705", assemblyFileName));
-// break;
- case ClrVersion.Net_1_1:
- fileName = LookupLocalizedXmlDoc (Path.Combine (frameworkPath, "v1.1.4322", assemblyFileName));
- break;
- case ClrVersion.Net_2_0:
- case ClrVersion.Clr_2_1:
- fileName = LookupLocalizedXmlDoc (Path.Combine (frameworkPath, "v2.0.50727", assemblyFileName))
- ?? LookupLocalizedXmlDoc (Path.Combine (referenceAssembliesPath, "v3.5"))
- ?? LookupLocalizedXmlDoc (Path.Combine (referenceAssembliesPath, "v3.0"))
- ?? LookupLocalizedXmlDoc (Path.Combine (referenceAssembliesPath, @".NETFramework\v3.5\Profile\Client"));
- break;
- default:
- fileName = LookupLocalizedXmlDoc (Path.Combine (referenceAssembliesPath, @".NETFramework\v4.0", assemblyFileName))
- ?? LookupLocalizedXmlDoc (Path.Combine (frameworkPath, "v4.0.30319", assemblyFileName));
- break;
- }
- return fileName;
- }
-
- static string LookupLocalizedXmlDoc (string fileName)
- {
- return XmlDocumentationProvider.LookupLocalizedXmlDoc (fileName);
- }
-
- #endregion
-
- class UnresolvedAssemblyProxy : IUnresolvedAssembly
- {
- public readonly string FileName;
- internal LazyAssemblyLoader CtxLoader;
-
- public IUnresolvedAssembly Ctx {
- get {
- return CtxLoader;
- }
- }
-
- public bool InLoad {
- get {
- return CtxLoader == null || CtxLoader.InLoad;
- }
- }
-
- public event EventHandler Loaded {
- add {
- var ctxLoader = CtxLoader;
- if (ctxLoader != null)
- ctxLoader.Loaded += value;
- }
- remove {
- var ctxLoader = CtxLoader;
- if (ctxLoader != null)
- ctxLoader.Loaded -= value;
- }
- }
-
- public UnresolvedAssemblyProxy (string fileName)
- {
- if (fileName == null)
- throw new ArgumentNullException ("fileName");
- this.FileName = fileName;
- }
-
- #region IUnresolvedAssembly implementation
-
- string IUnresolvedAssembly.AssemblyName {
- get {
- return Ctx.AssemblyName;
- }
- }
-
- string IUnresolvedAssembly.FullAssemblyName {
- get {
- return Ctx.FullAssemblyName;
- }
- }
-
- string IUnresolvedAssembly.Location {
- get {
- return Ctx.Location;
- }
- }
-
- IEnumerable<IUnresolvedAttribute> IUnresolvedAssembly.AssemblyAttributes {
- get {
- return Ctx.AssemblyAttributes;
- }
- }
-
- IEnumerable<IUnresolvedAttribute> IUnresolvedAssembly.ModuleAttributes {
- get {
- return Ctx.ModuleAttributes;
- }
- }
-
- IEnumerable<IUnresolvedTypeDefinition> IUnresolvedAssembly.TopLevelTypeDefinitions {
- get {
- return Ctx.TopLevelTypeDefinitions;
- }
- }
-
- #endregion
-
- #region IAssemblyReference implementation
-
- IAssembly IAssemblyReference.Resolve (ITypeResolveContext context)
- {
- var ctx = Ctx;
- if (ctx == null)
- return null;
- return ctx.Resolve (context);
- }
-
- #endregion
-
- public override string ToString ()
- {
- return string.Format ("[UnresolvedAssemblyProxy: FileName={0}]", FileName);
- }
- }
-
- internal class LazyAssemblyLoader : IUnresolvedAssembly
- {
- class LazyAssembly : IAssembly
- {
- readonly LazyAssemblyLoader loader;
- readonly ITypeResolveContext context;
- IAssembly assembly;
-
- IAssembly Assembly {
- get {
- lock (loader) {
- if (assembly == null) {
- loader.EnsureAssemblyLoaded ();
- assembly = loader.assembly.Resolve (context);
- }
- return assembly;
- }
- }
- }
-
-
- public LazyAssembly (LazyAssemblyLoader loader, ITypeResolveContext context)
- {
- this.loader = loader;
- this.context = context;
- }
-
- #region IAssembly implementation
-
- bool IAssembly.InternalsVisibleTo (IAssembly assembly)
- {
- return Assembly.InternalsVisibleTo (assembly);
- }
-
- ITypeDefinition IAssembly.GetTypeDefinition (TopLevelTypeName typeName)
- {
- return Assembly.GetTypeDefinition (typeName);
- }
-
- IUnresolvedAssembly IAssembly.UnresolvedAssembly {
- get {
- return Assembly.UnresolvedAssembly;
- }
- }
-
- bool IAssembly.IsMainAssembly {
- get {
- return Assembly.IsMainAssembly;
- }
- }
-
- string IAssembly.AssemblyName {
- get {
- return Assembly.AssemblyName;
- }
- }
-
- string IAssembly.FullAssemblyName {
- get {
- return Assembly.FullAssemblyName;
- }
- }
-
- IList<IAttribute> IAssembly.AssemblyAttributes {
- get {
- return Assembly.AssemblyAttributes;
- }
- }
-
- IList<IAttribute> IAssembly.ModuleAttributes {
- get {
- return Assembly.ModuleAttributes;
- }
- }
-
- INamespace IAssembly.RootNamespace {
- get {
- return Assembly.RootNamespace;
- }
- }
-
- IEnumerable<ITypeDefinition> IAssembly.TopLevelTypeDefinitions {
- get {
- return Assembly.TopLevelTypeDefinitions;
- }
- }
-
- #endregion
-
- #region ICompilationProvider implementation
-
- ICompilation ICompilationProvider.Compilation {
- get {
- return Assembly.Compilation;
- }
- }
-
- #endregion
-
- }
-
- #region IAssemblyReference implementation
-
- IAssembly IAssemblyReference.Resolve (ITypeResolveContext context)
- {
- if (assembly != null)
- return assembly.Resolve (context);
- return new LazyAssembly (this, context);
- }
-
- #endregion
-
- #region IUnresolvedAssembly implementation
-
- readonly object assemblyLock = new object ();
-
- string IUnresolvedAssembly.AssemblyName {
- get {
- lock (assemblyLock) {
- EnsureAssemblyLoaded ();
- return assembly.AssemblyName;
- }
- }
- }
-
- string IUnresolvedAssembly.FullAssemblyName {
- get {
- lock (assemblyLock) {
- EnsureAssemblyLoaded ();
- return assembly.FullAssemblyName;
- }
- }
- }
-
- string IUnresolvedAssembly.Location {
- get {
- lock (assemblyLock) {
- EnsureAssemblyLoaded ();
- return assembly.Location;
- }
- }
- }
-
- IEnumerable<IUnresolvedAttribute> IUnresolvedAssembly.AssemblyAttributes {
- get {
- lock (assemblyLock) {
- EnsureAssemblyLoaded ();
- return assembly.AssemblyAttributes;
- }
- }
- }
-
- IEnumerable<IUnresolvedAttribute> IUnresolvedAssembly.ModuleAttributes {
- get {
- lock (assemblyLock) {
- EnsureAssemblyLoaded ();
- return assembly.ModuleAttributes;
- }
- }
- }
-
- IEnumerable<IUnresolvedTypeDefinition> IUnresolvedAssembly.TopLevelTypeDefinitions {
- get {
- lock (assemblyLock) {
- EnsureAssemblyLoaded ();
- return assembly.TopLevelTypeDefinitions;
- }
- }
- }
-
- #endregion
-
- readonly string fileName;
- readonly string cache;
- IUnresolvedAssembly assembly;
-
- readonly object asmLocker = new object ();
- internal void EnsureAssemblyLoaded ()
- {
- lock (asmLocker) {
- if (assembly != null)
- return;
- var loadedAssembly = LoadAssembly ();
- if (loadedAssembly == null) {
- LoggingService.LogWarning ("Assembly " + fileName + " could not be loaded cleanly.");
- assembly = new DefaultUnresolvedAssembly (fileName);
- } else {
- assembly = loadedAssembly;
- }
-
- OnLoad (EventArgs.Empty);
- }
- }
-
- public override string ToString ()
- {
- return string.Format ("[LazyAssemblyLoader: fileName={0}, assembly={1}]", fileName, assembly);
- }
-
- public bool InLoad {
- get {
- return assembly == null;
- }
- }
-
- public event EventHandler Loaded;
-
- protected virtual void OnLoad (EventArgs e)
- {
- var handler = Loaded;
- if (handler != null)
- handler (this, e);
- }
-
- public LazyAssemblyLoader (string fileName, string cache)
- {
- this.fileName = fileName;
- this.cache = cache;
- }
-
-
- IUnresolvedAssembly LoadAssembly ()
- {
- var assemblyPath = cache != null ? Path.Combine (cache, "assembly.data") : null;
- var assemblyTag = cache != null ? Path.Combine (cache, "assembly.tag") : null;
- try {
- if (assemblyPath != null && assemblyTag != null && File.Exists (assemblyPath) && File.Exists (assemblyTag)) {
- var deserializedAssembly = DeserializeObject <IUnresolvedAssembly> (assemblyPath);
- if (deserializedAssembly != null) {
- return deserializedAssembly;
- }
- }
- } catch (Exception) {
- }
- IUnresolvedAssembly result;
- try {
- var loader = new IkvmLoader ();
- loader.IncludeInternalMembers = true;
- loader.DocumentationProvider = new CombinedDocumentationProvider (fileName);
- result = loader.LoadAssemblyFile (fileName);
- } catch (Exception e) {
- LoggingService.LogError ("Can't convert assembly: " + fileName, e);
- return null;
- }
-
- if (cache != null) {
- var writeTime = File.GetLastWriteTimeUtc (fileName);
- SerializeObject (assemblyPath, result);
- SerializeObject (assemblyTag, new AssemblyTag (writeTime));
- }
- return result;
- }
- }
-
- [Serializable]
- class CombinedDocumentationProvider : IDocumentationProvider
- {
- readonly string fileName;
- [NonSerialized]
- IDocumentationProvider baseProvider;
-
- public IDocumentationProvider BaseProvider {
- get {
- if (baseProvider == null) {
- FilePath xmlDocFile;
- if (GetXml (fileName, null, out xmlDocFile)) {
- try {
- baseProvider = new XmlDocumentationProvider (xmlDocFile);
- } catch (Exception ex) {
- LoggingService.LogWarning ("Ignoring error while reading xml doc from " + xmlDocFile, ex);
- }
- }
- if (baseProvider == null)
- baseProvider = new MonoDocDocumentationProvider ();
- }
- return baseProvider;
- }
- }
-
- public CombinedDocumentationProvider (string fileName)
- {
- this.fileName = fileName;
- }
-
- #region IDocumentationProvider implementation
-
- public DocumentationComment GetDocumentation (IEntity entity)
- {
- var provider = BaseProvider;
- return provider != null ? provider.GetDocumentation (entity) : null;
- }
-
- #endregion
-
- }
-
- static readonly object assemblyContextLock = new object ();
-
- static UnresolvedAssemblyProxy LoadAssemblyContext (FilePath fileName)
- {
- CanonicalizePath (ref fileName);
-
- UnresolvedAssemblyProxy loadedContext;
- if (cachedAssemblyContents.TryGetValue (fileName, out loadedContext)) {
- return loadedContext;
- }
- if (!File.Exists (fileName))
- return null;
- lock (assemblyContextLock) {
- if (cachedAssemblyContents.TryGetValue (fileName, out loadedContext)) {
- CheckModifiedFile (loadedContext);
- return loadedContext;
- }
-
- string cache = GetCacheDirectory (fileName, true);
-
- try {
- var result = new UnresolvedAssemblyProxy (fileName);
- result.CtxLoader = new LazyAssemblyLoader (fileName, cache);
- CheckModifiedFile (result);
- var newcachedAssemblyContents = new Dictionary<string, UnresolvedAssemblyProxy> (cachedAssemblyContents);
- newcachedAssemblyContents [fileName] = result;
- cachedAssemblyContents = newcachedAssemblyContents;
- OnAssemblyLoaded (new AssemblyLoadedEventArgs (result.CtxLoader));
- return result;
- } catch (Exception ex) {
- LoggingService.LogError ("Error loading assembly " + fileName, ex);
- return null;
- }
+ if (!gotDocumentRequestError) {
+ gotDocumentRequestError = true;
+ LoggingService.LogWarning ("Can't open requested document : " + analysisDocument + ":" + editor.FileName);
}
}
- internal static event EventHandler<AssemblyLoadedEventArgs> AssemblyLoaded;
-
- static void OnAssemblyLoaded (AssemblyLoadedEventArgs e)
- {
- var handler = AssemblyLoaded;
- if (handler != null)
- handler (null, e);
- }
-
- public static IUnresolvedAssembly LoadAssemblyContext (TargetRuntime runtime, TargetFramework fx, string fileName)
+ internal static void InformDocumentOpen (Microsoft.CodeAnalysis.Workspace ws, Microsoft.CodeAnalysis.DocumentId analysisDocument, TextEditor editor)
{
- if (File.Exists (fileName))
- return LoadAssemblyContext (fileName);
- var corLibRef = runtime.AssemblyContext.GetAssemblyForVersion (fileName, null, fx);
- return corLibRef == null ? null : LoadAssemblyContext (corLibRef.Location);
+ ((MonoDevelopWorkspace)ws).InformDocumentOpen (analysisDocument, editor);
}
- public static IProjectContent GetProjectContext (Project project)
- {
- if (project == null)
- throw new ArgumentNullException ("project");
- var content = GetProjectContentWrapper (project);
- if (content == null)
- return null;
- return content.Content;
- }
+ static bool gotDocumentRequestError = false;
- public static ICompilation GetCompilation (Project project)
+ public static Microsoft.CodeAnalysis.ProjectId GetProjectId (MonoDevelop.Projects.Project project)
{
if (project == null)
throw new ArgumentNullException ("project");
- var content = GetProjectContentWrapper (project);
- if (content == null)
- return null;
- return content.Compilation;
- }
-
- public static ICompilation GetCompilation (SystemAssembly assembly, ICompilation compilation)
- {
- var ctx = LoadAssemblyContext (assembly.Location);
- var list = compilation.ReferencedAssemblies.Select (r => r.UnresolvedAssembly).ToList ();
- list.Add (compilation.MainAssembly.UnresolvedAssembly);
- var result = new SimpleCompilation (ctx, list);
- return result;
- }
-
- static IEnumerable<SystemAssembly> GetFrameworkAssemblies (DotNetProject netProject)
- {
- var assemblies = new Dictionary<string, SystemAssembly> ();
- foreach (var assembly in netProject.AssemblyContext.GetAssemblies ()) {
- SystemAssembly existing;
- if (assemblies.TryGetValue (assembly.Name, out existing)) {
- Version v1, v2;
- if (!Version.TryParse (existing.Version, out v1))
- continue;
- if (!Version.TryParse (assembly.Version, out v2))
- continue;
- if (v1 > v2)
- continue;
+ foreach (var w in Workspaces) {
+ var projectId = w.GetProjectId (project);
+ if (projectId != null) {
+ return projectId;
}
- assemblies [assembly.Name] = assembly;
- }
- return assemblies.Values;
- }
-
- class FrameworkTask
- {
- public int RetryCount { get; set; }
-
- public Task<FrameworkLookup> Task { get; set; }
- }
-
- readonly static Dictionary<string, FrameworkTask> frameworkLookup = new Dictionary<string, FrameworkTask> ();
-
- static void StartFrameworkLookup (DotNetProject netProject)
- {
- if (netProject == null)
- throw new ArgumentNullException ("netProject");
- lock (frameworkLookup) {
- FrameworkTask result;
- if (netProject.TargetFramework == null)
- return;
- var frameworkName = netProject.TargetFramework.Name;
- if (!frameworkLookup.TryGetValue (frameworkName, out result))
- frameworkLookup [frameworkName] = result = new FrameworkTask ();
- if (result.Task != null)
- return;
- result.Task = Task.Factory.StartNew (delegate {
- return GetFrameworkLookup (netProject);
- });
- }
- }
-
- public static bool TryGetFrameworkLookup (DotNetProject project, out FrameworkLookup lookup)
- {
- lock (frameworkLookup) {
- FrameworkTask result;
- if (frameworkLookup.TryGetValue (project.TargetFramework.Name, out result)) {
- if (!result.Task.IsCompleted) {
- lookup = null;
- return false;
- }
- lookup = result.Task.Result;
- return true;
- }
- }
- lookup = null;
- return false;
- }
-
- public static bool RecreateFrameworkLookup (DotNetProject netProject)
- {
- lock (frameworkLookup) {
- FrameworkTask result;
- var frameworkName = netProject.TargetFramework.Name;
- if (!frameworkLookup.TryGetValue (frameworkName, out result))
- return false;
- if (result.RetryCount > 5) {
- LoggingService.LogError ("Can't create framework lookup for:" + frameworkName);
- return false;
- }
- result.RetryCount++;
- LoggingService.LogInfo ("Trying to recreate framework lookup for {0}, try {1}.", frameworkName, result.RetryCount);
- result.Task = null;
- StartFrameworkLookup (netProject);
- return true;
}
+ return null;
}
- static FrameworkLookup GetFrameworkLookup (DotNetProject netProject)
+ public static Microsoft.CodeAnalysis.Document GetCodeAnysisDocument (Microsoft.CodeAnalysis.DocumentId docId, CancellationToken cancellationToken = default (CancellationToken))
{
- FrameworkLookup result;
- string fileName;
- var cache = GetCacheDirectory (netProject.TargetFramework);
- fileName = Path.Combine (cache, "FrameworkLookup_" + FrameworkLookup.CurrentVersion + ".dat");
- try {
- if (File.Exists (fileName)) {
- result = FrameworkLookup.Load (fileName);
- if (result != null) {
- return result;
- }
+ if (docId == null)
+ throw new ArgumentNullException ("docId");
+ foreach (var w in Workspaces) {
+ var documentId = w.GetDocument (docId, cancellationToken);
+ if (documentId != null) {
+ return documentId;
}
- } catch (Exception e) {
- LoggingService.LogWarning ("Can't read framework cache - recreating...", e);
- }
-
- try {
- using (var creator = FrameworkLookup.Create (fileName)) {
- foreach (var assembly in GetFrameworkAssemblies (netProject)) {
- var ctx = LoadAssemblyContext (assembly.Location);
- foreach (var type in ctx.Ctx.GetAllTypeDefinitions ()) {
- if (!type.IsPublic)
- continue;
- creator.AddLookup (assembly.Package.Name, assembly.FullName, type);
- }
- }
- }
- } catch (Exception e) {
- LoggingService.LogError ("Error while storing framework lookup", e);
- return FrameworkLookup.Empty;
- }
-
- try {
- result = FrameworkLookup.Load (fileName);
- return result;
- } catch (Exception e) {
- LoggingService.LogError ("Error loading framework lookup", e);
- return FrameworkLookup.Empty;
}
+ return null;
}
- public static ProjectContentWrapper GetProjectContentWrapper (Project project)
+ public static MonoDevelop.Projects.Project GetMonoProject (Microsoft.CodeAnalysis.Project project)
{
if (project == null)
throw new ArgumentNullException ("project");
- ProjectContentWrapper content;
- if (projectContents.TryGetValue (project, out content))
- return content;
- // in case of outdated projects try to get the most recent project wrapper.
- foreach (var cnt in projectContents) {
- if (cnt.Key.FileName == project.FileName)
- return cnt.Value;
- }
- return null;
- }
-
- public static IProjectContent GetContext (FilePath file, string mimeType, string text)
- {
- using (var reader = new StringReader (text)) {
- var parsedDocument = ParseFile (file, mimeType, reader);
-
- var content = new CSharpProjectContent ();
- return content.AddOrUpdateFiles (parsedDocument.ParsedFile);
- }
- }
-
- static Dictionary<string, UnresolvedAssemblyProxy> cachedAssemblyContents = new Dictionary<string, UnresolvedAssemblyProxy> ();
-
- /// <summary>
- /// Force the update of a project context. Note: This method blocks the thread.
- /// It was just implemented for use inside unit tests.
- /// </summary>
- public static void ForceUpdate (ProjectContentWrapper context)
- {
- CheckModifiedFiles ();
- while (!context.IsLoaded) {
- Thread.Sleep (10);
- }
- }
-
- #region Parser queue
-
- static bool threadRunning;
-
- public static IProgressMonitorFactory ParseProgressMonitorFactory {
- get;
- set;
- }
-
- class InternalProgressMonitor
- : ProgressMonitor
- {
- public InternalProgressMonitor ()
- {
- StartParseOperation ();
- }
-
- public override void Dispose ()
- {
- EndParseOperation ();
- }
- }
-
- internal static ProgressMonitor GetParseProgressMonitor ()
- {
- var mon = ParseProgressMonitorFactory != null ? ParseProgressMonitorFactory.CreateProgressMonitor () : new ProgressMonitor ();
-
- return new AggregatedProgressMonitor (mon, new InternalProgressMonitor ());
- }
-
- static readonly Queue<ParsingJob> parseQueue = new Queue<ParsingJob> ();
-
- class ParsingJob
- {
- public ProjectContentWrapper Context;
- public IEnumerable<ProjectFile> FileList;
- // public Action<string, IProgressMonitor> ParseCallback;
- public void Run (ProgressMonitor monitor, CancellationToken token)
- {
- TypeSystemParserNode node = null;
- TypeSystemParser parser = null;
- var tags = Context.GetExtensionObject <ProjectCommentTags> ();
- try {
- Context.BeginLoadOperation ();
- var parsedFiles = new List<Tuple<ParsedDocument, IUnresolvedFile>> ();
- foreach (var file in (FileList ?? Context.Project.Files)) {
- if (token.IsCancellationRequested)
- return;
- var fileName = file.FilePath;
- if (filesSkippedInParseThread.Any (f => f == fileName)) {
- continue;
- }
- if (node == null || !node.CanParse (fileName, file.BuildAction)) {
- var newNode = GetTypeSystemParserNode (DesktopService.GetMimeTypeForUri (fileName), file.BuildAction);
- var newParser = newNode != null ? newNode.Parser : null;
- if (newParser == null)
- continue;
- node = newNode;
- parser = newParser;
- }
-
- if (parser == null || !File.Exists (fileName))
- continue;
- ParsedDocument parsedDocument;
- try {
- parsedDocument = parser.Parse (false, fileName, Context.Project);
- } catch (Exception e) {
- LoggingService.LogError ("Error while parsing " + fileName, e);
- continue;
- }
- if (token.IsCancellationRequested)
- return;
- if (tags != null)
- tags.UpdateTags (Context.Project, parsedDocument.FileName, parsedDocument.TagComments);
- if (token.IsCancellationRequested)
- return;
- parsedFiles.Add (Tuple.Create (parsedDocument, Context._content.GetFile (fileName)));
- }
- Context.UpdateContent (c => c.AddOrUpdateFiles (parsedFiles.Where (f => (f.Item1.Flags & ParsedDocumentFlags.NonSerializable) != ParsedDocumentFlags.NonSerializable).Select (p => p.Item1.ParsedFile)));
- foreach (var file in parsedFiles) {
- if (token.IsCancellationRequested)
- return;
- if (file.Item2 != null)
- Context.InformFileRemoved (new ParsedFileEventArgs (file.Item2));
- var parsedDocument = file.Item1;
- if ((parsedDocument.Flags & ParsedDocumentFlags.NonSerializable) != ParsedDocumentFlags.NonSerializable)
- Context.InformFileAdded (new ParsedFileEventArgs (parsedDocument.ParsedFile));
- }
- } finally {
- Context.EndLoadOperation ();
+ foreach (var w in Workspaces) {
+ var documentId = w.GetMonoProject (project);
+ if (documentId != null) {
+ return documentId;
}
}
+ return null;
}
- static void UpdateProjectCommentTasks (ProjectContentWrapper context, ParsedDocument parsedDocument)
- {
- var tags = context.GetExtensionObject <ProjectCommentTags> ();
- if (tags != null) // When tags are not there they're updated first time the tasks are requested.
- tags.UpdateTags (context.Project, parsedDocument.FileName, parsedDocument.TagComments);
- }
- // public static event EventHandler<ProjectFileEventArgs> FileParsed;
- static readonly object parseQueueLock = new object ();
- static readonly AutoResetEvent parseEvent = new AutoResetEvent (false);
- static readonly ManualResetEvent queueEmptied = new ManualResetEvent (true);
- static bool trackingFileChanges;
-
- public static bool TrackFileChanges {
- get {
- return trackingFileChanges;
- }
- set {
- lock (parseQueueLock) {
- if (value != trackingFileChanges) {
- trackingFileChanges = value;
- if (value)
- StartParserThread ();
- }
- }
- }
- }
-
- static int parseStatus;
-
- public static bool IsParsing {
- get { return parseStatus > 0; }
- }
-
- static readonly Dictionary<ProjectContentWrapper, ParsingJob> parseQueueIndex = new Dictionary<ProjectContentWrapper, ParsingJob> ();
-
- internal static int PendingJobCount {
- get {
- lock (parseQueueLock) {
- return parseQueueIndex.Count;
- }
- }
- }
-
- static void QueueParseJob (ProjectContentWrapper context, IEnumerable<ProjectFile> fileList = null)
- {
- var job = new ParsingJob {
- Context = context,
- FileList = fileList
- };
- lock (parseQueueLock) {
- RemoveParseJob (context);
- context.BeginLoadOperation ();
- parseQueueIndex [context] = job;
- parseQueue.Enqueue (job);
- parseEvent.Set ();
-
- if (parseQueueIndex.Count == 1)
- queueEmptied.Reset ();
- }
- }
-
- static bool WaitForParseJob (int timeout = 5000)
- {
- return parseEvent.WaitOne (timeout, true);
- }
-
- static ParsingJob DequeueParseJob ()
- {
- lock (parseQueueLock) {
- if (parseQueue.Count > 0) {
- var job = parseQueue.Dequeue ();
- parseQueueIndex.Remove (job.Context);
- return job;
- }
- return null;
- }
- }
-
- internal static void WaitForParseQueue ()
- {
- queueEmptied.WaitOne ();
- }
-
- static void RemoveParseJob (ProjectContentWrapper project)
- {
- lock (parseQueueLock) {
- ParsingJob job;
- if (parseQueueIndex.TryGetValue (project, out job)) {
- parseQueueIndex.Remove (project);
- project.EndLoadOperation ();
- }
- }
- }
-
- static void StartParserThread ()
- {
- lock (parseQueueLock) {
- if (!threadRunning) {
- threadRunning = true;
- var t = new Thread (new ThreadStart (ParserUpdateThread));
- t.Name = "Background parser";
- t.IsBackground = true;
- t.Priority = ThreadPriority.AboveNormal;
- t.Start ();
- }
- }
- }
-
- static void ParserUpdateThread ()
- {
- try {
- while (trackingFileChanges) {
- WaitForParseJob ();
-// CheckModifiedFiles ();
- if (trackingFileChanges)
- ConsumeParsingQueue ();
- }
- } catch (Exception ex) {
- LoggingService.LogError ("Unhandled error in parsing thread", ex);
- }
- lock (parseQueueLock) {
- threadRunning = false;
- if (trackingFileChanges)
- StartParserThread ();
- }
- }
-
- static bool IsFileModified (ProjectFile file, IUnresolvedFile parsedFile)
- {
- if (parsedFile == null || !parsedFile.LastWriteTime.HasValue)
- return true;
- try {
- return File.GetLastWriteTimeUtc (file.FilePath) != parsedFile.LastWriteTime;
- } catch (Exception) {
- return true;
- }
- }
-
- static void CheckModifiedFiles (Project project, ProjectFile[] projectFiles, ProjectContentWrapper content, CancellationToken token = default (CancellationToken))
- {
- if (token.IsCancellationRequested) {
- return;
- }
-// Console.WriteLine ("add modified file check for :" + project.Name);
- content.RunWhenLoaded (delegate(IProjectContent cnt) {
- try {
-// Console.WriteLine ("check for " + project.Name);
- content.BeginLoadOperation ();
- var modifiedFiles = new List<ProjectFile> ();
- var oldFileNewFile = new List<Tuple<ProjectFile, IUnresolvedFile>> ();
- foreach (var file in projectFiles) {
- if (token.IsCancellationRequested) {
- return;
- }
- if (file.BuildAction == null)
- continue;
- // if the file is already inside the content a parser exists for it, if not check if it can be parsed.
- var oldFile = cnt.GetFile (file.Name);
- oldFileNewFile.Add (Tuple.Create (file, oldFile));
- }
-
- // This is disk intensive and slow
- oldFileNewFile.RemoveAll (t => !IsFileModified (t.Item1, t.Item2));
-
- foreach (var v in oldFileNewFile) {
- var file = v.Item1;
- var oldFile = v.Item2;
- if (oldFile == null) {
- var parser = TypeSystemService.GetParser (DesktopService.GetMimeTypeForUri (file.Name), file.BuildAction);
- if (parser == null)
- continue;
- }
- modifiedFiles.Add (file);
- }
- var tags = content.GetExtensionObject <ProjectCommentTags> ();
-
- // check if file needs to be removed from project content
- foreach (var file in cnt.Files) {
- if (token.IsCancellationRequested) {
- return;
- }
- if (project.GetProjectFile (file.FileName) == null) {
- content.UpdateContent (c => c.RemoveFiles (file.FileName));
- content.InformFileRemoved (new ParsedFileEventArgs (file));
- if (tags != null)
- tags.RemoveFile (project, file.FileName);
- }
- }
- if (token.IsCancellationRequested) {
- return;
- }
- if (modifiedFiles.Count > 0) {
- QueueParseJob (content, modifiedFiles);
- WaitForParseJob ();
- }
- } catch (Exception e) {
- LoggingService.LogError ("Exception in check modified files.", e);
- } finally {
- content.EndLoadOperation ();
- }
- });
- }
-
- /// <summary>
- /// Used to store meta data information about the assembly.
- /// </summary>
- [Serializable]
- class AssemblyTag
- {
- public DateTime LastWriteTimeUTC { get; set; }
-
- public AssemblyTag (DateTime lastWriteTimeUTC)
- {
- this.LastWriteTimeUTC = lastWriteTimeUTC;
- }
- }
-
- static void CheckModifiedFile (UnresolvedAssemblyProxy context)
- {
- try {
- string cache = GetCacheDirectory (context.FileName);
- if (cache == null)
- return;
- var assemblyDataDirectory = Path.Combine (cache, "assembly.tag");
- var writeTime = File.GetLastWriteTimeUtc (context.FileName);
- var cacheTime = File.Exists (assemblyDataDirectory) ? DeserializeObject<AssemblyTag> (assemblyDataDirectory) : new AssemblyTag (writeTime);
- if (writeTime != cacheTime.LastWriteTimeUTC) {
- cache = GetCacheDirectory (context.FileName);
- if (cache != null) {
- try {
- // Files will be reloaded by the lazy loader
- File.Delete (assemblyDataDirectory);
- File.Delete (Path.Combine (cache, "assembly.data"));
- } catch {
- }
- context.CtxLoader = new LazyAssemblyLoader (context.FileName, cache);
- }
- }
- } catch (Exception e) {
- LoggingService.LogError ("Error while updating assembly " + context.FileName, e);
- }
- }
-
- static void CheckModifiedFiles ()
- {
- Queue<KeyValuePair<Project, ProjectContentWrapper>> list;
-
- lock (projectContentLock) {
- list = new Queue<KeyValuePair<Project, ProjectContentWrapper>> (projectContents);
- }
-
- while (list.Count > 0) {
- var readydb = list.Dequeue ();
- var files = readydb.Key.Files.ToArray ();
- CheckModifiedFiles (readydb.Key, files, readydb.Value);
- }
-
- var assemblyList = new Queue<KeyValuePair<string, UnresolvedAssemblyProxy>> (cachedAssemblyContents);
-
- while (assemblyList.Count > 0) {
- var readydb = assemblyList.Dequeue ();
- CheckModifiedFile (readydb.Value);
- }
- }
-
- static void ConsumeParsingQueue ()
- {
- int pending = 0;
- ProgressMonitor monitor = null;
- var token = loadCancellationSource.Token;
- StartParseOperation ();
- try {
- do {
- if (pending > 5 && monitor == null) {
- monitor = GetParseProgressMonitor ();
- monitor.BeginTask (GettextCatalog.GetString ("Generating database"), 0);
- }
- var job = DequeueParseJob ();
- if (job != null) {
- try {
- job.Run (monitor, token);
- } catch (Exception ex) {
- if (monitor == null)
- monitor = GetParseProgressMonitor ();
- monitor.ReportError (null, ex);
- } finally {
- job.Context.EndLoadOperation ();
- }
- }
-
- if (token.IsCancellationRequested)
- break;
- pending = PendingJobCount;
- } while (pending > 0);
- queueEmptied.Set ();
- } finally {
- if (monitor != null)
- monitor.Dispose ();
- EndParseOperation ();
- }
- }
-
- #endregion
-
- }
-
- sealed class AssemblyLoadedEventArgs : EventArgs
- {
- public readonly TypeSystemService.LazyAssemblyLoader Assembly;
-
- public AssemblyLoadedEventArgs (TypeSystemService.LazyAssemblyLoader assembly)
- {
- this.Assembly = assembly;
- }
- }
-
- public sealed class ProjectUnloadEventArgs : EventArgs
- {
- public readonly Project Project;
- public readonly TypeSystemService.ProjectContentWrapper Wrapper;
-
- public ProjectUnloadEventArgs (Project project, TypeSystemService.ProjectContentWrapper wrapper)
- {
- this.Project = project;
- this.Wrapper = wrapper;
- }
}
}
-
-
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService_WorkspaceHandling.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService_WorkspaceHandling.cs
new file mode 100644
index 0000000000..e623dbf213
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService_WorkspaceHandling.cs
@@ -0,0 +1,488 @@
+//
+// TypeSystemService.cs
+//
+// Author:
+// Mike Krüger <mkrueger@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 Microsoft.CodeAnalysis;
+using MonoDevelop.Core;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Mono.Addins;
+using MonoDevelop.Projects;
+using System.IO;
+using System.Linq;
+using System.Collections.Immutable;
+using System.Collections.Concurrent;
+
+namespace MonoDevelop.Ide.TypeSystem
+{
+
+// static class MonoDevelopWorkspaceFeatures
+// {
+// static FeaturePack pack;
+//
+// public static FeaturePack Features {
+// get {
+// if (pack == null)
+// Interlocked.CompareExchange (ref pack, ComputePack (), null);
+// return pack;
+// }
+// }
+//
+// static FeaturePack ComputePack ()
+// {
+// var assemblies = new List<Assembly> ();
+// var workspaceCoreAssembly = typeof(Workspace).Assembly;
+// assemblies.Add (workspaceCoreAssembly);
+//
+// LoadAssembly (assemblies, "Microsoft.CodeAnalysis.CSharp.Workspaces");
+// //LoadAssembly (assemblies, "Microsoft.CodeAnalysis.VisualBasic.Workspaces");
+//
+// var catalogs = assemblies.Select (a => new System.ComponentModel.Composition.Hosting.AssemblyCatalog (a));
+//
+// return new MefExportPack (catalogs);
+// }
+//
+// static void LoadAssembly (List<Assembly> assemblies, string assemblyName)
+// {
+// try {
+// var loadedAssembly = Assembly.Load (assemblyName);
+// assemblies.Add (loadedAssembly);
+// } catch (Exception e) {
+// LoggingService.LogWarning ("Couldn't load assembly:" + assemblyName, e);
+// }
+// }
+// }
+
+ public static partial class TypeSystemService
+ {
+ static readonly MonoDevelopWorkspace emptyWorkspace;
+
+ static ConcurrentBag<MonoDevelopWorkspace> workspaces = new ConcurrentBag<MonoDevelopWorkspace>();
+
+ static ImmutableArray<MonoDevelopWorkspace> Workspaces {
+ get {
+ return workspaces.ToImmutableArray ();
+ }
+ }
+ public static ImmutableArray<Microsoft.CodeAnalysis.Workspace> AllWorkspaces {
+ get {
+ return workspaces.ToImmutableArray<Microsoft.CodeAnalysis.Workspace> ();
+ }
+ }
+
+
+ internal static MonoDevelopWorkspace GetWorkspace (MonoDevelop.Projects.Solution solution)
+ {
+ if (solution == null)
+ throw new ArgumentNullException ("solution");
+ foreach (var ws in Workspaces) {
+ if (ws.MonoDevelopSolution == solution)
+ return ws;
+ }
+ return emptyWorkspace;
+ }
+
+ public static Microsoft.CodeAnalysis.Workspace Workspace {
+ get {
+ var solution = IdeApp.ProjectOperations?.CurrentSelectedSolution;
+ if (solution == null)
+ return emptyWorkspace;
+ return GetWorkspace (solution);
+ }
+ }
+
+
+ public static void NotifyFileChange (string fileName, string text)
+ {
+ foreach (var ws in Workspaces)
+ ws.UpdateFileContent (fileName, text);
+ }
+
+ internal static Microsoft.CodeAnalysis.Workspace Load (WorkspaceItem item, IProgressMonitor progressMonitor, bool loadInBackground = true)
+ {
+ using (Counters.ParserService.WorkspaceItemLoaded.BeginTiming ()) {
+ var workspace = new MonoDevelopWorkspace ();
+ if (!(item is MonoDevelop.Projects.Workspace))
+ workspaces.Add (workspace);
+ workspace.ShowStatusIcon ();
+ InternalLoad (item, progressMonitor, workspace, loadInBackground).ContinueWith (t => {
+ workspace.HideStatusIcon ();
+ });
+ return workspace;
+ }
+ }
+
+ static Task InternalLoad (MonoDevelop.Projects.WorkspaceItem item, IProgressMonitor progressMonitor, MonoDevelopWorkspace workspace, bool loadInBackground)
+ {
+ var ws = item as MonoDevelop.Projects.Workspace;
+ if (ws != null) {
+ Action loadAction = () => {
+ var newWorkspace = new MonoDevelopWorkspace ();
+ foreach (var it in ws.Items)
+ InternalLoad (it, progressMonitor, newWorkspace, false);
+ workspaces.Add (workspace);
+ ws.ItemAdded += OnWorkspaceItemAdded;
+ ws.ItemRemoved += OnWorkspaceItemRemoved;
+ };
+ if (loadInBackground) {
+ return Task.Run (loadAction);
+ } else {
+ loadAction ();
+ }
+ } else {
+ var solution = item as MonoDevelop.Projects.Solution;
+ if (solution != null) {
+ Action loadAction = () => {
+ workspace.TryLoadSolution (solution/*, progressMonitor*/);
+ solution.SolutionItemAdded += OnSolutionItemAdded;
+ solution.SolutionItemRemoved += OnSolutionItemRemoved;
+ };
+ if (loadInBackground) {
+ return Task.Run (loadAction);
+ } else {
+ loadAction ();
+ }
+ }
+ }
+ return Task.FromResult(false);
+ }
+
+ internal static void Unload (MonoDevelop.Projects.WorkspaceItem item)
+ {
+ var ws = item as MonoDevelop.Projects.Workspace;
+ if (ws != null) {
+ foreach (var it in ws.Items)
+ Unload (it);
+ ws.ItemAdded -= OnWorkspaceItemAdded;
+ ws.ItemRemoved -= OnWorkspaceItemRemoved;
+ MonoDocDocumentationProvider.ClearCommentCache ();
+ } else {
+ var solution = item as MonoDevelop.Projects.Solution;
+ if (solution != null) {
+ MonoDevelopWorkspace result = GetWorkspace (solution);
+ if (result != emptyWorkspace) {
+ workspaces = new ConcurrentBag<MonoDevelopWorkspace> (Workspaces.Where (w => w != result));
+ result.Dispose ();
+ }
+ solution.SolutionItemAdded -= OnSolutionItemAdded;
+ solution.SolutionItemRemoved -= OnSolutionItemRemoved;
+ if (solution.ParentWorkspace == null)
+ MonoDocDocumentationProvider.ClearCommentCache ();
+ }
+ }
+ }
+
+ public static DocumentId GetDocumentId (MonoDevelop.Projects.Project project, string fileName)
+ {
+ if (project == null)
+ throw new ArgumentNullException ("project");
+ if (fileName == null)
+ throw new ArgumentNullException ("fileName");
+ fileName = FileService.GetFullPath (fileName);
+ foreach (var w in Workspaces) {
+ var projectId = w.GetProjectId (project);
+ if (projectId != null)
+ return w.GetDocumentId (projectId, fileName);
+ }
+ return null;
+ }
+
+ public static DocumentId GetDocumentId (Microsoft.CodeAnalysis.Workspace workspace, MonoDevelop.Projects.Project project, string fileName)
+ {
+ if (project == null)
+ throw new ArgumentNullException ("project");
+ if (fileName == null)
+ throw new ArgumentNullException ("fileName");
+ fileName = FileService.GetFullPath (fileName);
+ var projectId = ((MonoDevelopWorkspace)workspace).GetProjectId (project);
+ if (projectId != null)
+ return ((MonoDevelopWorkspace)workspace).GetDocumentId (projectId, fileName);
+ return null;
+ }
+
+
+ public static DocumentId GetDocumentId (ProjectId projectId, string fileName)
+ {
+ if (projectId == null)
+ throw new ArgumentNullException ("projectId");
+ if (fileName == null)
+ throw new ArgumentNullException ("fileName");
+ foreach (var w in Workspaces) {
+ if (w.Contains (projectId))
+ return w.GetDocumentId (projectId, fileName);
+ }
+ return null;
+ }
+
+ public static IEnumerable<DocumentId> GetDocuments (string fileName)
+ {
+ if (fileName == null)
+ throw new ArgumentNullException ("fileName");
+ fileName = FileService.GetFullPath (fileName);
+ foreach (var w in Workspaces) {
+ foreach (var projectId in w.CurrentSolution.ProjectIds) {
+ var docId = w.GetDocumentId (projectId, fileName);
+ if (docId != null)
+ yield return docId;
+ }
+ }
+ }
+
+ public static Microsoft.CodeAnalysis.Project GetCodeAnalysisProject (MonoDevelop.Projects.Project project)
+ {
+ if (project == null)
+ throw new ArgumentNullException ("project");
+ foreach (var w in Workspaces) {
+ var projectId = w.GetProjectId (project);
+ if (projectId != null)
+ return w.CurrentSolution.GetProject (projectId);
+ }
+ return null;
+ }
+
+ public static async Task<Compilation> GetCompilationAsync (MonoDevelop.Projects.Project project, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (project == null)
+ throw new ArgumentNullException ("project");
+ foreach (var w in Workspaces) {
+ var projectId = w.GetProjectId (project);
+ if (projectId == null)
+ continue;
+ var roslynProject = w.CurrentSolution.GetProject (projectId);
+ if (roslynProject == null)
+ continue;
+ return await roslynProject.GetCompilationAsync (cancellationToken).ConfigureAwait (false);
+ }
+ return null;
+ }
+
+ static void OnWorkspaceItemAdded (object s, MonoDevelop.Projects.WorkspaceItemEventArgs args)
+ {
+ Task.Run (() => TypeSystemService.Load (args.Item, null));
+ }
+
+ static void OnWorkspaceItemRemoved (object s, MonoDevelop.Projects.WorkspaceItemEventArgs args)
+ {
+ Unload (args.Item);
+ }
+
+ static void OnSolutionItemAdded (object sender, MonoDevelop.Projects.SolutionItemChangeEventArgs args)
+ {
+ var project = args.SolutionItem as MonoDevelop.Projects.Project;
+ if (project != null) {
+ var ws = GetWorkspace (project.ParentSolution);
+ ws.AddProject (project);
+ }
+ }
+
+ static void OnSolutionItemRemoved (object sender, MonoDevelop.Projects.SolutionItemChangeEventArgs args)
+ {
+ var project = args.SolutionItem as MonoDevelop.Projects.Project;
+ var solution = sender as MonoDevelop.Projects.Solution;
+ if (project != null) {
+ var ws = GetWorkspace (solution);
+ ws.RemoveProject (project);
+ }
+ }
+
+ #region Tracked project handling
+ static readonly List<string> outputTrackedProjects = new List<string> ();
+
+ static void IntitializeTrackedProjectHandling ()
+ {
+ AddinManager.AddExtensionNodeHandler ("/MonoDevelop/TypeSystem/OutputTracking", delegate (object sender, ExtensionNodeEventArgs args) {
+ var projectType = ((TypeSystemOutputTrackingNode)args.ExtensionNode).ProjectType;
+ switch (args.Change) {
+ case ExtensionChange.Add:
+ outputTrackedProjects.Add (projectType);
+ break;
+ case ExtensionChange.Remove:
+ outputTrackedProjects.Remove (projectType);
+ break;
+ }
+ });
+ if (IdeApp.ProjectOperations != null)
+ IdeApp.ProjectOperations.EndBuild += HandleEndBuild;
+ if (IdeApp.Workspace != null)
+ IdeApp.Workspace.ActiveConfigurationChanged += HandleActiveConfigurationChanged;
+
+
+ }
+
+ static void HandleEndBuild (object sender, BuildEventArgs args)
+ {
+ var project = args.SolutionItem as DotNetProject;
+ if (project == null)
+ return;
+ CheckProjectOutput (project, true);
+ }
+
+ static void HandleActiveConfigurationChanged (object sender, EventArgs e)
+ {
+ foreach (var pr in IdeApp.ProjectOperations.CurrentSelectedSolution.GetAllProjects ()) {
+ var project = pr as DotNetProject;
+ if (project != null)
+ CheckProjectOutput (project, true);
+ }
+ }
+
+ internal static bool IsOutputTrackedProject (DotNetProject project)
+ {
+ if (project == null)
+ throw new ArgumentNullException ("project");
+ return project.GetProjectTypes ().Any (p => outputTrackedProjects.Contains (p, StringComparer.OrdinalIgnoreCase));
+ }
+
+ static void CheckProjectOutput (DotNetProject project, bool autoUpdate)
+ {
+ if (project == null)
+ throw new ArgumentNullException ("project");
+ if (IsOutputTrackedProject (project)) {
+ var fileName = project.GetOutputFileName (IdeApp.Workspace.ActiveConfiguration);
+ if (!File.Exists (fileName))
+ return;
+ FileService.NotifyFileChanged (fileName);
+ if (autoUpdate) {
+ // update documents
+ foreach (var openDocument in IdeApp.Workbench.Documents) {
+ openDocument.ReparseDocument ();
+ }
+ }
+ }
+ }
+ #endregion
+
+// TODO: Port framework lookup to NR6
+// #region FrameworkLookup
+// class FrameworkTask
+// {
+// public int RetryCount { get; set; }
+//
+// public Task<FrameworkLookup> Task { get; set; }
+// }
+//
+// readonly static Dictionary<string, FrameworkTask> frameworkLookup = new Dictionary<string, FrameworkTask> ();
+//
+// static void StartFrameworkLookup (DotNetProject netProject)
+// {
+// if (netProject == null)
+// throw new ArgumentNullException ("netProject");
+// lock (frameworkLookup) {
+// FrameworkTask result;
+// if (netProject.TargetFramework == null)
+// return;
+// var frameworkName = netProject.TargetFramework.Name;
+// if (!frameworkLookup.TryGetValue (frameworkName, out result))
+// frameworkLookup [frameworkName] = result = new FrameworkTask ();
+// if (result.Task != null)
+// return;
+// result.Task = Task.Factory.StartNew (delegate {
+// return GetFrameworkLookup (netProject);
+// });
+// }
+// }
+//
+// public static bool TryGetFrameworkLookup (DotNetProject project, out FrameworkLookup lookup)
+// {
+// lock (frameworkLookup) {
+// FrameworkTask result;
+// if (frameworkLookup.TryGetValue (project.TargetFramework.Name, out result)) {
+// if (!result.Task.IsCompleted) {
+// lookup = null;
+// return false;
+// }
+// lookup = result.Task.Result;
+// return true;
+// }
+// }
+// lookup = null;
+// return false;
+// }
+//
+// public static bool RecreateFrameworkLookup (DotNetProject netProject)
+// {
+// lock (frameworkLookup) {
+// FrameworkTask result;
+// var frameworkName = netProject.TargetFramework.Name;
+// if (!frameworkLookup.TryGetValue (frameworkName, out result))
+// return false;
+// if (result.RetryCount > 5) {
+// LoggingService.LogError ("Can't create framework lookup for:" + frameworkName);
+// return false;
+// }
+// result.RetryCount++;
+// LoggingService.LogInfo ("Trying to recreate framework lookup for {0}, try {1}.", frameworkName, result.RetryCount);
+// result.Task = null;
+// StartFrameworkLookup (netProject);
+// return true;
+// }
+// }
+//
+// static FrameworkLookup GetFrameworkLookup (DotNetProject netProject)
+// {
+// FrameworkLookup result;
+// string fileName;
+// var cache = GetCacheDirectory (netProject.TargetFramework);
+// fileName = Path.Combine (cache, "FrameworkLookup_" + FrameworkLookup.CurrentVersion + ".dat");
+// try {
+// if (File.Exists (fileName)) {
+// result = FrameworkLookup.Load (fileName);
+// if (result != null) {
+// return result;
+// }
+// }
+// } catch (Exception e) {
+// LoggingService.LogWarning ("Can't read framework cache - recreating...", e);
+// }
+//
+// try {
+// using (var creator = FrameworkLookup.Create (fileName)) {
+// foreach (var assembly in GetFrameworkAssemblies (netProject)) {
+// var ctx = LoadAssemblyContext (assembly.Location);
+// foreach (var type in ctx.Ctx.GetAllTypeDefinitions ()) {
+// if (!type.IsPublic)
+// continue;
+// creator.AddLookup (assembly.Package.Name, assembly.FullName, type);
+// }
+// }
+// }
+// } catch (Exception e) {
+// LoggingService.LogError ("Error while storing framework lookup", e);
+// return FrameworkLookup.Empty;
+// }
+//
+// try {
+// result = FrameworkLookup.Load (fileName);
+// return result;
+// } catch (Exception e) {
+// LoggingService.LogError ("Error loading framework lookup", e);
+// return FrameworkLookup.Empty;
+// }
+// }
+// #endregion
+ }
+
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/AddinsUpdateHandler.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/AddinsUpdateHandler.cs
index a40a755af4..bd5a88814f 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/AddinsUpdateHandler.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/AddinsUpdateHandler.cs
@@ -32,8 +32,8 @@ using Mono.Addins.Gui;
using MonoDevelop.Ide.ProgressMonitoring;
using Mono.Addins;
using MonoDevelop.Core.Setup;
-using Mono.TextEditor;
using System.Threading.Tasks;
+using MonoDevelop.Components;
namespace MonoDevelop.Ide.Updater
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.WelcomePage/WelcomePageFirstRun.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.WelcomePage/WelcomePageFirstRun.cs
index 2f4d880a34..df2f768770 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.WelcomePage/WelcomePageFirstRun.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.WelcomePage/WelcomePageFirstRun.cs
@@ -31,7 +31,6 @@ using MonoDevelop.Ide.Gui;
using MonoDevelop.Components;
using System.Collections.Generic;
using Xwt.Motion;
-using Mono.TextEditor;
namespace MonoDevelop.Ide.WelcomePage
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.WelcomePage/WelcomePageLinkButton.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.WelcomePage/WelcomePageLinkButton.cs
index 6fb3f20e73..9fa482fc34 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.WelcomePage/WelcomePageLinkButton.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.WelcomePage/WelcomePageLinkButton.cs
@@ -187,7 +187,7 @@ namespace MonoDevelop.Ide.WelcomePage
if (uri.StartsWith ("project://")) {
string projectUri = uri.Substring ("project://".Length);
Uri fileuri = new Uri (projectUri);
- Gdk.ModifierType mtype = Mono.TextEditor.GtkWorkarounds.GetCurrentKeyModifiers ();
+ Gdk.ModifierType mtype = GtkWorkarounds.GetCurrentKeyModifiers ();
bool inWorkspace = (mtype & Gdk.ModifierType.ControlMask) != 0;
IdeApp.Workspace.OpenWorkspaceItem (fileuri.LocalPath, !inWorkspace);
} else if (uri.StartsWith ("monodevelop://")) {
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.WelcomePage/WelcomePageListButton.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.WelcomePage/WelcomePageListButton.cs
index ec6e00a91a..08cc70f4cb 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.WelcomePage/WelcomePageListButton.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.WelcomePage/WelcomePageListButton.cs
@@ -27,7 +27,6 @@ using System;
using MonoDevelop.Core;
using MonoDevelop.Components;
using Gtk;
-using Mono.TextEditor;
namespace MonoDevelop.Ide.WelcomePage
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.WelcomePage/WelcomePageSection.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.WelcomePage/WelcomePageSection.cs
index b5f450b8b9..02401d3679 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.WelcomePage/WelcomePageSection.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.WelcomePage/WelcomePageSection.cs
@@ -28,7 +28,6 @@ using Gtk;
using System.Xml.Linq;
using MonoDevelop.Core;
using MonoDevelop.Components;
-using Mono.TextEditor;
namespace MonoDevelop.Ide.WelcomePage
{
@@ -129,8 +128,18 @@ namespace MonoDevelop.Ide.WelcomePage
if (uri.StartsWith ("project://")) {
string projectUri = uri.Substring ("project://".Length);
Uri fileuri = new Uri (projectUri);
- Gdk.ModifierType mtype = Mono.TextEditor.GtkWorkarounds.GetCurrentKeyModifiers ();
+ Gdk.ModifierType mtype = GtkWorkarounds.GetCurrentKeyModifiers ();
bool inWorkspace = (mtype & Gdk.ModifierType.ControlMask) != 0;
+
+ // Notify the RecentFiles that this item does not exist anymore.
+ // Possible other solution would be to check the recent projects list on focus in
+ // and update them accordingly.
+ if (!System.IO.File.Exists (fileuri.LocalPath)) {
+ MessageService.ShowError (GettextCatalog.GetString ("File not found {0}", fileuri.LocalPath));
+ FileService.NotifyFileRemoved (fileuri.LocalPath);
+ return;
+ }
+
IdeApp.Workspace.OpenWorkspaceItem (fileuri.LocalPath, !inWorkspace);
} else if (uri.StartsWith ("monodevelop://")) {
var cmdId = uri.Substring ("monodevelop://".Length);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj
index 530204b514..c170ba7116 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj
@@ -100,10 +100,45 @@
<Reference Include="System.Web" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Design" />
+ <Reference Include="System.ComponentModel.Composition" />
+ <Reference Include="System.Collections.Immutable">
+ <HintPath>..\..\..\packages\System.Collections.Immutable.1.1.33-beta\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Reflection.Metadata">
+ <HintPath>..\..\..\packages\System.Reflection.Metadata.1.0.18-beta\lib\portable-net45+win8\System.Reflection.Metadata.dll</HintPath>
+ </Reference>
<Reference Include="System.Windows.Forms" />
+ <Reference Include="Microsoft.CodeAnalysis.Desktop">
+ <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.Common.1.0.0-rc1\lib\net45\Microsoft.CodeAnalysis.Desktop.dll</HintPath>
+ </Reference>
+ <Reference Include="Microsoft.CodeAnalysis">
+ <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.Common.1.0.0-rc1\lib\net45\Microsoft.CodeAnalysis.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Runtime.Serialization" />
<Reference Include="Xamarin.Mac" Condition=" '$(Configuration)' == 'DebugMac' Or '$(Configuration)' == 'ReleaseMac' ">
<HintPath>..\..\..\external\Xamarin.Mac.dll</HintPath>
</Reference>
+ <Reference Include="Microsoft.CodeAnalysis.Workspaces.Desktop">
+ <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.0.0-rc1\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll</HintPath>
+ </Reference>
+ <Reference Include="Microsoft.CodeAnalysis.Workspaces">
+ <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.0.0-rc1\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Composition.AttributedModel">
+ <HintPath>..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.AttributedModel.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Composition.Convention">
+ <HintPath>..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Convention.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Composition.Hosting">
+ <HintPath>..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Hosting.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Composition.Runtime">
+ <HintPath>..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Runtime.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Composition.TypedParts">
+ <HintPath>..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.TypedParts.dll</HintPath>
+ </Reference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MonoDevelop.Core\MonoDevelop.Core.csproj">
@@ -111,11 +146,6 @@
<Name>MonoDevelop.Core</Name>
<Private>False</Private>
</ProjectReference>
- <ProjectReference Include="..\Mono.Texteditor\Mono.TextEditor.csproj">
- <Project>{A2329308-3751-4DBD-9A75-5F7B8B024625}</Project>
- <Name>Mono.TextEditor</Name>
- <Private>False</Private>
- </ProjectReference>
<ProjectReference Include="..\MonoDevelop.Projects.Formats.MSBuild\MonoDevelop.Projects.Formats.MSBuild.csproj">
<Project>{A437F1A3-78DF-4F00-8053-D32A8B1EB679}</Project>
<Name>MonoDevelop.Projects.Formats.MSBuild</Name>
@@ -124,12 +154,10 @@
<ProjectReference Include="..\..\..\external\nrefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
<Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project>
<Name>ICSharpCode.NRefactory</Name>
- <Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\..\external\nrefactory\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj">
<Project>{53DCA265-3C3C-42F9-B647-F72BA678122B}</Project>
<Name>ICSharpCode.NRefactory.CSharp</Name>
- <Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\..\external\xwt\Xwt\Xwt.csproj">
<Project>{92494904-35FA-4DC9-BDE9-3A3E87AC49D3}</Project>
@@ -170,6 +198,18 @@
<Project>{4CB170EF-DFE6-4A56-9E1B-A85449E827A7}</Project>
<Name>IKVM.Reflection</Name>
</ProjectReference>
+ <ProjectReference Include="..\..\..\external\NRefactory6\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory6.CSharp.csproj">
+ <Project>{7E891659-45F3-42B5-B940-A728780CCAE9}</Project>
+ <Name>ICSharpCode.NRefactory6.CSharp</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\external\NRefactory6\ICSharpCode.NRefactory.CSharp.Refactoring\ICSharpCode.NRefactory6.CSharp.Refactoring.csproj">
+ <Project>{C465A5DC-AD28-49A2-89C0-F81838814A7E}</Project>
+ <Name>ICSharpCode.NRefactory6.CSharp.Refactoring</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\external\nrefactory\ICSharpCode.NRefactory.Cecil\ICSharpCode.NRefactory.Cecil.csproj">
+ <Project>{2B8F4F83-C2B3-4E84-A27B-8DEE1BE0E006}</Project>
+ <Name>ICSharpCode.NRefactory.Cecil</Name>
+ </ProjectReference>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="templates\AppConfigFile.xft.xml">
@@ -913,7 +953,6 @@
<EmbeddedResource Include="icons\tree-popup-button-down%402x.png">
<LogicalName>tree-popup-button-down@2x.png</LogicalName>
</EmbeddedResource>
- <EmbeddedResource Include="MonoDevelop.Components\SearchEntry.cs" />
<EmbeddedResource Include="icons\clear-all-bookmarks-16.png">
<LogicalName>clear-all-bookmarks-16.png</LogicalName>
</EmbeddedResource>
@@ -2351,7 +2390,7 @@
</EmbeddedResource>
<EmbeddedResource Include="icons\mac\status-pushing-1-16%402x.png">
<LogicalName>status-pushing-1-16@2x.png</LogicalName>
- </EmbeddedResource>
+ </EmbeddedResource>
<EmbeddedResource Include="icons\mac\status-pushing-2-16.png">
<LogicalName>status-pushing-2-16.png</LogicalName>
</EmbeddedResource>
@@ -2540,9 +2579,7 @@
<Compile Include="MonoDevelop.Ide.Gui\ViewCommandHandlers.cs" />
<Compile Include="MonoDevelop.Ide.Gui.Content\IBookmarkBuffer.cs" />
<Compile Include="MonoDevelop.Ide.Gui.Content\IClipboardHandler.cs" />
- <Compile Include="MonoDevelop.Ide.Gui.Content\IEditableTextBuffer.cs" />
<Compile Include="MonoDevelop.Ide.Gui.Content\IPrintable.cs" />
- <Compile Include="MonoDevelop.Ide.Gui.Content\ITextBuffer.cs" />
<Compile Include="MonoDevelop.Ide.Gui.Dialogs\CommonAboutDialog.cs" />
<Compile Include="MonoDevelop.Ide.Gui.Dialogs\DirtyFilesDialog.cs" />
<Compile Include="MonoDevelop.Ide.Gui.Dialogs\NewLayoutDialog.cs" />
@@ -2595,7 +2632,6 @@
<Compile Include="MonoDevelop.Ide.Templates\CodeTranslationFileDescriptionTemplate.cs" />
<Compile Include="MonoDevelop.Ide.Gui.Dialogs\SelectEncodingsDialog.cs" />
<Compile Include="MonoDevelop.Ide.Gui.Dialogs\FileSelectorDialog.cs" />
- <Compile Include="MonoDevelop.Ide.Gui.Content\IEncodedTextContent.cs" />
<Compile Include="MonoDevelop.Ide.Tasks\TaskPriority.cs" />
<Compile Include="MonoDevelop.Ide.Gui.Pads\ErrorListPad.cs" />
<Compile Include="gtk-gui\generated.cs" />
@@ -2604,9 +2640,7 @@
<Compile Include="MonoDevelop.Ide.Tasks\CommentTasksView.cs" />
<Compile Include="MonoDevelop.Ide.Tasks\UserTasksView.cs" />
<Compile Include="MonoDevelop.Ide.Gui\LayoutComboBox.cs" />
- <Compile Include="MonoDevelop.Ide.Gui.Content\IExtensibleTextEditor.cs" />
<Compile Include="MonoDevelop.Ide.Gui.Pads.ProjectPad\UnknownEntryNodeBuilder.cs" />
- <Compile Include="MonoDevelop.Ide.Gui.Content\TextEditorExtension.cs" />
<Compile Include="MonoDevelop.Ide.Commands\NavigationCommands.cs" />
<Compile Include="MonoDevelop.Ide.Templates\ISolutionItemFeature.cs" />
<Compile Include="MonoDevelop.Ide.StandardHeader\StandardHeaderService.cs" />
@@ -2631,14 +2665,15 @@
<Compile Include="MonoDevelop.Ide.Templates\FileTemplateCondition.cs" />
<Compile Include="MonoDevelop.Ide.Templates\PartialTypeFileTemplateCondition.cs" />
<Compile Include="MonoDevelop.Ide.Templates\ParentProjectFileTemplateCondition.cs" />
- <Compile Include="MonoDevelop.Ide.Gui.Content\CompletionTextEditorExtension.cs" />
<Compile Include="MonoDevelop.Ide.Gui\ToolbarComboBox.cs" />
<Compile Include="MonoDevelop.Ide.Gui.Content\ISplittable.cs" />
<Compile Include="MonoDevelop.Ide.Gui.Content\IFoldable.cs" />
<Compile Include="MonoDevelop.Ide.ExternalTools\ExternalToolPanel.cs" />
<Compile Include="gtk-gui\MonoDevelop.Ide.ExternalTools.ExternalToolPanelWidget.cs" />
<Compile Include="MonoDevelop.Ide.Gui\MonoDevelopStatusBar.cs" />
- <Compile Include="MonoDevelop.Ide.Gui\DocumentSwitcher.cs" />
+ <Compile Include="MonoDevelop.Ide.Gui\DocumentSwitcher.cs">
+ <DependentUpon>GuiSyncContext.cs</DependentUpon>
+ </Compile>
<Compile Include="MonoDevelop.Ide.Gui.OptionPanels\IDEStyleOptionsPanel.cs" />
<Compile Include="gtk-gui\MonoDevelop.Ide.Gui.OptionPanels.IDEStyleOptionsPanelWidget.cs" />
<Compile Include="MonoDevelop.Ide.Gui.Content\IZoomable.cs" />
@@ -2667,7 +2702,6 @@
<Compile Include="MonoDevelop.Ide.Gui.Components\TransactedTreeBuilder.cs" />
<Compile Include="MonoDevelop.Ide.Gui.Content\INavigable.cs" />
<Compile Include="MonoDevelop.Ide.Gui.Content\IOpenNamedElementHandler.cs" />
- <Compile Include="MonoDevelop.Ide.Gui.Content\ISmartIndenter.cs" />
<Compile Include="AssemblyInfo.cs" />
<Compile Include="MonoDevelop.Ide.Gui.Content\ITextEditorResolver.cs" />
<Compile Include="MonoDevelop.Ide.Gui.OptionPanels\AuthorInformationPanel.cs" />
@@ -2741,7 +2775,9 @@
<Compile Include="MonoDevelop.Ide.Extensions\IOpenFileDialogHandler.cs" />
<Compile Include="MonoDevelop.Ide.Extensions\IAddFileDialogHandler.cs" />
<Compile Include="MonoDevelop.Ide.Extensions\TextEditorExtensionNode.cs" />
- <Compile Include="MonoDevelop.Ide.Gui\DockItemToolbarLoader.cs" />
+ <Compile Include="MonoDevelop.Ide.Gui\DockItemToolbarLoader.cs">
+ <DependentUpon>DisplayBindingService.cs</DependentUpon>
+ </Compile>
<Compile Include="MonoDevelop.Ide.Gui.Components\LogView.cs" />
<Compile Include="MonoDevelop.Ide.Gui\WorkbenchContext.cs" />
<Compile Include="MonoDevelop.Ide.Extensions\LayoutExtensionNode.cs" />
@@ -2867,7 +2903,6 @@
<Compile Include="MonoDevelop.Components.PropertyGrid.Editors\FlagsSelectorDialog.cs" />
<Compile Include="MonoDevelop.Components.PropertyGrid.Editors\FloatRange.cs" />
<Compile Include="MonoDevelop.Components.PropertyGrid.Editors\IntRange.cs" />
- <Compile Include="MonoDevelop.Components.PropertyGrid.Editors\TextEditor.cs" />
<Compile Include="MonoDevelop.Components.PropertyGrid.Editors\TextEditorDialog.cs" />
<Compile Include="MonoDevelop.Components.PropertyGrid.Editors\TimeSpanEditor.cs" />
<Compile Include="MonoDevelop.Components.PropertyGrid.Editors\BooleanEditorCell.cs" />
@@ -3137,7 +3172,6 @@
<Compile Include="MonoDevelop.Ide.WelcomePage\WelcomePageRecentProjectsList.cs" />
<Compile Include="MonoDevelop.Ide.WelcomePage\WelcomePageLinksList.cs" />
<Compile Include="MonoDevelop.Ide.Gui\ProjectLoadProgressMonitor.cs" />
- <Compile Include="MonoDevelop.Ide.Gui\CommonTextEditorOptions.cs" />
<Compile Include="MonoDevelop.Components\FileFilterSet.cs" />
<Compile Include="MonoDevelop.Ide\IdeVersionInfo.cs" />
<Compile Include="MonoDevelop.Components\ContextMenuTreeView.cs" />
@@ -3150,22 +3184,14 @@
<Compile Include="MonoDevelop.Ide\ProjectCreatedEventArgs.cs" />
<Compile Include="MonoDevelop.Ide.FindInFiles\MemberCollector.cs" />
<Compile Include="MonoDevelop.Ide.FindInFiles\SearchCollector.cs" />
- <Compile Include="MonoDevelop.Ide.TypeSystem\ProjectContentEventArgs.cs" />
<Compile Include="MonoDevelop.Ide.TypeSystem\TypeSystemService.cs" />
<Compile Include="MonoDevelop.Ide.TypeSystem\Ambience.cs" />
- <Compile Include="MonoDevelop.Ide.TypeSystem\AmbienceService.cs" />
- <Compile Include="MonoDevelop.Ide.TypeSystem\NetAmbience.cs" />
- <Compile Include="MonoDevelop.Ide.TypeSystem\OutputFlags.cs" />
- <Compile Include="MonoDevelop.Ide.TypeSystem\OutputSettings.cs" />
<Compile Include="MonoDevelop.Ide.TypeSystem\StockIcons.cs" />
<Compile Include="MonoDevelop.Ide.TypeSystem\FoldingRegion.cs" />
<Compile Include="MonoDevelop.Ide.TypeSystem\ParsedDocument.cs" />
<Compile Include="MonoDevelop.Ide.TypeSystem\Comment.cs" />
<Compile Include="MonoDevelop.Ide.TypeSystem\Tag.cs" />
- <Compile Include="MonoDevelop.Ide.TypeSystem\PreProcessorDefine.cs" />
- <Compile Include="MonoDevelop.Ide.TypeSystem\ConditionalRegion.cs" />
<Compile Include="MonoDevelop.Ide.TypeSystem\MarkupUtilities.cs" />
- <Compile Include="MonoDevelop.Ide.TypeSystem\CodeGenerationService.cs" />
<Compile Include="MonoDevelop.Ide.TypeSystem\CodeGenerator.cs" />
<Compile Include="MonoDevelop.Ide.TypeSystem\TypeSystemParserNode.cs" />
<Compile Include="MonoDevelop.Ide.TypeSystem\MonoDocDocumentationProvider.cs" />
@@ -3177,7 +3203,6 @@
<Compile Include="MonoDevelop.Components.MainToolbar\StatusArea.cs" />
<Compile Include="MonoDevelop.Components.MainToolbar\RoundButton.cs" />
<Compile Include="MonoDevelop.Components.MainToolbar\ButtonBar.cs" />
- <Compile Include="MonoDevelop.Ide.TypeSystem\ProjectCommentTags.cs" />
<Compile Include="MonoDevelop.Components.MainToolbar\ProjectSearchCategory.cs" />
<Compile Include="MonoDevelop.Components.MainToolbar\SearchCategory.cs" />
<Compile Include="MonoDevelop.Components.MainToolbar\ISearchDataSource.cs" />
@@ -3191,7 +3216,6 @@
<Compile Include="MonoDevelop.Components\TooltipPopoverWindow.cs" />
<Compile Include="MonoDevelop.Ide.Gui.Components\AnimatedIcon.cs" />
<Compile Include="MonoDevelop.Ide\DefaultWebCertificateProvider.cs" />
- <Compile Include="MonoDevelop.Ide.TypeSystem\ParsedFileEventArgs.cs" />
<Compile Include="MonoDevelop.Ide.Extensions\MimeTypeExtensionNode.cs" />
<Compile Include="MonoDevelop.Ide.Gui\DocumentView.cs" />
<Compile Include="MonoDevelop.Components\VPanedThin.cs" />
@@ -3200,7 +3224,6 @@
<Compile Include="MonoDevelop.Components\ExtendedLabel.cs" />
<Compile Include="MonoDevelop.Ide.CodeCompletion\TooltipInformation.cs" />
<Compile Include="MonoDevelop.Ide.CodeCompletion\TooltipInformationWindow.cs" />
- <Compile Include="MonoDevelop.Ide.CodeCompletion\ParameterDataProvider.cs" />
<Compile Include="MonoDevelop.Ide.TypeSystem\TypeSystemParser.cs" />
<Compile Include="MonoDevelop.Ide.WelcomePage\WelcomePageSection.cs" />
<Compile Include="MonoDevelop.Ide.WelcomePage\Style.cs" />
@@ -3220,7 +3243,6 @@
<Compile Include="MonoDevelop.Ide.TextEditing\TopLevelWidgetExtension.cs" />
<Compile Include="MonoDevelop.Ide.TextEditing\VerticalAlignment.cs" />
<Compile Include="MonoDevelop.Ide.TextEditing\HorizontalAlignment.cs" />
- <Compile Include="MonoDevelop.Ide.TextEditing\TextLineMarkerExtension.cs" />
<Compile Include="MonoDevelop.Ide.TextEditing\TextFileEventArgs.cs" />
<Compile Include="MonoDevelop.Ide.TextEditing\LineCountEventArgs.cs" />
<Compile Include="MonoDevelop.Ide.TextEditing\FileExtension.cs" />
@@ -3247,7 +3269,6 @@
<Compile Include="MonoDevelop.Ide.Gui\StatusBarIcon.cs" />
<Compile Include="MonoDevelop.Ide.Gui\StatusBarContextImpl.cs" />
<Compile Include="MonoDevelop.Components.MainToolbar\MainStatusBarContextImpl.cs" />
- <Compile Include="MonoDevelop.Ide.TypeSystem\MonoDevelopProjectContent.cs" />
<Compile Include="MonoDevelop.Components.Commands\ICommandDelegator.cs" />
<Compile Include="MonoDevelop.Ide.CustomTools\ResXFileCodeGenerator.cs" />
<Compile Include="MonoDevelop.Components\CellRendererImage.cs" />
@@ -3256,7 +3277,6 @@
<Compile Include="AddinInfo.cs" />
<Compile Include="MonoDevelop.Ide.CodeCompletion\CompletionCharacters.cs" />
<Compile Include="MonoDevelop.Ide.CodeCompletion\CompletionCharacterCodon.cs" />
- <Compile Include="MonoDevelop.Ide.TypeSystem\IRefactoringContext.cs" />
<Compile Include="MonoDevelop.Ide.Gui.Pads.ProjectPad\ImplicitFrameworkAssemblyReferenceNodeBuilder.cs" />
<Compile Include="MonoDevelop.Ide.Gui.Pads.ProjectPad\PortableFrameworkSubsetNodeBuilder.cs" />
<Compile Include="MonoDevelop.Components.MainToolbar\SearchInSolutionSearchCategory.cs" />
@@ -3273,6 +3293,57 @@
<Compile Include="MonoDevelop.Ide.Templates\WorkspaceItemCreatedInformation.cs" />
<Compile Include="MonoDevelop.Ide.Templates\PackageReferencesForCreatedProject.cs" />
<Compile Include="MonoDevelop.Ide.Templates\ProjectTemplatePackageInstaller.cs" />
+ <Compile Include="MonoDevelop.Ide.TypeSystem\MonoDevelopTextLoader.cs" />
+ <Compile Include="MonoDevelop.Ide.TypeSystem\MonoDevelopSourceTextContainer.cs" />
+ <Compile Include="MonoDevelop.Ide.CustomTools\PublicResXFileCodeGenerator.cs" />
+ <Compile Include="MonoDevelop.Components\ImageLoader.cs" />
+ <Compile Include="MonoDevelop.Ide.CodeCompletion\ParameterHintingData.cs" />
+ <Compile Include="MonoDevelop.Ide.TypeSystem\MonoDevelopWorkspace.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\IDocumentLine.cs" />
+ <Compile Include="MonoDevelop.Ide.CodeTemplates\IListDataProvider.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\ITextEditorOptions.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\WordFindStrategy.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\InsertionPoint.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\TextLink.cs">
+ <DependentUpon>TextLinkModeEventArgs.cs</DependentUpon>
+ </Compile>
+ <Compile Include="MonoDevelop.Components\WindowTransparencyDecorator.cs" />
+ <Compile Include="MonoDevelop.Components\GtkWorkarounds.cs" />
+ <Compile Include="MonoDevelop.Components\PangoUtil.cs" />
+ <Compile Include="MonoDevelop.Components\HslColor.cs" />
+ <Compile Include="MonoDevelop.Components\HelperMethods.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\SelectionMode.cs" />
+ <Compile Include="MonoDevelop.Components\GtkGestures.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\FileSettingsStore.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\InsertionCursorEventArgs.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\IFoldSegment.cs" />
+ <Compile Include="MonoDevelop.Ide.TextEditing\TextLineMarkerExtension.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\ITextLineMarker.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\TooltipProvider.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\ITextSegmentMarker.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\DocumentRegion.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\TextMarkerMouseEventArgs.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\DefaultSourceEditorOptions.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\TextEditor.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\ITextDocument.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\TextEditorDisplayBinding.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor.Extension\AbstractUsagesExtension.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\TextEditorViewContent.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor.Extension\IndentationTracker.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor.Extension\SelectionSurroundingProvider.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor.Extension\TextPasteHandler.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\DocumentLocation.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor.Highlighting\SyntaxModeService.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor.Highlighting\AmbientColor.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor.Highlighting\ColorScheme.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor.Highlighting\ColorDescriptionAttribute.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor.Highlighting\TemplateCodon.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor.Highlighting\IStreamProvider.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor.Highlighting\TemplateExtensionNodeLoader.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\TextLinkModeEventArgs.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\InsertionModeOptions.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\TextLinkModeOptions.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor.Extension\CompletionTextEditorExtension.cs" />
<Compile Include="MonoDevelop.Components.DockNotebook\DockNotebook.cs" />
<Compile Include="MonoDevelop.Components.DockNotebook\PlaceholderWindow.cs" />
<Compile Include="MonoDevelop.Components.DockNotebook\TabStrip.cs" />
@@ -3289,12 +3360,25 @@
<Compile Include="MonoDevelop.Components\ContextMenuExtensionsMac.cs" />
<Compile Include="MonoDevelop.Components\ContextMenuExtensionsGtk.cs" />
<Compile Include="MonoDevelop.Ide.Gui\Split.cs" />
- <Compile Include="MonoDevelop.Ide.CustomTools\PublicResXFileCodeGenerator.cs" />
- <Compile Include="MonoDevelop.Components\ImageLoader.cs" />
<Compile Include="MonoDevelop.Components.DockNotebook\DockWindow.cs" />
<Compile Include="MonoDevelop.Ide.CustomTools\MSBuildCustomTool.cs" />
<Compile Include="MonoDevelop.Components\Mac\GtkMacInterop.cs" />
<Compile Include="MonoDevelop.Components\Control.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor.Extension\TextEditorExtension.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\IUnitTestMarker.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor.Highlighting\ChunkStyle.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\TextMarkerFactory.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\InternalExtensionAPI\ITextEditorImpl.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\InternalExtensionAPI\ITextMarkerFactory.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\InternalExtensionAPI\IEditorActionHost.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\EditActions.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\DocumentContext.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\InternalExtensionAPI\ITextEditorFactory.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\FoldSegmentFactory.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\IReadonlyTextDocument.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor.Extension\Usage.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\TextEditorFactory.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\AutoSave.cs" />
<Compile Include="MonoDevelop.Ide.Templates\SolutionTemplate.cs" />
<Compile Include="MonoDevelop.Ide.Templates\TemplateCategory.cs" />
<Compile Include="MonoDevelop.Ide.Templates\TemplateWizard.cs" />
@@ -3339,7 +3423,38 @@
<Compile Include="MonoDevelop.Components\Mac\NSViewContainer.cs" />
<Compile Include="MonoDevelop.Components\Mac\GtkEmbed.cs" />
<Compile Include="MonoDevelop.Components\Mac\WidgetWithNativeWindow.cs" />
- <Compile Include="MonoDevelop.Ide.Tasks\UserTask.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor.Extension\IQuickTaskProvider.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor.Extension\QuickTask.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor.Highlighting\SemanticHighlighting.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor.Highlighting\ColoredSegment.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\SegmentTree.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor.Util\Diff.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor.Util\SimpleBracketMatcher.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor.Util\SimpleReadonlyDocument.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\Commands\DynamicAbbrevHandler.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor.Extension\ModifierKeys.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor.Extension\SpecialKey.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor.Extension\KeyDescriptor.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\MessageBubbles\MessageBubbleCommands.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\LineEventArgs.cs" />
+ <Compile Include="MonoDevelop.Ide.TypeSystem\Error.cs" />
+ <Compile Include="MonoDevelop.Ide.TypeSystem\MetadataReferenceCache.cs" />
+ <Compile Include="MonoDevelop.Ide.TypeSystem\IFoldingParser.cs" />
+ <Compile Include="MonoDevelop.Ide.TypeSystem\TypeSystemService_WorkspaceHandling.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\Projection\ProjectedSegment.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\Projection\Projection.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\Projection\ProjectedSemanticHighlighting.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\Projection\ProjectedTooltipProvider.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\Projection\ProjectedCompletionExtension.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\Projection\ProjectedDocumentContext.cs" />
+ <Compile Include="MonoDevelop.Ide.CodeCompletion\CompletionCategory.cs" />
+ <Compile Include="MonoDevelop.Ide.CodeCompletion\DisplayFlags.cs" />
+ <Compile Include="MonoDevelop.Ide.CodeCompletion\ParameterHintingResult.cs" />
+ <Compile Include="MonoDevelop.Ide.Tasks\TaskListEntry.cs" />
+ <Compile Include="MonoDevelop.Ide.TypeSystem\AmbienceTooltipProvider.cs" />
+ <Compile Include="MonoDevelop.Components.PropertyGrid.Editors\PropertyTextEditor.cs" />
+ <Compile Include="MonoDevelop.Ide.Tasks\ProjectCommentTags.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\CustomEditorOptions.cs" />
<Compile Include="MonoDevelop.Ide.Projects\NewProjectConfiguration.cs" />
<Compile Include="MonoDevelop.Components\EventBoxTooltip.cs" />
<Compile Include="MonoDevelop.Ide.Templates\ProjectTemplateCreateInformation.cs" />
@@ -3352,6 +3467,10 @@
<Compile Include="MonoDevelop.Components.MainToolbar\StatusBarContextHandler.cs" />
<Compile Include="MonoDevelop.Components.MainToolbar\IButtonBarButton.cs" />
<Compile Include="MonoDevelop.Components.MainToolbar\MainToolbarModels.cs" />
+ <Compile Include="MonoDevelop.Ide.CodeCompletion\MruCache.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\TooltipExtensionNode.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\Projection\IProjectionExtension.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor\Projection\ProjectedFilterCompletionTextEditorExtension.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Makefile.am" />
@@ -3363,6 +3482,7 @@
<None Include="MonoDevelop.Ide.dll.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
+ <None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Target Name="AfterBuild">
@@ -3395,6 +3515,10 @@
<Folder Include="MonoDevelop.Ide.WelcomePage\icons\" />
<Folder Include="MonoDevelop.Ide.TextEditing\" />
<Folder Include="MonoDevelop.Components.DockNotebook\" />
+ <Folder Include="MonoDevelop.Ide.Editor.Util\" />
+ <Folder Include="MonoDevelop.Ide.Editor\Commands\" />
+ <Folder Include="MonoDevelop.Ide.Editor\MessageBubbles\" />
+ <Folder Include="MonoDevelop.Ide.Editor\Projection\" />
<Folder Include="icons\mac\" />
</ItemGroup>
<ItemGroup>
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/DesktopService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/DesktopService.cs
index b8cba9ec3e..8455c21735 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/DesktopService.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/DesktopService.cs
@@ -166,14 +166,7 @@ namespace MonoDevelop.Ide
if (!File.Exists (file))
return false;
- using (var f = File.OpenRead (file)) {
- var buf = new byte[8192];
- var read = f.Read (buf, 0, buf.Length);
- for (int i = 0; i < read; i++)
- if (buf [i] == 0)
- return false;
- }
- return true;
+ return !MonoDevelop.Core.Text.TextFileUtility.IsBinary (file);
}
public async static Task<bool> GetFileIsTextAsync (string file, string mimeType = null)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/HelpOperations.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/HelpOperations.cs
index 166415e254..df86d6de4c 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/HelpOperations.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/HelpOperations.cs
@@ -35,7 +35,6 @@ using MonoDevelop.Core.Execution;
using System.IO;
using MonoDevelop.Core;
using MonoDevelop.Projects;
-using ICSharpCode.NRefactory.Semantics;
namespace MonoDevelop.Ide
{
@@ -227,14 +226,14 @@ namespace MonoDevelop.Ide
}
}
- public bool CanShowHelp (ResolveResult result)
- {
- try {
- return CanShowHelp (HelpService.GetMonoDocHelpUrl (result));
- } catch (Exception e) {
- LoggingService.LogError ("Error while trying to get monodoc help.", e);
- return false;
- }
- }
+// public bool CanShowHelp (ResolveResult result)
+// {
+// try {
+// return CanShowHelp (HelpService.GetMonoDocHelpUrl (result));
+// } catch (Exception e) {
+// LoggingService.LogError ("Error while trying to get monodoc help.", e);
+// return false;
+// }
+// }
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs
index deeb48a636..79f510c135 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs
@@ -223,7 +223,6 @@ namespace MonoDevelop.Ide
// Perser service initialization
TypeSystemService.TrackFileChanges = true;
- TypeSystemService.ParseProgressMonitorFactory = new ParseProgressMonitorFactory ();
Customizer.OnIdeInitialized ();
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs
index 1fd7b88e78..d096632d8e 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs
@@ -53,6 +53,7 @@ using MonoDevelop.Ide.Extensions;
using MonoDevelop.Components.Extensions;
using MonoDevelop.Ide.Desktop;
using System.Threading.Tasks;
+using MonoDevelop.Components;
namespace MonoDevelop.Ide
{
@@ -117,11 +118,11 @@ namespace MonoDevelop.Ide
Xwt.Toolkit.CurrentEngine.RegisterBackend<IExtendedTitleBarDialogBackend,GtkExtendedTitleBarDialogBackend> ();
//default to Windows IME on Windows
- if (Platform.IsWindows && Mono.TextEditor.GtkWorkarounds.GtkMinorVersion >= 16) {
+ if (Platform.IsWindows && GtkWorkarounds.GtkMinorVersion >= 16) {
var settings = Gtk.Settings.Default;
- var val = Mono.TextEditor.GtkWorkarounds.GetProperty (settings, "gtk-im-module");
+ var val = GtkWorkarounds.GetProperty (settings, "gtk-im-module");
if (string.IsNullOrEmpty (val.Val as string))
- Mono.TextEditor.GtkWorkarounds.SetProperty (settings, "gtk-im-module", new GLib.Value ("ime"));
+ GtkWorkarounds.SetProperty (settings, "gtk-im-module", new GLib.Value ("ime"));
}
InternalLog.Initialize ();
@@ -610,6 +611,14 @@ namespace MonoDevelop.Ide
static void HandleException (Exception ex, bool willShutdown)
{
var msg = String.Format ("An unhandled exception has occured. Terminating {0}? {1}", BrandingService.ApplicationName, willShutdown);
+ var aggregateException = ex as AggregateException;
+ if (aggregateException != null) {
+ aggregateException.Flatten ().Handle (innerEx => {
+ HandleException (innerEx, willShutdown);
+ return true;
+ });
+ return;
+ }
if (willShutdown)
LoggingService.LogFatalError (msg, ex);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ImageService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ImageService.cs
index 60e64618c6..2cff1a6d5a 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ImageService.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ImageService.cs
@@ -212,12 +212,12 @@ namespace MonoDevelop.Ide
static Gdk.Pixbuf Get2xIconVariant (Gdk.Pixbuf px)
{
- return Mono.TextEditor.GtkWorkarounds.Get2xVariant (px);
+ return GtkWorkarounds.Get2xVariant (px);
}
static void Set2xIconVariant (Gdk.Pixbuf px, Gdk.Pixbuf variant2x)
{
- Mono.TextEditor.GtkWorkarounds.Set2xVariant (px, variant2x);
+ GtkWorkarounds.Set2xVariant (px, variant2x);
}
static Dictionary<string,Xwt.Drawing.Image> icons = new Dictionary<string, Xwt.Drawing.Image> ();
@@ -489,7 +489,7 @@ namespace MonoDevelop.Ide
Gtk.IconSource source2x = null;
if (Platform.IsWindows) {
- var pixel_scale = Mono.TextEditor.GtkWorkarounds.GetPixelScale ();
+ var pixel_scale = GtkWorkarounds.GetPixelScale ();
source.Pixbuf = pixbuf.ScaleSimple ((int)(pixbuf.Width * pixel_scale), (int)(pixbuf.Height * pixel_scale), Gdk.InterpType.Bilinear);
} else {
source.Pixbuf = pixbuf;
@@ -499,17 +499,17 @@ namespace MonoDevelop.Ide
source.SizeWildcarded = iconSize == Gtk.IconSize.Invalid;
if (pixbuf2x != null) {
- if (Mono.TextEditor.GtkWorkarounds.SetSourceScale (source, 1)) {
- Mono.TextEditor.GtkWorkarounds.SetSourceScaleWildcarded (source, false);
+ if (GtkWorkarounds.SetSourceScale (source, 1)) {
+ GtkWorkarounds.SetSourceScaleWildcarded (source, false);
source2x = new Gtk.IconSource ();
source2x.Pixbuf = pixbuf2x;
source2x.Size = iconSize;
source2x.SizeWildcarded = iconSize == Gtk.IconSize.Invalid;
- Mono.TextEditor.GtkWorkarounds.SetSourceScale (source2x, 2);
- Mono.TextEditor.GtkWorkarounds.SetSourceScaleWildcarded (source2x, false);
+ GtkWorkarounds.SetSourceScale (source2x, 2);
+ GtkWorkarounds.SetSourceScaleWildcarded (source2x, false);
}
} else {
- Mono.TextEditor.GtkWorkarounds.SetSourceScaleWildcarded (source, true);
+ GtkWorkarounds.SetSourceScaleWildcarded (source, true);
}
iconSet.AddSource (source);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/MessageService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/MessageService.cs
index ea4319b4bc..b8d750f1f1 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/MessageService.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/MessageService.cs
@@ -30,6 +30,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
+using MonoDevelop.Components;
using Gtk;
using MonoDevelop.Core;
using MonoDevelop.Components.Extensions;
@@ -374,7 +375,7 @@ namespace MonoDevelop.Ide
else
PlaceDialog (dialog, parent);
#endif
- return Mono.TextEditor.GtkWorkarounds.RunDialogWithNotification (dialog);
+ return GtkWorkarounds.RunDialogWithNotification (dialog);
}
#if MAC
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs
index 660423cc7c..4caf1b5021 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs
@@ -45,18 +45,17 @@ using MonoDevelop.Ide.Gui;
using MonoDevelop.Ide.Projects;
using MonoDevelop.Core.Assemblies;
using MonoDevelop.Core.Instrumentation;
-using Mono.TextEditor;
using System.Diagnostics;
-using ICSharpCode.NRefactory.Documentation;
-using ICSharpCode.NRefactory.TypeSystem.Implementation;
using System.Text;
using MonoDevelop.Ide.TypeSystem;
-using ICSharpCode.NRefactory.TypeSystem;
using System.Threading.Tasks;
using System.Threading;
using ExecutionContext = MonoDevelop.Projects.ExecutionContext;
using MonoDevelop.Ide.Tasks;
using MonoDevelop.Projects.Formats.MSBuild;
+using System.Collections.Immutable;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Core.Text;
namespace MonoDevelop.Ide
{
@@ -231,31 +230,33 @@ namespace MonoDevelop.Ide
return (GetDeclaredFile(item) != null);
}*/
- public bool CanJumpToDeclaration (object element)
+ public bool CanJumpToDeclaration (Microsoft.CodeAnalysis.ISymbol symbol)
{
- if (element is ICSharpCode.NRefactory.TypeSystem.IVariable)
- return true;
- var entity = element as ICSharpCode.NRefactory.TypeSystem.IEntity;
- if (entity == null && element is ICSharpCode.NRefactory.TypeSystem.IType)
- entity = ((ICSharpCode.NRefactory.TypeSystem.IType)element).GetDefinition ();
- if (entity == null)
+ if (symbol == null)
return false;
- if (entity.Region.IsEmpty) {
- var parentAssembly = entity.ParentAssembly;
- if (parentAssembly == null)
- return false;
- return !string.IsNullOrEmpty (parentAssembly.UnresolvedAssembly.Location);
+ switch (symbol.Kind) {
+ case Microsoft.CodeAnalysis.SymbolKind.Local:
+ case Microsoft.CodeAnalysis.SymbolKind.Parameter:
+ case Microsoft.CodeAnalysis.SymbolKind.NamedType:
+ case Microsoft.CodeAnalysis.SymbolKind.Method:
+ case Microsoft.CodeAnalysis.SymbolKind.Field:
+ case Microsoft.CodeAnalysis.SymbolKind.Property:
+ case Microsoft.CodeAnalysis.SymbolKind.Event:
+ case Microsoft.CodeAnalysis.SymbolKind.Label:
+ case Microsoft.CodeAnalysis.SymbolKind.TypeParameter:
+ case Microsoft.CodeAnalysis.SymbolKind.RangeVariable:
+ return true;
}
- return true;
+ return false;
}
- static MonoDevelop.Ide.FindInFiles.SearchResult GetJumpTypePartSearchResult (ICSharpCode.NRefactory.TypeSystem.IUnresolvedTypeDefinition part)
+ static MonoDevelop.Ide.FindInFiles.SearchResult GetJumpTypePartSearchResult (Microsoft.CodeAnalysis.ISymbol part, Microsoft.CodeAnalysis.Location location)
{
- var provider = new MonoDevelop.Ide.FindInFiles.FileProvider (part.Region.FileName);
- var doc = new Mono.TextEditor.TextDocument ();
+ var provider = new MonoDevelop.Ide.FindInFiles.FileProvider (location.SourceTree.FilePath);
+ var doc = TextEditorFactory.CreateNewDocument ();
doc.Text = provider.ReadString ();
- int position = doc.LocationToOffset (part.Region.BeginLine, part.Region.BeginColumn);
- while (position + part.Name.Length < doc.TextLength) {
+ int position = location.SourceSpan.Start;
+ while (position + part.Name.Length < doc.Length) {
if (doc.GetTextAt (position, part.Name.Length) == part.Name)
break;
position++;
@@ -263,67 +264,90 @@ namespace MonoDevelop.Ide
return new MonoDevelop.Ide.FindInFiles.SearchResult (provider, position, part.Name.Length);
}
- public void JumpToDeclaration (ICSharpCode.NRefactory.TypeSystem.INamedElement visitable, bool askIfMultipleLocations = true)
+ public void JumpTo (Microsoft.CodeAnalysis.ISymbol symbol, Microsoft.CodeAnalysis.Location location, Project project = null)
{
- if (askIfMultipleLocations) {
- var type = visitable as ICSharpCode.NRefactory.TypeSystem.IType;
- if (type != null && type.GetDefinition () != null && type.GetDefinition ().Parts.Count > 1) {
- using (var monitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true)) {
- foreach (var part in type.GetDefinition ().Parts)
- monitor.ReportResult (GetJumpTypePartSearchResult (part));
+ if (location == null)
+ return;
+ if (location.IsInMetadata) {
+ string fileName = null;
+ var dn = project as DotNetProject;
+ if (dn == null)
+ return;
+ var metadataDllName = location.MetadataModule.Name;
+ if (metadataDllName == "CommonLanguageRuntimeLibrary")
+ metadataDllName = "corlib.dll";
+ foreach (var assembly in dn.GetReferencedAssemblies (IdeApp.Workspace.ActiveConfiguration)) {
+ if (assembly.IndexOf (metadataDllName) > 0) {
+ fileName = dn.GetAbsoluteChildPath (assembly);
+ break;
}
+ }
+ if (fileName == null)
return;
+ var doc = IdeApp.Workbench.OpenDocument (new FileOpenInformation (fileName, project));
+
+ if (doc != null) {
+ doc.RunWhenLoaded (delegate {
+ var handler = doc.PrimaryView.GetContent<MonoDevelop.Ide.Gui.Content.IOpenNamedElementHandler> ();
+ if (handler != null)
+ handler.Open (symbol);
+ });
}
- }
- JumpToDeclaration (visitable);
+ return;
+ }
+ IdeApp.Workbench.OpenDocument (new FileOpenInformation (location.SourceTree.FilePath, project) {
+ Offset = location.SourceSpan.Start
+ });
}
-
- void JumpToDeclaration (ICSharpCode.NRefactory.TypeSystem.INamedElement element)
+
+ public void JumpToDeclaration (Microsoft.CodeAnalysis.ISymbol symbol, Project project = null, bool askIfMultipleLocations = true)
{
- var entity = element as ICSharpCode.NRefactory.TypeSystem.IEntity;
-
- if (entity == null && element is ICSharpCode.NRefactory.TypeSystem.IType)
- entity = ((ICSharpCode.NRefactory.TypeSystem.IType)element).GetDefinition ();
- if (entity is SpecializedMember)
- entity = ((SpecializedMember)entity).MemberDefinition;
-
- if (entity == null) {
- LoggingService.LogError ("Unknown element:" + element);
+ if (symbol == null)
+ throw new ArgumentNullException ("symbol");
+ var locations = symbol.Locations;
+
+ if (askIfMultipleLocations && locations.Length > 1) {
+ using (var monitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true)) {
+ foreach (var part in locations)
+ monitor.ReportResult (GetJumpTypePartSearchResult (symbol, part));
+ }
return;
}
- string fileName;
- bool isCecilProjectContent = entity.Region.IsEmpty;
- if (isCecilProjectContent) {
- fileName = entity.ParentAssembly.UnresolvedAssembly.Location;
- } else {
- fileName = entity.Region.FileName;
- }
- var project = (entity is ITypeDefinition ? ((ITypeDefinition )entity) : entity.DeclaringTypeDefinition).GetProjectWhereTypeIsDefined ();
- var doc = IdeApp.Workbench.OpenDocument (fileName,
- project,
- entity.Region.BeginLine,
- entity.Region.BeginColumn);
+ JumpTo (symbol, locations.FirstOrDefault (), project);
+ }
- if (isCecilProjectContent && doc != null) {
+ public void JumpToMetadata (string metadataDllName, string documentationCommentId, Project project = null)
+ {
+ if (metadataDllName == null)
+ throw new ArgumentNullException ("metadataDllName");
+ if (documentationCommentId == null)
+ throw new ArgumentNullException ("documentationCommentId");
+ string fileName = metadataDllName;
+ if (metadataDllName == "CommonLanguageRuntimeLibrary")
+ metadataDllName = "corlib.dll";
+ var dn = project as DotNetProject;
+ if (dn != null) {
+ foreach (var assembly in dn.GetReferencedAssemblies (IdeApp.Workspace.ActiveConfiguration)) {
+ if (assembly.IndexOf(metadataDllName, StringComparison.Ordinal) > 0) {
+ fileName = dn.GetAbsoluteChildPath (assembly);
+ break;
+ }
+ }
+ }
+ if (fileName == null || !File.Exists (fileName))
+ return;
+ var doc = IdeApp.Workbench.OpenDocument (new FileOpenInformation (fileName));
+ if (doc != null) {
doc.RunWhenLoaded (delegate {
var handler = doc.PrimaryView.GetContent<MonoDevelop.Ide.Gui.Content.IOpenNamedElementHandler> ();
if (handler != null)
- handler.Open (entity);
+ handler.Open (documentationCommentId);
});
}
}
- public void JumpToDeclaration (ICSharpCode.NRefactory.TypeSystem.IVariable entity)
- {
- if (entity == null)
- throw new ArgumentNullException ("entity");
- string fileName = entity.Region.FileName;
- // variables are always in the same file -> file is already open, project not needed.
- IdeApp.Workbench.OpenDocument (fileName, null, entity.Region.BeginLine, entity.Region.BeginColumn);
- }
-
- public async Task RenameItem (IWorkspaceFileObject item, string newName)
+ public async void RenameItem (IWorkspaceFileObject item, string newName)
{
ProjectOptionsDialog.RenameItem (item, newName);
if (item is SolutionFolderItem) {
@@ -2100,7 +2124,12 @@ namespace MonoDevelop.Ide
return new BackgroundProgressMonitor (GettextCatalog.GetString ("Code completion database generation"), "md-parser");
}
}
-
+
+ public interface ITextFileProvider
+ {
+ ITextDocument GetEditableTextFile (FilePath filePath);
+ }
+
public class TextFileProvider : ITextFileProvider
{
static TextFileProvider instance = new TextFileProvider ();
@@ -2113,101 +2142,19 @@ namespace MonoDevelop.Ide
TextFileProvider ()
{
}
-
- class ProviderProxy : ITextEditorDataProvider, IEditableTextFile
- {
- TextEditorData data;
- string encoding;
- bool bom;
-
- public ProviderProxy (TextEditorData data, string encoding, bool bom)
- {
- this.data = data;
- this.encoding = encoding;
- this.bom = bom;
- }
-
- public TextEditorData GetTextEditorData ()
- {
- return data;
- }
-
- void Save ()
- {
- TextFile.WriteFile (Name, Text, encoding, bom);
- }
-
- #region IEditableTextFile implementation
- public FilePath Name { get { return data.Document.FileName; } }
- public int Length { get { return data.Length; } }
-
- public string GetText (int startPosition, int endPosition)
- {
- return data.GetTextBetween (startPosition, endPosition);
- }
-
- public char GetCharAt (int position)
- {
- return data.GetCharAt (position);
- }
-
- public int GetPositionFromLineColumn (int line, int column)
- {
- return data.Document.LocationToOffset (line, column);
- }
-
- public void GetLineColumnFromPosition (int position, out int line, out int column)
- {
- var loc = data.Document.OffsetToLocation (position);
- line = loc.Line;
- column = loc.Column;
- }
-
- public int InsertText (int position, string text)
- {
- int result = data.Insert (position, text);
- Save ();
-
- return result;
- }
-
- public void DeleteText (int position, int length)
- {
- data.Remove (position, length);
- Save ();
- }
-
- public string Text {
- get {
- return data.Text;
- }
- set {
- data.Text = value;
- Save ();
- }
- }
-
- #endregion
- }
-
- public IEditableTextFile GetEditableTextFile (FilePath filePath)
+ public ITextDocument GetEditableTextFile (FilePath filePath)
{
if (IdeApp.IsInitialized) {
foreach (var doc in IdeApp.Workbench.Documents) {
if (doc.FileName == filePath) {
- IEditableTextFile ef = doc.GetContent<IEditableTextFile> ();
+ var ef = doc.Editor;
if (ef != null) return ef;
}
}
}
-
- TextFile file = TextFile.ReadFile (filePath);
- TextEditorData data = new TextEditorData ();
- data.Document.FileName = filePath;
- data.Text = file.Text;
-
- return new ProviderProxy (data, file.SourceEncoding, file.HadBOM);
+
+ return TextEditorFactory.CreateNewDocument (StringTextSource.ReadFrom (filePath), filePath);
}
/// <summary>
@@ -2216,18 +2163,16 @@ namespace MonoDevelop.Ide
/// <returns><c>true</c>, if file operation was saved, <c>false</c> otherwise.</returns>
/// <param name="filePath">File path.</param>
/// <param name="operation">The operation.</param>
- public bool EditFile (FilePath filePath, Action<TextEditorData> operation)
+ public bool EditFile (FilePath filePath, Action<ITextDocument> operation)
{
if (operation == null)
throw new ArgumentNullException ("operation");
- bool hadBom;
- Encoding encoding;
bool isOpen;
- var data = GetTextEditorData (filePath, out hadBom, out encoding, out isOpen);
+ var data = GetTextEditorData (filePath, out isOpen);
operation (data);
if (!isOpen) {
- try {
- Mono.TextEditor.Utils.TextFileUtility.WriteText (filePath, data.Text, encoding, hadBom);
+ try {
+ data.Save ();
} catch (Exception e) {
LoggingService.LogError ("Error while saving changes to : " + filePath, e);
return false;
@@ -2236,13 +2181,13 @@ namespace MonoDevelop.Ide
return true;
}
- public TextEditorData GetTextEditorData (FilePath filePath)
+ public ITextDocument GetTextEditorData (FilePath filePath)
{
bool isOpen;
return GetTextEditorData (filePath, out isOpen);
}
- public TextEditorData GetReadOnlyTextEditorData (FilePath filePath)
+ public IReadonlyTextDocument GetReadOnlyTextEditorData (FilePath filePath)
{
if (filePath.IsNullOrEmpty)
throw new ArgumentNullException ("filePath");
@@ -2251,42 +2196,26 @@ namespace MonoDevelop.Ide
return doc.Editor;
}
}
- bool hadBom;
- Encoding encoding;
- var text = Mono.TextEditor.Utils.TextFileUtility.ReadAllText (filePath, out hadBom, out encoding);
- var data = new TextEditorData (TextDocument.CreateImmutableDocument (text));
- data.Document.MimeType = DesktopService.GetMimeTypeForUri (filePath);
- data.Document.FileName = filePath;
- data.Text = text;
+ var data = TextEditorFactory.CreateNewReadonlyDocument (StringTextSource.ReadFrom (filePath), filePath);
return data;
}
- public TextEditorData GetTextEditorData (FilePath filePath, out bool isOpen)
- {
- bool hadBom;
- Encoding encoding;
- return GetTextEditorData (filePath, out hadBom, out encoding, out isOpen);
- }
-
- public TextEditorData GetTextEditorData (FilePath filePath, out bool hadBom, out Encoding encoding, out bool isOpen)
+ public ITextDocument GetTextEditorData (FilePath filePath, out bool isOpen)
{
foreach (var doc in IdeApp.Workbench.Documents) {
if (doc.FileName == filePath) {
- var content = doc.GetContent <MonoDevelop.Ide.Gui.Content.IEncodedTextContent> ();
- var theEncoding = content != null ? content.SourceEncoding : null;
-
isOpen = true;
- hadBom = false;
- encoding = theEncoding ?? Encoding.Default;
return doc.Editor;
}
}
-
- var text = Mono.TextEditor.Utils.TextFileUtility.ReadAllText (filePath, out hadBom, out encoding);
- TextEditorData data = new TextEditorData ();
- data.Document.SuppressHighlightUpdate = true;
- data.Document.MimeType = DesktopService.GetMimeTypeForUri (filePath);
- data.Document.FileName = filePath;
+ bool hadBom;
+ Encoding encoding;
+ var text = TextFileUtility.ReadAllText (filePath, out hadBom, out encoding);
+ var data = TextEditorFactory.CreateNewDocument ();
+ data.UseBOM = hadBom;
+ data.Encoding = encoding;
+ data.MimeType = DesktopService.GetMimeTypeForUri (filePath);
+ data.FileName = filePath;
data.Text = text;
isOpen = false;
return data;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs
index 33cf83c704..7bfd13a306 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs
@@ -554,7 +554,7 @@ namespace MonoDevelop.Ide
if (reloading)
SetReloading (false);
}
-
+
using (monitor) {
try {
// Add the item in the GUI thread. It is not safe to do it in the background thread.
@@ -910,6 +910,11 @@ namespace MonoDevelop.Ide
internal void NotifyItemAdded (WorkspaceItem item)
{
+ try {
+ MonoDevelop.Ide.TypeSystem.TypeSystemService.Load (item, null);
+ } catch (Exception ex) {
+ LoggingService.LogError ("Could not load parser database.", ex);
+ }
if (DispatchService.IsGuiThread)
NotifyItemAddedGui (item, IsReloading);
else {
@@ -919,18 +924,9 @@ namespace MonoDevelop.Ide
});
}
}
-
+
void NotifyItemAddedGui (WorkspaceItem item, bool reloading)
{
- try {
-// Mono.Profiler.RuntimeControls.EnableProfiler ();
- MonoDevelop.Ide.TypeSystem.TypeSystemService.Load (item);
-// Mono.Profiler.RuntimeControls.DisableProfiler ();
-// Console.WriteLine ("PARSE LOAD: " + (DateTime.Now - t).TotalMilliseconds);
- } catch (Exception ex) {
- LoggingService.LogError ("Could not load parser database.", ex);
- }
-
Workspace ws = item as Workspace;
if (ws != null) {
ws.DescendantItemAdded += NotifyDescendantItemAdded;
@@ -982,10 +978,8 @@ namespace MonoDevelop.Ide
if (LastWorkspaceItemClosed != null)
LastWorkspaceItemClosed (this, EventArgs.Empty);
}
-
MonoDevelop.Ide.TypeSystem.TypeSystemService.Unload (item);
-// ParserDatabase.Unload (item);
-
+
NotifyDescendantItemRemoved (this, args);
}
@@ -1223,7 +1217,7 @@ namespace MonoDevelop.Ide
/// once for the workspace, and once for each solution.
/// </remarks>
public event EventHandler<WorkspaceItemEventArgs> WorkspaceItemLoaded;
-
+
/// <summary>
/// Fired when a workspace item (a solution or workspace) is unloaded
/// </summary>
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Services.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Services.cs
index bdc908fc2d..8be5d967a0 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Services.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Services.cs
@@ -53,6 +53,7 @@ namespace MonoDevelop.Ide
internal static TimerCounter OpenDocumentTimer = InstrumentationService.CreateTimerCounter ("Document opened", "IDE");
internal static TimerCounter DocumentOpened = InstrumentationService.CreateTimerCounter ("Document opened", "IDE", id:"Ide.Shell.DocumentOpened");
internal static TimerCounter BuildItemTimer = InstrumentationService.CreateTimerCounter ("Project/Solution built in the IDE", "IDE");
+ internal static Counter AutoSavedFiles = InstrumentationService.CreateCounter ("Autosaved Files", "Text Editor");
internal static Counter PadShown = InstrumentationService.CreateCounter ("Pad focused", "IDE", id:"Ide.Shell.PadShown");
internal static class ParserService {
diff --git a/main/src/core/MonoDevelop.Ide/packages.config b/main/src/core/MonoDevelop.Ide/packages.config
new file mode 100644
index 0000000000..0b521ddcb5
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/packages.config
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="Microsoft.CodeAnalysis.Common" version="1.0.0.0-beta2" targetFramework="net45" />
+ <package id="Microsoft.CodeAnalysis.CSharp" version="1.0.0.0-beta2" targetFramework="net45" />
+ <package id="Microsoft.CodeAnalysis.CSharp.Workspaces" version="1.0.0.0-beta2" targetFramework="net45" />
+ <package id="Microsoft.CodeAnalysis.Workspaces.Common" version="1.0.0.0-beta2" targetFramework="net45" />
+ <package id="Microsoft.Composition" version="1.0.27" targetFramework="net45" />
+ <package id="System.Collections.Immutable" version="1.1.33-beta" targetFramework="net45" />
+ <package id="System.Reflection.Metadata" version="1.0.18-beta" targetFramework="net45" />
+</packages> \ No newline at end of file