Browse Source

Merge branch '4.0'

pull/21/head
Daniel Grunwald 15 years ago
parent
commit
ce1cba0e6e
  1. 3057
      src/AddIns/BackendBindings/VBNetBinding/Project/Src/FormattingStrategy/Parser.cs
  2. 80
      src/AddIns/BackendBindings/VBNetBinding/Project/Src/FormattingStrategy/PushParser.frame
  3. 298
      src/AddIns/BackendBindings/VBNetBinding/Project/Src/FormattingStrategy/VBIndentationStrategy.atg
  4. 76
      src/AddIns/BackendBindings/VBNetBinding/Project/Src/FormattingStrategy/VBIndentationStrategy.cs
  5. 207
      src/AddIns/BackendBindings/VBNetBinding/Project/Src/FormattingStrategy/VBNetFormattingStrategy.cs
  6. 2
      src/AddIns/BackendBindings/VBNetBinding/Project/Src/LanguageUtils.cs
  7. 2
      src/AddIns/BackendBindings/VBNetBinding/Project/Src/Parser/Parser.cs
  8. 11
      src/AddIns/BackendBindings/VBNetBinding/Project/VBNetBinding.csproj
  9. 164
      src/AddIns/BackendBindings/VBNetBinding/Test/FormattingStrategy/IndentationTests.cs
  10. 10
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.cs
  11. 9
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/SharpDevelopCompletionWindow.cs
  12. 8
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/SnippetManager.cs
  13. 7
      src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core.UI/DisplayBinding/EDMDesignerViewContent.cs
  14. 2
      src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/Windows/EDMWizard/EDMWizardErrorUserControl.xaml
  15. 2
      src/AddIns/Misc/SharpRefactoring/Project/Src/Gui/InsertCtorDialog.xaml.cs
  16. 7
      src/AddIns/Misc/SharpRefactoring/Project/Src/InsertCtorSnippetRefactoring.cs
  17. 25
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextDocument.cs
  18. 2
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextDocumentWeakEventManager.cs
  19. 7
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/LineNumberMargin.cs
  20. 15
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs
  21. 1
      src/Libraries/NRefactory/Project/NRefactory.csproj
  22. 36
      src/Libraries/NRefactory/Project/Src/Lexer/VBNet/ExpressionFinder.atg
  23. 16
      src/Libraries/NRefactory/Project/Src/Lexer/VBNet/ExpressionFinder.cs
  24. 5329
      src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Parser.cs
  25. 1246
      src/Libraries/NRefactory/Project/Src/Parser/VBNet/Parser.cs
  26. 8
      src/Libraries/NRefactory/Project/Src/Parser/VBNet/VBNET.ATG
  27. 6
      src/Libraries/NRefactory/Test/Lexer/VBNet/LexerContextTests.cs
  28. 5
      src/Main/Base/Project/Src/Gui/Dialogs/SharpDevelopAboutPanels.cs
  29. 30
      src/Main/Base/Test/VBExpressionFinderTests.cs
  30. 1
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs
  31. 33
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ParameterListComparer.cs

3057
src/AddIns/BackendBindings/VBNetBinding/Project/Src/FormattingStrategy/Parser.cs

File diff suppressed because it is too large Load Diff

80
src/AddIns/BackendBindings/VBNetBinding/Project/Src/FormattingStrategy/PushParser.frame

@ -1,80 +0,0 @@
/*----------------------------------------------------------------------
Compiler Generator Coco/R,
Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
extended by M. Loeberbauer & A. Woess, Univ. of Linz
with improvements by Pat Terry, Rhodes University
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
As an exception, it is allowed to write an extension of Coco/R that is
used as a plugin in non-free software.
If not otherwise stated, any source code generated by Coco/R (other than
Coco/R itself) does not fall under the GNU General Public License.
----------------------------------------------------------------------*/
-->begin
-->namespace
partial class VBIndentationStrategy {
-->constants
const bool T = true;
const bool x = false;
-->declarations
readonly Stack<int> stateStack = new Stack<int>();
List<Token> errors = new List<Token>();
VBIndentationStrategy()
{
stateStack.Push(-1); // required so that we don't crash when leaving the root production
}
void Expect(int expectedKind, Token la)
{
if (la.Kind != expectedKind) {
Error(la);
Console.WriteLine("expected: " + expectedKind);
}
}
void Error(Token la)
{
Console.WriteLine("not expected: " + la);
errors.Add(la);
}
Token t;
public void InformToken(Token la)
{
-->informToken
if (la != null)
t = la;
}
public void Advance()
{
//Console.WriteLine("Advance");
InformToken(null);
}
static readonly BitArray[] set = {
-->initialization
};
} // end Parser
$$$

298
src/AddIns/BackendBindings/VBNetBinding/Project/Src/FormattingStrategy/VBIndentationStrategy.atg

@ -1,298 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using ICSharpCode.NRefactory.Parser;
PUSHCOMPILER VBIndentationStrategy
$tokenKindFieldName=Kind
/* START AUTOGENERATED TOKENS SECTION */
TOKENS
/* ----- terminal classes ----- */
/* EOF is 0 */
EOL
ident
LiteralString
LiteralCharacter
LiteralInteger
LiteralDouble
LiteralSingle
LiteralDecimal
LiteralDate
XmlOpenTag
XmlCloseTag
XmlStartInlineVB
XmlEndInlineVB
XmlCloseTagEmptyElement
XmlOpenEndTag
XmlContent
XmlComment
XmlCData
XmlProcessingInstruction
/* ----- special character ----- */
"="
":"
","
"&"
"/"
"\\"
"."
"..."
".@"
"!"
"-"
"+"
"^"
"?"
"*"
"{"
"}"
"("
")"
">"
"<"
"<>"
">="
"<="
"<<"
">>"
"+="
"^="
"-="
"*="
"/="
"\\="
"<<="
">>="
"&="
":="
/* ----- keywords ----- */
"AddHandler"
"AddressOf"
"Aggregate"
"Alias"
"And"
"AndAlso"
"Ansi"
"As"
"Ascending"
"Assembly"
"Auto"
"Binary"
"Boolean"
"ByRef"
"By"
"Byte"
"ByVal"
"Call"
"Case"
"Catch"
"CBool"
"CByte"
"CChar"
"CDate"
"CDbl"
"CDec"
"Char"
"CInt"
"Class"
"CLng"
"CObj"
"Compare"
"Const"
"Continue"
"CSByte"
"CShort"
"CSng"
"CStr"
"CType"
"CUInt"
"CULng"
"CUShort"
"Custom"
"Date"
"Decimal"
"Declare"
"Default"
"Delegate"
"Descending"
"Dim"
"DirectCast"
"Distinct"
"Do"
"Double"
"Each"
"Else"
"ElseIf"
"End"
"EndIf"
"Enum"
"Equals"
"Erase"
"Error"
"Event"
"Exit"
"Explicit"
"False"
"Finally"
"For"
"Friend"
"From"
"Function"
"Get"
"GetType"
"Global"
"GoSub"
"GoTo"
"Group"
"Handles"
"If"
"Implements"
"Imports"
"In"
"Infer"
"Inherits"
"Integer"
"Interface"
"Into"
"Is"
"IsNot"
"Join"
"Key"
"Let"
"Lib"
"Like"
"Long"
"Loop"
"Me"
"Mod"
"Module"
"MustInherit"
"MustOverride"
"MyBase"
"MyClass"
"Namespace"
"Narrowing"
"New"
"Next"
"Not"
"Nothing"
"NotInheritable"
"NotOverridable"
"Object"
"Of"
"Off"
"On"
"Operator"
"Option"
"Optional"
"Or"
"Order"
"OrElse"
"Out"
"Overloads"
"Overridable"
"Overrides"
"ParamArray"
"Partial"
"Preserve"
"Private"
"Property"
"Protected"
"Public"
"RaiseEvent"
"ReadOnly"
"ReDim"
"Rem"
"RemoveHandler"
"Resume"
"Return"
"SByte"
"Select"
"Set"
"Shadows"
"Shared"
"Short"
"Single"
"Skip"
"Static"
"Step"
"Stop"
"Strict"
"String"
"Structure"
"Sub"
"SyncLock"
"Take"
"Text"
"Then"
"Throw"
"To"
"True"
"Try"
"TryCast"
"TypeOf"
"UInteger"
"ULong"
"Unicode"
"Until"
"UShort"
"Using"
"Variant"
"Wend"
"When"
"Where"
"While"
"Widening"
"With"
"WithEvents"
"WriteOnly"
"Xor"
"GetXmlNamespace"
/* END AUTOGENERATED TOKENS SECTION */
PRODUCTIONS
/*------------------------------------------------------------------------*/
VBIndentationStrategy =
{ ANY }
{ NamespaceMemberDeclaration { ANY } }
.
StatementTerminator =
EOL | ":"
.
NamespaceMemberDeclaration =
NamespaceDeclaration
| TypeDeclaration
.
NamespaceDeclaration =
"Namespace" { ANY } StatementTerminator
(. Indent(la); .)
{ NamespaceMemberDeclaration { ANY } }
(. Unindent(la); .)
"End" "Namespace" StatementTerminator
.
TypeDeclaration =
ClassOrModuleOrStructureTypeDeclaration |
DelegateTypeDeclaration |
EnumTypeDeclaration |
InterfaceDeclaration
.
DelegateTypeDeclaration = "Delegate" { ANY } StatementTerminator .
EnumTypeDeclaration =
"Enum" { ANY } StatementTerminator
(. Indent(la); .)
{ ANY } StatementTerminator
(. Unindent(la); .)
"End" "Enum" StatementTerminator
.
END VBIndentationStrategy.

76
src/AddIns/BackendBindings/VBNetBinding/Project/Src/FormattingStrategy/VBIndentationStrategy.cs

@ -1,76 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.Parser;
using ICSharpCode.SharpDevelop.Editor;
namespace ICSharpCode.VBNetBinding
{
/// <summary>
/// Description of VBIndentationStrategy.
/// </summary>
public partial class VBIndentationStrategy
{
Stack<Block> indentationStack = new Stack<Block>();
ITextEditor editor;
IDocumentLine startLine, endLine;
public string CurrentIndent {
get { return (indentationStack.PeekOrDefault() ?? Block.Empty).Indentation; }
}
class Block {
public static readonly Block Empty = new Block {
Indentation = "",
StartLine = 1
};
public string Indentation;
public int StartLine;
}
public VBIndentationStrategy(ITextEditor editor, int start, int end)
: this()
{
this.editor = editor;
startLine = editor.Document.GetLine(start);
endLine = editor.Document.GetLine(end);
}
void Indent(Token la)
{
ApplyIndent(la);
Block parent = indentationStack.PeekOrDefault() ?? Block.Empty;
indentationStack.Push(new Block() { Indentation = parent.Indentation + editor.Options.IndentationString, StartLine = t.Location.Line + 1 } );
}
void Unindent(Token la)
{
ApplyIndent(la);
indentationStack.PopOrDefault();
}
void ApplyIndent(Token la)
{
Block current = indentationStack.PeekOrDefault() ?? Block.Empty;
if (t.Location.Line < startLine.LineNumber)
return;
IDocumentLine firstLine = startLine.LineNumber > current.StartLine ? startLine : editor.Document.GetLine(current.StartLine);
IDocumentLine currentLine = firstLine;
while (currentLine.LineNumber < la.Location.Line) {
editor.Document.SmartReplaceLine(currentLine, current.Indentation + currentLine.Text.Trim());
if (currentLine.LineNumber == endLine.LineNumber)
break;
currentLine = editor.Document.GetLine(currentLine.LineNumber + 1);
}
}
}
}

207
src/AddIns/BackendBindings/VBNetBinding/Project/Src/FormattingStrategy/VBNetFormattingStrategy.cs

@ -23,6 +23,7 @@ namespace ICSharpCode.VBNetBinding
/// </summary> /// </summary>
public class VBNetFormattingStrategy : DefaultFormattingStrategy public class VBNetFormattingStrategy : DefaultFormattingStrategy
{ {
#region VB Statements
static readonly List<VBStatement> statements; static readonly List<VBStatement> statements;
internal static List<VBStatement> Statements { internal static List<VBStatement> Statements {
@ -85,6 +86,7 @@ namespace ICSharpCode.VBNetBinding
Tokens.If, Tokens.For, Tokens.Do, Tokens.While, Tokens.With, Tokens.Select, Tokens.Try, Tokens.If, Tokens.For, Tokens.Do, Tokens.While, Tokens.With, Tokens.Select, Tokens.Try,
Tokens.Property, Tokens.Get, Tokens.Set Tokens.Property, Tokens.Get, Tokens.Set
}); });
#endregion
bool doCasing; bool doCasing;
bool doInsertion; bool doInsertion;
@ -408,7 +410,6 @@ namespace ICSharpCode.VBNetBinding
while ((currentToken = lexer.NextToken()).Kind != Tokens.EOF) { while ((currentToken = lexer.NextToken()).Kind != Tokens.EOF) {
if (prevToken == null) if (prevToken == null)
prevToken = currentToken; prevToken = currentToken;
if (IsBlockStart(lexer, currentToken, prevToken)) { if (IsBlockStart(lexer, currentToken, prevToken)) {
if ((tokens.Count > 0 && tokens.Peek().Kind != Tokens.Interface) || IsDeclaration(currentToken.Kind)) if ((tokens.Count > 0 && tokens.Peek().Kind != Tokens.Interface) || IsDeclaration(currentToken.Kind))
tokens.Push(currentToken); tokens.Push(currentToken);
@ -514,10 +515,9 @@ namespace ICSharpCode.VBNetBinding
ILexer lexer = ParserFactory.CreateLexer(SupportedLanguage.VBNet, new StringReader(editor.Document.Text)); ILexer lexer = ParserFactory.CreateLexer(SupportedLanguage.VBNet, new StringReader(editor.Document.Text));
Stack<string> indentation = new Stack<string>(); Stack<string> indentation = new Stack<string>();
indentation.Push(string.Empty); indentation.Push(string.Empty);
int oldLine = 1; List<int> eols = new List<int>();
bool inInterface = false; bool inInterface = false;
bool isMustOverride = false; bool isMustOverride = false;
@ -527,6 +527,9 @@ namespace ICSharpCode.VBNetBinding
Token currentToken = null; Token currentToken = null;
Token prevToken = null; Token prevToken = null;
int blockStart = 1;
int lambdaNesting = 0;
while ((currentToken = lexer.NextToken()).Kind != Tokens.EOF) { while ((currentToken = lexer.NextToken()).Kind != Tokens.EOF) {
if (prevToken == null) if (prevToken == null)
prevToken = currentToken; prevToken = currentToken;
@ -540,11 +543,29 @@ namespace ICSharpCode.VBNetBinding
if (currentToken.Kind == Tokens.Declare) if (currentToken.Kind == Tokens.Declare)
isDeclare = true; isDeclare = true;
if (currentToken.Kind == Tokens.EOL) if (currentToken.Kind == Tokens.EOL) {
isDelegate = isDeclare = isMustOverride = false; isDelegate = isDeclare = isMustOverride = false;
eols.Add(currentToken.Location.Line);
}
if (IsBlockEnd(currentToken, prevToken)) { if (IsBlockEnd(currentToken, prevToken)) {
ApplyToRange(editor, indentation, oldLine, currentToken.Location.Line, begin, end); // indent the lines inside the block
// this is an End-statement
// hence we indent from blockStart to the previous line
int blockEnd = currentToken.Location.Line - 1;
// if this is a lambda end include End-Statement in block
// if (lambdaNesting > 0 && (currentToken.Kind == Tokens.Function || currentToken.Kind == Tokens.Sub)) {
// blockEnd++;
// }
ApplyToRange(editor, indentation, eols, blockStart, blockEnd, begin, end);
if (lambdaNesting > 0 && (currentToken.Kind == Tokens.Function || currentToken.Kind == Tokens.Sub)) {
Unindent(indentation);
ApplyToRange(editor, indentation, eols, currentToken.Location.Line, currentToken.Location.Line, begin, end);
}
if (currentToken.Kind == Tokens.Interface) if (currentToken.Kind == Tokens.Interface)
inInterface = false; inInterface = false;
@ -556,12 +577,31 @@ namespace ICSharpCode.VBNetBinding
Unindent(indentation); Unindent(indentation);
} }
oldLine = currentToken.Location.Line; // block start is this line (for the lines between two blocks)
blockStart = currentToken.Location.Line;
if (lambdaNesting > 0 && (currentToken.Kind == Tokens.Function || currentToken.Kind == Tokens.Sub)) {
blockStart++;
lambdaNesting--;
}
} }
if (IsBlockStart(lexer, currentToken, prevToken)) { bool isMultiLineLambda;
int line = GetLastVisualLine(currentToken.Location.Line, editor); if (IsBlockStart(lexer, currentToken, prevToken, out isMultiLineLambda)) {
ApplyToRange(editor, indentation, oldLine, line, begin, end); // indent the lines between the last and this block
// this is a Begin-statement
// hence we indent from blockStart to the this line
int lastVisualLine = FindNextEol(lexer);
eols.Add(lastVisualLine);
ApplyToRange(editor, indentation, eols, blockStart, lastVisualLine, begin, end);
if (isMultiLineLambda && (currentToken.Kind == Tokens.Function || currentToken.Kind == Tokens.Sub)) {
lambdaNesting++;
int endColumn = currentToken.Location.Column;
int startColumn = DocumentUtilitites.GetWhitespaceAfter(editor.Document, editor.Document.GetLine(lastVisualLine).Offset).Length;
if (startColumn < endColumn)
Indent(editor, indentation, new string(' ', endColumn - startColumn - 1));
}
if (!inInterface && !isMustOverride && !isDeclare && !isDelegate) { if (!inInterface && !isMustOverride && !isDeclare && !isDelegate) {
Indent(editor, indentation); Indent(editor, indentation);
@ -573,31 +613,78 @@ namespace ICSharpCode.VBNetBinding
if (currentToken.Kind == Tokens.Interface) if (currentToken.Kind == Tokens.Interface)
inInterface = true; inInterface = true;
oldLine = line + 1; // block start is the following line (for the lines inside a block)
blockStart = lastVisualLine + 1;
} }
prevToken = currentToken; prevToken = currentToken;
} }
// do last indent step ApplyToRange(editor, indentation, eols, blockStart, editor.Document.TotalNumberOfLines, begin, end);
int newLine = prevToken.Location.Line;
if (oldLine > newLine)
newLine = oldLine;
ApplyToRange(editor, indentation, oldLine, newLine, begin, end);
return (indentation.PeekOrDefault() ?? string.Empty).Length; return (indentation.PeekOrDefault() ?? string.Empty).Length;
} }
static int GetLastVisualLine(int line, ITextEditor area) static int FindNextEol(ILexer lexer)
{ {
string text = area.Document.GetLine(line).Text.TrimComments(); lexer.StartPeek();
while (text.EndsWith("_", StringComparison.Ordinal)) {
line++; Token t = lexer.Peek();
text = area.Document.GetLine(line).Text.TrimComments();
while (t.Kind != Tokens.EOL)
t = lexer.Peek();
return t.Location.Line;
}
static void ApplyToRange(ITextEditor editor, Stack<string> indentation, List<int> eols, int blockStart, int blockEnd, int selectionStart, int selectionEnd) {
LoggingService.InfoFormatted("indenting line {0} to {1} with {2}", blockStart, blockEnd, (indentation.PeekOrDefault() ?? "").Length);
int nextEol = -1;
bool wasMultiLine = false;
for (int i = blockStart; i <= blockEnd; i++) {
IDocumentLine curLine = editor.Document.GetLine(i);
string lineText = curLine.Text.TrimStart();
string noComments = lineText.TrimComments().TrimEnd();
// adjust indentation if the current line is not selected
// lines between the selection will be aligned to the selected level
if (i < selectionStart || i > selectionEnd) {
indentation.PopOrDefault();
indentation.Push(DocumentUtilitites.GetWhitespaceAfter(editor.Document, curLine.Offset));
}
// look for next eol if line is not empty
// (the lexer does not produce eols for empty lines)
if (!string.IsNullOrEmpty(noComments) && i >= nextEol) {
int search = eols.BinarySearch(i);
if (search < 0)
search = ~search;
nextEol = search < eols.Count ? eols[search] : i;
}
// remove indentation in last line of multiline array(, collection, object) initializers
if (i == nextEol && wasMultiLine && noComments == "}") {
wasMultiLine = false;
Unindent(indentation);
}
// apply the indentation
editor.Document.SmartReplaceLine(curLine, (indentation.PeekOrDefault() ?? "") + lineText);
// indent line if it is ended by (implicit) line continuation
if (i < nextEol && !wasMultiLine) {
wasMultiLine = true;
Indent(editor, indentation);
}
// unindent if this is the last line of a multiline statement
if (i == nextEol && wasMultiLine) {
wasMultiLine = false;
Unindent(indentation);
}
} }
return line;
} }
static void Unindent(Stack<string> indentation) static void Unindent(Stack<string> indentation)
@ -605,13 +692,21 @@ namespace ICSharpCode.VBNetBinding
indentation.PopOrDefault(); indentation.PopOrDefault();
} }
static void Indent(ITextEditor editor, Stack<string> indentation) static void Indent(ITextEditor editor, Stack<string> indentation, string indent = null)
{ {
indentation.Push((indentation.PeekOrDefault() ?? string.Empty) + editor.Options.IndentationString); indentation.Push((indentation.PeekOrDefault() ?? string.Empty) + (indent ?? editor.Options.IndentationString));
} }
internal static bool IsBlockStart(ILexer lexer, Token current, Token prev) internal static bool IsBlockStart(ILexer lexer, Token current, Token prev)
{ {
bool tmp;
return IsBlockStart(lexer, current, prev, out tmp);
}
static bool IsBlockStart(ILexer lexer, Token current, Token prev, out bool isMultiLineLambda)
{
isMultiLineLambda = false;
if (blockTokens.Contains(current.Kind)) { if (blockTokens.Contains(current.Kind)) {
if (current.Kind == Tokens.If) { if (current.Kind == Tokens.If) {
if (prev.Kind != Tokens.EOL) if (prev.Kind != Tokens.EOL)
@ -627,10 +722,33 @@ namespace ICSharpCode.VBNetBinding
} }
} }
if (current.Kind == Tokens.Function) { // check if it is a lambda
if (current.Kind == Tokens.Function || current.Kind == Tokens.Sub) {
lexer.StartPeek(); lexer.StartPeek();
if (lexer.Peek().Kind == Tokens.OpenParenthesis) bool isSingleLineLambda = false;
if (lexer.Peek().Kind == Tokens.OpenParenthesis) {
isSingleLineLambda = true;
int brackets = 1;
// look for end of parameter list
while (brackets > 0) {
var t = lexer.Peek();
if (t.Kind == Tokens.OpenParenthesis)
brackets++;
if (t.Kind == Tokens.CloseParenthesis)
brackets--;
}
// expression is multi-line lambda if next Token is EOL
if (brackets == 0)
return isMultiLineLambda = (lexer.Peek().Kind == Tokens.EOL);
}
// do not indent if current token is start of single-line lambda
if (isSingleLineLambda)
return false; return false;
} }
@ -716,41 +834,6 @@ namespace ICSharpCode.VBNetBinding
return false; return false;
} }
static void ApplyToRange(ITextEditor editor, Stack<string> indentation, int begin, int end, int selBegin, int selEnd)
{
bool multiLine = false;
for (int i = begin; i <= end; i++) {
IDocumentLine curLine = editor.Document.GetLine(i);
string lineText = curLine.Text.TrimStart(' ', '\t', '\r', '\n');
string noComments = lineText.TrimComments().TrimEnd(' ', '\t', '\r', '\n');
if (i < selBegin || i > selEnd) {
indentation.PopOrDefault();
indentation.Push(DocumentUtilitites.GetWhitespaceAfter(editor.Document, curLine.Offset));
}
// change indentation before (indent this line)
if (multiLine && noComments.EndsWith("}", StringComparison.OrdinalIgnoreCase)) {
Unindent(indentation);
multiLine = false;
}
editor.Document.SmartReplaceLine(curLine, (indentation.PeekOrDefault() ?? string.Empty) + lineText);
// change indentation afterwards (indent next line)
if (!multiLine && noComments.EndsWith("_", StringComparison.OrdinalIgnoreCase)) {
Indent(editor, indentation);
multiLine = true;
}
if (multiLine && !noComments.EndsWith("_", StringComparison.OrdinalIgnoreCase)) {
multiLine = false;
Unindent(indentation);
}
}
}
/// <summary> /// <summary>
/// Gets the next member after the specified caret position. /// Gets the next member after the specified caret position.
/// </summary> /// </summary>

2
src/AddIns/BackendBindings/VBNetBinding/Project/Src/LanguageUtils.cs

@ -20,7 +20,7 @@ namespace ICSharpCode.VBNetBinding
if (line[i] == '"') if (line[i] == '"')
inStr = !inStr; inStr = !inStr;
if (line[i] == '\'' && !inStr) if (line[i] == '\'' && !inStr)
return line.Substring(0, i).Trim(); return line.Substring(0, i);
} }
return line; return line;

2
src/AddIns/BackendBindings/VBNetBinding/Project/Src/Parser/Parser.cs

@ -56,7 +56,7 @@ namespace ICSharpCode.VBNetBinding
&& directive.Arg.StartsWith("region", StringComparison.OrdinalIgnoreCase) && directive.Arg.StartsWith("region", StringComparison.OrdinalIgnoreCase)
&& regionStartDirectives.Any()) { && regionStartDirectives.Any()) {
ICSharpCode.NRefactory.PreprocessingDirective start = regionStartDirectives.Pop(); ICSharpCode.NRefactory.PreprocessingDirective start = regionStartDirectives.Pop();
cu.FoldingRegions.Add(new FoldingRegion(start.Arg.TrimComments().Trim('"'), DomRegion.FromLocation(start.StartPosition, directive.EndPosition))); cu.FoldingRegions.Add(new FoldingRegion(start.Arg.TrimComments().Trim().Trim('"'), DomRegion.FromLocation(start.StartPosition, directive.EndPosition)));
} }
} }
} }

11
src/AddIns/BackendBindings/VBNetBinding/Project/VBNetBinding.csproj

@ -63,10 +63,6 @@
<LogicalName>Resources.BuildOptions.xfrm</LogicalName> <LogicalName>Resources.BuildOptions.xfrm</LogicalName>
</EmbeddedResource> </EmbeddedResource>
<Compile Include="Src\Extensions.cs" /> <Compile Include="Src\Extensions.cs" />
<Compile Include="Src\FormattingStrategy\Parser.cs">
<DependentUpon>VBIndentationStrategy.atg</DependentUpon>
</Compile>
<Compile Include="Src\FormattingStrategy\VBIndentationStrategy.cs" />
<Compile Include="Src\FormattingStrategy\VBStatement.cs" /> <Compile Include="Src\FormattingStrategy\VBStatement.cs" />
<Compile Include="Src\LanguageUtils.cs" /> <Compile Include="Src\LanguageUtils.cs" />
<Compile Include="Src\OptionPanels\ProjectImportsOptions.xaml.cs"> <Compile Include="Src\OptionPanels\ProjectImportsOptions.xaml.cs">
@ -88,13 +84,6 @@
</Compile> </Compile>
<Compile Include="Src\Parser\Parser.cs" /> <Compile Include="Src\Parser\Parser.cs" />
<Compile Include="Src\Project\VBNetProject.cs" /> <Compile Include="Src\Project\VBNetProject.cs" />
<None Include="Src\FormattingStrategy\PushParser.frame">
<DependentUpon>VBIndentationStrategy.atg</DependentUpon>
</None>
<None Include="Src\FormattingStrategy\VBIndentationStrategy.atg">
<Generator>CocoParserGenerator</Generator>
<CustomToolNamespace>ICSharpCode.VBNetBinding</CustomToolNamespace>
</None>
<None Include="VBNetBinding.addin"> <None Include="VBNetBinding.addin">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>

164
src/AddIns/BackendBindings/VBNetBinding/Test/FormattingStrategy/IndentationTests.cs

@ -9,7 +9,7 @@ using NUnit.Framework;
namespace ICSharpCode.VBNetBinding.Tests namespace ICSharpCode.VBNetBinding.Tests
{ {
[TestFixture, Ignore] [TestFixture]
public class IndentationTests public class IndentationTests
{ {
[Test] [Test]
@ -63,22 +63,93 @@ End Interface";
} }
[Test] [Test]
public void ArrayInitializerTest() public void SD1775_Fix()
{ {
string expected = @"Public Class Test string expected = @"Public Class Test
Private Sub Tester() Private Sub Tester()
test(asdf, _ B = New Burger With {Cheese = True, _
asdf, _ Lettuce = True, _
asdf, _ Tomato = True, _
asdf) CookLevel = MeatCookLevel.WellDone}
Dim test As Integer() = { _
2,2,3,34,4,5 _
}
End Sub End Sub
End Class"; End Class";
string code = @"Public Class Test string code = @"Public Class Test
Private Sub Tester()
B = New Burger With {Cheese = True, _
Lettuce = True, _
Tomato = True, _
CookLevel = MeatCookLevel.WellDone}
End Sub
End Class";
RunFormatTest(code, expected);
}
[Test]
public void Simple()
{
string expected = @"'
' Created by SharpDevelop.
' User: Siegfried
' Date: 25.02.2011
' Time: 14:41
'
' To change this template use Tools | Options | Coding | Edit Standard Headers.
'
Imports Microsoft.VisualBasic.ApplicationServices
Namespace My
' This file controls the behaviour of the application.
Partial Class MyApplication
Public Sub New()
MyBase.New(AuthenticationMode.Windows)
Me.IsSingleInstance = False
Me.EnableVisualStyles = True
Me.SaveMySettingsOnExit = True
Me.ShutDownStyle = ShutdownMode.AfterMainFormCloses
End Sub
Protected Overrides Sub OnCreateMainForm()
Me.MainForm = My.Forms.MainForm
End Sub
End Class
End Namespace";
string code = @"'
' Created by SharpDevelop.
' User: Siegfried
' Date: 25.02.2011
' Time: 14:41
'
' To change this template use Tools | Options | Coding | Edit Standard Headers.
'
Imports Microsoft.VisualBasic.ApplicationServices
Namespace My
' This file controls the behaviour of the application.
Partial Class MyApplication
Public Sub New()
MyBase.New(AuthenticationMode.Windows)
Me.IsSingleInstance = False
Me.EnableVisualStyles = True
Me.SaveMySettingsOnExit = True
Me.ShutDownStyle = ShutdownMode.AfterMainFormCloses
End Sub
Protected Overrides Sub OnCreateMainForm()
Me.MainForm = My.Forms.MainForm
End Sub
End Class
End Namespace";
RunFormatTest(code, expected);
}
[Test]
public void ArrayInitializerTest()
{
string expected = @"Public Class Test
Private Sub Tester() Private Sub Tester()
test(asdf, _ test(asdf, _
asdf, _ asdf, _
@ -86,11 +157,24 @@ End Class";
asdf) asdf)
Dim test As Integer() = { _ Dim test As Integer() = { _
2,2,3,34,4,5 _ 2,2,3,34,4,5 _
} }
End Sub End Sub
End Class"; End Class";
string code = @"Public Class Test
Private Sub Tester()
test(asdf, _
asdf, _
asdf, _
asdf)
Dim test As Integer() = { _
2,2,3,34,4,5 _
}
End Sub
End Class";
RunFormatTest(code, expected); RunFormatTest(code, expected);
} }
@ -177,7 +261,7 @@ End Class";
[Test] [Test]
public void SelectCaseTest() public void SelectCaseTest()
{ {
string expected = @"Public Class Test string expected = @"Public Class Test
Private Sub Tester() Private Sub Tester()
Select Case a Select Case a
Case 0 Case 0
@ -215,7 +299,7 @@ End Class";
[Test] [Test]
public void SelectCaseTest2() public void SelectCaseTest2()
{ {
string expected = @"Public Class Test string expected = @"Public Class Test
Private Sub Tester() Private Sub Tester()
Select Case a Select Case a
Case 0 Case 0
@ -247,7 +331,7 @@ End Class";
[Test] [Test]
public void WithTest() public void WithTest()
{ {
string expected = @"Public Class Test string expected = @"Public Class Test
Private Sub Tester() Private Sub Tester()
With a With a
If True Then If True Then
@ -281,7 +365,7 @@ End Class";
[Test] [Test]
public void WithTest2() public void WithTest2()
{ {
string expected = @"Public Class Test string expected = @"Public Class Test
Private Sub Tester() Private Sub Tester()
With a With a
If True Then If True Then
@ -320,6 +404,56 @@ End Class";
RunFormatTest(code, expected); RunFormatTest(code, expected);
} }
[Test, Ignore]
// TODO : find out why unit test does not work, but normal run works
public void FunctionLambda()
{
string expected = @"Public Class Test
Private Sub Tester()
Dim increment1 = Function(x) x + 1
Dim increment2 = Function(x)
Return x + 2
End Function
End Sub
End Class";
string code = @"Public Class Test
Private Sub Tester()
Dim increment1 = Function(x) x + 1
Dim increment2 = Function(x)
Return x + 2
End Function
End Sub
End Class";
RunFormatTest(code, expected);
}
[Test, Ignore]
// TODO : find out why unit test does not work, but normal run works
public void SubLambda()
{
string expected = @"Public Class Test
Private Sub Tester()
Dim writeline1 = Sub(x) Console.WriteLine(x)
Dim writeline2 = Sub(x)
Console.WriteLine(x)
End Sub
End Sub
End Class";
string code = @"Public Class Test
Private Sub Tester()
Dim writeline1 = Sub(x) Console.WriteLine(x)
Dim writeline2 = Sub(x)
Console.WriteLine(x)
End Sub
End Sub
End Class";
RunFormatTest(code, expected);
}
void RunFormatTest(string code, string expectedCode) void RunFormatTest(string code, string expectedCode)
{ {
AvalonEditTextEditorAdapter editor = new AvalonEditTextEditorAdapter(new TextEditor()); AvalonEditTextEditorAdapter editor = new AvalonEditTextEditorAdapter(new TextEditor());

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

@ -28,7 +28,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
/// <summary> /// <summary>
/// ViewModel used for combobox items. /// ViewModel used for combobox items.
/// </summary> /// </summary>
class EntityItem : IComparable<EntityItem> class EntityItem : IComparable<EntityItem>, System.ComponentModel.INotifyPropertyChanged
{ {
IEntity entity; IEntity entity;
IImage image; IImage image;
@ -96,6 +96,14 @@ namespace ICSharpCode.AvalonEdit.AddIn
{ {
return text; return text;
} }
// I'm not sure if it actually was a leak or caused by something else, but I saw QCB.EntityItem being alive for longer
// than it should when looking at the heap with WinDbg.
// Maybe this was caused by http://support.microsoft.com/kb/938416/en-us, so I'm adding INotifyPropertyChanged to be sure.
event System.ComponentModel.PropertyChangedEventHandler System.ComponentModel.INotifyPropertyChanged.PropertyChanged {
add { }
remove { }
}
} }
public QuickClassBrowser() public QuickClassBrowser()

9
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/SharpDevelopCompletionWindow.cs

@ -2,6 +2,7 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System; using System;
using System.ComponentModel;
using System.Linq; using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
@ -137,7 +138,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
new object Description { get; } new object Description { get; }
} }
sealed class CodeCompletionDataAdapter : ICompletionData sealed class CodeCompletionDataAdapter : ICompletionData, INotifyPropertyChanged
{ {
readonly SharpDevelopCompletionWindow window; readonly SharpDevelopCompletionWindow window;
readonly ICompletionItem item; readonly ICompletionItem item;
@ -202,5 +203,11 @@ namespace ICSharpCode.AvalonEdit.AddIn
if (context.CompletionCharHandled && txea != null) if (context.CompletionCharHandled && txea != null)
txea.Handled = true; txea.Handled = true;
} }
// This is required to work around http://support.microsoft.com/kb/938416/en-us
event System.ComponentModel.PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged {
add { }
remove { }
}
} }
} }

8
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/SnippetManager.cs

@ -219,6 +219,14 @@ End If",
End While", End While",
Keyword = "While" Keyword = "While"
}, },
new CodeSnippet {
Name = "ctor",
Description = "Constructor",
Text = @"Public Sub New(${anchor:parameterList})
${refactoring:ctor}
End Sub",
Keyword = "Sub"
},
new CodeSnippet { new CodeSnippet {
Name = "Select", Name = "Select",
Description = "Select statement", Description = "Select statement",

7
src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core.UI/DisplayBinding/EDMDesignerViewContent.cs

@ -89,12 +89,7 @@ namespace ICSharpCode.Data.EDMDesigner.Core.UI.DisplayBinding
if (primaryFile == null) if (primaryFile == null)
throw new ArgumentNullException("primaryFile"); throw new ArgumentNullException("primaryFile");
try { primaryFile.ForceInitializeView(this); // call Load()
primaryFile.ForceInitializeView(this); // call Load()
} catch (WizardCancelledException) {
this.Files.Clear(); // unregister with OpenedFile
throw;
}
EDMDesignerChangeWatcher.AddEDMDesignerViewContent(this); EDMDesignerChangeWatcher.AddEDMDesignerViewContent(this);
} }

2
src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/Windows/EDMWizard/EDMWizardErrorUserControl.xaml

@ -9,6 +9,6 @@
</Grid.RowDefinitions> </Grid.RowDefinitions>
<TextBlock Margin="3">The following error(s) occured during generation of the Entity Data Model:</TextBlock> <TextBlock Margin="3">The following error(s) occured during generation of the Entity Data Model:</TextBlock>
<TextBox Grid.Row="1" Margin="3" Text="{Binding Path=Exception.FullMessage, ElementName=This, Mode=OneWay}" IsReadOnly="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" /> <TextBox Grid.Row="1" Margin="3" Text="{Binding Path=Exception, ElementName=This, Mode=OneWay}" IsReadOnly="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" />
</Grid> </Grid>
</data:WizardErrorUserControl> </data:WizardErrorUserControl>

2
src/AddIns/Misc/SharpRefactoring/Project/Src/Gui/InsertCtorDialog.xaml.cs

@ -80,7 +80,7 @@ namespace SharpRefactoring.Gui
new ThrowStatement( new ThrowStatement(
new ObjectCreateExpression( new ObjectCreateExpression(
new TypeReference("ArgumentOutOfRangeException"), new TypeReference("ArgumentOutOfRangeException"),
new List<Expression>() { new PrimitiveExpression(w.ParameterName, '"' + w.ParameterName + '"'), new IdentifierExpression(w.ParameterName), new BinaryOperatorExpression(new PrimitiveExpression("Value must be between "), BinaryOperatorType.Add, new BinaryOperatorExpression(new IdentifierExpression("lower"), BinaryOperatorType.Add, new BinaryOperatorExpression(new PrimitiveExpression(" and "), BinaryOperatorType.Add, new IdentifierExpression("upper")))) } new List<Expression>() { new PrimitiveExpression(w.ParameterName, '"' + w.ParameterName + '"'), new IdentifierExpression(w.ParameterName), new BinaryOperatorExpression(new PrimitiveExpression("Value must be between "), BinaryOperatorType.Concat, new BinaryOperatorExpression(new IdentifierExpression("lower"), BinaryOperatorType.Concat, new BinaryOperatorExpression(new PrimitiveExpression(" and "), BinaryOperatorType.Concat, new IdentifierExpression("upper")))) }
) )
) )
) )

7
src/AddIns/Misc/SharpRefactoring/Project/Src/InsertCtorSnippetRefactoring.cs

@ -70,14 +70,17 @@ namespace SharpRefactoring
{ {
int i = 0; int i = 0;
foreach (var f in sourceClass.Fields.Where(field => !field.IsConst && field.IsStatic == sourceClass.IsStatic)) { foreach (var f in sourceClass.Fields.Where(field => !field.IsConst
&& field.IsStatic == sourceClass.IsStatic
&& field.ReturnType != null)) {
yield return new PropertyOrFieldWrapper(f) { Index = i, IsSelected = true }; yield return new PropertyOrFieldWrapper(f) { Index = i, IsSelected = true };
i++; i++;
} }
foreach (var p in sourceClass.Properties.Where(prop => prop.CanSet && !prop.IsIndexer foreach (var p in sourceClass.Properties.Where(prop => prop.CanSet && !prop.IsIndexer
&& PropertyRefactoringMenuBuilder.IsAutomaticProperty(prop) && PropertyRefactoringMenuBuilder.IsAutomaticProperty(prop)
&& prop.IsStatic == sourceClass.IsStatic)) { && prop.IsStatic == sourceClass.IsStatic
&& prop.ReturnType != null)) {
yield return new PropertyOrFieldWrapper(p) { Index = i, IsSelected = true }; yield return new PropertyOrFieldWrapper(p) { Index = i, IsSelected = true };
i++; i++;
} }

25
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextDocument.cs

@ -4,6 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Globalization; using System.Globalization;
@ -21,7 +22,7 @@ namespace ICSharpCode.AvalonEdit.Document
/// <inheritdoc cref="VerifyAccess"/> /// <inheritdoc cref="VerifyAccess"/>
/// <para>However, there is a single method that is thread-safe: <see cref="CreateSnapshot()"/> (and its overloads).</para> /// <para>However, there is a single method that is thread-safe: <see cref="CreateSnapshot()"/> (and its overloads).</para>
/// </remarks> /// </remarks>
public sealed class TextDocument : ITextSource public sealed class TextDocument : ITextSource, INotifyPropertyChanged
{ {
#region Thread ownership #region Thread ownership
readonly object lockObject = new object(); readonly object lockObject = new object();
@ -207,8 +208,16 @@ namespace ICSharpCode.AvalonEdit.Document
/// Is raised when the TextLength property changes. /// Is raised when the TextLength property changes.
/// </summary> /// </summary>
/// <remarks><inheritdoc cref="Changing"/></remarks> /// <remarks><inheritdoc cref="Changing"/></remarks>
[Obsolete("This event will be removed in a future version; use the PropertyChanged event instead")]
public event EventHandler TextLengthChanged; public event EventHandler TextLengthChanged;
/// <summary>
/// Is raised when one of the properties <see cref="Text"/>, <see cref="TextLength"/>, <see cref="LineCount"/>,
/// <see cref="UndoStack"/> changes.
/// </summary>
/// <remarks><inheritdoc cref="Changing"/></remarks>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary> /// <summary>
/// Is raised before the document changes. /// Is raised before the document changes.
/// </summary> /// </summary>
@ -231,8 +240,7 @@ namespace ICSharpCode.AvalonEdit.Document
/// <item><description><b><see cref="EndUpdate">EndUpdate()</see></b></description> /// <item><description><b><see cref="EndUpdate">EndUpdate()</see></b></description>
/// <list type="bullet"> /// <list type="bullet">
/// <item><description><see cref="TextChanged"/> event is raised</description></item> /// <item><description><see cref="TextChanged"/> event is raised</description></item>
/// <item><description><see cref="TextLengthChanged"/> event is raised</description></item> /// <item><description><see cref="PropertyChanged"/> event is raised (for the Text, TextLength, LineCount properties, in that order)</description></item>
/// <item><description><see cref="LineCountChanged"/> event is raised</description></item>
/// <item><description>End of change group (on undo stack)</description></item> /// <item><description>End of change group (on undo stack)</description></item>
/// <item><description><see cref="UpdateFinished"/> event is raised</description></item> /// <item><description><see cref="UpdateFinished"/> event is raised</description></item>
/// </list></item> /// </list></item>
@ -418,21 +426,30 @@ namespace ICSharpCode.AvalonEdit.Document
fireTextChanged = false; fireTextChanged = false;
if (TextChanged != null) if (TextChanged != null)
TextChanged(this, EventArgs.Empty); TextChanged(this, EventArgs.Empty);
OnPropertyChanged("Text");
int textLength = rope.Length; int textLength = rope.Length;
if (textLength != oldTextLength) { if (textLength != oldTextLength) {
oldTextLength = textLength; oldTextLength = textLength;
if (TextLengthChanged != null) if (TextLengthChanged != null)
TextLengthChanged(this, EventArgs.Empty); TextLengthChanged(this, EventArgs.Empty);
OnPropertyChanged("TextLength");
} }
int lineCount = lineTree.LineCount; int lineCount = lineTree.LineCount;
if (lineCount != oldLineCount) { if (lineCount != oldLineCount) {
oldLineCount = lineCount; oldLineCount = lineCount;
if (LineCountChanged != null) if (LineCountChanged != null)
LineCountChanged(this, EventArgs.Empty); LineCountChanged(this, EventArgs.Empty);
OnPropertyChanged("LineCount");
} }
} }
} }
void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion #endregion
#region Insert / Remove / Replace #region Insert / Remove / Replace
@ -743,6 +760,7 @@ namespace ICSharpCode.AvalonEdit.Document
undoStack.ClearAll(); // first clear old undo stack, so that it can't be used to perform unexpected changes on this document undoStack.ClearAll(); // first clear old undo stack, so that it can't be used to perform unexpected changes on this document
// ClearAll() will also throw an exception when it's not safe to replace the undo stack (e.g. update is currently in progress) // ClearAll() will also throw an exception when it's not safe to replace the undo stack (e.g. update is currently in progress)
undoStack = value; undoStack = value;
OnPropertyChanged("UndoStack");
} }
} }
} }
@ -775,6 +793,7 @@ namespace ICSharpCode.AvalonEdit.Document
/// <summary> /// <summary>
/// Is raised when the LineCount property changes. /// Is raised when the LineCount property changes.
/// </summary> /// </summary>
[Obsolete("This event will be removed in a future version; use the PropertyChanged event instead")]
public event EventHandler LineCountChanged; public event EventHandler LineCountChanged;
#endregion #endregion

2
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextDocumentWeakEventManager.cs

@ -91,6 +91,7 @@ namespace ICSharpCode.AvalonEdit.Document
/// Weak event manager for the <see cref="TextDocument.LineCountChanged"/> event. /// Weak event manager for the <see cref="TextDocument.LineCountChanged"/> event.
/// </summary> /// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
[Obsolete("The TextDocument.LineCountChanged event will be removed in a future version. Use PropertyChangedEventManager instead.")]
public sealed class LineCountChanged : WeakEventManagerBase<LineCountChanged, TextDocument> public sealed class LineCountChanged : WeakEventManagerBase<LineCountChanged, TextDocument>
{ {
/// <inheritdoc/> /// <inheritdoc/>
@ -110,6 +111,7 @@ namespace ICSharpCode.AvalonEdit.Document
/// Weak event manager for the <see cref="TextDocument.TextLengthChanged"/> event. /// Weak event manager for the <see cref="TextDocument.TextLengthChanged"/> event.
/// </summary> /// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
[Obsolete("The TextDocument.TextLengthChanged event will be removed in a future version. Use PropertyChangedEventManager instead.")]
public sealed class TextLengthChanged : WeakEventManagerBase<TextLengthChanged, TextDocument> public sealed class TextLengthChanged : WeakEventManagerBase<TextLengthChanged, TextDocument>
{ {
/// <inheritdoc/> /// <inheritdoc/>

7
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/LineNumberMargin.cs

@ -2,6 +2,7 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System; using System;
using System.ComponentModel;
using System.Globalization; using System.Globalization;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
@ -89,11 +90,11 @@ namespace ICSharpCode.AvalonEdit.Editing
protected override void OnDocumentChanged(TextDocument oldDocument, TextDocument newDocument) protected override void OnDocumentChanged(TextDocument oldDocument, TextDocument newDocument)
{ {
if (oldDocument != null) { if (oldDocument != null) {
TextDocumentWeakEventManager.LineCountChanged.RemoveListener(oldDocument, this); PropertyChangedEventManager.RemoveListener(oldDocument, this, "LineCount");
} }
base.OnDocumentChanged(oldDocument, newDocument); base.OnDocumentChanged(oldDocument, newDocument);
if (newDocument != null) { if (newDocument != null) {
TextDocumentWeakEventManager.LineCountChanged.AddListener(newDocument, this); PropertyChangedEventManager.AddListener(newDocument, this, "LineCount");
} }
OnDocumentLineCountChanged(); OnDocumentLineCountChanged();
} }
@ -101,7 +102,7 @@ namespace ICSharpCode.AvalonEdit.Editing
/// <inheritdoc cref="IWeakEventListener.ReceiveWeakEvent"/> /// <inheritdoc cref="IWeakEventListener.ReceiveWeakEvent"/>
protected virtual bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e) protected virtual bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
{ {
if (managerType == typeof(TextDocumentWeakEventManager.LineCountChanged)) { if (managerType == typeof(PropertyChangedEventManager)) {
OnDocumentLineCountChanged(); OnDocumentLineCountChanged();
return true; return true;
} }

15
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs

@ -1739,12 +1739,21 @@ namespace ICSharpCode.AvalonEdit.Rendering
#endregion #endregion
/// <summary> /// <summary>
/// Collapses lines for the purpose of scrolling. This method is meant for /// Collapses lines for the purpose of scrolling. <see cref="DocumentLine"/>s marked as collapsed will be hidden
/// <see cref="VisualLineElementGenerator"/>s that cause <see cref="VisualLine"/>s to span /// and not used to start the generation of a <see cref="VisualLine"/>.
/// </summary>
/// <remarks>
/// This method is meant for <see cref="VisualLineElementGenerator"/>s that cause <see cref="VisualLine"/>s to span
/// multiple <see cref="DocumentLine"/>s. Do not call it without providing a corresponding /// multiple <see cref="DocumentLine"/>s. Do not call it without providing a corresponding
/// <see cref="VisualLineElementGenerator"/>. /// <see cref="VisualLineElementGenerator"/>.
/// If you want to create collapsible text sections, see <see cref="Folding.FoldingManager"/>. /// If you want to create collapsible text sections, see <see cref="Folding.FoldingManager"/>.
/// </summary> ///
/// Note that if you want a VisualLineElement to span from line N to line M, then you need to collapse only the lines
/// N+1 to M. Do not collapse line N itself.
///
/// When you no longer need the section to be collapsed, call <see cref="CollapsedLineSection.Uncollapse()"/> on the
/// <see cref="CollapsedLineSection"/> returned from this method.
/// </remarks>
public CollapsedLineSection CollapseLines(DocumentLine start, DocumentLine end) public CollapsedLineSection CollapseLines(DocumentLine start, DocumentLine end)
{ {
VerifyAccess(); VerifyAccess();

1
src/Libraries/NRefactory/Project/NRefactory.csproj

@ -155,6 +155,7 @@
<None Include="Src\Lexer\VBNet\ExpressionFinder.atg"> <None Include="Src\Lexer\VBNet\ExpressionFinder.atg">
<Generator>CocoParserGenerator</Generator> <Generator>CocoParserGenerator</Generator>
<CustomToolNamespace>ICSharpCode.NRefactory.Parser.VB</CustomToolNamespace> <CustomToolNamespace>ICSharpCode.NRefactory.Parser.VB</CustomToolNamespace>
<LastGenOutput>Parser.cs</LastGenOutput>
</None> </None>
<None Include="Src\Lexer\VBNet\PushParser.frame"> <None Include="Src\Lexer\VBNet\PushParser.frame">
<DependentUpon>ExpressionFinder.atg</DependentUpon> <DependentUpon>ExpressionFinder.atg</DependentUpon>

36
src/Libraries/NRefactory/Project/Src/Lexer/VBNet/ExpressionFinder.atg

@ -367,13 +367,13 @@ TypeOrMemberModifier =
InterfaceEvent = InterfaceEvent =
"Event" (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) Identifier (. PopContext(); .) "Event" (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) Identifier (. PopContext(); .)
[ "As" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) | "(" [ ParameterList ] ")" ] [ "As" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) | ParameterListInParenthesis ]
StatementTerminator StatementTerminator
. .
InterfaceProperty = InterfaceProperty =
"Property" (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) Identifier (. PopContext(); .) "Property" (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) Identifier (. PopContext(); .)
[ "(" [ ParameterList ] ")" ] [ "As" (. PushContext(Context.Type, la, t); .) { AttributeBlock } TypeName (. PopContext(); .) ] [ ParameterListInParenthesis ] [ "As" (. PushContext(Context.Type, la, t); .) { AttributeBlock } TypeName (. PopContext(); .) ]
StatementTerminator StatementTerminator
. .
@ -435,7 +435,7 @@ ExternalMemberDeclaration =
(. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) Identifier (. PopContext(); .) (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) Identifier (. PopContext(); .)
"Lib" LiteralString "Lib" LiteralString
[ "Alias" LiteralString ] [ "Alias" LiteralString ]
[ "(" [ ParameterList ] ")" ] [ ParameterListInParenthesis ]
[ "As" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) ] [ "As" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) ]
StatementTerminator StatementTerminator
. .
@ -443,10 +443,10 @@ ExternalMemberDeclaration =
EventMemberDeclaration = EventMemberDeclaration =
"Event" "Event"
(. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) Identifier (. PopContext(); .) (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) Identifier (. PopContext(); .)
( "As" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) | [ "(" [ ParameterList ] ")" ] ) ( "As" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) | [ ParameterListInParenthesis ] )
[ "Implements" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) /*"." IdentifierOrKeyword*/ [ "Implements" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) /*"." IdentifierOrKeyword*/
{ "," (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) /*"." IdentifierOrKeyword*/ } ] { "," (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) /*"." IdentifierOrKeyword*/ } ]
/* the TypeName production already allows the "." IdentifierOrKeyword syntax, so to avoid an ambiguous grammer we just leave that out */ /* the TypeName production already allows the "." IdentifierOrKeyword syntax, so to avoid an ambiguous grammar we just leave that out */
StatementTerminator StatementTerminator
. .
@ -463,8 +463,8 @@ CustomEventMemberDeclaration =
PropertyDeclaration = PropertyDeclaration =
"Property" "Property"
(. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) Identifier (. PopContext(); .) (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) Identifier (. PopContext(); .)
[ "(" [ ParameterList ] ")" ] [ ParameterListInParenthesis ]
[ "As" { AttributeBlock } ( NewExpression | (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) ) ] [ "As" (. PushContext(Context.Type, la, t); .) { AttributeBlock } ( NewExpression | TypeName ) (. PopContext(); .) ]
[ "Implements" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) /*"." IdentifierOrKeyword*/ [ "Implements" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) /*"." IdentifierOrKeyword*/
{ "," (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) /*"." IdentifierOrKeyword*/ } ] { "," (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) /*"." IdentifierOrKeyword*/ } ]
[ "=" Expression ] StatementTerminator [ "=" Expression ] StatementTerminator
@ -474,10 +474,10 @@ PropertyDeclaration =
// so we need to simulate it // so we need to simulate it
(.OnEachPossiblePath: SetIdentifierExpected(la); .) } (.OnEachPossiblePath: SetIdentifierExpected(la); .) }
[ (. PushContext(Context.Member, la, t); .) [ (. PushContext(Context.Member, la, t); .)
( "Get" | "Set" ) [ "(" [ ParameterList ] ")" ] ( "Get" | "Set" ) [ ParameterListInParenthesis ]
StatementTerminatorAndBlock StatementTerminatorAndBlock
"End" ( "Get" | "Set" ) StatementTerminator "End" ( "Get" | "Set" ) StatementTerminator
[ { AttributeBlock } { AccessModifier } ( "Get" | "Set" ) [ "(" [ ParameterList ] ")" ] [ { AttributeBlock } { AccessModifier } ( "Get" | "Set" ) [ ParameterListInParenthesis ]
StatementTerminatorAndBlock StatementTerminatorAndBlock
"End" ( "Get" | "Set" ) StatementTerminator ] "End" ( "Get" | "Set" ) StatementTerminator ]
@ -686,15 +686,19 @@ LambdaExpression =
. .
SubLambdaExpression = SubLambdaExpression =
"Sub" "(" [ ParameterList ] ")" "Sub" ParameterListInParenthesis
( GREEDY Statement | StatementTerminatorAndBlock "End" "Sub" ) ( GREEDY Statement | StatementTerminatorAndBlock "End" "Sub" )
. .
FunctionLambdaExpression = FunctionLambdaExpression =
"Function" "(" [ ParameterList ] ")" "Function" ParameterListInParenthesis
( GREEDY Expression | [ "As" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) ] StatementTerminatorAndBlock "End" "Function" ) ( GREEDY Expression | [ "As" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) ] StatementTerminatorAndBlock "End" "Function" )
. .
ParameterListInParenthesis =
"(" (. PushContext(Context.Default, la, t); .) [ ParameterList ] (. PopContext(); .) ")"
.
QueryExpression QueryExpression
(. PushContext(Context.Query, la, t); .) (. PushContext(Context.Query, la, t); .)
= =
@ -848,7 +852,7 @@ PrimitiveTypeName =
TypeName = ( "Global" | Identifier | PrimitiveTypeName | "?" /* used for ? = completion */ ) { TypeSuffix } { "." IdentifierOrKeyword { TypeSuffix } } . TypeName = ( "Global" | Identifier | PrimitiveTypeName | "?" /* used for ? = completion */ ) { TypeSuffix } { "." IdentifierOrKeyword { TypeSuffix } } .
TypeSuffix = "(" ( "Of" [ TypeName ] { "," [ TypeName ] } | [ ArgumentList ] ) ")" . TypeSuffix = "(" (. PushContext(Context.Expression, la, t); .) ( "Of" [ (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) ] { "," [ (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) ] } | [ ArgumentList ] ) (. PopContext(); .) ")" .
IdentifierOrKeyword = ident IdentifierOrKeyword = ident
| "AddHandler" | "AddHandler"
@ -1076,12 +1080,14 @@ VariableDeclarationStatement =
( "Dim" | "Static" | "Const" ) ( "Dim" | "Static" | "Const" )
(. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .)
Identifier (. PopContext(); .) [ "?" ] { "(" [ Expression ] { "," [ Expression ] } ")" } Identifier (. PopContext(); .) [ "?" ] { "(" [ Expression ] { "," [ Expression ] } ")" }
[ "As" (. PushContext(Context.Type, la, t); .) ( NewExpression | TypeName ) (. PopContext(); .) ]
[ "=" Expression ]
{ "," { ","
(. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .)
Identifier (. PopContext(); .) [ "?" ] { "(" [ Expression ] { "," [ Expression ] } ")" } Identifier (. PopContext(); .) [ "?" ] { "(" [ Expression ] { "," [ Expression ] } ")" }
[ "As" (. PushContext(Context.Type, la, t); .) ( NewExpression | TypeName ) (. PopContext(); .) ]
[ "=" Expression ]
} }
[ "As" (. PushContext(Context.Type, la, t); .) ( NewExpression | TypeName ) (. PopContext(); .) ]
[ "=" Expression ]
. .
WithOrLockStatement = WithOrLockStatement =
@ -1093,7 +1099,7 @@ AddOrRemoveHandlerStatement =
. .
RaiseEventStatement = RaiseEventStatement =
"RaiseEvent" IdentifierOrKeyword [ "(" [ ArgumentList ] ")" ] "RaiseEvent" IdentifierOrKeyword [ "(" (. PushContext(Context.Expression, la, t); .) [ ArgumentList ] (. PopContext(); .) ")" ]
. .
IfStatement = IfStatement =

16
src/Libraries/NRefactory/Project/Src/Lexer/VBNet/ExpressionFinder.cs

@ -25,14 +25,14 @@ namespace ICSharpCode.NRefactory.Parser.VB
} }
} }
void PushContext(Context context, Token la, Token t) void PushContext(Context context, Token la, Token t)
{ {
string indent = new string('\t', stack.Count); string indent = new string('\t', stack.Count);
Location l = la == null ? (t == null ? Location.Empty : t.EndLocation) : la.Location; Location l = la == null ? (t == null ? Location.Empty : t.EndLocation) : la.Location;
stack.Push(new Block() { context = context, lastExpressionStart = l }); stack.Push(new Block() { context = context, lastExpressionStart = l });
Print(indent + "enter " + context); Print(indent + "enter " + context);
} }
public ExpressionFinder(ExpressionFinderState state) public ExpressionFinder(ExpressionFinderState state)
{ {

5329
src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Parser.cs

File diff suppressed because it is too large Load Diff

1246
src/Libraries/NRefactory/Project/Src/Parser/VBNet/Parser.cs

File diff suppressed because it is too large Load Diff

8
src/Libraries/NRefactory/Project/Src/Parser/VBNet/VBNET.ATG

@ -2232,12 +2232,14 @@ SubLambdaExpression<out LambdaExpression lambda>
(. (.
lambda.ExpressionBody = inner; lambda.ExpressionBody = inner;
lambda.EndLocation = t.EndLocation; // la.Location? lambda.EndLocation = t.EndLocation; // la.Location?
lambda.ExtendedEndLocation = la.Location;
.) .)
| |
EmbeddedStatement<out statement> EmbeddedStatement<out statement>
(. (.
lambda.StatementBody = statement; lambda.StatementBody = statement;
lambda.EndLocation = t.EndLocation; lambda.EndLocation = t.EndLocation;
lambda.ExtendedEndLocation = la.Location;
.) .)
) )
| |
@ -2247,6 +2249,7 @@ SubLambdaExpression<out LambdaExpression lambda>
(. (.
lambda.StatementBody = statement; lambda.StatementBody = statement;
lambda.EndLocation = t.EndLocation; lambda.EndLocation = t.EndLocation;
lambda.ExtendedEndLocation = la.Location;
.) .)
) )
. .
@ -2267,13 +2270,15 @@ FunctionLambdaExpression<out LambdaExpression lambda>
Expr<out inner> Expr<out inner>
(. (.
lambda.ExpressionBody = inner; lambda.ExpressionBody = inner;
lambda.EndLocation = t.EndLocation; // la.Location? lambda.EndLocation = t.EndLocation;
lambda.ExtendedEndLocation = la.Location;
.) .)
| |
EmbeddedStatement<out statement> EmbeddedStatement<out statement>
(. (.
lambda.StatementBody = statement; lambda.StatementBody = statement;
lambda.EndLocation = t.EndLocation; lambda.EndLocation = t.EndLocation;
lambda.ExtendedEndLocation = la.Location;
.) .)
) )
| |
@ -2283,6 +2288,7 @@ FunctionLambdaExpression<out LambdaExpression lambda>
(. (.
lambda.StatementBody = statement; lambda.StatementBody = statement;
lambda.EndLocation = t.EndLocation; lambda.EndLocation = t.EndLocation;
lambda.ExtendedEndLocation = la.Location;
.) .)
) )
. .

6
src/Libraries/NRefactory/Test/Lexer/VBNet/LexerContextTests.cs

@ -483,12 +483,14 @@ End Module",
enter Expression enter Expression
enter Expression enter Expression
enter Expression enter Expression
enter Expression
exit Expression
exit Expression exit Expression
exit Expression exit Expression
exit Expression
enter Expression
enter Expression enter Expression
enter Expression enter Expression
enter Expression
exit Expression
exit Expression exit Expression
exit Expression exit Expression
exit Expression exit Expression

5
src/Main/Base/Project/Src/Gui/Dialogs/SharpDevelopAboutPanels.cs

@ -80,6 +80,11 @@ namespace ICSharpCode.SharpDevelop.Gui
#if DEBUG #if DEBUG
if (e.KeyData == (Keys.Control | Keys.Shift | Keys.E)) { if (e.KeyData == (Keys.Control | Keys.Shift | Keys.E)) {
throw new ClownFishException(); throw new ClownFishException();
} else if (e.KeyData == (Keys.Control | Keys.Shift | Keys.G)) {
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
versionInfoTextBox.Text = GetVersionInformationString();
} }
#endif #endif
} }

30
src/Main/Base/Test/VBExpressionFinderTests.cs

@ -635,6 +635,36 @@ End Module", "FileReader()", ExpressionContext.ObjectCreation);
End Module", "FileReader()", ExpressionContext.Default); End Module", "FileReader()", ExpressionContext.Default);
} }
[Test]
public void FunctionLambda()
{
FindFull(@"Module Test
Sub Main()
Dim f = Fun|ction(x, y) x + y
End Sub
End Module", "Function(x, y) x + y", ExpressionContext.Default);
}
[Test]
public void SubLambda()
{
FindFull(@"Module Test
Sub Main()
Dim f = Su|b(x, y) Console.WriteLine(x + y)
End Sub
End Module", "Sub(x, y) Console.WriteLine(x + y)", ExpressionContext.Default);
}
[Test]
public void NewExpression()
{
FindFull(@"Module Test
Sub Main()
Dim list = N|ew List(Of Integer)
End Sub
End Module", "New List(Of Integer)", ExpressionContext.Default);
}
#region Old Tests #region Old Tests
void OldTest(string expr, int offset) void OldTest(string expr, int offset)
{ {

1
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs

@ -87,6 +87,7 @@ namespace ICSharpCode.SharpDevelop.Dom
//Dictionary<IMember, IMember> overrideDict = new Dictionary<IMember, IMember>(); //Dictionary<IMember, IMember> overrideDict = new Dictionary<IMember, IMember>();
ParameterListComparer parameterListComparer = new ParameterListComparer(); ParameterListComparer parameterListComparer = new ParameterListComparer();
parameterListComparer.UseCachedHashes = true;
HashSet<IMethod> handledMethods = new HashSet<IMethod>(parameterListComparer); HashSet<IMethod> handledMethods = new HashSet<IMethod>(parameterListComparer);
Dictionary<IMethod, IMethod> overrideMethodDict = new Dictionary<IMethod, IMethod>(parameterListComparer); Dictionary<IMethod, IMethod> overrideMethodDict = new Dictionary<IMethod, IMethod>(parameterListComparer);
IMember nonMethodOverride = null; IMember nonMethodOverride = null;

33
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ParameterListComparer.cs

@ -10,10 +10,32 @@ namespace ICSharpCode.SharpDevelop.Dom
{ {
public class ParameterListComparer : IEqualityComparer<IMethod> public class ParameterListComparer : IEqualityComparer<IMethod>
{ {
Dictionary<IMethod, int> cachedHashes;
/// <summary>
/// Gets/Sets whether to cache hashcodes. This can improve performance for
/// algorithms that repeatedly request the hash of a parameter list.
/// </summary>
/// <remarks>
/// This class is thread-safe only when not using cached hashes.
/// Also, cached hashes may cause a memory leak when the ParameterListComparer
/// instance is kept alive.
/// </remarks>
public bool UseCachedHashes {
get {
return cachedHashes != null;
}
set {
cachedHashes = value ? new Dictionary<IMethod, int>() : null;
}
}
public bool Equals(IMethod x, IMethod y) public bool Equals(IMethod x, IMethod y)
{ {
if (GetHashCode(x) != GetHashCode(y)) if (cachedHashes != null) {
return false; if (GetHashCode(x) != GetHashCode(y))
return false;
}
var paramsX = x.Parameters; var paramsX = x.Parameters;
var paramsY = y.Parameters; var paramsY = y.Parameters;
if (paramsX.Count != paramsY.Count) if (paramsX.Count != paramsY.Count)
@ -31,12 +53,10 @@ namespace ICSharpCode.SharpDevelop.Dom
return true; return true;
} }
Dictionary<IMethod, int> cachedHashes = new Dictionary<IMethod, int>();
public int GetHashCode(IMethod obj) public int GetHashCode(IMethod obj)
{ {
int hashCode; int hashCode;
if (cachedHashes.TryGetValue(obj, out hashCode)) if (cachedHashes != null && cachedHashes.TryGetValue(obj, out hashCode))
return hashCode; return hashCode;
hashCode = obj.TypeParameters.Count; hashCode = obj.TypeParameters.Count;
unchecked { unchecked {
@ -49,7 +69,8 @@ namespace ICSharpCode.SharpDevelop.Dom
} }
} }
} }
cachedHashes[obj] = hashCode; if (cachedHashes != null)
cachedHashes[obj] = hashCode;
return hashCode; return hashCode;
} }
} }

Loading…
Cancel
Save