Browse Source

Fixed SD2-1626 - Type parameters placed incorrectly when implementing interface nested inside generic class

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@5297 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
pull/1/head
Daniel Grunwald 16 years ago
parent
commit
ea8ead857b
  1. 73
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Refactoring/CodeGenerator.cs
  2. 4
      src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/ICSharpCode.SharpDevelop.Dom.Tests.csproj
  3. 59
      src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/ImplementInterfaceTests.cs

73
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Refactoring/CodeGenerator.cs

@ -43,26 +43,66 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring @@ -43,26 +43,66 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring
if (returnType == null) return TypeReference.Null;
if (returnType is NullReturnType) return TypeReference.Null;
TypeReference typeRef;
if (IsPrimitiveType(returnType))
typeRef = new TypeReference(returnType.FullyQualifiedName, true);
else if (context != null && CanUseShortTypeName(returnType, context))
typeRef = new TypeReference(returnType.Name);
else
typeRef = new TypeReference(returnType.FullyQualifiedName);
while (returnType.IsArrayReturnType) {
ArrayReturnType arrayReturnType = returnType.CastToArrayReturnType();
if (arrayReturnType != null) {
TypeReference typeRef = ConvertType(arrayReturnType.ArrayElementType, context);
int[] rank = typeRef.RankSpecifier ?? new int[0];
Array.Resize(ref rank, rank.Length + 1);
rank[rank.Length - 1] = returnType.CastToArrayReturnType().ArrayDimensions - 1;
rank[rank.Length - 1] = arrayReturnType.ArrayDimensions - 1;
typeRef.RankSpecifier = rank;
returnType = returnType.CastToArrayReturnType().ArrayElementType;
return typeRef;
}
PointerReturnType pointerReturnType = returnType.CastToDecoratingReturnType<PointerReturnType>();
if (pointerReturnType != null) {
TypeReference typeRef = ConvertType(pointerReturnType.BaseType, context);
typeRef.PointerNestingLevel++;
return typeRef;
}
IList<IReturnType> typeArguments = EmptyList<IReturnType>.Instance;
if (returnType.IsConstructedReturnType) {
foreach (IReturnType typeArgument in returnType.CastToConstructedReturnType().TypeArguments) {
typeArguments = returnType.CastToConstructedReturnType().TypeArguments;
}
IClass c = returnType.GetUnderlyingClass();
if (c != null) {
return CreateTypeReference(c, typeArguments, context);
} else {
TypeReference typeRef;
if (IsPrimitiveType(returnType))
typeRef = new TypeReference(returnType.FullyQualifiedName, true);
else if (context != null && CanUseShortTypeName(returnType, context))
typeRef = new TypeReference(returnType.Name);
else
typeRef = new TypeReference(returnType.FullyQualifiedName);
foreach (IReturnType typeArgument in typeArguments) {
typeRef.GenericTypes.Add(ConvertType(typeArgument, context));
}
return typeRef;
}
}
static TypeReference CreateTypeReference(IClass c, IList<IReturnType> typeArguments, ClassFinder context)
{
if (c.DeclaringType != null) {
TypeReference outerClass = CreateTypeReference(c.DeclaringType, typeArguments, context);
List<TypeReference> args = new List<TypeReference>();
for (int i = c.DeclaringType.TypeParameters.Count; i < Math.Min(c.TypeParameters.Count, typeArguments.Count); i++) {
args.Add(ConvertType(typeArguments[i], context));
}
return new InnerClassTypeReference(outerClass, c.Name, args);
} else {
TypeReference typeRef;
if (IsPrimitiveType(c.DefaultReturnType))
typeRef = new TypeReference(c.FullyQualifiedName, true);
else if (context != null && CanUseShortTypeName(c.DefaultReturnType, context))
typeRef = new TypeReference(c.Name);
else
typeRef = new TypeReference(c.FullyQualifiedName);
for (int i = 0; i < Math.Min(c.TypeParameters.Count, typeArguments.Count); i++) {
typeRef.GenericTypes.Add(ConvertType(typeArguments[i], context));
}
return typeRef;
}
return typeRef;
}
static bool IsPrimitiveType(IReturnType returnType)
@ -78,9 +118,12 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring @@ -78,9 +118,12 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring
/// </summary>
public static bool CanUseShortTypeName(IReturnType returnType, ClassFinder context)
{
int typeArgumentCount = (returnType.IsConstructedReturnType) ? returnType.CastToConstructedReturnType().TypeArguments.Count : 0;
IReturnType typeInTargetContext = context.SearchType(returnType.Name, typeArgumentCount);
return typeInTargetContext != null && typeInTargetContext.FullyQualifiedName == returnType.FullyQualifiedName;
if (returnType == null || context == null)
return false;
IReturnType typeInTargetContext = context.SearchType(returnType.Name, returnType.TypeArgumentCount);
return typeInTargetContext != null
&& typeInTargetContext.FullyQualifiedName == returnType.FullyQualifiedName
&& typeInTargetContext.TypeArgumentCount == returnType.TypeArgumentCount;
}
public static Modifiers ConvertModifier(ModifierEnum modifiers, ClassFinder targetContext)

4
src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/ICSharpCode.SharpDevelop.Dom.Tests.csproj

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{7DB80259-24D4-46C3-A024-53FF1987733D}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@ -50,6 +51,7 @@ @@ -50,6 +51,7 @@
<Compile Include="ClassInheritanceTreeTests.cs" />
<Compile Include="CodeSnippetConverterTests.cs" />
<Compile Include="CSharpAmbienceTests.cs" />
<Compile Include="ImplementInterfaceTests.cs" />
<Compile Include="NRefactoryAstConverterTests.cs" />
<Compile Include="NRefactoryRefactoringProviderTests.cs" />
<Compile Include="NUnitHelpers\SyntaxHelpers.cs" />

59
src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/ImplementInterfaceTests.cs

@ -0,0 +1,59 @@ @@ -0,0 +1,59 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.PrettyPrinter;
using ICSharpCode.SharpDevelop.Dom.Refactoring;
using NUnit.Framework;
namespace ICSharpCode.SharpDevelop.Dom.Tests
{
[TestFixture]
public class ImplementInterfaceTests
{
[Test]
public void NestedInterfaceInGenericClass()
{
// See SD2-1626
DefaultProjectContent pc = new DefaultProjectContent();
pc.ReferencedContents.Add(SharedProjectContentRegistryForTests.Instance.Mscorlib);
DefaultCompilationUnit cu = new DefaultCompilationUnit(pc);
DefaultClass container = new DefaultClass(cu, "TestClass");
container.TypeParameters.Add(new DefaultTypeParameter(container, "T", 0));
DefaultClass innerClass = new DefaultClass(cu, container);
innerClass.FullyQualifiedName = "TestClass.INestedInterface";
innerClass.ClassType = ClassType.Interface;
innerClass.TypeParameters.Add(new DefaultTypeParameter(innerClass, "T", 0));
innerClass.Properties.Add(new DefaultProperty(innerClass, "P") {
ReturnType = new GenericReturnType(innerClass.TypeParameters[0]),
CanGet = true
});
container.InnerClasses.Add(innerClass);
pc.AddClassToNamespaceList(container);
DefaultClass targetClass = new DefaultClass(cu, "TargetClass");
List<AbstractNode> nodes = new List<AbstractNode>();
IReturnType interf = new SearchClassReturnType(pc, targetClass, 0, 0, "TestClass.INestedInterface", 1);
interf = new ConstructedReturnType(interf, new IReturnType[] { SharedProjectContentRegistryForTests.Instance.Mscorlib.GetClass("System.String", 0).DefaultReturnType });
CSharpCodeGenerator codeGen = new CSharpCodeGenerator();
codeGen.ImplementInterface(nodes, interf, true, targetClass);
Assert.AreEqual(1, nodes.Count);
CSharpOutputVisitor output = new CSharpOutputVisitor();
output.Options.IndentationChar = ' ';
output.Options.IndentSize = 2;
nodes[0].AcceptVisitor(output, null);
Assert.AreEqual("string TestClass<string>.INestedInterface.P {\n get {\n throw new NotImplementedException();\n }\n}", output.Text.Replace("\r", "").Trim());
}
}
}
Loading…
Cancel
Save