Browse Source

Add support for partial classes to the form designer.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@687 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 20 years ago
parent
commit
0cfa16791c
  1. 102
      src/AddIns/DisplayBindings/FormDesigner/Project/Src/FormDesigner/DesignerGenerator/AbstractDesignerGenerator.cs
  2. 93
      src/AddIns/DisplayBindings/FormDesigner/Project/Src/FormDesigner/DesignerLoader/NRefactoryDesignerLoader.cs
  3. 14
      src/AddIns/DisplayBindings/FormDesigner/Project/Src/FormDesigner/FormDesignerSecondaryDisplayBinding.cs
  4. 5
      src/Main/Base/Project/Src/Gui/IWorkbenchWindow.cs
  5. 19
      src/Main/Base/Project/Src/Services/ParserService/ParserService.cs
  6. 4
      src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/DocumentIterator/WholeSolutionDocumentIterator.cs

102
src/AddIns/DisplayBindings/FormDesigner/Project/Src/FormDesigner/DesignerGenerator/AbstractDesignerGenerator.cs

@ -19,6 +19,7 @@ using ICSharpCode.SharpDevelop.Dom; @@ -19,6 +19,7 @@ using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor;
using ICSharpCode.Core;
using ICSharpCode.TextEditor.Document;
namespace ICSharpCode.FormDesigner
{
@ -53,14 +54,15 @@ namespace ICSharpCode.FormDesigner @@ -53,14 +54,15 @@ namespace ICSharpCode.FormDesigner
void ComponentRemoved(object sender, ComponentEventArgs e)
{
try {
Reparse(viewContent.Document.TextContent);
Reparse();
foreach (IField field in c.Fields) {
if (field.Name == e.Component.Site.Name) {
int startOffset = viewContent.Document.PositionToOffset(new Point(0, field.Region.BeginLine - 1));
int endOffset = viewContent.Document.PositionToOffset(new Point(0, field.Region.EndLine));
viewContent.Document.Remove(startOffset, endOffset - startOffset);
int startOffset = document.PositionToOffset(new Point(0, field.Region.BeginLine - 1));
int endOffset = document.PositionToOffset(new Point(0, field.Region.EndLine));
document.Remove(startOffset, endOffset - startOffset);
}
}
SaveDocument();
} catch (Exception ex) {
MessageService.ShowError(ex);
}
@ -77,14 +79,15 @@ namespace ICSharpCode.FormDesigner @@ -77,14 +79,15 @@ namespace ICSharpCode.FormDesigner
void ComponentAdded(object sender, ComponentEventArgs e)
{
try {
Reparse(viewContent.Document.TextContent);
int endOffset = viewContent.Document.PositionToOffset(new Point(0, initializeComponents.BodyRegion.EndLine));
viewContent.Document.Insert(endOffset, tabs + GenerateFieldDeclaration(e.Component.GetType(), e.Component.Site.Name) + Environment.NewLine);
Reparse();
int endOffset = document.PositionToOffset(new Point(0, initializeComponents.BodyRegion.EndLine));
document.Insert(endOffset, tabs + GenerateFieldDeclaration(e.Component.GetType(), e.Component.Site.Name) + Environment.NewLine);
if (CodeDOMGenerator.IsNonVisualComponent(viewContent.Host, e.Component)) {
if (!IsNonVisualComponentContainerDefined) {
viewContent.Document.Insert(endOffset, tabs + GenerateFieldDeclaration(typeof(Container), NonVisualComponentContainerName) + Environment.NewLine);
document.Insert(endOffset, tabs + GenerateFieldDeclaration(typeof(Container), NonVisualComponentContainerName) + Environment.NewLine);
}
}
SaveDocument();
} catch (Exception ex) {
MessageService.ShowError(ex);
}
@ -92,13 +95,18 @@ namespace ICSharpCode.FormDesigner @@ -92,13 +95,18 @@ namespace ICSharpCode.FormDesigner
void ComponentRenamed(object sender, ComponentRenameEventArgs e)
{
Reparse(viewContent.Document.TextContent);
foreach (IField field in c.Fields) {
if (field.Name == e.OldName) {
int startOffset = viewContent.Document.PositionToOffset(new Point(0, field.Region.BeginLine - 1));
int endOffset = viewContent.Document.PositionToOffset(new Point(0, field.Region.EndLine));
viewContent.Document.Replace(startOffset, endOffset - startOffset, tabs + GenerateFieldDeclaration(e.Component.GetType(), e.NewName) + Environment.NewLine);
try {
Reparse();
foreach (IField field in c.Fields) {
if (field.Name == e.OldName) {
int startOffset = document.PositionToOffset(new Point(0, field.Region.BeginLine - 1));
int endOffset = document.PositionToOffset(new Point(0, field.Region.EndLine));
document.Replace(startOffset, endOffset - startOffset, tabs + GenerateFieldDeclaration(e.Component.GetType(), e.NewName) + Environment.NewLine);
}
}
SaveDocument();
} catch (Exception ex) {
MessageService.ShowError(ex);
}
}
@ -108,35 +116,73 @@ namespace ICSharpCode.FormDesigner @@ -108,35 +116,73 @@ namespace ICSharpCode.FormDesigner
public void MergeFormChanges()
{
if (tabs == null) Reparse(viewContent.Document.TextContent);
if (tabs == null) Reparse();
// generate file and get initialize components string
StringWriter writer = new StringWriter();
new CodeDOMGenerator(viewContent.Host, CreateCodeProvider(), tabs + '\t').ConvertContentDefinition(writer);
string statements = writer.ToString();
Reparse(viewContent.Document.TextContent);
// initializeComponents.BodyRegion.BeginLine + 1
DomRegion bodyRegion = GetReplaceRegion(viewContent.Document, initializeComponents);
DomRegion bodyRegion = GetReplaceRegion(document, initializeComponents);
if (bodyRegion.BeginColumn <= 0 || bodyRegion.EndColumn <= 0)
throw new InvalidOperationException("Column must be > 0");
int startOffset = viewContent.Document.PositionToOffset(new Point(bodyRegion.BeginColumn - 1, bodyRegion.BeginLine - 1));
int endOffset = viewContent.Document.PositionToOffset(new Point(bodyRegion.EndColumn - 1, bodyRegion.EndLine - 1));
int startOffset = document.PositionToOffset(new Point(bodyRegion.BeginColumn - 1, bodyRegion.BeginLine - 1));
int endOffset = document.PositionToOffset(new Point(bodyRegion.EndColumn - 1, bodyRegion.EndLine - 1));
viewContent.Document.Replace(startOffset, endOffset - startOffset, statements);
document.Replace(startOffset, endOffset - startOffset, statements);
SaveDocument();
}
protected void Reparse(string content)
IDocument document;
string saveDocumentToFile; // only set when InitializeComponent was loaded from code-behind file that was not opened
void SaveDocument()
{
if (saveDocumentToFile != null) {
NamedFileOperationDelegate method = delegate(string fileName) {
using (StreamWriter writer = new StreamWriter(fileName, false, System.Text.Encoding.UTF8)) {
writer.Write(document.TextContent);
}
};
FileUtility.ObservedSave(method, saveDocumentToFile, FileErrorPolicy.Inform);
}
}
protected void Reparse()
{
saveDocumentToFile = null;
// get new initialize components
string content = viewContent.Document.TextContent;
ParseInformation info = ParserService.ParseFile(viewContent.TextEditorControl.FileName, content, false, true);
ICompilationUnit cu = (ICompilationUnit)info.BestCompilationUnit;
foreach (IClass c in cu.Classes) {
if (FormDesignerSecondaryDisplayBinding.BaseClassIsFormOrControl(c)) {
initializeComponents = FormDesignerSecondaryDisplayBinding.GetInitializeComponents(c);
if (initializeComponents != null) {
using (StringReader r = new StringReader(content)) {
string designerFile = initializeComponents.DeclaringType.CompilationUnit.FileName;
string designerContent;
if (FileUtility.IsEqualFileName(viewContent.TextEditorControl.FileName, designerFile)) {
designerContent = content;
document = viewContent.Document;
} else {
IWorkbenchWindow window = FileService.GetOpenFile(designerFile);
if (window == null) {
document = new DocumentFactory().CreateDocument();
designerContent = ParserService.GetParseableFileContent(designerFile);
document.TextContent = designerContent;
saveDocumentToFile = designerFile;
} else {
ITextEditorControlProvider tecp = window.ViewContent as ITextEditorControlProvider;
if (tecp == null)
throw new ApplicationException("designer file viewcontent must implement ITextEditorControlProvider");
document = tecp.TextEditorControl.Document;
designerContent = document.TextContent;
}
ParserService.ParseFile(designerFile, designerContent, false, true);
}
using (StringReader r = new StringReader(designerContent)) {
int count = initializeComponents.Region.BeginLine;
for (int i = 1; i < count; i++)
r.ReadLine();
@ -165,7 +211,7 @@ namespace ICSharpCode.FormDesigner @@ -165,7 +211,7 @@ namespace ICSharpCode.FormDesigner
return false;
}
Reparse(viewContent.Document.TextContent);
Reparse();
foreach (IMethod method in c.Methods) {
if (method.Name == eventMethodName) {
@ -174,7 +220,7 @@ namespace ICSharpCode.FormDesigner @@ -174,7 +220,7 @@ namespace ICSharpCode.FormDesigner
}
}
MergeFormChanges();
Reparse(viewContent.Document.TextContent);
Reparse();
position = c.Region.EndLine + 1;
@ -188,9 +234,10 @@ namespace ICSharpCode.FormDesigner @@ -188,9 +234,10 @@ namespace ICSharpCode.FormDesigner
public ICollection GetCompatibleMethods(EventDescriptor edesc)
{
Reparse(viewContent.Document.TextContent);
Reparse();
ArrayList compatibleMethods = new ArrayList();
MethodInfo methodInfo = edesc.EventType.GetMethod("Invoke");
c = c.DefaultReturnType.GetUnderlyingClass();
foreach (IMethod method in c.Methods) {
if (method.Parameters.Count == methodInfo.GetParameters().Length) {
bool found = true;
@ -213,12 +260,13 @@ namespace ICSharpCode.FormDesigner @@ -213,12 +260,13 @@ namespace ICSharpCode.FormDesigner
public ICollection GetCompatibleMethods(EventInfo edesc)
{
Reparse(viewContent.Document.TextContent);
Reparse();
ArrayList compatibleMethods = new ArrayList();
MethodInfo methodInfo = edesc.GetAddMethod();
ParameterInfo pInfo = methodInfo.GetParameters()[0];
string eventName = pInfo.ParameterType.ToString().Replace("EventHandler", "EventArgs");
c = c.DefaultReturnType.GetUnderlyingClass();
foreach (IMethod method in c.Methods) {
if (method.Parameters.Count == 2) {
bool found = true;

93
src/AddIns/DisplayBindings/FormDesigner/Project/Src/FormDesigner/DesignerLoader/NRefactoryDesignerLoader.cs

@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.ComponentModel.Design;
@ -20,6 +21,7 @@ using ICSharpCode.Core; @@ -20,6 +21,7 @@ using ICSharpCode.Core;
using ICSharpCode.TextEditor;
using ICSharpCode.TextEditor.Document;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.FormDesigner.Services;
using ICSharpCode.NRefactory.Parser;
using ICSharpCode.NRefactory.Parser.AST;
@ -109,30 +111,95 @@ namespace ICSharpCode.FormDesigner @@ -109,30 +111,95 @@ namespace ICSharpCode.FormDesigner
{
LoggingService.Debug("NRefactoryDesignerLoader.Parse()");
lastTextContent = TextContent;
ICSharpCode.NRefactory.Parser.IParser p = ICSharpCode.NRefactory.Parser.ParserFactory.CreateParser(language, new StringReader(lastTextContent));
p.Parse();
if (p.Errors.count > 0) {
throw new FormDesignerLoadException(p.Errors.ErrorOutput);
}
// Try to fix the type names to fully qualified ones
ParseInformation parseInfo = ParserService.GetParseInformation(textEditorControl.FileName);
#if DEBUG
if ((Control.ModifierKeys & (Keys.Alt | Keys.Control)) == (Keys.Alt | Keys.Control)) {
System.Diagnostics.Debugger.Break();
}
#endif
lastTextContent = TextContent;
ParseInformation parseInfo = ParserService.GetParseInformation(textEditorControl.FileName);
IClass formClass = null;
foreach (IClass c in parseInfo.BestCompilationUnit.Classes) {
if (FormDesignerSecondaryDisplayBinding.BaseClassIsFormOrControl(c)) {
formClass = c;
break;
}
}
if (formClass == null)
throw new FormDesignerLoadException("No class derived from Form or Control was found.");
// Initialize designer for formClass
formClass = formClass.DefaultReturnType.GetUnderlyingClass();
List<IClass> parts;
if (formClass is CompoundClass) {
parts = (formClass as CompoundClass).Parts;
} else {
parts = new List<IClass>();
parts.Add(formClass);
}
List<KeyValuePair<string, CompilationUnit>> compilationUnits = new List<KeyValuePair<string, CompilationUnit>>();
bool foundInitMethod = false;
FixTypeNames(p.CompilationUnit, parseInfo.BestCompilationUnit, ref foundInitMethod);
foreach (IClass part in parts) {
string fileName = part.CompilationUnit.FileName;
if (fileName == null) continue;
bool found = false;
foreach (KeyValuePair<string, CompilationUnit> entry in compilationUnits) {
if (FileUtility.IsEqualFileName(fileName, entry.Key)) {
found = true;
break;
}
}
if (found) continue;
string fileContent = ParserService.GetParseableFileContent(fileName);
ICSharpCode.NRefactory.Parser.IParser p = ICSharpCode.NRefactory.Parser.ParserFactory.CreateParser(language, new StringReader(fileContent));
p.Parse();
if (p.Errors.count > 0) {
throw new FormDesignerLoadException("Syntax errors in " + fileName + ":\r\n" + p.Errors.ErrorOutput);
}
// Try to fix the type names to fully qualified ones
FixTypeNames(p.CompilationUnit, parseInfo.BestCompilationUnit, ref foundInitMethod);
compilationUnits.Add(new KeyValuePair<string, CompilationUnit>(fileName, p.CompilationUnit));
}
if (!foundInitMethod)
throw new FormDesignerLoadException("The InitializeComponent method was not found. Designer cannot be loaded.");
CompilationUnit combinedCu = new CompilationUnit();
NamespaceDeclaration nsDecl = new NamespaceDeclaration(formClass.Namespace);
combinedCu.AddChild(nsDecl);
TypeDeclaration formDecl = new TypeDeclaration(Modifier.Public, null);
nsDecl.AddChild(formDecl);
formDecl.Name = formClass.Name;
foreach (KeyValuePair<string, CompilationUnit> entry in compilationUnits) {
foreach (object o in entry.Value.Children) {
TypeDeclaration td = o as TypeDeclaration;
if (td != null && td.Name == formDecl.Name) {
foreach (INode node in td.Children)
formDecl.AddChild(node);
formDecl.BaseTypes.AddRange(td.BaseTypes);
}
if (o is NamespaceDeclaration) {
foreach (object o2 in ((NamespaceDeclaration)o).Children) {
td = o2 as TypeDeclaration;
if (td != null && td.Name == formDecl.Name) {
foreach (INode node in td.Children)
formDecl.AddChild(node);
formDecl.BaseTypes.AddRange(td.BaseTypes);
}
}
}
}
}
CodeDOMVisitor visitor = new CodeDOMVisitor();
visitor.Visit(p.CompilationUnit, null);
visitor.Visit(combinedCu, null);
// output generated CodeDOM to the console :
#if DEBUG

14
src/AddIns/DisplayBindings/FormDesigner/Project/Src/FormDesigner/FormDesignerSecondaryDisplayBinding.cs

@ -20,6 +20,9 @@ namespace ICSharpCode.FormDesigner @@ -20,6 +20,9 @@ namespace ICSharpCode.FormDesigner
{
public static IMethod GetInitializeComponents(IClass c)
{
c = c.DefaultReturnType.GetUnderlyingClass();
if (c == null)
return null;
foreach (IMethod method in c.Methods) {
if ((method.Name == "InitializeComponents" || method.Name == "InitializeComponent") && method.Parameters.Count == 0) {
return method;
@ -32,13 +35,16 @@ namespace ICSharpCode.FormDesigner @@ -32,13 +35,16 @@ namespace ICSharpCode.FormDesigner
{
// Simple test for fully qualified name
foreach (IReturnType baseType in c.BaseTypes) {
if (baseType.FullyQualifiedName == "System.Windows.Forms.Form" || baseType.FullyQualifiedName == "System.Windows.Forms.UserControl") {
if (baseType.FullyQualifiedName == "System.Windows.Forms.Form"
|| baseType.FullyQualifiedName == "System.Windows.Forms.UserControl"
// also accept Form and UserControl when they could not be resolved
|| baseType.FullyQualifiedName == "Form"
|| baseType.FullyQualifiedName == "UserControl")
{
return true;
}
}
// Test for real base type (does not work while solution load thread is still running)
IProjectContent pc = ProjectContentRegistry.WinForms;
return c.IsTypeInInheritanceTree(pc.GetClass("System.Windows.Forms.Form")) || c.IsTypeInInheritanceTree(pc.GetClass("System.Windows.Forms.UserControl"));
return false;
}
public static bool IsDesignable(ParseInformation info)

5
src/Main/Base/Project/Src/Gui/IWorkbenchWindow.cs

@ -25,7 +25,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -25,7 +25,7 @@ namespace ICSharpCode.SharpDevelop.Gui
}
/// <summary>
/// The current view content which is shown inside this window.
/// The primary view content in this window.
/// </summary>
IViewContent ViewContent {
get;
@ -40,6 +40,9 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -40,6 +40,9 @@ namespace ICSharpCode.SharpDevelop.Gui
}
*/
/// <summary>
/// The current view content which is shown inside this window.
/// </summary>
IBaseViewContent ActiveViewContent {
get;
}

19
src/Main/Base/Project/Src/Services/ParserService/ParserService.cs

@ -401,6 +401,25 @@ namespace ICSharpCode.Core @@ -401,6 +401,25 @@ namespace ICSharpCode.Core
return parseInformation;
}
public static string GetParseableFileContent(string fileName)
{
IWorkbenchWindow window = FileService.GetOpenFile(fileName);
if (window != null) {
IViewContent viewContent = window.ViewContent;
IEditable editable = viewContent as IEditable;
if (editable != null) {
return editable.Text;
}
}
//string res = project.GetParseableFileContent(fileName);
//if (res != null)
// return res;
// load file
Properties textEditorProperties = PropertyService.Get("ICSharpCode.TextEditor.Document.Document.DefaultDocumentAggregatorProperties", new Properties());
Encoding tmp = Encoding.GetEncoding(textEditorProperties.Get("Encoding", 1252));
return ICSharpCode.TextEditor.Util.FileReader.ReadFileContent(fileName, ref tmp, tmp);
}
public static ParseInformation GetParseInformation(string fileName)
{

4
src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/DocumentIterator/WholeSolutionDocumentIterator.cs

@ -50,9 +50,9 @@ namespace SearchAndReplace @@ -50,9 +50,9 @@ namespace SearchAndReplace
IDocument document;
string fileName = files[curIndex].ToString();
foreach (IViewContent content in WorkbenchSingleton.Workbench.ViewContentCollection) {
// WINDOWS DEPENDENCY : ToUpper
if (content.FileName != null &&
Path.GetFullPath(content.FileName).ToUpper() == Path.GetFullPath(fileName).ToUpper()) {
FileUtility.IsEqualFileName(content.FileName, fileName))
{
document = (((ITextEditorControlProvider)content).TextEditorControl).Document;
return new ProvidedDocumentInformation(document,
fileName,

Loading…
Cancel
Save