Browse Source

MainFile property now set when converting a project to IronPython.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@4151 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Matt Ward 17 years ago
parent
commit
71711e3c7d
  1. 71
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/ConvertProjectToPythonProjectCommand.cs
  2. 28
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/NRefactoryToPythonConverter.cs
  3. 12
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonProject.cs
  4. 22
      src/AddIns/BackendBindings/Python/PythonBinding/Test/Converter/ConvertToPythonProjectCommandTestFixture.cs
  5. 120
      src/AddIns/BackendBindings/Python/PythonBinding/Test/Converter/ProjectHasStartupObjectTestFixture.cs
  6. 27
      src/AddIns/BackendBindings/Python/PythonBinding/Test/Converter/StaticMethodConversionTestFixture.cs
  7. 1
      src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj
  8. 20
      src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/DerivedConvertProjectToPythonProjectCommand.cs

71
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/ConvertProjectToPythonProjectCommand.cs

@ -6,10 +6,14 @@
// </file> // </file>
using System; using System;
using System.Collections.ObjectModel;
using System.IO; using System.IO;
using System.Text; using System.Text;
using ICSharpCode.Core;
using ICSharpCode.NRefactory.Ast;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Project.Converter; using ICSharpCode.SharpDevelop.Project.Converter;
using ICSharpCode.TextEditor.Document; using ICSharpCode.TextEditor.Document;
@ -42,9 +46,9 @@ namespace ICSharpCode.PythonBinding
protected override IProject CreateProject(string targetProjectDirectory, IProject sourceProject) protected override IProject CreateProject(string targetProjectDirectory, IProject sourceProject)
{ {
// Add IronPython reference. // Add IronPython reference.
IProject targetProject = base.CreateProject(targetProjectDirectory, sourceProject); PythonProject targetProject = (PythonProject)base.CreateProject(targetProjectDirectory, sourceProject);
IProjectItemListProvider targetProjectItems = targetProject as IProjectItemListProvider; IProjectItemListProvider targetProjectItems = targetProject as IProjectItemListProvider;
targetProjectItems.AddProjectItem(CreateIronPythonReference(targetProject)); targetProjectItems.AddProjectItem(CreateIronPythonReference(targetProject));
return targetProject; return targetProject;
} }
@ -55,15 +59,31 @@ namespace ICSharpCode.PythonBinding
{ {
NRefactoryToPythonConverter converter = NRefactoryToPythonConverter.Create(sourceItem.Include); NRefactoryToPythonConverter converter = NRefactoryToPythonConverter.Create(sourceItem.Include);
if (converter != null) { if (converter != null) {
targetItem.Include = Path.ChangeExtension(sourceItem.Include, ".py"); targetItem.Include = ChangeExtension(sourceItem.Include);
string code = GetParseableFileContent(sourceItem.FileName); string code = GetParseableFileContent(sourceItem.FileName);
string pythonCode = converter.Convert(code); string pythonCode = converter.Convert(code);
PythonProject pythonTargetProject = (PythonProject)targetItem.Project;
if ((converter.EntryPointMethods.Count > 0) && !pythonTargetProject.HasMainFile) {
pythonTargetProject.AddMainFile(targetItem.Include);
}
SaveFile(targetItem.FileName, pythonCode, textEditorProperties.Encoding); SaveFile(targetItem.FileName, pythonCode, textEditorProperties.Encoding);
} else { } else {
LanguageConverterConvertFile(sourceItem, targetItem); LanguageConverterConvertFile(sourceItem, targetItem);
} }
} }
/// <summary>
/// Adds the MainFile property since adding it in the CreateProject method would mean
/// it gets removed via the base class CopyProperties method.
/// </summary>
protected override void CopyProperties(IProject sourceProject, IProject targetProject)
{
base.CopyProperties(sourceProject, targetProject);
AddMainFile(sourceProject, (PythonProject)targetProject);
}
/// <summary> /// <summary>
/// Calls the LanguageConverter class method ConvertFile which copies the source file to the target /// Calls the LanguageConverter class method ConvertFile which copies the source file to the target
@ -90,11 +110,56 @@ namespace ICSharpCode.PythonBinding
return ParserService.GetParseableFileContent(fileName); return ParserService.GetParseableFileContent(fileName);
} }
/// <summary>
/// Gets the project content for the specified project.
/// </summary>
protected virtual IProjectContent GetProjectContent(IProject project)
{
return ParserService.GetProjectContent(project);
}
ReferenceProjectItem CreateIronPythonReference(IProject project) ReferenceProjectItem CreateIronPythonReference(IProject project)
{ {
ReferenceProjectItem reference = new ReferenceProjectItem(project, "IronPython"); ReferenceProjectItem reference = new ReferenceProjectItem(project, "IronPython");
reference.SetMetadata("HintPath", @"$(PythonBinPath)\IronPython.dll"); reference.SetMetadata("HintPath", @"$(PythonBinPath)\IronPython.dll");
return reference; return reference;
} }
/// <summary>
/// Adds a MainFile if the source project has a StartupObject.
/// </summary>
void AddMainFile(IProject sourceProject, PythonProject targetProject)
{
string startupObject = GetStartupObject(sourceProject);
if (startupObject != null) {
IClass c = FindClass(sourceProject, startupObject);
if (c != null) {
string fileName = FileUtility.GetRelativePath(sourceProject.Directory, c.CompilationUnit.FileName);
targetProject.AddMainFile(ChangeExtension(fileName));
}
}
}
string GetStartupObject(IProject project)
{
MSBuildBasedProject msbuildProject = project as MSBuildBasedProject;
if (msbuildProject != null) {
return msbuildProject.GetProperty(null, null, "StartupObject");
}
return null;
}
IClass FindClass(IProject project, string name)
{
return GetProjectContent(project).GetClass(name, 0);
}
/// <summary>
/// Changes the extension to ".py"
/// </summary>
static string ChangeExtension(string fileName)
{
return Path.ChangeExtension(fileName, ".py");
}
} }
} }

28
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/NRefactoryToPythonConverter.cs

@ -7,6 +7,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO; using System.IO;
using System.Text; using System.Text;
using ICSharpCode.NRefactory; using ICSharpCode.NRefactory;
@ -33,6 +34,7 @@ namespace ICSharpCode.PythonBinding
// references to fields or parameters. // references to fields or parameters.
List<ParameterDeclarationExpression> methodParameters = new List<ParameterDeclarationExpression>(); List<ParameterDeclarationExpression> methodParameters = new List<ParameterDeclarationExpression>();
SupportedLanguage language; SupportedLanguage language;
List<MethodDeclaration> entryPointMethods;
public NRefactoryToPythonConverter(SupportedLanguage language) public NRefactoryToPythonConverter(SupportedLanguage language)
{ {
@ -124,12 +126,21 @@ namespace ICSharpCode.PythonBinding
// Convert to NRefactory code DOM. // Convert to NRefactory code DOM.
CompilationUnit unit = GenerateCompilationUnit(source, language); CompilationUnit unit = GenerateCompilationUnit(source, language);
// Convert to Python code. // Convert to Python code.3
entryPointMethods = new List<MethodDeclaration>();
codeBuilder = new StringBuilder(); codeBuilder = new StringBuilder();
unit.AcceptVisitor(this, null); unit.AcceptVisitor(this, null);
return codeBuilder.ToString().TrimEnd(); return codeBuilder.ToString().TrimEnd();
} }
/// <summary>
/// Gets a list of possible entry point methods found when converting the
/// python source code.
/// </summary>
public ReadOnlyCollection<MethodDeclaration> EntryPointMethods {
get { return entryPointMethods.AsReadOnly(); }
}
/// <summary> /// <summary>
/// Converts from the NRefactory's binary operator type to a string. /// Converts from the NRefactory's binary operator type to a string.
@ -793,6 +804,9 @@ namespace ICSharpCode.PythonBinding
if (IsStatic(methodDeclaration)) { if (IsStatic(methodDeclaration)) {
AppendIndentedLine(methodDeclaration.Name + " = staticmethod(" + methodDeclaration.Name + ")"); AppendIndentedLine(methodDeclaration.Name + " = staticmethod(" + methodDeclaration.Name + ")");
AppendNewLine(); AppendNewLine();
// Save Main entry point method.
SaveMethodIfMainEntryPoint(methodDeclaration);
} }
return null; return null;
@ -1684,6 +1698,16 @@ namespace ICSharpCode.PythonBinding
return SupportedLanguage.VBNet; return SupportedLanguage.VBNet;
} }
return SupportedLanguage.CSharp; return SupportedLanguage.CSharp;
} }
/// <summary>
/// Saves the method declaration if it is a main entry point.
/// </summary>
void SaveMethodIfMainEntryPoint(MethodDeclaration method)
{
if (method.Name == "Main") {
entryPointMethods.Add(method);
}
}
} }
} }

12
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonProject.cs

@ -61,6 +61,18 @@ namespace ICSharpCode.PythonBinding
return base.GetDefaultItemType(fileName); return base.GetDefaultItemType(fileName);
} }
public void AddMainFile(string fileName)
{
SetProperty(null, null, "MainFile", fileName, PropertyStorageLocations.Base, true);
}
/// <summary>
/// Returns true if a main file is already defined for this project.
/// </summary>
public bool HasMainFile {
get { return GetProperty(null, null, "MainFile") != null; }
}
protected override void Create(ProjectCreateInformation information) protected override void Create(ProjectCreateInformation information)
{ {
base.Create(information); base.Create(information);

22
src/AddIns/BackendBindings/Python/PythonBinding/Test/Converter/ConvertToPythonProjectCommandTestFixture.cs

@ -27,13 +27,16 @@ namespace PythonBinding.Tests.Converter
FileProjectItem source; FileProjectItem source;
FileProjectItem target; FileProjectItem target;
MockProject sourceProject; MockProject sourceProject;
IProject targetProject; PythonProject targetProject;
FileProjectItem textFileSource; FileProjectItem textFileSource;
FileProjectItem textFileTarget; FileProjectItem textFileTarget;
MockTextEditorProperties mockTextEditorProperties; MockTextEditorProperties mockTextEditorProperties;
ReferenceProjectItem ironPythonReference; ReferenceProjectItem ironPythonReference;
string sourceCode = "class Foo\r\n" + string sourceCode = "class Foo\r\n" +
"{\r\n" + "{\r\n" +
" static void Main()\r\n" +
" {\r\n" +
" }\r\n" +
"}"; "}";
[TestFixtureSetUp] [TestFixtureSetUp]
@ -55,7 +58,7 @@ namespace PythonBinding.Tests.Converter
sourceProject = new MockProject(); sourceProject = new MockProject();
sourceProject.Directory = @"d:\projects\test"; sourceProject.Directory = @"d:\projects\test";
source = new FileProjectItem(sourceProject, ItemType.Compile, @"src\Program.cs"); source = new FileProjectItem(sourceProject, ItemType.Compile, @"src\Program.cs");
targetProject = convertProjectCommand.CallCreateProject(@"d:\projects\test\converted", sourceProject); targetProject = (PythonProject)convertProjectCommand.CallCreateProject(@"d:\projects\test\converted", sourceProject);
target = new FileProjectItem(targetProject, source.ItemType, source.Include); target = new FileProjectItem(targetProject, source.ItemType, source.Include);
source.CopyMetadataTo(target); source.CopyMetadataTo(target);
@ -125,5 +128,20 @@ namespace PythonBinding.Tests.Converter
{ {
Assert.AreEqual(@"$(PythonBinPath)\IronPython.dll", ironPythonReference.GetMetadata("HintPath")); Assert.AreEqual(@"$(PythonBinPath)\IronPython.dll", ironPythonReference.GetMetadata("HintPath"));
} }
[Test]
public void MainFileIsProgramPyFile()
{
PropertyStorageLocations location;
Assert.AreEqual(@"src\Program.py", targetProject.GetProperty(null, null, "MainFile", out location));
}
[Test]
public void PropertyStorageLocationForMainFilePropertyIsGlobal()
{
PropertyStorageLocations location;
targetProject.GetProperty(null, null, "MainFile", out location);
Assert.AreEqual(PropertyStorageLocations.Base, location);
}
} }
} }

120
src/AddIns/BackendBindings/Python/PythonBinding/Test/Converter/ProjectHasStartupObjectTestFixture.cs

@ -0,0 +1,120 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using ICSharpCode.Core;
using ICSharpCode.NRefactory;
using ICSharpCode.PythonBinding;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.DefaultEditor.Codons;
using ICSharpCode.SharpDevelop.Project;
using NUnit.Framework;
using PythonBinding.Tests.Utils;
namespace PythonBinding.Tests.Converter
{
[TestFixture]
public class ProjectHasStartupObjectTestFixture
{
DerivedConvertProjectToPythonProjectCommand convertProjectCommand;
FileProjectItem mainFile;
FileProjectItem main2File;
FileProjectItem targetMainFile;
FileProjectItem targetMain2File;
MSBuildBasedProject sourceProject;
PythonProject targetProject;
MockTextEditorProperties mockTextEditorProperties;
MockProjectContent mockProjectContent;
string startupObject = "RootNamespace.Main";
string mainSource = "class Foo\r\n" +
"{\r\n" +
" static void Main()\r\n" +
" {\r\n" +
" }\r\n" +
"}";
string main2Source = "class Bar\r\n" +
"{\r\n" +
" static void Main()\r\n" +
" {\r\n" +
" }\r\n" +
"}";
[TestFixtureSetUp]
public void SetUpFixture()
{
MSBuildEngineHelper.InitMSBuildEngine();
List<LanguageBindingDescriptor> bindings = new List<LanguageBindingDescriptor>();
using (TextReader reader = PythonBindingAddInFile.ReadAddInFile()) {
AddIn addin = AddIn.Load(reader, String.Empty);
bindings.Add(new LanguageBindingDescriptor(AddInHelper.GetCodon(addin, "/SharpDevelop/Workbench/LanguageBindings", "Python")));
}
LanguageBindingService.SetBindings(bindings);
// Set up IProjectContent so the ConvertProjectToPythonProjectCommand can
// locate the startup object and determine it's filename.
mockProjectContent = new MockProjectContent();
MockClass mainClass = new MockClass(mockProjectContent, startupObject);
mainClass.CompilationUnit.FileName = @"d:\projects\test\src\Main2.cs";
mockProjectContent.ClassToReturnFromGetClass = mainClass;
mockTextEditorProperties = new MockTextEditorProperties();
convertProjectCommand = new DerivedConvertProjectToPythonProjectCommand(mockTextEditorProperties);
convertProjectCommand.ProjectContent = mockProjectContent;
mockTextEditorProperties.Encoding = Encoding.Unicode;
Solution solution = new Solution();
sourceProject = new MSBuildBasedProject(solution.BuildEngine);
sourceProject.Parent = solution;
sourceProject.FileName = @"d:\projects\test\source.csproj";
sourceProject.SetProperty(null, null, "StartupObject", startupObject, PropertyStorageLocations.Base, true);
mainFile = new FileProjectItem(sourceProject, ItemType.Compile, @"src\Main.cs");
targetProject = (PythonProject)convertProjectCommand.CallCreateProject(@"d:\projects\test\converted", sourceProject);
convertProjectCommand.CallCopyProperties(sourceProject, targetProject);
targetMainFile = new FileProjectItem(targetProject, mainFile.ItemType, mainFile.Include);
mainFile.CopyMetadataTo(targetMainFile);
main2File = new FileProjectItem(sourceProject, ItemType.Compile, @"src\Main2.cs");
targetMain2File = new FileProjectItem(targetProject, main2File.ItemType, main2File.Include);
main2File.CopyMetadataTo(targetMain2File);
convertProjectCommand.AddParseableFileContent(mainFile.FileName, mainSource);
convertProjectCommand.AddParseableFileContent(main2File.FileName, main2Source);
convertProjectCommand.CallConvertFile(mainFile, targetMainFile);
convertProjectCommand.CallConvertFile(main2File, targetMain2File);
}
[Test]
public void MainFileIsMain2PyFile()
{
PropertyStorageLocations location;
Assert.AreEqual(@"src\Main2.py", targetProject.GetProperty(null, null, "MainFile", out location));
}
[Test]
public void PropertyStorageLocationForMainFilePropertyIsGlobal()
{
PropertyStorageLocations location;
targetProject.GetProperty(null, null, "MainFile", out location);
Assert.AreEqual(PropertyStorageLocations.Base, location);
}
[Test]
public void ClassSearchedFor()
{
Assert.AreEqual(startupObject, mockProjectContent.GetClassName);
}
}
}

27
src/AddIns/BackendBindings/Python/PythonBinding/Test/Converter/StaticMethodConversionTestFixture.cs

@ -35,12 +35,20 @@ namespace PythonBinding.Tests.Converter
" }\r\n" + " }\r\n" +
"}"; "}";
string python;
NRefactoryToPythonConverter converter;
[SetUp]
public void Init()
{
converter = new NRefactoryToPythonConverter(SupportedLanguage.CSharp);
converter.IndentString = " ";
python = converter.Convert(csharp);
}
[Test] [Test]
public void ConvertedPythonCode() public void ConvertedPythonCode()
{ {
NRefactoryToPythonConverter converter = new NRefactoryToPythonConverter(SupportedLanguage.CSharp);
converter.IndentString = " ";
string python = converter.Convert(csharp);
string expectedPython = "class Foo(object):\r\n" + string expectedPython = "class Foo(object):\r\n" +
" def Main(args):\r\n" + " def Main(args):\r\n" +
" pass\r\n" + " pass\r\n" +
@ -54,8 +62,19 @@ namespace PythonBinding.Tests.Converter
"\r\n" + "\r\n" +
" def Run(self):\r\n" + " def Run(self):\r\n" +
" pass"; " pass";
Assert.AreEqual(expectedPython, python); Assert.AreEqual(expectedPython, python);
} }
[Test]
public void EntryPointMethodFound()
{
Assert.AreEqual(1, converter.EntryPointMethods.Count);
}
[Test]
public void MainEntryPointMethodNameIsMain()
{
Assert.AreEqual("Main", converter.EntryPointMethods[0].Name);
}
} }
} }

1
src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj

@ -133,6 +133,7 @@
<Compile Include="Converter\NullConversionTestFixture.cs" /> <Compile Include="Converter\NullConversionTestFixture.cs" />
<Compile Include="Converter\ObjectCreationTestFixture.cs" /> <Compile Include="Converter\ObjectCreationTestFixture.cs" />
<Compile Include="Converter\ObjectInitializerConversionTestFixture.cs" /> <Compile Include="Converter\ObjectInitializerConversionTestFixture.cs" />
<Compile Include="Converter\ProjectHasStartupObjectTestFixture.cs" />
<Compile Include="Converter\PropertyConversionTestFixture.cs" /> <Compile Include="Converter\PropertyConversionTestFixture.cs" />
<Compile Include="Converter\PropertyWithGetSetStatementsTestfixture.cs" /> <Compile Include="Converter\PropertyWithGetSetStatementsTestfixture.cs" />
<Compile Include="Converter\RemoveHandlerConversionTestFixture.cs" /> <Compile Include="Converter\RemoveHandlerConversionTestFixture.cs" />

20
src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/DerivedConvertProjectToPythonProjectCommand.cs

@ -10,6 +10,7 @@ using System.Collections.Generic;
using System.Text; using System.Text;
using ICSharpCode.PythonBinding; using ICSharpCode.PythonBinding;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.TextEditor.Document; using ICSharpCode.TextEditor.Document;
@ -35,6 +36,7 @@ namespace PythonBinding.Tests.Utils
List<SourceAndTargetFile> sourceAndTargetFilesPassedToBaseClass = new List<SourceAndTargetFile>(); List<SourceAndTargetFile> sourceAndTargetFilesPassedToBaseClass = new List<SourceAndTargetFile>();
List<ConvertedFile> savedFiles = new List<ConvertedFile>(); List<ConvertedFile> savedFiles = new List<ConvertedFile>();
List<ConvertedFile> parseableFileContent = new List<ConvertedFile>(); List<ConvertedFile> parseableFileContent = new List<ConvertedFile>();
IProjectContent projectContent;
public DerivedConvertProjectToPythonProjectCommand(ITextEditorProperties textEditorProperties) public DerivedConvertProjectToPythonProjectCommand(ITextEditorProperties textEditorProperties)
: base(textEditorProperties) : base(textEditorProperties)
@ -52,6 +54,14 @@ namespace PythonBinding.Tests.Utils
get { return savedFiles; } get { return savedFiles; }
} }
/// <summary>
/// Sets the project content to be returned from the GetProjectContent method.
/// </summary>
public IProjectContent ProjectContent {
get { return projectContent; }
set { projectContent = value; }
}
public void AddParseableFileContent(string fileName, string content) public void AddParseableFileContent(string fileName, string content)
{ {
parseableFileContent.Add(new ConvertedFile(fileName, content, null)); parseableFileContent.Add(new ConvertedFile(fileName, content, null));
@ -67,6 +77,11 @@ namespace PythonBinding.Tests.Utils
return base.CreateProject(directory, sourceProject); return base.CreateProject(directory, sourceProject);
} }
public void CallCopyProperties(IProject source, IProject target)
{
base.CopyProperties(source, target);
}
protected override void LanguageConverterConvertFile(FileProjectItem source, FileProjectItem target) protected override void LanguageConverterConvertFile(FileProjectItem source, FileProjectItem target)
{ {
sourceAndTargetFilesPassedToBaseClass.Add(new SourceAndTargetFile(source, target)); sourceAndTargetFilesPassedToBaseClass.Add(new SourceAndTargetFile(source, target));
@ -86,5 +101,10 @@ namespace PythonBinding.Tests.Utils
} }
return null; return null;
} }
protected override IProjectContent GetProjectContent(IProject project)
{
return projectContent;
}
} }
} }

Loading…
Cancel
Save