@@ -142,7 +142,8 @@ internal class FileTemplateImpl : FileTemplate, ICategory
142142 List < ReferenceProjectItem > requiredAssemblyReferences = new List < ReferenceProjectItem > ( ) ;
143143
144144 XmlElement fileoptions = null ;
145- Action < FileTemplateResult > actions ;
145+ Action < FileTemplateResult > createActions ;
146+ Action < FileTemplateResult > openActions ;
146147
147148 public string Author {
148149 get {
@@ -292,19 +293,26 @@ public FileTemplateImpl(XmlDocument doc, IReadOnlyFileSystem fileSystem)
292293 }
293294 }
294295
296+ if ( doc . DocumentElement [ "CreateActions" ] != null ) {
297+ foreach ( XmlElement el in doc . DocumentElement [ "CreateActions" ] ) {
298+ Action < FileTemplateResult > action = ReadAction ( el ) ;
299+ if ( action != null )
300+ createActions += action ;
301+ }
302+ }
303+
295304 if ( doc . DocumentElement [ "Actions" ] != null ) {
296305 foreach ( XmlElement el in doc . DocumentElement [ "Actions" ] ) {
297306 Action < FileTemplateResult > action = ReadAction ( el ) ;
298307 if ( action != null )
299- actions += action ;
308+ openActions += action ;
300309 }
301310 }
302311
303312 fileoptions = doc . DocumentElement [ "AdditionalOptions" ] ;
304313
305314 // load the files
306- XmlElement files = doc . DocumentElement [ "Files" ] ;
307- XmlNodeList nodes = files . ChildNodes ;
315+ XmlNodeList nodes = doc . DocumentElement [ "Files" ] . ChildNodes ;
308316 foreach ( XmlNode filenode in nodes ) {
309317 if ( filenode is XmlElement ) {
310318 this . files . Add ( new FileDescriptionTemplate ( ( XmlElement ) filenode , fileSystem ) ) ;
@@ -336,13 +344,13 @@ static Action<FileTemplateResult> ReadAction(XmlElement el)
336344
337345 public override void RunActions ( FileTemplateResult result )
338346 {
339- if ( actions != null )
340- actions ( result ) ;
347+ if ( openActions != null )
348+ openActions ( result ) ;
341349 }
342350
343351 public override string SuggestFileName ( DirectoryName basePath )
344352 {
345- if ( defaultName . IndexOf ( "${Number}" ) >= 0 ) {
353+ if ( defaultName . IndexOf ( "${Number}" , StringComparison . Ordinal ) >= 0 ) {
346354 try {
347355 int curNumber = 1 ;
348356
@@ -377,7 +385,7 @@ public override object CreateCustomizationObject()
377385 LocalizedTypeDescriptor localizedTypeDescriptor = new LocalizedTypeDescriptor ( ) ;
378386 foreach ( TemplateProperty property in Properties ) {
379387 LocalizedProperty localizedProperty ;
380- if ( property . Type . StartsWith ( "Types:" ) ) {
388+ if ( property . Type . StartsWith ( "Types:" , StringComparison . Ordinal ) ) {
381389 localizedProperty = new LocalizedProperty ( property . Name , "System.Enum" , property . Category , property . Description ) ;
382390 TemplateType type = null ;
383391 foreach ( TemplateType templateType in CustomTypes ) {
@@ -448,33 +456,53 @@ public override FileTemplateResult Create(FileTemplateOptions options)
448456 return null ;
449457 }
450458 }
451- ScriptRunner scriptRunner = new ScriptRunner ( ) ;
452- foreach ( FileDescriptionTemplate newFile in FileDescriptionTemplates ) {
453- FileOperationResult opresult = FileUtility . ObservedSave (
454- ( ) => {
455- string resultFile ;
456- if ( ! String . IsNullOrEmpty ( newFile . BinaryFileName ) ) {
457- resultFile = SaveFile ( newFile , null , newFile . BinaryFileName , options ) ;
458- } else {
459- resultFile = SaveFile ( newFile , scriptRunner . CompileScript ( this , newFile ) , null , options ) ;
460- }
461- if ( resultFile != null ) {
462- result . NewFiles . Add ( FileName . Create ( resultFile ) ) ;
463- }
464- } , FileName . Create ( StringParser . Parse ( newFile . Name ) )
465- ) ;
466- if ( opresult != FileOperationResult . OK )
467- return null ;
459+ try {
460+ var filesToOpen = new List < FileName > ( ) ;
461+ ScriptRunner scriptRunner = new ScriptRunner ( ) ;
462+ foreach ( FileDescriptionTemplate newFile in FileDescriptionTemplates ) {
463+ FileOperationResult opresult = FileUtility . ObservedSave (
464+ ( ) => {
465+ OpenedFile resultFile ;
466+ bool shouldOpen ;
467+ if ( ! String . IsNullOrEmpty ( newFile . BinaryFileName ) ) {
468+ resultFile = SaveFile ( newFile , null , newFile . BinaryFileName , options , out shouldOpen ) ;
469+ } else {
470+ resultFile = SaveFile ( newFile , scriptRunner . CompileScript ( this , newFile ) , null , options , out shouldOpen ) ;
471+ }
472+ if ( resultFile != null ) {
473+ result . NewOpenedFiles . Add ( resultFile ) ;
474+ result . NewFiles . Add ( resultFile . FileName ) ;
475+ if ( shouldOpen )
476+ filesToOpen . Add ( resultFile . FileName ) ;
477+ }
478+ } , FileName . Create ( StringParser . Parse ( newFile . Name ) )
479+ ) ;
480+ if ( opresult != FileOperationResult . OK )
481+ return null ;
482+ }
483+
484+ // Run creation actions
485+ if ( createActions != null )
486+ createActions ( result ) ;
487+
488+ foreach ( var filename in filesToOpen . Intersect ( result . NewFiles ) )
489+ SD . FileService . OpenFile ( filename ) ;
490+ } finally {
491+ // Now that the view contents
492+ foreach ( var file in result . NewOpenedFiles ) {
493+ file . CloseIfAllViewsClosed ( ) ;
494+ }
495+ result . NewOpenedFiles . RemoveAll ( f => f . RegisteredViewContents . Count == 0 ) ;
496+ }
497+ // raise FileCreated event for the new files.
498+ foreach ( var fileName in result . NewFiles ) {
499+ FileService . FireFileCreated ( fileName , false ) ;
468500 }
469501
470502 if ( project != null ) {
471503 project . Save ( ) ;
472504 }
473505
474- // raise FileCreated event for the new files.
475- foreach ( var fileName in result . NewFiles ) {
476- FileService . FireFileCreated ( fileName , false ) ;
477- }
478506 return result ;
479507 }
480508
@@ -486,8 +514,12 @@ bool IsFilenameAvailable(string fileName)
486514 return true ;
487515 }
488516
489- string SaveFile ( FileDescriptionTemplate newFile , string content , string binaryFileName , FileTemplateOptions options )
517+ /// <summary>
518+ /// Creates an OpenedFile for the new file, fills it with the file content, and saves it to disk.
519+ /// </summary>
520+ OpenedFile SaveFile ( FileDescriptionTemplate newFile , string content , string binaryFileName , FileTemplateOptions options , out bool shouldOpen )
490521 {
522+ shouldOpen = false ;
491523 string unresolvedFileName = StringParser . Parse ( newFile . Name ) ;
492524 // Parse twice so that tags used in included standard header are parsed
493525 string parsedContent = StringParser . Parse ( StringParser . Parse ( content ) ) ;
@@ -502,8 +534,8 @@ string SaveFile(FileDescriptionTemplate newFile, string content, string binaryFi
502534 // when newFile.Name is "${Path}/${FileName}", there might be a useless '/' in front of the file name
503535 // if the file is created when no project is opened. So we remove single '/' or '\', but not double
504536 // '\\' (project is saved on network share).
505- if ( unresolvedFileName . StartsWith ( "/" ) && ! unresolvedFileName . StartsWith ( "//" )
506- || unresolvedFileName . StartsWith ( "\\ " ) && ! unresolvedFileName . StartsWith ( "\\ \\ " ) )
537+ if ( unresolvedFileName . StartsWith ( "/" , StringComparison . Ordinal ) && ! unresolvedFileName . StartsWith ( "//" , StringComparison . Ordinal )
538+ || unresolvedFileName . StartsWith ( "\\ " , StringComparison . Ordinal ) && ! unresolvedFileName . StartsWith ( "\\ \\ " , StringComparison . Ordinal ) )
507539 {
508540 unresolvedFileName = unresolvedFileName . Substring ( 1 ) ;
509541 }
@@ -519,6 +551,7 @@ string SaveFile(FileDescriptionTemplate newFile, string content, string binaryFi
519551 File . WriteAllText ( fileName , parsedContent , SD . FileService . DefaultFileEncoding ) ;
520552 if ( project != null )
521553 AddTemplateFileToProject ( project , newFile , fileName ) ;
554+ return SD . FileService . GetOrCreateOpenedFile ( fileName ) ;
522555 } else {
523556 if ( ! String . IsNullOrEmpty ( binaryFileName ) ) {
524557 LoggingService . Warn ( "binary file was skipped" ) ;
@@ -539,15 +572,15 @@ string SaveFile(FileDescriptionTemplate newFile, string content, string binaryFi
539572 } else {
540573 file = SD . FileService . CreateUntitledOpenedFile ( Path . GetFileName ( fileName ) , data ) ;
541574 }
542-
543- SD . FileService . OpenFile ( file . FileName ) ;
575+ shouldOpen = true ;
576+ OpenedFile retVal = file ;
577+ file = null ; // don't close file when there was no exception and we're returning it
578+ return retVal ;
544579 } finally {
545580 if ( file != null )
546581 file . CloseIfAllViewsClosed ( ) ;
547582 }
548583 }
549-
550- return fileName ;
551584 }
552585
553586 static void AddTemplateFileToProject ( IProject project , FileDescriptionTemplate newFile , FileName fileName )
0 commit comments