18 changed files with 579 additions and 25 deletions
@ -0,0 +1,91 @@
@@ -0,0 +1,91 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using ICSharpCode.NRefactory.Ast; |
||||
using ICSharpCode.PackageManagement.EnvDTE; |
||||
using ICSharpCode.SharpDevelop.Dom; |
||||
using ICSharpCode.SharpDevelop.Dom.Refactoring; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class ClassCodeGenerator |
||||
{ |
||||
public ClassCodeGenerator(IClass c) |
||||
: this(c, new DocumentLoader()) |
||||
{ |
||||
} |
||||
|
||||
public ClassCodeGenerator(IClass c, IDocumentLoader documentLoader) |
||||
{ |
||||
this.Class = c; |
||||
this.DocumentLoader = documentLoader; |
||||
} |
||||
|
||||
IClass Class { get; set; } |
||||
IDocumentLoader DocumentLoader { get; set; } |
||||
|
||||
ICompilationUnit CompilationUnit { |
||||
get { return Class.CompilationUnit; } |
||||
} |
||||
|
||||
public CodeVariable AddPublicVariable(string name, string type) |
||||
{ |
||||
CodeGenerator codeGenerator = GetCodeGenerator(); |
||||
IRefactoringDocumentView view = LoadClassDocumentView(); |
||||
codeGenerator.InsertCodeAtEnd(Class.Region, view.RefactoringDocument, CreateField(name, type)); |
||||
return GetVariableInserted(view); |
||||
} |
||||
|
||||
CodeGenerator GetCodeGenerator() |
||||
{ |
||||
return CompilationUnit.Language.CodeGenerator; |
||||
} |
||||
|
||||
IRefactoringDocumentView LoadClassDocumentView() |
||||
{ |
||||
return DocumentLoader.LoadRefactoringDocumentView(CompilationUnit.FileName); |
||||
} |
||||
|
||||
FieldDeclaration CreateField(string name, string type) |
||||
{ |
||||
return new FieldDeclaration(new List<AttributeSection>()) { |
||||
TypeReference = new TypeReference(type), |
||||
Modifier = Modifiers.Public, |
||||
Fields = CreateVariableDeclarations(name) |
||||
}; |
||||
} |
||||
|
||||
List<VariableDeclaration> CreateVariableDeclarations(string name) |
||||
{ |
||||
var variables = new List<VariableDeclaration>(); |
||||
variables.Add(new VariableDeclaration(name)); |
||||
return variables; |
||||
} |
||||
|
||||
CodeVariable GetVariableInserted(IRefactoringDocumentView view) |
||||
{ |
||||
IField field = FindField(view); |
||||
return new CodeVariable(field); |
||||
} |
||||
|
||||
IField FindField(IRefactoringDocumentView view) |
||||
{ |
||||
ICompilationUnit unit = view.Parse(); |
||||
IClass matchedClass = FindMatchingClass(unit); |
||||
return matchedClass.Fields.Last(); |
||||
} |
||||
|
||||
IClass FindMatchingClass(ICompilationUnit unit) |
||||
{ |
||||
foreach (IClass c in unit.Classes) { |
||||
if (c.FullyQualifiedName == Class.FullyQualifiedName) { |
||||
return c; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using ICSharpCode.SharpDevelop.Dom; |
||||
using ICSharpCode.SharpDevelop.Dom.Refactoring; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public interface IRefactoringDocumentView |
||||
{ |
||||
IRefactoringDocument RefactoringDocument { get; } |
||||
ICompilationUnit Parse(); |
||||
} |
||||
} |
||||
@ -0,0 +1,39 @@
@@ -0,0 +1,39 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Dom; |
||||
using ICSharpCode.SharpDevelop.Dom.Refactoring; |
||||
using ICSharpCode.SharpDevelop.Editor; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class RefactoringDocumentView : IRefactoringDocumentView |
||||
{ |
||||
IViewContent view; |
||||
|
||||
public RefactoringDocumentView(string fileName) |
||||
{ |
||||
view = FileService.OpenFile(fileName); |
||||
RefactoringDocument = LoadDocument(); |
||||
} |
||||
|
||||
IRefactoringDocument LoadDocument() |
||||
{ |
||||
var textEditorProvider = view as ITextEditorProvider; |
||||
return new RefactoringDocumentAdapter(new ThreadSafeDocument(textEditorProvider.TextEditor.Document)); |
||||
} |
||||
|
||||
public IRefactoringDocument RefactoringDocument { get; private set; } |
||||
|
||||
public ICompilationUnit Parse() |
||||
{ |
||||
if (WorkbenchSingleton.InvokeRequired) { |
||||
return WorkbenchSingleton.SafeThreadFunction(() => Parse()); |
||||
} |
||||
return ParserService.ParseViewContent(view).CompilationUnit; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,70 @@
@@ -0,0 +1,70 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using ICSharpCode.SharpDevelop.Editor; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class ThreadSafeDocumentLine : IDocumentLine |
||||
{ |
||||
IDocumentLine line; |
||||
|
||||
public ThreadSafeDocumentLine(IDocumentLine line) |
||||
{ |
||||
this.line = line; |
||||
} |
||||
|
||||
public int Offset { |
||||
get { |
||||
if (WorkbenchSingleton.InvokeRequired) { |
||||
return WorkbenchSingleton.SafeThreadFunction(() => Offset); |
||||
} |
||||
return line.Offset; |
||||
} |
||||
} |
||||
|
||||
public int Length { |
||||
get { |
||||
if (WorkbenchSingleton.InvokeRequired) { |
||||
return WorkbenchSingleton.SafeThreadFunction(() => Length); |
||||
} |
||||
return line.Length; |
||||
} |
||||
} |
||||
|
||||
public int EndOffset { |
||||
get { |
||||
throw new NotImplementedException(); |
||||
} |
||||
} |
||||
|
||||
public int TotalLength { |
||||
get { |
||||
throw new NotImplementedException(); |
||||
} |
||||
} |
||||
|
||||
public int DelimiterLength { |
||||
get { |
||||
throw new NotImplementedException(); |
||||
} |
||||
} |
||||
|
||||
public int LineNumber { |
||||
get { |
||||
throw new NotImplementedException(); |
||||
} |
||||
} |
||||
|
||||
public string Text { |
||||
get { |
||||
if (WorkbenchSingleton.InvokeRequired) { |
||||
return WorkbenchSingleton.SafeThreadFunction(() => Text); |
||||
} |
||||
return line.Text; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,179 @@
@@ -0,0 +1,179 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using ICSharpCode.NRefactory.Ast; |
||||
using ICSharpCode.PackageManagement; |
||||
using ICSharpCode.PackageManagement.EnvDTE; |
||||
using ICSharpCode.SharpDevelop.Dom; |
||||
using ICSharpCode.SharpDevelop.Dom.Refactoring; |
||||
using NUnit.Framework; |
||||
using PackageManagement.Tests.Helpers; |
||||
using Rhino.Mocks; |
||||
|
||||
namespace PackageManagement.Tests |
||||
{ |
||||
[TestFixture] |
||||
public class ClassCodeGeneratorTests |
||||
{ |
||||
ClassHelper helper; |
||||
ClassCodeGenerator codeGenerator; |
||||
CodeVariable codeVariable; |
||||
IDocumentLoader documentLoader; |
||||
IRefactoringDocument document; |
||||
FakeCodeGenerator fakeCodeGenerator; |
||||
IRefactoringDocumentView documentView; |
||||
|
||||
[SetUp] |
||||
public void Init() |
||||
{ |
||||
helper = new ClassHelper(); |
||||
document = MockRepository.GenerateStub<IRefactoringDocument>(); |
||||
documentView = MockRepository.GenerateStub<IRefactoringDocumentView>(); |
||||
documentLoader = MockRepository.GenerateStub<IDocumentLoader>(); |
||||
fakeCodeGenerator = helper.CompilationUnitHelper.FakeCodeGenerator; |
||||
} |
||||
|
||||
void CreateClass(string name) |
||||
{ |
||||
helper.CreatePublicClass(name); |
||||
} |
||||
|
||||
void CreateCodeGenerator() |
||||
{ |
||||
codeGenerator = new ClassCodeGenerator(helper.Class, documentLoader); |
||||
} |
||||
|
||||
void SetClassFileName(string fileName) |
||||
{ |
||||
helper.SetClassFileName(fileName); |
||||
} |
||||
|
||||
void SetDocumentFileName(string fileName) |
||||
{ |
||||
documentView.Stub(view => view.RefactoringDocument).Return(document); |
||||
documentLoader.Stub(loader => loader.LoadRefactoringDocumentView(fileName)).Return(documentView); |
||||
} |
||||
|
||||
void AddFieldToClassForReparse(string name) |
||||
{ |
||||
AddFieldToClassForReparse(name, DomRegion.Empty); |
||||
} |
||||
|
||||
void AddFieldToClassForReparse(string name, DomRegion region) |
||||
{ |
||||
ClassHelper helper = CreateClassHelper("MyClass"); |
||||
helper.AddFieldToClass(name, region); |
||||
AddClassesToReparsedCompilationUnit(helper); |
||||
} |
||||
|
||||
void AddFieldsToClassForReparse(params string[] names) |
||||
{ |
||||
ClassHelper helper = CreateClassHelper("MyClass"); |
||||
foreach (string name in names) { |
||||
helper.AddFieldToClass(name); |
||||
} |
||||
AddClassesToReparsedCompilationUnit(helper); |
||||
} |
||||
|
||||
void AddClassesToReparsedCompilationUnit(params ClassHelper[] classHelpers) |
||||
{ |
||||
var compilationUnitHelper = new CompilationUnitHelper(); |
||||
foreach (ClassHelper helper in classHelpers) { |
||||
compilationUnitHelper.AddClass(helper.Class); |
||||
} |
||||
documentView.Stub(d => d.Parse()).Return(compilationUnitHelper.CompilationUnit); |
||||
} |
||||
|
||||
ClassHelper CreateClassHelper(string name) |
||||
{ |
||||
var helper = new ClassHelper(); |
||||
helper.CreateClass(name); |
||||
return helper; |
||||
} |
||||
|
||||
void AddPublicVariable(string name, string type) |
||||
{ |
||||
codeVariable = codeGenerator.AddPublicVariable(name, type); |
||||
} |
||||
|
||||
[Test] |
||||
public void AddPublicVariable_VariableNameAndTypeIsString_ReturnsCodeVariable() |
||||
{ |
||||
CreateClass("MyClass"); |
||||
CreateCodeGenerator(); |
||||
string fileName = @"d:\projects\myproject\MyClass.cs"; |
||||
SetClassFileName(fileName); |
||||
SetDocumentFileName(fileName); |
||||
AddFieldToClassForReparse("MyClass.MyVariable", new DomRegion(1, 2, 1, 5)); |
||||
|
||||
AddPublicVariable("MyVariable", "System.String"); |
||||
|
||||
TextPoint start = codeVariable.GetStartPoint(); |
||||
TextPoint end = codeVariable.GetEndPoint(); |
||||
Assert.AreEqual("MyVariable", codeVariable.Name); |
||||
Assert.AreEqual(1, start.Line); |
||||
Assert.AreEqual(2, start.LineCharOffset); |
||||
Assert.AreEqual(1, end.Line); |
||||
Assert.AreEqual(5, end.LineCharOffset); |
||||
} |
||||
|
||||
[Test] |
||||
public void AddPublicVariable_VariableNameAndTypeIsCustomType_CodeForFieldAddedAtEndOfClass() |
||||
{ |
||||
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); |
||||
AddFieldToClassForReparse("MyClass.MyVariable"); |
||||
|
||||
AddPublicVariable("MyVar", "MyType"); |
||||
|
||||
FieldDeclaration field = fakeCodeGenerator.NodePassedToInsertCodeAtEnd as FieldDeclaration; |
||||
Assert.AreEqual(classRegion, fakeCodeGenerator.RegionPassedToInsertCodeAtEnd); |
||||
Assert.AreEqual(document, fakeCodeGenerator.DocumentPassedToInsertCodeAtEnd); |
||||
Assert.AreEqual(Modifiers.Public, field.Modifier); |
||||
Assert.AreEqual("MyType", field.TypeReference.Type); |
||||
Assert.AreEqual("MyVar", field.Fields[0].Name); |
||||
} |
||||
|
||||
[Test] |
||||
public void AddPublicVariable_ReparsedClassHasTwoFields_LastFieldReturned() |
||||
{ |
||||
CreateClass("MyClass"); |
||||
CreateCodeGenerator(); |
||||
string fileName = @"d:\projects\myproject\MyClass.cs"; |
||||
SetClassFileName(fileName); |
||||
SetDocumentFileName(fileName); |
||||
AddFieldsToClassForReparse("MyClass.First", "MyClass.MyVariable"); |
||||
|
||||
AddPublicVariable("MyVariable", "System.String"); |
||||
|
||||
Assert.AreEqual("MyVariable", codeVariable.Name); |
||||
} |
||||
|
||||
[Test] |
||||
public void AddPublicVariable_ReparsedCompilationUnitHasThreeClasses_VariableReturnedFromCorrectClass() |
||||
{ |
||||
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.AddFieldToClass("MyClass2.MyVariable"); |
||||
|
||||
AddClassesToReparsedCompilationUnit(class1, class2, class3); |
||||
|
||||
AddPublicVariable("MyVariable", "System.String"); |
||||
|
||||
Assert.AreEqual("MyVariable", codeVariable.Name); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using ICSharpCode.NRefactory.Ast; |
||||
using ICSharpCode.SharpDevelop.Dom.Refactoring; |
||||
using NUnit.Framework; |
||||
|
||||
namespace PackageManagement.Tests |
||||
{ |
||||
[TestFixture] |
||||
public class CodeGeneratorTests |
||||
{ |
||||
CSharpCodeGenerator codeGenerator; |
||||
|
||||
void CreateCodeGenerator() |
||||
{ |
||||
codeGenerator = new CSharpCodeGenerator(); |
||||
} |
||||
|
||||
[Test] |
||||
public void GenerateCode_Field_CreatesField() |
||||
{ |
||||
CreateCodeGenerator(); |
||||
var field = new FieldDeclaration(new List<AttributeSection>()); |
||||
field.TypeReference = new TypeReference("MyClass"); |
||||
field.Modifier = Modifiers.Public; |
||||
field.Fields.Add(new VariableDeclaration("myField")); |
||||
|
||||
string code = codeGenerator.GenerateCode(field, String.Empty); |
||||
|
||||
string expectedCode = "public MyClass myField;\r\n"; |
||||
|
||||
Assert.AreEqual(expectedCode, code); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using ICSharpCode.SharpDevelop.Dom; |
||||
using Rhino.Mocks; |
||||
|
||||
namespace PackageManagement.Tests.Helpers |
||||
{ |
||||
public class CompilationUnitHelper |
||||
{ |
||||
public ICompilationUnit CompilationUnit; |
||||
public FakeCodeGenerator FakeCodeGenerator = new FakeCodeGenerator(); |
||||
public List<IClass> Classes = new List<IClass>(); |
||||
|
||||
public CompilationUnitHelper() |
||||
{ |
||||
CompilationUnit = MockRepository.GenerateStub<ICompilationUnit>(); |
||||
LanguageProperties language = MockRepository.GenerateStub<LanguageProperties>(StringComparer.InvariantCultureIgnoreCase); |
||||
language.Stub(lang => lang.CodeGenerator).Return(FakeCodeGenerator); |
||||
CompilationUnit.Stub(unit => unit.Language).Return(language); |
||||
CompilationUnit.Stub(unit => unit.Classes).Return(Classes); |
||||
} |
||||
|
||||
public void SetFileName(string fileName) |
||||
{ |
||||
CompilationUnit.FileName = fileName; |
||||
} |
||||
|
||||
public void AddClass(IClass c) |
||||
{ |
||||
Classes.Add(c); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,34 @@
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Linq; |
||||
using ICSharpCode.NRefactory.Ast; |
||||
using ICSharpCode.SharpDevelop.Dom; |
||||
using ICSharpCode.SharpDevelop.Dom.Refactoring; |
||||
|
||||
namespace PackageManagement.Tests.Helpers |
||||
{ |
||||
public class FakeCodeGenerator : CodeGenerator |
||||
{ |
||||
public FakeCodeGenerator() |
||||
{ |
||||
} |
||||
|
||||
public override string GenerateCode(AbstractNode node, string indentation) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public DomRegion RegionPassedToInsertCodeAtEnd; |
||||
public IRefactoringDocument DocumentPassedToInsertCodeAtEnd; |
||||
public AbstractNode NodePassedToInsertCodeAtEnd; |
||||
|
||||
public override void InsertCodeAtEnd(DomRegion region, IRefactoringDocument document, params AbstractNode[] nodes) |
||||
{ |
||||
RegionPassedToInsertCodeAtEnd = region; |
||||
DocumentPassedToInsertCodeAtEnd = document; |
||||
NodePassedToInsertCodeAtEnd = nodes.FirstOrDefault(); |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue