Browse Source

[CodeIssues] Adding an issue that highlights when a base class does not have a parameterless constructor, and the child class does not invoke any of the base class constructors.

pull/32/merge
Adam Connelly 13 years ago
parent
commit
4f3695ca03
  1. 23
      ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
  2. 60
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/NoDefaultConstructorIssue.cs
  3. 87
      ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/NoDefaultConstructorIssueTests.cs
  4. 21
      ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj

23
ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj

@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<ProductVersion>10.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<SignAssembly>True</SignAssembly>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>..\ICSharpCode.NRefactory.snk</AssemblyOriginatorKeyFile>
<DelaySign>False</DelaySign>
<AssemblyOriginatorKeyMode>File</AssemblyOriginatorKeyMode>
@ -40,14 +40,13 @@ @@ -40,14 +40,13 @@
<DefineConstants>TRACE;FULL_AST;NET_4_0</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>PdbOnly</DebugType>
<DebugSymbols>false</DebugSymbols>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<DebugType>none</DebugType>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugType>Full</DebugType>
<DebugType>full</DebugType>
<DebugSymbols>true</DebugSymbols>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'net_4_5_Debug' ">
<Optimize>False</Optimize>
@ -56,9 +55,10 @@ @@ -56,9 +55,10 @@
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'net_4_5_Debug|AnyCPU' ">
<DebugType>Full</DebugType>
<DebugType>full</DebugType>
<DebugSymbols>true</DebugSymbols>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'net_4_5_Release' ">
<Optimize>True</Optimize>
@ -67,9 +67,9 @@ @@ -67,9 +67,9 @@
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'net_4_5_Release|AnyCPU' ">
<DebugType>PdbOnly</DebugType>
<DebugSymbols>false</DebugSymbols>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<DebugType>none</DebugType>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
@ -503,6 +503,7 @@ @@ -503,6 +503,7 @@
<Compile Include="Refactoring\CodeIssues\ParameterCanBeDemotedIssue\IsArrayTypeCriterion.cs" />
<Compile Include="Refactoring\CodeIssues\ParameterCanBeDemotedIssue\SupportsIndexingCriterion.cs" />
<Compile Include="Refactoring\CodeIssues\RedundantWhereWithPredicateIssue.cs" />
<Compile Include="Refactoring\CodeIssues\NoDefaultConstructorIssue.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">

60
ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/NoDefaultConstructorIssue.cs

@ -0,0 +1,60 @@ @@ -0,0 +1,60 @@
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[IssueDescription ("No default constructor in base class",
Description = "There is no default constructor in the base class",
Category = IssueCategories.CompilerErrors,
Severity = Severity.Error,
IssueMarker = IssueMarker.Underline)]
public class NoDefaultConstructorIssue : ICodeIssueProvider
{
public IEnumerable<CodeIssue> GetIssues(BaseRefactoringContext context)
{
return new GatherVisitor(context).GetIssues();
}
private class GatherVisitor : GatherVisitorBase
{
private bool initializerInvoked;
public GatherVisitor(BaseRefactoringContext context)
: base(context)
{
}
public override void VisitTypeDeclaration(TypeDeclaration typeDeclaration)
{
var result = ctx.Resolve(typeDeclaration) as TypeResolveResult;
var baseType = result.Type.GetNonInterfaceBaseTypes().FirstOrDefault(t => !t.IsKnownType(KnownTypeCode.Object) && !object.Equals(t, result.Type));
if (baseType != null)
{
var constructor = baseType.GetConstructors(c => c.Parameters.Count == 0).FirstOrDefault();
if (constructor == null) {
base.VisitTypeDeclaration(typeDeclaration);
if (!this.initializerInvoked) {
var identifier = typeDeclaration.GetChildByRole(Roles.Identifier);
this.AddIssue(identifier, ctx.TranslateString("There is no default constructor in the base class"));
}
}
}
}
public override void VisitConstructorInitializer(ConstructorInitializer constructorInitializer)
{
var result = ctx.Resolve(constructorInitializer);
if (!result.IsError) {
this.initializerInvoked = true;
}
}
}
}
}

87
ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/NoDefaultConstructorIssueTests.cs

@ -0,0 +1,87 @@ @@ -0,0 +1,87 @@
using NUnit.Framework;
using ICSharpCode.NRefactory.CSharp.CodeIssues;
using ICSharpCode.NRefactory.CSharp.Refactoring;
namespace ICSharpCode.NRefactory.CSharp.CodeIssues
{
[TestFixture]
public class NoDefaultConstructorIssueTests : InspectionActionTestBase
{
[Test]
public void ShouldReturnIssueIfBaseConstructorNotInvoked()
{
var testInput =
@"class BaseClass
{
public BaseClass(string input) {}
}
class ChildClass : BaseClass
{
}";
Test<NoDefaultConstructorIssue>(testInput, 1);
}
[Test]
public void ShouldNotReturnIssueIfBaseClassHasDefaultConstructor()
{
var testInput =
@"class BaseClass
{
}
class ChildClass : BaseClass
{
}";
Test<NoDefaultConstructorIssue>(testInput, 0);
}
[Test]
public void ShouldNotReturnIssueIfBaseConstructorIsInvoked()
{
var testInput =
@"class BaseClass
{
public BaseClass(string input) {}
}
class ChildClass : BaseClass
{
public ChildClass() : base(""test"") {}
}";
Test<NoDefaultConstructorIssue>(testInput, 0);
}
[Test]
public void ShouldReturnIssueIfInvalidArgumentsArePassedToBaseConstructor()
{
var testInput =
@"class BaseClass
{
public BaseClass(string input) {}
}
class ChildClass : BaseClass
{
public ChildClass() : base(123) {}
}";
Test<NoDefaultConstructorIssue>(testInput, 1);
}
[Test]
public void ShouldIgnoreInterfaces()
{
var testInput =
@"class TestClass : System.Collections.IList
{
}";
Test<NoDefaultConstructorIssue>(testInput, 0);
}
}
}

21
ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj

@ -59,6 +59,26 @@ @@ -59,6 +59,26 @@
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<DebugType>none</DebugType>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'net_4_5_Debug|AnyCPU' ">
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'net_4_5_Release|AnyCPU' ">
<DebugType>none</DebugType>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'net_4_5_Debug|x86' ">
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'net_4_5_Release|x86' ">
<DebugType>none</DebugType>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="System" />
@ -360,6 +380,7 @@ @@ -360,6 +380,7 @@
<Compile Include="CSharp\CodeIssues\ParameterCanBeDemotedIssue\SupportsIndexingCriterionTests.cs" />
<Compile Include="CSharp\CodeActions\CreateBackingStoreTests.cs" />
<Compile Include="CSharp\CodeIssues\RedundantWhereWithPredicateIssueTests.cs" />
<Compile Include="CSharp\CodeIssues\NoDefaultConstructorIssueTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Mono.Cecil\Mono.Cecil.csproj">

Loading…
Cancel
Save