Giter Site home page Giter Site logo

johnnymorganz / stylua Goto Github PK

View Code? Open in Web Editor NEW
1.4K 14.0 61.0 2.33 MB

An opinionated Lua code formatter

License: Mozilla Public License 2.0

Rust 80.73% Lua 14.28% TypeScript 4.01% Shell 0.07% JavaScript 0.89% Dockerfile 0.03%
lua formatter pretty-printer printer luau stylua luaformatter hacktoberfest

stylua's Issues

unexpected token `:`

With this code in a file:

function serializeInt(outputValue): number
end

I get this error:

error: could not format file scalars.lua: error parsing: error occurred while creating ast: unexpected token `:`. (starting from line 28, character 35 and ending on line 28, character 36)
additional information: expected 'end'

Indentation level of multiline-if 'then' does not respect the expanded function calls it is nested within

The indentation level of 'then' in multi-line if statements appears to decrease by one for every expanded function call it's nested in.

baz(
	first_arg___ooooooooooooooooooooooooooooooooooooooooooo,
	second_arg___qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq,

	function()
		if
			multiline_if___aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
			and multiline_if___bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
	then
			biz()
		end
	end
)
biz(
	first_arg___aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
	second_arg___bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,

	baz(
		first_arg___ooooooooooooooooooooooooooooooooooooooooooo,
		second_arg___qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq,

		function()
			if
				multiline_if___aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
				and multiline_if___bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
	then
				biz()
			end
		end
	)
)

This exact problem does not appear to exist for expanded expressions that aren't function calls:

local result = first_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
	and (function()
	if
		multiline_if___aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
		and multiline_if___bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
	then

	end

	return second
end)()

Break up long if statement conditions

if someReallyLongCondition and someOtherReallyLongCondition and somethingElse then
    doSomething()
    doSomethingElse()
end

... should be formatted as ...

if
    someReallyLongCondition
    and someOtherReallyLongCondition
    and somethingElse
then
    doSomething()
    doSomethingElse()
end

Configuration files need to be complete

I had a stylua.toml with:

line_endings = "Windows"

...and got the following error: config file not in correct format: missing field indent_type at line 1 column 1

Table types in Luau do not correctly move onto new lines

type PromptSettings = {
    object: string,
    action: string,
    holdDuration: number,
    keyboardKey: KeyCode,
    gamepadKey: KeyCode,
    distance: number,
    lineOfSight: boolean,
    offset: Vector2,
}

... should be kept the same, but it is reformatted as ...

type PromptSettings = { object: string, action: string, holdDuration: number, keyboardKey: KeyCode, gamepadKey: KeyCode, distance: number, lineOfSight: boolean, offset: Vector2,  }

Single Multi-line if Statement

StyLua uses multi-line if statement formatting even when the expression will only be put on a single line:

if
	not (one and two and three and four and five and six and seven and eight and nine and ten and eleven and twelve and thirteen and fourteen and fifteen and sixteen)
then

end

In this case, I might expect it to remain on one line or be broken up (with a higher indentation).

Moving code onto one line with comment breaks code

Before running StyLua:

local foo_result = foo( --a comment
	"oof"
)

local expr_result = 1 + 2 + 3 + 4 + 5 --a comment
	+ 6 + 6 + 8

After running StyLua:

local foo_result = foo( --a comment"oof")

local expr_result = 1 + 2 + 3 + 4 + 5 --a comment + 6 + 6 + 8

if... then ... else statements not aligned when wrapped and indented

Input

local myObj = {
	myProp = function(reallyLongVariableNameEatsUpSpace)
		if
			reallyLongVariableNameEatsUpSpace == "foo"
			or reallyLongVariableNameEatsUpSpace == "bar"
			or reallyLongVariableNameEatsUpSpace == "baz"
		then
			return "hello"
		end
	end,
}

Output

local myObj = {
	myProp = function(reallyLongVariableNameEatsUpSpace)
		if
			reallyLongVariableNameEatsUpSpace == "foo"
			or reallyLongVariableNameEatsUpSpace == "bar"
			or reallyLongVariableNameEatsUpSpace == "baz"
	then
			return "hello"
		end
	end,
}

Expected Behavior

The then statement should be aligned with the corresponding if ... end blocks

- 	then
+ 		then

PS: This project is amazing and solving so many issues - hope my edge case detection / bug reporting is helpful, but very grateful to have 95%+ of our formatting auto solved.

Indentation of function block within expanded expression is too low

Function blocks within expanded expressions seem to base their indentation on that of the line on which the expression begins.

local expr = first_______________________________________________________________________________________________________
	and function()
	foo()
end

Both my text editor (VS Code) and I expect the indentation to be based on the line where the function block begins:

local expr = first_______________________________________________________________________________________________________
	and function()
		foo()
	end

I say VS Code expects this because that's the indentation level it gives me when I enter onto a new line, starting from the end of function()

Repeat until loops aligns the until line to the left

Currently, repeat ... until ... loops are left aligned to the entire document, which should not happen & should align with the repeat line.

Test code:

local function Foo(bar)
	local count = 0

	repeat
		count += 1
	until count == 10
end

Foo('thing')

Format this and the following is generated:

local function Foo(bar)
	local count = 0

	repeat
		count += 1
until count == 10
end

Foo("thing")

Incorrectly expands function call containing comments

With the recent update, a function call containing comments now becomes expanded, when we do not want it to be

For example:

local App = Roact.createElement("Frame", {
	Size = UDim2.fromScale(0.5, 0), -- comment
	foo = bar,
}, {
	foo = bar
})

should remain the same, however it is incorrectly formatted as

local App = Roact.createElement(
	"Frame",
	{
		Size = UDim2.fromScale(0.5, 0), -- comment
		foo = bar,
	},
	{
		foo = bar,
	}
)

EDIT: This seems to actually be a regression from v0.2.1 -> v0.3.0

unexpected token `type`

On current main (hash d870087), in a file where I have

type Array<T> = { [number]: T }

I get this error:

error: could not format file definition.lua: error parsing: error occurred while creating ast: unexpected token `type`. (starting from line 30, character 1 and ending on line 31, character 5)
additional information: leftover token

It would be nice if it would skip that AST parent node and proceed, rather than erroring.

Formatting removing required semicolons

In code such as the following, it removes the required semicolon, which breaks the code.

function PlayerPromise.PromiseUserIdFromName(Username: string)
	return Promise.Defer(function(Resolve, Reject)
		local Success, Value = pcall(Players.GetUserIdFromNameAsync, Players, Username);
		(Success and Resolve or Reject)(Value)
	end)
end

image

Situations where StyLua should/shouldn't wrap onto new lines

Below is an example where I'm not entirely sure if it should be wrapped or not:

error(
    "Owner `" .. tostring(owner) .. "` already has a pawn. Try deleting their currently owned pawn."
)

This needs to be thought about and then determined on what to do

Comments at the end of line continuations

Input:

if code == 9 -- \t
or code == 32 -- <space>
   then
    print(code)
end

Output:

if code == 9 -- \t or code == 32 -- <space> then
	print(code)
end

Expected (combine code and comments serially):

if code == 9 or code == 32 then -- \t  -- <space> 
	print(code)
end

Expected (do nothing if removing new line will place executing code inside a comment):

if code == 9 -- \t
or code == 32 -- <space>
   then
    print(code)
end

(same as input)

or do nothing if removing a newline is going to

Allow use of an ignore file

It would be really useful to have a file similar to a .prettierignore (something like .styluaignore possibly) that allows coordination of which files to format without having to pass options to command line every time. This would allow much easier adoption in git projects that are already familiar with this style of collaboration coordination.

Code getting commented out on new lines

Code can get commented out and ruin the file.

Original:

-- Stop Movement
if
	-- Moved for at least 0.1 seconds
	((tick() - Player.PlayerDataLocal.IsRunningTimeStamp.Value) > 0.1) and     -- Speed is less than threshold
	(Utility.Vec3XZLengthSquared(Player.Character.PrimaryPart.Velocity) <= RunThresholdSpeedSqr)
then --0.01
	Player.PlayerDataLocal.IsRunning.Value = false
end

Formatted:

-- Stop Movement
if
-- Moved for at least 0.1 seconds
	((tick() - Player.PlayerDataLocal.IsRunningTimeStamp.Value) > 0.1)
	and  -- Speed is less than threshold(Utility.Vec3XZLengthSquared(Player.Character.PrimaryPart.Velocity) <= RunThresholdSpeedSqr)
then --0.01
	Player.PlayerDataLocal.IsRunning.Value = false
end

Use column width as a bigger indicator when to split lines

Currently, the formatted chooses to split lines by determining the number of bytes between the contained span braces (for TableConstructor and FunctionArgs).
This isn't great, as it doesn't take into account the current column width (e.g. if we are a few indents deep)

Column width should be used as the deciding factor about when to introduce line breaks (need to find a way to calculate this as the formatters currently "don't know about their surroundings")

Indentation Level of 'then

I'm closing this and reopening with a better title. This issue was unintentionally posted before being completed.

List indentation shifts to the left on the first & last values

The current behavior of formatting a large list that spans multiple lines will put the top and bottom values of a table on the complete left side of the document.

Test code:

local Suffixes = {"k", "M", "B", "T", "qd", "Qn", "sx", "Sp", "O", "N", "de", "Ud", "DD", "tdD", "qdD", "QnD",
	"sxD", "SpD", "OcD", "NvD", "Vgn", "UVg", "DVg", "TVg", "qtV", "QnV", "SeV", "SPG", "OVG",
	"NVG", "TGN", "UTG", "DTG", "tsTG", "qtTG", "QnTG", "ssTG", "SpTG", "OcTG", "NoTG", "QdDR",
	"uQDR", "dQDR", "tQDR", "qdQDR", "QnQDR", "sxQDR", "SpQDR", "OQDDr", "NQDDr", "qQGNT", "uQGNT",
	"dQGNT", "tQGNT", "qdQGNT", "QnQGNT", "sxQGNT", "SpQGNT", "OQQGNT", "NQQGNT", "SXGNTL"}

Incorrect type formatting for anonymous functions in Luau

local Object = {ClassName = "Object"}
Object.__tostring = function(self): string
    return self.ClassName
end

... is output as ...

local Object = { ClassName = "Object" }
Object.__tostring = function(self)
: string	return self.ClassName
end

Eager Wrapping with Comments

This input gets wrapped eagerly.

last = last or #array -- If last isn't provided, go to the end

Becoming this, due to the comment.

last = last
	or #array -- If last isn't provided, go to the end

However, this remains unchanged.

last = last or #array

Configuration for quote style of strings

Quote style (single quote vs double quote) for strings is a hot topic, including what to do with escapes, consistency etc.
I was wondering whether we should introduce configuration for this specific point.

There would have to be two parts to this:

  1. quote style (single quote or double quote), and
  2. forcing quote style - should we force the chosen quotes regardless of whether we could reduce the number of escapes in the string or not? There are arguments for this (consistency with all strings in codebase) and against (reduce number of escapes necessary, making string easier to read).

So, there are two questions to answer here: 1) should we add this configuration option? and 2) what should be our default? [currently our default is double quote - which will remain so - and forcing regardless of escapes - which I'm not sure which is better]

Allow checking that files are already formatted

This would be similar to prettier --check (prettier also uses prettier --write when formatting the files to distinguish) and would allow quick checks that the project is already compliant with the formatting created by StyLua. This can help with CI checks to ensure everyone is using StyLua in their contributions easily.

Hang expressions within a function call if necessary

There are situations where codebases have strings concatenated together so that they can push them onto multiple lines, to improve the readability.
For example:

local longString = foo(
     "We are wrapping this %s "
    .. "onto multiple lines "
    .. "for ease of editing and %d readability", 
    myStringVar, 
    myNumberVar
)

We should keep them expanded if that is the case (with the similar logic as to what we do with already expanded tables)

Double quotes preceded by escaped backslash

Input:

local str = '\\"""'

Output:

local str = "\\"\"\""

Expected:

local str = "\\\"\"\""

Preserve the escape on the \ character and then escape the first double quote since the string has been converted to double quotes. It would be nice if strings were formatted to avoidEscapes, but for simplicity - forcing into double quotes seems fine too.

Maintain `do` block formatting

do blocks get moved down from their original starting line, which should not occur if it causes no issues.

What I wrote:

local thing = {} do
	thing.__index = thing

	function thing.new()
		return setmetatable({ key = "hi" }, thing)
	end

	function thing:method()
		print(self.key)
	end
end

What's formatted:

local thing = {}
do
	thing.__index = thing

	function thing.new()
		return setmetatable({ key = "hi" }, thing)
	end

	function thing:method()
		print(self.key)
	end
end

The do should not move below the line.

Attempting to match globs finds no files

Using the example in the readme for avoiding matching .spec.lua files or modified ones like stylua -g **/*.lua -g !**/*.spec.lua . just returns error: no files provided. Ideally this should match against regular .lua files that are discoverable in the path given.

This seems to be related to the glob option matching multiple patterns following it and the path to run on being treated as a glob. stylua -g **/*.lua . has this problem, but stylua -g **/*.lua --check . does not.

Luau 'type' keyword isn't supported

Any file I have that includes any mention of the type keyword cannot be formatted.
Small example:

type Array<T> = { [number]: T }
type Set<T> = { [T]: boolean }

I would be fine if this part of the AST was transferred without any attempts at formatting :)

Remove excess parentheses

Stylua should remove excess parentheses where it is safe to do so.

local x
something((x))

should become:

local x
something(x)

However, it's not always safe to remove parentheses. Inside of binary operator expressions, parentheses can denote precedence, so these parentheses should not be removed:

local x = (1 + 2) * 3

Additionally, parentheses can cull extra values returned from a multiple return:

function x()
  return 1, 2
end

print(x()) --> 1, 2
print((x())) --> 1

In this example above, removing the parentheses in the expression (x()) is unsafe, because it changes how the code runs.

In cases like this, Stylua should still compress down to one set: print(((x()))) should become print((x())).

Preserve Comments

Comments are treated as trivia and are not preserved in the format

VSCode: Format selection command

A Format Selection with Stylua command would make it easier to format small parts of a file. This is useful when you are working on a large file, and only want your new changes to be affected by the formatting.

Wrap comments when they excede a certain line length

Comments should ideally be wrapped at a certain line length to maintain readability. Roblox's style guide suggests 80, which is what I use, but I've also seen people use 120 or any random number.

This should ideally apply only to comments that on on lines by themselves (blah() --todo foobar shouldn't be formatted) and wrap at word boundaries (which can be accomplished with a basic regex pattern). To avoid styling the comment or ruining LDoc, it should maintain any trivia at the beginning of the comment (e.g. preserve --- and -- ).

VS Code extension doesn't respect .styluaignore

When adding a directory to ignore then formatting a file in that directory it will apply the formatting to it. I would guess due to not checking the directory opened in VS Code to check for a .styluaignore file.

Preserve trailing comments in multiline tables

Currently, if you have a comment at the end of an entry in a table with a comma:

local foo = {
    foo = bar, -- this is a comment
    bar = baz
}

... it isn't preserved.

In addition, if you have do not have a trailing comma, and have a comment ...

local foo = {
    foo = bar,
    bar = baz -- comment
}

... StyLua incorrectly places the comma ...

local foo = {
    foo = bar,
    bar = baz -- comment,
}

Could not format file: thread 'main' has overflowed its stack

We have an unusual edge case which returns the error:

Could not format file: thread 'main' has overflowed its stack

The following block of code fails when including the last expression in the if statement

if
	code == 65
	or code == 66
	or code == 67
	or code == 68
	or code == 69
	or code == 70
	or code == 71
	or code == 72
	or code == 73
	or code == 74
	or code == 75
	or code == 76
	or code == 77
	or code == 78
	or code == 79
	or code == 80
	or code == 81
	or code == 82
	or code == 83
	or code == 84
	or code == 85
	or code == 86
	or code == 87
	or code == 88
	or code == 89
	or code == 90
	or code == 95
	or code == 97
	or code == 98
	or code == 99
	or code == 100
	or code == 101
	or code == 102
	or code == 103
	or code == 104
	or code == 105
	or code == 106
	or code == 107
	or code == 108
	or code == 109
	or code == 110
	or code == 111
	or code == 112
	or code == 113
	or code == 114
	or code == 115
				or code == 116
then
	print("hi")

end

It's definitely a strange edge case, and there are ways to rewrite the code to avoid this, but we have some constraints that prevent excessive rewrites.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.