VsixCommunity / Community.VisualStudio.Toolkit

Making it easier to write Visual Studio extensions
Other
256 stars 44 forks source link

Source generator goes in infinite loop for .xml file extension. #436

Closed prabhav-mehra closed 11 months ago

prabhav-mehra commented 1 year ago

I have a VSIX extension which runs on a .xml file of a particular format and creates another .xml (expecting only one file) in some different format using the provided file content.

Now when I run this extension on a .xml file, it goes in a loop when creating the generated .xml file with the filename in the format of {fileName}1^n.xml

Suppose I run the extension on a test.xml, it sets the custom tool and creates test1.xml, test11.xml, test111.xml and so on, until I terminate the program.

When I change the GetDefaultExtension to ".cs" this doesn't happen and then it only creates one file.

Providing some code below. This is fairly similar to one from the SingleFileGenerator sample. I haven't gotten that to work for some reason to see if it's only a .xml thing, something related to my source generator or some error on files except the ".cs" extension.

// MyCommand.cs
        protected override Task InitializeCompletedAsync()
        {
              Command.Supported = false;
              return base.InitializeCompletedAsync();
        }

        protected override async Task ExecuteAsync(OleMenuCmdEventArgs e)
        {
              var file = await VS.Solutions.GetActiveItemAsync() as PhysicalFile;
              await file.TrySetAttributeAsync("custom tool", ToolsAndroidRestrictionGenerator.Name);
        }

//  ToolsAndroidRestrictionGenerator.cs
        public class ToolsAndroidRestrictionGenerator : BaseCodeGeneratorWithSite
        {
              public const string Name = nameof(ToolsAndroidRestrictionGenerator);
              public const string Description = "Copy xml file";

              public override string GetDefaultExtension()
              {
                  return ".xml";
              }

              protected override byte[] GenerateCode(string inputFileName, string inputFileContent)
              {

                  string code = CopyXml(inputFileContent);

                  return Encoding.UTF8.GetBytes(code);
              }

              private static string CopyXml(string fileContent) {}

        }

// Main Class

      [PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
      [InstalledProductRegistration(Vsix.Name, Vsix.Description, Vsix.Version)]
      [ProvideMenuResource("Menus.ctmenu", 1)]
      [Guid(PackageGuids.ToolsString)]
      [ProvideCodeGenerator(typeof(ToolsAndroidRestrictionGenerator), ToolsAndroidRestrictionGenerator.Name, ToolsAndroidRestrictionGenerator.Description, true, RegisterCodeBase = true)]
      [ProvideCodeGeneratorExtension(ToolsAndroidRestrictionGenerator.Name, ".xml")]
      [ProvideUIContextRule(PackageGuids.CommandVisisiblityString,
          name: "Xml files",
          expression: "Xml",
          termNames: new[] { "Xml" },
          termValues: new[] { "HierSingleSelectionName:.xml$" })]
      public sealed class ToolsPackage : ToolkitPackage
      {
            protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress)
            {
                await this.RegisterCommandsAsync();

            }
      }
reduckted commented 1 year ago

This is just a guess, but it sounds like the code generator is running on the original file and the generated file because the generated file has the same extension that code generator operates on.

You probably need to either generate to a file with a different extension (which doesn't sound like it would be practical in your scenario), or not automatically apply the code generator to all XML files.

prabhav-mehra commented 1 year ago

@reduckted yep thats correct. That’s probably what’s happening. Is it possible I can change the name of the generated file, or change the location of the genrated file. So test.xml (the original file) creates 1 generated_test.xml file and hardcode the generated_test somewhere. And make it generator run on only test.xml or/and generate the generated file to some folder.

prabhav-mehra commented 1 year ago

@reduckted I tried different things to achieve what you had suggested, couldn't get it to work. Is there any example I can refer to get the same result?