Browse Source
1663c9a Fix NamespaceDefinitionOverwritesTypeName unit test. b6845ed Fix icsharpcode/NRefactory#385 - Can't resolve indexer with protected access modifier 16f49e7 Try to fix a namespace name lookup bug. 5aded3f Fixed bug in 'ConvertToLambdaExpressionIssue'. 61c10b1 Categorized some code issues. 2b54760 Fixed bug in 'DelegateSubtractionIssue'. bae55fb Fixed 'IsInactiveConditionalMethod' in SemanticHighlightingVisitor. 2a7a8bb Fixed possible infinite loop. 8acf7df Fix CSharpAmbience output for classes in the global namespace. 830e7d6 Fixed bug in xmldoc issue. df27cc6 Revert "Merged Hint & Suggestion severity. (These two are too close and" fc6f5c7 Merged Hint & Suggestion severity. (These two are too close and doesn't really make sense to separate) 7eaf69e Fixed 'Bug 17945 - Bad 'unnecessary cast' warning'. 008b2b0 Fix potential NullReferenceException in TypeSystemAstBuilder.ConvertConstructor b92cbff Fix potential InvalidCastException in AccessToClosureIssue. 5a31546 Fix NullReferenceException when calling GetBaseMembers() on global method. b31436e Merge pull request icsharpcode/NRefactory#384 from DavidKarlas/master 93ab8b3 Fixing Constructor Initializer placement and new adding policies NewLineBeforeConstructorInitializerColon and NewLineAfterConstructorInitializerColon a219cff Fixed a bug in constant value type system conversion. 5056b18 Fixed unit tests. a31d543 Improved GetTypeForQueryVariable f5d76b8 Removed resolveinvocationongiventarget call. 0dcf0a3 Added another work around for the query variable issue. cdd1892 Revert "Try to use a syntactical approach for resolving lambda expressions." ffdb464 Try to use a syntactical approach for resolving lambda expressions. 1bd7434 Added failing unit test. be4d1c0 Improved CS0618UsageOfObsoleteMemberIssue d20744e Set XmlResolver=null to avoid looking up external DTDs. ff9fee2 Fix bug in AstNode.GetNodesBetween().pull/387/merge
56 changed files with 1113 additions and 569 deletions
0
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Uncategorized/CompilerErrors/CS1729TypeHasNoConstructorWithNArgumentsIssue.cs → src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Custom/CompilerErrors/CS1729TypeHasNoConstructorWithNArgumentsIssue.cs
0
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Uncategorized/CompilerErrors/CS1729TypeHasNoConstructorWithNArgumentsIssue.cs → src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Custom/CompilerErrors/CS1729TypeHasNoConstructorWithNArgumentsIssue.cs
@ -1,175 +0,0 @@
@@ -1,175 +0,0 @@
|
||||
//
|
||||
// OptionalParameterCouldBeSkippedIssue.cs
|
||||
//
|
||||
// Author:
|
||||
// Simon Lindgren <simon.n.lindgren@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2012 Simon Lindgren
|
||||
//
|
||||
// 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.Collections.Generic; |
||||
using ICSharpCode.NRefactory.CSharp.Resolver; |
||||
using System.Linq; |
||||
using ICSharpCode.NRefactory.Semantics; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using System; |
||||
using ICSharpCode.NRefactory.Refactoring; |
||||
|
||||
namespace ICSharpCode.NRefactory.CSharp.Refactoring |
||||
{ |
||||
[IssueDescription("Optional argument has default value and can be skipped", |
||||
Description = "Finds calls to functions where optional parameters are used and the passed argument is the same as the default.", |
||||
Category = IssueCategories.RedundanciesInCode, |
||||
Severity = Severity.Hint)] |
||||
public class OptionalParameterCouldBeSkippedIssue : GatherVisitorCodeIssueProvider |
||||
{ |
||||
protected override IGatherVisitor CreateVisitor(BaseRefactoringContext context) |
||||
{ |
||||
return new GatherVisitor(context); |
||||
} |
||||
|
||||
class GatherVisitor : GatherVisitorBase<OptionalParameterCouldBeSkippedIssue> |
||||
{ |
||||
static readonly object removeAllRedundantArgumentsKey = new object (); |
||||
|
||||
public GatherVisitor(BaseRefactoringContext context) : base (context) |
||||
{ |
||||
} |
||||
|
||||
public override void VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression) |
||||
{ |
||||
base.VisitObjectCreateExpression(objectCreateExpression); |
||||
|
||||
CheckMethodCall(objectCreateExpression, objectCreateExpression.Arguments, |
||||
(objectCreation, args) => new ObjectCreateExpression(objectCreation.Type.Clone(), args)); |
||||
} |
||||
|
||||
public override void VisitInvocationExpression(InvocationExpression invocationExpression) |
||||
{ |
||||
base.VisitInvocationExpression(invocationExpression); |
||||
|
||||
CheckMethodCall(invocationExpression, invocationExpression.Arguments, |
||||
(invocation, args) => new InvocationExpression(invocation.Target.Clone(), args)); |
||||
} |
||||
|
||||
void CheckMethodCall<T> (T node, IEnumerable<Expression> args, Func<T, IEnumerable<Expression>, T> generateReplacement) where T: AstNode |
||||
{ |
||||
// The first two checks are unnecessary, but eliminates the majority of calls early,
|
||||
// improving performance.
|
||||
var arguments = args.ToArray(); |
||||
if (arguments.Length == 0) |
||||
return; |
||||
var lastArg = arguments[arguments.Length - 1]; |
||||
if (!(lastArg is PrimitiveExpression || lastArg is NamedArgumentExpression)) |
||||
return; |
||||
|
||||
var invocationResolveResult = ctx.Resolve(node) as CSharpInvocationResolveResult; |
||||
if (invocationResolveResult == null) |
||||
return; |
||||
|
||||
string actionMessage = ctx.TranslateString("Remove redundant arguments"); |
||||
|
||||
var redundantArguments = GetRedundantArguments(arguments, invocationResolveResult); |
||||
var action = new CodeAction(actionMessage, script => { |
||||
var newArgumentList = arguments |
||||
.Where(arg => !redundantArguments.Contains(arg)) |
||||
.Select(arg => arg.Clone()); |
||||
var newInvocation = generateReplacement(node, newArgumentList); |
||||
script.Replace(node, newInvocation); |
||||
}, node, removeAllRedundantArgumentsKey); |
||||
var issueMessage = ctx.TranslateString("Argument is identical to the default value"); |
||||
var lastPositionalArgument = redundantArguments.FirstOrDefault(expression => !(expression is NamedArgumentExpression)); |
||||
|
||||
foreach (var argument in redundantArguments) { |
||||
var localArgument = argument; |
||||
var actions = new List<CodeAction>(); |
||||
actions.Add(action); |
||||
|
||||
if (localArgument is NamedArgumentExpression || localArgument == lastPositionalArgument) { |
||||
var title = ctx.TranslateString("Remove this argument"); |
||||
actions.Add(new CodeAction(title, script => { |
||||
var newArgumentList = arguments |
||||
.Where(arg => arg != localArgument) |
||||
.Select(arg => arg.Clone()); |
||||
var newInvocation = generateReplacement(node, newArgumentList); |
||||
script.Replace(node, newInvocation); |
||||
}, node, null)); |
||||
} else { |
||||
var title = ctx.TranslateString("Remove this and the following positional arguments"); |
||||
actions.Add(new CodeAction(title, script => { |
||||
var newArgumentList = arguments |
||||
.Where(arg => arg.StartLocation < localArgument.StartLocation && !(arg is NamedArgumentExpression)) |
||||
.Select(arg => arg.Clone()); |
||||
var newInvocation = generateReplacement(node, newArgumentList); |
||||
script.Replace(node, newInvocation); |
||||
}, node, null)); |
||||
} |
||||
|
||||
AddIssue(new CodeIssue(localArgument, issueMessage, actions) { IssueMarker = IssueMarker.GrayOut }); |
||||
} |
||||
} |
||||
|
||||
IList<Expression> GetRedundantArguments(Expression[] arguments, CSharpInvocationResolveResult invocationResolveResult) |
||||
{ |
||||
var argumentToParameterMap = invocationResolveResult.GetArgumentToParameterMap(); |
||||
var resolvedParameters = invocationResolveResult.Member.Parameters; |
||||
|
||||
IList<Expression> redundantArguments = new List<Expression>(); |
||||
|
||||
for (int i = arguments.Length - 1; i >= 0; i--) { |
||||
var parameterIndex = argumentToParameterMap[i]; |
||||
if (parameterIndex == -1) |
||||
// This particular parameter is an error, but keep trying the other ones
|
||||
continue; |
||||
var parameter = resolvedParameters[parameterIndex]; |
||||
var argument = arguments[i]; |
||||
if (argument is PrimitiveExpression) { |
||||
if (parameter.IsParams) |
||||
// before positional params arguments all optional arguments are needed, otherwise some of the
|
||||
// param arguments will be shifted out of the params into the fixed parameters
|
||||
break; |
||||
if (!parameter.IsOptional) |
||||
// There can be no optional parameters preceding a required one
|
||||
break; |
||||
var argumentResolveResult = ctx.Resolve(argument) as ConstantResolveResult; |
||||
if (argumentResolveResult == null || parameter.ConstantValue != argumentResolveResult.ConstantValue) |
||||
// Stop here since any arguments before this one has to be there
|
||||
// to enable the passing of this argument
|
||||
break; |
||||
redundantArguments.Add(argument); |
||||
} else if (argument is NamedArgumentExpression) { |
||||
var expression = ((NamedArgumentExpression)argument).Expression as PrimitiveExpression; |
||||
if (expression == null) |
||||
continue; |
||||
var expressionResolveResult = ctx.Resolve(expression) as ConstantResolveResult; |
||||
if (expressionResolveResult == null || parameter.ConstantValue != expressionResolveResult.ConstantValue) |
||||
// continue, since there can still be more arguments that are redundant
|
||||
continue; |
||||
redundantArguments.Add(argument); |
||||
} else { |
||||
// This is a non-constant positional argument => no more redundancies are possible
|
||||
break; |
||||
} |
||||
} |
||||
return redundantArguments; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
@ -1,305 +0,0 @@
@@ -1,305 +0,0 @@
|
||||
//
|
||||
// OptionalParameterCouldBeSkippedTests.cs
|
||||
//
|
||||
// Author:
|
||||
// Simon Lindgren <simon.n.lindgren@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2012 Simon Lindgren
|
||||
//
|
||||
// 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 NUnit.Framework; |
||||
using ICSharpCode.NRefactory.CSharp.CodeActions; |
||||
using ICSharpCode.NRefactory.CSharp.Refactoring; |
||||
|
||||
namespace ICSharpCode.NRefactory.CSharp.CodeIssues |
||||
{ |
||||
[TestFixture] |
||||
public class OptionalParameterCouldBeSkippedTests : InspectionActionTestBase |
||||
{ |
||||
[Test] |
||||
public void SimpleCase() |
||||
{ |
||||
var input = @"
|
||||
class TestClass |
||||
{ |
||||
void Foo(string a1 = ""a1"") |
||||
{ |
||||
} |
||||
|
||||
void Bar() |
||||
{ |
||||
Foo (""a1""); |
||||
} |
||||
}";
|
||||
TestRefactoringContext context; |
||||
var issues = GetIssues(new OptionalParameterCouldBeSkippedIssue(), input, out context); |
||||
Assert.AreEqual(1, issues.Count); |
||||
var issue = issues [0]; |
||||
Assert.AreEqual(2, issue.Actions.Count); |
||||
|
||||
CheckFix(context, issues [0], @"
|
||||
class TestClass |
||||
{ |
||||
void Foo(string a1 = ""a1"") |
||||
{ |
||||
} |
||||
|
||||
void Bar() |
||||
{ |
||||
Foo (); |
||||
} |
||||
}");
|
||||
} |
||||
|
||||
[Test] |
||||
public void ChecksConstructors() |
||||
{ |
||||
var input = @"
|
||||
class TestClass |
||||
{ |
||||
public TestClass(string a1 = ""a1"") |
||||
{ |
||||
} |
||||
|
||||
void Bar() |
||||
{ |
||||
var foo = new TestClass (""a1""); |
||||
} |
||||
}";
|
||||
TestRefactoringContext context; |
||||
var issues = GetIssues(new OptionalParameterCouldBeSkippedIssue(), input, out context); |
||||
Assert.AreEqual(1, issues.Count); |
||||
var issue = issues [0]; |
||||
Assert.AreEqual(2, issue.Actions.Count); |
||||
|
||||
CheckFix(context, issues [0], @"
|
||||
class TestClass |
||||
{ |
||||
public TestClass(string a1 = ""a1"") |
||||
{ |
||||
} |
||||
|
||||
void Bar() |
||||
{ |
||||
var foo = new TestClass (); |
||||
} |
||||
}");
|
||||
} |
||||
|
||||
[Test] |
||||
public void IgnoresAllParametersPreceedingANeededOne() |
||||
{ |
||||
var input = @"
|
||||
class TestClass |
||||
{ |
||||
void Foo(string a1 = ""a1"", string a2 = ""a2"", string a3 = ""a3"") |
||||
{ |
||||
} |
||||
|
||||
void Bar() |
||||
{ |
||||
Foo (""a1"", ""Another string"", ""a3""); |
||||
} |
||||
}";
|
||||
TestRefactoringContext context; |
||||
var issues = GetIssues(new OptionalParameterCouldBeSkippedIssue(), input, out context); |
||||
Assert.AreEqual(1, issues.Count); |
||||
var issue = issues [0]; |
||||
Assert.AreEqual(2, issue.Actions.Count); |
||||
|
||||
CheckFix(context, issues [0], @"
|
||||
class TestClass |
||||
{ |
||||
void Foo(string a1 = ""a1"", string a2 = ""a2"", string a3 = ""a3"") |
||||
{ |
||||
} |
||||
|
||||
void Bar() |
||||
{ |
||||
Foo (""a1"", ""Another string""); |
||||
} |
||||
}");
|
||||
} |
||||
|
||||
[Test] |
||||
public void ChecksParametersIfParamsAreUnused() |
||||
{ |
||||
var input = @"
|
||||
class TestClass |
||||
{ |
||||
void Foo(string a1 = ""a1"", string a2 = ""a2"", string a3 = ""a3"", params string[] extraStrings) |
||||
{ |
||||
} |
||||
|
||||
void Bar() |
||||
{ |
||||
Foo (""a1"", ""a2"", ""a3""); |
||||
} |
||||
}";
|
||||
TestRefactoringContext context; |
||||
var issues = GetIssues(new OptionalParameterCouldBeSkippedIssue(), input, out context); |
||||
Assert.AreEqual(3, issues.Count); |
||||
Assert.AreEqual(2, issues[0].Actions.Count); |
||||
Assert.AreEqual(2, issues[1].Actions.Count); |
||||
Assert.AreEqual(2, issues[2].Actions.Count); |
||||
|
||||
CheckFix(context, issues [2], @"
|
||||
class TestClass |
||||
{ |
||||
void Foo(string a1 = ""a1"", string a2 = ""a2"", string a3 = ""a3"", params string[] extraStrings) |
||||
{ |
||||
} |
||||
|
||||
void Bar() |
||||
{ |
||||
Foo (); |
||||
} |
||||
}");
|
||||
} |
||||
|
||||
[Test] |
||||
public void IgnoresIfParamsAreUsed() |
||||
{ |
||||
var input = @"
|
||||
class TestClass |
||||
{ |
||||
void Foo(string a1 = ""a1"", string a2 = ""a2"", string a3 = ""a3"", params string[] extraStrings) |
||||
{ |
||||
} |
||||
|
||||
void Bar() |
||||
{ |
||||
Foo (""a1"", ""a2"", ""a3"", ""extraString""); |
||||
} |
||||
}";
|
||||
TestRefactoringContext context; |
||||
var issues = GetIssues(new OptionalParameterCouldBeSkippedIssue(), input, out context); |
||||
Assert.AreEqual(0, issues.Count); |
||||
} |
||||
|
||||
[Test] |
||||
public void NamedArgument() |
||||
{ |
||||
var input = @"
|
||||
class TestClass |
||||
{ |
||||
void Foo(string a1 = ""a1"", string a2 = ""a2"") |
||||
{ |
||||
} |
||||
|
||||
void Bar() |
||||
{ |
||||
Foo (a2: ""a2""); |
||||
} |
||||
}";
|
||||
TestRefactoringContext context; |
||||
var issues = GetIssues(new OptionalParameterCouldBeSkippedIssue(), input, out context); |
||||
Assert.AreEqual(1, issues.Count); |
||||
Assert.AreEqual(2, issues[0].Actions.Count); |
||||
|
||||
CheckFix(context, issues [0], @"
|
||||
class TestClass |
||||
{ |
||||
void Foo(string a1 = ""a1"", string a2 = ""a2"") |
||||
{ |
||||
} |
||||
|
||||
void Bar() |
||||
{ |
||||
Foo (); |
||||
} |
||||
}");
|
||||
} |
||||
|
||||
[Test] |
||||
public void DoesNotStopAtDifferingNamedParameters() |
||||
{ |
||||
var input = @"
|
||||
class TestClass |
||||
{ |
||||
void Foo(string a1 = ""a1"", string a2 = ""a2"", string a3 = ""a3"") |
||||
{ |
||||
} |
||||
|
||||
void Bar() |
||||
{ |
||||
Foo (""a1"", ""a2"", a3: ""non-default""); |
||||
} |
||||
}";
|
||||
TestRefactoringContext context; |
||||
var issues = GetIssues(new OptionalParameterCouldBeSkippedIssue(), input, out context); |
||||
Assert.AreEqual(2, issues.Count); |
||||
Assert.AreEqual(2, issues[0].Actions.Count); |
||||
Assert.AreEqual(2, issues[1].Actions.Count); |
||||
|
||||
CheckFix(context, issues [1], @"
|
||||
class TestClass |
||||
{ |
||||
void Foo(string a1 = ""a1"", string a2 = ""a2"", string a3 = ""a3"") |
||||
{ |
||||
} |
||||
|
||||
void Bar() |
||||
{ |
||||
Foo (a3: ""non-default""); |
||||
} |
||||
}");
|
||||
} |
||||
|
||||
[Test] |
||||
public void DoesNotStopAtNamedParamsArray() |
||||
{ |
||||
var input = @"
|
||||
class TestClass |
||||
{ |
||||
void Foo(string a1 = ""a1"", string a2 = ""a2"", params string[] extras) |
||||
{ |
||||
} |
||||
|
||||
void Bar() |
||||
{ |
||||
Foo (""a1"", ""a2"", extras: new [] { ""extra1"" }); |
||||
} |
||||
}";
|
||||
TestRefactoringContext context; |
||||
var issues = GetIssues(new OptionalParameterCouldBeSkippedIssue(), input, out context); |
||||
Assert.AreEqual(2, issues.Count); |
||||
Assert.AreEqual(2, issues[0].Actions.Count); |
||||
Assert.AreEqual(2, issues[1].Actions.Count); |
||||
|
||||
// TODO: Fix formatting
|
||||
CheckFix(context, issues [1], @"
|
||||
class TestClass |
||||
{ |
||||
void Foo(string a1 = ""a1"", string a2 = ""a2"", params string[] extras) |
||||
{ |
||||
} |
||||
|
||||
void Bar() |
||||
{ |
||||
Foo (extras: new[] { |
||||
""extra1"" |
||||
}); |
||||
} |
||||
}");
|
||||
} |
||||
} |
||||
} |
||||
|
||||
Loading…
Reference in new issue