Browse Source

Refactored parser service.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
ab95b18a3f
  1. 2
      SharpDevelop.sln
  2. 13
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpSemanticHighlighter.cs
  3. 8
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionBinding.cs
  4. 3
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingStrategy.cs
  5. 6
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/CSharpSymbolSearch.cs
  6. 19
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/Parser.cs
  7. 2
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/CSharpMyNamespaceBuilder.cs
  8. 7
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/IssueManager.cs
  9. 3
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDScript.cs
  10. 7
      src/AddIns/BackendBindings/CSharpBinding/Tests/MockTextEditor.cs
  11. 1
      src/AddIns/BackendBindings/CppBinding/CppBinding/CppBinding.csproj
  12. 44
      src/AddIns/BackendBindings/CppBinding/CppBinding/Project/DependencyRelation.cs
  13. 160
      src/AddIns/BackendBindings/CppBinding/CppBinding/Project/MultiDictionary.cs
  14. 5
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlOutlineContentHost.xaml.cs
  15. 15
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlParser.cs
  16. 5
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlSymbolSearch.cs
  17. 4
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditViewContent.cs
  18. 10
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs
  19. 2
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs
  20. 4
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActions/EditorActionsProvider.cs
  21. 4
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/DefaultChangeWatcher.cs
  22. 2
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.cs
  23. 2
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/CodeSnippet.cs
  24. 4
      src/AddIns/VersionControl/GitAddIn/Src/OverlayIconManager.cs
  25. 4
      src/AddIns/VersionControl/SubversionAddIn/Src/Gui/ProjectBrowserVisitor/OverlayIconManager.cs
  26. 30
      src/Main/Base/Project/ICSharpCode.SharpDevelop.addin
  27. 13
      src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
  28. 2
      src/Main/Base/Project/Src/Editor/Commands/SymbolUnderCaretMenuCommand.cs
  29. 3
      src/Main/Base/Project/Src/Editor/IDocumentBaseVersionProvider.cs
  30. 2
      src/Main/Base/Project/Src/Editor/ToolTipRequestEventArgs.cs
  31. 6
      src/Main/Base/Project/Src/Gui/Dialogs/GotoDialog.cs
  32. 3
      src/Main/Base/Project/Src/Gui/Dialogs/NewFileDialog.cs
  33. 5
      src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/IDEOptions/TaskListOptionsl.xaml.cs
  34. 2
      src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/GacReferencePanel.cs
  35. 4
      src/Main/Base/Project/Src/Gui/Dialogs/WordCountDialog.cs
  36. 5
      src/Main/Base/Project/Src/Gui/IWorkbench.cs
  37. 7
      src/Main/Base/Project/Src/Gui/Pads/DefinitionViewPad.cs
  38. 4
      src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/Commands/ReferenceFolderNodeCommands.cs
  39. 2
      src/Main/Base/Project/Src/Gui/Pads/PropertyPad/PropertyPad.cs
  40. 6
      src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskListPad.cs
  41. 5
      src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskListPadCommands.cs
  42. 72
      src/Main/Base/Project/Src/Gui/WorkbenchSingleton.cs
  43. 2
      src/Main/Base/Project/Src/Internal/Templates/Project/ProjectDescriptor.cs
  44. 11
      src/Main/Base/Project/Src/Project/AbstractProject.cs
  45. 13
      src/Main/Base/Project/Src/Project/CompilableProject.cs
  46. 2
      src/Main/Base/Project/Src/Project/CustomTool.cs
  47. 12
      src/Main/Base/Project/Src/Project/IProject.cs
  48. 3
      src/Main/Base/Project/Src/Project/ProjectChangeWatcher.cs
  49. 10
      src/Main/Base/Project/Src/Refactoring/EditorRefactoringContext.cs
  50. 3
      src/Main/Base/Project/Src/Services/File/FileChangeWatcher.cs
  51. 6
      src/Main/Base/Project/Src/Services/File/FileService.cs
  52. 55
      src/Main/Base/Project/Src/Services/File/IFileService.cs
  53. 4
      src/Main/Base/Project/Src/Services/File/OpenedFile.cs
  54. 93
      src/Main/Base/Project/Src/Services/IMessageLoop.cs
  55. 2
      src/Main/Base/Project/Src/Services/NavigationService/NavigationService.cs
  56. 11
      src/Main/Base/Project/Src/Services/ParserService/DomAssemblyName.cs
  57. 30
      src/Main/Base/Project/Src/Services/ParserService/IGlobalAssemblyCacheService.cs
  58. 23
      src/Main/Base/Project/Src/Services/ParserService/IParser.cs
  59. 291
      src/Main/Base/Project/Src/Services/ParserService/IParserService.cs
  60. 13
      src/Main/Base/Project/Src/Services/ParserService/ParseInformationEventArgs.cs
  61. 44
      src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs
  62. 18
      src/Main/Base/Project/Src/Services/ParserService/ParsedFileListener.cs
  63. 1026
      src/Main/Base/Project/Src/Services/ParserService/ParserService.cs
  64. 6
      src/Main/Base/Project/Src/Services/ProjectService/ParseableFileContentFinder.cs
  65. 4
      src/Main/Base/Project/Src/Services/ProjectService/ProjectService.cs
  66. 35
      src/Main/Base/Project/Src/Services/RefactoringService/FindReferenceService.cs
  67. 19
      src/Main/Base/Project/Src/Services/RefactoringService/FindReferencesAndRenameHelper.cs
  68. 18
      src/Main/Base/Project/Src/Services/SD.cs
  69. 6
      src/Main/Base/Project/Src/Services/Tasks/TaskService.cs
  70. 2
      src/Main/Base/Project/Src/Util/ExtensionMethods.cs
  71. 115
      src/Main/Base/Project/Src/Util/MultiDictionary.cs
  72. 16
      src/Main/Base/Project/Src/Util/ReactiveExtensions.cs
  73. 112
      src/Main/Base/Project/Src/Util/WorkerThread.cs
  74. 120
      src/Main/Base/Project/Src/Util/WpfSynchronizeInvoke.cs
  75. 0
      src/Main/SharpDevelop/Parser/Fusion.cs
  76. 28
      src/Main/SharpDevelop/Parser/GlobalAssemblyCacheService.cs
  77. 2
      src/Main/SharpDevelop/Parser/ParserDescriptor.cs
  78. 2
      src/Main/SharpDevelop/Parser/ParserDoozer.cs
  79. 359
      src/Main/SharpDevelop/Parser/ParserService.cs
  80. 330
      src/Main/SharpDevelop/Parser/ParserServiceEntry.cs
  81. 2
      src/Main/SharpDevelop/Sda/CallHelper.cs
  82. 45
      src/Main/SharpDevelop/SharpDevelop.csproj
  83. 2
      src/Main/SharpDevelop/Startup/App.xaml
  84. 2
      src/Main/SharpDevelop/Startup/App.xaml.cs
  85. 4
      src/Main/SharpDevelop/Startup/SharpDevelopMain.cs
  86. 2
      src/Main/SharpDevelop/Startup/SplashScreen.cs
  87. 3
      src/Main/SharpDevelop/Workbench/AvalonDockLayout.cs
  88. 3
      src/Main/SharpDevelop/Workbench/AvalonPadContent.cs
  89. 3
      src/Main/SharpDevelop/Workbench/AvalonWorkbenchWindow.cs
  90. 7
      src/Main/SharpDevelop/Workbench/ChooseLayoutCommand.cs
  91. 146
      src/Main/SharpDevelop/Workbench/DispatcherMessageLoop.cs
  92. 61
      src/Main/SharpDevelop/Workbench/FileService.cs
  93. 2
      src/Main/SharpDevelop/Workbench/FullScreenEnabledWindow.cs
  94. 9
      src/Main/SharpDevelop/Workbench/LayoutConfiguration.cs
  95. 3
      src/Main/SharpDevelop/Workbench/SDStatusBar.cs
  96. 15
      src/Main/SharpDevelop/Workbench/SingleInstanceHelper.cs
  97. 5
      src/Main/SharpDevelop/Workbench/StatusBarService.cs
  98. 20
      src/Main/SharpDevelop/Workbench/WorkbenchStartup.cs
  99. 29
      src/Main/SharpDevelop/Workbench/WpfWorkbench.cs
  100. 8
      src/Main/SharpDevelop/Workbench/WpfWorkbench.xaml

2
SharpDevelop.sln

@ -1,7 +1,7 @@
 
Microsoft Visual Studio Solution File, Format Version 11.00 Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010 # Visual Studio 2010
# SharpDevelop 4.2.0.8695-Beta 2 # SharpDevelop 4.2.0.8707-Beta 2
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Main", "Main", "{256F5C28-532C-44C0-8AB8-D8EC5E492E01}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Main", "Main", "{256F5C28-532C-44C0-8AB8-D8EC5E492E01}"
ProjectSection(SolutionItems) = postProject ProjectSection(SolutionItems) = postProject
EndProjectSection EndProjectSection

13
src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpSemanticHighlighter.cs

@ -14,6 +14,7 @@ using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Parser; using ICSharpCode.SharpDevelop.Parser;
@ -60,15 +61,15 @@ namespace CSharpBinding
this.valueKeywordColor = highlightingDefinition.GetNamedColor("NullOrValueKeywords"); this.valueKeywordColor = highlightingDefinition.GetNamedColor("NullOrValueKeywords");
this.parameterModifierColor = highlightingDefinition.GetNamedColor("ParameterModifiers"); this.parameterModifierColor = highlightingDefinition.GetNamedColor("ParameterModifiers");
ParserService.ParseInformationUpdated += ParserService_ParseInformationUpdated; SD.ParserService.ParseInformationUpdated += ParserService_ParseInformationUpdated;
ParserService.LoadSolutionProjectsThreadEnded += ParserService_LoadSolutionProjectsThreadEnded; SD.ParserService.LoadSolutionProjectsThreadEnded += ParserService_LoadSolutionProjectsThreadEnded;
syntaxHighlighter.VisibleDocumentLinesChanged += syntaxHighlighter_VisibleDocumentLinesChanged; syntaxHighlighter.VisibleDocumentLinesChanged += syntaxHighlighter_VisibleDocumentLinesChanged;
} }
public void Dispose() public void Dispose()
{ {
ParserService.ParseInformationUpdated -= ParserService_ParseInformationUpdated; SD.ParserService.ParseInformationUpdated -= ParserService_ParseInformationUpdated;
ParserService.LoadSolutionProjectsThreadEnded -= ParserService_LoadSolutionProjectsThreadEnded; SD.ParserService.LoadSolutionProjectsThreadEnded -= ParserService_LoadSolutionProjectsThreadEnded;
syntaxHighlighter.VisibleDocumentLinesChanged -= syntaxHighlighter_VisibleDocumentLinesChanged; syntaxHighlighter.VisibleDocumentLinesChanged -= syntaxHighlighter_VisibleDocumentLinesChanged;
} }
#endregion #endregion
@ -202,7 +203,7 @@ namespace CSharpBinding
return cachedLine.HighlightedLine; return cachedLine.HighlightedLine;
} }
var parseInfo = ParserService.GetCachedParseInformation(textEditor.FileName, textEditor.Document.Version) as CSharpFullParseInformation; var parseInfo = SD.ParserService.GetCachedParseInformation(textEditor.FileName, textEditor.Document.Version) as CSharpFullParseInformation;
if (parseInfo == null) { if (parseInfo == null) {
if (!invalidLines.Contains(documentLine)) if (!invalidLines.Contains(documentLine))
invalidLines.Add(documentLine); invalidLines.Add(documentLine);
@ -218,7 +219,7 @@ namespace CSharpBinding
} }
} }
var compilation = ParserService.GetCompilationForFile(parseInfo.FileName); var compilation = SD.ParserService.GetCompilationForFile(parseInfo.FileName);
this.resolver = parseInfo.GetResolver(compilation); this.resolver = parseInfo.GetResolver(compilation);
HighlightedLine line = new HighlightedLine(textEditor.Document, documentLine); HighlightedLine line = new HighlightedLine(textEditor.Document, documentLine);

8
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionBinding.cs

@ -4,11 +4,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using CSharpBinding.Parser; using CSharpBinding.Parser;
using ICSharpCode.NRefactory.Completion; using ICSharpCode.NRefactory.Completion;
using ICSharpCode.NRefactory.CSharp.Completion; using ICSharpCode.NRefactory.CSharp.Completion;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Editor.CodeCompletion; using ICSharpCode.SharpDevelop.Editor.CodeCompletion;
using ICSharpCode.SharpDevelop.Parser; using ICSharpCode.SharpDevelop.Parser;
@ -38,13 +38,13 @@ namespace CSharpBinding.Completion
bool ShowCompletion(ITextEditor editor, char completionChar, bool ctrlSpace) bool ShowCompletion(ITextEditor editor, char completionChar, bool ctrlSpace)
{ {
// Don't require the very latest parse information, an older cached version is OK. // Don't require the very latest parse information, an older cached version is OK.
var parseInfo = ParserService.GetCachedParseInformation(editor.FileName) as CSharpFullParseInformation; var parseInfo = SD.ParserService.GetCachedParseInformation(editor.FileName) as CSharpFullParseInformation;
if (parseInfo == null) { if (parseInfo == null) {
parseInfo = ParserService.Parse(editor.FileName, editor.Document) as CSharpFullParseInformation; parseInfo = SD.ParserService.Parse(editor.FileName, editor.Document) as CSharpFullParseInformation;
if (parseInfo == null) if (parseInfo == null)
return false; return false;
} }
ICompilation compilation = ParserService.GetCompilationForFile(editor.FileName); ICompilation compilation = SD.ParserService.GetCompilationForFile(editor.FileName);
var pc = compilation.MainAssembly.UnresolvedAssembly as IProjectContent; var pc = compilation.MainAssembly.UnresolvedAssembly as IProjectContent;
if (pc == null) if (pc == null)
return false; return false;

3
src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingStrategy.cs

@ -9,6 +9,7 @@ using ICSharpCode.AvalonEdit.Indentation.CSharp;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Parser; using ICSharpCode.SharpDevelop.Parser;
@ -180,7 +181,7 @@ namespace CSharpBinding.FormattingStrategy
FileName fileName = editor.FileName; FileName fileName = editor.FileName;
IUnresolvedEntity nextElement = null; IUnresolvedEntity nextElement = null;
if (fileName != null) { if (fileName != null) {
IParsedFile parsedFile = ParserService.ParseFile(fileName, editor.Document.CreateSnapshot()); IParsedFile parsedFile = SD.ParserService.ParseFile(fileName, editor.Document);
if (parsedFile != null) { if (parsedFile != null) {
var currentClass = parsedFile.GetInnermostTypeDefinition(caretLine, 0); var currentClass = parsedFile.GetInnermostTypeDefinition(caretLine, 0);
int nextElementLine = int.MaxValue; int nextElementLine = int.MaxValue;

6
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/CSharpSymbolSearch.cs

@ -8,7 +8,6 @@ using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using CSharpBinding.Parser; using CSharpBinding.Parser;
using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.Core; using ICSharpCode.Core;
@ -19,6 +18,7 @@ using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Utils; using ICSharpCode.NRefactory.Utils;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor.Search; using ICSharpCode.SharpDevelop.Editor.Search;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Parser; using ICSharpCode.SharpDevelop.Parser;
@ -44,7 +44,7 @@ namespace CSharpBinding
{ {
this.project = project; this.project = project;
searchScopes = fr.GetSearchScopes(entity); searchScopes = fr.GetSearchScopes(entity);
compilation = ParserService.GetCompilation(project); compilation = SD.ParserService.GetCompilation(project);
interestingFileNames = new IList<string>[searchScopes.Count]; interestingFileNames = new IList<string>[searchScopes.Count];
for (int i = 0; i < searchScopes.Count; i++) { for (int i = 0; i < searchScopes.Count; i++) {
interestingFileNames[i] = fr.GetInterestingFiles(searchScopes[i], compilation).Select(f => f.FileName).ToList(); interestingFileNames[i] = fr.GetInterestingFiles(searchScopes[i], compilation).Select(f => f.FileName).ToList();
@ -93,7 +93,7 @@ namespace CSharpBinding
return; return;
} }
var parseInfo = ParserService.Parse(fileName, textSource) as CSharpFullParseInformation; var parseInfo = SD.ParserService.Parse(fileName, textSource) as CSharpFullParseInformation;
if (parseInfo == null) if (parseInfo == null)
return; return;
ReadOnlyDocument document = null; ReadOnlyDocument document = null;

19
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/Parser.cs

@ -28,17 +28,7 @@ namespace CSharpBinding.Parser
{ {
public class TParser : IParser public class TParser : IParser
{ {
///<summary>IParser Interface</summary> public IReadOnlyList<string> TaskListTokens { get; set; }
string[] lexerTags;
public string[] LexerTags {
get {
return lexerTags;
}
set {
lexerTags = value;
}
}
public bool CanParse(string fileName) public bool CanParse(string fileName)
{ {
@ -77,7 +67,8 @@ namespace CSharpBinding.Parser
} }
*/ */
public ParseInformation Parse(FileName fileName, ITextSource fileContent, bool fullParseInformationRequested) public ParseInformation Parse(FileName fileName, ITextSource fileContent, bool fullParseInformationRequested,
IProject parentProject, CancellationToken cancellationToken)
{ {
CSharpParser parser = new CSharpParser(); CSharpParser parser = new CSharpParser();
parser.GenerateTypeSystemMode = !fullParseInformationRequested; parser.GenerateTypeSystemMode = !fullParseInformationRequested;
@ -102,7 +93,7 @@ namespace CSharpBinding.Parser
ReadOnlyDocument document = null; ReadOnlyDocument document = null;
foreach (var comment in cu.Descendants.OfType<Comment>().Where(c => c.CommentType != CommentType.InactiveCode)) { foreach (var comment in cu.Descendants.OfType<Comment>().Where(c => c.CommentType != CommentType.InactiveCode)) {
int matchLength; int matchLength;
int index = comment.Content.IndexOfAny(lexerTags, 0, out matchLength); int index = comment.Content.IndexOfAny(TaskListTokens, 0, out matchLength);
if (index > -1) { if (index > -1) {
if (document == null) if (document == null)
document = new ReadOnlyDocument(fileContent); document = new ReadOnlyDocument(fileContent);
@ -115,7 +106,7 @@ namespace CSharpBinding.Parser
int endOffset = Math.Min(document.GetLineByNumber(startLocation.Line).EndOffset, document.GetOffset(comment.EndLocation) - commentEndSignLength); int endOffset = Math.Min(document.GetLineByNumber(startLocation.Line).EndOffset, document.GetOffset(comment.EndLocation) - commentEndSignLength);
string content = document.GetText(absoluteOffset, endOffset - absoluteOffset); string content = document.GetText(absoluteOffset, endOffset - absoluteOffset);
tagComments.Add(new TagComment(content.Substring(0, matchLength), new DomRegion(cu.FileName, startLocation.Line, startLocation.Column), content.Substring(matchLength))); tagComments.Add(new TagComment(content.Substring(0, matchLength), new DomRegion(cu.FileName, startLocation.Line, startLocation.Column), content.Substring(matchLength)));
index = comment.Content.IndexOfAny(lexerTags, endOffset - startOffset - commentSignLength, out matchLength); index = comment.Content.IndexOfAny(TaskListTokens, endOffset - startOffset - commentSignLength, out matchLength);
} while (index > -1); } while (index > -1);
} }
} }

2
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/CSharpMyNamespaceBuilder.cs

@ -63,7 +63,7 @@ namespace CSharpBinding
continue; continue;
} }
if (trimmedLine == "/*LIST OF FORMS*/") { if (trimmedLine == "/*LIST OF FORMS*/") {
var compilation = ParserService.GetCompilation(vbProject); var compilation = SD.ParserService.GetCompilation(vbProject);
ITypeDefinition myFormsClass = FindMyFormsClass(compilation.MainAssembly, ns); ITypeDefinition myFormsClass = FindMyFormsClass(compilation.MainAssembly, ns);
if (myFormsClass != null) { if (myFormsClass != null) {
string indentation = line.Substring(0, line.Length - trimmedLine.Length); string indentation = line.Substring(0, line.Length - trimmedLine.Length);

7
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/IssueManager.cs

@ -15,6 +15,7 @@ using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Refactoring; using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.Editor;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Parser; using ICSharpCode.SharpDevelop.Parser;
@ -90,14 +91,14 @@ namespace CSharpBinding.Refactoring
{ {
this.editor = editor; this.editor = editor;
this.markerService = editor.GetService(typeof(ITextMarkerService)) as ITextMarkerService; this.markerService = editor.GetService(typeof(ITextMarkerService)) as ITextMarkerService;
ParserService.ParserUpdateStepFinished += ParserService_ParserUpdateStepFinished; //SD.ParserService.ParserUpdateStepFinished += ParserService_ParserUpdateStepFinished;
editor.ContextActionProviders.Add(this); editor.ContextActionProviders.Add(this);
} }
public void Dispose() public void Dispose()
{ {
editor.ContextActionProviders.Remove(this); editor.ContextActionProviders.Remove(this);
ParserService.ParserUpdateStepFinished -= ParserService_ParserUpdateStepFinished; //SD.ParserService.ParserUpdateStepFinished -= ParserService_ParserUpdateStepFinished;
if (cancellationTokenSource != null) if (cancellationTokenSource != null)
cancellationTokenSource.Cancel(); cancellationTokenSource.Cancel();
Clear(); Clear();
@ -243,7 +244,7 @@ namespace CSharpBinding.Refactoring
try { try {
await Task.Run( await Task.Run(
delegate { delegate {
var compilation = ParserService.GetCompilationForFile(parseInfo.FileName); var compilation = SD.ParserService.GetCompilationForFile(parseInfo.FileName);
var resolver = parseInfo.GetResolver(compilation); var resolver = parseInfo.GetResolver(compilation);
var context = new SDRefactoringContext(textSource, resolver, new TextLocation(0, 0), 0, 0, cancellationToken); var context = new SDRefactoringContext(textSource, resolver, new TextLocation(0, 0), 0, 0, cancellationToken);
foreach (var issueProvider in issueProviders.Value) { foreach (var issueProvider in issueProviders.Value) {

3
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDScript.cs

@ -10,6 +10,7 @@ using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Refactoring; using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Parser; using ICSharpCode.SharpDevelop.Parser;
@ -41,7 +42,7 @@ namespace CSharpBinding.Refactoring
public override void FormatText(AstNode node) public override void FormatText(AstNode node)
{ {
var parseInfo = ParserService.Parse(editor.FileName, editor.Document) as CSharpFullParseInformation; var parseInfo = SD.ParserService.Parse(editor.FileName, editor.Document) as CSharpFullParseInformation;
if (parseInfo != null) { if (parseInfo != null) {
//var startLocation = editor.Document.GetLocation(offset); //var startLocation = editor.Document.GetLocation(offset);
//var endLocation = editor.Document.GetLocation(offset + length); //var endLocation = editor.Document.GetLocation(offset + length);

7
src/AddIns/BackendBindings/CSharpBinding/Tests/MockTextEditor.cs

@ -1,6 +1,7 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System.Threading;
using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Highlighting;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -27,18 +28,16 @@ namespace CSharpBinding.Tests
public MockTextEditor() public MockTextEditor()
: base(new TextEditor()) : base(new TextEditor())
{ {
PropertyService.InitializeServiceForUnitTests();
} }
public override FileName FileName { public override FileName FileName {
get { return new FileName("mockFileName.cs"); } get { return new FileName("mockFileName.cs"); }
} }
public void CreateParseInformation() public ParseInformation CreateParseInformation()
{ {
var parser = new CSharpBinding.Parser.TParser(); var parser = new CSharpBinding.Parser.TParser();
var parseInfo = parser.Parse(this.FileName, this.Document, true); return parser.Parse(this.FileName, this.Document, true, null, CancellationToken.None);
ParserService.RegisterParseInformation(parseInfo.FileName, parseInfo, parser);
} }
ICompletionItemList lastCompletionItemList; ICompletionItemList lastCompletionItemList;

1
src/AddIns/BackendBindings/CppBinding/CppBinding/CppBinding.csproj

@ -71,7 +71,6 @@
<Compile Include="CppFormattingStrategy.cs" /> <Compile Include="CppFormattingStrategy.cs" />
<Compile Include="CppLanguageBinding.cs" /> <Compile Include="CppLanguageBinding.cs" />
<Compile Include="Project\DependencyRelation.cs" /> <Compile Include="Project\DependencyRelation.cs" />
<Compile Include="Project\MultiDictionary.cs" />
<Compile Include="Project\ApplicationOptions.cs"> <Compile Include="Project\ApplicationOptions.cs">
<SubType>UserControl</SubType> <SubType>UserControl</SubType>
</Compile> </Compile>

44
src/AddIns/BackendBindings/CppBinding/CppBinding/Project/DependencyRelation.cs

@ -3,9 +3,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Diagnostics;
using ICSharpCode.SharpDevelop;
namespace ICSharpCode.CppBinding.Project namespace ICSharpCode.CppBinding.Project
{ {
@ -18,13 +20,14 @@ namespace ICSharpCode.CppBinding.Project
: this(new MultiDictionary<T1, T2>()) : this(new MultiDictionary<T1, T2>())
{ } { }
public DependencyRelation(IMultiDictionary<T1, T2> innerDep) public DependencyRelation(MultiDictionary<T1, T2> innerDep)
{ {
dep = innerDep; dep = innerDep;
revDep = new MultiDictionary<T2, T1>(); revDep = new MultiDictionary<T2, T1>();
foreach (KeyValuePair<T1, T2> item in dep) foreach (var group in dep)
revDep.Add(item.Value, item.Key); foreach (var value in group)
revDep.Add(value, group.Key);
} }
/// <summary> /// <summary>
@ -53,11 +56,9 @@ namespace ICSharpCode.CppBinding.Project
/// Returns a list of items given element directly depend on. /// Returns a list of items given element directly depend on.
/// If there is no element in the dependency relation, returns an empty list. /// If there is no element in the dependency relation, returns an empty list.
/// </summary> /// </summary>
public IList<T2> DependOn(T1 element) public IReadOnlyList<T2> DependOn(T1 element)
{ {
if (dep.ContainsKey(element)) return dep[element];
return dep[element];
return new List<T2>();
} }
/// <summary> /// <summary>
@ -83,11 +84,9 @@ namespace ICSharpCode.CppBinding.Project
/// If the is no item that depend on given element, returns an empty list. /// If the is no item that depend on given element, returns an empty list.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public IList<T1> DependingOn(T2 element) public IReadOnlyList<T1> DependingOn(T2 element)
{ {
if (revDep.ContainsKey(element)) return revDep[element];
return revDep[element];
return new List<T1>();
} }
/// <summary> /// <summary>
@ -108,7 +107,7 @@ namespace ICSharpCode.CppBinding.Project
return DependencyTree(revDep, element).Cast<T1>(); return DependencyTree(revDep, element).Cast<T1>();
} }
IEnumerable<T> DependencyTree<T, U>(IMultiDictionary<T, U> rel, T startItem) IEnumerable<T> DependencyTree<T, U>(MultiDictionary<T, U> rel, T startItem)
{ {
HashSet<T> visited = new HashSet<T>(); HashSet<T> visited = new HashSet<T>();
Stack<T> pendingItems = new Stack<T>(); Stack<T> pendingItems = new Stack<T>();
@ -117,21 +116,20 @@ namespace ICSharpCode.CppBinding.Project
while (pendingItems.Count > 0) while (pendingItems.Count > 0)
{ {
T currentItem = pendingItems.Pop(); T currentItem = pendingItems.Pop();
if (rel.ContainsKey(currentItem)) foreach (T depend in rel[currentItem].Cast<T>())
foreach (T depend in rel[currentItem].Cast<T>()) if (!visited.Contains(depend))
if (!visited.Contains(depend)) {
{ visited.Add(depend);
visited.Add(depend); pendingItems.Push(depend);
pendingItems.Push(depend); yield return depend;
yield return depend; }
}
} }
} }
//dependency relation //dependency relation
IMultiDictionary<T1, T2> dep; MultiDictionary<T1, T2> dep;
//reverse dependency relation //reverse dependency relation
IMultiDictionary<T2, T1> revDep; MultiDictionary<T2, T1> revDep;
} }
} }

160
src/AddIns/BackendBindings/CppBinding/CppBinding/Project/MultiDictionary.cs

@ -1,160 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
namespace ICSharpCode.CppBinding.Project
{
public interface IMultiDictionary<TKey, TValue> : ICollection<KeyValuePair<TKey, TValue>>
{
void Add(TKey key, TValue value);
bool Contains(TKey key, TValue value);
bool ContainsKey(TKey key);
bool Remove(TKey key, TValue value);
IList<TValue> this[TKey key] { get; }
}
/// <summary>
/// A dictionary that allows multiple pairs with the same key.
/// </summary>
public class MultiDictionary<TKey, TValue> : IMultiDictionary<TKey,TValue>
{
public MultiDictionary()
: this(new Dictionary<TKey, IList<TValue>>())
{ }
public MultiDictionary(IDictionary<TKey, IList<TValue>> innerDictionary)
{
if (innerDictionary == null)
throw new ArgumentNullException("innerDictionary");
dict = innerDictionary;
count = CountElements(dict);
}
IDictionary<TKey, IList<TValue>> dict;
int count;
public void Add(TKey key, TValue value)
{
IList<TValue> valueList;
if (!dict.TryGetValue(key, out valueList))
{
valueList = new List<TValue>();
dict.Add(key, valueList);
}
valueList.Add(value);
count++;
}
public bool Contains(TKey key, TValue value)
{
IList<TValue> valueList;
if (!dict.TryGetValue(key, out valueList))
return false;
return valueList.Contains(value);
}
public bool ContainsKey(TKey key)
{
return dict.ContainsKey(key);
}
public bool Remove(TKey key, TValue value)
{
IList<TValue> valueList;
if (!dict.TryGetValue(key, out valueList))
return false;
return valueList.Remove(value);
}
public IList<TValue> this[TKey key]
{
get
{
return new ReadOnlyCollection<TValue>(dict[key]);
}
}
#region ICollection<KeyValuePair<TKey,TValue>> Members
public void Add(KeyValuePair<TKey, TValue> item)
{
Add(item.Key, item.Value);
}
public void Clear()
{
dict.Clear();
count = 0;
}
public bool Contains(KeyValuePair<TKey, TValue> item)
{
return Contains(item.Key, item.Value);
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
if (array == null)
throw new ArgumentNullException("array");
if (arrayIndex < 0)
throw new ArgumentOutOfRangeException("arrayIndex");
if (array.Rank != 1)
throw new ArgumentException("Array is multidimensional", "array");
if (arrayIndex + count >= array.Length)
throw new ArgumentException("Array is to small", "array");
foreach (KeyValuePair<TKey, IList<TValue>> item in dict)
foreach (TValue value in item.Value)
array[arrayIndex++] = new KeyValuePair<TKey, TValue>(item.Key, value);
}
public int Count
{
get { return count; }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(KeyValuePair<TKey, TValue> item)
{
return Remove(item.Key, item.Value);
}
#endregion
#region IEnumerable<KeyValuePair<TKey,TValue>> Members
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
foreach (KeyValuePair<TKey, IList<TValue>> item in dict)
foreach (TValue value in item.Value)
yield return new KeyValuePair<TKey, TValue>(item.Key, value);
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
static int CountElements(IDictionary<TKey, IList<TValue>> dict)
{
int count = 0;
foreach (KeyValuePair<TKey, IList<TValue>> item in dict)
count += item.Value.Count;
return count;
}
}
}

5
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlOutlineContentHost.xaml.cs

@ -27,7 +27,7 @@ namespace ICSharpCode.XamlBinding
InitializeComponent(); InitializeComponent();
ParserService.ParseInformationUpdated += ParseInfoUpdated; SD.ParserService.ParseInformationUpdated += ParseInfoUpdated;
} }
void ParseInfoUpdated(object sender, ParseInformationEventArgs e) void ParseInfoUpdated(object sender, ParseInformationEventArgs e)
@ -35,6 +35,7 @@ namespace ICSharpCode.XamlBinding
if (this.editor == null || !FileUtility.IsEqualFileName(this.editor.FileName, e.FileName)) if (this.editor == null || !FileUtility.IsEqualFileName(this.editor.FileName, e.FileName))
return; return;
#warning Reimplement XAML outline
// var cu = e.NewCompilationUnit as XamlCompilationUnit; // var cu = e.NewCompilationUnit as XamlCompilationUnit;
// //
// if (cu != null && cu.TreeRootNode != null) // if (cu != null && cu.TreeRootNode != null)
@ -103,7 +104,7 @@ namespace ICSharpCode.XamlBinding
public void Dispose() public void Dispose()
{ {
ParserService.ParseInformationUpdated -= ParseInfoUpdated; SD.ParserService.ParseInformationUpdated -= ParseInfoUpdated;
} }
} }
} }

15
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlParser.cs

@ -27,13 +27,7 @@ namespace ICSharpCode.XamlBinding
/// </summary> /// </summary>
public class XamlParser : IParser public class XamlParser : IParser
{ {
string[] lexerTags; public IReadOnlyList<string> TaskListTokens { get; set; }
public string[] LexerTags
{
get { return lexerTags; }
set { lexerTags = value; }
}
// public LanguageProperties Language // public LanguageProperties Language
// { // {
@ -132,7 +126,8 @@ namespace ICSharpCode.XamlBinding
volatile IncrementalParserState parserState; volatile IncrementalParserState parserState;
public ParseInformation Parse(FileName fileName, ITextSource fileContent, bool fullParseInformationRequested) public ParseInformation Parse(FileName fileName, ITextSource fileContent, bool fullParseInformationRequested,
IProject parentProject, CancellationToken cancellationToken)
{ {
AXmlParser parser = new AXmlParser(); AXmlParser parser = new AXmlParser();
AXmlDocument document; AXmlDocument document;
@ -155,7 +150,7 @@ namespace ICSharpCode.XamlBinding
foreach (var tag in TreeTraversal.PreOrder<AXmlObject>(xmlDocument, node => node.Children).OfType<AXmlTag>().Where(t => t.IsComment)) { foreach (var tag in TreeTraversal.PreOrder<AXmlObject>(xmlDocument, node => node.Children).OfType<AXmlTag>().Where(t => t.IsComment)) {
int matchLength; int matchLength;
AXmlText comment = tag.Children.OfType<AXmlText>().First(); AXmlText comment = tag.Children.OfType<AXmlText>().First();
int index = comment.Value.IndexOfAny(lexerTags, 0, out matchLength); int index = comment.Value.IndexOfAny(TaskListTokens, 0, out matchLength);
if (index > -1) { if (index > -1) {
if (document == null) if (document == null)
document = fileContent as IDocument ?? new ReadOnlyDocument(fileContent); document = fileContent as IDocument ?? new ReadOnlyDocument(fileContent);
@ -165,7 +160,7 @@ namespace ICSharpCode.XamlBinding
int endOffset = Math.Min(document.GetLineByOffset(startOffset).EndOffset, comment.EndOffset); int endOffset = Math.Min(document.GetLineByOffset(startOffset).EndOffset, comment.EndOffset);
string content = document.GetText(startOffset, endOffset - startOffset); string content = document.GetText(startOffset, endOffset - startOffset);
parseInfo.TagComments.Add(new TagComment(content.Substring(0, matchLength), new DomRegion(parseInfo.FileName, startLocation.Line, startLocation.Column), content.Substring(matchLength))); parseInfo.TagComments.Add(new TagComment(content.Substring(0, matchLength), new DomRegion(parseInfo.FileName, startLocation.Line, startLocation.Column), content.Substring(matchLength)));
index = comment.Value.IndexOfAny(lexerTags, endOffset - comment.StartOffset, out matchLength); index = comment.Value.IndexOfAny(TaskListTokens, endOffset - comment.StartOffset, out matchLength);
} while (index > -1); } while (index > -1);
} }
} }

5
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlSymbolSearch.cs

@ -13,6 +13,7 @@ using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor.Search; using ICSharpCode.SharpDevelop.Editor.Search;
using ICSharpCode.SharpDevelop.Parser; using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
@ -35,7 +36,7 @@ namespace ICSharpCode.XamlBinding
public XamlSymbolSearch(IProject project, IEntity entity) public XamlSymbolSearch(IProject project, IEntity entity)
{ {
this.entity = entity; this.entity = entity;
compilation = ParserService.GetCompilation(project); compilation = SD.ParserService.GetCompilation(project);
interestingFileNames = new List<FileName>(); interestingFileNames = new List<FileName>();
foreach (var item in project.ParentSolution.SolutionFolderContainers.Select(f => f.SolutionItems).SelectMany(si => si.Items).Where(i => ".xaml".Equals(Path.GetExtension(i.Location), StringComparison.OrdinalIgnoreCase))) foreach (var item in project.ParentSolution.SolutionFolderContainers.Select(f => f.SolutionItems).SelectMany(si => si.Items).Where(i => ".xaml".Equals(Path.GetExtension(i.Location), StringComparison.OrdinalIgnoreCase)))
interestingFileNames.Add(new FileName(Path.Combine(project.ParentSolution.Directory, item.Location))); interestingFileNames.Add(new FileName(Path.Combine(project.ParentSolution.Directory, item.Location)));
@ -81,7 +82,7 @@ namespace ICSharpCode.XamlBinding
if (offset < 0) if (offset < 0)
return; return;
var parseInfo = ParserService.Parse(fileName, textSource) as XamlFullParseInformation; var parseInfo = SD.ParserService.Parse(fileName, textSource) as XamlFullParseInformation;
if (parseInfo == null) if (parseInfo == null)
return; return;
ReadOnlyDocument document = null; ReadOnlyDocument document = null;

4
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditViewContent.cs

@ -171,7 +171,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
FileName newFileName = file.FileName; FileName newFileName = file.FileName;
if (!string.IsNullOrEmpty(oldFileName)) if (!string.IsNullOrEmpty(oldFileName))
ParserService.ClearParseInformation(oldFileName); SD.ParserService.ClearParseInformation(oldFileName);
BookmarksNotifyNameChange(oldFileName, newFileName); BookmarksNotifyNameChange(oldFileName, newFileName);
@ -182,7 +182,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
codeEditor.FileName = newFileName; codeEditor.FileName = newFileName;
UpdateSyntaxHighlighting(newFileName); UpdateSyntaxHighlighting(newFileName);
ParserService.ParseAsync(file.FileName, codeEditor.Document).FireAndForget(); SD.ParserService.ParseAsync(file.FileName, codeEditor.Document).FireAndForget();
} }
} }

10
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs

@ -141,7 +141,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
{ {
CodeEditorOptions.Instance.PropertyChanged += CodeEditorOptions_Instance_PropertyChanged; CodeEditorOptions.Instance.PropertyChanged += CodeEditorOptions_Instance_PropertyChanged;
CustomizedHighlightingColor.ActiveColorsChanged += CustomizedHighlightingColor_ActiveColorsChanged; CustomizedHighlightingColor.ActiveColorsChanged += CustomizedHighlightingColor_ActiveColorsChanged;
ParserService.ParseInformationUpdated += ParserServiceParseInformationUpdated; SD.ParserService.ParseInformationUpdated += ParserServiceParseInformationUpdated;
this.FlowDirection = FlowDirection.LeftToRight; // code editing is always left-to-right this.FlowDirection = FlowDirection.LeftToRight; // code editing is always left-to-right
this.CommandBindings.Add(new CommandBinding(SharpDevelopRoutedCommands.SplitView, OnSplitView)); this.CommandBindings.Add(new CommandBinding(SharpDevelopRoutedCommands.SplitView, OnSplitView));
@ -476,7 +476,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
// Immediately parse on enter. // Immediately parse on enter.
// This ensures we have up-to-date CC info about the method boundary when a user // This ensures we have up-to-date CC info about the method boundary when a user
// types near the end of a method. // types near the end of a method.
ParserService.ParseAsync(this.FileName, this.Document.CreateSnapshot()).FireAndForget(); SD.ParserService.ParseAsync(this.FileName, this.Document.CreateSnapshot()).FireAndForget();
} else { } else {
if (e.Text.Length == 1) { if (e.Text.Length == 1) {
foreach (ICodeCompletionBinding cc in CodeCompletionBindings) { foreach (ICodeCompletionBinding cc in CodeCompletionBindings) {
@ -539,10 +539,10 @@ namespace ICSharpCode.AvalonEdit.AddIn
void FetchParseInformation() void FetchParseInformation()
{ {
ParseInformation parseInfo = ParserService.GetCachedParseInformation(this.FileName); ParseInformation parseInfo = SD.ParserService.GetCachedParseInformation(this.FileName);
if (parseInfo == null) { if (parseInfo == null) {
// if parse info is not yet available, start parsing on background // if parse info is not yet available, start parsing on background
ParserService.ParseAsync(this.FileName, primaryTextEditorAdapter.Document).FireAndForget(); SD.ParserService.ParseAsync(this.FileName, primaryTextEditorAdapter.Document).FireAndForget();
// we'll receive the result using the ParseInformationUpdated event // we'll receive the result using the ParseInformationUpdated event
} }
ParseInformationUpdated(parseInfo); ParseInformationUpdated(parseInfo);
@ -600,7 +600,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
{ {
CodeEditorOptions.Instance.PropertyChanged -= CodeEditorOptions_Instance_PropertyChanged; CodeEditorOptions.Instance.PropertyChanged -= CodeEditorOptions_Instance_PropertyChanged;
CustomizedHighlightingColor.ActiveColorsChanged -= CustomizedHighlightingColor_ActiveColorsChanged; CustomizedHighlightingColor.ActiveColorsChanged -= CustomizedHighlightingColor_ActiveColorsChanged;
ParserService.ParseInformationUpdated -= ParserServiceParseInformationUpdated; SD.ParserService.ParseInformationUpdated -= ParserServiceParseInformationUpdated;
if (primaryTextEditorAdapter.Language != null) if (primaryTextEditorAdapter.Language != null)
primaryTextEditorAdapter.Language.Detach(); primaryTextEditorAdapter.Language.Detach();

2
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs

@ -550,7 +550,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
parseInfo = null; parseInfo = null;
} else { } else {
if (parseInfo == null || !parseInfo.IsFullParseInformation) if (parseInfo == null || !parseInfo.IsFullParseInformation)
parseInfo = ParserService.Parse(this.FileName, this.Document); parseInfo = SD.ParserService.Parse(this.FileName, this.Document);
} }
IServiceContainer container = this.Adapter.GetService(typeof(IServiceContainer)) as IServiceContainer; IServiceContainer container = this.Adapter.GetService(typeof(IServiceContainer)) as IServiceContainer;

4
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActions/EditorActionsProvider.cs

@ -6,9 +6,9 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.NRefactory; using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Parser; using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.SharpDevelop.Refactoring; using ICSharpCode.SharpDevelop.Refactoring;
@ -83,7 +83,7 @@ namespace ICSharpCode.AvalonEdit.AddIn.ContextActions
/// </summary> /// </summary>
async Task<IEnumerable<IContextAction>> GetActionsAsync(IEnumerable<IContextActionProvider> providers, CancellationToken cancellationToken) async Task<IEnumerable<IContextAction>> GetActionsAsync(IEnumerable<IContextActionProvider> providers, CancellationToken cancellationToken)
{ {
if (ParserService.LoadSolutionProjectsThreadRunning) if (SD.ParserService.LoadSolutionProjectsThreadRunning)
return EmptyList<IContextAction>.Instance; return EmptyList<IContextAction>.Instance;
var providerList = providers.ToList(); var providerList = providers.ToList();
var actions = await Task.WhenAll(providerList.Select(p => p.GetAvailableActionsAsync(this.EditorContext, cancellationToken))); var actions = await Task.WhenAll(providerList.Select(p => p.GetAvailableActionsAsync(this.EditorContext, cancellationToken)));

4
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/DefaultChangeWatcher.cs

@ -4,11 +4,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Utils; using ICSharpCode.AvalonEdit.Utils;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.Editor;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Parser; using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.SharpDevelop.Widgets.MyersDiff; using ICSharpCode.SharpDevelop.Widgets.MyersDiff;
@ -137,7 +137,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
stream.CopyTo(memory); stream.CopyTo(memory);
stream.Close(); stream.Close();
memory.Position = 0; memory.Position = 0;
return FileReader.ReadFileContent(memory, ParserService.DefaultFileEncoding); return FileReader.ReadFileContent(memory, SD.FileService.DefaultFileEncoding);
} }
Stream GetBaseVersion(FileName fileName) Stream GetBaseVersion(FileName fileName)

2
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.cs

@ -242,7 +242,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
IUnresolvedTypeDefinition selectedClass = item != null ? item.Entity as IUnresolvedTypeDefinition : null; IUnresolvedTypeDefinition selectedClass = item != null ? item.Entity as IUnresolvedTypeDefinition : null;
memberItems = new List<EntityItem>(); memberItems = new List<EntityItem>();
if (selectedClass != null) { if (selectedClass != null) {
ICompilation compilation = ParserService.GetCompilationForFile(FileName.Create(selectedClass.ParsedFile.FileName)); ICompilation compilation = SD.ParserService.GetCompilationForFile(FileName.Create(selectedClass.ParsedFile.FileName));
var context = new SimpleTypeResolveContext(compilation.MainAssembly); var context = new SimpleTypeResolveContext(compilation.MainAssembly);
ITypeDefinition compoundClass = selectedClass.Resolve(context).GetDefinition(); ITypeDefinition compoundClass = selectedClass.Resolve(context).GetDefinition();
if (compoundClass != null) { if (compoundClass != null) {

2
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/CodeSnippet.cs

@ -194,7 +194,7 @@ namespace ICSharpCode.AvalonEdit.AddIn.Snippets
static IUnresolvedTypeDefinition GetCurrentClass(ITextEditor editor) static IUnresolvedTypeDefinition GetCurrentClass(ITextEditor editor)
{ {
var parseInfo = ParserService.GetExistingParsedFile(editor.FileName); var parseInfo = SD.ParserService.GetExistingParsedFile(editor.FileName);
if (parseInfo != null) { if (parseInfo != null) {
return parseInfo.GetInnermostTypeDefinition(editor.Caret.Location); return parseInfo.GetInnermostTypeDefinition(editor.Caret.Location);
} }

4
src/AddIns/VersionControl/GitAddIn/Src/OverlayIconManager.cs

@ -7,9 +7,9 @@ using System.Diagnostics;
using System.Drawing; using System.Drawing;
using System.Threading; using System.Threading;
using System.Windows.Forms; using System.Windows.Forms;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.Core.WinForms; using ICSharpCode.Core.WinForms;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
@ -83,7 +83,7 @@ namespace ICSharpCode.GitAddIn
// sleep a tiny bit to give main thread time to add more jobs to the queue // sleep a tiny bit to give main thread time to add more jobs to the queue
Thread.Sleep(100); Thread.Sleep(100);
while (true) { while (true) {
if (ICSharpCode.SharpDevelop.Parser.ParserService.LoadSolutionProjectsThreadRunning) { if (SD.ParserService.LoadSolutionProjectsThreadRunning) {
// Run OverlayIconManager much more slowly while solution is being loaded. // Run OverlayIconManager much more slowly while solution is being loaded.
// This prevents the disk from seeking too much // This prevents the disk from seeking too much
Thread.Sleep(100); Thread.Sleep(100);

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

@ -6,9 +6,9 @@ using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Threading; using System.Threading;
using System.Windows.Forms; using System.Windows.Forms;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.Core.WinForms; using ICSharpCode.Core.WinForms;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.Svn namespace ICSharpCode.Svn
@ -139,7 +139,7 @@ namespace ICSharpCode.Svn
// sleep a tiny bit to give main thread time to add more jobs to the queue // sleep a tiny bit to give main thread time to add more jobs to the queue
Thread.Sleep(2); Thread.Sleep(2);
while (true) { while (true) {
if (ICSharpCode.SharpDevelop.Parser.ParserService.LoadSolutionProjectsThreadRunning) { if (SD.ParserService.LoadSolutionProjectsThreadRunning) {
// Run OverlayIconManager much more slowly while solution is being loaded. // Run OverlayIconManager much more slowly while solution is being loaded.
// This prevents the disk from seeking too much // This prevents the disk from seeking too much
Thread.Sleep(100); Thread.Sleep(100);

30
src/Main/Base/Project/ICSharpCode.SharpDevelop.addin

@ -41,7 +41,6 @@
<Doozer name="Pad" class="ICSharpCode.SharpDevelop.PadDoozer"/> <Doozer name="Pad" class="ICSharpCode.SharpDevelop.PadDoozer"/>
<Doozer name="ProjectBinding" class="ICSharpCode.SharpDevelop.ProjectBindingDoozer"/> <Doozer name="ProjectBinding" class="ICSharpCode.SharpDevelop.ProjectBindingDoozer"/>
<Doozer name="LanguageBinding" class="ICSharpCode.SharpDevelop.LanguageBindingDoozer"/> <Doozer name="LanguageBinding" class="ICSharpCode.SharpDevelop.LanguageBindingDoozer"/>
<Doozer name="Parser" class="ICSharpCode.SharpDevelop.Parser.ParserDoozer"/>
<Doozer name="BrowserSchemeExtension" class="ICSharpCode.SharpDevelop.BrowserDisplayBinding.SchemeExtensionDoozer"/> <Doozer name="BrowserSchemeExtension" class="ICSharpCode.SharpDevelop.BrowserDisplayBinding.SchemeExtensionDoozer"/>
<Doozer name="CodeCompletionBinding" class="ICSharpCode.SharpDevelop.Editor.CodeCompletion.CodeCompletionBindingDoozer"/> <Doozer name="CodeCompletionBinding" class="ICSharpCode.SharpDevelop.Editor.CodeCompletion.CodeCompletionBindingDoozer"/>
<Doozer name="Debugger" class="ICSharpCode.SharpDevelop.Debugging.DebuggerDoozer"/> <Doozer name="Debugger" class="ICSharpCode.SharpDevelop.Debugging.DebuggerDoozer"/>
@ -49,9 +48,20 @@
<Doozer name="TaskBoundAdditionalLogger" class="ICSharpCode.SharpDevelop.Project.TaskBoundAdditionalLoggerDoozer"/> <Doozer name="TaskBoundAdditionalLogger" class="ICSharpCode.SharpDevelop.Project.TaskBoundAdditionalLoggerDoozer"/>
<Doozer name="TaskBoundLoggerFilter" class="ICSharpCode.SharpDevelop.Project.TaskBoundLoggerFilterDoozer"/> <Doozer name="TaskBoundLoggerFilter" class="ICSharpCode.SharpDevelop.Project.TaskBoundLoggerFilterDoozer"/>
</Import> </Import>
<Import assembly=":SharpDevelop"/> <Import assembly=":SharpDevelop">
<Doozer name="Parser" class="ICSharpCode.SharpDevelop.Parser.ParserDoozer"/>
</Import>
</Runtime> </Runtime>
<Path name="/SharpDevelop/Services">
<Service id="ICSharpCode.SharpDevelop.Parser.IGlobalAssemblyCacheService"
class="ICSharpCode.SharpDevelop.Parser.GlobalAssemblyCacheService"/>
<Service id="ICSharpCode.SharpDevelop.Parser.IParserService"
class="ICSharpCode.SharpDevelop.Parser.ParserService"/>
<Service id="ICSharpCode.SharpDevelop.IFileService"
class="ICSharpCode.SharpDevelop.Workbench.FileService"/>
</Path>
<Path name = "/SharpDevelop/Workbench/Ambiences"> <Path name = "/SharpDevelop/Workbench/Ambiences">
<Class id = ".NET" <Class id = ".NET"
class = "ICSharpCode.SharpDevelop.NetAmbience"/> class = "ICSharpCode.SharpDevelop.NetAmbience"/>
@ -1066,7 +1076,7 @@
<ToolbarItem id = "ChooseLayout" <ToolbarItem id = "ChooseLayout"
type = "ComboBox" type = "ComboBox"
class = "ICSharpCode.SharpDevelop.Gui.Workbench.ChooseLayoutCommand" /> class = "ICSharpCode.SharpDevelop.Workbench.ChooseLayoutCommand" />
<ToolbarItem id="NavigationSeparator" type="Separator"/> <ToolbarItem id="NavigationSeparator" type="Separator"/>
<Condition name="CanNavigateBack" action="Disable"> <Condition name="CanNavigateBack" action="Disable">
@ -2243,18 +2253,6 @@
class = "ICSharpCode.SharpDevelop.Gui.ToggleConsoleWordWrapCommand"/> class = "ICSharpCode.SharpDevelop.Gui.ToggleConsoleWordWrapCommand"/>
</Path> </Path>
<Path name="/SharpDevelop/Services/ParserService/SingleFileGacReferences">
<String id = "System" text = "System"/>
<String id = "System.Core" text = "System.Core"/>
<String id = "System.Data" text = "System.Data"/>
<String id = "System.Data.DataSetExtensions" text = "System.Data.DataSetExtensions"/>
<String id = "System.Drawing" text = "System.Drawing"/>
<String id = "System.Web" text = "System.Web"/>
<String id = "System.Windows.Forms" text = "System.Windows.Forms"/>
<String id = "System.Xml" text = "System.Xml"/>
<String id = "System.Xml.Linq" text = "System.Xml.Linq"/>
</Path>
<Path name = "/SharpDevelop/BackendBindings/TemplateCommands"> <Path name = "/SharpDevelop/BackendBindings/TemplateCommands">
<Class id="AddDotNet35ReferencesIfTargetFrameworkIs35" <Class id="AddDotNet35ReferencesIfTargetFrameworkIs35"
class="ICSharpCode.SharpDevelop.Project.Commands.AddDotNet35ReferencesIfTargetFrameworkIs35Command"/> class="ICSharpCode.SharpDevelop.Project.Commands.AddDotNet35ReferencesIfTargetFrameworkIs35Command"/>
@ -2286,6 +2284,6 @@
</Path> </Path>
<Path name = "/SharpDevelop/Workbench/ProjectBehaviors"> <Path name = "/SharpDevelop/Workbench/ProjectBehaviors">
</Path> </Path>
</AddIn> </AddIn>

13
src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj

@ -360,8 +360,10 @@
<Compile Include="Src\Services\DisplayBinding\ISecondaryDisplayBinding.cs" /> <Compile Include="Src\Services\DisplayBinding\ISecondaryDisplayBinding.cs" />
<Compile Include="Src\Services\DisplayBinding\ShellExecuteDisplayBinding.cs" /> <Compile Include="Src\Services\DisplayBinding\ShellExecuteDisplayBinding.cs" />
<Compile Include="Src\Services\File\FileChangeWatcher.cs" /> <Compile Include="Src\Services\File\FileChangeWatcher.cs" />
<Compile Include="Src\Services\File\IFileService.cs" />
<Compile Include="Src\Services\File\OpenedFile.cs" /> <Compile Include="Src\Services\File\OpenedFile.cs" />
<Compile Include="Src\Services\File\RecentOpen.cs" /> <Compile Include="Src\Services\File\RecentOpen.cs" />
<Compile Include="Src\Services\IMessageLoop.cs" />
<Compile Include="Src\Services\LanguageBinding\AggregatedLanguageBinding.cs" /> <Compile Include="Src\Services\LanguageBinding\AggregatedLanguageBinding.cs" />
<Compile Include="Src\Services\LanguageBinding\DefaultLanguageBinding.cs" /> <Compile Include="Src\Services\LanguageBinding\DefaultLanguageBinding.cs" />
<Compile Include="Src\Services\LanguageBinding\ILanguageBinding.cs" /> <Compile Include="Src\Services\LanguageBinding\ILanguageBinding.cs" />
@ -377,13 +379,11 @@
<Compile Include="Src\Services\MimeTypeDetection.cs" /> <Compile Include="Src\Services\MimeTypeDetection.cs" />
<Compile Include="Src\Services\ParserService\AssemblyParserService.cs" /> <Compile Include="Src\Services\ParserService\AssemblyParserService.cs" />
<Compile Include="Src\Services\ParserService\DomAssemblyName.cs" /> <Compile Include="Src\Services\ParserService\DomAssemblyName.cs" />
<Compile Include="Src\Services\ParserService\Fusion.cs" /> <Compile Include="Src\Services\ParserService\IGlobalAssemblyCacheService.cs" />
<Compile Include="Src\Services\ParserService\GacInterop.cs" /> <Compile Include="Src\Services\ParserService\IParserService.cs" />
<Compile Include="Src\Services\ParserService\ParsedFileListener.cs" />
<Compile Include="Src\Services\ParserService\IParser.cs" /> <Compile Include="Src\Services\ParserService\IParser.cs" />
<Compile Include="Src\Services\ParserService\ParseInformation.cs" /> <Compile Include="Src\Services\ParserService\ParseInformation.cs" />
<Compile Include="Src\Services\ParserService\LoadSolutionProjects.cs" /> <Compile Include="Src\Services\ParserService\LoadSolutionProjects.cs" />
<Compile Include="Src\Services\ParserService\ParserService.cs" />
<Compile Include="Src\Services\ParserService\SharpDevelopSolutionSnapshot.cs" /> <Compile Include="Src\Services\ParserService\SharpDevelopSolutionSnapshot.cs" />
<Compile Include="Src\Services\ProjectService\CompileModifiedProjectsOnly.cs" /> <Compile Include="Src\Services\ProjectService\CompileModifiedProjectsOnly.cs" />
<Compile Include="Src\Services\ProjectService\SolutionConfigurationEventHandler.cs" /> <Compile Include="Src\Services\ProjectService\SolutionConfigurationEventHandler.cs" />
@ -578,8 +578,6 @@
<Compile Include="Src\Gui\Pads\ProjectBrowser\Commands\ToolbarCommands.cs" /> <Compile Include="Src\Gui\Pads\ProjectBrowser\Commands\ToolbarCommands.cs" />
<Compile Include="Src\Services\ProjectBinding\ProjectBindingDescriptor.cs" /> <Compile Include="Src\Services\ProjectBinding\ProjectBindingDescriptor.cs" />
<Compile Include="Src\Services\DisplayBinding\DisplayBindingDescriptor.cs" /> <Compile Include="Src\Services\DisplayBinding\DisplayBindingDescriptor.cs" />
<Compile Include="Src\Services\ParserService\Doozer\ParserDoozer.cs" />
<Compile Include="Src\Services\ParserService\Doozer\ParserDescriptor.cs" />
<Compile Include="Src\Gui\XmlForms\Lib\IPropertyValueCreator.cs" /> <Compile Include="Src\Gui\XmlForms\Lib\IPropertyValueCreator.cs" />
<Compile Include="Src\Gui\XmlForms\Lib\IStringValueFilter.cs" /> <Compile Include="Src\Gui\XmlForms\Lib\IStringValueFilter.cs" />
<Compile Include="Src\Gui\XmlForms\Lib\StringWrapper.cs" /> <Compile Include="Src\Gui\XmlForms\Lib\StringWrapper.cs" />
@ -734,6 +732,7 @@
<Compile Include="Src\Services\ProjectService\ProjectLoader.cs" /> <Compile Include="Src\Services\ProjectService\ProjectLoader.cs" />
<Compile Include="Src\Util\DotnetDetection.cs" /> <Compile Include="Src\Util\DotnetDetection.cs" />
<Compile Include="Src\Util\FakeXmlViewContent.cs" /> <Compile Include="Src\Util\FakeXmlViewContent.cs" />
<Compile Include="Src\Util\MultiDictionary.cs" />
<Compile Include="Src\Util\ReactiveExtensions.cs" /> <Compile Include="Src\Util\ReactiveExtensions.cs" />
<Compile Include="Src\Util\SharpDevelopServiceContainer.cs" /> <Compile Include="Src\Util\SharpDevelopServiceContainer.cs" />
<Compile Include="Src\Util\TreeNode.cs" /> <Compile Include="Src\Util\TreeNode.cs" />
@ -784,8 +783,6 @@
<Compile Include="Src\Util\UnclosableStream.cs" /> <Compile Include="Src\Util\UnclosableStream.cs" />
<Compile Include="Src\Util\WeakCollection.cs" /> <Compile Include="Src\Util\WeakCollection.cs" />
<Compile Include="Src\Util\WindowsFormsPrinting.cs" /> <Compile Include="Src\Util\WindowsFormsPrinting.cs" />
<Compile Include="Src\Util\WpfSynchronizeInvoke.cs" />
<Compile Include="Src\Util\WorkerThread.cs" />
<EmbeddedResource Include="Resources\DefaultManifest.manifest" /> <EmbeddedResource Include="Resources\DefaultManifest.manifest" />
<EmbeddedResource Include="Src\Gui\Dialogs\ExtractInterfaceDialog.resx"> <EmbeddedResource Include="Src\Gui\Dialogs\ExtractInterfaceDialog.resx">
<DependentUpon>ExtractInterfaceDialog.cs</DependentUpon> <DependentUpon>ExtractInterfaceDialog.cs</DependentUpon>

2
src/Main/Base/Project/Src/Editor/Commands/SymbolUnderCaretMenuCommand.cs

@ -27,7 +27,7 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands
public void Run(ITextEditor editor, int caretOffset) public void Run(ITextEditor editor, int caretOffset)
{ {
var location = editor.Document.GetLocation(caretOffset); var location = editor.Document.GetLocation(caretOffset);
var resolveResult = ParserService.Resolve(editor.FileName, location, editor.Document); var resolveResult = SD.ParserService.Resolve(editor, location);
RunImpl(editor, editor.Caret.Offset, resolveResult); RunImpl(editor, editor.Caret.Offset, resolveResult);
} }

3
src/Main/Base/Project/Src/Editor/IDocumentBaseVersionProvider.cs

@ -49,8 +49,7 @@ namespace ICSharpCode.SharpDevelop.Editor
{ {
this.watcher = new FileSystemWatcher(repositoryRoot); this.watcher = new FileSystemWatcher(repositoryRoot);
if (WorkbenchSingleton.Workbench != null) watcher.SynchronizingObject = SD.MainThread.SynchronizingObject;
watcher.SynchronizingObject = WorkbenchSingleton.Workbench.SynchronizingObject;
WorkbenchSingleton.MainWindow.Activated += MainWindowActivated; WorkbenchSingleton.MainWindow.Activated += MainWindowActivated;

2
src/Main/Base/Project/Src/Editor/ToolTipRequestEventArgs.cs

@ -45,7 +45,7 @@ namespace ICSharpCode.SharpDevelop.Editor
get { get {
if (!resolveResultInitialized) { if (!resolveResultInitialized) {
if (InDocument) if (InDocument)
resolveResult = ParserService.Resolve(this.Editor.FileName, this.LogicalPosition, this.Editor.Document); resolveResult = SD.ParserService.Resolve(this.Editor, this.LogicalPosition);
resolveResultInitialized = true; resolveResultInitialized = true;
} }
return resolveResult; return resolveResult;

6
src/Main/Base/Project/Src/Gui/Dialogs/GotoDialog.cs

@ -38,14 +38,14 @@ namespace ICSharpCode.SharpDevelop.Gui
{ {
InitializeComponent(); InitializeComponent();
FormLocationHelper.ApplyWindow(this, "ICSharpCode.SharpDevelop.Gui.GotoDialog.Bounds", true); FormLocationHelper.ApplyWindow(this, "ICSharpCode.SharpDevelop.Gui.GotoDialog.Bounds", true);
ParserService.LoadSolutionProjectsThreadEnded += ParserService_LoadSolutionProjectsThreadEnded; SD.ParserService.LoadSolutionProjectsThreadEnded += ParserService_LoadSolutionProjectsThreadEnded;
textBox.Focus(); textBox.Focus();
} }
protected override void OnClosed(EventArgs e) protected override void OnClosed(EventArgs e)
{ {
Instance = null; Instance = null;
ParserService.LoadSolutionProjectsThreadEnded -= ParserService_LoadSolutionProjectsThreadEnded; SD.ParserService.LoadSolutionProjectsThreadEnded -= ParserService_LoadSolutionProjectsThreadEnded;
base.OnClosed(e); base.OnClosed(e);
} }
@ -163,7 +163,7 @@ namespace ICSharpCode.SharpDevelop.Gui
{ {
ITextEditor editor = GetEditor(); ITextEditor editor = GetEditor();
if (editor != null) { if (editor != null) {
IParsedFile parseInfo = ParserService.GetExistingParsedFile(editor.FileName); IParsedFile parseInfo = SD.ParserService.GetExistingParsedFile(editor.FileName);
if (parseInfo != null) { if (parseInfo != null) {
foreach (IUnresolvedTypeDefinition c in parseInfo.TopLevelTypeDefinitions) { foreach (IUnresolvedTypeDefinition c in parseInfo.TopLevelTypeDefinitions) {
AddAllMembersMatchingText(c, text); AddAllMembersMatchingText(c, text);

3
src/Main/Base/Project/Src/Gui/Dialogs/NewFileDialog.cs

@ -393,8 +393,7 @@ namespace ICSharpCode.SharpDevelop.Gui
if (!String.IsNullOrEmpty(binaryFileName)) if (!String.IsNullOrEmpty(binaryFileName))
File.Copy(binaryFileName, parsedFileName); File.Copy(binaryFileName, parsedFileName);
else else
File.WriteAllText(parsedFileName, parsedContent, ParserService.DefaultFileEncoding); File.WriteAllText(parsedFileName, parsedContent, SD.FileService.DefaultFileEncoding);
ParserService.ParseFileAsync(FileName.Create(parsedFileName), new StringTextSource(parsedContent)).FireAndForget();
} else { } else {
if (!String.IsNullOrEmpty(binaryFileName)) { if (!String.IsNullOrEmpty(binaryFileName)) {
LoggingService.Warn("binary file was skipped"); LoggingService.Warn("binary file was skipped");

5
src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/IDEOptions/TaskListOptionsl.xaml.cs

@ -23,8 +23,7 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels
public TaskListXaml() public TaskListXaml()
{ {
InitializeComponent(); InitializeComponent();
string[] tokens = ParserService.TaskListTokens; foreach (var token in SD.ParserService.TaskListTokens) {
foreach (var token in tokens) {
listView.Items.Add(token); listView.Items.Add(token);
}; };
} }
@ -80,7 +79,7 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels
tokens.Add(text); tokens.Add(text);
} }
} }
ParserService.TaskListTokens = tokens.ToArray(); SD.ParserService.TaskListTokens = tokens.ToArray();
return true; return true;
} }
} }

2
src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/GacReferencePanel.cs

@ -442,7 +442,7 @@ namespace ICSharpCode.SharpDevelop.Gui
protected virtual IList<DomAssemblyName> GetCacheContent() protected virtual IList<DomAssemblyName> GetCacheContent()
{ {
return GacInterop.GetGacAssemblyFullNames() return SD.GlobalAssemblyCache.GetGacAssemblyFullNames()
.Where(name => !name.ShortName.EndsWith(".resources", StringComparison.OrdinalIgnoreCase)) .Where(name => !name.ShortName.EndsWith(".resources", StringComparison.OrdinalIgnoreCase))
.ToList(); .ToList();
} }

4
src/Main/Base/Project/Src/Gui/Dialogs/WordCountDialog.cs

@ -53,7 +53,9 @@ namespace ICSharpCode.SharpDevelop.Gui
{ {
if (!File.Exists(filename)) return null; if (!File.Exists(filename)) return null;
return GetReport(filename, ParserService.GetParseableFileContent(filename).CreateReader()); using (var reader = SD.FileService.GetFileContent(filename).CreateReader()) {
return GetReport(filename, reader);
}
} }
Report GetReport(IViewContent content, TextReader reader) Report GetReport(IViewContent content, TextReader reader)

5
src/Main/Base/Project/Src/Gui/IWorkbench.cs

@ -21,11 +21,6 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary> /// </summary>
IWin32Window MainWin32Window { get; } IWin32Window MainWin32Window { get; }
/// <summary>
/// Object for executing methods on the main thread.
/// </summary>
ISynchronizeInvoke SynchronizingObject { get; }
/// <summary> /// <summary>
/// The main window. /// The main window.
/// </summary> /// </summary>

7
src/Main/Base/Project/Src/Gui/Pads/DefinitionViewPad.cs

@ -40,7 +40,8 @@ namespace ICSharpCode.SharpDevelop.Gui
ctl = Editor.AvalonEdit.AvalonEditTextEditorAdapter.CreateAvalonEditInstance(); ctl = Editor.AvalonEdit.AvalonEditTextEditorAdapter.CreateAvalonEditInstance();
ctl.IsReadOnly = true; ctl.IsReadOnly = true;
ctl.MouseDoubleClick += OnDoubleClick; ctl.MouseDoubleClick += OnDoubleClick;
ParserService.ParserUpdateStepFinished += OnParserUpdateStep; throw new NotImplementedException();
//ParserService.ParserUpdateStepFinished += OnParserUpdateStep;
ctl.IsVisibleChanged += delegate { UpdateTick(null); }; ctl.IsVisibleChanged += delegate { UpdateTick(null); };
} }
@ -49,7 +50,7 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary> /// </summary>
public override void Dispose() public override void Dispose()
{ {
ParserService.ParserUpdateStepFinished -= OnParserUpdateStep; //ParserService.ParserUpdateStepFinished -= OnParserUpdateStep;
ctl.Document = null; ctl.Document = null;
base.Dispose(); base.Dispose();
} }
@ -95,7 +96,7 @@ namespace ICSharpCode.SharpDevelop.Gui
// don't resolve when an unrelated file was changed // don't resolve when an unrelated file was changed
if (e != null && editor.FileName != e.FileName) return null; if (e != null && editor.FileName != e.FileName) return null;
return ParserService.ResolveAsync(editor.FileName, editor.Caret.Location, editor.Document); return SD.ParserService.ResolveAsync(editor.FileName, editor.Caret.Location, editor.Document);
} }
DomRegion oldPosition; DomRegion oldPosition;

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

@ -68,7 +68,7 @@ namespace ICSharpCode.SharpDevelop.Project.Commands
} }
// Update code completion. // Update code completion.
ParserService.ParseFileAsync(FileName.Create(webReference.WebProxyFileName)).FireAndForget(); SD.ParserService.ParseFileAsync(FileName.Create(webReference.WebProxyFileName), parentProject: url.Project).FireAndForget();
} }
} catch (WebException ex) { } catch (WebException ex) {
MessageService.ShowException(ex, String.Format(StringParser.Parse("${res:ICSharpCode.SharpDevelop.Commands.ProjectBrowser.RefreshWebReference.ReadServiceDescriptionError}"), url.UpdateFromURL)); MessageService.ShowException(ex, String.Format(StringParser.Parse("${res:ICSharpCode.SharpDevelop.Commands.ProjectBrowser.RefreshWebReference.ReadServiceDescriptionError}"), url.UpdateFromURL));
@ -125,7 +125,7 @@ namespace ICSharpCode.SharpDevelop.Project.Commands
AddWebReferenceToProjectBrowser(node, refDialog.WebReference); AddWebReferenceToProjectBrowser(node, refDialog.WebReference);
// Add proxy to code completion. // Add proxy to code completion.
ParserService.ParseFileAsync(FileName.Create(refDialog.WebReference.WebProxyFileName)).FireAndForget(); SD.ParserService.ParseFileAsync(FileName.Create(refDialog.WebReference.WebProxyFileName)).FireAndForget();
node.Project.Save(); node.Project.Save();
} }

2
src/Main/Base/Project/Src/Gui/Pads/PropertyPad/PropertyPad.cs

@ -413,7 +413,7 @@ namespace ICSharpCode.SharpDevelop.Gui
if (gridItem != null) { if (gridItem != null) {
Type component = gridItem.PropertyDescriptor.ComponentType; Type component = gridItem.PropertyDescriptor.ComponentType;
if (component != null) { if (component != null) {
ICompilation compilation = ParserService.GetCompilation(ProjectService.CurrentProject); ICompilation compilation = SD.ParserService.GetCompilation(ProjectService.CurrentProject);
IType componentType = compilation.FindType(component); IType componentType = compilation.FindType(component);
IProperty property = componentType.GetProperties(p => p.Name == gridItem.PropertyDescriptor.Name).FirstOrDefault(); IProperty property = componentType.GetProperties(p => p.Name == gridItem.PropertyDescriptor.Name).FirstOrDefault();
if (property != null) if (property != null)

6
src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskListPad.cs

@ -129,7 +129,7 @@ namespace ICSharpCode.SharpDevelop.Gui
contentPanel.Controls.Add(taskView); contentPanel.Controls.Add(taskView);
string[] tokens = ParserService.TaskListTokens; IReadOnlyList<string> tokens = SD.ParserService.TaskListTokens;
foreach (string token in tokens) foreach (string token in tokens)
{ {
@ -219,7 +219,7 @@ namespace ICSharpCode.SharpDevelop.Gui
if (WorkbenchSingleton.Workbench.ActiveViewContent == null) if (WorkbenchSingleton.Workbench.ActiveViewContent == null)
return null; return null;
IParsedFile parseInfo = ParserService.GetExistingParsedFile(WorkbenchSingleton.Workbench.ActiveViewContent.PrimaryFileName); IParsedFile parseInfo = SD.ParserService.GetExistingParsedFile(WorkbenchSingleton.Workbench.ActiveViewContent.PrimaryFileName);
if (parseInfo != null) { if (parseInfo != null) {
IPositionable positionable = WorkbenchSingleton.Workbench.ActiveViewContent as IPositionable; IPositionable positionable = WorkbenchSingleton.Workbench.ActiveViewContent as IPositionable;
if (positionable != null) { if (positionable != null) {
@ -236,7 +236,7 @@ namespace ICSharpCode.SharpDevelop.Gui
// Tasks are created by parsing, so the parse information for item.FileName should already be present. // Tasks are created by parsing, so the parse information for item.FileName should already be present.
// If they aren't, that's because the file might have been deleted/renamed in the meantime. // If they aren't, that's because the file might have been deleted/renamed in the meantime.
// We use GetExistingParseInformation to avoid trying to parse a file that might have been deleted/renamed. // We use GetExistingParseInformation to avoid trying to parse a file that might have been deleted/renamed.
IParsedFile parseInfo = ParserService.GetExistingParsedFile(item.FileName); IParsedFile parseInfo = SD.ParserService.GetExistingParsedFile(item.FileName);
if (parseInfo != null) { if (parseInfo != null) {
var c = parseInfo.GetInnermostTypeDefinition(item.Line, item.Column); var c = parseInfo.GetInnermostTypeDefinition(item.Line, item.Column);
if (c != null) return c; if (c != null) return c;

5
src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskListPadCommands.cs

@ -2,6 +2,7 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System; using System;
using System.Collections.Generic;
using System.Windows.Forms; using System.Windows.Forms;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.Core.WinForms; using ICSharpCode.Core.WinForms;
@ -76,9 +77,9 @@ namespace ICSharpCode.SharpDevelop.Gui
public class TaskListTokensBuilder public class TaskListTokensBuilder
{ {
public static ShowTaskListTokenButton[] BuildItems(string[] tokens) public static ShowTaskListTokenButton[] BuildItems(IReadOnlyList<string> tokens)
{ {
ShowTaskListTokenButton[] buttons = new ShowTaskListTokenButton[tokens.Length]; ShowTaskListTokenButton[] buttons = new ShowTaskListTokenButton[tokens.Count];
for (int i = 0; i < buttons.Length; i++) for (int i = 0; i < buttons.Length; i++)
{ {

72
src/Main/Base/Project/Src/Gui/WorkbenchSingleton.cs

@ -4,6 +4,7 @@
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Forms; using System.Windows.Forms;
using ICSharpCode.Core; using ICSharpCode.Core;
@ -70,7 +71,6 @@ namespace ICSharpCode.SharpDevelop.Gui
DisplayBindingService.InitializeService(); DisplayBindingService.InitializeService();
FileService.InitializeService(); FileService.InitializeService();
ParserService.InitializeParserService();
TaskService.Initialize(); TaskService.Initialize();
Bookmarks.BookmarkManager.Initialize(); Bookmarks.BookmarkManager.Initialize();
Project.CustomToolsService.Initialize(); Project.CustomToolsService.Initialize();
@ -80,7 +80,7 @@ namespace ICSharpCode.SharpDevelop.Gui
if (messageService != null) { if (messageService != null) {
messageService.DialogOwner = workbench.MainWin32Window; messageService.DialogOwner = workbench.MainWin32Window;
Debug.Assert(messageService.DialogOwner != null); Debug.Assert(messageService.DialogOwner != null);
messageService.DialogSynchronizeInvoke = workbench.SynchronizingObject; messageService.DialogSynchronizeInvoke = SD.MainThread.SynchronizingObject;
} }
workbench.Initialize(); workbench.Initialize();
@ -133,7 +133,7 @@ namespace ICSharpCode.SharpDevelop.Gui
if (workbench == null) if (workbench == null)
return false; // unit test mode, don't crash return false; // unit test mode, don't crash
else else
return workbench.SynchronizingObject.InvokeRequired; return SD.MainThread.InvokeRequired;
} }
} }
@ -166,13 +166,7 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary> /// </summary>
public static R SafeThreadFunction<R>(Func<R> method) public static R SafeThreadFunction<R>(Func<R> method)
{ {
// InvokeRequired test is necessary so that we don't run other actions in the message queue return SD.MainThread.InvokeIfRequired(method);
// when we're already running on the main thread (unexpected reentrancy)
ISynchronizeInvoke si = workbench.SynchronizingObject;
if (si.InvokeRequired)
return (R)workbench.SynchronizingObject.Invoke(method, emptyObjectArray);
else
return method();
} }
/// <summary> /// <summary>
@ -182,11 +176,7 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary> /// </summary>
public static R SafeThreadFunction<A, R>(Func<A, R> method, A arg1) public static R SafeThreadFunction<A, R>(Func<A, R> method, A arg1)
{ {
ISynchronizeInvoke si = workbench.SynchronizingObject; return SD.MainThread.InvokeIfRequired(() => method(arg1));
if (si.InvokeRequired)
return (R)si.Invoke(method, new object[] { arg1 });
else
return method(arg1);
} }
/// <summary> /// <summary>
@ -196,11 +186,7 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary> /// </summary>
public static void SafeThreadCall(Action method) public static void SafeThreadCall(Action method)
{ {
ISynchronizeInvoke si = workbench.SynchronizingObject; SD.MainThread.InvokeIfRequired(method);
if (si.InvokeRequired)
si.Invoke(method, emptyObjectArray);
else
method();
} }
/// <summary> /// <summary>
@ -210,11 +196,7 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary> /// </summary>
public static void SafeThreadCall<A>(Action<A> method, A arg1) public static void SafeThreadCall<A>(Action<A> method, A arg1)
{ {
ISynchronizeInvoke si = workbench.SynchronizingObject; SD.MainThread.InvokeIfRequired(() => method(arg1));
if (si.InvokeRequired)
si.Invoke(method, new object[] { arg1 });
else
method(arg1);
} }
/// <summary> /// <summary>
@ -224,11 +206,7 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary> /// </summary>
public static void SafeThreadCall<A, B>(Action<A, B> method, A arg1, B arg2) public static void SafeThreadCall<A, B>(Action<A, B> method, A arg1, B arg2)
{ {
ISynchronizeInvoke si = workbench.SynchronizingObject; SD.MainThread.InvokeIfRequired(() => method(arg1, arg2));
if (si.InvokeRequired)
si.Invoke(method, new object[] { arg1, arg2 });
else
method(arg1, arg2);
} }
/// <summary> /// <summary>
@ -238,11 +216,7 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary> /// </summary>
public static void SafeThreadCall<A, B, C>(Action<A, B, C> method, A arg1, B arg2, C arg3) public static void SafeThreadCall<A, B, C>(Action<A, B, C> method, A arg1, B arg2, C arg3)
{ {
ISynchronizeInvoke si = workbench.SynchronizingObject; SD.MainThread.InvokeIfRequired(() => method(arg1, arg2, arg3));
if (si.InvokeRequired)
si.Invoke(method, new object[] { arg1, arg2, arg3 });
else
method(arg1, arg2, arg3);
} }
/// <summary> /// <summary>
@ -250,7 +224,7 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary> /// </summary>
public static void SafeThreadAsyncCall(Action method) public static void SafeThreadAsyncCall(Action method)
{ {
workbench.SynchronizingObject.BeginInvoke(method, emptyObjectArray); SD.MainThread.InvokeAsync(method).FireAndForget();
} }
/// <summary> /// <summary>
@ -258,7 +232,7 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary> /// </summary>
public static void SafeThreadAsyncCall<A>(Action<A> method, A arg1) public static void SafeThreadAsyncCall<A>(Action<A> method, A arg1)
{ {
workbench.SynchronizingObject.BeginInvoke(method, new object[] { arg1 }); SD.MainThread.InvokeAsync(() => method(arg1)).FireAndForget();
} }
/// <summary> /// <summary>
@ -266,7 +240,7 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary> /// </summary>
public static void SafeThreadAsyncCall<A, B>(Action<A, B> method, A arg1, B arg2) public static void SafeThreadAsyncCall<A, B>(Action<A, B> method, A arg1, B arg2)
{ {
workbench.SynchronizingObject.BeginInvoke(method, new object[] { arg1, arg2 }); SD.MainThread.InvokeAsync(() => method(arg1, arg2)).FireAndForget();
} }
/// <summary> /// <summary>
@ -274,30 +248,16 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary> /// </summary>
public static void SafeThreadAsyncCall<A, B, C>(Action<A, B, C> method, A arg1, B arg2, C arg3) public static void SafeThreadAsyncCall<A, B, C>(Action<A, B, C> method, A arg1, B arg2, C arg3)
{ {
workbench.SynchronizingObject.BeginInvoke(method, new object[] { arg1, arg2, arg3 }); SD.MainThread.InvokeAsync(() => method(arg1, arg2, arg3)).FireAndForget();
} }
/// <summary> /// <summary>
/// Calls a method on the GUI thread, but delays the call a bit. /// Calls a method on the GUI thread, but delays the call a bit.
/// </summary> /// </summary>
public static void CallLater(TimeSpan delay, Action method) public static async void CallLater(TimeSpan delay, Action method)
{ {
int delayMilliseconds = (int)delay.TotalMilliseconds; await Task.Delay(delay).ConfigureAwait(false);
if (delayMilliseconds < 0) SD.MainThread.InvokeAsync(method).FireAndForget();
throw new ArgumentOutOfRangeException("delay", delay, "Value must be positive");
if (method == null)
throw new ArgumentNullException("method");
SafeThreadAsyncCall(
delegate {
Timer t = new Timer();
t.Interval = Math.Max(1, delayMilliseconds);
t.Tick += delegate {
t.Stop();
t.Dispose();
method();
};
t.Start();
});
} }
#endregion #endregion

2
src/Main/Base/Project/Src/Internal/Templates/Project/ProjectDescriptor.cs

@ -372,7 +372,7 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
File.Copy(file.BinaryFileName,fileName); File.Copy(file.BinaryFileName,fileName);
} else { } else {
// Textual content // Textual content
StreamWriter sr = new StreamWriter(File.Create(fileName), ParserService.DefaultFileEncoding); StreamWriter sr = new StreamWriter(File.Create(fileName), SD.FileService.DefaultFileEncoding);
string fileContent = StringParser.Parse(file.Content, new StringTagPair("ProjectName", projectCreateInformation.ProjectName), new StringTagPair("FileName", fileName)); string fileContent = StringParser.Parse(file.Content, new StringTagPair("ProjectName", projectCreateInformation.ProjectName), new StringTagPair("FileName", fileName));
fileContent = StringParser.Parse(fileContent); fileContent = StringParser.Parse(fileContent);
if (SD.EditorControlService.GlobalOptions.IndentationString != "\t") { if (SD.EditorControlService.GlobalOptions.IndentationString != "\t") {

11
src/Main/Base/Project/Src/Project/AbstractProject.cs

@ -15,6 +15,7 @@ using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Debugging; using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Gui.OptionPanels; using ICSharpCode.SharpDevelop.Gui.OptionPanels;
using ICSharpCode.SharpDevelop.Parser;
namespace ICSharpCode.SharpDevelop.Project namespace ICSharpCode.SharpDevelop.Project
{ {
@ -409,6 +410,16 @@ namespace ICSharpCode.SharpDevelop.Project
} }
} }
public virtual event EventHandler<ParseInformationEventArgs> ParseInformationUpdated {
add {}
remove {}
}
public virtual void OnParseInformationUpdated(ParseInformationEventArgs args)
{
throw new NotSupportedException();
}
/// <summary> /// <summary>
/// Creates a new projectItem for the passed itemType /// Creates a new projectItem for the passed itemType
/// </summary> /// </summary>

13
src/Main/Base/Project/Src/Project/CompilableProject.cs

@ -379,6 +379,19 @@ namespace ICSharpCode.SharpDevelop.Project
return GetParseProjectContentContainer().ProjectContent; return GetParseProjectContentContainer().ProjectContent;
} }
} }
public override void OnParseInformationUpdated(ParseInformationEventArgs args)
{
GetParseProjectContentContainer().ParseInformationUpdated(args.OldParsedFile, args.NewParsedFile);
// OnParseInformationUpdated is called inside a lock, but we don't want to raise the event inside that lock.
// To ensure events are raised in the same order, we always invoke on the main thread.
SD.MainThread.InvokeAsync(
delegate {
ParseInformationUpdated(null, args);
});
}
public override event EventHandler<ParseInformationEventArgs> ParseInformationUpdated = delegate {};
#endregion #endregion
} }
} }

2
src/Main/Base/Project/Src/Project/CustomTool.cs

@ -201,7 +201,7 @@ namespace ICSharpCode.SharpDevelop.Project
}, },
outputFileName, FileErrorPolicy.Inform); outputFileName, FileErrorPolicy.Inform);
EnsureOutputFileIsInProject(baseItem, outputFileName); EnsureOutputFileIsInProject(baseItem, outputFileName);
ParserService.ParseAsync(FileName.Create(outputFileName), new StringTextSource(codeOutput)).FireAndForget(); SD.ParserService.ParseAsync(FileName.Create(outputFileName), new StringTextSource(codeOutput)).FireAndForget();
} }
public void GenerateCodeDomAsync(FileProjectItem baseItem, string outputFileName, Func<CodeCompileUnit> func) public void GenerateCodeDomAsync(FileProjectItem baseItem, string outputFileName, Func<CodeCompileUnit> func)

12
src/Main/Base/Project/Src/Project/IProject.cs

@ -12,6 +12,7 @@ using System.Xml.Linq;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Parser;
namespace ICSharpCode.SharpDevelop.Project namespace ICSharpCode.SharpDevelop.Project
{ {
@ -304,6 +305,17 @@ namespace ICSharpCode.SharpDevelop.Project
/// An object that can be used to perform the search; or null if this project does not support symbol searches. /// An object that can be used to perform the search; or null if this project does not support symbol searches.
/// </returns> /// </returns>
Refactoring.ISymbolSearch PrepareSymbolSearch(IEntity entity); Refactoring.ISymbolSearch PrepareSymbolSearch(IEntity entity);
/// <summary>
/// Occurs whenever parse information for this project was updated. This event is raised on the main thread.
/// </summary>
event EventHandler<ParseInformationEventArgs> ParseInformationUpdated;
/// <summary>
/// Notifies the project that the parse information was updated.
/// This method is called by the parser service <b>within a per-file lock</b>.
/// </summary>
void OnParseInformationUpdated(ParseInformationEventArgs args);
} }
/// <summary> /// <summary>

3
src/Main/Base/Project/Src/Project/ProjectChangeWatcher.cs

@ -72,8 +72,7 @@ namespace ICSharpCode.SharpDevelop.Project
try { try {
if (watcher == null) { if (watcher == null) {
watcher = new FileSystemWatcher(); watcher = new FileSystemWatcher();
if (WorkbenchSingleton.Workbench != null) watcher.SynchronizingObject = SD.MainThread.SynchronizingObject;
watcher.SynchronizingObject = WorkbenchSingleton.Workbench.SynchronizingObject;
watcher.Changed += OnFileChangedEvent; watcher.Changed += OnFileChangedEvent;
watcher.Created += OnFileChangedEvent; watcher.Created += OnFileChangedEvent;
watcher.Renamed += OnFileChangedEvent; watcher.Renamed += OnFileChangedEvent;

10
src/Main/Base/Project/Src/Refactoring/EditorRefactoringContext.cs

@ -76,7 +76,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
{ {
lock (syncRoot) { lock (syncRoot) {
if (parseInformation == null) if (parseInformation == null)
parseInformation = ParserService.ParseAsync(this.FileName, this.TextSource); parseInformation = SD.ParserService.ParseAsync(this.FileName, this.TextSource);
return parseInformation; return parseInformation;
} }
} }
@ -86,6 +86,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
/// </summary> /// </summary>
public ParseInformation GetParseInformation() public ParseInformation GetParseInformation()
{ {
// waiting for the task is safe because we specified the text source in the ParseAsync call
return GetParseInformationAsync().Result; return GetParseInformationAsync().Result;
} }
@ -96,7 +97,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
{ {
lock (syncRoot) { lock (syncRoot) {
if (compilation == null) if (compilation == null)
compilation = Task.FromResult(ParserService.GetCompilationForFile(this.FileName)); compilation = Task.FromResult(SD.ParserService.GetCompilationForFile(this.FileName));
return compilation; return compilation;
} }
} }
@ -145,14 +146,11 @@ namespace ICSharpCode.SharpDevelop.Refactoring
async Task<ResolveResult> ResolveCurrentSymbolAsync() async Task<ResolveResult> ResolveCurrentSymbolAsync()
{ {
var parser = ParserService.GetParser(this.FileName);
if (parser == null)
return null;
var parseInfo = await GetParseInformationAsync().ConfigureAwait(false); var parseInfo = await GetParseInformationAsync().ConfigureAwait(false);
if (parseInfo == null) if (parseInfo == null)
return null; return null;
var compilation = await GetCompilationAsync().ConfigureAwait(false); var compilation = await GetCompilationAsync().ConfigureAwait(false);
return await Task.Run(() => ParserService.ResolveAsync(this.FileName, caretLocation, this.TextSource, CancellationToken.None)).ConfigureAwait(false); return await Task.Run(() => SD.ParserService.ResolveAsync(this.FileName, caretLocation, this.TextSource, compilation)).ConfigureAwait(false);
} }
/// <summary> /// <summary>

3
src/Main/Base/Project/Src/Services/File/FileChangeWatcher.cs

@ -134,8 +134,7 @@ namespace ICSharpCode.SharpDevelop
try { try {
if (watcher == null) { if (watcher == null) {
watcher = new FileSystemWatcher(); watcher = new FileSystemWatcher();
if (WorkbenchSingleton.Workbench != null) watcher.SynchronizingObject = SD.MainThread.SynchronizingObject;
watcher.SynchronizingObject = WorkbenchSingleton.Workbench.SynchronizingObject;
watcher.Changed += OnFileChangedEvent; watcher.Changed += OnFileChangedEvent;
watcher.Created += OnFileChangedEvent; watcher.Created += OnFileChangedEvent;
watcher.Renamed += OnFileChangedEvent; watcher.Renamed += OnFileChangedEvent;

6
src/Main/Base/Project/Src/Services/File/FileService.cs

@ -44,7 +44,7 @@ namespace ICSharpCode.SharpDevelop
PropertyService.SetNestedProperties("RecentOpen", recentOpen.ToProperties()); PropertyService.SetNestedProperties("RecentOpen", recentOpen.ToProperties());
} }
ProjectService.SolutionLoaded -= ProjectServiceSolutionLoaded; ProjectService.SolutionLoaded -= ProjectServiceSolutionLoaded;
ParserService.LoadSolutionProjectsThreadEnded -= ParserServiceLoadSolutionProjectsThreadEnded; SD.ParserService.LoadSolutionProjectsThreadEnded -= ParserServiceLoadSolutionProjectsThreadEnded;
serviceInitialized = false; serviceInitialized = false;
} }
@ -52,7 +52,7 @@ namespace ICSharpCode.SharpDevelop
{ {
if (!serviceInitialized) { if (!serviceInitialized) {
ProjectService.SolutionLoaded += ProjectServiceSolutionLoaded; ProjectService.SolutionLoaded += ProjectServiceSolutionLoaded;
ParserService.LoadSolutionProjectsThreadEnded += ParserServiceLoadSolutionProjectsThreadEnded; SD.ParserService.LoadSolutionProjectsThreadEnded += ParserServiceLoadSolutionProjectsThreadEnded;
serviceInitialized = true; serviceInitialized = true;
} }
} }
@ -278,7 +278,7 @@ namespace ICSharpCode.SharpDevelop
/// <param name="content">Content of the file to create</param> /// <param name="content">Content of the file to create</param>
public static IViewContent NewFile(string defaultName, string content) public static IViewContent NewFile(string defaultName, string content)
{ {
return NewFile(defaultName, ParserService.DefaultFileEncoding.GetBytesWithPreamble(content)); return NewFile(defaultName, SD.FileService.DefaultFileEncoding.GetBytesWithPreamble(content));
} }
/// <summary> /// <summary>

55
src/Main/Base/Project/Src/Services/File/IFileService.cs

@ -0,0 +1,55 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Text;
using System.Threading;
using ICSharpCode.Core;
using ICSharpCode.NRefactory.Editor;
namespace ICSharpCode.SharpDevelop
{
/// <summary>
/// File service.
/// </summary>
public interface IFileService
{
/// <summary>
/// Gets the default file encoding.
/// This property is thread-safe.
/// </summary>
Encoding DefaultFileEncoding { get; }
/// <summary>
/// Gets the content of the specified file.
/// If the file is currently open in SharpDevelop, retrieves a snapshot
/// of the editor content.
/// </summary>
/// <remarks>
/// This method is thread-safe. This method involves waiting for the main thread, so using it while
/// holding a lock can lead to deadlocks.
/// </remarks>
ITextSource GetFileContent(FileName fileName);
/// <inheritdoc cref="GetParseableFileContent(FileName)"/>
ITextSource GetFileContent(string fileName);
/// <summary>
/// Gets the file content for a file that is currently open.
/// Returns null if the file is not open.
/// </summary>
/// <remarks>
/// This method is thread-safe. This method involves waiting for the main thread, so using it while
/// holding a lock can lead to deadlocks.
/// </remarks>
ITextSource GetFileContentForOpenFile(FileName fileName);
/// <summary>
/// Gets the file content from disk, ignoring open files.
/// </summary>
/// <remarks>
/// This method is thread-safe.
/// </remarks>
ITextSource GetFileContentFromDisk(FileName fileName, CancellationToken cancellationToken = default(CancellationToken));
}
}

4
src/Main/Base/Project/Src/Services/File/OpenedFile.cs

@ -461,9 +461,9 @@ namespace ICSharpCode.SharpDevelop
// We discarded some information when closing the file, // We discarded some information when closing the file,
// so we need to re-parse it. // so we need to re-parse it.
if (File.Exists(this.FileName)) if (File.Exists(this.FileName))
ParserService.ParseAsync(this.FileName).FireAndForget(); SD.ParserService.ParseAsync(this.FileName).FireAndForget();
else else
ParserService.ClearParseInformation(this.FileName); SD.ParserService.ClearParseInformation(this.FileName);
} }
} }
} }

93
src/Main/Base/Project/Src/Services/IMessageLoop.cs

@ -0,0 +1,93 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Threading;
namespace ICSharpCode.SharpDevelop
{
/// <summary>
/// Represents a thread running a message loop.
/// </summary>
public interface IMessageLoop
{
/// <summary>
/// Gets the thread corresponding to this message loop.
/// </summary>
Thread Thread { get; }
/// <summary>
/// Gets the dispatcher for this message loop.
/// </summary>
Dispatcher Dispatcher { get; }
/// <summary>
/// Gets the synchronization context corresponding to this message loop.
/// </summary>
SynchronizationContext SynchronizationContext { get; }
/// <summary>
/// Gets the <see cref="ISynchronizeInvoke"/> implementation corresponding to this message loop.
/// </summary>
ISynchronizeInvoke SynchronizingObject { get; }
/// <summary>
/// Gets whether the current thread is different from the thread running this message loop.
/// </summary>
/// <remarks><c>InvokeRequired = !CheckAcess()</c></remarks>
bool InvokeRequired { get; }
/// <summary>
/// Gets whether the current thread is the same as the thread running this message loop.
/// </summary>
/// <remarks><c>CheckAccess() = !InvokeRequired</c></remarks>
bool CheckAccess();
/// <summary>
/// Throws an exception if the current thread is different from the thread running this message loop.
/// </summary>
void VerifyAccess();
/// <summary>
/// Invokes the specified callback on the message loop and waits for its completion.
/// If the current thread is the thread running the message loop, executes the callback
/// directly without pumping the message loop.
/// </summary>
void InvokeIfRequired(Action callback);
/// <inheritdoc see="Invoke(Action)"/>
void InvokeIfRequired(Action callback, DispatcherPriority priority);
/// <inheritdoc see="Invoke(Action)"/>
void InvokeIfRequired(Action callback, DispatcherPriority priority, CancellationToken cancellationToken);
/// <summary>
/// Invokes the specified callback, waits for its completion, and returns the result.
/// If the current thread is the thread running the message loop, executes the callback
/// directly without pumping the message loop.
/// </summary>
T InvokeIfRequired<T>(Func<T> callback);
/// <inheritdoc see="Invoke{T}(Func{T})"/>
T InvokeIfRequired<T>(Func<T> callback, DispatcherPriority priority);
/// <inheritdoc see="Invoke{T}(Func{T})"/>
T InvokeIfRequired<T>(Func<T> callback, DispatcherPriority priority, CancellationToken cancellationToken);
/// <summary>
/// Invokes the specified callback.
/// </summary>
/// <returns>Returns a task that is signalled when the execution of the callback is completed.</returns>
Task InvokeAsync(Action callback);
/// <inheritdoc see="InvokeAsync(Action)"/>
Task InvokeAsync(Action callback, DispatcherPriority priority);
/// <inheritdoc see="InvokeAsync(Action)"/>
Task InvokeAsync(Action callback, DispatcherPriority priority, CancellationToken cancellationToken);
/// <inheritdoc see="InvokeAsync(Action)"/>
Task<T> InvokeAsync<T>(Func<T> callback);
/// <inheritdoc see="InvokeAsync(Action)"/>
Task<T> InvokeAsync<T>(Func<T> callback, DispatcherPriority priority);
/// <inheritdoc see="InvokeAsync(Action)"/>
Task<T> InvokeAsync<T>(Func<T> callback, DispatcherPriority priority, CancellationToken cancellationToken);
}
}

2
src/Main/Base/Project/Src/Services/NavigationService/NavigationService.cs

@ -70,7 +70,7 @@ namespace ICSharpCode.SharpDevelop
// ignore files opened as part of loading a solution. // ignore files opened as part of loading a solution.
ProjectService.SolutionLoading += ProjectService_SolutionLoading; ProjectService.SolutionLoading += ProjectService_SolutionLoading;
ParserService.LoadSolutionProjectsThreadEnded += LoadSolutionProjectsThreadEnded; SD.ParserService.LoadSolutionProjectsThreadEnded += LoadSolutionProjectsThreadEnded;
FileService.FileRenamed += FileService_FileRenamed; FileService.FileRenamed += FileService_FileRenamed;
ProjectService.SolutionClosed += ProjectService_SolutionClosed; ProjectService.SolutionClosed += ProjectService_SolutionClosed;

11
src/Main/Base/Project/Src/Services/ParserService/DomAssemblyName.cs

@ -9,6 +9,7 @@ namespace ICSharpCode.SharpDevelop.Parser
/// Similar to System.Reflection.AssemblyName, but does not raise an exception /// Similar to System.Reflection.AssemblyName, but does not raise an exception
/// on invalid assembly names. (See SD-1307) /// on invalid assembly names. (See SD-1307)
/// </summary> /// </summary>
[Serializable]
public sealed class DomAssemblyName : IEquatable<DomAssemblyName> public sealed class DomAssemblyName : IEquatable<DomAssemblyName>
{ {
readonly string fullAssemblyName; readonly string fullAssemblyName;
@ -79,15 +80,5 @@ namespace ICSharpCode.SharpDevelop.Parser
{ {
return other != null && fullAssemblyName == other.fullAssemblyName; return other != null && fullAssemblyName == other.fullAssemblyName;
} }
internal static DomAssemblyName[] Convert(System.Reflection.AssemblyName[] names)
{
if (names == null) return null;
DomAssemblyName[] n = new DomAssemblyName[names.Length];
for (int i = 0; i < names.Length; i++) {
n[i] = new DomAssemblyName(names[i].FullName);
}
return n;
}
} }
} }

30
src/Main/Base/Project/Src/Services/ParserService/IGlobalAssemblyCacheService.cs

@ -0,0 +1,30 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
namespace ICSharpCode.SharpDevelop.Parser
{
/// <summary>
/// Interface for global assembly cache service.
/// </summary>
public interface IGlobalAssemblyCacheService
{
/// <summary>
/// Gets whether the file name is within the GAC.
/// </summary>
bool IsGACAssembly(string fileName);
/// <summary>
/// Gets the names of all assemblies in the GAC.
/// </summary>
IEnumerable<DomAssemblyName> GetGacAssemblyFullNames();
/// <summary>
/// Gets the file name for an assembly stored in the GAC.
/// Returns null if the assembly cannot be found.
/// </summary>
string FindAssemblyInNetGac(DomAssemblyName reference);
}
}

23
src/Main/Base/Project/Src/Services/ParserService/IParser.cs

@ -2,17 +2,18 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System; using System;
using System.Collections.Generic;
using System.Threading; using System.Threading;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.NRefactory; using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.SharpDevelop.Refactoring; using ICSharpCode.SharpDevelop.Refactoring;
namespace ICSharpCode.SharpDevelop.Project namespace ICSharpCode.SharpDevelop.Parser
{ {
/// <summary> /// <summary>
/// Represents a language parser that produces ParseInformation /// Represents a language parser that produces ParseInformation
@ -23,10 +24,7 @@ namespace ICSharpCode.SharpDevelop.Project
/// <summary> /// <summary>
/// Gets/Sets the tags used to identify tasks. /// Gets/Sets the tags used to identify tasks.
/// </summary> /// </summary>
string[] LexerTags { IReadOnlyList<string> TaskListTokens { get; set; }
get;
set;
}
/// <summary> /// <summary>
/// Gets if the parser can parse the specified file. /// Gets if the parser can parse the specified file.
@ -45,15 +43,20 @@ namespace ICSharpCode.SharpDevelop.Project
/// Specifies whether full parse information were requested for this file. /// Specifies whether full parse information were requested for this file.
/// If this parameter is false, only the ParsedFile and TagComments on the parse information need to be set. /// If this parameter is false, only the ParsedFile and TagComments on the parse information need to be set.
/// </param> /// </param>
/// <param name="parentProject">The parent project for this parse run.</param>
/// <param name="cancellationToken">Cancellation Token.</param>
/// <returns>The parse information representing the parse results.</returns> /// <returns>The parse information representing the parse results.</returns>
/// <remarks> /// <remarks>
/// SharpDevelop may call IParser.Parse in parallel; even on the same IParser instance /// The SharpDevelop parser service may call IParser.Parse in parallel;
/// if there are two parallel parse requests for the same file. Parser implementations must be thread-safe. /// even on the same IParser instance if there are two parallel parse requests for the same file.
/// Parser implementations must be thread-safe.
///
/// The SharpDevelop main thread is allowed to wait for a parse operation to finish; thus IParser /// The SharpDevelop main thread is allowed to wait for a parse operation to finish; thus IParser
/// implementations must not invoke methods on the main thread and wait for their results, /// implementations must not invoke methods on the main thread and wait for their results,
/// as that would deadlock. /// as that would deadlock.
/// </remarks> /// </remarks>
ParseInformation Parse(FileName fileName, ITextSource fileContent, bool fullParseInformationRequested); ParseInformation Parse(FileName fileName, ITextSource fileContent, bool fullParseInformationRequested,
IProject parentProject, CancellationToken cancellationToken);
ResolveResult Resolve(ParseInformation parseInfo, TextLocation location, ICompilation compilation, CancellationToken cancellationToken); ResolveResult Resolve(ParseInformation parseInfo, TextLocation location, ICompilation compilation, CancellationToken cancellationToken);

291
src/Main/Base/Project/Src/Services/ParserService/IParserService.cs

@ -0,0 +1,291 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using ICSharpCode.Core;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Refactoring;
namespace ICSharpCode.SharpDevelop.Parser
{
/// <summary>
/// Manages parse runs and caches ParseInformation.
/// </summary>
public interface IParserService
{
/// <summary>
/// Gets/Sets the task list tokens.
/// The getter of this property is thread-safe;
/// the setter must only be called on the main thread.
/// </summary>
IReadOnlyList<string> TaskListTokens { get; set; }
#region Load Solution Projects Thread
/// <summary>
/// Gets whether the solution is being loaded, or a major re-parse is happening
/// (e.g. after adding a project).
/// </summary>
/// <remarks>This property is only changed by the main thread.</remarks>
bool LoadSolutionProjectsThreadRunning { get; }
/// <summary>
/// This event is raised when the LoadSolutionProjectsThreadRunning property changes to <c>true</c>.
/// This always happens on the main thread.
/// </summary>
event EventHandler LoadSolutionProjectsThreadStarted;
/// <summary>
/// This event is raised when the LoadSolutionProjectsThreadRunning property changes to <c>false</c>.
/// This always happens on the main thread.
/// </summary>
event EventHandler LoadSolutionProjectsThreadEnded; // TODO: rename to finished
#endregion
#region GetCompilation
/// <summary>
/// Gets or creates a compilation for the specified project.
/// </summary>
/// <remarks>
/// This method is thread-safe.
/// This method never returns null - in case of errors, a dummy compilation is created.
/// </remarks>
ICompilation GetCompilation(IProject project);
/// <summary>
/// Gets or creates a compilation for the project that contains the specified file.
/// </summary>
/// <remarks>
/// This method is thread-safe.
/// This method never returns null - in case of errors, a dummy compilation is created.
/// </remarks>
ICompilation GetCompilationForFile(FileName fileName);
/// <summary>
/// Gets a snapshot of the current compilations
/// This method is useful when a consistent snapshot across multiple compilations is needed.
/// </summary>
/// <remarks>
/// This method is thread-safe.
/// </remarks>
SharpDevelopSolutionSnapshot GetCurrentSolutionSnapshot();
/// <summary>
/// Invalidates the current solution snapshot, causing
/// the next <see cref="GetCurrentSolutionSnapshot()"/> call to create a new one.
/// This method needs to be called whenever IProject.ProjectContent changes.
/// </summary>
/// <remarks>
/// This method is thread-safe.
/// </remarks>
void InvalidateCurrentSolutionSnapshot();
#endregion
#region GetExistingParsedFile
/// <summary>
/// Gets the unresolved type system for the specified file.
/// </summary>
/// <param name="fileName">Name of the file.</param>
/// <param name="version">
/// Optional: requested version of the file.
/// If this parameter is specified and the existing parsed file belongs to a different version,
/// this method will return null.
/// </param>
/// <param name="parentProject">
/// Optional: If the file is part of multiple projects, specifies
/// which parsed version of the file to return (for example, different project settings
/// can cause the file to be parsed differently).
/// </param>
/// <returns>
/// Returns the IParsedFile for the specified file,
/// or null if the file has not been parsed yet.
/// </returns>
/// <remarks>This method is thread-safe.</remarks>
IParsedFile GetExistingParsedFile(FileName fileName, ITextSourceVersion version = null, IProject parentProject = null);
/// <summary>
/// Gets full parse information for the specified file, if it is available.
/// </summary>
/// <param name="fileName">Name of the file.</param>
/// <param name="version">
/// Optional: requested version of the file.
/// If this parameter is specified and the existing parsed file belongs to a different version,
/// this method will return null.
/// </param>
/// <param name="parentProject">
/// Optional: If the file is part of multiple projects, specifies
/// which parsed version of the file to return (for example, different project settings
/// can cause the file to be parsed differently).
/// </param>
/// <returns>
/// If only the IParsedFile is available (non-full parse information), this method returns null.
/// </returns>
ParseInformation GetCachedParseInformation(FileName fileName, ITextSourceVersion version = null, IProject parentProject = null);
#endregion
#region Parse
/// <summary>
/// Parses the specified file.
/// Produces full parse information.
/// </summary>
/// <param name="fileName">Name of the file to parse</param>
/// <param name="fileContent">Optional: Content of the file to parse.</param>
/// <param name="parentProject">
/// Optional: If the file is part of multiple projects, specifies
/// which parsed version of the file to return (for example, different project settings
/// can cause the file to be parsed differently).
/// </param>
/// <returns>
/// Returns the ParseInformation for the specified file, or null if the file cannot be parsed.
/// For files currently open in an editor, this method does not necessary reparse, but may return
/// an existing cached parse information (but only if it's still up-to-date).
/// </returns>
/// <remarks>
/// This method is thread-safe.
/// <para>
/// If <paramref name="fileContent"/> is null, this method will block and wait for the main thread
/// to retrieve the latest file content. This can cause deadlocks if this method is called within a lock.
/// </para>
/// <para>
/// If <paramref name="fileContent"/> not null, the exact file version specified will be parsed.
/// This method will not wait for the main thread in that case.
/// If the specified version is older than the latest version, the old version will be parsed
/// and returned, but the old parse information will not be registered.
/// </para>
/// </remarks>
ParseInformation Parse(FileName fileName, ITextSource fileContent = null, IProject parentProject = null,
CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Parses the specified file.
/// This method does not request full parse information.
/// </summary>
/// <param name="fileName">Name of the file to parse</param>
/// <param name="fileContent">Optional: Content of the file to parse.</param>
/// <param name="parentProject">
/// Optional: If the file is part of multiple projects, specifies
/// which parsed version of the file to return (for example, different project settings
/// can cause the file to be parsed differently).
/// </param>
/// <returns>
/// Returns the IParsedFile for the specified file, or null if the file cannot be parsed.
/// For files currently open in an editor, this method does not necessarily reparse, but may return
/// the existing IParsedFile (but only if it's still up-to-date).
/// </returns>
/// <remarks><inheritdoc cref="Parse"/></remarks>
IParsedFile ParseFile(FileName fileName, ITextSource fileContent = null, IProject parentProject = null,
CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Parses the specified file on a background thread.
/// Produces full parse information.
/// </summary>
/// <param name="fileName">Name of the file to parse</param>
/// <param name="fileContent">Optional: Content of the file to parse.</param>
/// <param name="parentProject">
/// Optional: If the file is part of multiple projects, specifies
/// which parsed version of the file to return (for example, different project settings
/// can cause the file to be parsed differently).
/// </param>
/// <returns><inheritdoc cref="Parse"/></returns>
/// <remarks>
/// This method is thread-safe.
/// <para>
/// If <paramref name="fileContent"/> is null, the task wait for the main thread
/// to retrieve the latest file content.
/// This means that waiting for the task can cause deadlocks. (however, using C# 5 <c>await</c> is safe)
/// </para>
/// <para>
/// If <paramref name="fileContent"/> not null, the exact file version specified will be parsed.
/// This method will not wait for the main thread in that case.
/// If the specified version is older than the latest version, the old version will be parsed
/// and returned, but the old parse information will not be registered.
/// </para>
/// </remarks>
Task<ParseInformation> ParseAsync(FileName fileName, ITextSource fileContent = null, IProject parentProject = null,
CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Parses the specified file on a background thread.
/// This method does not request full parse information.
/// </summary>
/// <param name="fileName">Name of the file to parse</param>
/// <param name="fileContent">Optional: Content of the file to parse.</param>
/// <param name="parentProject">
/// Optional: If the file is part of multiple projects, specifies
/// which parsed version of the file to return (for example, different project settings
/// can cause the file to be parsed differently).
/// </param>
/// <returns><inheritdoc cref="ParseFile"/></returns>
/// <remarks><inheritdoc cref="ParseAsync"/></remarks>
Task<IParsedFile> ParseFileAsync(FileName fileName, ITextSource fileContent = null, IProject parentProject = null,
CancellationToken cancellationToken = default(CancellationToken));
#endregion
#region Resolve
ResolveResult Resolve(ITextEditor editor, TextLocation location,
ICompilation compilation = null,
CancellationToken cancellationToken = default(CancellationToken));
ResolveResult Resolve(FileName fileName, TextLocation location,
ITextSource fileContent = null, ICompilation compilation = null,
CancellationToken cancellationToken = default(CancellationToken));
Task<ResolveResult> ResolveAsync(FileName fileName, TextLocation location,
ITextSource fileContent = null, ICompilation compilation = null,
CancellationToken cancellationToken = default(CancellationToken));
Task FindLocalReferencesAsync(FileName fileName, IVariable variable, Action<Reference> callback,
ITextSource fileContent = null, ICompilation compilation = null,
CancellationToken cancellationToken = default(CancellationToken));
#endregion
#region Parsed File Listeners
/// <summary>
/// Gets whether a parser is registered for the specified file name.
/// </summary>
bool HasParser(FileName fileName);
/// <summary>
/// Clears the cached parse information.
/// If the file does not belong to any project, this also clears the cached type system.
/// </summary>
void ClearParseInformation(FileName fileName);
/// <summary>
/// Adds a project that owns the file and wishes to receive parse information.
/// </summary>
/// <param name="fileName">Name of the file contained in the project.</param>
/// <param name="project">The parent project of the file.</param>
/// <param name="startAsyncParse">
/// Whether to start an asynchronous parse operation for the specified file.
/// </param>
/// <param name="isLinkedFile">
/// Specified whether the file is linked within the project, i.e. likely also belongs to another project.
/// The parser services tries to use the project that contains the file directly (non-linked)
/// as the primary parent project.
/// </param>
void AddOwnerProject(FileName fileName, IProject project, bool startAsyncParse, bool isLinkedFile);
/// <summary>
/// Removes a project from the owners of the file.
/// This method invokes <c>project.UpdateParseInformation(existingParsedFile, null);</c>.
/// (unless existingParsedFile==null)
/// </summary>
void RemoveOwnerProject(FileName fileName, IProject project);
/// <summary>
/// Occurs whenever parse information was updated. This event is raised on the main thread.
/// </summary>
event EventHandler<ParseInformationEventArgs> ParseInformationUpdated;
#endregion
}
}

13
src/Main/Base/Project/Src/Services/ParserService/ParseInformationEventArgs.cs

@ -6,11 +6,13 @@ using System.Diagnostics;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.SharpDevelop.Parser namespace ICSharpCode.SharpDevelop.Parser
{ {
public class ParseInformationEventArgs : EventArgs public class ParseInformationEventArgs : EventArgs
{ {
IProject parentProject;
IParsedFile oldParsedFile; IParsedFile oldParsedFile;
ParseInformation newParseInformation; ParseInformation newParseInformation;
@ -23,6 +25,14 @@ namespace ICSharpCode.SharpDevelop.Parser
} }
} }
/// <summary>
/// Gets the parent project for this parse information.
/// Returns null if the parse information is not associated with any project.
/// </summary>
public IProject ParentProject {
get { return parentProject; }
}
/// <summary> /// <summary>
/// The old parsed file. /// The old parsed file.
/// Returns null if no old parse information exists (first parse run). /// Returns null if no old parse information exists (first parse run).
@ -57,13 +67,14 @@ namespace ICSharpCode.SharpDevelop.Parser
get { return this.NewParsedFile; } get { return this.NewParsedFile; }
} }
public ParseInformationEventArgs(IParsedFile oldParsedFile, ParseInformation newParseInformation) public ParseInformationEventArgs(IProject parentProject, IParsedFile oldParsedFile, ParseInformation newParseInformation)
{ {
if (oldParsedFile == null && newParseInformation == null) if (oldParsedFile == null && newParseInformation == null)
throw new ArgumentNullException(); throw new ArgumentNullException();
if (oldParsedFile != null && newParseInformation != null) { if (oldParsedFile != null && newParseInformation != null) {
Debug.Assert(FileUtility.IsEqualFileName(oldParsedFile.FileName, newParseInformation.FileName)); Debug.Assert(FileUtility.IsEqualFileName(oldParsedFile.FileName, newParseInformation.FileName));
} }
this.parentProject = parentProject;
this.oldParsedFile = oldParsedFile; this.oldParsedFile = oldParsedFile;
this.newParseInformation = newParseInformation; this.newParseInformation = newParseInformation;
} }

44
src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs

@ -26,7 +26,6 @@ namespace ICSharpCode.SharpDevelop.Parser
/// </summary> /// </summary>
readonly object lockObj = new object(); readonly object lockObj = new object();
readonly ParsedFileListener myListener;
IProjectContent projectContent; IProjectContent projectContent;
IAssemblyReference[] references = { MinimalCorlib.Instance }; IAssemblyReference[] references = { MinimalCorlib.Instance };
bool initializing; bool initializing;
@ -38,19 +37,18 @@ namespace ICSharpCode.SharpDevelop.Parser
throw new ArgumentNullException("project"); throw new ArgumentNullException("project");
this.project = project; this.project = project;
this.projectContent = initialProjectContent.SetAssemblyName(project.AssemblyName); this.projectContent = initialProjectContent.SetAssemblyName(project.AssemblyName);
this.myListener = new ParsedFileListener(OnParsedFileUpdated);
this.initializing = true; this.initializing = true;
LoadSolutionProjects.AddJob(Initialize, "Loading " + project.Name + "...", GetInitializationWorkAmount()); LoadSolutionProjects.AddJob(Initialize, "Loading " + project.Name + "...", GetInitializationWorkAmount());
} }
void OnParsedFileUpdated(IParsedFile oldFile, IParsedFile newFile) public void ParseInformationUpdated(IParsedFile oldFile, IParsedFile newFile)
{ {
// This method is called by the parser service within the parser service lock. // This method is called by the parser service within the parser service lock.
lock (lockObj) { lock (lockObj) {
if (!disposed) if (!disposed)
projectContent = projectContent.UpdateProjectContent(oldFile, newFile); projectContent = projectContent.UpdateProjectContent(oldFile, newFile);
ParserService.InvalidateCurrentSolutionSnapshot(); SD.ParserService.InvalidateCurrentSolutionSnapshot();
} }
} }
@ -64,7 +62,7 @@ namespace ICSharpCode.SharpDevelop.Parser
disposed = true; disposed = true;
} }
foreach (var fileName in GetFilesToParse(project.Items)) { foreach (var fileName in GetFilesToParse(project.Items)) {
ParserService.RemoveParsedFileListener(fileName, myListener); SD.ParserService.RemoveOwnerProject(fileName.Item1, project);
} }
initializing = false; initializing = false;
} }
@ -107,12 +105,14 @@ namespace ICSharpCode.SharpDevelop.Parser
initializing = false; initializing = false;
} }
IEnumerable<FileName> GetFilesToParse(IEnumerable<ProjectItem> projectItems) static readonly ItemType[] compilableItemTypes = { ItemType.Compile, ItemType.Page };
IEnumerable<Tuple<FileName, bool>> GetFilesToParse(IEnumerable<ProjectItem> projectItems)
{ {
return ( return
from p in projectItems from p in projectItems.OfType<FileProjectItem>()
where (p.ItemType == ItemType.Compile || p.ItemType == ItemType.Page) && !String.IsNullOrEmpty(p.FileName) where compilableItemTypes.Contains(p.ItemType) && !String.IsNullOrEmpty(p.FileName)
select FileName.Create(p.FileName)); select Tuple.Create(FileName.Create(p.FileName), p.IsLink);
} }
void ParseFiles(ICollection<ProjectItem> projectItems, IProgressMonitor progressMonitor) void ParseFiles(ICollection<ProjectItem> projectItems, IProgressMonitor progressMonitor)
@ -128,16 +128,17 @@ namespace ICSharpCode.SharpDevelop.Parser
MaxDegreeOfParallelism = Environment.ProcessorCount, MaxDegreeOfParallelism = Environment.ProcessorCount,
CancellationToken = progressMonitor.CancellationToken CancellationToken = progressMonitor.CancellationToken
}, },
fileName => { tuple => {
var fileName = tuple.Item1;
// Don't read files we don't have a parser for. // Don't read files we don't have a parser for.
// This avoids loading huge files (e.g. sdps) when we have no intention of parsing them. // This avoids loading huge files (e.g. sdps) when we have no intention of parsing them.
if (ParserService.HasParser(fileName)) { if (SD.ParserService.HasParser(fileName)) {
ParserService.AddParsedFileListener(fileName, myListener, startAsyncParse: false); // We don't start an asynchronous parse operation since we want to
// parse on this thread.
SD.ParserService.AddOwnerProject(fileName, project, startAsyncParse: false, isLinkedFile: tuple.Item2);
ITextSource content = finder.Create(fileName); ITextSource content = finder.Create(fileName);
if (content != null) { if (content != null) {
// Parse the file on this thread so that AddParsedFileListener() does not SD.ParserService.ParseFile(fileName, content, project);
// start an asynchronous parse operation.
ParserService.ParseFile(fileName, content);
} }
} }
lock (progressLock) { lock (progressLock) {
@ -181,7 +182,7 @@ namespace ICSharpCode.SharpDevelop.Parser
lock (lockObj) { lock (lockObj) {
projectContent = projectContent.RemoveAssemblyReferences(this.references).AddAssemblyReferences(newReferences); projectContent = projectContent.RemoveAssemblyReferences(this.references).AddAssemblyReferences(newReferences);
this.references = newReferences.ToArray(); this.references = newReferences.ToArray();
ParserService.InvalidateCurrentSolutionSnapshot(); SD.ParserService.InvalidateCurrentSolutionSnapshot();
} }
}, progressMonitor.CancellationToken); }, progressMonitor.CancellationToken);
} }
@ -230,9 +231,10 @@ namespace ICSharpCode.SharpDevelop.Parser
ReparseReferences(); ReparseReferences();
} }
} }
if (e.ProjectItem.ItemType == ItemType.Compile) { FileProjectItem fileProjectItem = e.ProjectItem as FileProjectItem;
if (fileProjectItem != null && compilableItemTypes.Contains(fileProjectItem.ItemType)) {
var fileName = FileName.Create(e.ProjectItem.FileName); var fileName = FileName.Create(e.ProjectItem.FileName);
ParserService.AddParsedFileListener(fileName, myListener, startAsyncParse: true); SD.ParserService.AddOwnerProject(fileName, project, startAsyncParse: true, isLinkedFile: fileProjectItem.IsLink);
} }
} }
@ -255,7 +257,7 @@ namespace ICSharpCode.SharpDevelop.Parser
} }
if (e.ProjectItem.ItemType == ItemType.Compile) { if (e.ProjectItem.ItemType == ItemType.Compile) {
ParserService.RemoveParsedFileListener(FileName.Create(e.ProjectItem.FileName), myListener); SD.ParserService.RemoveOwnerProject(FileName.Create(e.ProjectItem.FileName), project);
} }
} }
} }

18
src/Main/Base/Project/Src/Services/ParserService/ParsedFileListener.cs

@ -1,18 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.SharpDevelop.Parser
{
/// <summary>
/// Listener for parse info changes.
/// Caution: The callback is invoked within the parser service's lock. Beware of deadlocks!
/// The method is called on the thread that performed the parse operation, which might be the main thread
/// or a background thread.
/// If possible, use the <see cref="ParserService.ParseInformationUpdated"/> event instead, which is called on the main thread
/// and after the parser service released its lock.
/// </summary>
public delegate void ParsedFileListener(IParsedFile oldFile, IParsedFile newFile);
}

1026
src/Main/Base/Project/Src/Services/ParserService/ParserService.cs

File diff suppressed because it is too large Load Diff

6
src/Main/Base/Project/Src/Services/ProjectService/ParseableFileContentFinder.cs

@ -17,7 +17,7 @@ namespace ICSharpCode.SharpDevelop.Project
/// </summary> /// </summary>
public class ParseableFileContentFinder public class ParseableFileContentFinder
{ {
FileName[] viewContentFileNamesCollection = WorkbenchSingleton.SafeThreadFunction(() => FileService.OpenedFiles.Select(f => f.FileName).ToArray()); FileName[] viewContentFileNamesCollection = SD.MainThread.InvokeIfRequired(() => FileService.OpenedFiles.Select(f => f.FileName).ToArray());
/// <summary> /// <summary>
/// Retrieves the file contents for the specified project items. /// Retrieves the file contents for the specified project items.
@ -26,10 +26,10 @@ namespace ICSharpCode.SharpDevelop.Project
{ {
foreach (FileName name in viewContentFileNamesCollection) { foreach (FileName name in viewContentFileNamesCollection) {
if (FileUtility.IsEqualFileName(name, fileName)) if (FileUtility.IsEqualFileName(name, fileName))
return WorkbenchSingleton.SafeThreadFunction(ParserService.GetParseableFileContent, fileName.ToString()); return SD.FileService.GetFileContent(fileName);
} }
try { try {
return new StringTextSource(ICSharpCode.AvalonEdit.Utils.FileReader.ReadFileContent(fileName, ParserService.DefaultFileEncoding)); return new StringTextSource(ICSharpCode.AvalonEdit.Utils.FileReader.ReadFileContent(fileName, SD.FileService.DefaultFileEncoding));
} catch (IOException) { } catch (IOException) {
return null; return null;
} catch (UnauthorizedAccessException) { } catch (UnauthorizedAccessException) {

4
src/Main/Base/Project/Src/Services/ProjectService/ProjectService.cs

@ -300,8 +300,7 @@ namespace ICSharpCode.SharpDevelop.Project
} catch (Exception ex) { } catch (Exception ex) {
MessageService.ShowException(ex); MessageService.ShowException(ex);
} }
// Create project contents for solution SD.ParserService.InvalidateCurrentSolutionSnapshot();
ParserService.OnSolutionLoaded();
Project.Converter.UpgradeViewContent.ShowIfRequired(openSolution); Project.Converter.UpgradeViewContent.ShowIfRequired(openSolution);
@ -549,7 +548,6 @@ namespace ICSharpCode.SharpDevelop.Project
openSolution.Dispose(); openSolution.Dispose();
openSolution = null; openSolution = null;
ParserService.OnSolutionClosed();
OnSolutionClosed(EventArgs.Empty); OnSolutionClosed(EventArgs.Empty);
CommandManager.InvalidateRequerySuggested(); CommandManager.InvalidateRequerySuggested();

35
src/Main/Base/Project/Src/Services/RefactoringService/FindReferenceService.cs

@ -67,7 +67,8 @@ namespace ICSharpCode.SharpDevelop.Refactoring
throw new ArgumentNullException("progressMonitor"); throw new ArgumentNullException("progressMonitor");
if (callback == null) if (callback == null)
throw new ArgumentNullException("callback"); throw new ArgumentNullException("callback");
if (ParserService.LoadSolutionProjectsThreadRunning) { SD.MainThread.VerifyAccess();
if (SD.ParserService.LoadSolutionProjectsThreadRunning) {
progressMonitor.ShowingDialog = true; progressMonitor.ShowingDialog = true;
MessageService.ShowMessage("${res:SharpDevelop.Refactoring.LoadSolutionProjectsThreadRunning}"); MessageService.ShowMessage("${res:SharpDevelop.Refactoring.LoadSolutionProjectsThreadRunning}");
progressMonitor.ShowingDialog = false; progressMonitor.ShowingDialog = false;
@ -90,26 +91,34 @@ namespace ICSharpCode.SharpDevelop.Refactoring
public static IObservable<SearchedFile> FindReferences(IEntity entity, IProgressMonitor progressMonitor) public static IObservable<SearchedFile> FindReferences(IEntity entity, IProgressMonitor progressMonitor)
{ {
return ReactiveExtensions.CreateObservable<SearchedFile>((monitor, callback) => FindReferencesAsync(entity, monitor, callback), progressMonitor); return ReactiveExtensions.CreateObservable<SearchedFile>(
(monitor, callback) => FindReferencesAsync(entity, monitor, callback),
progressMonitor);
} }
/// <summary> /// <summary>
/// Finds references to a local variable. /// Finds references to a local variable.
/// </summary> /// </summary>
public static void FindReferences(IVariable variable, Action<Reference> callback) public static async Task<SearchedFile> FindLocalReferencesAsync(IVariable variable, IProgressMonitor progressMonitor)
{ {
if (variable == null) if (variable == null)
throw new ArgumentNullException("variable"); throw new ArgumentNullException("variable");
if (callback == null) if (progressMonitor == null)
throw new ArgumentNullException("callback"); throw new ArgumentNullException("progressMonitor");
var fileName = FileName.Create(variable.Region.FileName); var fileName = FileName.Create(variable.Region.FileName);
IParser parser = ParserService.GetParser(fileName); List<Reference> references = new List<Reference>();
var fileContent = ParserService.GetParseableFileContent(fileName); await SD.ParserService.FindLocalReferencesAsync(
ParseInformation pi = ParserService.Parse(fileName, fileContent); fileName, variable,
if (pi == null || parser == null) r => { lock (references) references.Add(r); },
return; cancellationToken: progressMonitor.CancellationToken);
var compilation = ParserService.GetCompilationForFile(fileName); return new SearchedFile(fileName, references);
parser.FindLocalReferences(pi, fileContent, variable, compilation, callback, CancellationToken.None); }
public static IObservable<SearchedFile> FindLocalReferences(IVariable variable, IProgressMonitor progressMonitor)
{
return ReactiveExtensions.CreateObservable<SearchedFile>(
(monitor, callback) => FindLocalReferencesAsync(variable, monitor).ContinueWith(t => callback(t.Result)),
progressMonitor);
} }
#endregion #endregion
@ -148,7 +157,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
static SharpDevelopSolutionSnapshot GetSolutionSnapshot(ICompilation compilation) static SharpDevelopSolutionSnapshot GetSolutionSnapshot(ICompilation compilation)
{ {
var snapshot = compilation.SolutionSnapshot as SharpDevelopSolutionSnapshot; var snapshot = compilation.SolutionSnapshot as SharpDevelopSolutionSnapshot;
return snapshot ?? ParserService.GetCurrentSolutionSnapshot(); return snapshot ?? SD.ParserService.GetCurrentSolutionSnapshot();
} }

19
src/Main/Base/Project/Src/Services/RefactoringService/FindReferencesAndRenameHelper.cs

@ -234,6 +234,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
*/ */
#region Common helper functions #region Common helper functions
[Obsolete]
public static ProvidedDocumentInformation GetDocumentInformation(string fileName) public static ProvidedDocumentInformation GetDocumentInformation(string fileName)
{ {
OpenedFile file = FileService.GetOpenedFile(fileName); OpenedFile file = FileService.GetOpenedFile(fileName);
@ -246,7 +247,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
} }
} }
} }
ITextSource fileContent = ParserService.GetParseableFileContent(fileName); ITextSource fileContent = SD.FileService.GetFileContent(fileName);
return new ProvidedDocumentInformation(fileContent, fileName, 0); return new ProvidedDocumentInformation(fileContent, fileName, 0);
} }
@ -352,6 +353,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
} }
*/ */
[Obsolete]
public static void ShowAsSearchResults(string title, List<Reference> list) public static void ShowAsSearchResults(string title, List<Reference> list)
{ {
if (list == null) return; if (list == null) return;
@ -361,7 +363,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
IHighlighter highlighter = null; IHighlighter highlighter = null;
foreach (Reference r in list) { foreach (Reference r in list) {
if (document == null || fileName != r.FileName) { if (document == null || fileName != r.FileName) {
document = new TextDocument(ParserService.GetParseableFileContent(r.FileName)); document = new TextDocument(SD.FileService.GetFileContent(r.FileName));
fileName = r.FileName; fileName = r.FileName;
var def = HighlightingManager.Instance.GetDefinitionByExtension(Path.GetExtension(r.FileName)); var def = HighlightingManager.Instance.GetDefinitionByExtension(Path.GetExtension(r.FileName));
if (def != null) if (def != null)
@ -530,7 +532,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
public static void RunFindReferences(IEntity entity) public static void RunFindReferences(IEntity entity)
{ {
string entityName = (entity.DeclaringTypeDefinition != null ? entity.DeclaringTypeDefinition.Name + "." + entity.Name : entity.Name); string entityName = (entity.DeclaringTypeDefinition != null ? entity.DeclaringTypeDefinition.Name + "." + entity.Name : entity.Name);
var monitor = WorkbenchSingleton.StatusBar.CreateProgressMonitor(); var monitor = SD.StatusBar.CreateProgressMonitor();
var results = FindReferenceService.FindReferences(entity, monitor); var results = FindReferenceService.FindReferences(entity, monitor);
SearchResultsPad.Instance.ShowSearchResults(StringParser.Parse("${res:SharpDevelop.Refactoring.ReferencesTo}", new StringTagPair("Name", entityName)), results); SearchResultsPad.Instance.ShowSearchResults(StringParser.Parse("${res:SharpDevelop.Refactoring.ReferencesTo}", new StringTagPair("Name", entityName)), results);
SearchResultsPad.Instance.BringToFront(); SearchResultsPad.Instance.BringToFront();
@ -538,13 +540,10 @@ namespace ICSharpCode.SharpDevelop.Refactoring
public static void RunFindReferences(LocalResolveResult local) public static void RunFindReferences(LocalResolveResult local)
{ {
var references = new List<Reference>(); var monitor = SD.StatusBar.CreateProgressMonitor();
FindReferenceService.FindReferences(local.Variable, r => { lock (references) references.Add(r); }); var results = FindReferenceService.FindLocalReferences(local.Variable, monitor);
FindReferencesAndRenameHelper.ShowAsSearchResults( SearchResultsPad.Instance.ShowSearchResults(StringParser.Parse("${res:SharpDevelop.Refactoring.ReferencesTo}", new StringTagPair("Name", local.Variable.Name)), results);
StringParser.Parse("${res:SharpDevelop.Refactoring.ReferencesTo}", SearchResultsPad.Instance.BringToFront();
new StringTagPair("Name", local.Variable.Name)),
references
);
} }
// public static ICSharpCode.Core.WinForms.MenuCommand MakeFindReferencesMenuCommand(EventHandler handler) // public static ICSharpCode.Core.WinForms.MenuCommand MakeFindReferencesMenuCommand(EventHandler handler)

18
src/Main/Base/Project/Src/Services/SD.cs

@ -2,11 +2,13 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System; using System;
using System.ComponentModel;
using System.ComponentModel.Design; using System.ComponentModel.Design;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.Core.Implementation; using ICSharpCode.Core.Implementation;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Parser;
namespace ICSharpCode.SharpDevelop namespace ICSharpCode.SharpDevelop
{ {
@ -60,6 +62,10 @@ namespace ICSharpCode.SharpDevelop
get { return GetRequiredService<IWorkbench>(); } get { return GetRequiredService<IWorkbench>(); }
} }
public static IMessageLoop MainThread {
get { return GetRequiredService<IMessageLoop>(); }
}
/// <summary> /// <summary>
/// Gets the status bar. /// Gets the status bar.
/// </summary> /// </summary>
@ -82,5 +88,17 @@ namespace ICSharpCode.SharpDevelop
public static IAnalyticsMonitor AnalyticsMonitor { public static IAnalyticsMonitor AnalyticsMonitor {
get { return GetRequiredService<IAnalyticsMonitor>(); } get { return GetRequiredService<IAnalyticsMonitor>(); }
} }
public static IParserService ParserService {
get { return GetRequiredService<IParserService>(); }
}
public static IFileService FileService {
get { return GetRequiredService<IFileService>(); }
}
public static IGlobalAssemblyCacheService GlobalAssemblyCache {
get { return GetRequiredService<IGlobalAssemblyCacheService>(); }
}
} }
} }

6
src/Main/Base/Project/Src/Services/Tasks/TaskService.cs

@ -77,15 +77,15 @@ namespace ICSharpCode.SharpDevelop
internal static void Initialize() internal static void Initialize()
{ {
// avoid trouble with double initialization // avoid trouble with double initialization
ParserService.ParseInformationUpdated -= ParserService_ParseInformationUpdated; SD.ParserService.ParseInformationUpdated -= ParserService_ParseInformationUpdated;
ParserService.ParseInformationUpdated += ParserService_ParseInformationUpdated; SD.ParserService.ParseInformationUpdated += ParserService_ParseInformationUpdated;
ProjectService.SolutionClosed -= ProjectServiceSolutionClosed; ProjectService.SolutionClosed -= ProjectServiceSolutionClosed;
ProjectService.SolutionClosed += ProjectServiceSolutionClosed; ProjectService.SolutionClosed += ProjectServiceSolutionClosed;
} }
static void ParserService_ParseInformationUpdated(object sender, ParseInformationEventArgs e) static void ParserService_ParseInformationUpdated(object sender, ParseInformationEventArgs e)
{ {
if (e.NewParsedFile == ParserService.GetExistingParsedFile(e.FileName)) { if (e.NewParsedFile == SD.ParserService.GetExistingParsedFile(e.FileName)) {
// Call UpdateCommentTags only for the main parse information (if a file is in multiple projects), // Call UpdateCommentTags only for the main parse information (if a file is in multiple projects),
// and only if the results haven't already been replaced with a more recent ParseInformation. // and only if the results haven't already been replaced with a more recent ParseInformation.
if (e.NewParseInformation != null) { if (e.NewParseInformation != null) {

2
src/Main/Base/Project/Src/Util/ExtensionMethods.cs

@ -583,7 +583,7 @@ namespace ICSharpCode.SharpDevelop
return newContent; return newContent;
} }
public static int IndexOfAny(this string haystack, string[] needles, int startIndex, out int matchLength) public static int IndexOfAny(this string haystack, IEnumerable<string> needles, int startIndex, out int matchLength)
{ {
if (haystack == null) if (haystack == null)
throw new ArgumentNullException("haystack"); throw new ArgumentNullException("haystack");

115
src/Main/Base/Project/Src/Util/MultiDictionary.cs

@ -0,0 +1,115 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory;
namespace ICSharpCode.SharpDevelop
{
/// <summary>
/// A dictionary that allows multiple pairs with the same key.
/// </summary>
public class MultiDictionary<TKey, TValue> : ILookup<TKey, TValue>
{
Dictionary<TKey, List<TValue>> dict;
public MultiDictionary()
{
}
public MultiDictionary(IEqualityComparer<TKey> comparer)
{
dict = new Dictionary<TKey, List<TValue>>(comparer);
}
public void Add(TKey key, TValue value)
{
List<TValue> valueList;
if (!dict.TryGetValue(key, out valueList)) {
valueList = new List<TValue>();
dict.Add(key, valueList);
}
valueList.Add(value);
}
public bool Remove(TKey key, TValue value)
{
List<TValue> valueList;
if (dict.TryGetValue(key, out valueList)) {
if (valueList.Remove(value)) {
if (valueList.Count == 0)
dict.Remove(key);
return true;
}
}
return false;
}
public void Clear()
{
dict.Clear();
}
public IReadOnlyList<TValue> this[TKey key] {
get {
List<TValue> list;
if (dict.TryGetValue(key, out list))
return list;
else
return new TValue[0];
}
}
public int Count {
get { return dict.Count; }
}
IEnumerable<TValue> ILookup<TKey, TValue>.this[TKey key] {
get { return this[key]; }
}
bool ILookup<TKey, TValue>.Contains(TKey key)
{
return dict.ContainsKey(key);
}
public IEnumerator<IGrouping<TKey, TValue>> GetEnumerator()
{
foreach (var pair in dict)
yield return new Grouping(pair.Key, pair.Value);
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
sealed class Grouping : IGrouping<TKey, TValue>
{
readonly TKey key;
readonly List<TValue> values;
public Grouping(TKey key, List<TValue> values)
{
this.key = key;
this.values = values;
}
public TKey Key {
get { return key; }
}
public IEnumerator<TValue> GetEnumerator()
{
return values.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return values.GetEnumerator();
}
}
}
}

16
src/Main/Base/Project/Src/Util/ReactiveExtensions.cs

@ -3,10 +3,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Runtime.ExceptionServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Threading;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.SharpDevelop namespace ICSharpCode.SharpDevelop
@ -91,15 +91,17 @@ namespace ICSharpCode.SharpDevelop
return source.Subscribe(new AnonymousObserver<T>(onNext, onError, onCompleted)); return source.Subscribe(new AnonymousObserver<T>(onNext, onError, onCompleted));
} }
public static List<T> ToList<T>(this IObservable<T> source, CancellationToken cancellation) public static List<T> ToList<T>(this IObservable<T> source, CancellationToken cancellationToken)
{ {
List<T> results = new List<T>(); List<T> results = new List<T>();
ManualResetEventSlim ev = new ManualResetEventSlim(); ManualResetEventSlim ev = new ManualResetEventSlim();
Exception error = null; ExceptionDispatchInfo error = null;
using (source.Subscribe(item => results.Add(item), exception => { error = exception; ev.Set(); }, () => ev.Set())) using (source.Subscribe(item => results.Add(item),
ev.Wait(cancellation); exception => { error = ExceptionDispatchInfo.Capture(exception); ev.Set(); },
() => ev.Set()))
ev.Wait(cancellationToken);
if (error != null) if (error != null)
throw new TargetInvocationException(error); error.Throw();
return results; return results;
} }

112
src/Main/Base/Project/Src/Util/WorkerThread.cs

@ -1,112 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Threading;
namespace ICSharpCode.SharpDevelop.Util
{
/// <summary>
/// A worker thread that normally sleeps, but can run a queue of commands.
///
/// This class does not create a worker thread on its own, it merely manages tasks for
/// the worker thread that calls <see cref="RunLoop"/>.
/// </summary>
public class WorkerThread
{
sealed class AsyncTask : IAsyncResult
{
internal readonly ManualResetEventSlim manualResetEvent = new ManualResetEventSlim(false);
internal readonly Action method;
volatile bool isCompleted;
internal AsyncTask(Action method)
{
this.method = method;
}
internal void SetCompleted()
{
isCompleted = true;
manualResetEvent.Set();
}
public bool IsCompleted {
get { return isCompleted; }
}
public WaitHandle AsyncWaitHandle {
get { return manualResetEvent.WaitHandle; }
}
public object AsyncState { get; set; }
public bool CompletedSynchronously { get { return false; } }
}
/// <summary>
/// Runs <paramref name="method"/> on the worker thread.
/// </summary>
/// <param name="method">The method to run.</param>
/// <returns>IAsyncResult that gets completed when the action has executed.</returns>
public IAsyncResult Enqueue(Action method)
{
if (method == null)
throw new ArgumentNullException("method");
AsyncTask task = new AsyncTask(method);
lock (lockObject) {
taskQueue.Enqueue(task);
Monitor.Pulse(lockObject);
}
return task;
}
readonly object lockObject = new object();
// access needs lock using 'lockObject'
Queue<AsyncTask> taskQueue = new Queue<AsyncTask>();
// access needs lock using 'lockObject'
bool workerRunning;
// not a shared variable: accessed only within worker thread
bool exitWorker;
/// <summary>
/// Runs the worker thread loop on the current thread.
/// </summary>
public void RunLoop()
{
lock (lockObject) {
if (workerRunning)
throw new InvalidOperationException("There already is a worker running");
workerRunning = true;
}
try {
exitWorker = false;
while (!exitWorker) {
AsyncTask task;
lock (lockObject) {
while (taskQueue.Count == 0)
Monitor.Wait(lockObject);
task = taskQueue.Dequeue();
}
task.method();
task.SetCompleted();
}
} finally {
lock (lockObject) {
workerRunning = false;
}
}
}
/// <summary>
/// Exits running the worker thread after executing all currently enqueued methods.
/// </summary>
/// <returns>IAsyncResult that gets completed when the worker thread has shut down.</returns>
public IAsyncResult ExitWorkerThread()
{
return Enqueue(delegate { exitWorker = true; });
}
}
}

120
src/Main/Base/Project/Src/Util/WpfSynchronizeInvoke.cs

@ -1,120 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.ComponentModel;
using System.Reflection;
using System.Threading;
using System.Windows.Threading;
namespace ICSharpCode.SharpDevelop
{
/// <summary>
/// Implements the ISynchronizeInvoke interface by using a WPF dispatcher
/// to perform the cross-thread call.
/// </summary>
sealed class WpfSynchronizeInvoke : ISynchronizeInvoke
{
readonly Dispatcher dispatcher;
public WpfSynchronizeInvoke(Dispatcher dispatcher)
{
if (dispatcher == null)
throw new ArgumentNullException("dispatcher");
this.dispatcher = dispatcher;
}
public bool InvokeRequired {
get {
return !dispatcher.CheckAccess();
}
}
public IAsyncResult BeginInvoke(Delegate method, object[] args)
{
DispatcherOperation op;
if (args == null || args.Length == 0)
op = dispatcher.BeginInvoke(DispatcherPriority.Normal, method);
else if (args.Length == 1)
op = dispatcher.BeginInvoke(DispatcherPriority.Normal, method, args[0]);
else
op = dispatcher.BeginInvoke(DispatcherPriority.Normal, method, args[0], args.Splice(1));
return new AsyncResult(op);
}
sealed class AsyncResult : IAsyncResult
{
internal readonly DispatcherOperation op;
readonly object lockObj = new object();
ManualResetEvent resetEvent;
public AsyncResult(DispatcherOperation op)
{
this.op = op;
}
public bool IsCompleted {
get {
return op.Status == DispatcherOperationStatus.Completed;
}
}
public WaitHandle AsyncWaitHandle {
get {
lock (lockObj) {
if (resetEvent == null) {
op.Completed += op_Completed;
resetEvent = new ManualResetEvent(false);
if (IsCompleted)
resetEvent.Set();
}
return resetEvent;
}
}
}
void op_Completed(object sender, EventArgs e)
{
lock (lockObj) {
resetEvent.Set();
}
}
public object AsyncState {
get { return null; }
}
public bool CompletedSynchronously {
get { return false; }
}
}
public object EndInvoke(IAsyncResult result)
{
AsyncResult r = result as AsyncResult;
if (r == null)
throw new ArgumentException("result must be the return value of a WpfSynchronizeInvoke.BeginInvoke call!");
r.op.Wait();
return r.op.Result;
}
public object Invoke(Delegate method, object[] args)
{
object result = null;
Exception exception = null;
dispatcher.Invoke(
DispatcherPriority.Normal,
(Action)delegate {
try {
result = method.DynamicInvoke(args);
} catch (TargetInvocationException ex) {
exception = ex.InnerException;
}
});
// if an exception occurred, re-throw it on the calling thread
if (exception != null)
throw new TargetInvocationException(exception);
return result;
}
}
}

0
src/Main/Base/Project/Src/Services/ParserService/Fusion.cs → src/Main/SharpDevelop/Parser/Fusion.cs

28
src/Main/Base/Project/Src/Services/ParserService/GacInterop.cs → src/Main/SharpDevelop/Parser/GlobalAssemblyCacheService.cs

@ -1,25 +1,21 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
// Based on the MIT-licensed GacInterop.cs from ILSpy.
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;
using Mono.Cecil;
namespace ICSharpCode.SharpDevelop.Parser namespace ICSharpCode.SharpDevelop.Parser
{ {
/// <summary> sealed class GlobalAssemblyCacheService : IGlobalAssemblyCacheService
/// Interop with the .NET GAC.
/// </summary>
public static class GacInterop
{ {
/// <summary> public bool IsGACAssembly(string fileName)
/// Gets the names of all assemblies in the GAC. {
/// </summary> throw new NotImplementedException();
public static IEnumerable<DomAssemblyName> GetGacAssemblyFullNames() }
public IEnumerable<DomAssemblyName> GetGacAssemblyFullNames()
{ {
IApplicationContext applicationContext = null; IApplicationContext applicationContext = null;
IAssemblyEnum assemblyEnum = null; IAssemblyEnum assemblyEnum = null;
@ -37,7 +33,7 @@ namespace ICSharpCode.SharpDevelop.Parser
} }
} }
#region FindAssemblyInGac #region FindAssemblyInNetGac
// This region is based on code from Mono.Cecil: // This region is based on code from Mono.Cecil:
// Author: // Author:
@ -65,14 +61,14 @@ namespace ICSharpCode.SharpDevelop.Parser
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// //
static readonly string[] gac_paths = { Fusion.GetGacPath(false), Fusion.GetGacPath(true) }; readonly string[] gac_paths = { Fusion.GetGacPath(false), Fusion.GetGacPath(true) };
static readonly string[] gacs = { "GAC_MSIL", "GAC_32", "GAC" }; readonly string[] gacs = { "GAC_MSIL", "GAC_32", "GAC" };
static readonly string[] prefixes = { string.Empty, "v4.0_" }; readonly string[] prefixes = { string.Empty, "v4.0_" };
/// <summary> /// <summary>
/// Gets the file name for an assembly stored in the GAC. /// Gets the file name for an assembly stored in the GAC.
/// </summary> /// </summary>
public static string FindAssemblyInNetGac (DomAssemblyName reference) public string FindAssemblyInNetGac (DomAssemblyName reference)
{ {
// without public key, it can't be in the GAC // without public key, it can't be in the GAC
if (reference.PublicKeyToken == null) if (reference.PublicKeyToken == null)

2
src/Main/Base/Project/Src/Services/ParserService/Doozer/ParserDescriptor.cs → src/Main/SharpDevelop/Parser/ParserDescriptor.cs

@ -8,7 +8,7 @@ using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.SharpDevelop.Parser namespace ICSharpCode.SharpDevelop.Parser
{ {
public sealed class ParserDescriptor sealed class ParserDescriptor
{ {
Codon codon; Codon codon;
Type parserType; Type parserType;

2
src/Main/Base/Project/Src/Services/ParserService/Doozer/ParserDoozer.cs → src/Main/SharpDevelop/Parser/ParserDoozer.cs

@ -20,7 +20,7 @@ namespace ICSharpCode.SharpDevelop.Parser
/// <returns> /// <returns>
/// An ParserDescriptor object that wraps the IParser object. /// An ParserDescriptor object that wraps the IParser object.
/// </returns> /// </returns>
public sealed class ParserDoozer : IDoozer sealed class ParserDoozer : IDoozer
{ {
/// <summary> /// <summary>
/// Gets if the doozer handles codon conditions on its own. /// Gets if the doozer handles codon conditions on its own.

359
src/Main/SharpDevelop/Parser/ParserService.cs

@ -0,0 +1,359 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Threading;
using ICSharpCode.Core;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Refactoring;
namespace ICSharpCode.SharpDevelop.Parser
{
sealed class ParserService : IParserService
{
IList<ParserDescriptor> parserDescriptors;
public ParserService()
{
parserDescriptors = AddInTree.BuildItems<ParserDescriptor>("/Workspace/Parser", null, false);
}
#region ParseInformationUpdated
public event EventHandler<ParseInformationEventArgs> ParseInformationUpdated = delegate {};
internal void RaiseParseInformationUpdated(ParseInformationEventArgs e)
{
// RaiseParseInformationUpdated is called inside a lock, but we don't want to raise the event inside that lock.
// To ensure events are raised in the same order, we always invoke on the main thread.
WorkbenchSingleton.SafeThreadAsyncCall(
delegate {
string addition;
if (e.OldParsedFile == null)
addition = " (new)";
else if (e.NewParsedFile == null)
addition = " (removed)";
else
addition = " (updated)";
LoggingService.Debug("ParseInformationUpdated " + e.FileName + addition);
ParseInformationUpdated(null, e);
});
}
#endregion
#region TaskListTokens
IReadOnlyList<string> taskListTokens = LoadTaskListTokens();
public IReadOnlyList<string> TaskListTokens {
get { return taskListTokens; }
set {
SD.MainThread.VerifyAccess();
if (!value.SequenceEqual(taskListTokens)) {
taskListTokens = value.ToArray();
PropertyService.SetList("SharpDevelop.TaskListTokens", taskListTokens);
// TODO: trigger reparse?
}
}
}
static IReadOnlyList<string> LoadTaskListTokens()
{
if (PropertyService.Contains("SharpDevelop.TaskListTokens"))
return PropertyService.GetList<string>("SharpDevelop.TaskListTokens").ToArray();
else
return new string[] { "HACK", "TODO", "UNDONE", "FIXME" };
}
#endregion
#region Load Solution Projects Thread
public bool LoadSolutionProjectsThreadRunning {
get { return false; }
}
public event EventHandler LoadSolutionProjectsThreadStarted;
public event EventHandler LoadSolutionProjectsThreadEnded;
#endregion
#region Compilation
public ICompilation GetCompilation(IProject project)
{
return GetCurrentSolutionSnapshot().GetCompilation(project);
}
public ICompilation GetCompilationForFile(FileName fileName)
{
Solution solution = ProjectService.OpenSolution;
IProject project = solution != null ? solution.FindProjectContainingFile(fileName) : null;
if (project != null)
return GetCompilation(project);
var entry = GetFileEntry(fileName, false);
if (entry != null && entry.parser != null) {
var parsedFile = entry.GetExistingParsedFile(null, null);
if (parsedFile != null) {
ICompilation compilation = entry.parser.CreateCompilationForSingleFile(fileName, parsedFile);
if (compilation != null)
return compilation;
}
}
return MinimalCorlib.Instance.CreateCompilation();
}
// Use a WeakReference for caching the solution snapshot - it can require
// lots of memory and may not be invalidated soon enough if the user
// is only browsing code.
volatile WeakReference<SharpDevelopSolutionSnapshot> currentSolutionSnapshot;
public SharpDevelopSolutionSnapshot GetCurrentSolutionSnapshot()
{
var weakRef = currentSolutionSnapshot;
SharpDevelopSolutionSnapshot result;
if (weakRef == null || !weakRef.TryGetTarget(out result)) {
// create new snapshot if we don't have one cached
result = new SharpDevelopSolutionSnapshot(ProjectService.OpenSolution);
currentSolutionSnapshot = new WeakReference<SharpDevelopSolutionSnapshot>(result);
}
return result;
}
public void InvalidateCurrentSolutionSnapshot()
{
currentSolutionSnapshot = null;
}
#endregion
#region Entry management
const int cachedEntryCount = 5;
Dictionary<FileName, ParserServiceEntry> fileEntryDict = new Dictionary<FileName, ParserServiceEntry>();
Queue<ParserServiceEntry> cacheExpiryQueue = new Queue<ParserServiceEntry>();
ParserServiceEntry GetFileEntry(FileName fileName, bool createIfMissing)
{
if (fileName == null)
throw new ArgumentNullException("fileName");
ParserServiceEntry entry;
lock (fileEntryDict) {
if (!fileEntryDict.TryGetValue(fileName, out entry)) {
if (!createIfMissing)
return null;
entry = new ParserServiceEntry(this, fileName);
fileEntryDict.Add(fileName, entry);
}
}
return entry;
}
public void ClearParseInformation(FileName fileName)
{
ParserServiceEntry entry = GetFileEntry(fileName, false);
if (entry != null) {
entry.ExpireCache();
}
}
internal void RemoveEntry(ParserServiceEntry entry)
{
Debug.Assert(Monitor.IsEntered(entry));
lock (fileEntryDict) {
ParserServiceEntry entryAtKey;
if (fileEntryDict.TryGetValue(entry.fileName, out entryAtKey)) {
if (entry == entryAtKey)
fileEntryDict.Remove(entry.fileName);
}
}
}
internal void RegisterForCacheExpiry(ParserServiceEntry entry)
{
// This method should not be called within any locks
Debug.Assert(!Monitor.IsEntered(entry));
ParserServiceEntry expiredItem = null;
lock (cacheExpiryQueue) {
if (cacheExpiryQueue.Count >= cachedEntryCount) {
expiredItem = cacheExpiryQueue.Dequeue();
}
cacheExpiryQueue.Enqueue(entry);
}
if (expiredItem != null)
expiredItem.ExpireCache();
}
public void AddOwnerProject(FileName fileName, IProject project, bool startAsyncParse, bool isLinkedFile)
{
if (project == null)
throw new ArgumentNullException("project");
GetFileEntry(fileName, true).AddOwnerProject(project, isLinkedFile);
}
public void RemoveOwnerProject(FileName fileName, IProject project)
{
if (project == null)
throw new ArgumentNullException("project");
var entry = GetFileEntry(fileName, false);
if (entry != null)
entry.RemoveOwnerProject(project);
}
#endregion
#region Forward Parse() calls to entry
public IParsedFile GetExistingParsedFile(FileName fileName, ITextSourceVersion version, IProject parentProject)
{
var entry = GetFileEntry(fileName, false);
if (entry != null)
return entry.GetExistingParsedFile(version, parentProject);
else
return null;
}
public ParseInformation GetCachedParseInformation(FileName fileName, ITextSourceVersion version, IProject parentProject)
{
var entry = GetFileEntry(fileName, false);
if (entry != null)
return entry.GetCachedParseInformation(version, parentProject);
else
return null;
}
public ParseInformation Parse(FileName fileName, ITextSource fileContent, IProject parentProject, CancellationToken cancellationToken)
{
return GetFileEntry(fileName, true).Parse(fileContent, parentProject, cancellationToken);
}
public IParsedFile ParseFile(FileName fileName, ITextSource fileContent, IProject parentProject, CancellationToken cancellationToken)
{
return GetFileEntry(fileName, true).ParseFile(fileContent, parentProject, cancellationToken);
}
public Task<ParseInformation> ParseAsync(FileName fileName, ITextSource fileContent, IProject parentProject, CancellationToken cancellationToken)
{
return GetFileEntry(fileName, true).ParseAsync(fileContent, parentProject, cancellationToken);
}
public Task<IParsedFile> ParseFileAsync(FileName fileName, ITextSource fileContent, IProject parentProject, CancellationToken cancellationToken)
{
return GetFileEntry(fileName, true).ParseFileAsync(fileContent, parentProject, cancellationToken);
}
#endregion
#region Resolve
public ResolveResult Resolve(ITextEditor editor, TextLocation location, ICompilation compilation, CancellationToken cancellationToken)
{
if (editor == null)
throw new ArgumentNullException("editor");
return Resolve(editor.FileName, location, editor.Document, compilation, cancellationToken);
}
public ResolveResult Resolve(FileName fileName, TextLocation location, ITextSource fileContent, ICompilation compilation, CancellationToken cancellationToken)
{
var entry = GetFileEntry(fileName, true);
if (entry.parser == null)
return ErrorResolveResult.UnknownError;
IProject project = compilation != null ? compilation.GetProject() : null;
var parseInfo = entry.Parse(fileContent, project, cancellationToken);
if (parseInfo == null)
return ErrorResolveResult.UnknownError;
if (compilation == null)
compilation = GetCompilationForFile(fileName);
ResolveResult rr = entry.parser.Resolve(parseInfo, location, compilation, cancellationToken);
LoggingService.Debug("Resolved " + location + " to " + rr);
return rr;
}
public Task<ResolveResult> ResolveAsync(FileName fileName, TextLocation location, ITextSource fileContent, ICompilation compilation, CancellationToken cancellationToken)
{
var entry = GetFileEntry(fileName, true);
if (entry.parser == null)
return Task.FromResult<ResolveResult>(ErrorResolveResult.UnknownError);
IProject project = compilation != null ? compilation.GetProject() : null;
return entry.ParseAsync(fileContent, project, cancellationToken).ContinueWith(
delegate (Task<ParseInformation> parseInfoTask) {
var parseInfo = parseInfoTask.Result;
if (parseInfo == null)
return ErrorResolveResult.UnknownError;
if (compilation == null)
compilation = GetCompilationForFile(fileName);
ResolveResult rr = entry.parser.Resolve(parseInfo, location, compilation, cancellationToken);
LoggingService.Debug("Resolved " + location + " to " + rr);
return rr;
}, cancellationToken);
}
public async Task FindLocalReferencesAsync(FileName fileName, IVariable variable, Action<Reference> callback, ITextSource fileContent, ICompilation compilation, CancellationToken cancellationToken)
{
var entry = GetFileEntry(fileName, true);
if (entry.parser == null)
return;
if (fileContent == null)
fileContent = SD.FileService.GetFileContent(fileName);
if (compilation == null)
compilation = GetCompilationForFile(fileName);
var parseInfo = await entry.ParseAsync(fileContent, compilation.GetProject(), cancellationToken).ConfigureAwait(false);
await Task.Run(
() => entry.parser.FindLocalReferences(parseInfo, fileContent, variable, compilation, callback, cancellationToken)
);
}
#endregion
#region HasParser / CreateParser
public bool HasParser(FileName fileName)
{
if (fileName == null)
throw new ArgumentNullException("fileName");
if (parserDescriptors == null)
return false;
foreach (ParserDescriptor descriptor in parserDescriptors) {
if (descriptor.CanParse(fileName)) {
return true;
}
}
return false;
}
/// <summary>
/// Creates a new IParser instance that can parse the specified file.
/// This method is thread-safe.
/// </summary>
internal IParser CreateParser(FileName fileName)
{
if (fileName == null)
throw new ArgumentNullException("fileName");
if (parserDescriptors == null)
return null;
foreach (ParserDescriptor descriptor in parserDescriptors) {
if (descriptor.CanParse(fileName)) {
IParser p = descriptor.CreateParser();
if (p != null) {
p.TaskListTokens = TaskListTokens;
return p;
}
}
}
return null;
}
#endregion
internal void StartParserThread()
{
// TODO
}
internal void StopParserThread()
{
// TODO
}
}
}

330
src/Main/SharpDevelop/Parser/ParserServiceEntry.cs

@ -0,0 +1,330 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using ICSharpCode.Core;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.SharpDevelop.Parser
{
sealed class ParserServiceEntry
{
struct ProjectEntry
{
public readonly IProject Project;
public readonly IParsedFile ParsedFile;
public readonly ParseInformation CachedParseInformation;
public ProjectEntry(IProject project, IParsedFile parsedFile, ParseInformation cachedParseInformation)
{
this.Project = project;
this.ParsedFile = parsedFile;
this.CachedParseInformation = cachedParseInformation;
}
}
readonly ParserService parserService;
internal readonly FileName fileName;
internal readonly IParser parser;
List<ProjectEntry> entries = new List<ProjectEntry> { default(ProjectEntry) };
ITextSourceVersion currentVersion;
public ParserServiceEntry(ParserService parserService, FileName fileName)
{
this.parserService = parserService;
this.fileName = fileName;
this.parser = parserService.CreateParser(fileName);
}
#region Owner Projects
IProject PrimaryProject {
get { return entries[0].Project; }
}
int FindIndexForProject(IProject parentProject)
{
if (parentProject == null)
return 0;
for (int i = 0; i < entries.Count; i++) {
if (entries[i].Project == parentProject)
return i;
}
// project not found
return -1;
}
public void AddOwnerProject(IProject project, bool isLinkedFile)
{
Debug.Assert(project != null);
lock (this) {
if (FindIndexForProject(project) >= 0)
throw new InvalidOperationException("The project alreadys owns the file");
ProjectEntry newEntry = new ProjectEntry(project, null, null);
if (entries[0].Project == null) {
entries[0] = newEntry;
} else if (isLinkedFile) {
entries.Add(newEntry);
} else {
entries.Insert(0, newEntry);
}
}
}
public void RemoveOwnerProject(IProject project)
{
Debug.Assert(project != null);
lock (this) {
int index = FindIndexForProject(project);
if (index < 0)
throw new InvalidOperationException("The project does not own the file");
if (entries.Count == 1) {
entries[0] = default(ProjectEntry);
} else {
entries.RemoveAt(index);
}
}
}
#endregion
/// <summary>
/// Compares currentVersion with version.
/// -1 = currentVersion is older; 0 = same version; 1 = newVersion is older
/// </summary>
int CompareVersions(ITextSourceVersion newVersion)
{
if (currentVersion != null && newVersion != null && currentVersion.BelongsToSameDocumentAs(newVersion))
return currentVersion.CompareAge(newVersion);
else
return -1;
}
#region Expire Cache + GetExistingParsedFile + GetCachedParseInformation
public void ExpireCache()
{
lock (this) {
if (PrimaryProject == null) {
parserService.RemoveEntry(this);
} else {
for (int i = 0; i < entries.Count; i++) {
var oldEntry = entries[i];
entries[i] = new ProjectEntry(oldEntry.Project, oldEntry.ParsedFile, null);
}
}
}
}
public IParsedFile GetExistingParsedFile(ITextSourceVersion version, IProject parentProject)
{
lock (this) {
if (version != null && CompareVersions(version) != 0) {
return null;
}
int index = FindIndexForProject(parentProject);
if (index < 0)
return null;
return entries[index].ParsedFile;
}
}
public ParseInformation GetCachedParseInformation(ITextSourceVersion version, IProject parentProject)
{
lock (this) {
if (version != null && CompareVersions(version) != 0) {
return null;
}
int index = FindIndexForProject(parentProject);
if (index < 0)
return null;
return entries[index].CachedParseInformation;
}
}
#endregion
#region Parse
public ParseInformation Parse(ITextSource fileContent, IProject parentProject, CancellationToken cancellationToken)
{
if (fileContent == null) {
fileContent = SD.FileService.GetFileContent(fileName);
}
return DoParse(fileContent, parentProject, false, cancellationToken).CachedParseInformation;
}
public IParsedFile ParseFile(ITextSource fileContent, IProject parentProject, CancellationToken cancellationToken)
{
if (fileContent == null) {
fileContent = SD.FileService.GetFileContent(fileName);
}
return DoParse(fileContent, parentProject, false, cancellationToken).ParsedFile;
}
ProjectEntry DoParse(ITextSource fileContent, IProject parentProject, bool fullParseInformationRequested,
CancellationToken cancellationToken)
{
if (parser == null)
return default(ProjectEntry);
if (fileContent == null) {
// No file content was specified. Because the callers of this method already check for currently open files,
// we can assume that the file isn't open and simply read it from disk.
try {
fileContent = SD.FileService.GetFileContentFromDisk(fileName, cancellationToken);
} catch (IOException) {
// It is possible that the file gets deleted/becomes inaccessible while a background parse
// operation is enqueued, so we have to handle IO exceptions.
return default(ProjectEntry);
} catch (UnauthorizedAccessException) {
return default(ProjectEntry);
}
}
ProjectEntry result;
lock (this) {
int index = FindIndexForProject(parentProject);
int versionComparison = CompareVersions(fileContent.Version);
if (versionComparison > 0 || index < 0) {
// We're going backwards in time, or are requesting a project that is not an owner
// for this entry.
var parseInfo = parser.Parse(fileName, fileContent, fullParseInformationRequested, parentProject, cancellationToken);
FreezableHelper.Freeze(parseInfo.ParsedFile);
return new ProjectEntry(parentProject, parseInfo.ParsedFile, parseInfo);
} else {
if (versionComparison == 0 && index >= 0) {
// If full parse info is requested, ensure we have full parse info.
if (!(fullParseInformationRequested && entries[index].CachedParseInformation == null)) {
// We already have the requested version parsed, just return it:
return entries[index];
}
}
}
ParseInformationEventArgs[] results = new ParseInformationEventArgs[entries.Count];
for (int i = 0; i < entries.Count; i++) {
ParseInformation parseInfo;
try {
parseInfo = parser.Parse(fileName, fileContent, fullParseInformationRequested, entries[i].Project, cancellationToken);
} catch (Exception ex) {
SD.LoggingService.Error("Got " + ex.GetType().Name + " while parsing " + fileName);
throw;
}
if (parseInfo == null)
throw new NullReferenceException(parser.GetType().Name + ".Parse() returned null");
if (fullParseInformationRequested && !parseInfo.IsFullParseInformation)
throw new InvalidOperationException(parser.GetType().Name + ".Parse() did not return full parse info as requested.");
FreezableHelper.Freeze(parseInfo.ParsedFile);
results[i] = new ParseInformationEventArgs(entries[i].Project, entries[i].ParsedFile, parseInfo);
}
// Only if all parse runs succeeded, register the parse information.
currentVersion = fileContent.Version;
for (int i = 0; i < entries.Count; i++) {
if (fullParseInformationRequested || entries[i].CachedParseInformation != null)
entries[i] = new ProjectEntry(entries[i].Project, entries[i].ParsedFile, results[i].NewParseInformation);
else
entries[i] = new ProjectEntry(entries[i].Project, entries[i].ParsedFile, null);
if (entries[i].Project != null)
entries[i].Project.OnParseInformationUpdated(results[i]);
parserService.RaiseParseInformationUpdated(results[i]);
}
result = entries[index];
} // exit lock
parserService.RegisterForCacheExpiry(this);
return result;
}
#endregion
#region ParseAsync
Task<ProjectEntry> runningAsyncParseTask;
ITextSourceVersion runningAsyncParseFileContentVersion;
bool runningAsyncParseFullInfoRequested;
public async Task<ParseInformation> ParseAsync(ITextSource fileContent, IProject parentProject, CancellationToken cancellationToken)
{
return (await DoParseAsync(fileContent, parentProject, true, cancellationToken)).CachedParseInformation;
}
public async Task<IParsedFile> ParseFileAsync(ITextSource fileContent, IProject parentProject, CancellationToken cancellationToken)
{
return (await DoParseAsync(fileContent, parentProject, false, cancellationToken)).ParsedFile;
}
Task<ProjectEntry> DoParseAsync(ITextSource fileContent, IProject parentProject, bool requestFullParseInformation, CancellationToken cancellationToken)
{
// Create snapshot of file content, if required
bool lookupOpenFileOnTargetThread;
if (fileContent != null) {
lookupOpenFileOnTargetThread = false;
// File content was explicitly specified:
// Let's make a snapshot in case the text source is mutable.
fileContent = fileContent.CreateSnapshot();
} else if (SD.MainThread.InvokeRequired) {
// fileContent == null && not on the main thread:
// Don't fetch the file content right now; if we need to SafeThreadCall() anyways,
// it's better to do so from the background task.
lookupOpenFileOnTargetThread = true;
} else {
// fileContent == null && we are on the main thread:
// Let's look up the file in the list of open files right now
// so that we don't need to SafeThreadCall() later on.
lookupOpenFileOnTargetThread = false;
fileContent = SD.FileService.GetFileContentForOpenFile(fileName);
}
Task<ProjectEntry> task;
lock (this) {
if (fileContent != null) {
// Optimization:
// don't start a background task if fileContent was specified and up-to-date parse info is available
int index = FindIndexForProject(parentProject);
int versionComparison = CompareVersions(fileContent.Version);
if (versionComparison == 0 && index >= 0) {
// If full parse info is requested, ensure we have full parse info.
if (!(requestFullParseInformation && entries[index].CachedParseInformation == null)) {
// We already have the requested version parsed, just return it:
return Task.FromResult(entries[index]);
}
}
// Optimization:
// if an equivalent task is already running, return that one instead
if (runningAsyncParseTask != null && (!requestFullParseInformation || runningAsyncParseFullInfoRequested)
&& runningAsyncParseFileContentVersion.BelongsToSameDocumentAs(fileContent.Version)
&& runningAsyncParseFileContentVersion.CompareAge(fileContent.Version) == 0)
{
return runningAsyncParseTask;
}
}
task = new Task<ProjectEntry>(
delegate {
try {
if (lookupOpenFileOnTargetThread) {
fileContent = SD.FileService.GetFileContentForOpenFile(fileName);
}
return DoParse(fileContent, parentProject, requestFullParseInformation, cancellationToken);
} finally {
lock (this) {
runningAsyncParseTask = null;
runningAsyncParseFileContentVersion = null;
}
}
}, cancellationToken);
if (fileContent != null && fileContent.Version != null && !cancellationToken.CanBeCanceled) {
runningAsyncParseTask = task;
runningAsyncParseFileContentVersion = fileContent.Version;
runningAsyncParseFullInfoRequested = requestFullParseInformation;
}
}
task.Start();
return task;
}
#endregion
}
}

2
src/Main/SharpDevelop/Sda/CallHelper.cs

@ -17,7 +17,7 @@ using ICSharpCode.Core;
using ICSharpCode.Core.WinForms; using ICSharpCode.Core.WinForms;
using ICSharpCode.SharpDevelop.Commands; using ICSharpCode.SharpDevelop.Commands;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Gui.Workbench; using ICSharpCode.SharpDevelop.Workbench;
using ICSharpCode.SharpDevelop.Logging; using ICSharpCode.SharpDevelop.Logging;
using ICSharpCode.SharpDevelop.Parser; using ICSharpCode.SharpDevelop.Parser;

45
src/Main/SharpDevelop/SharpDevelop.csproj

@ -77,23 +77,32 @@
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Gui\App.xaml.cs" /> <Compile Include="Startup\App.xaml.cs" />
<Compile Include="Gui\SplashScreen.cs" /> <Compile Include="Startup\SharpDevelopMain.cs" />
<Compile Include="Gui\Workbench\AvalonDockLayout.cs" /> <Compile Include="Startup\SplashScreen.cs" />
<Compile Include="Gui\Workbench\AvalonPadContent.cs" /> <Compile Include="Workbench\AvalonDockLayout.cs" />
<Compile Include="Gui\Workbench\AvalonWorkbenchWindow.cs" /> <Compile Include="Workbench\AvalonPadContent.cs" />
<Compile Include="Gui\Workbench\ChooseLayoutCommand.cs" /> <Compile Include="Workbench\AvalonWorkbenchWindow.cs" />
<Compile Include="Gui\Workbench\FullScreenEnabledWindow.cs" /> <Compile Include="Workbench\ChooseLayoutCommand.cs" />
<Compile Include="Gui\Workbench\LayoutConfiguration.cs" /> <Compile Include="Workbench\DispatcherMessageLoop.cs" />
<Compile Include="Gui\Workbench\SDStatusBar.cs" /> <Compile Include="Workbench\FileService.cs" />
<Compile Include="Gui\Workbench\SingleInstanceHelper.cs" /> <Compile Include="Workbench\FullScreenEnabledWindow.cs" />
<Compile Include="Gui\Workbench\StatusBarService.cs" /> <Compile Include="Workbench\LayoutConfiguration.cs" />
<Compile Include="Gui\Workbench\WorkbenchStartup.cs" /> <Compile Include="Workbench\SDStatusBar.cs" />
<Compile Include="Gui\Workbench\WpfWorkbench.cs" /> <Compile Include="Workbench\SingleInstanceHelper.cs" />
<Compile Include="Workbench\StatusBarService.cs" />
<Compile Include="Workbench\WorkbenchStartup.cs" />
<Compile Include="Workbench\WpfWorkbench.cs" />
<Compile Include="Logging\ExceptionBox.cs" /> <Compile Include="Logging\ExceptionBox.cs" />
<Compile Include="Logging\log4netLoggingService.cs" /> <Compile Include="Logging\log4netLoggingService.cs" />
<Compile Include="Logging\LogMessageRecorder.cs" /> <Compile Include="Logging\LogMessageRecorder.cs" />
<Compile Include="Logging\SDMessageService.cs" /> <Compile Include="Logging\SDMessageService.cs" />
<Compile Include="Parser\Fusion.cs" />
<Compile Include="Parser\GlobalAssemblyCacheService.cs" />
<Compile Include="Parser\ParserDescriptor.cs" />
<Compile Include="Parser\ParserDoozer.cs" />
<Compile Include="Parser\ParserService.cs" />
<Compile Include="Parser\ParserServiceEntry.cs" />
<Compile Include="Sda\CallHelper.cs" /> <Compile Include="Sda\CallHelper.cs" />
<Compile Include="Sda\Document.cs" /> <Compile Include="Sda\Document.cs" />
<Compile Include="Sda\EventArgs.cs" /> <Compile Include="Sda\EventArgs.cs" />
@ -101,7 +110,6 @@
<Compile Include="Sda\SharpDevelopHost.cs" /> <Compile Include="Sda\SharpDevelopHost.cs" />
<Compile Include="Sda\StartupSettings.cs" /> <Compile Include="Sda\StartupSettings.cs" />
<Compile Include="Sda\WorkbenchSettings.cs" /> <Compile Include="Sda\WorkbenchSettings.cs" />
<Compile Include="SharpDevelopMain.cs" />
<EmbeddedResource Include="..\..\..\data\resources\StringResources.resx"> <EmbeddedResource Include="..\..\..\data\resources\StringResources.resx">
<Link>Resources\StringResources.resx</Link> <Link>Resources\StringResources.resx</Link>
</EmbeddedResource> </EmbeddedResource>
@ -174,14 +182,15 @@
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Gui" /> <Folder Include="Startup" />
<Folder Include="Gui\Workbench" /> <Folder Include="Workbench" />
<Folder Include="Logging" /> <Folder Include="Logging" />
<Folder Include="Parser" />
<Folder Include="Sda" /> <Folder Include="Sda" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Page Include="Gui\App.xaml" /> <Page Include="Startup\App.xaml" />
<Page Include="Gui\Workbench\WpfWorkbench.xaml" /> <Page Include="Workbench\WpfWorkbench.xaml" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project> </Project>

2
src/Main/SharpDevelop/Gui/App.xaml → src/Main/SharpDevelop/Startup/App.xaml

@ -1,4 +1,4 @@
<Application x:Class="ICSharpCode.SharpDevelop.Gui.App" x:ClassModifier="internal" <Application x:Class="ICSharpCode.SharpDevelop.Startup.App" x:ClassModifier="internal"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:core = "http://icsharpcode.net/sharpdevelop/core" xmlns:core = "http://icsharpcode.net/sharpdevelop/core"

2
src/Main/SharpDevelop/Gui/App.xaml.cs → src/Main/SharpDevelop/Startup/App.xaml.cs

@ -4,7 +4,7 @@
using System; using System;
using System.Windows; using System.Windows;
namespace ICSharpCode.SharpDevelop.Gui namespace ICSharpCode.SharpDevelop.Startup
{ {
/// <summary> /// <summary>
/// Interaction logic for App.xaml /// Interaction logic for App.xaml

4
src/Main/SharpDevelop/SharpDevelopMain.cs → src/Main/SharpDevelop/Startup/SharpDevelopMain.cs

@ -10,12 +10,12 @@ using System.Windows.Forms;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Gui.Workbench; using ICSharpCode.SharpDevelop.Workbench;
using ICSharpCode.SharpDevelop.Logging; using ICSharpCode.SharpDevelop.Logging;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Sda; using ICSharpCode.SharpDevelop.Sda;
namespace ICSharpCode.SharpDevelop namespace ICSharpCode.SharpDevelop.Startup
{ {
/// <summary> /// <summary>
/// This Class is the Core main class, it starts the program. /// This Class is the Core main class, it starts the program.

2
src/Main/SharpDevelop/Gui/SplashScreen.cs → src/Main/SharpDevelop/Startup/SplashScreen.cs

@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Windows.Forms; using System.Windows.Forms;
namespace ICSharpCode.SharpDevelop.Gui namespace ICSharpCode.SharpDevelop.Startup
{ {
sealed class SplashScreenForm : Form sealed class SplashScreenForm : Form
{ {

3
src/Main/SharpDevelop/Gui/Workbench/AvalonDockLayout.cs → src/Main/SharpDevelop/Workbench/AvalonDockLayout.cs

@ -12,8 +12,9 @@ using System.Windows.Media.Imaging;
using AvalonDock; using AvalonDock;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.SharpDevelop.Gui.Workbench namespace ICSharpCode.SharpDevelop.Workbench
{ {
/// <summary> /// <summary>
/// Workbench layout using the AvalonDock library. /// Workbench layout using the AvalonDock library.

3
src/Main/SharpDevelop/Gui/Workbench/AvalonPadContent.cs → src/Main/SharpDevelop/Workbench/AvalonPadContent.cs

@ -9,8 +9,9 @@ using System.Windows.Threading;
using AvalonDock; using AvalonDock;
using ICSharpCode.Core.Presentation; using ICSharpCode.Core.Presentation;
using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.SharpDevelop.Gui.Workbench namespace ICSharpCode.SharpDevelop.Workbench
{ {
sealed class AvalonPadContent : DockableContent, IDisposable sealed class AvalonPadContent : DockableContent, IDisposable
{ {

3
src/Main/SharpDevelop/Gui/Workbench/AvalonWorkbenchWindow.cs → src/Main/SharpDevelop/Workbench/AvalonWorkbenchWindow.cs

@ -14,8 +14,9 @@ using System.Windows.Threading;
using AvalonDock; using AvalonDock;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.Core.Presentation; using ICSharpCode.Core.Presentation;
using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.SharpDevelop.Gui.Workbench namespace ICSharpCode.SharpDevelop.Workbench
{ {
sealed class AvalonWorkbenchWindow : DocumentContent, IWorkbenchWindow, IOwnerState sealed class AvalonWorkbenchWindow : DocumentContent, IWorkbenchWindow, IOwnerState
{ {

7
src/Main/SharpDevelop/Gui/Workbench/ChooseLayoutCommand.cs → src/Main/SharpDevelop/Workbench/ChooseLayoutCommand.cs

@ -4,11 +4,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Windows.Forms;
using ICSharpCode.Core; using ICSharpCode.Core;
using System.Windows.Forms; using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.SharpDevelop.Gui.Workbench namespace ICSharpCode.SharpDevelop.Workbench
{ {
/// <summary> /// <summary>
/// Command for layout combobox in toolbar. /// Command for layout combobox in toolbar.
@ -45,7 +46,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
} }
if (oldItem != editIndex && oldItem != resetIndex) { if (oldItem != editIndex && oldItem != resetIndex) {
WorkbenchSingleton.Workbench.WorkbenchLayout.StoreConfiguration(); SD.Workbench.WorkbenchLayout.StoreConfiguration();
} }
if (comboBox.SelectedIndex == editIndex) { if (comboBox.SelectedIndex == editIndex) {

146
src/Main/SharpDevelop/Workbench/DispatcherMessageLoop.cs

@ -0,0 +1,146 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Threading;
namespace ICSharpCode.SharpDevelop.Workbench
{
sealed class DispatcherMessageLoop : IMessageLoop, ISynchronizeInvoke
{
readonly Dispatcher dispatcher;
readonly SynchronizationContext synchronizationContext;
public DispatcherMessageLoop(Dispatcher dispatcher, SynchronizationContext synchronizationContext)
{
this.dispatcher = dispatcher;
this.synchronizationContext = synchronizationContext;
}
public Thread Thread {
get { return dispatcher.Thread; }
}
public Dispatcher Dispatcher {
get { return dispatcher; }
}
public SynchronizationContext SynchronizationContext {
get { return synchronizationContext; }
}
public ISynchronizeInvoke SynchronizingObject {
get { return this; }
}
public bool InvokeRequired {
get { return !dispatcher.CheckAccess(); }
}
public bool CheckAccess()
{
return dispatcher.CheckAccess();
}
public void VerifyAccess()
{
dispatcher.VerifyAccess();
}
public void InvokeIfRequired(Action callback)
{
if (dispatcher.CheckAccess())
callback();
else
dispatcher.Invoke(callback);
}
public void InvokeIfRequired(Action callback, DispatcherPriority priority)
{
if (dispatcher.CheckAccess())
callback();
else
dispatcher.Invoke(callback, priority);
}
public void InvokeIfRequired(Action callback, DispatcherPriority priority, CancellationToken cancellationToken)
{
if (dispatcher.CheckAccess())
callback();
else
dispatcher.Invoke(callback, priority, cancellationToken);
}
public T InvokeIfRequired<T>(Func<T> callback)
{
if (dispatcher.CheckAccess())
return callback();
else
return dispatcher.Invoke(callback);
}
public T InvokeIfRequired<T>(Func<T> callback, DispatcherPriority priority)
{
if (dispatcher.CheckAccess())
return callback();
else
return dispatcher.Invoke(callback, priority);
}
public T InvokeIfRequired<T>(Func<T> callback, DispatcherPriority priority, CancellationToken cancellationToken)
{
if (dispatcher.CheckAccess())
return callback();
else
return dispatcher.Invoke(callback, priority, cancellationToken);
}
public Task InvokeAsync(Action callback)
{
return dispatcher.InvokeAsync(callback).Task;
}
public Task InvokeAsync(Action callback, DispatcherPriority priority)
{
return dispatcher.InvokeAsync(callback, priority).Task;
}
public Task InvokeAsync(Action callback, DispatcherPriority priority, CancellationToken cancellationToken)
{
return dispatcher.InvokeAsync(callback, priority, cancellationToken).Task;
}
public Task<T> InvokeAsync<T>(Func<T> callback)
{
return dispatcher.InvokeAsync(callback).Task;
}
public Task<T> InvokeAsync<T>(Func<T> callback, DispatcherPriority priority)
{
return dispatcher.InvokeAsync(callback, priority).Task;
}
public Task<T> InvokeAsync<T>(Func<T> callback, DispatcherPriority priority, CancellationToken cancellationToken)
{
return dispatcher.InvokeAsync(callback, priority, cancellationToken).Task;
}
IAsyncResult ISynchronizeInvoke.BeginInvoke(Delegate method, object[] args)
{
return dispatcher.InvokeAsync<object>(() => method.DynamicInvoke(args)).Task;
}
object ISynchronizeInvoke.EndInvoke(IAsyncResult result)
{
return ((Task<object>)result).Result;
}
object ISynchronizeInvoke.Invoke(Delegate method, object[] args)
{
return dispatcher.Invoke(() => method.DynamicInvoke(args));
}
}
}

61
src/Main/SharpDevelop/Workbench/FileService.cs

@ -0,0 +1,61 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.IO;
using System.Text;
using System.Threading;
using ICSharpCode.AvalonEdit.Utils;
using ICSharpCode.Core;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.SharpDevelop.Editor;
namespace ICSharpCode.SharpDevelop.Workbench
{
sealed class FileService : IFileService
{
public Encoding DefaultFileEncoding {
get {
return Encoding.GetEncoding(SharpDevelop.FileService.DefaultFileEncodingCodePage);
}
}
public ITextSource GetFileContent(FileName fileName)
{
return GetFileContentForOpenFile(fileName) ?? GetFileContentFromDisk(fileName, CancellationToken.None);
}
public ITextSource GetFileContent(string fileName)
{
return GetFileContent(FileName.Create(fileName));
}
public ITextSource GetFileContentForOpenFile(FileName fileName)
{
return SD.MainThread.InvokeIfRequired(
delegate {
OpenedFile file = SharpDevelop.FileService.GetOpenedFile(fileName);
if (file != null) {
IFileDocumentProvider p = file.CurrentView as IFileDocumentProvider;
if (p != null) {
IDocument document = p.GetDocumentForFile(file);
if (document != null) {
return document.CreateSnapshot();
}
}
using (Stream s = file.OpenRead()) {
// load file
return new StringTextSource(FileReader.ReadFileContent(s, DefaultFileEncoding));
}
}
return null;
});
}
public ITextSource GetFileContentFromDisk(FileName fileName, CancellationToken cancellationToken)
{
return new StringTextSource(FileReader.ReadFileContent(fileName, DefaultFileEncoding));
}
}
}

2
src/Main/SharpDevelop/Gui/Workbench/FullScreenEnabledWindow.cs → src/Main/SharpDevelop/Workbench/FullScreenEnabledWindow.cs

@ -6,7 +6,7 @@ using System.Windows;
using System.Windows.Forms; using System.Windows.Forms;
using System.Windows.Interop; using System.Windows.Interop;
namespace ICSharpCode.SharpDevelop.Gui.Workbench namespace ICSharpCode.SharpDevelop.Workbench
{ {
using WindowState = System.Windows.WindowState; using WindowState = System.Windows.WindowState;

9
src/Main/SharpDevelop/Gui/Workbench/LayoutConfiguration.cs → src/Main/SharpDevelop/Workbench/LayoutConfiguration.cs

@ -8,7 +8,7 @@ using System.Xml;
using ICSharpCode.Core; using ICSharpCode.Core;
namespace ICSharpCode.SharpDevelop.Gui.Workbench namespace ICSharpCode.SharpDevelop.Workbench
{ {
class LayoutConfiguration class LayoutConfiguration
{ {
@ -122,11 +122,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
return currentLayoutName; return currentLayoutName;
} }
set { set {
if (WorkbenchSingleton.InvokeRequired) SD.MainThread.VerifyAccess();
throw new InvalidOperationException("Invoke required");
if (value != CurrentLayoutName) { if (value != CurrentLayoutName) {
currentLayoutName = value; currentLayoutName = value;
WorkbenchSingleton.Workbench.WorkbenchLayout.LoadConfiguration(); SD.Workbench.WorkbenchLayout.LoadConfiguration();
OnLayoutChanged(EventArgs.Empty); OnLayoutChanged(EventArgs.Empty);
} }
} }
@ -135,7 +134,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
public static void ReloadDefaultLayout() public static void ReloadDefaultLayout()
{ {
currentLayoutName = DefaultLayoutName; currentLayoutName = DefaultLayoutName;
WorkbenchSingleton.Workbench.WorkbenchLayout.LoadConfiguration(); SD.Workbench.WorkbenchLayout.LoadConfiguration();
OnLayoutChanged(EventArgs.Empty); OnLayoutChanged(EventArgs.Empty);
} }

3
src/Main/SharpDevelop/Gui/Workbench/SDStatusBar.cs → src/Main/SharpDevelop/Workbench/SDStatusBar.cs

@ -11,8 +11,9 @@ using System.Windows.Media.Imaging;
using System.Windows.Shell; using System.Windows.Shell;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.SharpDevelop.Gui.Workbench namespace ICSharpCode.SharpDevelop.Workbench
{ {
class SDStatusBar : StatusBar class SDStatusBar : StatusBar
{ {

15
src/Main/SharpDevelop/Gui/Workbench/SingleInstanceHelper.cs → src/Main/SharpDevelop/Workbench/SingleInstanceHelper.cs

@ -11,7 +11,7 @@ using System.Windows.Forms;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.SharpDevelop.Gui.Workbench namespace ICSharpCode.SharpDevelop.Workbench
{ {
static class SingleInstanceHelper static class SingleInstanceHelper
{ {
@ -68,15 +68,14 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
return new IntPtr(RESULT_PROJECT_IS_OPEN); return new IntPtr(RESULT_PROJECT_IS_OPEN);
} else { } else {
try { try {
WorkbenchSingleton.SafeThreadAsyncCall( SD.MainThread.InvokeAsync(
delegate { NativeMethods.SetForegroundWindow(WorkbenchSingleton.MainWin32Window.Handle) ; } delegate { NativeMethods.SetForegroundWindow(SD.Workbench.MainWin32Window.Handle); }
); ).FireAndForget();
string tempFileName = Path.Combine(Path.GetTempPath(), "sd" + fileNumber + ".tmp"); string tempFileName = Path.Combine(Path.GetTempPath(), "sd" + fileNumber + ".tmp");
foreach (string file in File.ReadAllLines(tempFileName)) { foreach (string file in File.ReadAllLines(tempFileName)) {
WorkbenchSingleton.SafeThreadAsyncCall( SD.MainThread.InvokeAsync(
delegate(string openFileName) { FileService.OpenFile(openFileName); } delegate { SharpDevelop.FileService.OpenFile(file); }
, file ).FireAndForget();
);
} }
} catch (Exception ex) { } catch (Exception ex) {
LoggingService.Warn(ex); LoggingService.Warn(ex);

5
src/Main/SharpDevelop/Gui/Workbench/StatusBarService.cs → src/Main/SharpDevelop/Workbench/StatusBarService.cs

@ -8,8 +8,9 @@ using System.Threading;
using System.Windows; using System.Windows;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.SharpDevelop.Gui.Workbench namespace ICSharpCode.SharpDevelop.Workbench
{ {
sealed class StatusBarService : IStatusBarService sealed class StatusBarService : IStatusBarService
{ {
@ -57,7 +58,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
public IProgressMonitor CreateProgressMonitor(CancellationToken cancellationToken = default(CancellationToken)) public IProgressMonitor CreateProgressMonitor(CancellationToken cancellationToken = default(CancellationToken))
{ {
ProgressCollector progress = new ProgressCollector(WorkbenchSingleton.Workbench.SynchronizingObject, cancellationToken); ProgressCollector progress = new ProgressCollector(SD.MainThread.SynchronizingObject, cancellationToken);
AddProgress(progress); AddProgress(progress);
return progress.ProgressMonitor; return progress.ProgressMonitor;
} }

20
src/Main/SharpDevelop/Gui/Workbench/WorkbenchStartup.cs → src/Main/SharpDevelop/Workbench/WorkbenchStartup.cs

@ -4,15 +4,16 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Windows.Forms; using System.Threading;
using System.Windows.Interop; using System.Windows.Interop;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.Core.WinForms;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Startup;
namespace ICSharpCode.SharpDevelop.Gui.Workbench namespace ICSharpCode.SharpDevelop.Workbench
{ {
/// <summary> /// <summary>
/// Runs workbench initialization. /// Runs workbench initialization.
@ -30,6 +31,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
ComponentDispatcher.ThreadIdle -= ComponentDispatcher_ThreadIdle; // ensure we don't register twice ComponentDispatcher.ThreadIdle -= ComponentDispatcher_ThreadIdle; // ensure we don't register twice
ComponentDispatcher.ThreadIdle += ComponentDispatcher_ThreadIdle; ComponentDispatcher.ThreadIdle += ComponentDispatcher_ThreadIdle;
LayoutConfiguration.LoadLayoutConfiguration(); LayoutConfiguration.LoadLayoutConfiguration();
SD.Services.AddService(typeof(IMessageLoop), new DispatcherMessageLoop(app.Dispatcher, SynchronizationContext.Current));
WorkbenchSingleton.InitializeWorkbench(new WpfWorkbench(), new AvalonDockLayout()); WorkbenchSingleton.InitializeWorkbench(new WpfWorkbench(), new AvalonDockLayout());
} }
@ -54,7 +56,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
if (loader != null) { if (loader != null) {
loader.Load(fullFileName); loader.Load(fullFileName);
} else { } else {
FileService.OpenFile(fullFileName); SharpDevelop.FileService.OpenFile(fullFileName);
} }
} catch (Exception e) { } catch (Exception e) {
MessageService.ShowException(e, "unable to open file " + file); MessageService.ShowException(e, "unable to open file " + file);
@ -63,8 +65,8 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
// load previous solution // load previous solution
if (!didLoadSolutionOrFile && PropertyService.Get("SharpDevelop.LoadPrevProjectOnStartup", false)) { if (!didLoadSolutionOrFile && PropertyService.Get("SharpDevelop.LoadPrevProjectOnStartup", false)) {
if (FileService.RecentOpen.RecentProject.Count > 0) { if (SharpDevelop.FileService.RecentOpen.RecentProject.Count > 0) {
ProjectService.LoadSolution(FileService.RecentOpen.RecentProject[0]); ProjectService.LoadSolution(SharpDevelop.FileService.RecentOpen.RecentProject[0]);
didLoadSolutionOrFile = true; didLoadSolutionOrFile = true;
} }
} }
@ -81,14 +83,14 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
NavigationService.ResumeLogging(); NavigationService.ResumeLogging();
Parser.ParserService.StartParserThread(); ((ParserService)SD.ParserService).StartParserThread();
// finally run the workbench window ... // finally run the workbench window ...
app.Run(WorkbenchSingleton.MainWindow); app.Run(SD.Workbench.MainWindow);
// save the workbench memento in the ide properties // save the workbench memento in the ide properties
try { try {
PropertyService.SetNestedProperties(workbenchMemento, WorkbenchSingleton.Workbench.CreateMemento()); PropertyService.SetNestedProperties(workbenchMemento, SD.Workbench.CreateMemento());
} catch (Exception e) { } catch (Exception e) {
MessageService.ShowException(e, "Exception while saving workbench state."); MessageService.ShowException(e, "Exception while saving workbench state.");
} }

29
src/Main/SharpDevelop/Gui/Workbench/WpfWorkbench.cs → src/Main/SharpDevelop/Workbench/WpfWorkbench.cs

@ -16,12 +16,15 @@ using System.Windows.Input;
using System.Windows.Interop; using System.Windows.Interop;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Navigation; using System.Windows.Navigation;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.Core.Presentation; using ICSharpCode.Core.Presentation;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Parser; using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Startup;
namespace ICSharpCode.SharpDevelop.Gui.Workbench namespace ICSharpCode.SharpDevelop.Workbench
{ {
/// <summary> /// <summary>
/// Workbench implementation using WPF and AvalonDock. /// Workbench implementation using WPF and AvalonDock.
@ -53,7 +56,6 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
} }
public System.Windows.Forms.IWin32Window MainWin32Window { get { return this; } } public System.Windows.Forms.IWin32Window MainWin32Window { get { return this; } }
public ISynchronizeInvoke SynchronizingObject { get; private set; }
public Window MainWindow { get { return this; } } public Window MainWindow { get { return this; } }
IntPtr System.Windows.Forms.IWin32Window.Handle { IntPtr System.Windows.Forms.IWin32Window.Handle {
@ -72,7 +74,6 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
public WpfWorkbench() public WpfWorkbench()
{ {
this.SynchronizingObject = new WpfSynchronizeInvoke(this.Dispatcher);
SD.Services.AddService(typeof(IStatusBarService), new StatusBarService(statusBar)); SD.Services.AddService(typeof(IStatusBarService), new StatusBarService(statusBar));
InitializeComponent(); InitializeComponent();
InitFocusTrackingEvents(); InitFocusTrackingEvents();
@ -123,12 +124,12 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
AddHandler(Hyperlink.RequestNavigateEvent, new RequestNavigateEventHandler(OnRequestNavigate)); AddHandler(Hyperlink.RequestNavigateEvent, new RequestNavigateEventHandler(OnRequestNavigate));
Project.ProjectService.CurrentProjectChanged += SetProjectTitle; Project.ProjectService.CurrentProjectChanged += SetProjectTitle;
FileService.FileRemoved += CheckRemovedOrReplacedFile; SharpDevelop.FileService.FileRemoved += CheckRemovedOrReplacedFile;
FileService.FileReplaced += CheckRemovedOrReplacedFile; SharpDevelop.FileService.FileReplaced += CheckRemovedOrReplacedFile;
FileService.FileRenamed += CheckRenamedFile; SharpDevelop.FileService.FileRenamed += CheckRenamedFile;
FileService.FileRemoved += FileService.RecentOpen.FileRemoved; SharpDevelop.FileService.FileRemoved += SharpDevelop.FileService.RecentOpen.FileRemoved;
FileService.FileRenamed += FileService.RecentOpen.FileRenamed; SharpDevelop.FileService.FileRenamed += SharpDevelop.FileService.RecentOpen.FileRenamed;
requerySuggestedEventHandler = new EventHandler(CommandManager_RequerySuggested); requerySuggestedEventHandler = new EventHandler(CommandManager_RequerySuggested);
CommandManager.RequerySuggested += requerySuggestedEventHandler; CommandManager.RequerySuggested += requerySuggestedEventHandler;
@ -156,7 +157,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
// catch exceptions - e.g. incorrectly installed mail client // catch exceptions - e.g. incorrectly installed mail client
} }
} else { } else {
FileService.OpenFile(e.Uri.ToString()); SharpDevelop.FileService.OpenFile(e.Uri.ToString());
} }
} }
@ -171,7 +172,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
void CheckRemovedOrReplacedFile(object sender, FileEventArgs e) void CheckRemovedOrReplacedFile(object sender, FileEventArgs e)
{ {
foreach (OpenedFile file in FileService.OpenedFiles) { foreach (OpenedFile file in SharpDevelop.FileService.OpenedFiles) {
if (FileUtility.IsBaseDirectory(e.FileName, file.FileName)) { if (FileUtility.IsBaseDirectory(e.FileName, file.FileName)) {
foreach (IViewContent content in file.RegisteredViewContents.ToArray()) { foreach (IViewContent content in file.RegisteredViewContents.ToArray()) {
// content.WorkbenchWindow can be null if multiple view contents // content.WorkbenchWindow can be null if multiple view contents
@ -189,13 +190,13 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
void CheckRenamedFile(object sender, FileRenameEventArgs e) void CheckRenamedFile(object sender, FileRenameEventArgs e)
{ {
if (e.IsDirectory) { if (e.IsDirectory) {
foreach (OpenedFile file in FileService.OpenedFiles) { foreach (OpenedFile file in SharpDevelop.FileService.OpenedFiles) {
if (file.FileName != null && FileUtility.IsBaseDirectory(e.SourceFile, file.FileName)) { if (file.FileName != null && FileUtility.IsBaseDirectory(e.SourceFile, file.FileName)) {
file.FileName = new FileName(FileUtility.RenameBaseDirectory(file.FileName, e.SourceFile, e.TargetFile)); file.FileName = new FileName(FileUtility.RenameBaseDirectory(file.FileName, e.SourceFile, e.TargetFile));
} }
} }
} else { } else {
OpenedFile file = FileService.GetOpenedFile(e.SourceFile); OpenedFile file = SharpDevelop.FileService.GetOpenedFile(e.SourceFile);
if (file != null) { if (file != null) {
file.FileName = new FileName(e.TargetFile); file.FileName = new FileName(e.TargetFile);
} }
@ -593,7 +594,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
} }
Project.ProjectService.CloseSolution(); Project.ProjectService.CloseSolution();
ParserService.StopParserThread(); ((ParserService)SD.ParserService).StopParserThread();
restoreBoundsBeforeClosing = this.RestoreBounds; restoreBoundsBeforeClosing = this.RestoreBounds;
@ -668,7 +669,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
if (loader != null) { if (loader != null) {
FileUtility.ObservedLoad(new NamedFileOperationDelegate(loader.Load), file); FileUtility.ObservedLoad(new NamedFileOperationDelegate(loader.Load), file);
} else { } else {
FileService.OpenFile(file); SharpDevelop.FileService.OpenFile(file);
} }
} }
} }

8
src/Main/SharpDevelop/Gui/Workbench/WpfWorkbench.xaml → src/Main/SharpDevelop/Workbench/WpfWorkbench.xaml

@ -1,10 +1,10 @@
<gui:FullScreenEnabledWindow <wb:FullScreenEnabledWindow
x:Class = "ICSharpCode.SharpDevelop.Gui.Workbench.WpfWorkbench" x:Class = "ICSharpCode.SharpDevelop.Workbench.WpfWorkbench"
x:ClassModifier = "internal" x:ClassModifier = "internal"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:core = "http://icsharpcode.net/sharpdevelop/core" xmlns:core = "http://icsharpcode.net/sharpdevelop/core"
xmlns:gui = "clr-namespace:ICSharpCode.SharpDevelop.Gui.Workbench" xmlns:wb = "clr-namespace:ICSharpCode.SharpDevelop.Workbench"
Title = "{core:Localize MainWindow.DialogName}" Title = "{core:Localize MainWindow.DialogName}"
WindowStartupLocation = "Manual" WindowStartupLocation = "Manual"
Background = "{DynamicResource {x:Static SystemColors.ControlBrushKey}}" Background = "{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
@ -21,4 +21,4 @@
<!-- Statusbar will be inserted here (index: Count-2) --> <!-- Statusbar will be inserted here (index: Count-2) -->
<ContentPresenter Name="mainContent" /> <ContentPresenter Name="mainContent" />
</DockPanel> </DockPanel>
</gui:FullScreenEnabledWindow> </wb:FullScreenEnabledWindow>
Loading…
Cancel
Save