Skip to content

Commit a5931d0

Browse files
committed
fixed export logic for UserForm modules, refactored extension method.
1 parent 0779d50 commit a5931d0

File tree

1 file changed

+49
-34
lines changed

1 file changed

+49
-34
lines changed

Rubberduck.VBEEditor/Extensions/VBComponentExtensions.cs

Lines changed: 49 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Linq;
34
using System.IO;
45
using Microsoft.Vbe.Interop;
@@ -21,48 +22,62 @@ public static class VBComponentExtensions
2122
public static string ExportAsSourceFile(this VBComponent component, string directoryPath)
2223
{
2324
var path = Path.Combine(directoryPath, component.Name + component.Type.FileExtension());
24-
if (component.Type == vbext_ComponentType.vbext_ct_Document)
25+
switch (component.Type)
2526
{
26-
var lineCount = component.CodeModule.CountOfLines;
27-
if (lineCount > 0)
28-
{
29-
var text = component.CodeModule.get_Lines(1, lineCount);
30-
File.WriteAllText(path, text);
31-
}
27+
case vbext_ComponentType.vbext_ct_MSForm:
28+
ExportUserFormModule(component, path);
29+
break;
30+
case vbext_ComponentType.vbext_ct_Document:
31+
ExportDocumentModule(component, path);
32+
break;
33+
default:
34+
component.Export(path);
35+
break;
3236
}
33-
else if(component.Type == vbext_ComponentType.vbext_ct_MSForm)
37+
38+
return path;
39+
}
40+
41+
private static void ExportUserFormModule(VBComponent component, string path)
42+
{
43+
// VBIDE API inserts an extra newline when exporting a UserForm module.
44+
// this issue causes forms to always be treated as "modified" in source control, which causes conflicts.
45+
// we need to remove the extra newline before the file gets written to its output location.
46+
47+
var visibleCode = component.CodeModule.Lines().Split(new []{Environment.NewLine}, StringSplitOptions.None);
48+
var legitEmptyLineCount = visibleCode.TakeWhile(string.IsNullOrWhiteSpace).Count();
49+
50+
var tempFile = component.ExportToTempFile();
51+
var contents = File.ReadAllLines(tempFile);
52+
var nonAttributeLines = contents.TakeWhile(line => !line.StartsWith("Attribute")).Count();
53+
var attributeLines = contents.Skip(nonAttributeLines).TakeWhile(line => line.StartsWith("Attribute")).Count();
54+
var declarationsStartLine = nonAttributeLines + attributeLines + 1;
55+
56+
var emptyLineCount = contents.Skip(declarationsStartLine - 1)
57+
.TakeWhile(string.IsNullOrWhiteSpace)
58+
.Count();
59+
60+
var code = contents;
61+
if (emptyLineCount > legitEmptyLineCount)
3462
{
35-
// VBIDE API inserts an extra newline when exporting a UserForm module.
36-
// this issue causes forms to always be treated as "modified" in source control, which causes conflicts.
37-
// we need to remove the extra newline before the file gets written to its output location.
38-
var tempFile = component.ExportToTempFile();
39-
var contents = File.ReadAllLines(tempFile);
40-
var vbExposedAttributeLine = 0;
41-
for (var i = 0; i < contents.Length; i++)
42-
{
43-
if (contents[i].StartsWith("Attribute VB_Exposed = "))
44-
{
45-
vbExposedAttributeLine = i;
46-
break;
47-
}
48-
}
49-
if (contents.Length > vbExposedAttributeLine && contents[vbExposedAttributeLine + 1].Replace(Environment.NewLine, string.Empty).Trim() == string.Empty)
50-
{
51-
// first line in module is empty - assume it wasn't in the VBE
52-
var edited = contents.Take(vbExposedAttributeLine).Union(contents.Skip(vbExposedAttributeLine + 1)).ToArray();
53-
File.WriteAllLines(path, edited);
54-
}
63+
code = contents.Take(declarationsStartLine).Union(
64+
contents.Skip(declarationsStartLine + emptyLineCount - legitEmptyLineCount))
65+
.ToArray();
5566
}
56-
else
67+
File.WriteAllLines(path, code);
68+
}
69+
70+
private static void ExportDocumentModule(VBComponent component, string path)
71+
{
72+
var lineCount = component.CodeModule.CountOfLines;
73+
if (lineCount > 0)
5774
{
58-
// other module types can just be exported directly
59-
component.Export(path);
75+
var text = component.CodeModule.Lines[1, lineCount];
76+
File.WriteAllText(path, text);
6077
}
61-
62-
return path;
6378
}
6479

65-
public static string ExportToTempFile(this VBComponent component)
80+
private static string ExportToTempFile(this VBComponent component)
6681
{
6782
var path = Path.Combine(Path.GetTempPath(), component.Name + component.Type.FileExtension());
6883
component.Export(path);

0 commit comments

Comments
 (0)