ThisAssembly icon indicating copy to clipboard operation
ThisAssembly copied to clipboard

ThisAssembly.Strings: If resource name is not a valid code identifier, compilation fails

Open kzu opened this issue 2 years ago • 1 comments

If a resx file contains an entry with an invalid code identifier (like a number), the generated code will not compile, and the error is quite cryptic too.

We should validate that the name are valid C# identifiers and skip (probably warn too if they aren't?)

kzu avatar Nov 30 '21 21:11 kzu

Some quick notes:

  • The same check may be useful in other situations where identifiers are involved, e.g. user-defined constants.
  • Roslyn has a handy IsValidIdentifier utility method that can be used for this purpose.
  • There's an IsValidIdentifier method for Visual Basic too, so you may call one or the other according to the project's language.
  • F# is no concern, as it doesn't support code generators.

rdeago avatar May 19 '22 06:05 rdeago

I guess more than just checking whether the identifier is valid, you'd actually want it to generate code but turn the identifier into a valid one by replacing invalid chars with underscores, say...

kzu avatar Jan 10 '23 21:01 kzu

@viceroypenguin perhaps this could also use the sanitization you applied to resource class names?

kzu avatar Jan 10 '23 21:01 kzu

Yeah, I encountered this while working on Resources; I just got lazy and avoided it for now... 🙂. I would expect the code to work the same here. Could copy/paste or extract to common .cs file. The regex is doing the bulk of the work, so copy/paste would probably be fine.

viceroypenguin avatar Jan 10 '23 21:01 viceroypenguin

This method could be used to generate a valid identifier : it replaces any invalid identifier by '', removes redundant '', and prefixes the identifier by '_' if not valid :

        private string EscapeIdentifier(string filename)
        {
            var bytes = filename.ToCharArray();

            var replaced = bytes.Select(_ => SyntaxFacts.IsIdentifierPartCharacter(_) ? _ : '_').ToArray();

            var result = Regex.Replace(new string(replaced), "(_)+", "_");

            if (!SyntaxFacts.IsValidIdentifier(result))
            {
                result = "_" + result;
            }

            return result;
        }

As for now, all we can do is change all the files' name, but that's not always easy.

PhenX avatar Jul 28 '23 13:07 PhenX

Thanks for the suggestion @PhenX. Would you like to send a PR? 🙏

kzu avatar Aug 02 '23 10:08 kzu