Controlling tabs in generated code



Currently, when working with a toolkit project various files are created and some files are continuously re-generated in a toolkit project, and in the toolkit.automation project.
For the sake of this discussion we will make a distinction between T4 templates that are generated once (ever) and refer to these as "one-gen" (i.e. one-shot). T4 templates that are continuous regenerated throughout the lifecycle of the toolkit project are called "cont-gen".
For example, several "one-gen" files are created when the project is created, but the interface layer code "cont-gen" is regenerated whenever the project is built.

All T4 generated files will contain leading tabs or spaces, that is initially pre-determined by the templates in the authoring toolkit.
However, a VS user can determine whether to use TABS or SPACES in the Options of VS.
(i.e. Tools | Options | Text Editor | <language> | Tabs [Insert Spaces | Keep Tabs]).
This option sets the intention for all ocde in the project.
By default in VS, any VSTemplate (Item or Project) that is unfolded into a project in the solution will be reformatted heeding this setting, regarless of whether the template originally contained leading spaces or tabs. VS automatically reformats the whole document after creating it. This ensures that the current user's setting is honored.

However, T4 generated files are not subject to the same process when generated. Although, perhaps they could be. It is not done today.
Regardless, users of toolkits will expect code artifacts that are generated to also adhere to their settings.


Either: (1) add a post process to the T4 generation that reformats generated documents according to the user's desired leading tabs/spaces settings.
Or (2) ensure that T4 generated documents make use of utilities that insert leading tabs/spaces at generation time. Regardless of whether they are one-gen or cont-gen.

This can be achieved by using and wrapping the PushIndent() and PopIndent() methods provided by the T4 runtime, and using the currently selected option in the user's setting for the language of text being generated.
However, in order to do this for some T4 files, this makes the T4 overly complex when simple substitutions are all that is required. (e.g. see the guidance document XDOC file!!).


jezzsa wrote Mar 30, 2013 at 4:31 AM

We could of course just read the setting already configured in visual studio for the language being generated.
i.e. from Tools | Options | Text Editor | <language> | Tabs (Insert Spaces | Keep Tabs)

We could provide a method on the existing CodeGeneration class that a parameter for passing in the generated language, and return the appropriate characters to use to indent.

We then call this method from the PushIndent() method in the actual text template.
i.e. PushIndent(CodeGeneration.GetIndentation("c#"));

jezzsa wrote Mar 31, 2013 at 10:30 AM

At this point we have a method on the CodeGeneration class, and we are using it in only cont-gen templates, but this method hardcodes the return value of a TAB character at present (regarless of the language parameter specified). We need to write some more code in order to look up the users current settings.

jezzsa wrote Mar 31, 2013 at 10:39 AM

I also like the suggestion that we could enhance the T4 generation process of all code, and reformat the code after generation to comply to the configured settings in VS for that specific language.

Not sure if this is the starting point, but I found a link to something like what we could start from: http://msdn.microsoft.com/en-us/library/bb164633(v=VS.80).aspx

Although, VS language editor developers should have a clue how we can call upon VS to do the heavy lifting for us? No?

dcazzulino wrote Mar 31, 2013 at 1:15 PM

Non-trivial and useless. Nobody cares about tabs or spaces of generated code, it's "invisible" for all practical purposes. Just being able to read it to understand what it does, maybe...

jezzsa wrote Mar 31, 2013 at 10:41 PM

I knew you would say that kzu :) I hear you when you say that fixing the issue is 'non-trivial', but I think you may have intended to say that whether to have TABS and SPACES "may have little value to toolkit users".
Which may well be the case, and therefore not a high priority for the project to work on.
But I did want to share our findings in these area, things which I feel are often overlooked by projects that build developer tooling, when it comes to adoption of their automation.

The software industry has been slow to accept , adopt and demand software automation. Even though we (this group) wheels and deals in this space, and we move with folks who are a little more forward thinking in this space. We find more than the average amount of acceptance of automation. However, I think in general most software engineers out there, specifically either the most senior and most junior do not welcome automation as much as they could or should.

You have prompted me to get my thoughts down in more detail. I tried to respond here with some intelligent debate, but it went on too long. So I'll blog separately on this instead. :)

As I said, I think we put too little importance on this kind of thing, and we under-rate how our code generation tools should behave and perform. And that has a direct impact on the acceptance and adoption of them, and the frameworks within which they work. But let me expand more convincingly elsewhere.

For now, I am happy that this is low priority until told otherwise.

dcazzulino wrote Mar 31, 2013 at 11:44 PM

You mean tabs/spaces control will win the crowds over? Call me a skeptic ;)

jezzsa wrote Apr 7, 2013 at 4:38 AM

OK, after doing all the rework and discovering how VS templates handles this problem, to me it is clear that there would be a very simple solution to the problem.
I would hope that this is all that hard to implement in the NuPattern code generation command.

As it turns out, when Visual Studio unfolds a VS template, no matter whether the files in the template used TABS or SPACES or a mix, the files are automatically converted to the user defined settings specified in VS!

This means that we could follow suit with text templates, and after any generation, simply 'Reformat' the document using the user-defined settings in Visual Studio.

Presumably, there is a command or API in Viusal Studio that we can leverage to do this for us? The challenge will be finding out what that command or API is and applying it after NuPattern generates any text file with the CodeGeneration command.