Skip to content

layout, naming and jsDoc options - #19

Open
tinkerer-red wants to merge 1 commit into
Pizzaandy:mainfrom
tinkerer-red:main
Open

layout, naming and jsDoc options#19
tinkerer-red wants to merge 1 commit into
Pizzaandy:mainfrom
tinkerer-red:main

Conversation

@tinkerer-red

Copy link
Copy Markdown

AI Notice!

This PR was assisted with AI! feel free to close it, I only needed this for personal use anyways. While i can mostly read csharp im not very good at writing it. I merely needed to clean up the bad coding practices of 8 year old gamemaker code being updated. However to alleviate some concerns, i did not pump this out in a few minutes with a one off attempt, i spent several hours walking through each piece ensuring it was doing exactly what was expected. I've reviewed the code to the best of my abilities, and even did my best to refactor where i could to ensure the project stayed as close to your coding practices as possible. So real effort was at least put into this, and ai was merely used to bridge the gap. With that in mind im also aware some people refuse to use LLMs at all and can respect that. <3


Extends the existing formatter. Everything new is an option. Two defaults changed, noted below, easily changed back.

Default changes

  • width 90 to 120. This is the default gamemaker ide window size before a horz scrollbar appears.
  • braceStyle was [JsonIgnore], so it is now readable from .goborc.json.

Parser fixes

Not options, these are just cases that failed to parse:

  • Keyword shaped member names and struct keys: _d.mod, _b.data.mod, { static: 1, mod: 2, div: 3 }.
  • #region sitting between the branches of an if/else chain. Common in libraries.
  • A region's span now starts at the directive, so a comment in front of it is not pulled in.
  • An unterminated /* at end of file, which GameMaker reads as comment to EOF.

Layout

  • braceStyle gains NewLineIndented for a brace indented with its body.
  • elseOnNewLine puts else, catch and finally on their own line, to support the IDE's code editor.
  • stackedConditions splits a condition already broken across lines into one operand per line, operator leading, each operand parenthesized. Refuses when an operand is itself an unparenthesized &&/|| chain, since GM leaves that grouping platform dependent. A chain that fits on one line stays on one line.
  • braceSwitchCases braces a case once it holds more than one statement, not counting a trailing break, so the IDE can collapse it. Shorter cases stay on the case label's line.
  • inlineShortBlocks keeps a body written on the keyword's line there and adds the braces, so if a return true becomes if (a) { return true; }. It does not pull a multi line body up, and it pushes one back down if the line runs past width.
  • preserveGluedStatements leaves var _i = 0; repeat (_n) { \n...\n _i++} as written, never creates new ones. (this is just something i do a lot and needed it myself, could be removed.)
  • for headers are always printed flat. GameMaker has trouble compiling a wrapped one, hit it in GMLive and could not work out why specifically. GM will likely need a unit test for this if its discovered why. One occurrence in an 8k file repo, so reverting it is not a major issue.

Naming

  • prefixLocalVariables renames var x to var _x. It leaves a name alone when _x already exists, when a nested function declares the same name, and when the name is used as a shorthand struct key like { value }. The nested function case is future proofing for if/when GM gets closures. These could probably be allowed but that is more of the core gobo ast than i am comfortable editing.
  • prefixStaticVariables does the same for statics with __. Statics holding a function are skipped, since other files call them by name. Off by default, because namespace like functions are moderately common: function namespace(){ static Foo = "Bar" } \n namespace()

There was consideration to handle enums e_, and globals g_ but both of those are consistently cross file and not worth the trouble when the IDE natively supports refactor.

Comments and jsDoc

  • spaceAfterCommentMarker puts a space after the slashes.
  • wrapComments breaks comments running past width, respecting indent and
    jsDoc hanging columns as well as descriptions.
  • normalizeJsDocTags maps @desc to @description, {int} to {Real}, etc. Mostly because rumors suggest deprecations are coming, to keep these inline with real jsdoc better.
  • sortJsDocTags orders jsdocs into a standard order to, mostly to keep @self in a standardized place.
  • alignJsDocDescriptions lines up doc descriptions.
  • wrapJsDocInRegion wraps a docs comment in #region jsDoc so the IDE can collapse it. Another one for personal use, but there is an existing feature request for this.
  • addSelfToMethods adds @self naming the enclosing constructor, these are not explicitly required by jsdocs, feather, or gm, its only here to encourage consistency.
  • generateMissingJsDoc writes a skeleton above an undocumented function. Again here for consistency, a find all helps to know what you havent documented.
  • removeCommentedOutCode deletes comments that parse as code.

Rewrites

  • removeArrayCopyAccessor turns a[@ i] into a[i]. Off by default: it is only safe with the Copy on Write game option disabled, where the accessor does nothing. technically this one could also just simply be a find and replace all [@ though that captures strings.

Implementation notes

The naming and comment options run as passes over the syntax tree, so formatting runs twice. once to settle braces and indentation, then again over the result because the second pass needs braced code, otherwise a #region can land as the body of a braceless if. Also partially to do with libraries which place #regions between multiple if/else chains.

Comments come from the parser's trivia, not a standalone lexer pass. The lexer alone desyncs on template strings, because the parser is what drives its modes.

Tested against a 8k file repo: no parse errors, other then the one workaround mentioned before with GMLive, which is resolved as a hot fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant