stefanegli/ResxFormatter

Strip comments from Designer.cs files

Closed this issue · 6 comments

Please strip the comments from the Designer.cs file that is being generated by VisualStudio from resx files.

In our team we have VisualStudio installations with different language settings (i.e. English and German) and every time someone touches a resx file (for localization) the corresponding Designer.cs file is being generated and all comments therein are being replaced in whatever language has is being configured in the local VisualStudio. That leads to crazy conflicts when two people with different language settings are editing the same resx file.

So I propose, for any resx file your extension is editing, look for a corresponding Designer.cs file and strip comments from there, also.

Example:
"Localization.resx" is being edited
"Localization.Designer.cs" file is being generated by VisualStudio

=> ResxFormatter should strip comments from both files.

Interesting... have to see if this can even be done (not sure if the event is too soon and maybe there is no event for the designer file?). Simply striping the comments does feel somewhat wrong, because it can be helpful to see what a "key" might contain on the other hand having the string truncated can limit the usefulness in the IDE. Maybe I could replace the existing comment with something a bit more useful and more importantly well defined (i.e. specific language configured in EditorConfig file).

Do you have some example comment in German (or another language)? I am interested to see, what they look like.

Thanks for looking into it. Having the comment language configurable would of course be nice. I would have actually expected VS to provide that.

A German designer file starts with those comments:

//------------------------------------------------------------------------------
// <auto-generated>
//     Dieser Code wurde von einem Tool generiert.
//     Laufzeitversion:4.0.30319.42000
//
//     Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
//     der Code erneut generiert wird.
// </auto-generated>
//------------------------------------------------------------------------------

namespace ViewsPluginLib.Localization {
    using System;
    
    
    /// <summary>
    ///   Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
    /// </summary>
    // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
    // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
    // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
    // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    internal class Localization {
        
        private static global::System.Resources.ResourceManager resourceMan;
        
        private static global::System.Globalization.CultureInfo resourceCulture;
        
        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
        internal Localization() {
        }
        
        /// <summary>
        ///   Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
        /// </summary>
                       [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
        internal static global::System.Resources.ResourceManager ResourceManager {
            get {
                if (object.ReferenceEquals(resourceMan, null)) {
                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DHF2ViewsPluginLib.Localization.Localization", typeof(Localization).Assembly);
                    resourceMan = temp;
                }
                return resourceMan;
            }
        }
        
        /// <summary>
        ///   Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
        ///   Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
        /// </summary>
        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
        internal static global::System.Globalization.CultureInfo Culture {
            get {
                return resourceCulture;
            }
            set {
                resourceCulture = value;
            }
        }

and it goes on like that for the individual keys

        /// <summary>
        ///   Sucht eine lokalisierte Zeichenfolge, die Add Component ähnelt.
        /// </summary>
        internal static string AddDevice {
            get {
                return ResourceManager.GetString("AddDevice", resourceCulture);
            }
        }
        
        /// <summary>
        ///   Sucht eine lokalisierte Zeichenfolge, die Baud Rate ähnelt.
        /// </summary>
        internal static string BaudRate {
            get {
                return ResourceManager.GetString("BaudRate", resourceCulture);
            }
        }

It is as I feared: Visual Studio runs the custom tool after I am done formatting the resx file. I made a very basic implementation that strips the comments from the cs file and if I set a break point in my extension I can see how the cs file is updated correctly. after I let the program resume the custom tool write the cs file again and my modifications are gone.

Not entirely sure how to proceed with this. I can look into custom tools, maybe it makes sense to control the generation of the cs file directly. At this point I cannot promise you a quick solution to your problem.

Well, thanks anyhow for trying! It's an annoying behavior of Visual Studio and I cannot understand that this is not an issue annoying almost any multi language team.

So I went looking again... and found this:
https://www.codeproject.com/Articles/31907/Customize-the-Code-Generated-by-the-Resources-Desi

I guess that's kind of what you meant by "look into custom tools"?

In theory my extension could just write the designer file, pretty much as outlined in your link. The other thing I was considering to do it as follows:
https://docs.microsoft.com/en-us/visualstudio/extensibility/internals/implementing-single-file-generators?view=vs-2022

however, I think the best way forward is actually this here:
https://github.com/VocaDB/ResXFileCodeGenerator

It was never very appealing to have these files as part of the checked-in source code, and it seems that source generators can solve this problem and I think they will work better for .NET 6. The SDK style projects do not really properly deal with resx files as far as I can tell.

Thanks for taking your time and finding ResXFileCodeGenerator. I will check how that works.