Browse Source

newNR: fixed build errors in AvalonEdit.AddIn and CSharpBinding.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
f31bca1de7
  1. 2
      src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj
  2. 2
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpBracketSearcher.cs
  3. 10
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs
  4. 9
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs
  5. 264
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/EventHandlerCompletionItemProvider.cs
  6. 88
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingStrategy.cs
  7. 7
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/DocumentAccessor.cs
  8. 57
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/Parser.cs
  9. 10
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/CSharpMyNamespaceBuilder.cs
  10. 6
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/CSharpProject.cs
  11. 57
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/RemoveMembersInRangeVisitor.cs
  12. 2
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/VBNetToCSharpConvertVisitorWithMyFormsSupport.cs
  13. 5
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/VBNetToCSharpConverter.cs
  14. 2
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs
  15. 10
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs
  16. 4
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Commands/SortSelectionCommand.cs
  17. 6
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/MyersDiff/DocumentSequence.cs
  18. 4
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ParserFoldingStrategy.cs
  19. 2
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.cs
  20. 4
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/SharpDevelopTextEditor.cs
  21. 5
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/CodeSnippet.cs
  22. 10
      src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstLocation.cs
  23. 4
      src/Libraries/NRefactory/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj
  24. 2
      src/Main/Base/Project/Src/Gui/Dialogs/NewFileDialog.cs
  25. 4
      src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/Commands/ReferenceFolderNodeCommands.cs
  26. 2
      src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskListPad.cs
  27. 2
      src/Main/Base/Project/Src/Project/CustomTool.cs
  28. 37
      src/Main/Base/Project/Src/Services/AmbienceService/CSharpAmbience.cs
  29. 83
      src/Main/Base/Project/Src/Services/AmbienceService/IAmbience.cs
  30. 3
      src/Main/Base/Project/Src/Services/ParserService/IParser.cs
  31. 8
      src/Main/Base/Project/Src/Services/ParserService/ParseInformationEventArgs.cs
  32. 272
      src/Main/Base/Project/Src/Services/ParserService/ParserService.cs
  33. 12
      src/Main/Core/Project/Src/Services/FileUtility/FileName.cs

2
src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj

@ -62,14 +62,12 @@
<Compile Include="Src\CSharpBracketSearcher.cs" /> <Compile Include="Src\CSharpBracketSearcher.cs" />
<Compile Include="Src\CSharpLanguageBinding.cs" /> <Compile Include="Src\CSharpLanguageBinding.cs" />
<Compile Include="Src\CSharpProjectBinding.cs" /> <Compile Include="Src\CSharpProjectBinding.cs" />
<Compile Include="Src\EventHandlerCompletionItemProvider.cs" />
<Compile Include="Src\FormattingStrategy\CSharpFormattingStrategy.cs" /> <Compile Include="Src\FormattingStrategy\CSharpFormattingStrategy.cs" />
<Compile Include="Src\FormattingStrategy\DocumentAccessor.cs" /> <Compile Include="Src\FormattingStrategy\DocumentAccessor.cs" />
<Compile Include="Src\OptionPanels\BuildOptions.cs"> <Compile Include="Src\OptionPanels\BuildOptions.cs">
<SubType>Form</SubType> <SubType>Form</SubType>
</Compile> </Compile>
<Compile Include="Src\Parser\Parser.cs" /> <Compile Include="Src\Parser\Parser.cs" />
<Compile Include="Src\Project\RemoveMembersInRangeVisitor.cs" />
<Compile Include="Src\Project\VBNetToCSharpConvertVisitorWithMyFormsSupport.cs" /> <Compile Include="Src\Project\VBNetToCSharpConvertVisitorWithMyFormsSupport.cs" />
<Compile Include="Src\Project\CSharpMyNamespaceBuilder.cs" /> <Compile Include="Src\Project\CSharpMyNamespaceBuilder.cs" />
<Compile Include="Src\Project\CSharpProject.cs" /> <Compile Include="Src\Project\CSharpProject.cs" />

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

@ -5,7 +5,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using ICSharpCode.Editor;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
namespace CSharpBinding namespace CSharpBinding

10
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) // 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; using System;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.NRefactory; using ICSharpCode.NRefactory;
@ -33,13 +34,7 @@ namespace CSharpBinding
int cursor = editor.Caret.Offset; int cursor = editor.Caret.Offset;
if (ch == '[') { if (ch == '[') {
var line = editor.Document.GetLineForOffset(cursor); 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) { } else if (ch == ',' && CodeCompletionOptions.InsightRefreshOnComma && CodeCompletionOptions.InsightEnabled) {
IInsightWindow insightWindow; IInsightWindow insightWindow;
if (insightHandler.InsightRefreshOnComma(editor, ch, out insightWindow)) { if (insightHandler.InsightRefreshOnComma(editor, ch, out insightWindow)) {
@ -316,3 +311,4 @@ namespace CSharpBinding
#endregion #endregion
} }
} }
*/

9
src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs

@ -4,7 +4,6 @@
using System; using System;
using CSharpBinding.FormattingStrategy; using CSharpBinding.FormattingStrategy;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
namespace CSharpBinding namespace CSharpBinding
@ -18,10 +17,10 @@ namespace CSharpBinding
get { return new CSharpFormattingStrategy(); } get { return new CSharpFormattingStrategy(); }
} }
public override LanguageProperties Properties { // public override LanguageProperties Properties {
get { return LanguageProperties.CSharp; } // get { return LanguageProperties.CSharp; }
} // }
//
public override IBracketSearcher BracketSearcher { public override IBracketSearcher BracketSearcher {
get { return new CSharpBracketSearcher(); } get { return new CSharpBracketSearcher(); }
} }

264
src/AddIns/BackendBindings/CSharpBinding/Project/Src/EventHandlerCompletionItemProvider.cs

@ -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();
}
}
}
}

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

@ -5,11 +5,13 @@ using System;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using ICSharpCode.AvalonEdit.Indentation.CSharp; using ICSharpCode.AvalonEdit.Indentation.CSharp;
using ICSharpCode.SharpDevelop; using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.Editor;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Parser;
namespace CSharpBinding.FormattingStrategy namespace CSharpBinding.FormattingStrategy
{ {
@ -174,56 +176,35 @@ namespace CSharpBinding.FormattingStrategy
/// <summary> /// <summary>
/// Gets the next member after the specified caret position. /// Gets the next member after the specified caret position.
/// </summary> /// </summary>
object GetMemberAfter(ITextEditor editor, int caretLine) IEntity GetMemberAfter(ITextEditor editor, int caretLine)
{ {
string fileName = editor.FileName; FileName fileName = editor.FileName;
object nextElement = null; IEntity nextElement = null;
if (fileName != null && fileName.Length > 0 ) { if (fileName != null) {
ParseInformation parseInfo = ParserService.ParseFile(fileName, editor.Document.CreateSnapshot()); IParsedFile parsedFile = ParserService.ParseFile(fileName, editor.Document.CreateSnapshot());
if (parseInfo != null) { if (parsedFile != null) {
ICompilationUnit currentCompilationUnit = parseInfo.CompilationUnit; ITypeDefinition currentClass = parsedFile.GetInnerMostTypeDefinition(new TextLocation(caretLine, 0));
if (currentCompilationUnit != null) {
IClass currentClass = currentCompilationUnit.GetInnermostClass(caretLine, 0);
int nextElementLine = int.MaxValue; int nextElementLine = int.MaxValue;
if (currentClass == null) { if (currentClass == null) {
foreach (IClass c in currentCompilationUnit.Classes) { foreach (ITypeDefinition c in parsedFile.TopLevelTypeDefinitions) {
if (c.Region.BeginLine < nextElementLine && c.Region.BeginLine > caretLine) { if (c.Region.BeginLine < nextElementLine && c.Region.BeginLine > caretLine) {
nextElementLine = c.Region.BeginLine; nextElementLine = c.Region.BeginLine;
nextElement = c; nextElement = c;
} }
} }
} else { } else {
foreach (IClass c in currentClass.InnerClasses) { foreach (ITypeDefinition c in currentClass.NestedTypes) {
if (c.Region.BeginLine < nextElementLine && c.Region.BeginLine > caretLine) { if (c.Region.BeginLine < nextElementLine && c.Region.BeginLine > caretLine) {
nextElementLine = c.Region.BeginLine; nextElementLine = c.Region.BeginLine;
nextElement = c; nextElement = c;
} }
} }
foreach (IMember m in currentClass.Methods) { foreach (IMember m in currentClass.Members) {
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;
}
}
foreach (IMember m in currentClass.Fields) {
if (m.Region.BeginLine < nextElementLine && m.Region.BeginLine > caretLine) { if (m.Region.BeginLine < nextElementLine && m.Region.BeginLine > caretLine) {
nextElementLine = m.Region.BeginLine; nextElementLine = m.Region.BeginLine;
nextElement = m; nextElement = m;
} }
} }
foreach (IMember m in currentClass.Events) {
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 regions = 0;
int endregions = 0; int endregions = 0;
for (int i = 1; i <= document.TotalNumberOfLines; i++) { for (int i = 1; i <= document.LineCount; i++) {
string text = document.GetLine(i).Text.Trim(); string text = document.GetText(document.GetLineByNumber(i)).Trim();
if (text.StartsWith("#region")) { if (text.StartsWith("#region", StringComparison.Ordinal)) {
++regions; ++regions;
} else if (text.StartsWith("#endregion")) { } else if (text.StartsWith("#endregion", StringComparison.Ordinal)) {
++endregions; ++endregions;
} }
} }
@ -257,18 +238,18 @@ namespace CSharpBinding.FormattingStrategy
void FormatLineInternal(ITextEditor textArea, int lineNr, int cursorOffset, char ch) void FormatLineInternal(ITextEditor textArea, int lineNr, int cursorOffset, char ch)
{ {
IDocumentLine curLine = textArea.Document.GetLine(lineNr); IDocumentLine curLine = textArea.Document.GetLineByNumber(lineNr);
IDocumentLine lineAbove = lineNr > 1 ? textArea.Document.GetLine(lineNr - 1) : null; IDocumentLine lineAbove = lineNr > 1 ? textArea.Document.GetLineByNumber(lineNr - 1) : null;
string terminator = DocumentUtilitites.GetLineTerminator(textArea.Document, lineNr); string terminator = DocumentUtilitites.GetLineTerminator(textArea.Document, lineNr);
string curLineText; string curLineText;
//// local string for curLine segment //// local string for curLine segment
if (ch == '/') { if (ch == '/') {
curLineText = curLine.Text; curLineText = textArea.Document.GetText(curLine);
string lineAboveText = lineAbove == null ? "" : lineAbove.Text; string lineAboveText = lineAbove == null ? "" : textArea.Document.GetText(lineAbove);
if (curLineText != null && curLineText.EndsWith("///") && (lineAboveText == null || !lineAboveText.Trim().StartsWith("///"))) { if (curLineText != null && curLineText.EndsWith("///") && (lineAboveText == null || !lineAboveText.Trim().StartsWith("///"))) {
string indentation = DocumentUtilitites.GetWhitespaceAfter(textArea.Document, curLine.Offset); string indentation = DocumentUtilitites.GetWhitespaceAfter(textArea.Document, curLine.Offset);
object member = GetMemberAfter(textArea, lineNr); IEntity member = GetMemberAfter(textArea, lineNr);
if (member != null) { if (member != null) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.Append(" <summary>"); sb.Append(" <summary>");
@ -290,12 +271,15 @@ namespace CSharpBinding.FormattingStrategy
sb.Append("\"></param>"); sb.Append("\"></param>");
} }
} }
if (method.ReturnType != null && !method.IsConstructor && method.ReturnType.FullyQualifiedName != "System.Void") { if (!method.IsConstructor) {
IType returnType = method.ReturnType.Resolve(ParserService.CurrentTypeResolveContext);
if (returnType.Kind != TypeKind.Void) {
sb.Append(terminator); sb.Append(terminator);
sb.Append(indentation); sb.Append(indentation);
sb.Append("/// <returns></returns>"); sb.Append("/// <returns></returns>");
} }
} }
}
textArea.Document.Insert(cursorOffset, sb.ToString()); textArea.Document.Insert(cursorOffset, sb.ToString());
textArea.Caret.Offset = cursorOffset + indentation.Length + "/// ".Length + " <summary>".Length + terminator.Length; textArea.Caret.Offset = cursorOffset + indentation.Length + "/// ".Length + " <summary>".Length + terminator.Length;
@ -312,7 +296,7 @@ namespace CSharpBinding.FormattingStrategy
switch (ch) { switch (ch) {
case '>': case '>':
if (IsInsideDocumentationComment(textArea, curLine, cursorOffset)) { if (IsInsideDocumentationComment(textArea, curLine, cursorOffset)) {
curLineText = curLine.Text; curLineText = textArea.Document.GetText(curLine);
int column = cursorOffset - curLine.Offset; int column = cursorOffset - curLine.Offset;
int index = Math.Min(column - 1, curLineText.Length - 1); int index = Math.Min(column - 1, curLineText.Length - 1);
@ -347,11 +331,11 @@ namespace CSharpBinding.FormattingStrategy
//} //}
break; break;
case '\n': 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 //// 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)) && NeedEndregion(textArea.Document))
{ {
textArea.Document.Insert(cursorOffset, "#endregion"); textArea.Document.Insert(cursorOffset, "#endregion");
@ -382,8 +366,8 @@ namespace CSharpBinding.FormattingStrategy
} }
if (lineAbove != null && isInNormalCode) { if (lineAbove != null && isInNormalCode) {
IDocumentLine nextLine = lineNr + 1 <= textArea.Document.TotalNumberOfLines ? textArea.Document.GetLine(lineNr + 1) : null; IDocumentLine nextLine = lineNr + 1 <= textArea.Document.LineCount ? textArea.Document.GetLineByNumber(lineNr + 1) : null;
string nextLineText = (nextLine != null) ? nextLine.Text : ""; string nextLineText = (nextLine != null) ? textArea.Document.GetText(nextLine) : "";
int indexAbove = lineAboveText.IndexOf("///"); int indexAbove = lineAboveText.IndexOf("///");
int indexNext = nextLineText.IndexOf("///"); int indexNext = nextLineText.IndexOf("///");
@ -399,12 +383,12 @@ namespace CSharpBinding.FormattingStrategy
} }
} }
if (textArea.Options.AutoInsertBlockEnd && lineAbove != null && isInNormalCode) { if (textArea.Options.AutoInsertBlockEnd && lineAbove != null && isInNormalCode) {
string oldLineText = lineAbove.Text; string oldLineText = textArea.Document.GetText(lineAbove);
if (oldLineText.EndsWith("{")) { if (oldLineText.EndsWith("{")) {
if (NeedCurlyBracket(textArea.Document.Text)) { if (NeedCurlyBracket(textArea.Document.Text)) {
int insertionPoint = curLine.Offset + curLine.Length; int insertionPoint = curLine.Offset + curLine.Length;
textArea.Document.Insert(insertionPoint, terminator + "}"); textArea.Document.Insert(insertionPoint, terminator + "}");
IndentLine(textArea, textArea.Document.GetLine(lineNr + 1)); IndentLine(textArea, textArea.Document.GetLineByNumber(lineNr + 1));
textArea.Caret.Offset = insertionPoint; textArea.Caret.Offset = insertionPoint;
} }
} }

7
src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/DocumentAccessor.cs

@ -3,6 +3,7 @@
using System; using System;
using ICSharpCode.AvalonEdit.Indentation.CSharp; using ICSharpCode.AvalonEdit.Indentation.CSharp;
using ICSharpCode.Editor;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
namespace CSharpBinding.FormattingStrategy namespace CSharpBinding.FormattingStrategy
@ -25,7 +26,7 @@ namespace CSharpBinding.FormattingStrategy
throw new ArgumentNullException("document"); throw new ArgumentNullException("document");
doc = document; doc = document;
this.minLine = 1; this.minLine = 1;
this.maxLine = doc.TotalNumberOfLines; this.maxLine = doc.LineCount;
} }
/// <summary> /// <summary>
@ -79,8 +80,8 @@ namespace CSharpBinding.FormattingStrategy
} }
++num; ++num;
if (num > maxLine) return false; if (num > maxLine) return false;
line = doc.GetLine(num); line = doc.GetLineByNumber(num);
text = line.Text; text = doc.GetText(line);
return true; return true;
} }
} }

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

@ -3,10 +3,11 @@
using System; using System;
using System.IO; using System.IO;
using ICSharpCode.Core;
using ICSharpCode.Editor;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.SharpDevelop.Dom.CSharp;
using ICSharpCode.SharpDevelop.Dom.NRefactoryResolver;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
namespace CSharpBinding.Parser 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) public bool CanParse(string fileName)
{ {
return Path.GetExtension(fileName).Equals(".CS", StringComparison.OrdinalIgnoreCase); 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) void RetrieveRegions(ICompilationUnit cu, ICSharpCode.NRefactory.Parser.SpecialTracker tracker)
{ {
for (int i = 0; i < tracker.CurrentSpecials.Count; ++i) { 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) public ParseInformation Parse(IProjectContent projectContent, FileName fileName, ITextSource fileContent,
bool fullParseInformationRequested)
{ {
using (ICSharpCode.NRefactory.IParser p = ICSharpCode.NRefactory.ParserFactory.CreateParser(ICSharpCode.NRefactory.SupportedLanguage.CSharp, fileContent.CreateReader())) { throw new NotImplementedException();
return Parse(p, fileName, projectContent);
}
} }
ICompilationUnit Parse(ICSharpCode.NRefactory.IParser p, string fileName, IProjectContent projectContent) /*void AddCommentTags(ICompilationUnit cu, System.Collections.Generic.List<ICSharpCode.NRefactory.Parser.TagComment> tagComments)
{
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;
}
void AddCommentTags(ICompilationUnit cu, System.Collections.Generic.List<ICSharpCode.NRefactory.Parser.TagComment> tagComments)
{ {
foreach (ICSharpCode.NRefactory.Parser.TagComment tagComment in tagComments) { foreach (ICSharpCode.NRefactory.Parser.TagComment tagComment in tagComments) {
DomRegion tagRegion = new DomRegion(tagComment.StartPosition.Y, tagComment.StartPosition.X); DomRegion tagRegion = new DomRegion(tagComment.StartPosition.Y, tagComment.StartPosition.X);
@ -107,11 +77,6 @@ namespace CSharpBinding.Parser
cu.TagComments.Add(tag); cu.TagComments.Add(tag);
} }
} }
*/
public IResolver CreateResolver()
{
return new NRefactoryResolver(LanguageProperties.CSharp);
}
///////// IParser Interface END
} }
} }

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

@ -6,8 +6,8 @@ using System.Collections.Generic;
using ICSharpCode.Core; using ICSharpCode.Core;
using System.IO; using System.IO;
using System.Text; using System.Text;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
namespace CSharpBinding namespace CSharpBinding
@ -23,10 +23,10 @@ namespace CSharpBinding
return typeof(CSharpMyNamespaceBuilder).Assembly.GetManifestResourceStream("Resources.MyNamespaceSupportForCSharp.cs"); 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) { if (pc != null) {
return pc.GetClass(myNamespace + ".MyForms", 0); return pc.GetTypeDefinition(myNamespace, "MyForms", 0, StringComparer.Ordinal);
} }
return null; return null;
} }
@ -62,11 +62,11 @@ namespace CSharpBinding
continue; continue;
} }
if (trimmedLine == "/*LIST OF FORMS*/") { if (trimmedLine == "/*LIST OF FORMS*/") {
IClass myFormsClass = FindMyFormsClass(ParserService.GetProjectContent(vbProject), ns); ITypeDefinition myFormsClass = FindMyFormsClass(vbProject.ProjectContent, 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);
foreach (IProperty p in myFormsClass.Properties) { 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 + typeName + " " + p.Name + "_instance;");
output.AppendLine(indentation + "bool " + p.Name + "_isCreating;"); output.AppendLine(indentation + "bool " + p.Name + "_isCreating;");
output.AppendLine(indentation + "public " + typeName + " " + p.Name + " {"); output.AppendLine(indentation + "public " + typeName + " " + p.Name + " {");

6
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/CSharpProject.cs

@ -8,8 +8,6 @@ using System.IO;
using System.Linq; using System.Linq;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Dom.CSharp;
using ICSharpCode.SharpDevelop.Internal.Templates; using ICSharpCode.SharpDevelop.Internal.Templates;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Project.Converter; using ICSharpCode.SharpDevelop.Project.Converter;
@ -30,10 +28,6 @@ namespace CSharpBinding
get { return CSharpProjectBinding.LanguageName; } get { return CSharpProjectBinding.LanguageName; }
} }
public override LanguageProperties LanguageProperties {
get { return LanguageProperties.CSharp; }
}
void Init() void Init()
{ {
reparseReferencesSensitiveProperties.Add("TargetFrameworkVersion"); reparseReferencesSensitiveProperties.Add("TargetFrameworkVersion");

57
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/RemoveMembersInRangeVisitor.cs

@ -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
{
/// <summary>
/// Removes members that are in the specified range.
/// </summary>
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);
}
}
}

2
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) // 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; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@ -67,3 +68,4 @@ namespace CSharpBinding
} }
} }
} }
*/

5
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) // 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; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@ -104,7 +104,7 @@ namespace CSharpBinding
} else { } else {
// remove ifdef including the code // remove ifdef including the code
compilationUnit.AcceptVisitor(new RemoveMembersInRangeVisitor( 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); specials.RemoveRange(i, j - i + 1);
} }
i--; i--;
@ -119,3 +119,4 @@ namespace CSharpBinding
} }
} }
} }
*/

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

@ -518,7 +518,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
void FetchParseInformation() void FetchParseInformation()
{ {
ParseInformation parseInfo = ParserService.GetExistingParsedFile(this.FileName); ParseInformation parseInfo = 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); ParserService.ParseAsync(this.FileName, primaryTextEditorAdapter.Document);

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

@ -77,7 +77,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
hiddenDefinitionRenderer.Dispose(); hiddenDefinitionRenderer.Dispose();
} }
protected override string FileName { protected override ICSharpCode.Core.FileName FileName {
get { return this.Adapter.FileName; } get { return this.Adapter.FileName; }
} }
@ -456,7 +456,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
#region UpdateParseInformation - Folding #region UpdateParseInformation - Folding
void UpdateParseInformationForFolding() void UpdateParseInformationForFolding()
{ {
UpdateParseInformationForFolding(ParserService.GetExistingParsedFile(this.Adapter.FileName)); UpdateParseInformationForFolding(null);
} }
bool disableParseInformationFolding; bool disableParseInformationFolding;
@ -473,8 +473,12 @@ namespace ICSharpCode.AvalonEdit.AddIn
public void UpdateParseInformationForFolding(ParseInformation parseInfo) public void UpdateParseInformationForFolding(ParseInformation parseInfo)
{ {
if (!CodeEditorOptions.Instance.EnableFolding || disableParseInformationFolding) if (!CodeEditorOptions.Instance.EnableFolding || disableParseInformationFolding) {
parseInfo = null; parseInfo = null;
} else {
if (parseInfo == null || !parseInfo.IsFullParseInformation)
parseInfo = ParserService.Parse(this.FileName, this.Document);
}
IServiceContainer container = this.Adapter.GetService(typeof(IServiceContainer)) as IServiceContainer; IServiceContainer container = this.Adapter.GetService(typeof(IServiceContainer)) as IServiceContainer;
ParserFoldingStrategy folding = container.GetService(typeof(ParserFoldingStrategy)) as ParserFoldingStrategy; ParserFoldingStrategy folding = container.GetService(typeof(ParserFoldingStrategy)) as ParserFoldingStrategy;

4
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Commands/SortSelectionCommand.cs

@ -54,13 +54,13 @@ namespace ICSharpCode.AvalonEdit.AddIn.Commands
using (document.OpenUndoGroup()) { using (document.OpenUndoGroup()) {
for (int i = 0; i < lines.Count; ++i) { 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]); document.Replace(line.Offset, line.Length, lines[i]);
} }
// remove removed duplicate lines // remove removed duplicate lines
for (int i = startLine + lines.Count; i <= endLine; ++i) { 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); document.Remove(line.Offset, line.TotalLength);
} }
} }

6
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/MyersDiff/DocumentSequence.cs

@ -14,12 +14,12 @@ namespace ICSharpCode.AvalonEdit.AddIn.MyersDiff
public DocumentSequence(IDocument document, Dictionary<string, int> hashDict) public DocumentSequence(IDocument document, Dictionary<string, int> 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' // 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. // (really just a unique identifier for each line content) in our array.
for (int i = 1; i <= document.TotalNumberOfLines; i++) { for (int i = 1; i <= document.LineCount; i++) {
string text = document.GetLine(i).Text; string text = document.GetText(document.GetLineByNumber(i));
int hash; int hash;
if (!hashDict.TryGetValue(text, out hash)) { if (!hashDict.TryGetValue(text, out hash)) {
hash = hashDict.Count; hash = hashDict.Count;

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

@ -55,13 +55,15 @@ namespace ICSharpCode.AvalonEdit.AddIn
foreach (ITypeDefinition c in parseInfo.ParsedFile.TopLevelTypeDefinitions) { foreach (ITypeDefinition c in parseInfo.ParsedFile.TopLevelTypeDefinitions) {
AddClassMembers(c, newFoldMarkers); AddClassMembers(c, newFoldMarkers);
} }
#warning Additional folding regions
/*
foreach (FoldingRegion foldingRegion in parseInfo.FoldingRegions) { foreach (FoldingRegion foldingRegion in parseInfo.FoldingRegions) {
NewFolding f = new NewFoldingDefinition(GetOffset(foldingRegion.Region.BeginLine, foldingRegion.Region.BeginColumn), NewFolding f = new NewFoldingDefinition(GetOffset(foldingRegion.Region.BeginLine, foldingRegion.Region.BeginColumn),
GetOffset(foldingRegion.Region.EndLine, foldingRegion.Region.EndColumn)); GetOffset(foldingRegion.Region.EndLine, foldingRegion.Region.EndColumn));
f.DefaultClosed = isFirstUpdate; f.DefaultClosed = isFirstUpdate;
f.Name = foldingRegion.Name; f.Name = foldingRegion.Name;
newFoldMarkers.Add(f); newFoldMarkers.Add(f);
} }*/
} }
return newFoldMarkers.OrderBy(f => f.StartOffset); return newFoldMarkers.OrderBy(f => f.StartOffset);
} }

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

@ -51,7 +51,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList | ConversionFlags.UseFullyQualifiedMemberNames; ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList | ConversionFlags.UseFullyQualifiedMemberNames;
else else
ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList | ConversionFlags.ShowParameterList | ConversionFlags.ShowParameterNames; ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList | ConversionFlags.ShowParameterList | ConversionFlags.ShowParameterNames;
text = ambience.Convert(entity); text = ambience.ConvertEntity(entity);
image = ClassBrowserIconService.GetIcon(entity); image = ClassBrowserIconService.GetIcon(entity);
} }

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

@ -56,8 +56,8 @@ namespace ICSharpCode.AvalonEdit.AddIn
options.BindToTextEditor(this); options.BindToTextEditor(this);
} }
protected virtual string FileName { protected virtual ICSharpCode.Core.FileName FileName {
get { return "untitled"; } get { return ICSharpCode.Core.FileName.Create("untitled"); }
} }
SharpDevelopCompletionWindow completionWindow; SharpDevelopCompletionWindow completionWindow;

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

@ -196,7 +196,7 @@ namespace ICSharpCode.AvalonEdit.AddIn.Snippets
{ {
var parseInfo = ParserService.GetExistingParsedFile(editor.FileName); var parseInfo = ParserService.GetExistingParsedFile(editor.FileName);
if (parseInfo != null) { if (parseInfo != null) {
return parseInfo.GetInnermostClass(editor.Caret.Line, editor.Caret.Column); return parseInfo.GetInnerMostTypeDefinition(editor.Caret.Location);
} }
return null; return null;
} }
@ -207,12 +207,15 @@ namespace ICSharpCode.AvalonEdit.AddIn.Snippets
return s => s.ToLower(); return s => s.ToLower();
if ("toUpper".Equals(name, StringComparison.OrdinalIgnoreCase)) if ("toUpper".Equals(name, StringComparison.OrdinalIgnoreCase))
return s => s.ToUpper(); return s => s.ToUpper();
#warning Reimplement language-specific name conversion functions
/*
if ("toFieldName".Equals(name, StringComparison.OrdinalIgnoreCase)) if ("toFieldName".Equals(name, StringComparison.OrdinalIgnoreCase))
return s => context.Language.Properties.CodeGenerator.GetFieldName(s); return s => context.Language.Properties.CodeGenerator.GetFieldName(s);
if ("toPropertyName".Equals(name, StringComparison.OrdinalIgnoreCase)) if ("toPropertyName".Equals(name, StringComparison.OrdinalIgnoreCase))
return s => context.Language.Properties.CodeGenerator.GetPropertyName(s); return s => context.Language.Properties.CodeGenerator.GetPropertyName(s);
if ("toParameterName".Equals(name, StringComparison.OrdinalIgnoreCase)) if ("toParameterName".Equals(name, StringComparison.OrdinalIgnoreCase))
return s => context.Language.Properties.CodeGenerator.GetParameterName(s); return s => context.Language.Properties.CodeGenerator.GetParameterName(s);
*/
return null; return null;
} }

10
src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstLocation.cs

@ -133,5 +133,15 @@ namespace ICSharpCode.NRefactory.CSharp
{ {
return !(left < right); 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);
}
} }
} }

4
src/Libraries/NRefactory/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

@ -421,6 +421,10 @@
<Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project> <Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
<Name>Mono.Cecil</Name> <Name>Mono.Cecil</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\ICSharpCode.Editor\ICSharpCode.Editor.csproj">
<Project>{F054A788-B591-4561-A8BA-AE745BBEB817}</Project>
<Name>ICSharpCode.Editor</Name>
</ProjectReference>
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project> </Project>

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

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

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

@ -64,7 +64,7 @@ namespace ICSharpCode.SharpDevelop.Project.Commands
} }
// Update code completion. // Update code completion.
ParserService.ParseFile(webReference.WebProxyFileName); ParserService.ParseFileAsync(FileName.Create(webReference.WebProxyFileName));
} }
} 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));
@ -121,7 +121,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.ParseFile(refDialog.WebReference.WebProxyFileName); ParserService.ParseFileAsync(FileName.Create(refDialog.WebReference.WebProxyFileName));
node.Project.Save(); node.Project.Save();
} }

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

@ -210,7 +210,7 @@ namespace ICSharpCode.SharpDevelop.Gui
if (WorkbenchSingleton.Workbench.ActiveViewContent == null) if (WorkbenchSingleton.Workbench.ActiveViewContent == null)
return null; return null;
IParsedFile parseInfo = ParserService.GetParseInformation(WorkbenchSingleton.Workbench.ActiveViewContent.PrimaryFileName); IParsedFile parseInfo = 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) {

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(outputFileName, new StringTextSource(codeOutput)); ParserService.ParseAsync(FileName.Create(outputFileName), new StringTextSource(codeOutput));
} }
public void GenerateCodeDomAsync(FileProjectItem baseItem, string outputFileName, Func<CodeCompileUnit> func) public void GenerateCodeDomAsync(FileProjectItem baseItem, string outputFileName, Func<CodeCompileUnit> func)

37
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) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System; using System;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.SharpDevelop namespace ICSharpCode.SharpDevelop
{ {
@ -10,5 +11,41 @@ namespace ICSharpCode.SharpDevelop
/// </summary> /// </summary>
public class CSharpAmbience : IAmbience 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();
}
} }
} }

83
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) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System; using System;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.SharpDevelop namespace ICSharpCode.SharpDevelop
{ {
[Flags]
public enum ConversionFlags
{
/// <summary>
/// Convert only the name.
/// </summary>
None = 0,
/// <summary>
/// Show the parameter list
/// </summary>
ShowParameterList = 1,
/// <summary>
/// Show names for parameters
/// </summary>
ShowParameterNames = 2,
/// <summary>
/// Show the accessibility (private, public, etc.)
/// </summary>
ShowAccessibility = 4,
/// <summary>
/// Show the definition key word (class, struct, Sub, Function, etc.)
/// </summary>
ShowDefinitionKeyWord = 8,
/// <summary>
/// Show the fully qualified name for the member
/// </summary>
UseFullyQualifiedMemberNames = 0x10,
/// <summary>
/// Show modifiers (virtual, override, etc.)
/// </summary>
ShowModifiers = 0x20,
/// <summary>
/// Show the inheritance declaration
/// </summary>
ShowInheritanceList = 0x40,
IncludeHtmlMarkup = 0x80,
/// <summary>
/// Show the return type
/// </summary>
ShowReturnType = 0x100,
/// <summary>
/// Use fully qualified names for return type and parameters.
/// </summary>
UseFullyQualifiedTypeNames = 0x200,
/// <summary>
/// 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.
/// </summary>
IncludeBody = 0x400,
/// <summary>
/// Show the list of type parameters on method and class declarations.
/// Type arguments for parameter/return types are always shown.
/// </summary>
ShowTypeParameterList = 0x800,
StandardConversionFlags = ShowParameterNames |
ShowAccessibility |
ShowParameterList |
ShowReturnType |
ShowModifiers |
ShowTypeParameterList |
ShowDefinitionKeyWord,
All = 0xfff,
}
public interface IAmbience 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);
} }
} }

3
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) // 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 ICSharpCode.Core;
using ICSharpCode.Editor; using ICSharpCode.Editor;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Editor; 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 /// 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. /// if there are two parallel parse requests for the same file. Parser implementations must be thread-safe.
/// </remarks> /// </remarks>
ParseInformation Parse(IProjectContent projectContent, string fileName, ITextSource fileContent, ParseInformation Parse(IProjectContent projectContent, FileName fileName, ITextSource fileContent,
bool fullParseInformationRequested); bool fullParseInformationRequested);
//IResolver CreateResolver(); //IResolver CreateResolver();

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

@ -92,9 +92,9 @@ namespace ICSharpCode.SharpDevelop.Parser
{ {
FileName fileName; FileName fileName;
ITextSource content; 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) if (fileName == null)
throw new ArgumentNullException("fileName"); throw new ArgumentNullException("fileName");
@ -104,7 +104,7 @@ namespace ICSharpCode.SharpDevelop.Parser
throw new ArgumentNullException("parsedFile"); throw new ArgumentNullException("parsedFile");
this.fileName = fileName; this.fileName = fileName;
this.content = content; this.content = content;
this.parsedFile = parsedFile; this.parseInformation = parsedFile;
} }
public FileName FileName { public FileName FileName {
@ -121,7 +121,7 @@ namespace ICSharpCode.SharpDevelop.Parser
public IParsedFile ParsedFile { public IParsedFile ParsedFile {
get { get {
return parsedFile; return parseInformation.ParsedFile;
} }
} }
} }

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

@ -260,8 +260,8 @@ namespace ICSharpCode.SharpDevelop.Parser
snapshot = GetParseableFileContent(viewContent.PrimaryFileName); snapshot = GetParseableFileContent(viewContent.PrimaryFileName);
lastParseRun = ParseAsync(fileName, snapshot).ContinueWith( lastParseRun = ParseAsync(fileName, snapshot).ContinueWith(
delegate(Task<IParsedFile> backgroundTask) { delegate(Task<ParseInformation> backgroundTask) {
IParsedFile parseInfo = backgroundTask.Result; ParseInformation parseInfo = backgroundTask.Result;
RaiseParserUpdateStepFinished(new ParserUpdateStepEventArgs(fileName, snapshot, parseInfo)); 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 /// This method is thread-safe. This method involves waiting for the main thread, so using it while
/// holding a lock can lead to deadlocks. /// holding a lock can lead to deadlocks.
/// </summary> /// </summary>
public static ITextSource GetParseableFileContent(string fileName) public static ITextSource GetParseableFileContent(FileName fileName)
{ {
return Gui.WorkbenchSingleton.SafeThreadFunction(GetParseableFileContentInternal, fileName); ITextSource fileContent = Gui.WorkbenchSingleton.SafeThreadFunction(GetParseableFileContentForOpenFile, fileName);
if (fileContent != null)
return fileContent;
else
return new StringTextSource(ICSharpCode.AvalonEdit.Utils.FileReader.ReadFileContent(fileName, DefaultFileEncoding));
} }
static ITextSource GetParseableFileContentInternal(string fileName) public static ITextSource GetParseableFileContent(string fileName)
{ {
//ITextBuffer res = project.GetParseableFileContent(fileName); return GetParseableFileContent(FileName.Create(fileName));
//if (res != null) }
// return res;
/// <summary>
/// Gets the file content for a file that is currently open.
/// Returns null if the file is not open.
/// </summary>
static ITextSource GetParseableFileContentForOpenFile(FileName fileName)
{
OpenedFile file = FileService.GetOpenedFile(fileName); OpenedFile file = FileService.GetOpenedFile(fileName);
if (file != null) { if (file != null) {
IFileDocumentProvider p = file.CurrentView as IFileDocumentProvider; IFileDocumentProvider p = file.CurrentView as IFileDocumentProvider;
@ -344,9 +353,7 @@ namespace ICSharpCode.SharpDevelop.Parser
return new StringTextSource(ICSharpCode.AvalonEdit.Utils.FileReader.ReadFileContent(s, DefaultFileEncoding)); return new StringTextSource(ICSharpCode.AvalonEdit.Utils.FileReader.ReadFileContent(s, DefaultFileEncoding));
} }
} }
return null;
// load file
return new StringTextSource(ICSharpCode.AvalonEdit.Utils.FileReader.ReadFileContent(fileName, DefaultFileEncoding));
} }
#endregion #endregion
@ -358,6 +365,7 @@ namespace ICSharpCode.SharpDevelop.Parser
readonly FileName fileName; readonly FileName fileName;
internal readonly IParser parser; internal readonly IParser parser;
volatile IParsedFile mainParsedFile; volatile IParsedFile mainParsedFile;
volatile ParseInformation cachedParseInformation;
ITextSourceVersion bufferVersion; ITextSourceVersion bufferVersion;
IParsedFile[] oldUnits = emptyCompilationUnitArray; IParsedFile[] oldUnits = emptyCompilationUnitArray;
bool disposed; bool disposed;
@ -379,16 +387,12 @@ namespace ICSharpCode.SharpDevelop.Parser
} }
} }
public IParsedFile GetParseInformation(IProjectContent content) public ParseInformation GetCachedParseInformation()
{ {
IParsedFile p = GetExistingParseInformation(content); return cachedParseInformation; // read volatile
if (p != null)
return p;
else
return ParseFile(content, null);
} }
public IParsedFile GetExistingParseInformation(IProjectContent content) public IParsedFile GetExistingParsedFile(IProjectContent content)
{ {
if (content == null) { if (content == null) {
return this.mainParsedFile; // read volatile 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) 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) if (parser == null)
return null; return;
if (fileContent == null) { if (fileContent == null) {
// GetParseableFileContent must not be called inside any lock // No file content was specified. Because the callers of this method already check for currently open files,
// (otherwise we'd risk deadlocks because GetParseableFileContent must invoke on the main thread) // we can assume that the file isn't open and simply read it from disk.
fileContent = GetParseableFileContent(fileName); 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; ITextSourceVersion fileContentVersion = fileContent.Version;
List<IProjectContent> projectContents; List<IProjectContent> projectContents;
lock (this) { lock (this) {
if (this.disposed) if (this.disposed)
return null; return;
if (fileContentVersion != null && this.bufferVersion != null && this.bufferVersion.BelongsToSameDocumentAs(fileContentVersion)) { if (fileContentVersion != null && this.bufferVersion != null && this.bufferVersion.BelongsToSameDocumentAs(fileContentVersion)) {
if (this.bufferVersion.CompareAge(fileContentVersion) >= 0) { 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 // 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. // 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)) { 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 { } else {
projectContents = GetProjectContents(fileName); projectContents = GetProjectContents(fileName);
} }
} } // exit lock
// We now leave the lock to do the actual parsing. // 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 // This is done to allow IParser implementations to invoke methods on the main thread without
// risking deadlocks. // risking deadlocks.
@ -451,12 +510,10 @@ namespace ICSharpCode.SharpDevelop.Parser
// parse once for each project content that contains the file // parse once for each project content that contains the file
ParseInformation[] newParseInfo = new ParseInformation[projectContents.Count]; ParseInformation[] newParseInfo = new ParseInformation[projectContents.Count];
IParsedFile[] newUnits = new IParsedFile[projectContents.Count]; IParsedFile[] newUnits = new IParsedFile[projectContents.Count];
ParseInformation resultParseInfo = null;
IParsedFile resultUnit = null;
for (int i = 0; i < projectContents.Count; i++) { for (int i = 0; i < projectContents.Count; i++) {
IProjectContent pc = projectContents[i]; IProjectContent pc = projectContents[i];
try { try {
newParseInfo[i] = parser.Parse(pc, fileName, fileContent); newParseInfo[i] = parser.Parse(pc, fileName, fileContent, fullParseInformationRequested);
} catch (Exception ex) { } catch (Exception ex) {
throw new ApplicationException("Error parsing " + fileName, ex); throw new ApplicationException("Error parsing " + fileName, ex);
} }
@ -469,18 +526,34 @@ namespace ICSharpCode.SharpDevelop.Parser
} }
} }
lock (this) { lock (this) {
if (this.disposed) if (this.disposed) {
return null; resultParseInfo = null;
resultUnit = null;
return;
}
// ensure we never go backwards in time (we need to repeat this check after we've reacquired the lock) // 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 (fileContentVersion != null && this.bufferVersion != null && this.bufferVersion.BelongsToSameDocumentAs(fileContentVersion)) {
if (this.bufferVersion.CompareAge(fileContentVersion) >= 0) { if (this.bufferVersion.CompareAge(fileContentVersion) >= 0) {
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) { if (parentProjectContent != null) {
IParsedFile oldUnit = oldUnits.FirstOrDefault(o => o.ProjectContent == parentProjectContent); foreach (var oldUnit in this.oldUnits) {
if (oldUnit != null) if (oldUnit.ProjectContent == parentProjectContent) {
return oldUnit; resultUnit = oldUnit;
break;
}
}
}
return;
} }
return this.mainParsedFile;
} }
} }
@ -505,8 +578,13 @@ namespace ICSharpCode.SharpDevelop.Parser
this.bufferVersion = fileContentVersion; this.bufferVersion = fileContentVersion;
this.oldUnits = newUnits; this.oldUnits = newUnits;
this.mainParsedFile = resultUnit; 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() public void Clear()
@ -530,13 +608,67 @@ namespace ICSharpCode.SharpDevelop.Parser
} }
} }
public Task<IParsedFile> 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<ParseInformation> 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 {
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<IParsedFile> 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 // 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( return System.Threading.Tasks.Task.Factory.StartNew(
delegate { delegate {
try { try {
return ParseFile(null, fileContent); if (lookupOpenFileOnTargetThread) {
fileContent = WorkbenchSingleton.SafeThreadFunction(GetParseableFileContentForOpenFile, fileName);
}
ParseInformation parseInfo;
IParsedFile parsedFile;
DoParse(parentProjectContent, fileContent, false, out parseInfo, out parsedFile);
return parsedFile;
} catch (Exception ex) { } catch (Exception ex) {
MessageService.ShowException(ex, "Error during async parse"); MessageService.ShowException(ex, "Error during async parse");
return null; return null;
@ -593,7 +725,7 @@ namespace ICSharpCode.SharpDevelop.Parser
{ {
if (string.IsNullOrEmpty(fileName)) if (string.IsNullOrEmpty(fileName))
return null; return null;
return ParseFile(FileName.Create(fileName)); return Parse(FileName.Create(fileName));
} }
/// <summary> /// <summary>
@ -618,7 +750,7 @@ namespace ICSharpCode.SharpDevelop.Parser
return null; return null;
FileEntry entry = GetFileEntry(fileName, false); FileEntry entry = GetFileEntry(fileName, false);
if (entry != null) if (entry != null)
return entry.GetCachedParseInformation(null); return entry.GetCachedParseInformation();
else else
return null; return null;
} }
@ -686,7 +818,7 @@ namespace ICSharpCode.SharpDevelop.Parser
/// </remarks> /// </remarks>
public static ParseInformation Parse(FileName fileName, ITextSource fileContent = null) public static ParseInformation Parse(FileName fileName, ITextSource fileContent = null)
{ {
return GetFileEntry(fileName, true).Parse(null, fileContent); return GetFileEntry(fileName, true).Parse(fileContent);
} }
/// <summary> /// <summary>
@ -703,16 +835,34 @@ namespace ICSharpCode.SharpDevelop.Parser
/// </returns> /// </returns>
/// <remarks> /// <remarks>
/// This method is thread-safe. This parser being used may involve locking or waiting for the main thread, /// 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.
/// </remarks> /// </remarks>
public static Task<ParseInformation> ParseAsync(FileName fileName, ITextSource fileContent = null) public static Task<ParseInformation> ParseAsync(FileName fileName, ITextSource fileContent = null)
{ {
if (fileContent == null) return GetFileEntry(fileName, true).ParseAsync(fileContent);
throw new ArgumentNullException("fileContent");
// create snapshot (in case someone passes a mutable document to BeginParse)
return GetFileEntry(fileName, true).BeginParse(fileContent.CreateSnapshot());
} }
/// <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.
/// The fileContent is taken as a hint - if a newer version than it is already available, that will be used instead.
/// </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 necessary reparse, but may return
/// the existing IParsedFile (but only if it's still up-to-date).
/// </returns>
/// <remarks>
/// 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.
/// </remarks>
public static IParsedFile ParseFile(FileName fileName, ITextSource fileContent = null)
{
return GetFileEntry(fileName, true).ParseFile(null, fileContent);
}
/// <summary> /// <summary>
/// Parses the specified file. /// Parses the specified file.
@ -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. /// The fileContent is taken as a hint - if a newer version than it is already available, that will be used instead.
/// </param> /// </param>
/// <returns> /// <returns>
/// 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 /// 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).
/// </returns> /// </returns>
/// <remarks> /// <remarks>
/// This method is thread-safe. This parser being used may involve locking or waiting for the main thread, /// 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
/// </remarks> /// </remarks>
public static IParsedFile ParseFile(IProjectContent parentProjectContent, FileName fileName, ITextSource fileContent = null) 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);
}
/// <summary>
/// Async version of ParseFile().
/// </summary>
public static Task<IParsedFile> ParseFileAsync(FileName fileName, ITextSource fileContent = null)
{
return GetFileEntry(fileName, true).ParseFileAsync(null, fileContent);
}
/// <summary>
/// Async version of ParseFile().
/// </summary>
public static Task<IParsedFile> ParseFileAsync(IProjectContent parentProjectContent, FileName fileName, ITextSource fileContent = null)
{
return GetFileEntry(fileName, true).ParseFileAsync(parentProjectContent, fileContent);
} }
/// <summary> /// <summary>
@ -767,9 +933,9 @@ namespace ICSharpCode.SharpDevelop.Parser
return null; return null;
IEditable editable = viewContent as IEditable; IEditable editable = viewContent as IEditable;
if (editable != null) if (editable != null)
return ParseFile(viewContent.PrimaryFileName, editable.CreateSnapshot()); return Parse(viewContent.PrimaryFileName, editable.CreateSnapshot());
else else
return ParseFile(viewContent.PrimaryFileName); return Parse(viewContent.PrimaryFileName);
} }
/// <summary> /// <summary>
@ -777,7 +943,7 @@ namespace ICSharpCode.SharpDevelop.Parser
/// Will create a new IParser instance on demand. /// Will create a new IParser instance on demand.
/// This method is thread-safe. /// This method is thread-safe.
/// </summary> /// </summary>
public static IParser GetParser(string fileName) public static IParser GetParser(FileName fileName)
{ {
return GetFileEntry(fileName, true).parser; return GetFileEntry(fileName, true).parser;
} }
@ -788,7 +954,7 @@ namespace ICSharpCode.SharpDevelop.Parser
/// </summary> /// </summary>
public static void RegisterParseInformation(string fileName, IParsedFile cu) public static void RegisterParseInformation(string fileName, IParsedFile cu)
{ {
FileEntry entry = GetFileEntry(fileName, true); FileEntry entry = GetFileEntry(FileName.Create(fileName), true);
entry.RegisterParseInformation(cu); entry.RegisterParseInformation(cu);
} }

12
src/Main/Core/Project/Src/Services/FileUtility/FileName.cs

@ -22,6 +22,12 @@ namespace ICSharpCode.Core
this.normalizedFileName = FileUtility.NormalizePath(fileName); this.normalizedFileName = FileUtility.NormalizePath(fileName);
} }
[Obsolete("The input already is a FileName")]
public FileName(FileName fileName)
{
this.normalizedFileName = fileName.normalizedFileName;
}
/// <summary> /// <summary>
/// Creates a FileName instance from the string. /// 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). /// 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); 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) public static implicit operator string(FileName fileName)
{ {
if (fileName != null) if (fileName != null)

Loading…
Cancel
Save