24

I am splitting T4 code in separate files for modularity and reuse but I am finding out that each file costs me an empty line in output. For example:

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".ttinclude" #>
<#@ Import Namespace="System.Collections.Generic" #>
<#@ Include file="Includes.tt" #>
namespace <#= NameSpace #>
{

If Includes.tt lists 3 other *.tt files, I get 3 blank lines before the namespace. As I am adding code and splitting it in separate *.tt files, this empty space keeps growing. In fact, I packed all the include files into a single Includes.tt, hoping that this will cost me just one empty line. It didn't. I still get one empty line per each file listed in Includes.tt. Is there a way of avoiding this?

Edit: assuming that I am not making just a dumb mistake (and I sincerely hope that I am), the problem is not as trivial as it may appear on the first sight:

a) Reuse and modularity via included T4 files is as old as T4 itself and was mentioned in latest MSDN Magazine article: "Managing Complexity in T4 Code-Generation Solutions".

b) If code is auto-generated, it doesn't mean that it is Ok for it to be badly formatted or poorly legible.

c) With the current solution, in my case, for each and every generated .cs file the reader would have to scroll for one empty page until she starts seeing some generated text. All because I have split my code generation between multiple included .tt files. That just doesn't seem right.

Tony
  • 1,566
  • 2
  • 15
  • 27

6 Answers6

17

To add to Tony's answer: You can avoid the very long lines by adding the linebreaks within the T4 brackets like so:

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".ttinclude" #>
<#@ Import Namespace="System.Collections.Generic" #>
<#@ Include file="Usings.tt" 
#><#@ Include file="PropertyTypeEnum.tt" 
#><#@ Include....
#><#@ Include....
#><#@ Include....
#><#@ some other stuff 
B3ret
  • 597
  • 5
  • 19
  • oooooh! that's what that is for. _I learnt something new today_. +1 –  May 15 '20 at 07:46
16

Oh well, the solution turned out to be trivial, if somewhat unexpected : just put the include directives next to each other, instead of one below another :

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".ttinclude" #>
<#@ Import Namespace="System.Collections.Generic" #>
<#@ Include file="Usings.tt" #> <#@ Include file="PropertyTypeEnum.tt" #> <#@ Include.... 
Tony
  • 1,566
  • 2
  • 15
  • 27
  • 2
    Hi Tony - this is a bit of a legacy from our early versions. We're now somewhat loathe to 'fix' it as that would break backwards compatibility for folks who've used the workaround. We've toyed with the idea of an opt-in flag, something like 'smarterParsing=true', but i"m not too keen to have to test two parsing codepaths at this point. – GarethJ May 09 '12 at 19:12
  • The same trick works even with single Include - just make sure that there are no characters between closing tag of the include and the next instruction (be it literal or <# tag) – ViktorZ Mar 07 '14 at 10:24
  • The real reason is that every generated Template (it's cs code) has a \r\n in `public virtual string TransformText() { this.Write(" \r\n");`, so your answer is just working because the newline added by pressing return after each included template is omitted. – Sebastian May 21 '15 at 10:48
  • 1
    Is this a real issue though. I would have the T4 code more readable than the generated code, especially if its is just related to alan lines? or am I missing something? – Mark Redman Sep 03 '16 at 06:19
15

This also works for me in VS 2013:

<#@ include file="Other.tt" #><##>

and so

<#@ include file="One.tt" #><##>
<#@ include file="Two.tt" #><##>
...

The <##> is just an empty control block. <# /* any code here */ #> works just as well.

El Zorko
  • 3,349
  • 2
  • 26
  • 34
13

I had a more fundamental issue where each <#@ header line before <?xml caused its own blank line in the output, which caused the error:

error : Unexpected XML declaration.
        The XML declaration must be the first node in the document,
        and no white space characters are allowed to appear before it.
        Line 7, position 3.

After digging for a while I discovered the .tt file had Unix EOL.

When I switched to Windows EOL, the transform removed the blank lines.

Carl Walsh
  • 6,100
  • 2
  • 46
  • 50
5

In my case the blank lines resulted from a trailing space after the closing tag of import statements.

DySoS
  • 105
  • 1
  • 6
1

For me the problem occured when using Unix line endings (LF). Using Windows line endings (CR LF) resolved my problem and may resolve yours.

JoBrittain
  • 11
  • 1