This project is read-only.

T4Toolbox deletes files even if Generator.Validate() fails

Aug 8, 2013 at 9:08 AM
I created MyGenerator class that inherits from T4Toolbox.Generator. When I call MyGenerator.Run(), T4Toolbox first calls Validate() method and if there are validation errors it does not even call RunCore(), which is great.
The problem is that even if RunCore() is not called, T4Toolbox deletes all the files previously generated - which is not what I want... I just want to show errors in VS Error List, and keep the previously generated files intact.

We're using TFS for source control, and all files are getting checked-out and deleted, and I have to check-in those changes before I run MyGenerator again or I'm getting error pop-up dialogs for every file that T4Toolbox tries to check-out again.

Is there a way to tell T4Toolbox not to delete files previously generated if validation fails?

And secondly, how does T4Toolbox even know what files he previously generated when there is no log file created after running a Generator? If it saves it in the memory, how can it be accessed?
Sep 22, 2013 at 3:54 PM
I've got the same problem and there seems no really good way to achieve what we want. However I was able to implement a work around in my Generator class.
/// <summary>
/// A pseudo template that just read the content of the specified file
/// and returns the content when <see cref="M:TransformText"/> is called.
/// </summary>
public class RetentionTemplate : Template
{
    private readonly string outputPath;

    /// <summary>
    /// Initializes a new instance of the <see cref="RetentionTemplate"/> class.
    /// </summary>
    /// <param name="outputPath">The output path.</param>
    internal RetentionTemplate( string outputPath )
    {
        this.outputPath = outputPath;
    }

    public override string TransformText()
    {
        var content = File.ReadAllText( this.outputPath );
        return content;
    }
}


public class MyGenerator : Generator
{
    private bool runRetentionTransformation;

    /// <summary>
    /// Verify that the configuration exists and all objects can be found.
    /// </summary>
    protected override void Validate()
    {
        try {
            base.Validate();
            ValidateCore();
        }
        catch ( Exception ex ) {
            Error( ex.Message );
        }
        if ( Errors.HasErrors ) {
            Context.Host.LogErrors( Errors );
            Errors.Clear();
            Debug.Assert( !Errors.HasErrors );
            this.runRetentionTransformation = true;
        }
    }

    protected override void RunCore()
    {
        if ( this.runRetentionTransformation ) {
            RunRetentionTransformation();
        }
        else {
            RunTemplateTransformation();
        }
    }

    /// <summary>
    /// Fake transformation called in case that the validation failed.
    /// </summary>
    /// <remarks>
    /// This fake generation just reads all generated files
    /// created by the last run and just returns the current
    /// content as the transformation result.
    /// </remarks>
    private void RunRetentionTransformation()
    {
        var dte = (DTE)Context.GetService( typeof( DTE ) );
        if ( dte == null )
            return;

        var selectedItem = dte.SelectedItems.Item( 1 );
        var projectItem = selectedItem.ProjectItem;

        var templateFile = Context.Host.TemplateFile;
        var templateName = Path.GetFileNameWithoutExtension( templateFile );

        var subItems = projectItem.ProjectItems;
        foreach ( ProjectItem subItem in subItems ) {
            var fileCount = subItem.FileCount;
            for ( short i = 0; i < fileCount; ++i ) {
                var subItemPath = subItem.get_FileNames( i );
                var subItemName = Path.GetFileNameWithoutExtension( subItemPath );

                // The main transformation result is only used to log errors
                // and warnings. Do not overwrite it here.
                if ( subItemName == templateName ) {
                    continue;
                }
                var pseudoTemplate = new RetentionTemplate( subItemPath );
                var subItemFile = System.IO.Path.GetFileName( subItemPath );
                pseudoTemplate.RenderToFile( subItemFile );
            }
        }
    }

    /// <summary>
    /// The real code generation process
    /// </summary>
    private void RunTemplateTransformation()
    {
    }
}

I haven't finally testet this approach but up to now it seems to work.

Ralf