Browse Source

NRefactoryASTConvertVisitor: produce correct DOM for inner classes inside generic classes (copy the type parameters into all inner classes)

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@4955 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 17 years ago
parent
commit
51dcc82ad4
  1. 42
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryASTConvertVisitor.cs
  2. 33
      src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/NRefactoryAstConverterTests.cs

42
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryASTConvertVisitor.cs

@ -377,10 +377,10 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -377,10 +377,10 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
ConvertAttributes(typeDeclaration, c);
c.Documentation = GetDocumentation(region.BeginLine, typeDeclaration.Attributes);
if (currentClass.Count > 0) {
DefaultClass cur = GetCurrentClass();
cur.InnerClasses.Add(c);
c.FullyQualifiedName = cur.FullyQualifiedName + '.' + typeDeclaration.Name;
DefaultClass outerClass = GetCurrentClass();
if (outerClass != null) {
outerClass.InnerClasses.Add(c);
c.FullyQualifiedName = outerClass.FullyQualifiedName + '.' + typeDeclaration.Name;
} else {
c.FullyQualifiedName = PrependCurrentNamespace(typeDeclaration.Name);
cu.Classes.Add(c);
@ -388,7 +388,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -388,7 +388,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
c.UsingScope = currentNamespace;
currentClass.Push(c);
ConvertTemplates(typeDeclaration.Templates, c); // resolve constrains in context of the class
ConvertTemplates(outerClass, typeDeclaration.Templates, c); // resolve constrains in context of the class
// templates must be converted before base types because base types may refer to generic types
if (c.ClassType != ClassType.Enum && typeDeclaration.BaseTypes != null) {
@ -421,19 +421,33 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -421,19 +421,33 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
return ret;
}
void ConvertTemplates(IList<AST.TemplateDefinition> templateList, DefaultClass c)
void ConvertTemplates(DefaultClass outerClass, IList<AST.TemplateDefinition> templateList, DefaultClass c)
{
int index = 0;
if (templateList.Count == 0) {
int outerClassTypeParameterCount = outerClass != null ? outerClass.TypeParameters.Count : 0;
if (templateList.Count == 0 && outerClassTypeParameterCount == 0) {
c.TypeParameters = DefaultTypeParameter.EmptyTypeParameterList;
} else {
Debug.Assert(c.TypeParameters.Count == 0);
int index = 0;
if (outerClassTypeParameterCount > 0) {
foreach (DefaultTypeParameter outerTypeParamter in outerClass.TypeParameters) {
DefaultTypeParameter p = new DefaultTypeParameter(c, outerTypeParamter.Name, index++);
p.HasConstructableConstraint = outerTypeParamter.HasConstructableConstraint;
p.HasReferenceTypeConstraint = outerTypeParamter.HasReferenceTypeConstraint;
p.HasValueTypeConstraint = outerTypeParamter.HasValueTypeConstraint;
p.Attributes.AddRange(outerTypeParamter.Attributes);
p.Constraints.AddRange(outerTypeParamter.Constraints);
c.TypeParameters.Add(p);
}
}
foreach (AST.TemplateDefinition template in templateList) {
c.TypeParameters.Add(new DefaultTypeParameter(c, template.Name, index++));
}
// converting the constraints requires that the type parameters are already present
for (int i = 0; i < templateList.Count; i++) {
ConvertConstraints(templateList[i], (DefaultTypeParameter)c.TypeParameters[i]);
ConvertConstraints(templateList[i], (DefaultTypeParameter)c.TypeParameters[i + outerClassTypeParameterCount]);
}
}
}
@ -487,17 +501,17 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -487,17 +501,17 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
void CreateDelegate(DefaultClass c, string name, AST.TypeReference returnType, IList<AST.TemplateDefinition> templates, IList<AST.ParameterDeclarationExpression> parameters)
{
c.BaseTypes.Add(c.ProjectContent.SystemTypes.MulticastDelegate);
if (currentClass.Count > 0) {
DefaultClass cur = GetCurrentClass();
cur.InnerClasses.Add(c);
c.FullyQualifiedName = cur.FullyQualifiedName + '.' + name;
DefaultClass outerClass = GetCurrentClass();
if (outerClass != null) {
outerClass.InnerClasses.Add(c);
c.FullyQualifiedName = outerClass.FullyQualifiedName + '.' + name;
} else {
c.FullyQualifiedName = PrependCurrentNamespace(name);
cu.Classes.Add(c);
}
c.UsingScope = currentNamespace;
currentClass.Push(c); // necessary for CreateReturnType
ConvertTemplates(templates, c);
ConvertTemplates(outerClass, templates, c);
List<IParameter> p = new List<IParameter>();
if (parameters != null) {

33
src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/NRefactoryAstConverterTests.cs

@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
// </file>
using System;
using System.Linq;
using System.IO;
using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop.Dom.NRefactoryResolver;
@ -209,5 +210,37 @@ class X { @@ -209,5 +210,37 @@ class X {
Assert.AreEqual("Foo", p.Name);
Assert.AreEqual(1, p.Parameters.Count);
}
[Test]
public void GenericInnerClassTest()
{
ICompilationUnit cu = Parse(@"
using System;
class Outer<T1> where T1 : IDisposable {
class Inner<T2> where T2 : T1 {
public static void Method<T3>(T1 p1, T2 p2, T3 p3) where T3 : T2 { }
}
}
");
IClass outer = cu.Classes[0];
Assert.AreEqual(1, outer.TypeParameters.Count);
IClass inner = outer.InnerClasses[0];
Assert.AreEqual(2, inner.TypeParameters.Count);
Assert.AreEqual("T1", inner.TypeParameters[0].Name);
Assert.AreSame(inner, inner.TypeParameters[0].Class);
Assert.AreEqual("T2", inner.TypeParameters[1].Name);
Assert.AreSame(inner.TypeParameters[0], inner.TypeParameters[1].Constraints[0].CastToGenericReturnType().TypeParameter);
Assert.AreEqual("IDisposable", inner.TypeParameters[0].Constraints[0].Name);
IMethod method = inner.Methods.Single(m => m.Name == "Method");
Assert.AreEqual(1, method.TypeParameters.Count);
Assert.AreSame(inner.TypeParameters[0], method.Parameters[0].ReturnType.CastToGenericReturnType().TypeParameter);
Assert.AreSame(inner.TypeParameters[1], method.Parameters[1].ReturnType.CastToGenericReturnType().TypeParameter);
Assert.AreSame(method.TypeParameters[0], method.Parameters[2].ReturnType.CastToGenericReturnType().TypeParameter);
Assert.AreSame(inner.TypeParameters[1], method.TypeParameters[0].Constraints[0].CastToGenericReturnType().TypeParameter);
}
}
}

Loading…
Cancel
Save