Skip to content

Formatter counts lines from lexer tokens #16755

@straight-shoota

Description

@straight-shoota

When formatting some specific source code, the formatter produces an invalid result that doesn't parse anymore.

crystal tool format with Crystal 1.19.1 produces this invalid diff:

@@ -102,8 +101,8 @@ abstract class Admiral::Command
       type = command.is_a?(TypeDeclaration) ? command.type : type

       SubCommands::SPECS[name] = {
-        type:        type,
-        description: {
+        type: type,
+        descri       ption: {
           name + (short ? ", #{short.id}" : ""),
           description,
         },

I noticed the failure while formatting jwaldrip/admiral.cr@211937b in crystal-lang/test-ecosystem#89

The reproduction is not very concise because it requires certain line number arrangement to trigger the error. It can probably be minimized further.

Reproduction

abstract class Admiral::Command
  private macro inherited
    private struct SubCommands
      SPECS = {} of String => NamedTuple(
      )

      def self.locate(name)
        new(name.to_s).locate
      end

      def self.invoke(name, *args, **params)
        new(name).invoke(*args, **params)
      end

      def initialize(name : ::Admiral::StringValue)
        initialize name.value
      end

      def initialize(@name : String)
      end

      def invoke(*args, **params)
        if sub_command_class = locate
          sub_command_class.run(*args, **params, program_name: @name)
        else
          raise ::Admiral::Error.new("Invalid subcommand: #{@name}.")
        end
      end
    end

    def sub(command, *args, **params)
      SubCommands.invoke(command, *args, **params, parent: self)
    end
  end

    {%
      SubCommands::SPECS[name] = {
        type:        type,
        description: 1,
        short: short,
      }
    %}
end

It looks like some AST nodes have incorrect locations which then throws off the formatter when it aligns the values in the named tuple literal. The alignment processing runs after the actual code is generated and is informed by the reported line numbers.

I noticed a similar issue while implementing #16748 where it was related to skip_space_or_newline.


Add a 👍 reaction to issues you find important.

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind:bugA bug in the code. Does not apply to documentation, specs, etc.topic:tools:formatter

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions