Browse Source

Implement EnvDTE.CodeInterface.AddFunction.

pull/28/head
Matt Ward 14 years ago
parent
commit
32b975464f
  1. 39
      src/AddIns/Misc/PackageManagement/Project/Src/ClassCodeGenerator.cs
  2. 6
      src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/CodeElementsInNamespace.cs
  3. 3
      src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/CodeInterface.cs
  4. 8
      src/AddIns/Misc/PackageManagement/Project/Src/IMethodOrPropertyExtensions.cs
  5. 114
      src/AddIns/Misc/PackageManagement/Test/Src/ClassCodeGeneratorTests.cs
  6. 35
      src/AddIns/Misc/PackageManagement/Test/Src/CodeGeneratorTests.cs
  7. 11
      src/AddIns/Misc/PackageManagement/Test/Src/EnvDTE/CodeElementsInNamespaceTests.cs
  8. 28
      src/AddIns/Misc/PackageManagement/Test/Src/EnvDTE/CodeFunctionTests.cs
  9. 1
      src/AddIns/Misc/PackageManagement/Test/Src/EnvDTE/EditPointTests.cs
  10. 13
      src/AddIns/Misc/PackageManagement/Test/Src/Helpers/ClassHelper.cs
  11. 17
      src/AddIns/Misc/PackageManagement/Test/Src/Helpers/MethodHelper.cs
  12. 10
      src/AddIns/Misc/PackageManagement/Test/Src/Helpers/ProjectContentHelper.cs

39
src/AddIns/Misc/PackageManagement/Project/Src/ClassCodeGenerator.cs

@ -52,9 +52,9 @@ namespace ICSharpCode.PackageManagement @@ -52,9 +52,9 @@ namespace ICSharpCode.PackageManagement
FieldDeclaration CreateField(string name, string type)
{
return new FieldDeclaration(new List<AttributeSection>()) {
TypeReference = new TypeReference(type),
Fields = CreateVariableDeclarations(name),
Modifier = Modifiers.Public,
Fields = CreateVariableDeclarations(name)
TypeReference = new TypeReference(type)
};
}
@ -72,10 +72,14 @@ namespace ICSharpCode.PackageManagement @@ -72,10 +72,14 @@ namespace ICSharpCode.PackageManagement
}
IField FindField(IRefactoringDocumentView view)
{
return FindMatchingClass(view).Fields.Last();
}
IClass FindMatchingClass(IRefactoringDocumentView view)
{
ICompilationUnit unit = view.Parse();
IClass matchedClass = FindMatchingClass(unit);
return matchedClass.Fields.Last();
return FindMatchingClass(unit);
}
IClass FindMatchingClass(ICompilationUnit unit)
@ -87,5 +91,32 @@ namespace ICSharpCode.PackageManagement @@ -87,5 +91,32 @@ namespace ICSharpCode.PackageManagement
}
return null;
}
public CodeFunction AddPublicMethod(string name, string type)
{
CodeGenerator codeGenerator = GetCodeGenerator();
IRefactoringDocumentView view = LoadClassDocumentView();
codeGenerator.InsertCodeAtEnd(Class.Region, view.RefactoringDocument, CreateMethod(name, type));
return GetMethodInserted(view);
}
MethodDeclaration CreateMethod(string name, string type)
{
return new MethodDeclaration {
Name = name,
TypeReference = new TypeReference(type)
};
}
CodeFunction GetMethodInserted(IRefactoringDocumentView view)
{
IMethod method = FindMethod(view);
return new CodeFunction(method);
}
IMethod FindMethod(IRefactoringDocumentView view)
{
return FindMatchingClass(view).Methods.Last();
}
}
}

6
src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/CodeElementsInNamespace.cs

@ -55,7 +55,11 @@ namespace ICSharpCode.PackageManagement.EnvDTE @@ -55,7 +55,11 @@ namespace ICSharpCode.PackageManagement.EnvDTE
void AddCodeClass(IClass c)
{
AddCodeElement(new CodeClass2(projectContent, c));
if (c.ClassType == ClassType.Interface) {
AddCodeElement(new CodeInterface(projectContent, c));
} else {
AddCodeElement(new CodeClass2(projectContent, c));
}
}
}
}

3
src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/CodeInterface.cs

@ -40,7 +40,8 @@ namespace ICSharpCode.PackageManagement.EnvDTE @@ -40,7 +40,8 @@ namespace ICSharpCode.PackageManagement.EnvDTE
public CodeFunction AddFunction(string name, vsCMFunction kind, object type, object Position = null, vsCMAccess Access = vsCMAccess.vsCMAccessPublic)
{
throw new NotImplementedException();
var codeGenerator = new ClassCodeGenerator(Class);
return codeGenerator.AddPublicMethod(name, (string)type);
}
public override string FullName {

8
src/AddIns/Misc/PackageManagement/Project/Src/IMethodOrPropertyExtensions.cs

@ -15,7 +15,15 @@ namespace ICSharpCode.PackageManagement @@ -15,7 +15,15 @@ namespace ICSharpCode.PackageManagement
public static FilePosition GetEndPosition(this IMethodOrProperty method)
{
if (method.DeclaringTypeIsInterface()) {
return method.Region.ToEndPosition(method.CompilationUnit);
}
return method.BodyRegion.ToEndPosition(method.CompilationUnit);
}
public static bool DeclaringTypeIsInterface(this IMethodOrProperty method)
{
return method.DeclaringType.ClassType == ClassType.Interface;
}
}
}

114
src/AddIns/Misc/PackageManagement/Test/Src/ClassCodeGeneratorTests.cs

@ -19,6 +19,7 @@ namespace PackageManagement.Tests @@ -19,6 +19,7 @@ namespace PackageManagement.Tests
ClassHelper helper;
ClassCodeGenerator codeGenerator;
CodeVariable codeVariable;
CodeFunction codeFunction;
IDocumentLoader documentLoader;
IRefactoringDocument document;
FakeCodeGenerator fakeCodeGenerator;
@ -37,6 +38,7 @@ namespace PackageManagement.Tests @@ -37,6 +38,7 @@ namespace PackageManagement.Tests
void CreateClass(string name)
{
helper.CreatePublicClass(name);
helper.SetClassType(ICSharpCode.SharpDevelop.Dom.ClassType.Class);
}
void CreateCodeGenerator()
@ -92,13 +94,39 @@ namespace PackageManagement.Tests @@ -92,13 +94,39 @@ namespace PackageManagement.Tests
return helper;
}
void AddMethodToClassForReparse(string name)
{
AddMethodToClassForReparse(name, DomRegion.Empty, DomRegion.Empty);
}
void AddMethodToClassForReparse(string name, DomRegion region, DomRegion bodyRegion)
{
ClassHelper helper = CreateClassHelper("MyClass");
helper.AddMethodToClass(name, region, bodyRegion);
AddClassesToReparsedCompilationUnit(helper);
}
void AddMethodsToClassForReparse(params string[] names)
{
ClassHelper helper = CreateClassHelper("MyClass");
foreach (string name in names) {
helper.AddMethodToClass(name);
}
AddClassesToReparsedCompilationUnit(helper);
}
void AddPublicVariable(string name, string type)
{
codeVariable = codeGenerator.AddPublicVariable(name, type);
}
void AddPublicMethod(string name, string type)
{
codeFunction = codeGenerator.AddPublicMethod(name, type);
}
[Test]
public void AddPublicVariable_VariableNameAndTypeIsString_ReturnsCodeVariable()
public void AddPublicVariable_VariableTypeIsString_ReturnsCodeVariable()
{
CreateClass("MyClass");
CreateCodeGenerator();
@ -119,7 +147,7 @@ namespace PackageManagement.Tests @@ -119,7 +147,7 @@ namespace PackageManagement.Tests
}
[Test]
public void AddPublicVariable_VariableNameAndTypeIsCustomType_CodeForFieldAddedAtEndOfClass()
public void AddPublicVariable_VariableTypeIsCustomType_CodeForFieldAddedAtEndOfClass()
{
CreateClass("MyClass");
CreateCodeGenerator();
@ -175,5 +203,87 @@ namespace PackageManagement.Tests @@ -175,5 +203,87 @@ namespace PackageManagement.Tests
Assert.AreEqual("MyVariable", codeVariable.Name);
}
[Test]
public void AddPublicMethod_MethodReturnTypeIsCustomType_CodeForMethodAddedAtEndOfClass()
{
CreateClass("MyClass");
CreateCodeGenerator();
var classRegion = new DomRegion(1, 2, 3, 4);
helper.SetClassRegion(classRegion);
string fileName = @"d:\projects\myproject\MyClass.cs";
SetClassFileName(fileName);
SetDocumentFileName(fileName);
AddMethodToClassForReparse("MyClass.MyMethod");
AddPublicMethod("MyMethod", "MyType");
MethodDeclaration method = fakeCodeGenerator.NodePassedToInsertCodeAtEnd as MethodDeclaration;
Assert.AreEqual(classRegion, fakeCodeGenerator.RegionPassedToInsertCodeAtEnd);
Assert.AreEqual(document, fakeCodeGenerator.DocumentPassedToInsertCodeAtEnd);
Assert.AreEqual(Modifiers.None, method.Modifier);
Assert.AreEqual("MyType", method.TypeReference.Type);
Assert.AreEqual("MyMethod", method.Name);
Assert.IsNotNull(method.Body);
Assert.IsTrue(method.Body.IsNull);
}
[Test]
public void AddPublicMethod_MethodReturnTypeIsString_ReturnsCodeMethod()
{
CreateClass("MyClass");
CreateCodeGenerator();
string fileName = @"d:\projects\myproject\MyClass.cs";
SetClassFileName(fileName);
SetDocumentFileName(fileName);
AddMethodToClassForReparse("MyClass.MyMethod", new DomRegion(1, 2, 1, 5), new DomRegion(1, 5, 3, 3));
AddPublicMethod("MyMethod", "System.String");
TextPoint start = codeFunction.GetStartPoint();
TextPoint end = codeFunction.GetEndPoint();
Assert.AreEqual("MyMethod", codeFunction.Name);
Assert.AreEqual(1, start.Line);
Assert.AreEqual(2, start.LineCharOffset);
Assert.AreEqual(3, end.Line);
Assert.AreEqual(3, end.LineCharOffset);
}
[Test]
public void AddPublicMethod_ReparsedClassHasTwoMethods_LastMethodReturned()
{
CreateClass("MyClass");
CreateCodeGenerator();
string fileName = @"d:\projects\myproject\MyClass.cs";
SetClassFileName(fileName);
SetDocumentFileName(fileName);
AddMethodsToClassForReparse("MyClass.First", "MyClass.MyMethod");
AddPublicMethod("MyMethod", "System.String");
Assert.AreEqual("MyMethod", codeFunction.Name);
}
[Test]
public void AddPublicFunction_ReparsedCompilationUnitHasThreeClasses_MethodReturnedFromCorrectClass()
{
CreateClass("MyClass2");
CreateCodeGenerator();
string fileName = @"d:\projects\myproject\MyClass2.cs";
SetClassFileName(fileName);
SetDocumentFileName(fileName);
ClassHelper class1 = CreateClassHelper("MyClass1");
ClassHelper class2 = CreateClassHelper("MyClass2");
ClassHelper class3 = CreateClassHelper("MyClass3");
class2.AddMethodToClass("MyClass2.MyMethod");
AddClassesToReparsedCompilationUnit(class1, class2, class3);
AddPublicMethod("MyMethod", "System.String");
Assert.AreEqual("MyMethod", codeFunction.Name);
}
}
}

35
src/AddIns/Misc/PackageManagement/Test/Src/CodeGeneratorTests.cs

@ -34,5 +34,40 @@ namespace PackageManagement.Tests @@ -34,5 +34,40 @@ namespace PackageManagement.Tests
Assert.AreEqual(expectedCode, code);
}
[Test]
public void GenerateCode_Method_CreatesMethod()
{
CreateCodeGenerator();
var method = new MethodDeclaration();
method.Name = "MyMethod";
method.TypeReference = new TypeReference("MyReturnType");
method.Modifier = Modifiers.Public;
method.Body = new BlockStatement();
string code = codeGenerator.GenerateCode(method, String.Empty);
string expectedCode =
"public MyReturnType MyMethod()\r\n" +
"{\r\n" +
"}\r\n";
Assert.AreEqual(expectedCode, code);
}
[Test]
public void GenerateCode_InterfaceMethodDeclaration_CreatesMethod()
{
CreateCodeGenerator();
var method = new MethodDeclaration();
method.Name = "MyMethod";
method.TypeReference = new TypeReference("MyReturnType");
string code = codeGenerator.GenerateCode(method, String.Empty);
string expectedCode = "MyReturnType MyMethod();\r\n";
Assert.AreEqual(expectedCode, code);
}
}
}

11
src/AddIns/Misc/PackageManagement/Test/Src/EnvDTE/CodeElementsInNamespaceTests.cs

@ -132,5 +132,16 @@ namespace PackageManagement.Tests.EnvDTE @@ -132,5 +132,16 @@ namespace PackageManagement.Tests.EnvDTE
Assert.AreEqual("Test.MyClass", codeClass.FullName);
}
[Test]
public void Item_OneInterfaceCompletionEntryAndItemSelectedByName_ReturnsOneCodeInterface()
{
helper.AddInterfaceToProjectContentAndCompletionEntries("Test", "Test.IClass");
CreateCodeElements("Test");
CodeInterface codeInterface = codeElements.Item("IClass") as CodeInterface;
Assert.AreEqual("Test.IClass", codeInterface.FullName);
}
}
}

28
src/AddIns/Misc/PackageManagement/Test/Src/EnvDTE/CodeFunctionTests.cs

@ -39,6 +39,16 @@ namespace PackageManagement.Tests.EnvDTE @@ -39,6 +39,16 @@ namespace PackageManagement.Tests.EnvDTE
codeFunction = new CodeFunction(helper.Method);
}
void SetDeclaringTypeAsInterface(string name)
{
helper.AddDeclaringTypeAsInterface(name);
}
void SetDeclaringType(string name)
{
helper.AddDeclaringType(name);
}
[Test]
public void Access_PublicFunction_ReturnsPublic()
{
@ -63,6 +73,7 @@ namespace PackageManagement.Tests.EnvDTE @@ -63,6 +73,7 @@ namespace PackageManagement.Tests.EnvDTE
public void GetStartPoint_FunctionStartsAtColumn3_ReturnsPointWithOffset3()
{
CreatePublicFunction("Class1.MyFunction");
SetDeclaringType("Class1");
helper.FunctionStartsAtColumn(3);
TextPoint point = codeFunction.GetStartPoint();
@ -75,6 +86,7 @@ namespace PackageManagement.Tests.EnvDTE @@ -75,6 +86,7 @@ namespace PackageManagement.Tests.EnvDTE
public void GetStartPoint_FunctionStartsAtLine2_ReturnsPointWithLine2()
{
CreatePublicFunction("Class1.MyFunction");
SetDeclaringType("Class1");
helper.FunctionStartsAtLine(2);
TextPoint point = codeFunction.GetStartPoint();
@ -87,6 +99,7 @@ namespace PackageManagement.Tests.EnvDTE @@ -87,6 +99,7 @@ namespace PackageManagement.Tests.EnvDTE
public void GetEndPoint_FunctionBodyEndsAtColumn4_ReturnsPointWithOffset4()
{
CreatePublicFunction("Class1.MyFunction");
SetDeclaringType("Class1");
helper.FunctionBodyEndsAtColumn(4);
TextPoint point = codeFunction.GetEndPoint();
@ -99,6 +112,7 @@ namespace PackageManagement.Tests.EnvDTE @@ -99,6 +112,7 @@ namespace PackageManagement.Tests.EnvDTE
public void GetEndPoint_FunctionBodyEndsAtLine4_ReturnsPointWithLine4()
{
CreatePublicFunction("Class1.MyFunction");
SetDeclaringType("Class1");
helper.FunctionBodyEndsAtLine(4);
TextPoint point = codeFunction.GetEndPoint();
@ -116,5 +130,19 @@ namespace PackageManagement.Tests.EnvDTE @@ -116,5 +130,19 @@ namespace PackageManagement.Tests.EnvDTE
Assert.AreEqual(vsCMElement.vsCMElementFunction, kind);
}
[Test]
public void GetEndPoint_InterfaceMethod_ReturnsMethodsDeclarationRegionEndNotBodyRegionEnd()
{
CreatePublicFunction("MyInterface.MyMethod");
SetDeclaringTypeAsInterface("MyInterface");
helper.SetRegion(new DomRegion(1, 1, 1, 10));
helper.SetBodyRegion(new DomRegion(1, 10, 0, 0));
TextPoint point = codeFunction.GetEndPoint();
Assert.AreEqual(1, point.Line);
Assert.AreEqual(10, point.LineCharOffset);
}
}
}

1
src/AddIns/Misc/PackageManagement/Test/Src/EnvDTE/EditPointTests.cs

@ -105,6 +105,7 @@ namespace PackageManagement.Tests.EnvDTE @@ -105,6 +105,7 @@ namespace PackageManagement.Tests.EnvDTE
var methodRegion = new DomRegion(1, 5, 1, 10);
var methodBodyRegion = new DomRegion(1, 10, 3, 12);
CreateMethod(fileName, methodRegion, methodBodyRegion);
methodHelper.AddDeclaringType("MyClass");
DocumentOffsetToReturn(line: 1, column: 5, offset: 5);
DocumentOffsetToReturn(line: 3, column: 12, offset: 20);
DocumentFileName(fileName);

13
src/AddIns/Misc/PackageManagement/Test/Src/Helpers/ClassHelper.cs

@ -93,10 +93,18 @@ namespace PackageManagement.Tests.Helpers @@ -93,10 +93,18 @@ namespace PackageManagement.Tests.Helpers
/// Name should include the class prefix (e.g. "Class1.MyMethod");
/// </summary>
public void AddMethodToClass(string fullyQualifiedName)
{
AddMethodToClass(fullyQualifiedName, DomRegion.Empty, DomRegion.Empty);
}
public void AddMethodToClass(string fullyQualifiedName, DomRegion region, DomRegion bodyRegion)
{
var helper = new MethodHelper();
helper.ProjectContentHelper = ProjectContentHelper;
helper.CreateMethod(fullyQualifiedName);
helper.SetRegion(region);
helper.SetBodyRegion(bodyRegion);
helper.SetDeclaringType(Class);
methods.Add(helper.Method);
}
@ -144,5 +152,10 @@ namespace PackageManagement.Tests.Helpers @@ -144,5 +152,10 @@ namespace PackageManagement.Tests.Helpers
{
CompilationUnitHelper.SetFileName(fileName);
}
public void SetClassType(ClassType type)
{
Class.Stub(c => c.ClassType).Return(type);
}
}
}

17
src/AddIns/Misc/PackageManagement/Test/Src/Helpers/MethodHelper.cs

@ -85,5 +85,22 @@ namespace PackageManagement.Tests.Helpers @@ -85,5 +85,22 @@ namespace PackageManagement.Tests.Helpers
unit.FileName = fileName;
Method.Stub(m => m.CompilationUnit).Return(unit);
}
public void AddDeclaringTypeAsInterface(string name)
{
IClass declaringType = ProjectContentHelper.AddInterfaceToProjectContent(name);
SetDeclaringType(declaringType);
}
public void SetDeclaringType(IClass declaringType)
{
Method.Stub(m => m.DeclaringType).Return(declaringType);
}
public void AddDeclaringType(string name)
{
IClass declaringType = ProjectContentHelper.AddClassToProjectContent(name);
SetDeclaringType(declaringType);
}
}
}

10
src/AddIns/Misc/PackageManagement/Test/Src/Helpers/ProjectContentHelper.cs

@ -92,6 +92,16 @@ namespace PackageManagement.Tests.Helpers @@ -92,6 +92,16 @@ namespace PackageManagement.Tests.Helpers
return fakeClass;
}
public IClass AddInterfaceToProjectContentAndCompletionEntries(string namespaceName, string className)
{
IClass fakeClass = AddInterfaceToProjectContent(className);
var namespaceContents = new List<ICompletionEntry>();
namespaceContents.Add(fakeClass);
AddCompletionEntriesToNamespace(namespaceName, namespaceContents);
return fakeClass;
}
public void AddNamespaceNameToProjectContent(string name)
{
NamespaceNames.Add(name);

Loading…
Cancel
Save