Browse Source

Update to NRefactory version aa289c2.

aa289c2 Fix potential NullReferenceException in OperatorIsCanBeUsedIssue.
9db72dc Fix icsharpcode/NRefactory#377 - NullReferenceException in NullAnalysisVisitor
db2c7b6 Add IAstVisitor.VisitNullNode().
95141c8 Fix ICompilation.Import(ISymbol) for namespaces in extern alias.
c05dbd0 Handle errors if the XML file changes between the XmlDocumentationProvider ctor call and the GetDocumentation call.
e763376 Fixed bug in FunctionNeverReturnsIssue.
168b76f Formatting options change: blank lines are now >minimum< blank lines. TODO: Add options for maximum blank lines to preserve.
fde2a06 Fixed bug in 'XmlDocIssue'.
1403af7 Added 'CS1105ExtensionMethodMustBeDeclaredStaticAction'.
acca096 Merge pull request icsharpcode/NRefactory#381 from mono-soc-2013/MateY-IndentEngine
505c974 Issue with preprocessor directives.
4730eca Added some indenting unit tests.
412b324 Fixed possible parser bug.
989abdd Fixed completion bug.
3582f57 Fixed bug in StaticEventSubscriptionIssue
bbe2d12 Merge pull request icsharpcode/NRefactory#380 from Therzok/patch-2
43b42c5 Merge pull request icsharpcode/NRefactory#379 from Therzok/patch-1
02278d8 Fix typo in documentation
f08bcdb Add StaticEventSubscription static check test
084d2de StaticEventSubscriptionIssue - Check if static
b7ab0b1 Implemented StaticEventSubscriptionIssue
aa291c5 Fixed construct fixer tests.
dd6db96 Fixed unit test bug.
6899688 Fixed constructfixer tests on windows.
3d42715 Improved display location for 'RedundantBoolCompareIssue'.
c1b8ab5 Removed IndentStateFactory. (Creating the classes direcly is a magnitude faster)
e7b490e Optimized IsNewLine method.
d95fdc2 Added some optimizations to the indent engine.
313235e Speed up indentation engine
540af30 Fixed indentation bug.
7db77a4 Added some more construct fix cases. Unfortunately the parser error recovery isn't good enough for implementing that feature.
bd6d6f1 Added c# ConstructFixer.
pull/375/head
Daniel Grunwald 12 years ago
parent
commit
69ce7df7b7
  1. 2
      src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin
  2. 57
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CS1105ExtensionMethodMustBeDeclaredStaticAction.cs
  3. 147
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Custom/StaticEventSubscriptionIssue.cs
  4. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Custom/XmlDocIssue.cs
  5. 10
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Synced/CodeQuality/FunctionNeverReturnsIssue.cs
  6. 23
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Synced/CodeQuality/OperatorIsCanBeUsedIssue.cs
  7. 15
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Synced/RedundanciesInCode/RedundantBoolCompareIssue.cs
  8. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/ICSharpCode.NRefactory.CSharp.Refactoring.csproj
  9. 12
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Analysis/NullValueAnalysis.cs
  10. 5
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/AstNode.cs
  11. 5
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/AstType.cs
  12. 7
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/CSharpTokenNode.cs
  13. 26
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/DepthFirstAstVisitor.cs
  14. 5
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ArrayInitializerExpression.cs
  15. 5
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/Expression.cs
  16. 9
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/QueryExpression.cs
  17. 3
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/IAstVisitor.cs
  18. 5
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Identifier.cs
  19. 4
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/ObservableAstVisitor.cs
  20. 5
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/SimpleType.cs
  21. 9
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Statements/BlockStatement.cs
  22. 9
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Statements/Statement.cs
  23. 5
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Statements/TryCatchStatement.cs
  24. 5
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/Accessor.cs
  25. 7
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/ConstructorDeclaration.cs
  26. 7
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/VariableInitializer.cs
  27. 20
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs
  28. 18
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/CSharpFormattingOptions.cs
  29. 514
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/ConstructFixer.cs
  30. 36
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/FormattingOptionsFactory.cs
  31. 33
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/FormattingVisitor.cs
  32. 38
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/FormattingVisitor_Global.cs
  33. 4
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/Indent.cs
  34. 12
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
  35. 52
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/IndentEngine/CSharpIndentEngine.cs
  36. 304
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/IndentEngine/IndentState.cs
  37. 7
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs
  38. 5
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs
  39. 13
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-tokenizer.cs
  40. 10
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/ecore.cs
  41. 3
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs
  42. 7
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs
  43. 201
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Util/CloneableStack.cs
  44. 52
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/AstStructureTests.cs
  45. 4
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CSharpOutputVisitorTests.cs
  46. 8
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/AddUsing/AddUsingActionInsideNamespaceTests.cs
  47. 4
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/AddUsing/AddUsingRunActionTests.cs
  48. 83
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/CS1105ExtensionMethodMustBeDeclaredStaticActionTests.cs
  49. 37
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs
  50. 21
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/FunctionNeverReturnsIssueTests.cs
  51. 173
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/StaticEventSubscriptionIssueTests.cs
  52. 18
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/XmlDocIssueIssueTests.cs
  53. 665
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/ConstructFixerTests.cs
  54. 116
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TestBlankLineFormatting.cs
  55. 23
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TestGlobalLevelFormatting.cs
  56. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TestWrapping.cs
  57. 3
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj
  58. 104
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/IndentationTests/BlockTest.cs
  59. 60
      src/Libraries/NRefactory/ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs
  60. 9
      src/Libraries/NRefactory/ICSharpCode.NRefactory/Editor/UnicodeNewline.cs
  61. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory/Semantics/SizeOfResolveResult.cs
  62. 11
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/TypeSystemExtensions.cs

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

@ -339,6 +339,7 @@ @@ -339,6 +339,7 @@
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.SimplifyConditionalTernaryExpressionIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.SimplifyLinqExpressionIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.StaticConstructorParameterIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.StaticEventSubscriptionIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.StaticFieldInGenericTypeIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.StringCompareIsCultureSpecificIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.StringCompareToIsCultureSpecificIssue" />
@ -428,6 +429,7 @@ @@ -428,6 +429,7 @@
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateOverloadWithoutParameterAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreatePropertyAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.CS1520MethodMustHaveAReturnTypeAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.CS1105ExtensionMethodMustBeDeclaredStaticAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.DeclareLocalVariableAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ExtensionMethodInvocationToStaticMethodInvocationAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ExtractAnonymousMethodAction" />

57
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CS1105ExtensionMethodMustBeDeclaredStaticAction.cs

@ -0,0 +1,57 @@ @@ -0,0 +1,57 @@
//
// CS1105ExtensionMethodMustBeDeclaredStaticAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.TypeSystem;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Extension methods must be declared static")]
public class CS1105ExtensionMethodMustBeDeclaredStaticAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var method = context.GetNode<MethodDeclaration>();
if (method == null || !method.NameToken.Contains(context.Location))
yield break;
if (method.HasModifier(Modifiers.Static))
yield break;
var param = method.Parameters.FirstOrDefault();
if (param == null || param.ParameterModifier != ParameterModifier.This)
yield break;
yield return new CodeAction(
context.TranslateString("Convert method to static"),
script => script.ChangeModifier(method, method.Modifiers | Modifiers.Static),
method) {
Severity = ICSharpCode.NRefactory.Refactoring.Severity.Error
};
}
}
}

147
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Custom/StaticEventSubscriptionIssue.cs

@ -0,0 +1,147 @@ @@ -0,0 +1,147 @@
//
// StaticEventSubscriptionIssue.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.PatternMatching;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Refactoring;
using Mono.CSharp;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.CSharp.Resolver;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[IssueDescription("Static event removal check",
Description = "Checks if static events are removed",
Category = IssueCategories.CodeQualityIssues,
Severity = Severity.Warning)]
public class StaticEventSubscriptionIssue : GatherVisitorCodeIssueProvider
{
protected override IGatherVisitor CreateVisitor(BaseRefactoringContext context)
{
return new GatherVisitor(context);
}
class GatherVisitor : GatherVisitorBase<StaticEventSubscriptionIssue>
{
public GatherVisitor (BaseRefactoringContext ctx) : base (ctx)
{
}
public override void VisitSyntaxTree(SyntaxTree syntaxTree)
{
base.VisitSyntaxTree(syntaxTree);
foreach (var assignedEvent in assignedEvents) {
addedEvents.Remove(assignedEvent);
}
foreach (var hs in removedEvents) {
HashSet<Tuple<IMember, AssignmentExpression>> h;
if (!addedEvents.TryGetValue(hs.Key, out h))
continue;
foreach (var evt in hs.Value) {
restart:
foreach (var m in h) {
if (m.Item1 == evt) {
h.Remove(m);
goto restart;
}
}
}
}
foreach (var added in addedEvents) {
foreach (var usage in added.Value) {
AddIssue(new CodeIssue(usage.Item2.OperatorToken,
ctx.TranslateString("Subscription to static events without unsubscription may cause memory leaks.")));
}
}
}
public override void VisitMethodDeclaration(MethodDeclaration methodDeclaration)
{
if (methodDeclaration.HasModifier(Modifiers.Static))
return;
base.VisitMethodDeclaration(methodDeclaration);
}
public override void VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration)
{
if (constructorDeclaration.HasModifier(Modifiers.Static))
return;
base.VisitConstructorDeclaration(constructorDeclaration);
}
readonly Dictionary<IMember, HashSet<Tuple<IMember, AssignmentExpression>>> addedEvents = new Dictionary<IMember, HashSet<Tuple<IMember, AssignmentExpression>>>();
readonly Dictionary<IMember, HashSet<IMember>> removedEvents = new Dictionary<IMember, HashSet<IMember>>();
readonly HashSet<IMember> assignedEvents = new HashSet<IMember> ();
public override void VisitAssignmentExpression(AssignmentExpression assignmentExpression)
{
base.VisitAssignmentExpression(assignmentExpression);
if (assignmentExpression.Operator == AssignmentOperatorType.Add) {
var left = ctx.Resolve(assignmentExpression.Left) as MemberResolveResult;
if (left == null || left.Member.SymbolKind != SymbolKind.Event || !left.Member.IsStatic)
return;
if (assignmentExpression.Right is AnonymousMethodExpression || assignmentExpression.Right is LambdaExpression) {
AddIssue(new CodeIssue(assignmentExpression.OperatorToken,
ctx.TranslateString("Subscription to static events with an anonymous method may cause memory leaks.")));
}
var right = ctx.Resolve(assignmentExpression.Right) as MethodGroupResolveResult;
if (right == null || right.Methods.Count() != 1)
return;
HashSet<Tuple<IMember, AssignmentExpression>> hs;
if (!addedEvents.TryGetValue(left.Member, out hs))
addedEvents[left.Member] = hs = new HashSet<Tuple<IMember, AssignmentExpression>>();
hs.Add(Tuple.Create((IMember)right.Methods.First(), assignmentExpression));
} else if (assignmentExpression.Operator == AssignmentOperatorType.Subtract) {
var left = ctx.Resolve(assignmentExpression.Left) as MemberResolveResult;
if (left == null || left.Member.SymbolKind != SymbolKind.Event || !left.Member.IsStatic)
return;
var right = ctx.Resolve(assignmentExpression.Right) as MethodGroupResolveResult;
if (right == null || right.Methods.Count() != 1)
return;
HashSet<IMember> hs;
if (!removedEvents.TryGetValue(left.Member, out hs))
removedEvents[left.Member] = hs = new HashSet<IMember>();
hs.Add(right.Methods.First());
} else if (assignmentExpression.Operator == AssignmentOperatorType.Assign) {
var left = ctx.Resolve(assignmentExpression.Left) as MemberResolveResult;
if (left == null || left.Member.SymbolKind != SymbolKind.Event || !left.Member.IsStatic)
return;
assignedEvents.Add(left.Member);
}
}
}
}
}

2
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Custom/XmlDocIssue.cs

@ -183,6 +183,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -183,6 +183,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var m = member as IParameterizedMember;
if (m != null && m.Parameters.Any(p => p.Name == name.Value))
break;
if (name.Value == "value" && (member.SymbolKind == SymbolKind.Property || member.SymbolKind == SymbolKind.Indexer || member.SymbolKind == SymbolKind.Event) && el.Name == "paramref")
break;
AddXmlIssue(name.ValueSegment.Offset - firstline.Length + 1, name.ValueSegment.Length - 2, string.Format(ctx.TranslateString("Parameter '{0}' not found"), name.Value));
break;
case "exception":

10
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Synced/CodeQuality/FunctionNeverReturnsIssue.cs

@ -152,6 +152,16 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -152,6 +152,16 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return base.VisitAssignmentExpression(assignmentExpression);
}
public override bool VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression)
{
return false;
}
public override bool VisitLambdaExpression(LambdaExpression lambdaExpression)
{
return false;
}
public override bool VisitIdentifierExpression(IdentifierExpression identifierExpression)
{
return CheckRecursion(identifierExpression);

23
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Synced/CodeQuality/OperatorIsCanBeUsedIssue.cs

@ -24,6 +24,7 @@ @@ -24,6 +24,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.using System;
using System.Linq;
using ICSharpCode.NRefactory.PatternMatching;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Semantics;
@ -64,25 +65,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -64,25 +65,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (!m.Success)
return;
Expression identifier = null;
AstType type = null;
if (binaryOperatorExpression.Left is TypeOfExpression && binaryOperatorExpression.Right is InvocationExpression) {
type = (binaryOperatorExpression.Left as TypeOfExpression).Type;
var right = binaryOperatorExpression.Right as InvocationExpression;
identifier = (right.Target as MemberReferenceExpression).Target;
} else if (binaryOperatorExpression.Right is TypeOfExpression && binaryOperatorExpression.Left is InvocationExpression) {
type = (binaryOperatorExpression.Right as TypeOfExpression).Type;
var left = binaryOperatorExpression.Left as InvocationExpression;
identifier = (left.Target as MemberReferenceExpression).Target;
} else
return;
if (identifier == null || type == null)
Expression identifier = m.Get<Expression>("a").Single();
AstType type = m.Get<AstType>("b").Single();
var typeResolved = ctx.Resolve(type) as TypeResolveResult;
if (typeResolved == null)
return;
var typeResolved = ctx.Resolve(type) as TypeResolveResult;
if (typeResolved.Type.Kind == TypeKind.Class) {
if (!typeResolved.Type.GetDefinition().IsSealed) {
return;

15
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Synced/RedundanciesInCode/RedundantBoolCompareIssue.cs

@ -77,9 +77,20 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -77,9 +77,20 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (exprType == null || exprType.KnownTypeCode != KnownTypeCode.Boolean)
return;
var boolConstant = (bool)match.Get<PrimitiveExpression> ("const").First ().Value;
var boolExpr = match.Get<PrimitiveExpression>("const").First();
var boolConstant = (bool)boolExpr.Value;
TextLocation start, end;
if (boolExpr == binaryOperatorExpression.Left) {
start = binaryOperatorExpression.StartLocation;
end = binaryOperatorExpression.OperatorToken.EndLocation;
} else {
start = binaryOperatorExpression.OperatorToken.StartLocation;
end = binaryOperatorExpression.EndLocation;
}
AddIssue (new CodeIssue(
binaryOperatorExpression,
start, end,
boolConstant ? ctx.TranslateString ("Comparison with 'true' is redundant") : ctx.TranslateString ("Comparison with 'false' is redundant"),
ctx.TranslateString ("Remove redundant comparison"),
script => {

2
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/ICSharpCode.NRefactory.CSharp.Refactoring.csproj

@ -426,6 +426,8 @@ @@ -426,6 +426,8 @@
<Compile Include="CodeIssues\Uncategorized\RedundantNotNullAttributeInNonNullableTypeIssue.cs" />
<Compile Include="CodeIssues\Custom\CompilerErrors\CS0618UsageOfObsoleteMemberIssue.cs" />
<Compile Include="CodeIssues\Custom\CompilerErrors\CS0169FieldIsNeverUsedIssue.cs" />
<Compile Include="CodeIssues\Custom\StaticEventSubscriptionIssue.cs" />
<Compile Include="CodeActions\CS1105ExtensionMethodMustBeDeclaredStaticAction.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>

12
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Analysis/NullValueAnalysis.cs

@ -776,6 +776,18 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -776,6 +776,18 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
this.analysis = analysis;
}
protected override VisitorResult VisitChildren(AstNode node, VariableStatusInfo data)
{
Debug.Fail("Missing override for " + node.GetType().Name);
return VisitorResult.ForValue(data, NullValueStatus.Unknown);
}
public override VisitorResult VisitNullNode(AstNode nullNode, VariableStatusInfo data)
{
// can occur due to syntax errors
return VisitorResult.ForValue(data, NullValueStatus.Unknown);
}
public override VisitorResult VisitEmptyStatement(EmptyStatement emptyStatement, VariableStatusInfo data)
{
return VisitorResult.ForValue(data, NullValueStatus.Unknown);

5
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/AstNode.cs

@ -59,16 +59,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -59,16 +59,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch (AstNode other, PatternMatching.Match match)

5
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/AstType.cs

@ -41,16 +41,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -41,16 +41,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)

7
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/CSharpTokenNode.cs

@ -50,16 +50,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -50,16 +50,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)

26
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/DepthFirstAstVisitor.cs

@ -44,6 +44,14 @@ namespace ICSharpCode.NRefactory.CSharp @@ -44,6 +44,14 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
public virtual void VisitNullNode(AstNode nullNode)
{
// Should we call VisitChildren here?
// We usually want to ignore null nodes.
// Older NR versions (before VisitNullNode was introduced) didn't call VisitChildren() with null nodes;
// so changing this might break VisitChildren() overrides that expect the node to be part of the AST.
}
public virtual void VisitSyntaxTree (SyntaxTree syntaxTree)
{
VisitChildren (syntaxTree);
@ -637,6 +645,15 @@ namespace ICSharpCode.NRefactory.CSharp @@ -637,6 +645,15 @@ namespace ICSharpCode.NRefactory.CSharp
return default (T);
}
public virtual T VisitNullNode(AstNode nullNode)
{
// Should we call VisitChildren here?
// We usually want to ignore null nodes.
// Older NR versions (before VisitNullNode was introduced) didn't call VisitChildren() with null nodes;
// so changing this might break VisitChildren() overrides that expect the node to be part of the AST.
return default (T);
}
public virtual T VisitSyntaxTree (SyntaxTree unit)
{
return VisitChildren (unit);
@ -1230,6 +1247,15 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1230,6 +1247,15 @@ namespace ICSharpCode.NRefactory.CSharp
return default (S);
}
public virtual S VisitNullNode(AstNode nullNode, T data)
{
// Should we call VisitChildren here?
// We usually want to ignore null nodes.
// Older NR versions (before VisitNullNode was introduced) didn't call VisitChildren() with null nodes;
// so changing this might break VisitChildren() overrides that expect the node to be part of the AST.
return default (S);
}
public virtual S VisitSyntaxTree (SyntaxTree unit, T data)
{
return VisitChildren (unit, data);

5
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ArrayInitializerExpression.cs

@ -72,16 +72,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -72,16 +72,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)

5
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/Expression.cs

@ -43,16 +43,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -43,16 +43,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)

9
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/QueryExpression.cs

@ -38,16 +38,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -38,16 +38,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)

3
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/IAstVisitor.cs

@ -147,6 +147,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -147,6 +147,7 @@ namespace ICSharpCode.NRefactory.CSharp
void VisitCSharpTokenNode(CSharpTokenNode cSharpTokenNode);
void VisitIdentifier(Identifier identifier);
void VisitNullNode(AstNode nullNode);
void VisitPatternPlaceholder(AstNode placeholder, PatternMatching.Pattern pattern);
}
@ -277,6 +278,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -277,6 +278,7 @@ namespace ICSharpCode.NRefactory.CSharp
S VisitCSharpTokenNode(CSharpTokenNode cSharpTokenNode);
S VisitIdentifier(Identifier identifier);
S VisitNullNode(AstNode nullNode);
S VisitPatternPlaceholder(AstNode placeholder, PatternMatching.Pattern pattern);
}
@ -407,6 +409,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -407,6 +409,7 @@ namespace ICSharpCode.NRefactory.CSharp
S VisitCSharpTokenNode(CSharpTokenNode cSharpTokenNode, T data);
S VisitIdentifier(Identifier identifier, T data);
S VisitNullNode(AstNode nullNode, T data);
S VisitPatternPlaceholder(AstNode placeholder, PatternMatching.Pattern pattern, T data);
}
}

5
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Identifier.cs

@ -41,16 +41,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -41,16 +41,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)

4
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/ObservableAstVisitor.cs

@ -44,6 +44,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -44,6 +44,10 @@ namespace ICSharpCode.NRefactory.CSharp
if (leave != null)
leave(node);
}
void IAstVisitor.VisitNullNode(AstNode nullNode)
{
}
public event Action<SyntaxTree> EnterSyntaxTree, LeaveSyntaxTree;

5
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/SimpleType.cs

@ -49,16 +49,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -49,16 +49,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)

9
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Statements/BlockStatement.cs

@ -47,16 +47,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -47,16 +47,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)

9
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Statements/Statement.cs

@ -42,16 +42,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -42,16 +42,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)

5
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Statements/TryCatchStatement.cs

@ -104,16 +104,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -104,16 +104,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)

5
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/Accessor.cs

@ -45,16 +45,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -45,16 +45,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)

7
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/ConstructorDeclaration.cs

@ -113,16 +113,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -113,16 +113,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)

7
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/VariableInitializer.cs

@ -41,16 +41,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -41,16 +41,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
visitor.VisitNullNode(this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
return visitor.VisitNullNode(this);
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{
return default (S);
return visitor.VisitNullNode(this, data);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)

20
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs

@ -2342,7 +2342,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -2342,7 +2342,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
Action<ICompletionData, IType> typeCallback = null;
var inferredTypesCategory = new Category("Inferred Types", null);
var derivedTypesCategory = new Category("Derived Types", null);
if (hintType != null) {
if (hintType != null && (hintType.Kind != TypeKind.TypeParameter || IsTypeParameterInScope(hintType))) {
if (hintType.Kind != TypeKind.Unknown) {
var lookup = new MemberLookup(
ctx.CurrentTypeDefinition,
@ -2426,6 +2427,21 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -2426,6 +2427,21 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return wrapper.Result;
}
bool IsTypeParameterInScope(IType hintType)
{
var tp = hintType as ITypeParameter;
var ownerName = tp.Owner.ReflectionName;
if (currentMember != null && ownerName == currentMember.ReflectionName)
return true;
var ot = currentType;
while (ot != null) {
if (ownerName == ot.ReflectionName)
return true;
ot = ot.DeclaringTypeDefinition;
}
return false;
}
IEnumerable<ICompletionData> GetOverrideCompletionData(IUnresolvedTypeDefinition type, string modifiers)
{
var wrapper = new CompletionDataWrapper(this);
@ -2818,7 +2834,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -2818,7 +2834,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
var astResolver = unit != null ? CompletionContextProvider.GetResolver(state, unit) : null;
IType hintType = exprParent != null && astResolver != null ?
TypeGuessing.GetValidTypes(astResolver, exprParent).FirstOrDefault() :
TypeGuessing.GetValidTypes(astResolver, exprParent).FirstOrDefault() :
null;
var result = new CompletionDataWrapper(this);
var lookup = new MemberLookup(

18
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/CSharpFormattingOptions.cs

@ -777,47 +777,47 @@ namespace ICSharpCode.NRefactory.CSharp @@ -777,47 +777,47 @@ namespace ICSharpCode.NRefactory.CSharp
#endregion
#region Blank Lines
public int BlankLinesBeforeUsings {
public int MinimumBlankLinesBeforeUsings {
get;
set;
}
public int BlankLinesAfterUsings {
public int MinimumBlankLinesAfterUsings {
get;
set;
}
public int BlankLinesBeforeFirstDeclaration {
public int MinimumBlankLinesBeforeFirstDeclaration {
get;
set;
}
public int BlankLinesBetweenTypes {
public int MinimumBlankLinesBetweenTypes {
get;
set;
}
public int BlankLinesBetweenFields {
public int MinimumBlankLinesBetweenFields {
get;
set;
}
public int BlankLinesBetweenEventFields {
public int MinimumBlankLinesBetweenEventFields {
get;
set;
}
public int BlankLinesBetweenMembers {
public int MinimumBlankLinesBetweenMembers {
get;
set;
}
public int BlankLinesAroundRegion {
public int MinimumBlankLinesAroundRegion {
get;
set;
}
public int BlankLinesInsideRegion {
public int MinimumBlankLinesInsideRegion {
get;
set;
}

514
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/ConstructFixer.cs

@ -0,0 +1,514 @@ @@ -0,0 +1,514 @@
//
// ConstructFixer.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.Editor;
using System.Text;
using System.Reflection;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp
{
abstract class ConstructCompleter
{
public abstract bool TryFix (ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset);
protected AstNode GetLastNonErrorChild (AstNode node)
{
var lastNode = node.LastChild;
while (lastNode is ErrorNode) {
lastNode = lastNode.GetPrevNode(FormattingVisitor.NoWhitespacePredicate);
}
return lastNode;
}
}
class TypeDeclarationCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var typeDeclaration = syntaxTree.GetNodeAt<TypeDeclaration>(location);
if (typeDeclaration != null) {
if (typeDeclaration.LBraceToken.IsNull && typeDeclaration.RBraceToken.IsNull) {
if (typeDeclaration.Members.Any())
return false;
var lastNode = GetLastNonErrorChild (typeDeclaration);
if (lastNode == null)
return false;
var insertionOffset = document.GetOffset(lastNode.EndLocation);
document.Insert(insertionOffset, fixer.GenerateBody (typeDeclaration, fixer.Options.ClassBraceStyle, false, ref newOffset));
return true;
}
}
return false;
}
}
class DelegateDeclarationCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var typeDeclaration = syntaxTree.GetNodeAt<DelegateDeclaration>(location);
if (typeDeclaration != null) {
if (typeDeclaration.RParToken.IsNull) {
var lastNode = GetLastNonErrorChild (typeDeclaration);
if (lastNode == null)
return false;
var insertionOffset = document.GetOffset(lastNode.EndLocation);
document.Insert(insertionOffset, ");\n");
newOffset += ");\n".Length;
return true;
}
}
return false;
}
}
class MethodDeclarationCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var methodDeclaration = syntaxTree.GetNodeAt<MethodDeclaration>(location);
if (methodDeclaration != null) {
if (!methodDeclaration.LParToken.IsNull && methodDeclaration.RParToken.IsNull) {
var lastNode = GetLastNonErrorChild (methodDeclaration);
if (lastNode == null)
return false;
var insertionOffset = document.GetOffset(lastNode.EndLocation);
document.Insert(insertionOffset, ")\n\t{\t\t\n\t}");
newOffset += ")\n\t{\t\t".Length;
return true;
}
}
return false;
}
}
class IfStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var ifStatement = syntaxTree.GetNodeAt<IfElseStatement>(location);
if (ifStatement != null) {
if (!ifStatement.LParToken.IsNull && ifStatement.RParToken.IsNull) {
var lastNode = GetLastNonErrorChild (ifStatement);
if (lastNode == null)
return false;
var insertionOffset = document.GetOffset(lastNode.EndLocation);
document.Insert(insertionOffset, fixer.GenerateBody (ifStatement, fixer.Options.StatementBraceStyle, true, ref newOffset));
return true;
}
}
return false;
}
}
class ForeachStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var ifStatement = syntaxTree.GetNodeAt<ForeachStatement>(location);
if (ifStatement != null) {
if (!ifStatement.LParToken.IsNull && ifStatement.RParToken.IsNull) {
var lastNode = GetLastNonErrorChild (ifStatement);
if (lastNode == null)
return false;
var insertionOffset = document.GetOffset(lastNode.EndLocation);
document.Insert(insertionOffset, fixer.GenerateBody (ifStatement, fixer.Options.StatementBraceStyle, true, ref newOffset));
return true;
}
}
return false;
}
}
class WhileStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var ifStatement = syntaxTree.GetNodeAt<WhileStatement>(location);
if (ifStatement != null) {
if (!ifStatement.LParToken.IsNull && ifStatement.RParToken.IsNull) {
var lastNode = GetLastNonErrorChild (ifStatement);
if (lastNode == null)
return false;
var insertionOffset = document.GetOffset(lastNode.EndLocation);
document.Insert(insertionOffset, fixer.GenerateBody (ifStatement, fixer.Options.StatementBraceStyle, true, ref newOffset));
return true;
}
}
return false;
}
}
class DoWhileStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var stmt = syntaxTree.GetNodeAt<DoWhileStatement>(location);
if (stmt != null) {
if (!stmt.LParToken.IsNull && stmt.RParToken.IsNull) {
var lastNode = GetLastNonErrorChild (stmt);
if (lastNode == null)
return false;
var insertionOffset = document.GetOffset(lastNode.EndLocation);
document.Insert(insertionOffset, ");");
newOffset = insertionOffset + 2;
return true;
}
}
return false;
}
}
class FixedStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var stmt = syntaxTree.GetNodeAt<FixedStatement>(location);
if (stmt != null) {
if (!stmt.LParToken.IsNull && stmt.RParToken.IsNull) {
var lastNode = GetLastNonErrorChild (stmt);
if (lastNode == null)
return false;
var insertionOffset = document.GetOffset(lastNode.EndLocation);
document.Insert(insertionOffset, fixer.GenerateBody (stmt, fixer.Options.StatementBraceStyle, true, ref newOffset));
return true;
}
}
return false;
}
}
class SwitchStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var switchStatement = syntaxTree.GetNodeAt<SwitchStatement>(location);
if (switchStatement != null) {
if (!switchStatement.LParToken.IsNull && switchStatement.RParToken.IsNull) {
var lastNode = GetLastNonErrorChild (switchStatement);
if (lastNode == null)
return false;
var insertionOffset = document.GetOffset(lastNode.EndLocation);
document.Insert(insertionOffset, fixer.GenerateBody (switchStatement, fixer.Options.StatementBraceStyle, true, ref newOffset));
return true;
}
}
return false;
}
}
class InvocationCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var invocationExpression = syntaxTree.GetNodeAt<InvocationExpression>(location);
if (invocationExpression != null) {
if (!invocationExpression.LParToken.IsNull && invocationExpression.RParToken.IsNull) {
var lastNode = GetLastNonErrorChild (invocationExpression);
if (lastNode == null)
return false;
var insertionOffset = document.GetOffset(lastNode.EndLocation);
newOffset = insertionOffset;
var text = ")";
newOffset++;
var expressionStatement = invocationExpression.Parent as ExpressionStatement;
if (expressionStatement != null) {
if (expressionStatement.SemicolonToken.IsNull)
text = ");";
newOffset ++;
}
document.Insert(insertionOffset, text);
return true;
}
}
return false;
}
}
class BreakStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var stmt = syntaxTree.GetNodeAt<BreakStatement>(location);
if (stmt != null && stmt.SemicolonToken.IsNull) {
// TODO !!!!
return true;
}
return false;
}
}
class CheckedStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var stmt = syntaxTree.GetNodeAt<CheckedExpression>(location);
if (stmt != null && stmt.Parent is ExpressionStatement) {
var insertionOffset = document.GetOffset(stmt.EndLocation);
document.Insert(insertionOffset, fixer.GenerateBody (stmt, fixer.Options.StatementBraceStyle, false, ref newOffset));
return true;
}
return false;
}
}
class UncheckedStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var stmt = syntaxTree.GetNodeAt<UncheckedExpression>(location);
if (stmt != null && stmt.Parent is ExpressionStatement) {
var insertionOffset = document.GetOffset(stmt.EndLocation);
document.Insert(insertionOffset, fixer.GenerateBody (stmt, fixer.Options.StatementBraceStyle, false, ref newOffset));
return true;
}
return false;
}
}
class ExpressionStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var expressionStatement = syntaxTree.GetNodeAt<ExpressionStatement>(location);
if (expressionStatement != null) {
int offset = document.GetOffset(expressionStatement.Expression.EndLocation);
if (expressionStatement.SemicolonToken.IsNull) {
document.Insert(offset, ";");
newOffset = offset + 1;
}
return true;
}
return false;
}
}
class LockStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var stmt = syntaxTree.GetNodeAt<LockStatement>(location);
if (stmt != null) {
if (!stmt.LParToken.IsNull && stmt.RParToken.IsNull) {
var lastNode = GetLastNonErrorChild (stmt);
if (lastNode == null)
return false;
var insertionOffset = document.GetOffset(lastNode.EndLocation);
document.Insert(insertionOffset, fixer.GenerateBody (stmt, fixer.Options.StatementBraceStyle, true, ref newOffset));
return true;
}
}
return false;
}
}
class ReturnStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var stmt = syntaxTree.GetNodeAt<ReturnStatement>(location);
if (stmt != null && stmt.SemicolonToken.IsNull) {
var insertionOffset = document.GetOffset(stmt.EndLocation);
document.Insert(insertionOffset, ";");
newOffset = insertionOffset + 1;
return true;
}
return false;
}
}
class YieldReturnStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var stmt = syntaxTree.GetNodeAt<YieldReturnStatement>(location);
if (stmt != null && stmt.SemicolonToken.IsNull) {
var insertionOffset = document.GetOffset(stmt.EndLocation);
document.Insert(insertionOffset, ";");
newOffset = insertionOffset + 1;
return true;
}
return false;
}
}
class ThrowStatementCompleter : ConstructCompleter
{
public override bool TryFix(ConstructFixer fixer, SyntaxTree syntaxTree, IDocument document, TextLocation location, ref int newOffset)
{
var stmt = syntaxTree.GetNodeAt<ThrowStatement>(location);
if (stmt != null && stmt.SemicolonToken.IsNull) {
var insertionOffset = document.GetOffset(stmt.EndLocation);
document.Insert(insertionOffset, ";");
newOffset = insertionOffset + 1;
return true;
}
return false;
}
}
public class ConstructFixer
{
static readonly ConstructCompleter[] completer = {
new TypeDeclarationCompleter(),
new DelegateDeclarationCompleter (),
new MethodDeclarationCompleter (),
new IfStatementCompleter (),
new ForeachStatementCompleter (),
new WhileStatementCompleter (),
new LockStatementCompleter (),
new FixedStatementCompleter (),
new DoWhileStatementCompleter (),
new SwitchStatementCompleter (),
new BreakStatementCompleter (),
new ThrowStatementCompleter (),
new ReturnStatementCompleter (),
new YieldReturnStatementCompleter (),
new CheckedStatementCompleter (),
new UncheckedStatementCompleter (),
new InvocationCompleter (),
new ExpressionStatementCompleter ()
};
readonly CSharpFormattingOptions options;
readonly TextEditorOptions textEditorOptions;
public CSharpFormattingOptions Options {
get {
return options;
}
}
public ConstructFixer(CSharpFormattingOptions options, TextEditorOptions textEditorOptions)
{
this.options = options;
this.textEditorOptions = textEditorOptions;
}
string GetIndent(AstNode node)
{
if (node == null || node is SyntaxTree)
return "";
if (node is BlockStatement || node is TypeDeclaration || node is NamespaceDeclaration)
return "\t" + GetIndent(node.Parent);
return GetIndent(node.Parent);
}
internal string GenerateBody(AstNode node, BraceStyle braceStyle, bool addClosingBracket, ref int newOffset)
{
StringBuilder result = new StringBuilder();
if (addClosingBracket)
result.Append(")");
var nodeIndent = GetIndent(node.Parent);
switch (braceStyle) {
case BraceStyle.DoNotChange:
case BraceStyle.BannerStyle:
case BraceStyle.EndOfLine:
result.Append(" ");
result.Append("{");
result.Append(textEditorOptions.EolMarker);
result.Append(nodeIndent + "\t");
break;
case BraceStyle.EndOfLineWithoutSpace:
result.Append("{");
result.Append(textEditorOptions.EolMarker);
result.Append(nodeIndent + "\t");
break;
case BraceStyle.NextLine:
result.Append(textEditorOptions.EolMarker);
result.Append(nodeIndent);
result.Append("{");
result.Append(textEditorOptions.EolMarker);
result.Append(nodeIndent + "\t");
break;
case BraceStyle.NextLineShifted:
result.Append(textEditorOptions.EolMarker);
result.Append(nodeIndent + "\t");
result.Append("{");
result.Append(textEditorOptions.EolMarker);
result.Append(nodeIndent + "\t");
break;
case BraceStyle.NextLineShifted2:
result.Append(textEditorOptions.EolMarker);
result.Append(nodeIndent + "\t");
result.Append("{");
result.Append(textEditorOptions.EolMarker);
result.Append(nodeIndent + "\t" + "\t");
break;
}
newOffset += result.Length;
result.Append(textEditorOptions.EolMarker);
result.Append(nodeIndent);
result.Append("}");
return result.ToString();
}
public bool TryFix (IDocument document, int offset, out int newOffset)
{
newOffset = offset;
var syntaxTree = SyntaxTree.Parse(document, "a.cs");
var location = document.GetLocation(offset - 1);
foreach (var c in completer) {
if (c.TryFix(this, syntaxTree, document, location, ref newOffset)) {
return true;
}
}
return false;
}
}
}

36
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/FormattingOptionsFactory.cs

@ -171,17 +171,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -171,17 +171,17 @@ namespace ICSharpCode.NRefactory.CSharp
SpaceAfterIndexerDeclarationParameterComma = true,
BlankLinesBeforeUsings = 0,
BlankLinesAfterUsings = 1,
MinimumBlankLinesBeforeUsings = 0,
MinimumBlankLinesAfterUsings = 1,
UsingPlacement = UsingPlacement.TopOfFile,
BlankLinesBeforeFirstDeclaration = 0,
BlankLinesBetweenTypes = 1,
BlankLinesBetweenFields = 0,
BlankLinesBetweenEventFields = 0,
BlankLinesBetweenMembers = 1,
BlankLinesAroundRegion = 1,
BlankLinesInsideRegion = 1,
MinimumBlankLinesBeforeFirstDeclaration = 0,
MinimumBlankLinesBetweenTypes = 1,
MinimumBlankLinesBetweenFields = 0,
MinimumBlankLinesBetweenEventFields = 0,
MinimumBlankLinesBetweenMembers = 1,
MinimumBlankLinesAroundRegion = 1,
MinimumBlankLinesInsideRegion = 1,
AlignToFirstIndexerArgument = false,
AlignToFirstIndexerDeclarationParameter = true,
AlignToFirstMethodCallArgument = false,
@ -341,16 +341,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -341,16 +341,16 @@ namespace ICSharpCode.NRefactory.CSharp
SpaceAfterIndexerDeclarationParameterComma = true,
RemoveEndOfLineWhiteSpace = true,
BlankLinesBeforeUsings = 0,
BlankLinesAfterUsings = 1,
MinimumBlankLinesBeforeUsings = 0,
MinimumBlankLinesAfterUsings = 1,
BlankLinesBeforeFirstDeclaration = 0,
BlankLinesBetweenTypes = 1,
BlankLinesBetweenFields = 0,
BlankLinesBetweenEventFields = 0,
BlankLinesBetweenMembers = 1,
BlankLinesAroundRegion = 1,
BlankLinesInsideRegion = 1,
MinimumBlankLinesBeforeFirstDeclaration = 0,
MinimumBlankLinesBetweenTypes = 1,
MinimumBlankLinesBetweenFields = 0,
MinimumBlankLinesBetweenEventFields = 0,
MinimumBlankLinesBetweenMembers = 1,
MinimumBlankLinesAroundRegion = 1,
MinimumBlankLinesInsideRegion = 1,
KeepCommentsAtFirstColumn = true,
ChainedMethodCallWrapping = Wrapping.DoNotChange,

33
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/FormattingVisitor.cs

@ -119,7 +119,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -119,7 +119,7 @@ namespace ICSharpCode.NRefactory.CSharp
#region NewLines
void AdjustNewLineBlock(AstNode startNode, int targetNewLineCount)
void AdjustNewLineBlock(AstNode startNode, int targetMinimumNewLineCount)
{
var indentString = policy.EmptyLineFormatting == EmptyLineFormatting.Indent ? curIndent.IndentString : "";
@ -127,7 +127,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -127,7 +127,7 @@ namespace ICSharpCode.NRefactory.CSharp
var node = startNode.NextSibling;
int currentNewLineCount = 0;
// Check the existing newlines
for (; currentNewLineCount < targetNewLineCount; node = node.NextSibling) {
for (; currentNewLineCount < targetMinimumNewLineCount; node = node.NextSibling) {
if (node is WhitespaceNode)
continue;
if (!(node is NewLineNode))
@ -160,10 +160,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -160,10 +160,10 @@ namespace ICSharpCode.NRefactory.CSharp
// end of file/block etc, nothing more to do but break before assigning null to node
break;
}
if (currentNewLineCount < targetNewLineCount) {
if (currentNewLineCount < targetMinimumNewLineCount) {
// We need to add more newlines
var builder = new StringBuilder();
for (; currentNewLineCount < targetNewLineCount; currentNewLineCount++) {
for (; currentNewLineCount < targetMinimumNewLineCount; currentNewLineCount++) {
if (currentNewLineCount > 0)
// Don't indent the first line in the block since that is not an empty line.
builder.Append(indentString);
@ -171,18 +171,18 @@ namespace ICSharpCode.NRefactory.CSharp @@ -171,18 +171,18 @@ namespace ICSharpCode.NRefactory.CSharp
}
var offset = document.GetOffset(newLineInsertPosition);
AddChange(offset, 0, builder.ToString());
} else if (currentNewLineCount == targetNewLineCount && node is NewLineNode){
// Check to see if there are any newlines to remove
var endNode = node.GetNextSibling(n => !(n is NewLineNode || n is WhitespaceNode));
if (endNode != null) {
var startOffset = document.GetOffset(newLineInsertPosition);
var endOffset = document.GetOffset(new TextLocation(endNode.StartLocation.Line, 0));
EnsureText(startOffset, endOffset, null);
}
} else if (currentNewLineCount == targetMinimumNewLineCount && node is NewLineNode){
// // Check to see if there are any newlines to remove
// var endNode = node.GetNextSibling(n => !(n is NewLineNode || n is WhitespaceNode));
// if (endNode != null) {
// var startOffset = document.GetOffset(newLineInsertPosition);
// var endOffset = document.GetOffset(new TextLocation(endNode.StartLocation.Line, 0));
// EnsureText(startOffset, endOffset, null);
// }
}
}
public void EnsureNewLinesAfter(AstNode node, int blankLines)
public void EnsureMinimumNewLinesAfter(AstNode node, int blankLines)
{
if (node is PreProcessorDirective) {
var directive = (PreProcessorDirective)node;
@ -196,7 +196,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -196,7 +196,7 @@ namespace ICSharpCode.NRefactory.CSharp
AdjustNewLineBlock(node, blankLines);
}
public void EnsureBlankLinesBefore(AstNode node, int blankLines)
public void EnsureMinimumBlankLinesBefore(AstNode node, int blankLines)
{
if (formatter.FormattingMode != FormattingMode.Intrusive)
return;
@ -207,7 +207,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -207,7 +207,8 @@ namespace ICSharpCode.NRefactory.CSharp
} while (line > 0 && IsSpacing(document.GetLineByNumber(line)));
if (line > 0 && !IsSpacing(document.GetLineByNumber(line)))
line++;
if (loc.Line - line == blankLines)
if (loc.Line - line >= blankLines)
return;
var sb = new StringBuilder ();
@ -371,7 +372,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -371,7 +372,7 @@ namespace ICSharpCode.NRefactory.CSharp
return i;
}
static bool NoWhitespacePredicate(AstNode arg)
internal static bool NoWhitespacePredicate(AstNode arg)
{
return !(arg is NewLineNode || arg is WhitespaceNode);
}

38
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/FormattingVisitor_Global.cs

@ -49,9 +49,9 @@ namespace ICSharpCode.NRefactory.CSharp @@ -49,9 +49,9 @@ namespace ICSharpCode.NRefactory.CSharp
return -1;
}
if ((child is UsingDeclaration || child is UsingAliasDeclaration) && !(nextSibling is UsingDeclaration || nextSibling is UsingAliasDeclaration)) {
newLines += policy.BlankLinesAfterUsings;
newLines += policy.MinimumBlankLinesAfterUsings;
} else if ((child is TypeDeclaration) && (nextSibling is TypeDeclaration)) {
newLines += policy.BlankLinesBetweenTypes;
newLines += policy.MinimumBlankLinesBetweenTypes;
}
return newLines;
@ -62,14 +62,14 @@ namespace ICSharpCode.NRefactory.CSharp @@ -62,14 +62,14 @@ namespace ICSharpCode.NRefactory.CSharp
bool first = true;
VisitChildrenToFormat(unit, child => {
if (first && (child is UsingDeclaration || child is UsingAliasDeclaration)) {
EnsureBlankLinesBefore(child, policy.BlankLinesBeforeUsings);
EnsureMinimumBlankLinesBefore(child, policy.MinimumBlankLinesBeforeUsings);
first = false;
}
if (NoWhitespacePredicate(child))
FixIndentation(child);
child.AcceptVisitor(this);
if (NoWhitespacePredicate(child) && !first)
EnsureNewLinesAfter(child, GetGlobalNewLinesFor(child));
EnsureMinimumNewLinesAfter(child, GetGlobalNewLinesFor(child));
});
}
@ -126,11 +126,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -126,11 +126,11 @@ namespace ICSharpCode.NRefactory.CSharp
var next = child.GetNextSibling(NoWhitespacePredicate);
var blankLines = 1;
if (next is UsingDeclaration || next is UsingAliasDeclaration) {
blankLines += policy.BlankLinesBeforeUsings;
blankLines += policy.MinimumBlankLinesBeforeUsings;
} else {
blankLines += policy.BlankLinesBeforeFirstDeclaration;
blankLines += policy.MinimumBlankLinesBeforeFirstDeclaration;
}
EnsureNewLinesAfter(child, blankLines);
EnsureMinimumNewLinesAfter(child, blankLines);
startFormat = true;
return;
}
@ -148,7 +148,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -148,7 +148,7 @@ namespace ICSharpCode.NRefactory.CSharp
FixIndentationForceNewLine(child);
child.AcceptVisitor(this);
if (NoWhitespacePredicate(child))
EnsureNewLinesAfter(child, GetGlobalNewLinesFor(child));
EnsureMinimumNewLinesAfter(child, GetGlobalNewLinesFor(child));
});
if (policy.IndentNamespaceBody)
@ -223,7 +223,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -223,7 +223,7 @@ namespace ICSharpCode.NRefactory.CSharp
if (child.Role == Roles.LBrace) {
startFormat = true;
if (braceStyle != BraceStyle.DoNotChange)
EnsureNewLinesAfter(child, GetTypeLevelNewLinesFor(child));
EnsureMinimumNewLinesAfter(child, GetTypeLevelNewLinesFor(child));
return;
}
if (child.Role == Roles.RBrace) {
@ -234,14 +234,14 @@ namespace ICSharpCode.NRefactory.CSharp @@ -234,14 +234,14 @@ namespace ICSharpCode.NRefactory.CSharp
return;
if (child.Role == Roles.Comma) {
ForceSpacesBeforeRemoveNewLines (child, false);
EnsureNewLinesAfter(child, 1);
EnsureMinimumNewLinesAfter(child, 1);
return;
}
if (NoWhitespacePredicate(child))
FixIndentationForceNewLine(child);
child.AcceptVisitor(this);
if (NoWhitespacePredicate(child) && child.GetNextSibling (NoWhitespacePredicate).Role != Roles.Comma)
EnsureNewLinesAfter(child, GetTypeLevelNewLinesFor(child));
EnsureMinimumNewLinesAfter(child, GetTypeLevelNewLinesFor(child));
});
if (indentBody)
@ -257,12 +257,12 @@ namespace ICSharpCode.NRefactory.CSharp @@ -257,12 +257,12 @@ namespace ICSharpCode.NRefactory.CSharp
if (child is PreProcessorDirective) {
var directive = (PreProcessorDirective)child;
if (directive.Type == PreProcessorDirectiveType.Region) {
blankLines += policy.BlankLinesInsideRegion;
blankLines += policy.MinimumBlankLinesInsideRegion;
}
if (directive.Type == PreProcessorDirectiveType.Endregion) {
if (child.GetNextSibling(NoWhitespacePredicate) is CSharpTokenNode)
return 1;
blankLines += policy.BlankLinesAroundRegion;
blankLines += policy.MinimumBlankLinesAroundRegion;
}
return blankLines;
}
@ -272,10 +272,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -272,10 +272,10 @@ namespace ICSharpCode.NRefactory.CSharp
if (directive.Type == PreProcessorDirectiveType.Region) {
if (child is CSharpTokenNode)
return 1;
blankLines += policy.BlankLinesAroundRegion;
blankLines += policy.MinimumBlankLinesAroundRegion;
}
if (directive.Type == PreProcessorDirectiveType.Endregion)
blankLines += policy.BlankLinesInsideRegion;
blankLines += policy.MinimumBlankLinesInsideRegion;
if (directive.Type == PreProcessorDirectiveType.Endif)
return -1;
if (directive.Type == PreProcessorDirectiveType.Undef)
@ -288,27 +288,27 @@ namespace ICSharpCode.NRefactory.CSharp @@ -288,27 +288,27 @@ namespace ICSharpCode.NRefactory.CSharp
return 1;
if (child is EventDeclaration) {
if (nextSibling is EventDeclaration) {
blankLines += policy.BlankLinesBetweenEventFields;
blankLines += policy.MinimumBlankLinesBetweenEventFields;
return blankLines;
}
}
if (child is FieldDeclaration || child is FixedFieldDeclaration) {
if (nextSibling is FieldDeclaration || nextSibling is FixedFieldDeclaration) {
blankLines += policy.BlankLinesBetweenFields;
blankLines += policy.MinimumBlankLinesBetweenFields;
return blankLines;
}
}
if (child is TypeDeclaration) {
if (nextSibling is TypeDeclaration) {
blankLines += policy.BlankLinesBetweenTypes;
blankLines += policy.MinimumBlankLinesBetweenTypes;
return blankLines;
}
}
if (nextSibling.Role == Roles.TypeMemberRole)
blankLines += policy.BlankLinesBetweenMembers;
blankLines += policy.MinimumBlankLinesBetweenMembers;
return blankLines;
}

4
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/Indent.cs

@ -41,7 +41,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -41,7 +41,7 @@ namespace ICSharpCode.NRefactory.CSharp
public class Indent
{
readonly Stack<IndentType> indentStack = new Stack<IndentType>();
readonly CloneableStack<IndentType> indentStack = new CloneableStack<IndentType>();
readonly TextEditorOptions options;
int curIndent;
int extraSpaces;
@ -61,7 +61,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -61,7 +61,7 @@ namespace ICSharpCode.NRefactory.CSharp
Indent(Indent engine)
{
this.indentStack = new Stack<IndentType>(engine.indentStack.Reverse());
this.indentStack = engine.indentStack.Clone();
this.options = engine.options;
this.curIndent = engine.curIndent;
this.extraSpaces = engine.extraSpaces;

12
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj

@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
<NoStdLib>False</NoStdLib>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<ProductVersion>10.0.0</ProductVersion>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>..\ICSharpCode.NRefactory.snk</AssemblyOriginatorKeyFile>
@ -77,13 +77,9 @@ @@ -77,13 +77,9 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="System.Core" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\ICSharpCode.NRefactory\Properties\GlobalAssemblyInfo.cs">
@ -388,6 +384,8 @@ @@ -388,6 +384,8 @@
<Compile Include="Refactoring\CodeGenerationService.cs" />
<Compile Include="Formatter\FormattingVisitor_Query.cs" />
<Compile Include="Analysis\AnnotationNames.cs" />
<Compile Include="Formatter\ConstructFixer.cs" />
<Compile Include="Util\CloneableStack.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">

52
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/IndentEngine/CSharpIndentEngine.cs

@ -80,12 +80,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -80,12 +80,16 @@ namespace ICSharpCode.NRefactory.CSharp
/// </summary>
internal HashSet<string> customConditionalSymbols;
/// <summary>
/// Stores the results of evaluations of the preprocessor if/elif directives
/// in the current block (between #if and #endif).
/// </summary>
internal CloneableStack<bool> ifDirectiveEvalResults = new CloneableStack<bool> ();
/// <summary>
/// True if any of the preprocessor if/elif directives in the current
/// block (between #if and #endif) were evaluated to true.
/// Stores the indentation levels of the if directives in the current block.
/// </summary>
internal Stack<bool> ifDirectiveEvalResult = new Stack<bool> ();
internal CloneableStack<Indent> ifDirectiveIndents = new CloneableStack<Indent>();
/// <summary>
/// Stores the last sequence of characters that can form a
@ -245,7 +249,6 @@ namespace ICSharpCode.NRefactory.CSharp @@ -245,7 +249,6 @@ namespace ICSharpCode.NRefactory.CSharp
/// </summary>
internal char previousNewline = '\0';
/// <summary>
/// Current indent level on this line.
/// </summary>
@ -283,7 +286,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -283,7 +286,7 @@ namespace ICSharpCode.NRefactory.CSharp
this.textEditorOptions = textEditorOptions;
this.document = document;
this.currentState = IndentStateFactory.Default(this);
this.currentState = new GlobalBodyState(this);
this.conditionalSymbols = new HashSet<string>();
this.customConditionalSymbols = new HashSet<string>();
@ -311,7 +314,6 @@ namespace ICSharpCode.NRefactory.CSharp @@ -311,7 +314,6 @@ namespace ICSharpCode.NRefactory.CSharp
this.wordToken = new StringBuilder(prototype.wordToken.ToString());
this.previousKeyword = string.Copy(prototype.previousKeyword);
this.ifDirectiveEvalResult = prototype.ifDirectiveEvalResult;
this.offset = prototype.offset;
this.line = prototype.line;
@ -324,7 +326,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -324,7 +326,8 @@ namespace ICSharpCode.NRefactory.CSharp
this.currentIndent = new StringBuilder(prototype.CurrentIndent.ToString());
this.lineBeganInsideMultiLineComment = prototype.lineBeganInsideMultiLineComment;
this.lineBeganInsideVerbatimString = prototype.lineBeganInsideVerbatimString;
this.ifDirectiveEvalResult = new Stack<bool>(prototype.ifDirectiveEvalResult.Reverse());
this.ifDirectiveEvalResults = prototype.ifDirectiveEvalResults.Clone();
this.ifDirectiveIndents = prototype.ifDirectiveIndents.Clone();
this.EnableCustomIndentLevels = prototype.EnableCustomIndentLevels;
}
@ -373,27 +376,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -373,27 +376,16 @@ namespace ICSharpCode.NRefactory.CSharp
var isNewLine = NewLine.IsNewLine(ch);
if (!isNewLine) {
currentState.Push(currentChar = ch);
} else {
if (ch == NewLine.LF && previousNewline == NewLine.CR) {
offset++;
return;
}
currentState.Push(currentChar = newLineChar);
}
offset++;
if (!isNewLine)
{
offset++;
previousNewline = '\0';
// ignore whitespace and newline chars
if (!char.IsWhiteSpace(currentChar))
var isWhitespace = currentChar == ' ' || currentChar == '\t';
if (!isWhitespace)
{
previousChar = currentChar;
isLineStart = false;
}
isLineStart &= char.IsWhiteSpace(ch);
if (isLineStart)
{
currentIndent.Append(ch);
@ -408,9 +400,14 @@ namespace ICSharpCode.NRefactory.CSharp @@ -408,9 +400,14 @@ namespace ICSharpCode.NRefactory.CSharp
{
column++;
}
}
else
{
} else {
if (ch == NewLine.LF && previousNewline == NewLine.CR) {
offset++;
return;
}
currentState.Push(currentChar = newLineChar);
offset++;
previousNewline = ch;
// there can be more than one chars that determine the EOL,
// the engine uses only one of them defined with newLineChar
@ -432,9 +429,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -432,9 +429,10 @@ namespace ICSharpCode.NRefactory.CSharp
/// <inheritdoc />
public void Reset()
{
currentState = IndentStateFactory.Default(this);
currentState = new GlobalBodyState(this);
conditionalSymbols.Clear();
ifDirectiveEvalResult.Clear();
ifDirectiveEvalResults.Clear();
ifDirectiveIndents.Clear();
offset = 0;
line = 1;

304
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/IndentEngine/IndentState.cs

@ -73,22 +73,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -73,22 +73,8 @@ namespace ICSharpCode.NRefactory.CSharp
#region Constructors
/// <summary>
/// Creates a new indentation state.
/// </summary>
/// <param name="engine">
/// The indentation engine that uses this state.
/// </param>
/// <param name="parent">
/// The parent state, or null if this state doesn't have one ->
/// e.g. the state represents the global space.
/// </param>
protected IndentState(CSharpIndentEngine engine, IndentState parent = null)
protected IndentState()
{
Parent = parent;
Engine = engine;
InitializeState();
}
/// <summary>
@ -125,6 +111,14 @@ namespace ICSharpCode.NRefactory.CSharp @@ -125,6 +111,14 @@ namespace ICSharpCode.NRefactory.CSharp
#region Methods
internal void Initialize (CSharpIndentEngine engine, IndentState parent = null)
{
Parent = parent;
Engine = engine;
InitializeState();
}
/// <summary>
/// Initializes the state:
/// - sets the default indentation levels.
@ -169,9 +163,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -169,9 +163,11 @@ namespace ICSharpCode.NRefactory.CSharp
/// The type of the new state. Must be assignable from <see cref="IndentState"/>.
/// </typeparam>
public void ChangeState<T>()
where T : IndentState
where T : IndentState, new ()
{
Engine.currentState = IndentStateFactory.Create<T>(Engine.currentState);
var t = new T();
t.Initialize(Engine, Engine.currentState);
Engine.currentState = t;
}
/// <summary>
@ -181,7 +177,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -181,7 +177,7 @@ namespace ICSharpCode.NRefactory.CSharp
public void ExitState()
{
OnExit();
Engine.currentState = Engine.currentState.Parent ?? IndentStateFactory.Default(Engine);
Engine.currentState = Engine.currentState.Parent ?? new GlobalBodyState(Engine);
}
/// <summary>
@ -233,81 +229,6 @@ namespace ICSharpCode.NRefactory.CSharp @@ -233,81 +229,6 @@ namespace ICSharpCode.NRefactory.CSharp
#endregion
#region IndentStateFactory
/// <summary>
/// Indentation state factory.
/// </summary>
public static class IndentStateFactory
{
/// <summary>
/// Creates a new state.
/// </summary>
/// <param name="stateType">
/// Type of the state. Must be assignable from <see cref="IndentState"/>.
/// </param>
/// <param name="engine">
/// Indentation engine for the state.
/// </param>
/// <param name="parent">
/// Parent state.
/// </param>
/// <returns>
/// A new state of type <paramref name="stateType"/>.
/// </returns>
static IndentState Create(Type stateType, CSharpIndentEngine engine, IndentState parent = null)
{
return (IndentState)Activator.CreateInstance(stateType, engine, parent);
}
/// <summary>
/// Creates a new state.
/// </summary>
/// <typeparam name="T">
/// Type of the state. Must be assignable from <see cref="IndentState"/>.
/// </typeparam>
/// <param name="engine">
/// Indentation engine for the state.
/// </param>
/// <param name="parent">
/// Parent state.
/// </param>
/// <returns>
/// A new state of type <typeparamref name="T"/>.
/// </returns>
public static IndentState Create<T>(CSharpIndentEngine engine, IndentState parent = null)
where T : IndentState
{
return Create(typeof(T), engine, parent);
}
/// <summary>
/// Creates a new state.
/// </summary>
/// <typeparam name="T">
/// Type of the state. Must be assignable from <see cref="IndentState"/>.
/// </typeparam>
/// <param name="prototype">
/// Parent state. Also, the indentation engine of the prototype is
/// used as the engine for the new state.
/// </param>
/// <returns>
/// A new state of type <typeparamref name="T"/>.
/// </returns>
public static IndentState Create<T>(IndentState prototype)
where T : IndentState
{
return Create(typeof(T), prototype.Engine, prototype);
}
/// <summary>
/// The default state, used for the global space.
/// </summary>
public static Func<CSharpIndentEngine, IndentState> Default = engine => Create<GlobalBodyState>(engine);
}
#endregion
#region Null state
/// <summary>
@ -318,8 +239,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -318,8 +239,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// </remarks>
public class NullState : IndentState
{
public NullState(CSharpIndentEngine engine, IndentState parent = null)
: base(engine, parent)
public NullState()
{ }
public NullState(NullState prototype, CSharpIndentEngine engine)
@ -349,25 +269,14 @@ namespace ICSharpCode.NRefactory.CSharp @@ -349,25 +269,14 @@ namespace ICSharpCode.NRefactory.CSharp
/// </remarks>
public abstract class BracketsBodyBaseState : IndentState
{
/// <summary>
/// Defines transitions for all types of open brackets.
/// </summary>
public static Dictionary<char, Action<IndentState>> OpenBrackets =
new Dictionary<char, Action<IndentState>>
{
{ '{', state => state.ChangeState<BracesBodyState>() },
{ '(', state => state.ChangeState<ParenthesesBodyState>() },
{ '[', state => state.ChangeState<SquareBracketsBodyState>() },
};
/// <summary>
/// When derived in a concrete bracket body state, represents
/// the closed bracket character pair.
/// </summary>
public abstract char ClosedBracket { get; }
protected BracketsBodyBaseState(CSharpIndentEngine engine, IndentState parent = null)
: base(engine, parent)
protected BracketsBodyBaseState()
{ }
protected BracketsBodyBaseState(BracketsBodyBaseState prototype, CSharpIndentEngine engine)
@ -377,41 +286,45 @@ namespace ICSharpCode.NRefactory.CSharp @@ -377,41 +286,45 @@ namespace ICSharpCode.NRefactory.CSharp
public override void Push(char ch)
{
base.Push(ch);
if (ch == '#' && Engine.isLineStart)
{
ChangeState<PreProcessorState>();
}
else if (ch == '/' && Engine.previousChar == '/')
{
ChangeState<LineCommentState>();
}
else if (ch == '*' && Engine.previousChar == '/')
{
ChangeState<MultiLineCommentState>();
}
else if (ch == '"')
{
if (Engine.previousChar == '@')
{
ChangeState<VerbatimStringState>();
}
else
{
ChangeState<StringLiteralState>();
}
}
else if (ch == '\'')
{
ChangeState<CharacterState>();
}
else if (OpenBrackets.ContainsKey(ch))
{
OpenBrackets[ch](this);
}
else if (ch == ClosedBracket)
{
ExitState();
switch (ch) {
case '#':
if (Engine.isLineStart)
ChangeState<PreProcessorState>();
break;
case '/':
if (Engine.previousChar == '/')
ChangeState<LineCommentState>();
break;
case '*':
if (Engine.previousChar == '/')
ChangeState<MultiLineCommentState>();
break;
case '"':
if (Engine.previousChar == '@')
{
ChangeState<VerbatimStringState>();
}
else
{
ChangeState<StringLiteralState>();
}
break;
case '\'':
ChangeState<CharacterState>();
break;
case '{':
ChangeState<BracesBodyState>();
break;
case '(':
ChangeState<ParenthesesBodyState>();
break;
case '[':
ChangeState<SquareBracketsBodyState>();
break;
default:
if (ch == ClosedBracket)
ExitState();
break;
}
}
}
@ -465,7 +378,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -465,7 +378,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// <summary>
/// Contains indent levels of nested if statements.
/// </summary>
public Stack<Indent> NestedIfStatementLevels = new Stack<Indent>();
internal CloneableStack<Indent> NestedIfStatementLevels = new CloneableStack<Indent>();
/// <summary>
/// Contains the indent level of the last statement or body keyword.
@ -499,8 +412,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -499,8 +412,7 @@ namespace ICSharpCode.NRefactory.CSharp
get { return '}'; }
}
public BracesBodyState(CSharpIndentEngine engine, IndentState parent = null)
: base(engine, parent)
public BracesBodyState()
{
}
@ -510,7 +422,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -510,7 +422,7 @@ namespace ICSharpCode.NRefactory.CSharp
CurrentBody = prototype.CurrentBody;
NextBody = prototype.NextBody;
CurrentStatement = prototype.CurrentStatement;
NestedIfStatementLevels = new Stack<Indent>(prototype.NestedIfStatementLevels);
NestedIfStatementLevels = prototype.NestedIfStatementLevels.Clone();
IsRightHandExpression = prototype.IsRightHandExpression;
IsEqualCharPushed = prototype.IsEqualCharPushed;
IsMemberReferenceDotHandled = prototype.IsMemberReferenceDotHandled;
@ -553,7 +465,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -553,7 +465,7 @@ namespace ICSharpCode.NRefactory.CSharp
{
OnStatementExit();
}
else if (ch == '=' && !new[] { '=', '<', '>', '!' }.Contains(Engine.previousChar))
else if (ch == '=' && !(Engine.previousChar == '=' || Engine.previousChar == '<' || Engine.previousChar == '>' || Engine.previousChar == '!'))
{
IsEqualCharPushed = true;
}
@ -909,7 +821,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -909,7 +821,7 @@ namespace ICSharpCode.NRefactory.CSharp
case Body.None:
if (!Engine.formattingOptions.IndentBlocks)
return false;
style = BraceStyle.NextLine;
style = Engine.formattingOptions.StatementBraceStyle;
return true;
case Body.Namespace:
if (!Engine.formattingOptions.IndentNamespaceBody)
@ -1000,10 +912,15 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1000,10 +912,15 @@ namespace ICSharpCode.NRefactory.CSharp
get { return '\0'; }
}
public GlobalBodyState(CSharpIndentEngine engine, IndentState parent = null)
: base(engine, parent)
public GlobalBodyState()
{ }
public GlobalBodyState(CSharpIndentEngine engine)
{
Initialize (engine, null);
}
public GlobalBodyState(GlobalBodyState prototype, CSharpIndentEngine engine)
: base(prototype, engine)
{ }
@ -1032,8 +949,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1032,8 +949,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// </remarks>
public class SwitchCaseState : BracesBodyState
{
public SwitchCaseState(CSharpIndentEngine engine, IndentState parent = null)
: base(engine, parent)
public SwitchCaseState()
{ }
public SwitchCaseState(SwitchCaseState prototype, CSharpIndentEngine engine)
@ -1138,8 +1054,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1138,8 +1054,7 @@ namespace ICSharpCode.NRefactory.CSharp
get { return ')'; }
}
public ParenthesesBodyState(CSharpIndentEngine engine, IndentState parent = null)
: base(engine, parent)
public ParenthesesBodyState()
{ }
public ParenthesesBodyState(ParenthesesBodyState prototype, CSharpIndentEngine engine)
@ -1226,8 +1141,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1226,8 +1141,7 @@ namespace ICSharpCode.NRefactory.CSharp
get { return ']'; }
}
public SquareBracketsBodyState(CSharpIndentEngine engine, IndentState parent = null)
: base(engine, parent)
public SquareBracketsBodyState()
{ }
public SquareBracketsBodyState(SquareBracketsBodyState prototype, CSharpIndentEngine engine)
@ -1316,8 +1230,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1316,8 +1230,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// </summary>
public StringBuilder DirectiveStatement;
public PreProcessorState(CSharpIndentEngine engine, IndentState parent = null)
: base(engine, parent)
public PreProcessorState()
{
DirectiveType = PreProcessorDirective.None;
DirectiveStatement = new StringBuilder();
@ -1354,8 +1267,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1354,8 +1267,8 @@ namespace ICSharpCode.NRefactory.CSharp
switch (DirectiveType)
{
case PreProcessorDirective.If:
Engine.ifDirectiveEvalResult.Push(eval(DirectiveStatement.ToString()));
if (Engine.ifDirectiveEvalResult.Peek())
Engine.ifDirectiveEvalResults.Push(eval(DirectiveStatement.ToString()));
if (Engine.ifDirectiveEvalResults.Peek())
{
// the if/elif directive is true -> continue with the previous state
}
@ -1367,11 +1280,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1367,11 +1280,11 @@ namespace ICSharpCode.NRefactory.CSharp
}
break;
case PreProcessorDirective.Elif:
if (Engine.ifDirectiveEvalResult.Count > 0)
if (Engine.ifDirectiveEvalResults.Count > 0)
{
if (!Engine.ifDirectiveEvalResult.Peek())
if (!Engine.ifDirectiveEvalResults.Peek())
{
Engine.ifDirectiveEvalResult.Pop();
Engine.ifDirectiveEvalResults.Pop();
goto case PreProcessorDirective.If;
}
}
@ -1379,7 +1292,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1379,7 +1292,7 @@ namespace ICSharpCode.NRefactory.CSharp
ChangeState<PreProcessorCommentState>();
break;
case PreProcessorDirective.Else:
if (Engine.ifDirectiveEvalResult.Count > 0 && Engine.ifDirectiveEvalResult.Peek())
if (Engine.ifDirectiveEvalResults.Count > 0 && Engine.ifDirectiveEvalResults.Peek())
{
// some if/elif directive was true -> change to a state that will
// ignore any chars until #endif
@ -1406,7 +1319,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1406,7 +1319,8 @@ namespace ICSharpCode.NRefactory.CSharp
break;
case PreProcessorDirective.Endif:
// marks the end of this block
Engine.ifDirectiveEvalResult.Pop();
Engine.ifDirectiveEvalResults.Pop();
Engine.ifDirectiveIndents.Pop();
break;
case PreProcessorDirective.Region:
case PreProcessorDirective.Pragma:
@ -1424,7 +1338,14 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1424,7 +1338,14 @@ namespace ICSharpCode.NRefactory.CSharp
// OPTION: IndentPreprocessorStatements
if (Engine.formattingOptions.IndentPreprocessorDirectives)
{
ThisLineIndent = Parent.ThisLineIndent.Clone();
if (Engine.ifDirectiveIndents.Count > 0)
{
ThisLineIndent = Engine.ifDirectiveIndents.Peek().Clone();
}
else
{
ThisLineIndent = Parent.ThisLineIndent.Clone();
}
}
else
{
@ -1476,6 +1397,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1476,6 +1397,10 @@ namespace ICSharpCode.NRefactory.CSharp
{
ThisLineIndent = Parent.NextLineIndent.Clone();
}
else if (DirectiveType == PreProcessorDirective.If)
{
Engine.ifDirectiveIndents.Push(ThisLineIndent.Clone());
}
}
}
@ -1729,8 +1654,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1729,8 +1654,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// </remarks>
public class PreProcessorCommentState : IndentState
{
public PreProcessorCommentState(CSharpIndentEngine engine, IndentState parent = null)
: base(engine, parent)
public PreProcessorCommentState()
{ }
public PreProcessorCommentState(PreProcessorCommentState prototype, CSharpIndentEngine engine)
@ -1752,8 +1676,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1752,8 +1676,17 @@ namespace ICSharpCode.NRefactory.CSharp
public override void InitializeState()
{
ThisLineIndent = Parent.NextLineIndent.Clone();
NextLineIndent = ThisLineIndent.Clone();
if (Engine.formattingOptions.IndentPreprocessorDirectives &&
Engine.ifDirectiveIndents.Count > 0)
{
ThisLineIndent = Engine.ifDirectiveIndents.Peek().Clone();
NextLineIndent = ThisLineIndent.Clone();
}
else
{
ThisLineIndent = Parent.NextLineIndent.Clone();
NextLineIndent = ThisLineIndent.Clone();
}
}
public override IndentState Clone(CSharpIndentEngine engine)
@ -1777,8 +1710,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1777,8 +1710,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// </summary>
public bool CheckForDocComment = true;
public LineCommentState(CSharpIndentEngine engine, IndentState parent = null)
: base(engine, parent)
public LineCommentState()
{
/* if (engine.formattingOptions.KeepCommentsAtFirstColumn && engine.column == 2)
ThisLineIndent.Reset();*/
@ -1832,8 +1764,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1832,8 +1764,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// </summary>
public class DocCommentState : IndentState
{
public DocCommentState(CSharpIndentEngine engine, IndentState parent = null)
: base(engine, parent)
public DocCommentState()
{ }
public DocCommentState(DocCommentState prototype, CSharpIndentEngine engine)
@ -1881,8 +1812,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1881,8 +1812,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// </remarks>
public bool IsAnyCharPushed;
public MultiLineCommentState(CSharpIndentEngine engine, IndentState parent = null)
: base(engine, parent)
public MultiLineCommentState()
{ }
public MultiLineCommentState(MultiLineCommentState prototype, CSharpIndentEngine engine)
@ -1929,8 +1859,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1929,8 +1859,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// </summary>
public bool IsEscaped;
public StringLiteralState(CSharpIndentEngine engine, IndentState parent = null)
: base(engine, parent)
public StringLiteralState()
{ }
public StringLiteralState(StringLiteralState prototype, CSharpIndentEngine engine)
@ -1943,16 +1872,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1943,16 +1872,11 @@ namespace ICSharpCode.NRefactory.CSharp
{
base.Push(ch);
if (ch == Engine.newLineChar)
{
ExitState();
}
else if (!IsEscaped && ch == '"')
{
if (ch == Engine.newLineChar || (!IsEscaped && ch == '"')) {
ExitState();
} else {
IsEscaped = ch == '\\' && !IsEscaped;
}
IsEscaped = ch == '\\' && !IsEscaped;
}
public override void InitializeState()
@ -1981,8 +1905,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1981,8 +1905,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// </summary>
public bool IsEscaped;
public VerbatimStringState(CSharpIndentEngine engine, IndentState parent = null)
: base(engine, parent)
public VerbatimStringState()
{ }
public VerbatimStringState(VerbatimStringState prototype, CSharpIndentEngine engine)
@ -2031,8 +1954,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -2031,8 +1954,7 @@ namespace ICSharpCode.NRefactory.CSharp
/// </summary>
public bool IsEscaped;
public CharacterState(CSharpIndentEngine engine, IndentState parent = null)
: base(engine, parent)
public CharacterState()
{ }
public CharacterState(CharacterState prototype, CSharpIndentEngine engine)

7
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs

@ -1263,7 +1263,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1263,7 +1263,7 @@ namespace ICSharpCode.NRefactory.CSharp
bool first = true;
foreach (var member in typeDeclaration.Members) {
if (!first) {
for (int i = 0; i < policy.BlankLinesBetweenMembers; i++)
for (int i = 0; i < policy.MinimumBlankLinesBetweenMembers; i++)
NewLine();
}
first = false;
@ -2066,7 +2066,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -2066,7 +2066,7 @@ namespace ICSharpCode.NRefactory.CSharp
nextSibling = nextSibling.NextSibling;
if ((node is UsingDeclaration || node is UsingAliasDeclaration) && !(nextSibling is UsingDeclaration || nextSibling is UsingAliasDeclaration)) {
for (int i = 0; i < policy.BlankLinesAfterUsings; i++)
for (int i = 0; i < policy.MinimumBlankLinesAfterUsings; i++)
NewLine();
}
}
@ -2220,6 +2220,9 @@ namespace ICSharpCode.NRefactory.CSharp @@ -2220,6 +2220,9 @@ namespace ICSharpCode.NRefactory.CSharp
WriteIdentifier(identifier);
}
void IAstVisitor.VisitNullNode(AstNode nullNode)
{
}
#endregion
#region Pattern Nodes

5
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs

@ -213,6 +213,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -213,6 +213,11 @@ namespace ICSharpCode.NRefactory.CSharp
{
return new CodeSnippetStatement(MakeSnippet(stmt));
}
CodeObject IAstVisitor<CodeObject>.VisitNullNode(AstNode nullNode)
{
return null;
}
CodeObject IAstVisitor<CodeObject>.VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression)
{

13
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-tokenizer.cs

@ -2466,12 +2466,14 @@ namespace Mono.CSharp @@ -2466,12 +2466,14 @@ namespace Mono.CSharp
int length = TokenizePreprocessorIdentifier (out c, out startCol, out endLine, out endCol);
#if FULL_AST
var pragmaDirective = sbag.GetPragmaPreProcessorDirective();
pragmaDirective.WarningColumn = startCol;
if (pragmaDirective != null)
pragmaDirective.WarningColumn = startCol;
#endif
if (length == pragma_warning.Length && IsTokenIdentifierEqual (pragma_warning)) {
length = TokenizePreprocessorIdentifier (out c, out startCol, out endLine, out endCol);
#if FULL_AST
pragmaDirective.DisableRestoreColumn = startCol;
if (pragmaDirective != null)
pragmaDirective.DisableRestoreColumn = startCol;
#endif
//
@ -2481,7 +2483,8 @@ namespace Mono.CSharp @@ -2481,7 +2483,8 @@ namespace Mono.CSharp
if (length == pragma_warning_disable.Length) {
bool disable = IsTokenIdentifierEqual (pragma_warning_disable);
#if FULL_AST
pragmaDirective.Disalbe = disable;
if (pragmaDirective != null)
pragmaDirective.Disalbe = disable;
#endif
if (disable || IsTokenIdentifierEqual (pragma_warning_restore)) {
// skip over white space
@ -2516,7 +2519,8 @@ namespace Mono.CSharp @@ -2516,7 +2519,8 @@ namespace Mono.CSharp
if (code > 0) {
#if FULL_AST
var literal = new IntConstant(context.BuiltinTypes, code, startLoc);
pragmaDirective.Codes.Add (literal);
if (pragmaDirective != null)
pragmaDirective.Codes.Add (literal);
// literal.ParsedValue = reader.ReadChars (read_start, reader.Position + 1);
#endif
if (disable) {
@ -2540,6 +2544,7 @@ namespace Mono.CSharp @@ -2540,6 +2544,7 @@ namespace Mono.CSharp
return;
}
//
// #pragma checksum
//

10
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/ecore.cs

@ -7017,15 +7017,15 @@ namespace Mono.CSharp { @@ -7017,15 +7017,15 @@ namespace Mono.CSharp {
{
return null;
}
protected override bool DoFlowAnalysis(FlowAnalysisContext fc)
public override object Accept (Mono.CSharp.StructuralVisitor visitor)
{
return false;
return visitor.Visit (this);
}
public override object Accept (Mono.CSharp.StructuralVisitor visitor)
protected override bool DoFlowAnalysis(FlowAnalysisContext fc)
{
return visitor.Visit (this);
return false;
}
}
}

3
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs

@ -746,13 +746,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -746,13 +746,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return false;
}
/*
bool PerformVirtualLookup(IMember member, IMember referencedMember)
{
if (FindCallsThroughVirtualBaseMethod && member.IsOverride && !WholeVirtualSlot)
return true;
var typeDef = referencedMember.DeclaringTypeDefinition;
return FindCallsThroughInterface && typeDef != null && typeDef.Kind == TypeKind.Interface;
}
}*/
sealed class FindFieldReferences : FindMemberReferencesNavigator
{

7
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs

@ -568,7 +568,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -568,7 +568,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
usingScope.Freeze();
resolver = resolver.WithCurrentUsingScope(new ResolvedUsingScope(resolver.CurrentTypeResolveContext, usingScope));
}
ResolveResult IAstVisitor<ResolveResult>.VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration)
{
CSharpResolver previousResolver = resolver;
@ -3929,6 +3929,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -3929,6 +3929,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return null;
}
ResolveResult IAstVisitor<ResolveResult>.VisitNullNode(AstNode nullNode)
{
return null;
}
ResolveResult IAstVisitor<ResolveResult>.VisitPatternPlaceholder(AstNode placeholder, ICSharpCode.NRefactory.PatternMatching.Pattern pattern)
{
return null;

201
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Util/CloneableStack.cs

@ -0,0 +1,201 @@ @@ -0,0 +1,201 @@
//
// CloneableStack.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Collections;
namespace ICSharpCode.NRefactory.CSharp
{
class CloneableStack<T> : IEnumerable<T>, ICollection<T>, ICloneable, IEquatable<CloneableStack<T>>
{
int count;
StackItem top;
#region IEnumerable[T] implementation
public IEnumerator<T> GetEnumerator ()
{
return new StackItemEnumerator (top);
}
IEnumerator IEnumerable.GetEnumerator ()
{
return new StackItemEnumerator (top);
}
#endregion
#region ICloneable implementation
public CloneableStack<T> Clone ()
{
CloneableStack<T> result = new CloneableStack<T> ();
result.count = count;
result.top = top;
return result;
}
object ICloneable.Clone ()
{
return Clone();
}
#endregion
public void Clear ()
{
top = null;
count = 0;
}
public void Push (T item)
{
top = new StackItem (top, item);
count++;
}
public T Peek ()
{
return top.Item;
}
public T Pop ()
{
T result = top.Item;
top = top.Parent;
count--;
return result;
}
#region IEquatable[T] implementation
public bool Equals (CloneableStack<T> other)
{
return ReferenceEquals (top, other.top);
}
#endregion
#region ICollection[T] implementation
void ICollection<T>.Add (T item)
{
Push (item);
}
void ICollection<T>.Clear ()
{
top = null;
count = 0;
}
bool ICollection<T>.Contains (T item)
{
foreach (T t in this) {
if (t.Equals (item))
return true;
}
return false;
}
void ICollection<T>.CopyTo (T[] array, int arrayIndex)
{
int idx = arrayIndex;
foreach (T t in this) {
array[idx++] = t;
}
}
bool ICollection<T>.Remove (T item)
{
throw new NotImplementedException ();
}
public int Count {
get {
return count;
}
}
bool ICollection<T>.IsReadOnly {
get {
return false;
}
}
#endregion
class StackItem
{
public readonly StackItem Parent;
public readonly T Item;
public StackItem (StackItem parent, T item)
{
Parent = parent;
Item = item;
}
}
class StackItemEnumerator : IEnumerator<T>
{
StackItem cur, first;
public StackItemEnumerator (StackItem cur)
{
this.cur = first = new StackItem (cur, default(T));
}
#region IDisposable implementation
void IDisposable.Dispose ()
{
cur = first = null;
}
#endregion
#region IEnumerator implementation
bool IEnumerator.MoveNext ()
{
if (cur == null)
return false;
cur = cur.Parent;
return cur != null;
}
void IEnumerator.Reset ()
{
cur = first;
}
object IEnumerator.Current {
get {
return cur.Item;
}
}
#endregion
#region IEnumerator[T] implementation
T IEnumerator<T>.Current {
get {
return cur.Item;
}
}
#endregion
}
}
}

52
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/AstStructureTests.cs

@ -59,5 +59,57 @@ namespace ICSharpCode.NRefactory.CSharp @@ -59,5 +59,57 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
}
[Test]
public void NullNodesCallVisitNullNode()
{
foreach (Type type in typeof(AstNode).Assembly.GetExportedTypes()) {
if (type.IsSubclassOf(typeof(AstNode))) {
var nullField = type.GetField("Null");
if (nullField != null) {
AstNode nullNode = (AstNode)nullField.GetValue(null);
Assert.IsTrue(nullNode.IsNull, nullNode.GetType().Name + " should be a null node");
var v1 = new VisitNullNodeTest();
var v2 = new VisitNullNodeTest<string>();
var v3 = new VisitNullNodeTest<string, string>();
nullNode.AcceptVisitor(v1);
nullNode.AcceptVisitor(v2);
nullNode.AcceptVisitor(v3, null);
Assert.IsTrue(v1.called, nullNode.GetType().Name + " should call 'void VisitNullNode();'");
Assert.IsTrue(v2.called, nullNode.GetType().Name + " should call 'T VisitNullNode();'");
Assert.IsTrue(v3.called, nullNode.GetType().Name + " should call 'S VisitNullNode(T data);'");
}
}
}
}
class VisitNullNodeTest : DepthFirstAstVisitor
{
internal bool called;
public override void VisitNullNode(AstNode nullNode)
{
called = true;
}
}
class VisitNullNodeTest<T> : DepthFirstAstVisitor<T>
{
internal bool called;
public override T VisitNullNode(AstNode nullNode)
{
called = true;
return base.VisitNullNode(nullNode);
}
}
class VisitNullNodeTest<T, S> : DepthFirstAstVisitor<T, S>
{
internal bool called;
public override S VisitNullNode(AstNode nullNode, T data)
{
called = true;
return base.VisitNullNode(nullNode, data);
}
}
}
}

4
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CSharpOutputVisitorTests.cs

@ -160,7 +160,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -160,7 +160,7 @@ namespace ICSharpCode.NRefactory.CSharp
";
var unit = SyntaxTree.Parse(code);
var options = FormattingOptionsFactory.CreateMono();
options.BlankLinesBetweenMembers = 2;
options.MinimumBlankLinesBetweenMembers = 2;
AssertOutput("class Test\n{\n$Test ()\n${\n$}\n\n\n$void Foo ()\n${\n$}\n\n\n$int P {\n$$get;\n$$set;\n$}\n}\n", unit, options);
}
@ -179,7 +179,7 @@ namespace NS @@ -179,7 +179,7 @@ namespace NS
";
var unit = SyntaxTree.Parse(code);
var options = FormattingOptionsFactory.CreateMono();
options.BlankLinesAfterUsings = 2;
options.MinimumBlankLinesAfterUsings = 2;
AssertOutput("using System;\nusing System.Collections;\nusing List = System.Collections.List;\n\n\nnamespace NS\n{\n$using System.Collections.Generic;\n$using Collection = System.Collections.Collection;\n$using System.Xml;\n\n\n$class C\n${\n$}\n}\n", unit, options);
}

8
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/AddUsing/AddUsingActionInsideNamespaceTests.cs

@ -32,7 +32,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions.AddUsing @@ -32,7 +32,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions.AddUsing
}";
formattingOptions.UsingPlacement = UsingPlacement.InsideNamespace;
formattingOptions.BlankLinesAfterUsings = 0;
formattingOptions.MinimumBlankLinesAfterUsings = 0;
Test(new AddUsingAction(), testCode, expectedOutput);
}
@ -62,8 +62,8 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions.AddUsing @@ -62,8 +62,8 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions.AddUsing
}";
formattingOptions.UsingPlacement = UsingPlacement.InsideNamespace;
formattingOptions.BlankLinesBeforeUsings = 2;
formattingOptions.BlankLinesAfterUsings = 0;
formattingOptions.MinimumBlankLinesBeforeUsings = 2;
formattingOptions.MinimumBlankLinesAfterUsings = 0;
Test(new AddUsingAction(), testCode, expectedOutput);
}
@ -93,7 +93,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions.AddUsing @@ -93,7 +93,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions.AddUsing
}";
formattingOptions.UsingPlacement = UsingPlacement.InsideNamespace;
formattingOptions.BlankLinesAfterUsings = 2;
formattingOptions.MinimumBlankLinesAfterUsings = 2;
Test(new AddUsingAction(), testCode, expectedOutput);
}

4
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/AddUsing/AddUsingRunActionTests.cs

@ -61,7 +61,7 @@ namespace TestNamespace @@ -61,7 +61,7 @@ namespace TestNamespace
}
}";
formattingOptions.BlankLinesAfterUsings = 2;
formattingOptions.MinimumBlankLinesAfterUsings = 2;
Test(new AddUsingAction(), testCode, expectedOutput);
}
@ -91,7 +91,7 @@ namespace TestNamespace @@ -91,7 +91,7 @@ namespace TestNamespace
}
}";
formattingOptions.BlankLinesBeforeUsings = 2;
formattingOptions.MinimumBlankLinesBeforeUsings = 2;
Test(new AddUsingAction(), testCode, expectedOutput);
}

83
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/CS1105ExtensionMethodMustBeDeclaredStaticActionTests.cs

@ -0,0 +1,83 @@ @@ -0,0 +1,83 @@
//
// CS1105ExtensionMethodMustBeDeclaredStaticActionTests.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using NUnit.Framework;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.CSharp.CodeActions;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.CodeIssues
{
[TestFixture]
public class CS1105ExtensionMethodMustBeDeclaredStaticActionTests : ContextActionTestBase
{
[Test]
public void TestMethod()
{
Test<CS1105ExtensionMethodMustBeDeclaredStaticAction> (
@"static class Foo
{
public void $FooBar (this string foo)
{
}
}",
@"static class Foo
{
public static void FooBar (this string foo)
{
}
}", 0, true);
}
[Test]
public void TestWrongContext1()
{
TestWrongContext<CS1105ExtensionMethodMustBeDeclaredStaticAction> (
@"static class Foo
{
public static void $FooBar (this string foo)
{
}
}");
}
[Test]
public void TestWrongContext2()
{
TestWrongContext<CS1105ExtensionMethodMustBeDeclaredStaticAction> (
@"class Foo
{
public void $FooBar (string foo)
{
}
}");
}
}
}

37
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs

@ -6314,5 +6314,42 @@ class Program @@ -6314,5 +6314,42 @@ class Program
");
Assert.IsTrue(provider == null || provider.Count == 0);
}
/// <summary>
/// Bug 17653 - Wrong completion entry in tuple factory method
/// </summary>
[Test]
public void TestBug17653 ()
{
CombinedProviderTest(@"using System;
class Foo
{
public static void Main (string[] args)
{
$Tuple.Create(new $
}
}
", provider => Assert.IsNull(provider.Find("T1"), "'T1' found (type parameter)."));
}
[Test]
public void TestBug17653_ValidTypeParameterCreation ()
{
CombinedProviderTest(@"using System;
class Foo<T1> where T1 : new()
{
public static void Main (string[] args)
{
$T1 t = new $
}
}
", provider => {
Assert.IsNotNull(provider.Find("T1"), "'T1' found (type parameter).");
Assert.AreEqual("T1", provider.DefaultCompletionString);
});
}
}
}

21
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/FunctionNeverReturnsIssueTests.cs

@ -26,6 +26,7 @@ @@ -26,6 +26,7 @@
using ICSharpCode.NRefactory.CSharp.Refactoring;
using NUnit.Framework;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.CodeIssues
{
@ -516,5 +517,25 @@ class TestClass @@ -516,5 +517,25 @@ class TestClass
}
}");
}
/// <summary>
/// Bug 17769 - Incorrect "method never returns" warning
/// </summary>
[Test]
public void TestBug17769 ()
{
TestWrongContext<FunctionNeverReturnsIssue> (@"
using System.Linq;
class A
{
A[] list = new A[0];
public bool Test ()
{
return list.Any (t => t.Test ());
}
}
");
}
}
}

173
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/StaticEventSubscriptionIssueTests.cs

@ -0,0 +1,173 @@ @@ -0,0 +1,173 @@
//
// StaticEventSubscriptionIssueTests.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.CSharp.CodeActions;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp.CodeIssues
{
[TestFixture]
public class StaticEventSubscriptionIssueTests: InspectionActionTestBase
{
[Test]
public void TestAnonymousMethodSubscription()
{
TestIssue<StaticEventSubscriptionIssue>(@"
using System;
class Foo
{
public static event EventHandler FooBar;
public void Test ()
{
FooBar += delegate {
Console.WriteLine (""Hello World!"");
};
}
}
");
}
[Test]
public void TestAnonymousMethodSubscription_ValidCase()
{
TestWrongContext<StaticEventSubscriptionIssue>(@"
using System;
class Foo
{
public static event EventHandler FooBar;
public static void Test ()
{
FooBar += delegate {
Console.WriteLine (""Hello World!"");
};
}
}
");
}
[Test]
public void TestIssue()
{
TestIssue<StaticEventSubscriptionIssue>(@"
using System;
class Foo
{
public static event EventHandler FooBar;
public void Test ()
{
FooBar += MyMethod;
}
void MyMethod (object sender, EventArgs args)
{
}
}
");
}
[Test]
public void TestNoIssue()
{
TestWrongContext<StaticEventSubscriptionIssue>(@"
using System;
class Foo
{
public static event EventHandler FooBar;
public void Test ()
{
FooBar += MyMethod;
}
public void Unsubscribe ()
{
FooBar -= MyMethod;
}
void MyMethod (object sender, EventArgs args)
{
}
}
");
}
[Test]
public void TestNonStatic()
{
TestWrongContext<StaticEventSubscriptionIssue>(@"
using System;
class Foo
{
public event EventHandler FooBar;
public void Test ()
{
FooBar += MyMethod;
}
void MyMethod (object sender, EventArgs args)
{
}
}
");
}
[Test]
public void TestNullAssignment()
{
TestWrongContext<StaticEventSubscriptionIssue>(@"
using System;
class Foo
{
public static event EventHandler FooBar;
public void Test ()
{
FooBar += MyMethod;
}
public void Unsubscribe ()
{
FooBar = null;
}
void MyMethod (object sender, EventArgs args)
{
}
}
");
}
}
}

18
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/XmlDocIssueIssueTests.cs

@ -150,6 +150,24 @@ namespace Foo { @@ -150,6 +150,24 @@ namespace Foo {
}
}");
}
/// <summary>
/// Bug 17729 - Incorrect XML-docs warning about 'value' paramref
/// </summary>
[Test]
public void TestBug17729 ()
{
TestWrongContext<XmlDocIssue>(@"
using System;
class Foo {
/// <summary>
/// If <paramref name=""value""/> is 0 ...
/// </summary>
public int Bar { get; set; }
}
");
}
}

665
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/ConstructFixerTests.cs

@ -0,0 +1,665 @@ @@ -0,0 +1,665 @@
//
// ConstructFixerTests.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using NUnit.Framework;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.Editor;
namespace ICSharpCode.NRefactory.CSharp.FormattingTests
{
[TestFixture]
public class ConstructFixerTests
{
static void Test (string input, string expectedOutput)
{
input = input.Replace("\r\n", "\n");
expectedOutput = expectedOutput.Replace("\r\n", "\n");
int caretPositon = input.IndexOf('$');
if (caretPositon > 0)
input = input.Substring(0, caretPositon) + input.Substring(caretPositon + 1);
var document1 = new StringBuilderDocument(input);
int expectedCaretPosition = expectedOutput.IndexOf('$');
if (expectedCaretPosition > 0)
expectedOutput = expectedOutput.Substring(0, expectedCaretPosition) + expectedOutput.Substring(expectedCaretPosition + 1);
var fixer = new ConstructFixer(FormattingOptionsFactory.CreateMono (), new TextEditorOptions { EolMarker = "\n" });
int newCaretPosition;
Assert.IsTrue(fixer.TryFix(document1, caretPositon, out newCaretPosition));
var isEqual = expectedOutput == document1.Text.Replace("\r\n", "\n");
if (!isEqual) {
System.Console.WriteLine("expected:");
System.Console.WriteLine(expectedOutput);
System.Console.WriteLine("was:");
System.Console.WriteLine(document1.Text);
}
Assert.IsTrue(isEqual);
Assert.AreEqual(expectedCaretPosition, newCaretPosition);
}
[Test]
public void TestMethodCallCase1()
{
Test(
@"
class Foo
{
void Bar (int i)
{
Bar (42$
}
}", @"
class Foo
{
void Bar (int i)
{
Bar (42);$
}
}");
}
[Test]
public void TestMethodCallCase2()
{
Test(
@"
class Foo
{
void Bar ()
{
Bar$ (;
}
}", @"
class Foo
{
void Bar ()
{
Bar ();$
}
}");
}
[Test]
public void TestMethodCallCase3()
{
Test(
@"
class Foo
{
void Bar ()
{
Bar ($)
}
}", @"
class Foo
{
void Bar ()
{
Bar ();$
}
}");
}
[Test]
public void TestClassDeclaration()
{
Test(@"class Foo$", @"class Foo
{
$
}");
}
[Ignore("Fixme - parser error")]
[Test]
public void TestClassDeclaration_TestErrorRecovery()
{
Test(@"class Foo$
// Foo
", @"class Foo
{
$
}
// Foo");
}
[Ignore("Fixme - parser error")]
[Test]
public void TestDelegateDeclaration()
{
Test(
@"delegate void FooHandler (object foo$",
@"delegate void FooHandler (object foo);
$");
}
[Ignore("Fixme - parser error")]
[Test]
public void TestMethodDeclaration()
{
Test(
@"
class Foo
{
void Bar (int i$
}
", @"
class Foo
{
void Bar (int i)
{
$
}
}");
}
[Ignore("Fixme - parser error")]
[Test]
public void TestFieldDeclaration()
{
Test(
@"
class Foo
{
int f$
}", @"
class Foo
{
inf f;
}");
}
[Test]
public void TestIfStatement()
{
Test(
@"
class Foo
{
void Bar (int i)
{
if (true$
}
}", @"
class Foo
{
void Bar (int i)
{
if (true) {
$
}
}
}");
}
[Ignore("Fixme - parser error")]
[Test]
public void TestFixedStatement()
{
Test(
@"
unsafe class Foo
{
void Bar (int i)
{
fixed (int* ptr = &i$
}
}", @"
unsafe class Foo
{
void Bar (int i)
{
fixed (int* ptr = &i) {
$
}
}
}");
}
[Ignore("Fixme - parser error")]
[Test]
public void TestUsingStatement()
{
Test(
@"
class Foo
{
void Bar ()
{
using (var foo = new Foo()$
}
}", @"
class Foo
{
void Bar ()
{
using (var foo = new Foo()) {
$
}
}
}");
}
[Test]
public void TestLockStatement()
{
Test(
@"
class Foo
{
void Bar ()
{
lock (foo$
}
}", @"
class Foo
{
void Bar ()
{
lock (foo) {
$
}
}
}");
}
[Ignore("Fixme - parser error")]
[Test]
public void TestForeachStatement()
{
Test(
@"
class Foo
{
void Bar (string s)
{
foreach (var c in s$
}
}", @"
class Foo
{
void Bar (string s)
{
foreach (var c in s) {
$
}
}
}");
}
[Test]
public void TestWhileStatement()
{
Test(
@"
class Foo
{
void Bar ()
{
while (true$
}
}", @"
class Foo
{
void Bar ()
{
while (true) {
$
}
}
}");
}
[Test]
public void TestSwitch()
{
Test(
@"
class Foo
{
void Bar (int i)
{
switch (i$
}
}
", @"
class Foo
{
void Bar (int i)
{
switch (i) {
$
}
}
}
");
}
[Ignore("Fixme - parser error")]
[Test]
public void TestCase()
{
Test(
@"
class Foo
{
void Bar (int i)
{
switch (i) {
case 1$
}
}
}
", @"
class Foo
{
void Bar (int i)
{
switch (i) {
case 1:
$
}
}
}");
}
[Ignore("Fixme - parser error")]
[Test]
public void TestBreakStatement()
{
Test(
@"
class Foo
{
void Bar ()
{
break$
}
}", @"
class Foo
{
void Bar ()
{
break;
}
}");
}
[Ignore("Fixme - parser error")]
[Test]
public void TestGotoStatement()
{
Test(
@"
class Foo
{
void Bar ()
{
goto foo$
}
}", @"
class Foo
{
void Bar ()
{
goto foo;
}
}");
}
[Test]
public void TestReturnStatement()
{
Test(
@"
class Foo
{
int Bar ()
{
return 5$
}
}", @"
class Foo
{
int Bar ()
{
return 5;$
}
}");
}
[Ignore("Fixme - parser error")]
[Test]
public void TestYieldBreakStatement()
{
Test(
@"
class Foo
{
int Bar ()
{
yield break$
}
}", @"
class Foo
{
int Bar ()
{
yield break;$
}
}");
}
[Test]
public void TestYieldReturnStatement()
{
Test(
@"
class Foo
{
int Bar ()
{
yield return 5$
}
}", @"
class Foo
{
int Bar ()
{
yield return 5;$
}
}");
}
[Test]
public void TestThrowStatement()
{
Test(
@"
class Foo
{
int Bar ()
{
throw new Exception()$
}
}", @"
class Foo
{
int Bar ()
{
throw new Exception();$
}
}");
}
[Test]
public void TestCheckedStatement()
{
Test(
@"
class Foo
{
void Bar ()
{
checked$
}
}", @"
class Foo
{
void Bar ()
{
checked {
$
}
}
}");
}
[Test]
public void TestUncheckedStatement()
{
Test(
@"
class Foo
{
void Bar ()
{
unchecked$
}
}", @"
class Foo
{
void Bar ()
{
unchecked {
$
}
}
}");
}
[Ignore("Fixme - parser error")]
[Test]
public void TestUnsafeStatement()
{
Test(
@"
class Foo
{
void Bar ()
{
unsafe$
}
}", @"
class Foo
{
void Bar ()
{
unsafe {
$
}
}
}");
}
[Ignore("Fixme - parser error")]
[Test]
public void TestContinueStatement()
{
Test(
@"
class Foo
{
void Bar ()
{
continue$
}
}", @"
class Foo
{
void Bar ()
{
continue;
}
}");
}
[Test]
public void TestDoWhile()
{
Test(
@"
class Foo
{
void Bar ()
{
do {
} while (true$
}
}", @"
class Foo
{
void Bar ()
{
do {
} while (true);$
}
}");
}
[Ignore("Fixme - parser error")]
[Test]
public void TestComplexCase()
{
Test(
@"
class Foo
{
bool Bar (int i)
{
if$ (Bar (1
}
}", @"
class Foo
{
bool Bar (int i)
{
if (Bar ((((Bar((1))))))) {
$
}
}
}");
}
}
}

116
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TestBlankLineFormatting.cs

@ -38,7 +38,7 @@ namespace ICSharpCode.NRefactory.CSharp.FormattingTests @@ -38,7 +38,7 @@ namespace ICSharpCode.NRefactory.CSharp.FormattingTests
public void TestBlankLinesAfterUsings ()
{
CSharpFormattingOptions policy = FormattingOptionsFactory.CreateMono ();
policy.BlankLinesAfterUsings = 2;
policy.MinimumBlankLinesAfterUsings = 2;
var adapter = Test (policy, @"using System;
using System.Text;
@ -49,14 +49,6 @@ namespace Test @@ -49,14 +49,6 @@ namespace Test
using System.Text;
namespace Test
{
}", FormattingMode.Intrusive);
policy.BlankLinesAfterUsings = 0;
Continue (policy, adapter,
@"using System;
using System.Text;
namespace Test
{
}", FormattingMode.Intrusive);
@ -66,8 +58,8 @@ namespace Test @@ -66,8 +58,8 @@ namespace Test
public void TestBlankLinesBeforeUsings ()
{
CSharpFormattingOptions policy = FormattingOptionsFactory.CreateMono ();
policy.BlankLinesAfterUsings = 0;
policy.BlankLinesBeforeUsings = 2;
policy.MinimumBlankLinesAfterUsings = 0;
policy.MinimumBlankLinesBeforeUsings = 2;
var adapter = Test (policy, @"using System;
using System.Text;
@ -80,14 +72,6 @@ using System; @@ -80,14 +72,6 @@ using System;
using System.Text;
namespace Test
{
}", FormattingMode.Intrusive);
policy.BlankLinesBeforeUsings = 0;
Continue (policy, adapter,
@"using System;
using System.Text;
namespace Test
{
}", FormattingMode.Intrusive);
}
@ -95,7 +79,7 @@ namespace Test @@ -95,7 +79,7 @@ namespace Test
public void TestBlankLinesBeforeFirstDeclaration ()
{
CSharpFormattingOptions policy = FormattingOptionsFactory.CreateMono ();
policy.BlankLinesBeforeFirstDeclaration = 2;
policy.MinimumBlankLinesBeforeFirstDeclaration = 2;
var adapter = Test (policy, @"namespace Test
{
@ -111,22 +95,14 @@ namespace Test @@ -111,22 +95,14 @@ namespace Test
{
}
}", FormattingMode.Intrusive);
policy.BlankLinesBeforeFirstDeclaration = 0;
Continue (policy, adapter,
@"namespace Test
{
class Test
{
}
}", FormattingMode.Intrusive);
}
[Test]
public void TestBlankLinesBetweenTypes ()
{
CSharpFormattingOptions policy = FormattingOptionsFactory.CreateMono ();
policy.BlankLinesBetweenTypes = 1;
policy.MinimumBlankLinesBetweenTypes = 1;
var adapter = Test (policy, @"namespace Test
{
@ -154,27 +130,14 @@ namespace Test @@ -154,27 +130,14 @@ namespace Test
{
}
}", FormattingMode.Intrusive);
policy.BlankLinesBetweenTypes = 0;
Continue (policy, adapter, @"namespace Test
{
class Test1
{
}
class Test2
{
}
class Test3
{
}
}", FormattingMode.Intrusive);
}
[Test]
public void TestBlankLinesBetweenFields ()
{
CSharpFormattingOptions policy = FormattingOptionsFactory.CreateMono ();
policy.BlankLinesBetweenFields = 1;
policy.MinimumBlankLinesBetweenFields = 1;
var adapter = Test (policy, @"class Test
{
@ -190,21 +153,14 @@ namespace Test @@ -190,21 +153,14 @@ namespace Test
int c;
}", FormattingMode.Intrusive);
policy.BlankLinesBetweenFields = 0;
Continue (policy, adapter, @"class Test
{
int a;
int b;
int c;
}", FormattingMode.Intrusive);
}
[Test]
public void TestBlankLinesBetweenEventFields ()
{
CSharpFormattingOptions policy = FormattingOptionsFactory.CreateMono ();
policy.BlankLinesBetweenEventFields = 1;
policy.MinimumBlankLinesBetweenEventFields = 1;
var adapter = Test (policy, @"class Test
{
@ -220,22 +176,14 @@ namespace Test @@ -220,22 +176,14 @@ namespace Test
public event EventHandler c;
}", FormattingMode.Intrusive);
policy.BlankLinesBetweenEventFields = 0;
Continue (policy, adapter,
@"class Test
{
public event EventHandler a;
public event EventHandler b;
public event EventHandler c;
}", FormattingMode.Intrusive);
}
[Test]
public void TestBlankLinesBetweenMembers ()
{
CSharpFormattingOptions policy = FormattingOptionsFactory.CreateMono ();
policy.BlankLinesBetweenMembers = 1;
policy.MinimumBlankLinesBetweenMembers = 1;
var adapter = Test (policy, @"class Test
{
@ -263,26 +211,13 @@ namespace Test @@ -263,26 +211,13 @@ namespace Test
}
}", FormattingMode.Intrusive);
policy.BlankLinesBetweenMembers = 0;
Continue (policy, adapter, @"class Test
{
void AMethod ()
{
}
void BMethod ()
{
}
void CMethod ()
{
}
}", FormattingMode.Intrusive);
}
[Test]
public void TestBlankLinesAroundRegion ()
{
CSharpFormattingOptions policy = FormattingOptionsFactory.CreateMono ();
policy.BlankLinesAroundRegion = 2;
policy.MinimumBlankLinesAroundRegion = 2;
var adapter = Test (policy, @"class Test
{
@ -312,27 +247,13 @@ namespace Test @@ -312,27 +247,13 @@ namespace Test
}
}", FormattingMode.Intrusive);
policy.BlankLinesAroundRegion = 0;
Continue (policy, adapter, @"class Test
{
#region FooBar
void AMethod ()
{
}
#endregion
void BMethod ()
{
}
}", FormattingMode.Intrusive);
}
[Test]
public void TestBlankLinesInsideRegion ()
{
CSharpFormattingOptions policy = FormattingOptionsFactory.CreateMono ();
policy.BlankLinesInsideRegion = 2;
policy.MinimumBlankLinesInsideRegion = 2;
var adapter = Test (policy, @"class Test
{
#region FooBar
@ -353,15 +274,6 @@ namespace Test @@ -353,15 +274,6 @@ namespace Test
#endregion
}", FormattingMode.Intrusive);
policy.BlankLinesInsideRegion = 0;
Continue (policy, adapter, @"class Test
{
#region FooBar
void AMethod ()
{
}
#endregion
}", FormattingMode.Intrusive);
}
/// <summary>

23
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TestGlobalLevelFormatting.cs

@ -94,26 +94,11 @@ class Foo @@ -94,26 +94,11 @@ class Foo
");
}
[Test]
public void TestOverlappingChangeBug ()
{
var policy = FormattingOptionsFactory.CreateMono ();
Test (policy,
@"//
using System;", @"//
using System;");
}
[Test]
public void TestUsingBlankLines ()
{
var policy = FormattingOptionsFactory.CreateMono();
policy.BlankLinesBeforeUsings = 2;
policy.MinimumBlankLinesBeforeUsings = 2;
Test(policy,
@"//
using System;",
@ -127,7 +112,7 @@ using System;"); @@ -127,7 +112,7 @@ using System;");
public void TestUsingBlankLinesCase2 ()
{
var policy = FormattingOptionsFactory.CreateMono();
policy.BlankLinesBeforeUsings = 2;
policy.MinimumBlankLinesBeforeUsings = 2;
Test(policy,
@"//
@ -143,7 +128,7 @@ using System;"); @@ -143,7 +128,7 @@ using System;");
public void TestUsingBlankLinesCase3 ()
{
var policy = FormattingOptionsFactory.CreateMono();
policy.BlankLinesBeforeUsings = 2;
policy.MinimumBlankLinesBeforeUsings = 2;
Test(policy,
@"
@ -157,7 +142,7 @@ using System;"); @@ -157,7 +142,7 @@ using System;");
public void TestUsingBlankLinesCase4 ()
{
var policy = FormattingOptionsFactory.CreateMono();
policy.BlankLinesBeforeUsings = 2;
policy.MinimumBlankLinesBeforeUsings = 2;
Test (policy,
@"using System;",
@"

2
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TestWrapping.cs

@ -632,7 +632,7 @@ int j, @@ -632,7 +632,7 @@ int j,
public void TestNoBlankLinesBetweenEndBraceAndEndParenthesis ()
{
CSharpFormattingOptions policy = FormattingOptionsFactory.CreateMono ();
policy.BlankLinesBetweenMembers = 1;
policy.MinimumBlankLinesBetweenMembers = 1;
Test (policy, @"class Test
{

3
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj

@ -616,6 +616,9 @@ @@ -616,6 +616,9 @@
<Compile Include="CSharp\CodeIssues\RedundantNotNullAttributeInNonNullableTypeTests.cs" />
<Compile Include="CSharp\CodeIssues\CS0618UsageOfObsoleteMemberIssueTests.cs" />
<Compile Include="CSharp\CodeIssues\CS0169FieldIsNeverUsedIssueTests.cs" />
<Compile Include="FormattingTests\ConstructFixerTests.cs" />
<Compile Include="CSharp\CodeIssues\StaticEventSubscriptionIssueTests.cs" />
<Compile Include="CSharp\CodeActions\CS1105ExtensionMethodMustBeDeclaredStaticActionTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\cecil\Mono.Cecil.csproj">

104
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/IndentationTests/BlockTest.cs

@ -1062,5 +1062,109 @@ class Foo { @@ -1062,5 +1062,109 @@ class Foo {
Assert.AreEqual("\t", indent.ThisLineIndent);
Assert.AreEqual("", indent.NextLineIndent);
}
[Test]
public void TestNextLineShifted_IfStatement()
{
var policy = FormattingOptionsFactory.CreateMono();
policy.StatementBraceStyle = BraceStyle.NextLineShifted;
var indent = Helper.CreateEngine(@"
class Foo
{
public static void Main (string[] args)
{
if (true)
{$
}
", policy);
Assert.AreEqual("\t\t\t", indent.ThisLineIndent);
Assert.AreEqual("\t\t\t", indent.NextLineIndent);
}
[Test]
public void TestPreprocessorIndenting_Case1()
{
var policy = FormattingOptionsFactory.CreateMono();
policy.StatementBraceStyle = BraceStyle.NextLineShifted;
var indent = Helper.CreateEngine(@"
using System;
class X
{
static void Foo (int arg)
{
#if !DEBUG
if (arg > 0) {
#else$
if (arg < 0) {
#endif
}
}
public static void Main ()
{
}
}", policy);
Assert.AreEqual("\t\t", indent.ThisLineIndent);
}
[Test]
public void TestPreprocessorIndenting_Case2()
{
var policy = FormattingOptionsFactory.CreateMono();
policy.StatementBraceStyle = BraceStyle.NextLineShifted;
var indent = Helper.CreateEngine(@"
using System;
class X
{
static void Foo (int arg)
{
#if !DEBUG
if (arg > 0) {
#else
if (arg < 0) {$
#endif
}
}
public static void Main ()
{
}
}", policy);
Assert.AreEqual("\t\t", indent.ThisLineIndent);
Assert.AreEqual("\t\t", indent.NextLineIndent);
}
[Test]
public void TestPreprocessorIndenting_Case3()
{
var policy = FormattingOptionsFactory.CreateMono();
policy.StatementBraceStyle = BraceStyle.NextLineShifted;
var indent = Helper.CreateEngine(@"
using System;
class X
{
static void Foo (int arg)
{
#if !DEBUG
if (arg > 0) {
#else
if (arg < 0) {
#endif
$
}
}
public static void Main ()
{
}
}", policy);
Assert.AreEqual("\t\t\t", indent.ThisLineIndent);
Assert.AreEqual("\t\t\t", indent.NextLineIndent);
}
}
}

60
src/Libraries/NRefactory/ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs

@ -102,14 +102,15 @@ namespace ICSharpCode.NRefactory.Documentation @@ -102,14 +102,15 @@ namespace ICSharpCode.NRefactory.Documentation
XmlDocumentationCache cache = new XmlDocumentationCache();
readonly string fileName;
DateTime lastWriteDate;
IndexEntry[] index; // SORTED array of index entries
volatile IndexEntry[] index; // SORTED array of index entries
#region Constructor / Redirection support
/// <summary>
/// Creates a new XmlDocumentationProvider.
/// </summary>
/// <param name="fileName">Name of the .xml file.</param>
/// <exception cref="IOException">Error reading from XML file (or from redirected file)</exception>
/// <exception cref="XmlException">Invalid XML file</exception>
public XmlDocumentationProvider(string fileName)
{
if (fileName == null)
@ -203,7 +204,7 @@ namespace ICSharpCode.NRefactory.Documentation @@ -203,7 +204,7 @@ namespace ICSharpCode.NRefactory.Documentation
#region Load / Create Index
void ReadXmlDoc(XmlTextReader reader)
{
lastWriteDate = File.GetLastWriteTimeUtc(fileName);
//lastWriteDate = File.GetLastWriteTimeUtc(fileName);
// Open up a second file stream for the line<->position mapping
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)) {
LinePositionMapper linePosMapper = new LinePositionMapper(fs);
@ -218,7 +219,7 @@ namespace ICSharpCode.NRefactory.Documentation @@ -218,7 +219,7 @@ namespace ICSharpCode.NRefactory.Documentation
}
}
indexList.Sort();
this.index = indexList.ToArray();
this.index = indexList.ToArray(); // volatile write
}
}
@ -295,8 +296,13 @@ namespace ICSharpCode.NRefactory.Documentation @@ -295,8 +296,13 @@ namespace ICSharpCode.NRefactory.Documentation
{
if (key == null)
throw new ArgumentNullException("key");
return GetDocumentation(key, true);
}
string GetDocumentation(string key, bool allowReload)
{
int hashcode = GetHashCode(key);
var index = this.index; // read volatile field
// index is sorted, so we can use binary search
int m = Array.BinarySearch(index, new IndexEntry(hashcode, 0));
if (m < 0)
@ -310,18 +316,48 @@ namespace ICSharpCode.NRefactory.Documentation @@ -310,18 +316,48 @@ namespace ICSharpCode.NRefactory.Documentation
lock (cache) {
string val;
if (!cache.TryGet(key, out val)) {
// go through all items that have the correct hash
while (++m < index.Length && index[m].HashCode == hashcode) {
val = LoadDocumentation(key, index[m].PositionInFile);
if (val != null)
break;
try {
// go through all items that have the correct hash
while (++m < index.Length && index[m].HashCode == hashcode) {
val = LoadDocumentation(key, index[m].PositionInFile);
if (val != null)
break;
}
// cache the result (even if it is null)
cache.Add(key, val);
} catch (IOException) {
// may happen if the documentation file was deleted/is inaccessible/changed (EndOfStreamException)
return allowReload ? ReloadAndGetDocumentation(key) : null;
} catch (XmlException) {
// may happen if the documentation file was changed so that the file position no longer starts on a valid XML element
return allowReload ? ReloadAndGetDocumentation(key) : null;
}
// cache the result (even if it is null)
cache.Add(key, val);
}
return val;
}
}
string ReloadAndGetDocumentation(string key)
{
try {
// Reload the index
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)) {
using (XmlTextReader xmlReader = new XmlTextReader(fs)) {
xmlReader.XmlResolver = null; // no DTD resolving
xmlReader.MoveToContent();
ReadXmlDoc(xmlReader);
}
}
} catch (IOException) {
// Ignore errors on reload; IEntity.Documentation callers aren't prepared to handle exceptions
this.index = new IndexEntry[0]; // clear index to avoid future load attempts
return null;
} catch (XmlException) {
this.index = new IndexEntry[0]; // clear index to avoid future load attempts
return null;
}
return GetDocumentation(key, allowReload: false); // prevent infinite reload loops
}
#endregion
#region GetDocumentation for entity

9
src/Libraries/NRefactory/ICSharpCode.NRefactory/Editor/UnicodeNewline.cs

@ -322,7 +322,14 @@ namespace ICSharpCode.NRefactory @@ -322,7 +322,14 @@ namespace ICSharpCode.NRefactory
/// </summary>
public static bool IsNewLine(char ch)
{
return GetDelimiterLength (ch) > 0;
return
ch == NewLine.CR ||
ch == NewLine.LF ||
ch == NewLine.NEL ||
ch == NewLine.VT ||
ch == NewLine.FF ||
ch == NewLine.LS ||
ch == NewLine.PS;
}
/// <summary>

2
src/Libraries/NRefactory/ICSharpCode.NRefactory/Semantics/SizeOfResolveResult.cs

@ -22,7 +22,7 @@ using ICSharpCode.NRefactory.TypeSystem; @@ -22,7 +22,7 @@ using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Semantics
{
/// <summary>
/// Represents the 'typeof'.
/// Represents the 'sizeof'.
/// </summary>
public class SizeOfResolveResult : ResolveResult
{

11
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/TypeSystemExtensions.cs

@ -237,16 +237,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -237,16 +237,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
);
}
case SymbolKind.Namespace:
INamespace ns = (INamespace)symbol;
if (ns.ParentNamespace == null) {
return compilation.RootNamespace;
} else {
INamespace importedParent = Import(compilation, ns.ParentNamespace);
if (importedParent != null)
return importedParent.GetChildNamespace(ns.Name);
else
return null;
}
return Import(compilation, (INamespace)symbol);
default:
if (symbol is IEntity)
return Import(compilation, (IEntity)symbol);

Loading…
Cancel
Save