From f31bca1de73f283aa54cf9d4f368ff4ff1704c51 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 21 Aug 2011 15:15:59 +0200 Subject: [PATCH] newNR: fixed build errors in AvalonEdit.AddIn and CSharpBinding. --- .../Project/CSharpBinding.csproj | 2 - .../Project/Src/CSharpBracketSearcher.cs | 2 +- .../Project/Src/CSharpCompletionBinding.cs | 10 +- .../Project/Src/CSharpLanguageBinding.cs | 9 +- .../Src/EventHandlerCompletionItemProvider.cs | 264 ----------------- .../CSharpFormattingStrategy.cs | 122 ++++---- .../FormattingStrategy/DocumentAccessor.cs | 7 +- .../Project/Src/Parser/Parser.cs | 57 +--- .../Src/Project/CSharpMyNamespaceBuilder.cs | 10 +- .../Project/Src/Project/CSharpProject.cs | 6 - .../Project/RemoveMembersInRangeVisitor.cs | 57 ---- ...oCSharpConvertVisitorWithMyFormsSupport.cs | 2 + .../Src/Project/VBNetToCSharpConverter.cs | 5 +- .../AvalonEdit.AddIn/Src/CodeEditor.cs | 2 +- .../AvalonEdit.AddIn/Src/CodeEditorView.cs | 10 +- .../Src/Commands/SortSelectionCommand.cs | 4 +- .../Src/MyersDiff/DocumentSequence.cs | 6 +- .../Src/ParserFoldingStrategy.cs | 4 +- .../AvalonEdit.AddIn/Src/QuickClassBrowser.cs | 2 +- .../Src/SharpDevelopTextEditor.cs | 4 +- .../Src/Snippets/CodeSnippet.cs | 5 +- .../CSharp/Ast/AstLocation.cs | 10 + .../ICSharpCode.NRefactory.csproj | 4 + .../Project/Src/Gui/Dialogs/NewFileDialog.cs | 2 +- .../Commands/ReferenceFolderNodeCommands.cs | 4 +- .../Src/Gui/Pads/TaskList/TaskListPad.cs | 2 +- .../Base/Project/Src/Project/CustomTool.cs | 2 +- .../AmbienceService/CSharpAmbience.cs | 37 +++ .../Src/Services/AmbienceService/IAmbience.cs | 83 ++++++ .../Src/Services/ParserService/IParser.cs | 3 +- .../ParseInformationEventArgs.cs | 8 +- .../Services/ParserService/ParserService.cs | 278 ++++++++++++++---- .../Src/Services/FileUtility/FileName.cs | 12 + 33 files changed, 488 insertions(+), 547 deletions(-) delete mode 100644 src/AddIns/BackendBindings/CSharpBinding/Project/Src/EventHandlerCompletionItemProvider.cs delete mode 100644 src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/RemoveMembersInRangeVisitor.cs diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj b/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj index c46d7acc8c..828f87922c 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj @@ -62,14 +62,12 @@ - Form - diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpBracketSearcher.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpBracketSearcher.cs index 0e8f5b6618..f3d9c454b4 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpBracketSearcher.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpBracketSearcher.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; - +using ICSharpCode.Editor; using ICSharpCode.SharpDevelop.Editor; namespace CSharpBinding diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs index 640e829325..de29c9425e 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs @@ -1,6 +1,7 @@ // 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.Core; using ICSharpCode.NRefactory; @@ -33,13 +34,7 @@ namespace CSharpBinding int cursor = editor.Caret.Offset; if (ch == '[') { var line = editor.Document.GetLineForOffset(cursor); - /* TODO: AVALONEDIT Reimplement this - if (TextUtilities.FindPrevWordStart(editor.ActiveTextAreaControl.Document, cursor) <= line.Offset) { - // [ is first character on the line - // -> Attribute completion - editor.ShowCompletionWindow(new AttributesDataProvider(ParserService.CurrentProjectContent), ch); - return true; - }*/ + } else if (ch == ',' && CodeCompletionOptions.InsightRefreshOnComma && CodeCompletionOptions.InsightEnabled) { IInsightWindow insightWindow; if (insightHandler.InsightRefreshOnComma(editor, ch, out insightWindow)) { @@ -316,3 +311,4 @@ namespace CSharpBinding #endregion } } +*/ \ No newline at end of file diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs index 69597d0443..98b74f8093 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs @@ -4,7 +4,6 @@ using System; using CSharpBinding.FormattingStrategy; using ICSharpCode.SharpDevelop; -using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.SharpDevelop.Editor; namespace CSharpBinding @@ -18,10 +17,10 @@ namespace CSharpBinding get { return new CSharpFormattingStrategy(); } } - public override LanguageProperties Properties { - get { return LanguageProperties.CSharp; } - } - +// public override LanguageProperties Properties { +// get { return LanguageProperties.CSharp; } +// } +// public override IBracketSearcher BracketSearcher { get { return new CSharpBracketSearcher(); } } diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/EventHandlerCompletionItemProvider.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/EventHandlerCompletionItemProvider.cs deleted file mode 100644 index acb2f92f94..0000000000 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/EventHandlerCompletionItemProvider.cs +++ /dev/null @@ -1,264 +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.Text; -using ICSharpCode.Core; -using ICSharpCode.SharpDevelop; -using ICSharpCode.SharpDevelop.Dom; -using ICSharpCode.SharpDevelop.Dom.CSharp; -using ICSharpCode.SharpDevelop.Editor; -using ICSharpCode.SharpDevelop.Editor.CodeCompletion; -using System.Windows.Input; - -namespace CSharpBinding -{ - public class EventHandlerCompletionItemProvider : AbstractCompletionItemProvider - { - string expression; - ResolveResult resolveResult; - IReturnType resolvedReturnType; - IClass resolvedClass; - - public EventHandlerCompletionItemProvider(string expression, ResolveResult resolveResult) - { - this.expression = expression; - this.resolveResult = resolveResult; - this.resolvedReturnType = resolveResult.ResolvedType; - this.resolvedClass = resolvedReturnType.GetUnderlyingClass(); - } - - public override ICompletionItemList GenerateCompletionList(ITextEditor editor) - { - DefaultCompletionItemList result = new DefaultCompletionItemList(); - result.InsertSpace = true; - - // delegate { } - result.Items.Add(new DelegateCompletionItem("delegate { };", 3, - "${res:CSharpBinding.InsertAnonymousMethod}")); - - CSharpAmbience ambience = new CSharpAmbience(); - // get eventHandler type name incl. type argument list - ambience.ConversionFlags = ConversionFlags.ShowParameterNames | ConversionFlags.ShowTypeParameterList | ConversionFlags.UseFullyQualifiedTypeNames; - string eventHandlerFullyQualifiedTypeName = ambience.Convert(resolvedReturnType); - ambience.ConversionFlags = ConversionFlags.ShowParameterNames | ConversionFlags.ShowTypeParameterList; - string eventHandlerTypeName = ambience.Convert(resolvedReturnType); - - // retrieve Invoke method from resolvedReturnType instead of resolvedClass to get a method where - // type arguments are substituted. - IMethod invoke = resolvedReturnType.GetMethods().Find(delegate(IMethod m) { return m.Name == "Invoke"; }); - StringBuilder parameterString = new StringBuilder(); - if (invoke != null) { - - // build the parameter string - for (int i = 0; i < invoke.Parameters.Count; ++i) { - if (i > 0) { - parameterString.Append(", "); - } - - parameterString.Append(ambience.Convert(invoke.Parameters[i])); - } - - // delegate(object sender, EventArgs e) { }; - StringBuilder anonMethodWithParametersBuilder = - new StringBuilder("delegate(").Append(parameterString.ToString()).Append(") { };"); - result.Items.Add(new DelegateCompletionItem(anonMethodWithParametersBuilder.ToString(), 3, - "${res:CSharpBinding.InsertAnonymousMethodWithParameters}")); - - // new EventHandler(ClassName_EventName); - IClass callingClass = resolveResult.CallingClass; - bool inStatic = false; - if (resolveResult.CallingMember != null) - inStatic = resolveResult.CallingMember.IsStatic; - - // ...build the new handler name... - string newHandlerName = BuildHandlerName(); - if (newHandlerName == null) { - MemberResolveResult mrr = resolveResult as MemberResolveResult; - IEvent eventMember = (mrr != null ? mrr.ResolvedMember as IEvent : null); - newHandlerName = - ((callingClass != null) ? callingClass.Name : "callingClass") - + "_" - + ((eventMember != null) ? eventMember.Name : "eventMember"); - } - - // ...build the completion text... - StringBuilder newHandlerTextBuilder = new StringBuilder("new ").Append(eventHandlerTypeName).Append("("); - newHandlerTextBuilder.Append(newHandlerName).Append(");"); - - // ...build the optional new method text... - StringBuilder newHandlerCodeBuilder = new StringBuilder(); - newHandlerCodeBuilder.AppendLine().AppendLine(); - if (inStatic) - newHandlerCodeBuilder.Append("static "); - newHandlerCodeBuilder.Append(ambience.Convert(invoke.ReturnType)).Append(" ").Append(newHandlerName); - newHandlerCodeBuilder.Append("(").Append(parameterString.ToString()).AppendLine(")"); - newHandlerCodeBuilder.AppendLine("{"); - newHandlerCodeBuilder.AppendLine("throw new NotImplementedException();"); - newHandlerCodeBuilder.Append("}"); - - // ...and add it to the completionData. - result.Items.Add(new NewEventHandlerCompletionItem( - newHandlerTextBuilder.ToString(), - 2+newHandlerName.Length, - newHandlerName.Length, - "new " + eventHandlerFullyQualifiedTypeName + - "(" + newHandlerName + StringParser.Parse(")\n${res:CSharpBinding.GenerateNewHandlerInstructions}\n") - + CodeCompletionItem.ConvertDocumentation(resolvedClass.Documentation), - resolveResult, - newHandlerCodeBuilder.ToString() - )); - - if (callingClass != null) { - foreach (IMethod method in callingClass.DefaultReturnType.GetMethods()) { - if (inStatic && !method.IsStatic) - continue; - if (!method.IsAccessible(callingClass, true)) - continue; - if (method.Parameters.Count != invoke.Parameters.Count) - continue; - // check return type compatibility: - if (!MemberLookupHelper.ConversionExists(method.ReturnType, invoke.ReturnType)) - continue; - bool ok = true; - for (int i = 0; i < invoke.Parameters.Count; i++) { - if (!MemberLookupHelper.ConversionExists(invoke.Parameters[i].ReturnType, method.Parameters[i].ReturnType)) { - ok = false; - break; - } - } - if (ok) { - result.Items.Add(new CodeCompletionItem(method)); - } - } - } - } - result.SortItems(); - return result; - } - - string BuildHandlerName() - { - if (expression != null) - expression = expression.Trim(); - if (string.IsNullOrEmpty(expression)) - return null; - if (!(char.IsLetter(expression[0]) || expression[0] == '_')) - return null; - StringBuilder handlerNameBuilder = new StringBuilder(); - for (int i = 0; i < expression.Length; i++) { - if (char.IsLetterOrDigit(expression[i]) || expression[i] == '_') { - handlerNameBuilder.Append(expression[i]); - } else if (expression[i] == '.') { - if (ICSharpCode.NRefactory.Parser.CSharp.Keywords.IsNonIdentifierKeyword(handlerNameBuilder.ToString())) { - return null; - } - handlerNameBuilder.Append('_'); - } else { - return null; - } - } - return handlerNameBuilder.ToString(); - } - - sealed class DelegateCompletionItem : DefaultCompletionItem - { - int cursorOffset; - - public DelegateCompletionItem(string text, int cursorOffset, string documentation) - : base(text) - { - this.cursorOffset = cursorOffset; - this.Description = StringParser.Parse(documentation); - this.Image = ClassBrowserIconService.Delegate; - } - - public override void Complete(CompletionContext context) - { - base.Complete(context); - context.Editor.Caret.Column -= cursorOffset; - } - } - - sealed class NewEventHandlerCompletionItem : DefaultCompletionItem - { - int selectionBeginOffset; - int selectionLength; - ResolveResult resolveResult; - string newHandlerCode; - - ITextEditor editor; - - public NewEventHandlerCompletionItem(string text, int selectionBeginOffset, int selectionLength, string documentation, ResolveResult resolveResult, string newHandlerCode) - : base(text) - { - this.selectionBeginOffset = selectionBeginOffset; - this.selectionLength = selectionLength; - this.resolveResult = resolveResult; - this.newHandlerCode = newHandlerCode; - - this.Description = StringParser.Parse(documentation); - this.Image = ClassBrowserIconService.Delegate; - } - - public override void Complete(CompletionContext context) - { - base.Complete(context); - - // save a reference to the relevant textArea so that we can remove our event handlers after the next keystroke - editor = context.Editor; - // select suggested name - editor.Caret.Column -= this.selectionBeginOffset; - editor.Select(editor.Caret.Offset, this.selectionLength); - - // TODO: refactor ToolTip architecture to allow for showing a tooltip relative to the current caret position so that we can show our "press TAB to create this method" text as a text-based tooltip - - // TODO: skip the auto-insert step if the method already exists, or change behavior so that it moves the caret inside the existing method. - - // attach our keydown filter to catch the next character pressed - editor.SelectionChanged += EditorSelectionChanged; - editor.KeyPress += EditorKeyPress; - } - - - void RemoveEventHandlers() - { - if (editor != null) { - editor.SelectionChanged -= EditorSelectionChanged; - editor.KeyPress -= EditorKeyPress; - editor = null; - } - } - - void EditorSelectionChanged(object sender, EventArgs e) - { - RemoveEventHandlers(); - } - - void EditorKeyPress(object sender, KeyEventArgs e) - { - if (e.Key == Key.Tab || e.Key == Key.Enter || e.Key == Key.Return) { - using (editor.Document.OpenUndoGroup()) { - - // is there a better way to calculate the optimal insertion point? - DomRegion region = resolveResult.CallingMember.BodyRegion; - editor.Caret.Line = region.EndLine; - editor.Caret.Column = region.EndColumn; - - editor.Document.Insert(editor.Caret.Offset, this.newHandlerCode); - - editor.Language.FormattingStrategy.IndentLines(editor, region.EndLine, editor.Caret.Line); - - IDocumentLine line = editor.Document.GetLine(editor.Caret.Line - 1); - int indentationLength = DocumentUtilitites.GetWhitespaceAfter(editor.Document, line.Offset).Length; - - editor.Select(line.Offset + indentationLength, line.Length - indentationLength); - } - e.Handled = true; - } - // detatch our keydown filter to return to the normal processing state - RemoveEventHandlers(); - } - } - } -} diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingStrategy.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingStrategy.cs index 5f7adc39c0..64480c0d05 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingStrategy.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingStrategy.cs @@ -5,11 +5,13 @@ using System; using System.Diagnostics; using System.Linq; using System.Text; - using ICSharpCode.AvalonEdit.Indentation.CSharp; -using ICSharpCode.SharpDevelop; -using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.Core; +using ICSharpCode.Editor; +using ICSharpCode.NRefactory.CSharp; +using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.SharpDevelop.Editor; +using ICSharpCode.SharpDevelop.Parser; namespace CSharpBinding.FormattingStrategy { @@ -174,54 +176,33 @@ namespace CSharpBinding.FormattingStrategy /// /// Gets the next member after the specified caret position. /// - object GetMemberAfter(ITextEditor editor, int caretLine) + IEntity GetMemberAfter(ITextEditor editor, int caretLine) { - string fileName = editor.FileName; - object nextElement = null; - if (fileName != null && fileName.Length > 0 ) { - ParseInformation parseInfo = ParserService.ParseFile(fileName, editor.Document.CreateSnapshot()); - if (parseInfo != null) { - ICompilationUnit currentCompilationUnit = parseInfo.CompilationUnit; - if (currentCompilationUnit != null) { - IClass currentClass = currentCompilationUnit.GetInnermostClass(caretLine, 0); - int nextElementLine = int.MaxValue; - if (currentClass == null) { - foreach (IClass c in currentCompilationUnit.Classes) { - if (c.Region.BeginLine < nextElementLine && c.Region.BeginLine > caretLine) { - nextElementLine = c.Region.BeginLine; - nextElement = c; - } - } - } else { - foreach (IClass c in currentClass.InnerClasses) { - if (c.Region.BeginLine < nextElementLine && c.Region.BeginLine > caretLine) { - nextElementLine = c.Region.BeginLine; - nextElement = c; - } - } - foreach (IMember m in currentClass.Methods) { - if (m.Region.BeginLine < nextElementLine && m.Region.BeginLine > caretLine) { - nextElementLine = m.Region.BeginLine; - nextElement = m; - } - } - foreach (IMember m in currentClass.Properties) { - if (m.Region.BeginLine < nextElementLine && m.Region.BeginLine > caretLine) { - nextElementLine = m.Region.BeginLine; - nextElement = m; - } + FileName fileName = editor.FileName; + IEntity nextElement = null; + if (fileName != null) { + IParsedFile parsedFile = ParserService.ParseFile(fileName, editor.Document.CreateSnapshot()); + if (parsedFile != null) { + ITypeDefinition currentClass = parsedFile.GetInnerMostTypeDefinition(new TextLocation(caretLine, 0)); + int nextElementLine = int.MaxValue; + if (currentClass == null) { + foreach (ITypeDefinition c in parsedFile.TopLevelTypeDefinitions) { + if (c.Region.BeginLine < nextElementLine && c.Region.BeginLine > caretLine) { + nextElementLine = c.Region.BeginLine; + nextElement = c; } - foreach (IMember m in currentClass.Fields) { - if (m.Region.BeginLine < nextElementLine && m.Region.BeginLine > caretLine) { - nextElementLine = m.Region.BeginLine; - nextElement = m; - } + } + } else { + foreach (ITypeDefinition c in currentClass.NestedTypes) { + if (c.Region.BeginLine < nextElementLine && c.Region.BeginLine > caretLine) { + nextElementLine = c.Region.BeginLine; + nextElement = c; } - foreach (IMember m in currentClass.Events) { - if (m.Region.BeginLine < nextElementLine && m.Region.BeginLine > caretLine) { - nextElementLine = m.Region.BeginLine; - nextElement = m; - } + } + foreach (IMember m in currentClass.Members) { + if (m.Region.BeginLine < nextElementLine && m.Region.BeginLine > caretLine) { + nextElementLine = m.Region.BeginLine; + nextElement = m; } } } @@ -237,11 +218,11 @@ namespace CSharpBinding.FormattingStrategy { int regions = 0; int endregions = 0; - for (int i = 1; i <= document.TotalNumberOfLines; i++) { - string text = document.GetLine(i).Text.Trim(); - if (text.StartsWith("#region")) { + for (int i = 1; i <= document.LineCount; i++) { + string text = document.GetText(document.GetLineByNumber(i)).Trim(); + if (text.StartsWith("#region", StringComparison.Ordinal)) { ++regions; - } else if (text.StartsWith("#endregion")) { + } else if (text.StartsWith("#endregion", StringComparison.Ordinal)) { ++endregions; } } @@ -257,18 +238,18 @@ namespace CSharpBinding.FormattingStrategy void FormatLineInternal(ITextEditor textArea, int lineNr, int cursorOffset, char ch) { - IDocumentLine curLine = textArea.Document.GetLine(lineNr); - IDocumentLine lineAbove = lineNr > 1 ? textArea.Document.GetLine(lineNr - 1) : null; + IDocumentLine curLine = textArea.Document.GetLineByNumber(lineNr); + IDocumentLine lineAbove = lineNr > 1 ? textArea.Document.GetLineByNumber(lineNr - 1) : null; string terminator = DocumentUtilitites.GetLineTerminator(textArea.Document, lineNr); string curLineText; //// local string for curLine segment if (ch == '/') { - curLineText = curLine.Text; - string lineAboveText = lineAbove == null ? "" : lineAbove.Text; + curLineText = textArea.Document.GetText(curLine); + string lineAboveText = lineAbove == null ? "" : textArea.Document.GetText(lineAbove); if (curLineText != null && curLineText.EndsWith("///") && (lineAboveText == null || !lineAboveText.Trim().StartsWith("///"))) { string indentation = DocumentUtilitites.GetWhitespaceAfter(textArea.Document, curLine.Offset); - object member = GetMemberAfter(textArea, lineNr); + IEntity member = GetMemberAfter(textArea, lineNr); if (member != null) { StringBuilder sb = new StringBuilder(); sb.Append(" "); @@ -290,10 +271,13 @@ namespace CSharpBinding.FormattingStrategy sb.Append("\">"); } } - if (method.ReturnType != null && !method.IsConstructor && method.ReturnType.FullyQualifiedName != "System.Void") { - sb.Append(terminator); - sb.Append(indentation); - sb.Append("/// "); + if (!method.IsConstructor) { + IType returnType = method.ReturnType.Resolve(ParserService.CurrentTypeResolveContext); + if (returnType.Kind != TypeKind.Void) { + sb.Append(terminator); + sb.Append(indentation); + sb.Append("/// "); + } } } textArea.Document.Insert(cursorOffset, sb.ToString()); @@ -312,7 +296,7 @@ namespace CSharpBinding.FormattingStrategy switch (ch) { case '>': if (IsInsideDocumentationComment(textArea, curLine, cursorOffset)) { - curLineText = curLine.Text; + curLineText = textArea.Document.GetText(curLine); int column = cursorOffset - curLine.Offset; int index = Math.Min(column - 1, curLineText.Length - 1); @@ -347,11 +331,11 @@ namespace CSharpBinding.FormattingStrategy //} break; case '\n': - string lineAboveText = lineAbove == null ? "" : lineAbove.Text; + string lineAboveText = lineAbove == null ? "" : textArea.Document.GetText(lineAbove); //// curLine might have some text which should be added to indentation - curLineText = curLine.Text; + curLineText = textArea.Document.GetText(curLine); - if (lineAbove != null && lineAbove.Text.Trim().StartsWith("#region") + if (lineAboveText != null && lineAboveText.Trim().StartsWith("#region") && NeedEndregion(textArea.Document)) { textArea.Document.Insert(cursorOffset, "#endregion"); @@ -382,8 +366,8 @@ namespace CSharpBinding.FormattingStrategy } if (lineAbove != null && isInNormalCode) { - IDocumentLine nextLine = lineNr + 1 <= textArea.Document.TotalNumberOfLines ? textArea.Document.GetLine(lineNr + 1) : null; - string nextLineText = (nextLine != null) ? nextLine.Text : ""; + IDocumentLine nextLine = lineNr + 1 <= textArea.Document.LineCount ? textArea.Document.GetLineByNumber(lineNr + 1) : null; + string nextLineText = (nextLine != null) ? textArea.Document.GetText(nextLine) : ""; int indexAbove = lineAboveText.IndexOf("///"); int indexNext = nextLineText.IndexOf("///"); @@ -399,12 +383,12 @@ namespace CSharpBinding.FormattingStrategy } } if (textArea.Options.AutoInsertBlockEnd && lineAbove != null && isInNormalCode) { - string oldLineText = lineAbove.Text; + string oldLineText = textArea.Document.GetText(lineAbove); if (oldLineText.EndsWith("{")) { if (NeedCurlyBracket(textArea.Document.Text)) { int insertionPoint = curLine.Offset + curLine.Length; textArea.Document.Insert(insertionPoint, terminator + "}"); - IndentLine(textArea, textArea.Document.GetLine(lineNr + 1)); + IndentLine(textArea, textArea.Document.GetLineByNumber(lineNr + 1)); textArea.Caret.Offset = insertionPoint; } } diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/DocumentAccessor.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/DocumentAccessor.cs index 359b6faa3f..91e6619d69 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/DocumentAccessor.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/DocumentAccessor.cs @@ -3,6 +3,7 @@ using System; using ICSharpCode.AvalonEdit.Indentation.CSharp; +using ICSharpCode.Editor; using ICSharpCode.SharpDevelop.Editor; namespace CSharpBinding.FormattingStrategy @@ -25,7 +26,7 @@ namespace CSharpBinding.FormattingStrategy throw new ArgumentNullException("document"); doc = document; this.minLine = 1; - this.maxLine = doc.TotalNumberOfLines; + this.maxLine = doc.LineCount; } /// @@ -79,8 +80,8 @@ namespace CSharpBinding.FormattingStrategy } ++num; if (num > maxLine) return false; - line = doc.GetLine(num); - text = line.Text; + line = doc.GetLineByNumber(num); + text = doc.GetText(line); return true; } } diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/Parser.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/Parser.cs index 90a6612d1d..1e7f78d0e4 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/Parser.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/Parser.cs @@ -3,10 +3,11 @@ using System; using System.IO; +using ICSharpCode.Core; +using ICSharpCode.Editor; +using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.SharpDevelop; -using ICSharpCode.SharpDevelop.Dom; -using ICSharpCode.SharpDevelop.Dom.CSharp; -using ICSharpCode.SharpDevelop.Dom.NRefactoryResolver; +using ICSharpCode.SharpDevelop.Parser; using ICSharpCode.SharpDevelop.Project; namespace CSharpBinding.Parser @@ -25,27 +26,12 @@ namespace CSharpBinding.Parser } } - public LanguageProperties Language { - get { - return LanguageProperties.CSharp; - } - } - - public IExpressionFinder CreateExpressionFinder(string fileName) - { - return new CSharpExpressionFinder(ParserService.GetParseInformation(fileName)); - } - public bool CanParse(string fileName) { return Path.GetExtension(fileName).Equals(".CS", StringComparison.OrdinalIgnoreCase); } - public bool CanParse(IProject project) - { - return project.Language == "C#"; - } - + /* void RetrieveRegions(ICompilationUnit cu, ICSharpCode.NRefactory.Parser.SpecialTracker tracker) { for (int i = 0; i < tracker.CurrentSpecials.Count; ++i) { @@ -75,31 +61,15 @@ namespace CSharpBinding.Parser } } } + */ - public ICompilationUnit Parse(IProjectContent projectContent, string fileName, ITextBuffer fileContent) - { - using (ICSharpCode.NRefactory.IParser p = ICSharpCode.NRefactory.ParserFactory.CreateParser(ICSharpCode.NRefactory.SupportedLanguage.CSharp, fileContent.CreateReader())) { - return Parse(p, fileName, projectContent); - } - } - - ICompilationUnit Parse(ICSharpCode.NRefactory.IParser p, string fileName, IProjectContent projectContent) + public ParseInformation Parse(IProjectContent projectContent, FileName fileName, ITextSource fileContent, + bool fullParseInformationRequested) { - p.Lexer.SpecialCommentTags = lexerTags; - p.ParseMethodBodies = false; - p.Parse(); - - NRefactoryASTConvertVisitor visitor = new NRefactoryASTConvertVisitor(projectContent, ICSharpCode.NRefactory.SupportedLanguage.CSharp); - visitor.Specials = p.Lexer.SpecialTracker.CurrentSpecials; - visitor.VisitCompilationUnit(p.CompilationUnit, null); - visitor.Cu.FileName = fileName; - visitor.Cu.ErrorsDuringCompile = p.Errors.Count > 0; - RetrieveRegions(visitor.Cu, p.Lexer.SpecialTracker); - AddCommentTags(visitor.Cu, p.Lexer.TagComments); - return visitor.Cu; + throw new NotImplementedException(); } - void AddCommentTags(ICompilationUnit cu, System.Collections.Generic.List tagComments) + /*void AddCommentTags(ICompilationUnit cu, System.Collections.Generic.List tagComments) { foreach (ICSharpCode.NRefactory.Parser.TagComment tagComment in tagComments) { DomRegion tagRegion = new DomRegion(tagComment.StartPosition.Y, tagComment.StartPosition.X); @@ -107,11 +77,6 @@ namespace CSharpBinding.Parser cu.TagComments.Add(tag); } } - - public IResolver CreateResolver() - { - return new NRefactoryResolver(LanguageProperties.CSharp); - } - ///////// IParser Interface END + */ } } diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/CSharpMyNamespaceBuilder.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/CSharpMyNamespaceBuilder.cs index e9a6b708e2..607e6560a8 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/CSharpMyNamespaceBuilder.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/CSharpMyNamespaceBuilder.cs @@ -6,8 +6,8 @@ using System.Collections.Generic; using ICSharpCode.Core; using System.IO; using System.Text; +using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.SharpDevelop; -using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.SharpDevelop.Project; namespace CSharpBinding @@ -23,10 +23,10 @@ namespace CSharpBinding return typeof(CSharpMyNamespaceBuilder).Assembly.GetManifestResourceStream("Resources.MyNamespaceSupportForCSharp.cs"); } - internal static IClass FindMyFormsClass(IProjectContent pc, string myNamespace) + internal static ITypeDefinition FindMyFormsClass(IProjectContent pc, string myNamespace) { if (pc != null) { - return pc.GetClass(myNamespace + ".MyForms", 0); + return pc.GetTypeDefinition(myNamespace, "MyForms", 0, StringComparer.Ordinal); } return null; } @@ -62,11 +62,11 @@ namespace CSharpBinding continue; } if (trimmedLine == "/*LIST OF FORMS*/") { - IClass myFormsClass = FindMyFormsClass(ParserService.GetProjectContent(vbProject), ns); + ITypeDefinition myFormsClass = FindMyFormsClass(vbProject.ProjectContent, ns); if (myFormsClass != null) { string indentation = line.Substring(0, line.Length - trimmedLine.Length); foreach (IProperty p in myFormsClass.Properties) { - string typeName = "global::" + p.ReturnType.FullyQualifiedName; + string typeName = "global::" + p.ReturnType.Resolve(vbProject.TypeResolveContext).FullName; output.AppendLine(indentation + typeName + " " + p.Name + "_instance;"); output.AppendLine(indentation + "bool " + p.Name + "_isCreating;"); output.AppendLine(indentation + "public " + typeName + " " + p.Name + " {"); diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/CSharpProject.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/CSharpProject.cs index f64affd20b..e57f9459b3 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/CSharpProject.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/CSharpProject.cs @@ -8,8 +8,6 @@ using System.IO; using System.Linq; using ICSharpCode.SharpDevelop; -using ICSharpCode.SharpDevelop.Dom; -using ICSharpCode.SharpDevelop.Dom.CSharp; using ICSharpCode.SharpDevelop.Internal.Templates; using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project.Converter; @@ -30,10 +28,6 @@ namespace CSharpBinding get { return CSharpProjectBinding.LanguageName; } } - public override LanguageProperties LanguageProperties { - get { return LanguageProperties.CSharp; } - } - void Init() { reparseReferencesSensitiveProperties.Add("TargetFrameworkVersion"); diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/RemoveMembersInRangeVisitor.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/RemoveMembersInRangeVisitor.cs deleted file mode 100644 index c1e4ba64df..0000000000 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/RemoveMembersInRangeVisitor.cs +++ /dev/null @@ -1,57 +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; -using ICSharpCode.NRefactory.Ast; -using ICSharpCode.NRefactory.Visitors; -using ICSharpCode.SharpDevelop.Dom; - -namespace CSharpBinding -{ - /// - /// Removes members that are in the specified range. - /// - sealed class RemoveMembersInRangeVisitor : AbstractAstTransformer - { - DomRegion region; - - public RemoveMembersInRangeVisitor(DomRegion region) - { - this.region = region; - } - - bool RemoveIfInRange(INode node) - { - if (node.StartLocation.IsEmpty) - return false; - if (region.IsInside(node.StartLocation.Line, node.StartLocation.Column)) { - if (node.EndLocation.IsEmpty || region.IsInside(node.EndLocation.Line, node.EndLocation.Column)) { - RemoveCurrentNode(); - return true; - } - } - return false; - } - - public override object VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, object data) - { - return RemoveIfInRange(propertyDeclaration) ? null : base.VisitPropertyDeclaration(propertyDeclaration, data); - } - - public override object VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data) - { - return RemoveIfInRange(methodDeclaration) ? null : base.VisitMethodDeclaration(methodDeclaration, data); - } - - public override object VisitFieldDeclaration(FieldDeclaration fieldDeclaration, object data) - { - return RemoveIfInRange(fieldDeclaration) ? null : base.VisitFieldDeclaration(fieldDeclaration, data); - } - - public override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) - { - return RemoveIfInRange(typeDeclaration) ? null : base.VisitTypeDeclaration(typeDeclaration, data); - } - } -} diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/VBNetToCSharpConvertVisitorWithMyFormsSupport.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/VBNetToCSharpConvertVisitorWithMyFormsSupport.cs index bbe2d34d49..2e1e87ca1b 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/VBNetToCSharpConvertVisitorWithMyFormsSupport.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/VBNetToCSharpConvertVisitorWithMyFormsSupport.cs @@ -1,6 +1,7 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +/* using System; using System.Collections.Generic; using System.IO; @@ -67,3 +68,4 @@ namespace CSharpBinding } } } +*/ \ No newline at end of file diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/VBNetToCSharpConverter.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/VBNetToCSharpConverter.cs index 3dedfbacd5..4ab90e3434 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/VBNetToCSharpConverter.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/VBNetToCSharpConverter.cs @@ -1,6 +1,6 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - +/* using System; using System.Collections.Generic; using System.IO; @@ -104,7 +104,7 @@ namespace CSharpBinding } else { // remove ifdef including the code compilationUnit.AcceptVisitor(new RemoveMembersInRangeVisitor( - DomRegion.FromLocation(specials[i].StartPosition, specials[j].EndPosition)), null); + new DomRegion(specials[i].StartPosition, specials[j].EndPosition)), null); specials.RemoveRange(i, j - i + 1); } i--; @@ -119,3 +119,4 @@ namespace CSharpBinding } } } +*/ \ No newline at end of file diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs index 7c737bb4d3..f4242fddc5 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs @@ -518,7 +518,7 @@ namespace ICSharpCode.AvalonEdit.AddIn void FetchParseInformation() { - ParseInformation parseInfo = ParserService.GetExistingParsedFile(this.FileName); + ParseInformation parseInfo = ParserService.GetCachedParseInformation(this.FileName); if (parseInfo == null) { // if parse info is not yet available, start parsing on background ParserService.ParseAsync(this.FileName, primaryTextEditorAdapter.Document); diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs index 6a358e091e..72cc9f58e7 100755 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs @@ -77,7 +77,7 @@ namespace ICSharpCode.AvalonEdit.AddIn hiddenDefinitionRenderer.Dispose(); } - protected override string FileName { + protected override ICSharpCode.Core.FileName FileName { get { return this.Adapter.FileName; } } @@ -456,7 +456,7 @@ namespace ICSharpCode.AvalonEdit.AddIn #region UpdateParseInformation - Folding void UpdateParseInformationForFolding() { - UpdateParseInformationForFolding(ParserService.GetExistingParsedFile(this.Adapter.FileName)); + UpdateParseInformationForFolding(null); } bool disableParseInformationFolding; @@ -473,8 +473,12 @@ namespace ICSharpCode.AvalonEdit.AddIn public void UpdateParseInformationForFolding(ParseInformation parseInfo) { - if (!CodeEditorOptions.Instance.EnableFolding || disableParseInformationFolding) + if (!CodeEditorOptions.Instance.EnableFolding || disableParseInformationFolding) { parseInfo = null; + } else { + if (parseInfo == null || !parseInfo.IsFullParseInformation) + parseInfo = ParserService.Parse(this.FileName, this.Document); + } IServiceContainer container = this.Adapter.GetService(typeof(IServiceContainer)) as IServiceContainer; ParserFoldingStrategy folding = container.GetService(typeof(ParserFoldingStrategy)) as ParserFoldingStrategy; diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Commands/SortSelectionCommand.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Commands/SortSelectionCommand.cs index 330acd339d..0df4a585c3 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Commands/SortSelectionCommand.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Commands/SortSelectionCommand.cs @@ -54,13 +54,13 @@ namespace ICSharpCode.AvalonEdit.AddIn.Commands using (document.OpenUndoGroup()) { for (int i = 0; i < lines.Count; ++i) { - IDocumentLine line = document.GetLine(startLine + i); + IDocumentLine line = document.GetLineByNumber(startLine + i); document.Replace(line.Offset, line.Length, lines[i]); } // remove removed duplicate lines for (int i = startLine + lines.Count; i <= endLine; ++i) { - IDocumentLine line = document.GetLine(startLine + lines.Count); + IDocumentLine line = document.GetLineByNumber(startLine + lines.Count); document.Remove(line.Offset, line.TotalLength); } } diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/MyersDiff/DocumentSequence.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/MyersDiff/DocumentSequence.cs index 2f37b44ce3..3fcaf8a0d4 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/MyersDiff/DocumentSequence.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/MyersDiff/DocumentSequence.cs @@ -14,12 +14,12 @@ namespace ICSharpCode.AvalonEdit.AddIn.MyersDiff public DocumentSequence(IDocument document, Dictionary hashDict) { - this.hashes = new int[document.TotalNumberOfLines]; + this.hashes = new int[document.LineCount]; // Construct a perfect hash for the document lines, and store the 'hash code' // (really just a unique identifier for each line content) in our array. - for (int i = 1; i <= document.TotalNumberOfLines; i++) { - string text = document.GetLine(i).Text; + for (int i = 1; i <= document.LineCount; i++) { + string text = document.GetText(document.GetLineByNumber(i)); int hash; if (!hashDict.TryGetValue(text, out hash)) { hash = hashDict.Count; diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ParserFoldingStrategy.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ParserFoldingStrategy.cs index 3e84c2fa49..1dc936d936 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ParserFoldingStrategy.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ParserFoldingStrategy.cs @@ -55,13 +55,15 @@ namespace ICSharpCode.AvalonEdit.AddIn foreach (ITypeDefinition c in parseInfo.ParsedFile.TopLevelTypeDefinitions) { AddClassMembers(c, newFoldMarkers); } + #warning Additional folding regions + /* foreach (FoldingRegion foldingRegion in parseInfo.FoldingRegions) { NewFolding f = new NewFoldingDefinition(GetOffset(foldingRegion.Region.BeginLine, foldingRegion.Region.BeginColumn), GetOffset(foldingRegion.Region.EndLine, foldingRegion.Region.EndColumn)); f.DefaultClosed = isFirstUpdate; f.Name = foldingRegion.Name; newFoldMarkers.Add(f); - } + }*/ } return newFoldMarkers.OrderBy(f => f.StartOffset); } diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.cs index e24b15b96c..74ddcabdc8 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.cs @@ -51,7 +51,7 @@ namespace ICSharpCode.AvalonEdit.AddIn ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList | ConversionFlags.UseFullyQualifiedMemberNames; else ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList | ConversionFlags.ShowParameterList | ConversionFlags.ShowParameterNames; - text = ambience.Convert(entity); + text = ambience.ConvertEntity(entity); image = ClassBrowserIconService.GetIcon(entity); } diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/SharpDevelopTextEditor.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/SharpDevelopTextEditor.cs index e8d110714d..dd311b74b1 100755 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/SharpDevelopTextEditor.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/SharpDevelopTextEditor.cs @@ -56,8 +56,8 @@ namespace ICSharpCode.AvalonEdit.AddIn options.BindToTextEditor(this); } - protected virtual string FileName { - get { return "untitled"; } + protected virtual ICSharpCode.Core.FileName FileName { + get { return ICSharpCode.Core.FileName.Create("untitled"); } } SharpDevelopCompletionWindow completionWindow; diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/CodeSnippet.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/CodeSnippet.cs index df764ed9f6..77ce10e2bb 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/CodeSnippet.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/CodeSnippet.cs @@ -196,7 +196,7 @@ namespace ICSharpCode.AvalonEdit.AddIn.Snippets { var parseInfo = ParserService.GetExistingParsedFile(editor.FileName); if (parseInfo != null) { - return parseInfo.GetInnermostClass(editor.Caret.Line, editor.Caret.Column); + return parseInfo.GetInnerMostTypeDefinition(editor.Caret.Location); } return null; } @@ -207,12 +207,15 @@ namespace ICSharpCode.AvalonEdit.AddIn.Snippets return s => s.ToLower(); if ("toUpper".Equals(name, StringComparison.OrdinalIgnoreCase)) return s => s.ToUpper(); + #warning Reimplement language-specific name conversion functions + /* if ("toFieldName".Equals(name, StringComparison.OrdinalIgnoreCase)) return s => context.Language.Properties.CodeGenerator.GetFieldName(s); if ("toPropertyName".Equals(name, StringComparison.OrdinalIgnoreCase)) return s => context.Language.Properties.CodeGenerator.GetPropertyName(s); if ("toParameterName".Equals(name, StringComparison.OrdinalIgnoreCase)) return s => context.Language.Properties.CodeGenerator.GetParameterName(s); + */ return null; } diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstLocation.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstLocation.cs index 2d0a5a7962..624eb9bf31 100644 --- a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstLocation.cs +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstLocation.cs @@ -133,5 +133,15 @@ namespace ICSharpCode.NRefactory.CSharp { return !(left < right); } + + public static implicit operator AstLocation(ICSharpCode.Editor.TextLocation location) + { + return new AstLocation(location.Line, location.Column); + } + + public static implicit operator ICSharpCode.Editor.TextLocation(AstLocation location) + { + return new ICSharpCode.Editor.TextLocation(location.Line, location.Column); + } } } diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj b/src/Libraries/NRefactory/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj index 2e03047685..e9cbf99298 100644 --- a/src/Libraries/NRefactory/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj @@ -421,6 +421,10 @@ {D68133BD-1E63-496E-9EDE-4FBDBF77B486} Mono.Cecil + + {F054A788-B591-4561-A8BA-AE745BBEB817} + ICSharpCode.Editor + \ No newline at end of file diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/NewFileDialog.cs b/src/Main/Base/Project/Src/Gui/Dialogs/NewFileDialog.cs index a994985d08..70fe4f11ad 100644 --- a/src/Main/Base/Project/Src/Gui/Dialogs/NewFileDialog.cs +++ b/src/Main/Base/Project/Src/Gui/Dialogs/NewFileDialog.cs @@ -395,7 +395,7 @@ namespace ICSharpCode.SharpDevelop.Gui File.Copy(binaryFileName, parsedFileName); else File.WriteAllText(parsedFileName, parsedContent, ParserService.DefaultFileEncoding); - ParserService.ParseFile(parsedFileName, new StringTextSource(parsedContent)); + ParserService.ParseFileAsync(FileName.Create(parsedFileName), new StringTextSource(parsedContent)); } else { if (!String.IsNullOrEmpty(binaryFileName)) { LoggingService.Warn("binary file was skipped"); diff --git a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/Commands/ReferenceFolderNodeCommands.cs b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/Commands/ReferenceFolderNodeCommands.cs index 0c9140eea7..7c365c3806 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/Commands/ReferenceFolderNodeCommands.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/Commands/ReferenceFolderNodeCommands.cs @@ -64,7 +64,7 @@ namespace ICSharpCode.SharpDevelop.Project.Commands } // Update code completion. - ParserService.ParseFile(webReference.WebProxyFileName); + ParserService.ParseFileAsync(FileName.Create(webReference.WebProxyFileName)); } } catch (WebException ex) { MessageService.ShowException(ex, String.Format(StringParser.Parse("${res:ICSharpCode.SharpDevelop.Commands.ProjectBrowser.RefreshWebReference.ReadServiceDescriptionError}"), url.UpdateFromURL)); @@ -121,7 +121,7 @@ namespace ICSharpCode.SharpDevelop.Project.Commands AddWebReferenceToProjectBrowser(node, refDialog.WebReference); // Add proxy to code completion. - ParserService.ParseFile(refDialog.WebReference.WebProxyFileName); + ParserService.ParseFileAsync(FileName.Create(refDialog.WebReference.WebProxyFileName)); node.Project.Save(); } diff --git a/src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskListPad.cs b/src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskListPad.cs index a33a4d62f5..bdefd7afaf 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskListPad.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskListPad.cs @@ -210,7 +210,7 @@ namespace ICSharpCode.SharpDevelop.Gui if (WorkbenchSingleton.Workbench.ActiveViewContent == null) return null; - IParsedFile parseInfo = ParserService.GetParseInformation(WorkbenchSingleton.Workbench.ActiveViewContent.PrimaryFileName); + IParsedFile parseInfo = ParserService.GetExistingParsedFile(WorkbenchSingleton.Workbench.ActiveViewContent.PrimaryFileName); if (parseInfo != null) { IPositionable positionable = WorkbenchSingleton.Workbench.ActiveViewContent as IPositionable; if (positionable != null) { diff --git a/src/Main/Base/Project/Src/Project/CustomTool.cs b/src/Main/Base/Project/Src/Project/CustomTool.cs index 06798e8d9d..1d1c709a4f 100644 --- a/src/Main/Base/Project/Src/Project/CustomTool.cs +++ b/src/Main/Base/Project/Src/Project/CustomTool.cs @@ -201,7 +201,7 @@ namespace ICSharpCode.SharpDevelop.Project }, outputFileName, FileErrorPolicy.Inform); EnsureOutputFileIsInProject(baseItem, outputFileName); - ParserService.ParseAsync(outputFileName, new StringTextSource(codeOutput)); + ParserService.ParseAsync(FileName.Create(outputFileName), new StringTextSource(codeOutput)); } public void GenerateCodeDomAsync(FileProjectItem baseItem, string outputFileName, Func func) diff --git a/src/Main/Base/Project/Src/Services/AmbienceService/CSharpAmbience.cs b/src/Main/Base/Project/Src/Services/AmbienceService/CSharpAmbience.cs index ad75032994..e2319ce2f9 100644 --- a/src/Main/Base/Project/Src/Services/AmbienceService/CSharpAmbience.cs +++ b/src/Main/Base/Project/Src/Services/AmbienceService/CSharpAmbience.cs @@ -2,6 +2,7 @@ // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; +using ICSharpCode.NRefactory.TypeSystem; namespace ICSharpCode.SharpDevelop { @@ -10,5 +11,41 @@ namespace ICSharpCode.SharpDevelop /// public class CSharpAmbience : IAmbience { + public ConversionFlags ConversionFlags { get; set; } + + public string ConvertEntity(IEntity e) + { + throw new NotImplementedException(); + } + + public string ConvertParameter(IVariable v) + { + throw new NotImplementedException(); + } + + public string ConvertType(IType type) + { + throw new NotImplementedException(); + } + + public string ConvertAccessibility(Accessibility accessibility) + { + throw new NotImplementedException(); + } + + public string WrapAttribute(string attribute) + { + throw new NotImplementedException(); + } + + public string WrapComment(string comment) + { + throw new NotImplementedException(); + } + + public string GetIntrinsicTypeName(string dotNetTypeName) + { + throw new NotImplementedException(); + } } } diff --git a/src/Main/Base/Project/Src/Services/AmbienceService/IAmbience.cs b/src/Main/Base/Project/Src/Services/AmbienceService/IAmbience.cs index 7854a8567b..3f0f4330e6 100644 --- a/src/Main/Base/Project/Src/Services/AmbienceService/IAmbience.cs +++ b/src/Main/Base/Project/Src/Services/AmbienceService/IAmbience.cs @@ -2,11 +2,94 @@ // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; +using ICSharpCode.NRefactory.TypeSystem; namespace ICSharpCode.SharpDevelop { + [Flags] + public enum ConversionFlags + { + /// + /// Convert only the name. + /// + None = 0, + /// + /// Show the parameter list + /// + ShowParameterList = 1, + /// + /// Show names for parameters + /// + ShowParameterNames = 2, + /// + /// Show the accessibility (private, public, etc.) + /// + ShowAccessibility = 4, + /// + /// Show the definition key word (class, struct, Sub, Function, etc.) + /// + ShowDefinitionKeyWord = 8, + /// + /// Show the fully qualified name for the member + /// + UseFullyQualifiedMemberNames = 0x10, + /// + /// Show modifiers (virtual, override, etc.) + /// + ShowModifiers = 0x20, + /// + /// Show the inheritance declaration + /// + ShowInheritanceList = 0x40, + + IncludeHtmlMarkup = 0x80, + /// + /// Show the return type + /// + ShowReturnType = 0x100, + /// + /// Use fully qualified names for return type and parameters. + /// + UseFullyQualifiedTypeNames = 0x200, + /// + /// Include opening brace (or equivalent) for methods or classes; + /// or semicolon (or equivalent) for field, events. + /// For properties, a block indicating if there is a getter/setter is included. + /// + IncludeBody = 0x400, + /// + /// Show the list of type parameters on method and class declarations. + /// Type arguments for parameter/return types are always shown. + /// + ShowTypeParameterList = 0x800, + + StandardConversionFlags = ShowParameterNames | + ShowAccessibility | + ShowParameterList | + ShowReturnType | + ShowModifiers | + ShowTypeParameterList | + ShowDefinitionKeyWord, + + All = 0xfff, + } + public interface IAmbience { + ConversionFlags ConversionFlags { + get; + set; + } + + string ConvertEntity(IEntity e); + string ConvertParameter(IVariable v); + string ConvertType(IType type); + + string ConvertAccessibility(Accessibility accessibility); + + string WrapAttribute(string attribute); + string WrapComment(string comment); + string GetIntrinsicTypeName(string dotNetTypeName); } } diff --git a/src/Main/Base/Project/Src/Services/ParserService/IParser.cs b/src/Main/Base/Project/Src/Services/ParserService/IParser.cs index e52da544d4..b9830d3f99 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/IParser.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/IParser.cs @@ -1,6 +1,7 @@ // 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 ICSharpCode.Core; using ICSharpCode.Editor; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.SharpDevelop.Editor; @@ -45,7 +46,7 @@ namespace ICSharpCode.SharpDevelop.Project /// SharpDevelop may call IParser.Parse in parallel. This will be done on the same IParser instance /// if there are two parallel parse requests for the same file. Parser implementations must be thread-safe. /// - ParseInformation Parse(IProjectContent projectContent, string fileName, ITextSource fileContent, + ParseInformation Parse(IProjectContent projectContent, FileName fileName, ITextSource fileContent, bool fullParseInformationRequested); //IResolver CreateResolver(); diff --git a/src/Main/Base/Project/Src/Services/ParserService/ParseInformationEventArgs.cs b/src/Main/Base/Project/Src/Services/ParserService/ParseInformationEventArgs.cs index 9f4417479a..a0dec8a2ed 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/ParseInformationEventArgs.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/ParseInformationEventArgs.cs @@ -92,9 +92,9 @@ namespace ICSharpCode.SharpDevelop.Parser { FileName fileName; ITextSource content; - IParsedFile parsedFile; + ParseInformation parseInformation; - public ParserUpdateStepEventArgs(FileName fileName, ITextSource content, IParsedFile parsedFile) + public ParserUpdateStepEventArgs(FileName fileName, ITextSource content, ParseInformation parsedFile) { if (fileName == null) throw new ArgumentNullException("fileName"); @@ -104,7 +104,7 @@ namespace ICSharpCode.SharpDevelop.Parser throw new ArgumentNullException("parsedFile"); this.fileName = fileName; this.content = content; - this.parsedFile = parsedFile; + this.parseInformation = parsedFile; } public FileName FileName { @@ -121,7 +121,7 @@ namespace ICSharpCode.SharpDevelop.Parser public IParsedFile ParsedFile { get { - return parsedFile; + return parseInformation.ParsedFile; } } } diff --git a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs index 3b18dea81d..2c55750c51 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs @@ -260,8 +260,8 @@ namespace ICSharpCode.SharpDevelop.Parser snapshot = GetParseableFileContent(viewContent.PrimaryFileName); lastParseRun = ParseAsync(fileName, snapshot).ContinueWith( - delegate(Task backgroundTask) { - IParsedFile parseInfo = backgroundTask.Result; + delegate(Task backgroundTask) { + ParseInformation parseInfo = backgroundTask.Result; RaiseParserUpdateStepFinished(new ParserUpdateStepEventArgs(fileName, snapshot, parseInfo)); }); } @@ -318,17 +318,26 @@ namespace ICSharpCode.SharpDevelop.Parser /// This method is thread-safe. This method involves waiting for the main thread, so using it while /// holding a lock can lead to deadlocks. /// + public static ITextSource GetParseableFileContent(FileName fileName) + { + ITextSource fileContent = Gui.WorkbenchSingleton.SafeThreadFunction(GetParseableFileContentForOpenFile, fileName); + if (fileContent != null) + return fileContent; + else + return new StringTextSource(ICSharpCode.AvalonEdit.Utils.FileReader.ReadFileContent(fileName, DefaultFileEncoding)); + } + public static ITextSource GetParseableFileContent(string fileName) { - return Gui.WorkbenchSingleton.SafeThreadFunction(GetParseableFileContentInternal, fileName); + return GetParseableFileContent(FileName.Create(fileName)); } - static ITextSource GetParseableFileContentInternal(string fileName) + /// + /// Gets the file content for a file that is currently open. + /// Returns null if the file is not open. + /// + static ITextSource GetParseableFileContentForOpenFile(FileName fileName) { - //ITextBuffer res = project.GetParseableFileContent(fileName); - //if (res != null) - // return res; - OpenedFile file = FileService.GetOpenedFile(fileName); if (file != null) { IFileDocumentProvider p = file.CurrentView as IFileDocumentProvider; @@ -344,9 +353,7 @@ namespace ICSharpCode.SharpDevelop.Parser return new StringTextSource(ICSharpCode.AvalonEdit.Utils.FileReader.ReadFileContent(s, DefaultFileEncoding)); } } - - // load file - return new StringTextSource(ICSharpCode.AvalonEdit.Utils.FileReader.ReadFileContent(fileName, DefaultFileEncoding)); + return null; } #endregion @@ -358,6 +365,7 @@ namespace ICSharpCode.SharpDevelop.Parser readonly FileName fileName; internal readonly IParser parser; volatile IParsedFile mainParsedFile; + volatile ParseInformation cachedParseInformation; ITextSourceVersion bufferVersion; IParsedFile[] oldUnits = emptyCompilationUnitArray; bool disposed; @@ -379,16 +387,12 @@ namespace ICSharpCode.SharpDevelop.Parser } } - public IParsedFile GetParseInformation(IProjectContent content) + public ParseInformation GetCachedParseInformation() { - IParsedFile p = GetExistingParseInformation(content); - if (p != null) - return p; - else - return ParseFile(content, null); + return cachedParseInformation; // read volatile } - public IParsedFile GetExistingParseInformation(IProjectContent content) + public IParsedFile GetExistingParsedFile(IProjectContent content) { if (content == null) { return this.mainParsedFile; // read volatile @@ -407,30 +411,84 @@ namespace ICSharpCode.SharpDevelop.Parser } } + public ParseInformation Parse(ITextSource fileContent) + { + if (fileContent == null) { + fileContent = WorkbenchSingleton.SafeThreadFunction(GetParseableFileContentForOpenFile, fileName); + } + + ParseInformation parseInfo; + IParsedFile parsedFile; + DoParse(null, fileContent, true, out parseInfo, out parsedFile); + return parseInfo; + } + public IParsedFile ParseFile(IProjectContent parentProjectContent, ITextSource fileContent) { + if (fileContent == null) { + fileContent = WorkbenchSingleton.SafeThreadFunction(GetParseableFileContentForOpenFile, fileName); + } + + ParseInformation parseInfo; + IParsedFile parsedFile; + DoParse(parentProjectContent, fileContent, false, out parseInfo, out parsedFile); + return parsedFile; + } + + void DoParse(IProjectContent parentProjectContent, ITextSource fileContent, + bool fullParseInformationRequested, out ParseInformation resultParseInfo, out IParsedFile resultUnit) + { + resultParseInfo = null; + resultUnit = null; + if (parser == null) - return null; + return; if (fileContent == null) { - // GetParseableFileContent must not be called inside any lock - // (otherwise we'd risk deadlocks because GetParseableFileContent must invoke on the main thread) - fileContent = GetParseableFileContent(fileName); + // 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. + lock (this) { + // Don't bother reading the file if this FileEntry was already disposed. + if (this.disposed) + return; + } + string fileAsString; + try { + fileAsString = ICSharpCode.AvalonEdit.Utils.FileReader.ReadFileContent(fileName, DefaultFileEncoding); + } catch (IOException) { + return; + } catch (UnauthorizedAccessException) { + return; + } + fileContent = new StringTextSource(fileAsString); } ITextSourceVersion fileContentVersion = fileContent.Version; List projectContents; lock (this) { if (this.disposed) - return null; + return; if (fileContentVersion != null && this.bufferVersion != null && this.bufferVersion.BelongsToSameDocumentAs(fileContentVersion)) { if (this.bufferVersion.CompareAge(fileContentVersion) >= 0) { - // Special case: (necessary due to parentProjectContent optimization) + // Special case: (necessary due to parentProjectContent optimization below) // Detect when a file belongs to multiple projects but the ParserService hasn't realized // that, yet. In this case, do another parse run to detect all parent projects. if (!(parentProjectContent != null && this.oldUnits.Length == 1 && this.oldUnits[0].ProjectContent != parentProjectContent)) { - return this.mainParsedFile; + // If full parse info is requested, ensure we have full parse info. + if (!(fullParseInformationRequested && this.cachedParseInformation == null)) { + resultParseInfo = this.cachedParseInformation; + resultUnit = this.mainParsedFile; + if (parentProjectContent != null) { + foreach (var oldUnit in this.oldUnits) { + if (oldUnit.ProjectContent == parentProjectContent) { + resultUnit = oldUnit; + break; + } + } + } + return; + } } } } @@ -443,7 +501,8 @@ namespace ICSharpCode.SharpDevelop.Parser } else { projectContents = GetProjectContents(fileName); } - } + } // exit lock + // We now leave the lock to do the actual parsing. // This is done to allow IParser implementations to invoke methods on the main thread without // risking deadlocks. @@ -451,12 +510,10 @@ namespace ICSharpCode.SharpDevelop.Parser // parse once for each project content that contains the file ParseInformation[] newParseInfo = new ParseInformation[projectContents.Count]; IParsedFile[] newUnits = new IParsedFile[projectContents.Count]; - ParseInformation resultParseInfo = null; - IParsedFile resultUnit = null; for (int i = 0; i < projectContents.Count; i++) { IProjectContent pc = projectContents[i]; try { - newParseInfo[i] = parser.Parse(pc, fileName, fileContent); + newParseInfo[i] = parser.Parse(pc, fileName, fileContent, fullParseInformationRequested); } catch (Exception ex) { throw new ApplicationException("Error parsing " + fileName, ex); } @@ -469,18 +526,34 @@ namespace ICSharpCode.SharpDevelop.Parser } } lock (this) { - if (this.disposed) - return null; + if (this.disposed) { + resultParseInfo = null; + resultUnit = null; + return; + } // ensure we never go backwards in time (we need to repeat this check after we've reacquired the lock) if (fileContentVersion != null && this.bufferVersion != null && this.bufferVersion.BelongsToSameDocumentAs(fileContentVersion)) { if (this.bufferVersion.CompareAge(fileContentVersion) >= 0) { - if (parentProjectContent != null) { - IParsedFile oldUnit = oldUnits.FirstOrDefault(o => o.ProjectContent == parentProjectContent); - if (oldUnit != null) - return oldUnit; + if (fullParseInformationRequested && this.cachedParseInformation == null) { + // We must not go backwards in time, but the newer version that we have parsed + // does not have full parse information. + // Thus, we return the parse information that we found above, + // but we won't register it. + return; + } else { + resultParseInfo = this.cachedParseInformation; + resultUnit = this.mainParsedFile; + if (parentProjectContent != null) { + foreach (var oldUnit in this.oldUnits) { + if (oldUnit.ProjectContent == parentProjectContent) { + resultUnit = oldUnit; + break; + } + } + } + return; } - return this.mainParsedFile; } } @@ -505,8 +578,13 @@ namespace ICSharpCode.SharpDevelop.Parser this.bufferVersion = fileContentVersion; this.oldUnits = newUnits; this.mainParsedFile = resultUnit; - return resultUnit; - } + // Cached the new parse information around if it was requested, or if we had already cached parse information previously. + if (resultParseInfo.IsFullParseInformation && (fullParseInformationRequested || this.cachedParseInformation != null)) { + this.cachedParseInformation = resultParseInfo; + } else { + this.cachedParseInformation = null; + } + } // exit lock } public void Clear() @@ -530,13 +608,67 @@ namespace ICSharpCode.SharpDevelop.Parser } } - public Task BeginParse(ITextSource fileContent) + void SnapshotFileContentForAsyncOperation(ref ITextSource fileContent, out 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 (WorkbenchSingleton.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 = GetParseableFileContentForOpenFile(fileName); + } + } + + public Task ParseAsync(ITextSource fileContent) + { + bool lookupOpenFileOnTargetThread; + SnapshotFileContentForAsyncOperation(ref fileContent, out lookupOpenFileOnTargetThread); + // TODO: don't use background task if fileContent was specified and up-to-date parse info is available return System.Threading.Tasks.Task.Factory.StartNew( delegate { try { - return ParseFile(null, fileContent); + if (lookupOpenFileOnTargetThread) { + fileContent = WorkbenchSingleton.SafeThreadFunction(GetParseableFileContentForOpenFile, fileName); + } + ParseInformation parseInfo; + IParsedFile parsedFile; + DoParse(null, fileContent, true, out parseInfo, out parsedFile); + return parseInfo; + } catch (Exception ex) { + MessageService.ShowException(ex, "Error during async parse"); + return null; + } + } + ); + } + + public Task ParseFileAsync(IProjectContent parentProjectContent, ITextSource fileContent) + { + bool lookupOpenFileOnTargetThread; + SnapshotFileContentForAsyncOperation(ref fileContent, out lookupOpenFileOnTargetThread); + + // TODO: don't use background task if fileContent was specified and up-to-date parse info is available + return System.Threading.Tasks.Task.Factory.StartNew( + delegate { + try { + if (lookupOpenFileOnTargetThread) { + fileContent = WorkbenchSingleton.SafeThreadFunction(GetParseableFileContentForOpenFile, fileName); + } + ParseInformation parseInfo; + IParsedFile parsedFile; + DoParse(parentProjectContent, fileContent, false, out parseInfo, out parsedFile); + return parsedFile; } catch (Exception ex) { MessageService.ShowException(ex, "Error during async parse"); return null; @@ -593,7 +725,7 @@ namespace ICSharpCode.SharpDevelop.Parser { if (string.IsNullOrEmpty(fileName)) return null; - return ParseFile(FileName.Create(fileName)); + return Parse(FileName.Create(fileName)); } /// @@ -618,7 +750,7 @@ namespace ICSharpCode.SharpDevelop.Parser return null; FileEntry entry = GetFileEntry(fileName, false); if (entry != null) - return entry.GetCachedParseInformation(null); + return entry.GetCachedParseInformation(); else return null; } @@ -686,7 +818,7 @@ namespace ICSharpCode.SharpDevelop.Parser /// public static ParseInformation Parse(FileName fileName, ITextSource fileContent = null) { - return GetFileEntry(fileName, true).Parse(null, fileContent); + return GetFileEntry(fileName, true).Parse(fileContent); } /// @@ -703,20 +835,38 @@ namespace ICSharpCode.SharpDevelop.Parser /// /// /// This method is thread-safe. This parser being used may involve locking or waiting for the main thread, - /// so using this method while holding a lock can lead to deadlocks. + /// so waiting for the task can cause deadlocks. /// public static Task ParseAsync(FileName fileName, ITextSource fileContent = null) { - if (fileContent == null) - throw new ArgumentNullException("fileContent"); - // create snapshot (in case someone passes a mutable document to BeginParse) - return GetFileEntry(fileName, true).BeginParse(fileContent.CreateSnapshot()); + return GetFileEntry(fileName, true).ParseAsync(fileContent); } + /// + /// Parses the specified file. + /// This method does not request full parse information + /// + /// Name of the file to parse + /// Optional: Content of the file to parse. + /// The fileContent is taken as a hint - if a newer version than it is already available, that will be used instead. + /// + /// + /// 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 necessary reparse, but may return + /// the existing IParsedFile (but only if it's still up-to-date). + /// + /// + /// This method is thread-safe. This parser being used may involve locking or waiting for the main thread, + /// so using this method while holding a lock can lead to deadlocks. + /// + public static IParsedFile ParseFile(FileName fileName, ITextSource fileContent = null) + { + return GetFileEntry(fileName, true).ParseFile(null, fileContent); + } /// /// Parses the specified file. - /// This method does not request full parse information + /// This method does not request full parse information /// /// /// Project content to use as a parent project for the parse run. @@ -727,9 +877,9 @@ namespace ICSharpCode.SharpDevelop.Parser /// The fileContent is taken as a hint - if a newer version than it is already available, that will be used instead. /// /// - /// Returns the ParseInformation for the specified file, or null if the file cannot be parsed. + /// 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 necessary reparse, but may return - /// an existing cached parse information (but only if it's still up-to-date). + /// the existing IParsedFile (but only if it's still up-to-date). /// /// /// This method is thread-safe. This parser being used may involve locking or waiting for the main thread, @@ -737,7 +887,23 @@ namespace ICSharpCode.SharpDevelop.Parser /// public static IParsedFile ParseFile(IProjectContent parentProjectContent, FileName fileName, ITextSource fileContent = null) { - return GetFileEntry(fileName, true).Parse(parentProjectContent, fileContent); + return GetFileEntry(fileName, true).ParseFile(parentProjectContent, fileContent); + } + + /// + /// Async version of ParseFile(). + /// + public static Task ParseFileAsync(FileName fileName, ITextSource fileContent = null) + { + return GetFileEntry(fileName, true).ParseFileAsync(null, fileContent); + } + + /// + /// Async version of ParseFile(). + /// + public static Task ParseFileAsync(IProjectContent parentProjectContent, FileName fileName, ITextSource fileContent = null) + { + return GetFileEntry(fileName, true).ParseFileAsync(parentProjectContent, fileContent); } /// @@ -767,9 +933,9 @@ namespace ICSharpCode.SharpDevelop.Parser return null; IEditable editable = viewContent as IEditable; if (editable != null) - return ParseFile(viewContent.PrimaryFileName, editable.CreateSnapshot()); + return Parse(viewContent.PrimaryFileName, editable.CreateSnapshot()); else - return ParseFile(viewContent.PrimaryFileName); + return Parse(viewContent.PrimaryFileName); } /// @@ -777,7 +943,7 @@ namespace ICSharpCode.SharpDevelop.Parser /// Will create a new IParser instance on demand. /// This method is thread-safe. /// - public static IParser GetParser(string fileName) + public static IParser GetParser(FileName fileName) { return GetFileEntry(fileName, true).parser; } @@ -788,7 +954,7 @@ namespace ICSharpCode.SharpDevelop.Parser /// public static void RegisterParseInformation(string fileName, IParsedFile cu) { - FileEntry entry = GetFileEntry(fileName, true); + FileEntry entry = GetFileEntry(FileName.Create(fileName), true); entry.RegisterParseInformation(cu); } diff --git a/src/Main/Core/Project/Src/Services/FileUtility/FileName.cs b/src/Main/Core/Project/Src/Services/FileUtility/FileName.cs index 0c68818a5e..aafac8823d 100644 --- a/src/Main/Core/Project/Src/Services/FileUtility/FileName.cs +++ b/src/Main/Core/Project/Src/Services/FileUtility/FileName.cs @@ -22,6 +22,12 @@ namespace ICSharpCode.Core this.normalizedFileName = FileUtility.NormalizePath(fileName); } + [Obsolete("The input already is a FileName")] + public FileName(FileName fileName) + { + this.normalizedFileName = fileName.normalizedFileName; + } + /// /// Creates a FileName instance from the string. /// It is valid to pass null or an empty string to this method (in that case, a null reference will be returned). @@ -34,6 +40,12 @@ namespace ICSharpCode.Core return new FileName(fileName); } + [Obsolete("The input already is a FileName")] + public static FileName Create(FileName fileName) + { + return fileName; + } + public static implicit operator string(FileName fileName) { if (fileName != null)