diff --git a/CHANGELOG.md b/CHANGELOG.md index 11c01613..8ddfd4c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,17 @@ - Added haxe-test-adapter [#286](https://github.com/HaxeCheckstyle/haxe-formatter/issues/286) + [#287](https://github.com/HaxeCheckstyle/haxe-formatter/issues/287) + [#289](https://github.com/HaxeCheckstyle/haxe-formatter/issues/289) - Added `wrapping.implementsExtends` [#288](https://github.com/HaxeCheckstyle/haxe-formatter/issues/288) - Added `emptylines.afterFileHeaderComment`and `emptylines.betweenMultilineComments` fixes [#292](https://github.com/HaxeCheckstyle/haxe-formatter/issues/292) ([#296](https://github.com/HaxeCheckstyle/haxe-formatter/issues/296)) +- Added wrapping location to allow wrapping before delimiting token, fixes [#299](https://github.com/HaxeCheckstyle/haxe-formatter/issues/299) () - Fixed whitespace of type check in array comprehension, fixes [#284](https://github.com/HaxeCheckstyle/haxe-formatter/issues/284) ([#285](https://github.com/HaxeCheckstyle/haxe-formatter/issues/285)) - Fixed conditional modifier handling, fixes [#291](https://github.com/HaxeCheckstyle/haxe-formatter/issues/291) ([#293](https://github.com/HaxeCheckstyle/haxe-formatter/issues/293)) - Fixed whitespace after left curly in anon type hints [#297](https://github.com/HaxeCheckstyle/haxe-formatter/issues/297) +- Fixed anon types handling when `leftCurly` is set to `both`, fixes [#301](https://github.com/HaxeCheckstyle/haxe-formatter/issues/301) () +- Fixed same line handling of `expressionIf`, fixes [#304](https://github.com/HaxeCheckstyle/haxe-formatter/issues/304) () +- Fixed indentation of object literals, fixes [#305](https://github.com/HaxeCheckstyle/haxe-formatter/issues/305) () +- Fixed same line handling of cases with object pattern, fixes [#306](https://github.com/HaxeCheckstyle/haxe-formatter/issues/306) () +- Fixed empty line after metadata with function, fixes [#307](https://github.com/HaxeCheckstyle/haxe-formatter/issues/307) () +- Fixed missing space before `(`, fixes [#308](https://github.com/HaxeCheckstyle/haxe-formatter/issues/308) () +- Removed stacktrace from output with invalid `hxformat.json` files, fixes [#300](https://github.com/HaxeCheckstyle/haxe-formatter/issues/300) () ## version 1.3.0 (2018-12-05) diff --git a/buildCommon.hxml b/buildCommon.hxml index 5614b561..e49940de 100644 --- a/buildCommon.hxml +++ b/buildCommon.hxml @@ -4,7 +4,9 @@ -lib json2object -lib hxargs -lib compiletime +-lib safety -cp src -main formatter.Cli +# --macro nullSafety('formatter') diff --git a/buildSchema.hxml b/buildSchema.hxml index 2adb1f84..0d1ca2a1 100644 --- a/buildSchema.hxml +++ b/buildSchema.hxml @@ -3,6 +3,7 @@ -lib hxparse -lib json2object -lib hxargs +-lib safety -cp src -cp schema diff --git a/buildTest.hxml b/buildTest.hxml index 0e25c3ba..f8fa0389 100644 --- a/buildTest.hxml +++ b/buildTest.hxml @@ -9,6 +9,7 @@ -lib mcover -lib munit -lib compiletime +-lib safety -lib haxe-test-adapter # -D debugLog diff --git a/display.hxml b/display.hxml index b756c258..aa4a2efb 100644 --- a/display.hxml +++ b/display.hxml @@ -10,4 +10,5 @@ -lib mcover -lib munit -lib compiletime +-lib safety -lib haxe-test-adapter diff --git a/resources/formatter-schema.json b/resources/formatter-schema.json index 36c7bad2..4bdf3542 100644 --- a/resources/formatter-schema.json +++ b/resources/formatter-schema.json @@ -104,7 +104,7 @@ "propertyOrder": 1 }, "conditionalPolicy": { - "description": "only applies to non inlined conditionals\n\t\t\"fixedZero\" = all conditional statements should start in column 1\n\t\t\"aligned\" = conditional statements share indentation of surrounding code\n\t\t\"alignedIncrease\" = same as \"aligned\" but will increase indent by +1 for enclosed code", + "description": "only applies to non inlined conditionals\n\t\t\"fixedZero\" = all conditional statements should start in column 1\n\t\t\"aligned\" = conditional statements share indentation of surrounding code\n\t\t\"alignedIncrease\" = same as \"aligned\" but will increase indent by +1 for enclosed code\n\t\t\"alignedDecrease\" = same as \"aligned\" but will decrease indent by -1 for enclosed code", "type": "string", "enum": [ "fixedZero", @@ -143,10 +143,19 @@ ], "propertyOrder": 1 }, + "defaultLocation": { + "description": "default wrapping location before / after last token", + "type": "string", + "enum": [ + "beforeLast", + "afterLast" + ], + "propertyOrder": 2 + }, "defaultAdditionalIndent": { "description": "adds indentation to all wrapped lines when applying defaultWrap", "type": "integer", - "propertyOrder": 2 + "propertyOrder": 3 }, "rules": { "description": "list of wrapping rules\n\t\twrapping uses only the first rule whose conditions evaluates to true", @@ -369,6 +378,15 @@ "additionalIndent": { "description": "adds indentation to all wrapped lines", "type": "integer", + "propertyOrder": 3 + }, + "location": { + "description": "default wrapping location before / after last token", + "type": "string", + "enum": [ + "beforeLast", + "afterLast" + ], "propertyOrder": 2 }, "type": { diff --git a/schema/import.hx b/schema/import.hx new file mode 100644 index 00000000..bd1c8326 --- /dev/null +++ b/schema/import.hx @@ -0,0 +1 @@ +using Safety; diff --git a/src/formatter/Cli.hx b/src/formatter/Cli.hx index f50131a6..bfce06f9 100644 --- a/src/formatter/Cli.hx +++ b/src/formatter/Cli.hx @@ -33,7 +33,9 @@ class Cli { #end if (Sys.getEnv("HAXELIB_RUN") == "1") { - Sys.setCwd(args.pop()); + if (args.length > 0) { + Sys.setCwd(args.pop().unsafe()); + } } var paths = []; @@ -167,7 +169,7 @@ class Cli { } case Failure(errorMessage): FormatStats.incFailed(); - Sys.stderr().writeString('Failed to format $path: $errorMessage'); + Sys.stderr().writeString('Failed to format $path: $errorMessage\n'); exitCode = 1; case Disabled: FormatStats.incDisabled(); diff --git a/src/formatter/Formatter.hx b/src/formatter/Formatter.hx index 67b7272d..5e77abe0 100644 --- a/src/formatter/Formatter.hx +++ b/src/formatter/Formatter.hx @@ -31,8 +31,12 @@ class Formatter { var config:Config = loadConfig(file.name); return formatFileWithConfig(file, config, tokenData); } catch (e:Any) { + #if debug var callstack = CallStack.toString(CallStack.exceptionStack()); return Failure(e + "\n" + callstack + "\n\n"); + #else + return Failure(e); + #end } } @@ -66,7 +70,7 @@ class Formatter { markWrapping.run(); markEmptyLines.run(); - markTokenText.finalRun(null); + markTokenText.finalRun(); var lines:CodeLines = new CodeLines(parsedCode, indenter); lines.applyWrapping(config.wrapping); @@ -83,7 +87,7 @@ class Formatter { function loadConfig(fileName:String):Config { var config:Config = new Config(); - var configFileName:String = determineFormatterConfig(fileName); + var configFileName:Null = determineFormatterConfig(fileName); if (configFileName == null) { return config; } diff --git a/src/formatter/codedata/CodeLine.hx b/src/formatter/codedata/CodeLine.hx index 5aa6db08..be556431 100644 --- a/src/formatter/codedata/CodeLine.hx +++ b/src/formatter/codedata/CodeLine.hx @@ -5,7 +5,7 @@ import formatter.marker.Indenter; class CodeLine { var parts:Array; - var currentPart:CodePart; + var currentPart:Null; public var indent:Int; public var emptyLinesAfter:Int; @@ -31,7 +31,7 @@ class CodeLine { firstLineLength: -1, lastLineLength: -1 }; - parts.push(currentPart); + parts.push(currentPart.unsafe()); } currentPart.lastToken = tokenInfo.token; if ((tokenInfo.whitespaceAfter == Space) && (tokenInfo.spacesAfter > 0)) { diff --git a/src/formatter/codedata/CodeLines.hx b/src/formatter/codedata/CodeLines.hx index 99e380fe..71edbc3f 100644 --- a/src/formatter/codedata/CodeLines.hx +++ b/src/formatter/codedata/CodeLines.hx @@ -20,7 +20,7 @@ class CodeLines { } function buildLines() { - var line:CodeLine = null; + var line:Null = null; var index:Int = 0; while (index < parsedCode.tokenList.tokens.length) { var tokenInfo:TokenInfo = parsedCode.tokenList.getTokenAt(index); diff --git a/src/formatter/codedata/TokenList.hx b/src/formatter/codedata/TokenList.hx index ac23981c..7d0f1186 100644 --- a/src/formatter/codedata/TokenList.hx +++ b/src/formatter/codedata/TokenList.hx @@ -11,7 +11,7 @@ import formatter.config.Config; class TokenList { static inline var NEWLINE_TO_SPACE:String = "Newline -> Space"; - public var tokens:Array; + public var tokens:Array>; public var leadingEmptyLInes:Int; public function new() { @@ -54,7 +54,7 @@ class TokenList { } } - public function getTokenAt(index:Int):TokenInfo { + public function getTokenAt(index:Int):Null { if (tokens.length <= index) { return null; } @@ -64,11 +64,11 @@ class TokenList { return tokens[index]; } - public function getPreviousToken(token:TokenTree):TokenInfo { + public function getPreviousToken(token:TokenTree):Null { if ((token == null) || (token.index <= 0)) { return null; } - var prevToken:TokenInfo = null; + var prevToken:Null = null; var prevIndex:Int = token.index - 1; if (prevIndex >= tokens.length) { return null; @@ -82,11 +82,11 @@ class TokenList { return prevToken; } - public function getNextToken(token:TokenTree):TokenInfo { + public function getNextToken(token:TokenTree):Null { if ((token == null) || (token.index <= 0)) { return null; } - var nextToken:TokenInfo = null; + var nextToken:Null = null; var nextIndex:Int = token.index + 1; if (nextIndex >= tokens.length) { return null; @@ -104,11 +104,11 @@ class TokenList { if (token.index < 0) { return; } - var info:TokenInfo = tokens[token.index]; + var info:Null = tokens[token.index]; if (info == null) { return; } - var prev:TokenInfo = null; + var prev:Null = null; var prevIndex:Int = token.index - 1; while (prev == null) { if (prevIndex < 0) { @@ -146,7 +146,7 @@ class TokenList { } } - function applyWhitespace(info:TokenInfo, policy:WhitespaceAfterType, ?pos:PosInfos) { + function applyWhitespace(info:Null, policy:WhitespaceAfterType, ?pos:PosInfos) { if (info == null) { return; } @@ -206,7 +206,7 @@ class TokenList { if (token.index < 0) { return; } - var info:TokenInfo = tokens[token.index]; + var info:Null = tokens[token.index]; if (info == null) { return; } @@ -223,7 +223,7 @@ class TokenList { } public function spacesBefore(token:TokenTree, count:Int, ?pos:PosInfos) { - var info:TokenInfo = getPreviousToken(token); + var info:Null = getPreviousToken(token); if (info == null) { return; } @@ -243,7 +243,7 @@ class TokenList { if (token.index < 0) { return; } - var info:TokenInfo = tokens[token.index]; + var info:Null = tokens[token.index]; if (info == null) { return; } @@ -264,7 +264,7 @@ class TokenList { } public function lineEndBefore(token:TokenTree, ?pos:PosInfos) { - var info:TokenInfo = getPreviousToken(token); + var info:Null = getPreviousToken(token); if (info == null) { return; } @@ -299,7 +299,7 @@ class TokenList { if (token.index < 0) { return; } - var info:TokenInfo = tokens[token.index]; + var info:Null = tokens[token.index]; if (info == null) { return; } @@ -328,7 +328,7 @@ class TokenList { } public function noLineEndBefore(token:TokenTree, ?pos:PosInfos) { - var info:TokenInfo = getPreviousToken(token); + var info:Null = getPreviousToken(token); if (info == null) { return; } @@ -360,7 +360,7 @@ class TokenList { if (token.index < 0) { return; } - var info:TokenInfo = tokens[token.index]; + var info:Null = tokens[token.index]; if (info == null) { return; } @@ -378,7 +378,7 @@ class TokenList { leadingEmptyLInes = count; return; } - var info:TokenInfo = getPreviousToken(token); + var info:Null = getPreviousToken(token); if (info == null) { return; } @@ -393,7 +393,7 @@ class TokenList { if (lastToken == null) { return; } - var info:TokenInfo = tokens[lastToken.index]; + var info:Null = tokens[lastToken.index]; if (info == null) { return; } @@ -407,7 +407,7 @@ class TokenList { if (token.index < 0) { return; } - var info:TokenInfo = tokens[token.index]; + var info:Null = tokens[token.index]; if (info == null) { return; } @@ -418,7 +418,7 @@ class TokenList { if (token.index < 0) { return; } - var info:TokenInfo = tokens[token.index]; + var info:Null = tokens[token.index]; if (info == null) { return; } @@ -429,7 +429,7 @@ class TokenList { } public function wrapBefore(token:TokenTree, wrap:Bool, ?pos:PosInfos) { - var prev:TokenInfo = getPreviousToken(token); + var prev:Null = getPreviousToken(token); if (prev == null) { return; } @@ -446,8 +446,8 @@ class TokenList { var index = tokenStart.index; while (index < tokenEnd.index) { var first:Bool = index == tokenStart.index; - var info:TokenInfo = tokens[index++]; - var next:TokenInfo = tokens[index]; + var info:Null = tokens[index++]; + var next:Null = tokens[index]; if (info == null) { continue; } @@ -533,7 +533,7 @@ class TokenList { if (token.index < 0) { return; } - var info:TokenInfo = tokens[token.index]; + var info:Null = tokens[token.index]; if (info == null) { return; } @@ -543,8 +543,8 @@ class TokenList { info.additionalIndent = indent; } - public function findTokenAtOffset(offset:Int):TokenInfo { - var lastInfo:TokenInfo = null; + public function findTokenAtOffset(offset:Int):Null { + var lastInfo:Null = null; for (info in tokens) { if (info == null) { @@ -573,7 +573,7 @@ class TokenList { endIndex = first.index; } while (startIndex < endIndex) { - var currTok:TokenInfo = tokens[startIndex++]; + var currTok:Null = tokens[startIndex++]; if (currTok == null) { continue; } @@ -591,7 +591,7 @@ class TokenList { if (token.index < 0) { return 0; } - var current:TokenInfo = tokens[token.index]; + var current:Null = tokens[token.index]; if (current == null) { return 0; } @@ -619,7 +619,7 @@ class TokenList { if (token.index < 0) { return 0; } - var current:TokenInfo = tokens[token.index]; + var current:Null = tokens[token.index]; if (current == null) { return 0; } @@ -638,7 +638,7 @@ class TokenList { return length; } for (child in token.children) { - var current:TokenInfo = tokens[child.index]; + var current:Null = tokens[child.index]; if ((current != null) && (current.whitespaceAfter == Newline)) { break; } @@ -656,7 +656,7 @@ class TokenList { } var length:Int = 0; for (index in tokenStart.index...tokenEnd.index) { - var current:TokenInfo = tokens[index]; + var current:Null = tokens[index]; if (current == null) { continue; } @@ -683,7 +683,7 @@ class TokenList { if (start < 0) { break; } - var info:TokenInfo = tokens[start--]; + var info:Null = tokens[start--]; if (info == null) { continue; } @@ -697,7 +697,7 @@ class TokenList { if (start >= tokens.length) { break; } - var info:TokenInfo = tokens[start++]; + var info:Null = tokens[start++]; if (info == null) { continue; } @@ -726,7 +726,7 @@ class TokenList { if (start < 0) { break; } - var info:TokenInfo = tokens[start--]; + var info:Null = tokens[start--]; if (info == null) { continue; } @@ -755,7 +755,7 @@ class TokenList { if (start >= tokens.length) { break; } - var info:TokenInfo = tokens[start++]; + var info:Null = tokens[start++]; if (info == null) { continue; } @@ -778,7 +778,7 @@ class TokenList { if (token.index < 0) { return 0; } - var info:TokenInfo = tokens[token.index]; + var info:Null = tokens[token.index]; if (info == null) { return 0; } @@ -793,7 +793,7 @@ class TokenList { } public function isNewLineBefore(token:TokenTree):Bool { - var info:TokenInfo = getPreviousToken(token); + var info:Null = getPreviousToken(token); if (info == null) { return false; } @@ -801,7 +801,7 @@ class TokenList { } public function isNewLineAfter(token:TokenTree):Bool { - var info:TokenInfo = getTokenAt(token.index); + var info:Null = getTokenAt(token.index); if (info == null) { return false; } @@ -818,7 +818,7 @@ class TokenList { start++; } for (index in start...end) { - var info:TokenInfo = tokens[index]; + var info:Null = tokens[index]; if (info == null) { continue; } diff --git a/src/formatter/config/Config.hx b/src/formatter/config/Config.hx index dc7f32ca..6a557e7d 100644 --- a/src/formatter/config/Config.hx +++ b/src/formatter/config/Config.hx @@ -28,25 +28,18 @@ class Config { } public function readConfigFromString(jsonContent:String, fileName:String) { - try { - var parser:JsonParser = new JsonParser(); - var data:FormatterConfig = parser.fromJson(jsonContent, fileName); - emptyLines = data.emptyLines; - indentation = data.indentation; - lineEnds = data.lineEnds; - sameLine = data.sameLine; - whitespace = data.whitespace; - wrapping = data.wrapping; - disableFormatting = data.disableFormatting; - excludes = []; - for (exclude in data.excludes) { - excludes.push(new EReg(exclude, "")); - } - } catch (e:Any) { - // disable formatting rather than using an incorrect format - disableFormatting = true; - trace(e); - Sys.println(CallStack.toString(CallStack.callStack())); + var parser:JsonParser = new JsonParser(); + var data:FormatterConfig = parser.fromJson(jsonContent, fileName); + emptyLines = data.emptyLines; + indentation = data.indentation; + lineEnds = data.lineEnds; + sameLine = data.sameLine; + whitespace = data.whitespace; + wrapping = data.wrapping; + disableFormatting = data.disableFormatting; + excludes = []; + for (exclude in data.excludes) { + excludes.push(new EReg(exclude, "")); } } diff --git a/src/formatter/config/IndentationConfig.hx b/src/formatter/config/IndentationConfig.hx index 5e4d40e0..527ab186 100644 --- a/src/formatter/config/IndentationConfig.hx +++ b/src/formatter/config/IndentationConfig.hx @@ -6,6 +6,7 @@ typedef IndentationConfig = { "fixedZero" = all conditional statements should start in column 1 "aligned" = conditional statements share indentation of surrounding code "alignedIncrease" = same as "aligned" but will increase indent by +1 for enclosed code + "alignedDecrease" = same as "aligned" but will decrease indent by -1 for enclosed code **/ @:default(Aligned) @:optional var conditionalPolicy:ConditionalIndentationPolicy; diff --git a/src/formatter/config/WrapConfig.hx b/src/formatter/config/WrapConfig.hx index 60bf5297..8917df1d 100644 --- a/src/formatter/config/WrapConfig.hx +++ b/src/formatter/config/WrapConfig.hx @@ -264,6 +264,11 @@ typedef WrapRules = { **/ @:default(NoWrap) @:optional var defaultWrap:WrappingType; + /** + default wrapping location before / after last token + **/ + @:default(AfterLast) @:optional var defaultLocation:WrappingLocation; + /** adds indentation to all wrapped lines when applying defaultWrap **/ @@ -282,6 +287,11 @@ typedef WrapRule = { **/ var type:WrappingType; + /** + default wrapping location before / after last token + **/ + @:default(AfterLast) @:optional var location:WrappingLocation; + /** adds indentation to all wrapped lines **/ @@ -298,6 +308,12 @@ abstract WrappingType(String) { var Keep = "keep"; } +@:enum +abstract WrappingLocation(String) { + var BeforeLast = "beforeLast"; + var AfterLast = "afterLast"; +} + typedef WrapCondition = { var cond:WrapConditionType; @:default(1) @:optional var value:Int; diff --git a/src/formatter/import.hx b/src/formatter/import.hx index c0f6e17e..5a73c5a8 100644 --- a/src/formatter/import.hx +++ b/src/formatter/import.hx @@ -10,6 +10,7 @@ import tokentree.utils.TokenTreeCheckUtils; import formatter.codedata.ParsedCode; import formatter.codedata.TokenInfo; +using Safety; using StringTools; using tokentree.TokenTreeAccessHelper; using formatter.config.WhitespacePolicy; diff --git a/src/formatter/marker/Indenter.hx b/src/formatter/marker/Indenter.hx index 7158bc67..9ff85831 100644 --- a/src/formatter/marker/Indenter.hx +++ b/src/formatter/marker/Indenter.hx @@ -9,7 +9,7 @@ import formatter.config.IndentationConfig; class Indenter { var config:IndentationConfig; - var parsedCode:ParsedCode; + var parsedCode:Null; public function new(config:IndentationConfig) { this.config = config; @@ -112,7 +112,7 @@ class Indenter { case PClose: return findEffectiveParent(token.parent); case Kwd(KwdIf): - var prev:TokenInfo = parsedCode.tokenList.getPreviousToken(token); + var prev:Null = parsedCode.tokenList.getPreviousToken(token); if (prev.whitespaceAfter == Newline) { return token; } @@ -150,7 +150,7 @@ class Indenter { default: } case CommentLine(_): - var next:TokenInfo = parsedCode.tokenList.getNextToken(token); + var next:Null = parsedCode.tokenList.getNextToken(token); if (next == null) { return token; } @@ -170,10 +170,10 @@ class Indenter { function countLineBreaks(indentingTokensCandidates:Array):Int { var count:Int = 0; - var prevToken:TokenTree = null; - var currentToken:TokenTree = null; + var prevToken:Null = null; + var currentToken:Null = null; var mustIndent:Bool; - var lastIndentingToken:TokenTree = null; + var lastIndentingToken:Null = null; for (token in indentingTokensCandidates) { prevToken = currentToken; if (prevToken == null) { @@ -242,6 +242,16 @@ class Indenter { if (currentToken.access().parent().parent().is(Kwd(KwdTypedef)).exists()) { continue; } + var type:BrOpenType = TokenTreeCheckUtils.getBrOpenType(prevToken); + switch (type) { + case OBJECTDECL: + var brClose:TokenTree = prevToken.access().firstOf(BrClose).token; + if ((brClose != null) && (!parsedCode.tokenList.isSameLine(prevToken, brClose)) && !config.indentObjectLiteral) { + continue; + } + default: + // continue; + } default: } case DblDot: @@ -307,14 +317,14 @@ class Indenter { function findIndentingCandidates(token:TokenTree):Array { var indentingTokensCandidates:Array = []; - var lastIndentingToken:TokenTree = null; + var lastIndentingToken:Null = null; switch (token.tok) { case Dot: lastIndentingToken = token; default: } indentingTokensCandidates.push(token); - var parent:TokenTree = token; + var parent:Null = token; while ((parent.parent != null) && (parent.parent.tok != null)) { parent = parent.parent; if (parent.pos.min > token.pos.min) { @@ -353,7 +363,7 @@ class Indenter { if ((token.parent.is(Kwd(KwdCase))) || (token.parent.is(Kwd(KwdDefault)))) { return true; } - var info:TokenInfo = parsedCode.tokenList.getTokenAt(token.index); + var info:Null = parsedCode.tokenList.getTokenAt(token.index); if (info == null) { return false; } diff --git a/src/formatter/marker/MarkEmptyLines.hx b/src/formatter/marker/MarkEmptyLines.hx index 13cfc835..29eeb49f 100644 --- a/src/formatter/marker/MarkEmptyLines.hx +++ b/src/formatter/marker/MarkEmptyLines.hx @@ -234,7 +234,7 @@ class MarkEmptyLines extends MarkerBase { markBeginAndEndType(block, typeConfig.beginType, typeConfig.endType); var finalTokDef:TokenDef = #if (haxe_ver >= 4.0) Kwd(KwdFinal); #else Const(CIdent(FINAL)); #end - var functions:Array = c.filter([Kwd(KwdFunction), Kwd(KwdVar), finalTokDef], FIRST); + var functions:Array = findClassAndAbstractFields(c); var prevToken:TokenTree = null; var prevTokenType:TokenFieldType = null; var currToken:TokenTree = null; @@ -249,6 +249,25 @@ class MarkEmptyLines extends MarkerBase { } } + function findClassAndAbstractFields(c:TokenTree):Array { + return c.filterCallback(function(token:TokenTree, index:Int):FilterResult { + return switch (token.tok) { + case Kwd(KwdFunction), Kwd(KwdVar): + FOUND_SKIP_SUBTREE; + case Const(CIdent(FINAL)): + FOUND_SKIP_SUBTREE; + #if (haxe_ver >= 4.0) + case Kwd(KwdFinal): + FOUND_SKIP_SUBTREE; + #end + case At: + SKIP_SUBTREE; + default: + GO_DEEPER; + } + }); + } + function markBeginAndEndType(brOpen:TokenTree, beginType:Int, endType:Int) { if (brOpen == null) { return; @@ -262,7 +281,7 @@ class MarkEmptyLines extends MarkerBase { emptyLinesBefore(brClose, endType); } - function markClassFieldEmptyLines(prevToken:TokenTree, prevTokenType:TokenFieldType, currToken:TokenTree, currTokenType:TokenFieldType, + function markClassFieldEmptyLines(prevToken:Null, prevTokenType:TokenFieldType, currToken:TokenTree, currTokenType:TokenFieldType, conf:ClassFieldsEmptyLinesConfig) { if (prevToken == null) { return; @@ -350,7 +369,7 @@ class MarkEmptyLines extends MarkerBase { } function markExternClass(c:TokenTree, conf:InterfaceFieldsEmptyLinesConfig) { - var block:TokenTree = c.access().firstChild().firstOf(BrOpen).token; + var block:Null = c.access().firstChild().firstOf(BrOpen).token; if (block == null) { return; } @@ -359,10 +378,10 @@ class MarkEmptyLines extends MarkerBase { var finalTokDef:TokenDef = #if (haxe_ver >= 4.0) Kwd(KwdFinal); #else Const(CIdent(FINAL)); #end var fields:Array = block.filter([Kwd(KwdFunction), Kwd(KwdVar), finalTokDef], FIRST); - var prevToken:TokenTree = null; - var prevTokenType:TokenFieldType = null; - var currToken:TokenTree = null; - var currTokenType:TokenFieldType = null; + var prevToken:Null = null; + var prevTokenType:Null = null; + var currToken:Null = null; + var currTokenType:Null = null; for (field in fields) { currToken = field; currTokenType = FieldUtils.getFieldType(field, PUBLIC); @@ -379,7 +398,7 @@ class MarkEmptyLines extends MarkerBase { } } - function markInterfaceEmptyLines(prevToken:TokenTree, prevTokenType:TokenFieldType, currToken:TokenTree, currTokenType:TokenFieldType, + function markInterfaceEmptyLines(prevToken:Null, prevTokenType:TokenFieldType, currToken:TokenTree, currTokenType:TokenFieldType, conf:InterfaceFieldsEmptyLinesConfig) { if (prevToken == null) { return; @@ -427,15 +446,15 @@ class MarkEmptyLines extends MarkerBase { } function markEnumAbstracts(token:TokenTree) { - var block:TokenTree = token.access().firstChild().firstOf(BrOpen).token; + var block:Null = token.access().firstChild().firstOf(BrOpen).token; markBeginAndEndType(block, config.emptyLines.enumAbstractEmptyLines.beginType, config.emptyLines.enumAbstractEmptyLines.endType); var functions:Array = token.filter([Kwd(KwdFunction), Kwd(KwdVar)], FIRST); - var prevToken:TokenTree = null; - var prevTokenType:TokenFieldType = null; - var currToken:TokenTree = null; - var currTokenType:TokenFieldType = null; + var prevToken:Null = null; + var prevTokenType:Null = null; + var currToken:Null = null; + var currTokenType:Null = null; for (func in functions) { currToken = func; currTokenType = FieldUtils.getFieldType(func, PUBLIC); @@ -445,7 +464,7 @@ class MarkEmptyLines extends MarkerBase { } } - function markEnumAbstractFieldEmptyLines(prevToken:TokenTree, prevTokenType:TokenFieldType, currToken:TokenTree, + function markEnumAbstractFieldEmptyLines(prevToken:Null, prevTokenType:TokenFieldType, currToken:TokenTree, currTokenType:TokenFieldType) { if (prevToken == null) { return; @@ -517,7 +536,7 @@ class MarkEmptyLines extends MarkerBase { if ((block.children == null) || (block.children.length <= 0)) { return; } - var prevToken:TokenTree = null; + var prevToken:Null = null; for (child in block.children) { switch (child.tok) { case BrClose: @@ -538,7 +557,7 @@ class MarkEmptyLines extends MarkerBase { function markTypedefs() { var typedefs:Array = parsedCode.root.filter([Kwd(KwdTypedef)], ALL); for (t in typedefs) { - var block:TokenTree = t.access().firstChild().firstOf(Binop(OpAssign)).firstOf(BrOpen).token; + var block:Null = t.access().firstChild().firstOf(Binop(OpAssign)).firstOf(BrOpen).token; if (block == null) { continue; } @@ -546,7 +565,7 @@ class MarkEmptyLines extends MarkerBase { } } - function skipSharpFields(prevToken:TokenTree):TokenTree { + function skipSharpFields(prevToken:TokenTree):Null { var next:TokenTree = prevToken.nextSibling; if (next == null) { return prevToken; @@ -587,14 +606,14 @@ class MarkEmptyLines extends MarkerBase { if (types.length <= 1) { return; } - var prevTypeInfo:TypeEmptyLinesInfo = null; + var prevTypeInfo:Null = null; for (type in types) { var newTypeInfo:TypeEmptyLinesInfo = getTypeInfo(type); if (prevTypeInfo == null) { prevTypeInfo = newTypeInfo; continue; } - var next:TokenInfo = getNextToken(prevTypeInfo.token); + var next:Null = getNextToken(prevTypeInfo.token); if (next != null) { switch (next.token.tok) { case Sharp(MarkLineEnds.SHARP_ELSE), Sharp(MarkLineEnds.SHARP_ELSE_IF): @@ -620,14 +639,14 @@ class MarkEmptyLines extends MarkerBase { if (isSameLine(token, info.token)) { info.oneLine = true; } - var atToken:TokenTree = token.access().firstChild().isCIdent().firstOf(At).token; + var atToken:Null = token.access().firstChild().isCIdent().firstOf(At).token; if (atToken != null) { if (!isSameLine(atToken, info.token)) { info.oneLine = false; } } while (true) { - var next:TokenInfo = getNextToken(info.token); + var next:Null = getNextToken(info.token); if (next == null) { break; } @@ -662,7 +681,7 @@ class MarkEmptyLines extends MarkerBase { if (lastChild == null) { continue; } - var next:TokenInfo = getNextToken(lastChild); + var next:Null = getNextToken(lastChild); if (next == null) { continue; } @@ -684,7 +703,7 @@ class MarkEmptyLines extends MarkerBase { } }); for (sharp in sharps) { - var prev:TokenInfo = getPreviousToken(sharp); + var prev:Null = getPreviousToken(sharp); if ((prev != null) && (prev.whitespaceAfter != Newline)) { continue; } @@ -717,7 +736,7 @@ class MarkEmptyLines extends MarkerBase { } }); for (comment in comments) { - var effectiveToken:TokenTree = null; + var effectiveToken:Null = null; effectiveToken = comment; if (comment.previousSibling != null) { if ((comment.parent != null) && (comment.parent.tok != null)) { @@ -784,7 +803,7 @@ class MarkEmptyLines extends MarkerBase { } }); for (comment in comments) { - var sibling:TokenTree = comment.nextSibling; + var sibling:Null = comment.nextSibling; if (sibling == null) { continue; } @@ -805,21 +824,21 @@ class MarkEmptyLines extends MarkerBase { switch (token.tok) { case Kwd(KwdIf): removeEmptyLinesAroundBlock(token.children[1], config.emptyLines.beforeBlocks, Keep); - var block:TokenTree = token.access().firstOf(Kwd(KwdElse)).previousSibling().token; + var block:Null = token.access().firstOf(Kwd(KwdElse)).previousSibling().token; if (block != null) { removeEmptyLinesAroundBlock(block, Keep, config.emptyLines.afterBlocks); } case Kwd(KwdElse): removeEmptyLinesAroundBlock(token.getFirstChild(), config.emptyLines.beforeBlocks, Keep); case Kwd(KwdCase), Kwd(KwdDefault): - var block:TokenTree = token.access().firstOf(DblDot).firstChild().token; + var block:Null = token.access().firstOf(DblDot).firstChild().token; removeEmptyLinesAroundBlock(block, config.emptyLines.beforeBlocks, Keep); case Kwd(KwdFunction): case Kwd(KwdFor): removeEmptyLinesAroundBlock(token.children[1], config.emptyLines.beforeBlocks, Keep); case Kwd(KwdDo): removeEmptyLinesAroundBlock(token.getFirstChild(), config.emptyLines.beforeBlocks, Keep); - var block:TokenTree = token.access().lastChild().previousSibling().token; + var block:Null = token.access().lastChild().previousSibling().token; removeEmptyLinesAroundBlock(block, Keep, config.emptyLines.afterBlocks); case Kwd(KwdWhile): if ((token.parent == null) || (!token.parent.is(Kwd(KwdDo)))) { @@ -827,7 +846,7 @@ class MarkEmptyLines extends MarkerBase { } case Kwd(KwdTry): removeEmptyLinesAroundBlock(token.getFirstChild(), config.emptyLines.beforeBlocks, Keep); - var block:TokenTree = token.access().lastChild().previousSibling().token; + var block:Null = token.access().lastChild().previousSibling().token; removeEmptyLinesAroundBlock(block, Keep, config.emptyLines.afterBlocks); case Kwd(KwdCatch): removeEmptyLinesAroundBlock(token.children[1], config.emptyLines.beforeBlocks, Keep); @@ -842,7 +861,7 @@ class MarkEmptyLines extends MarkerBase { return; } if (before == Remove) { - var prev:TokenInfo = getPreviousToken(block); + var prev:Null = getPreviousToken(block); if (prev != null) { emptyLinesAfter(prev.token, 0); } @@ -855,7 +874,7 @@ class MarkEmptyLines extends MarkerBase { function keepExistingEmptyLines() { var funcs:Array = parsedCode.root.filter([Kwd(KwdFunction)], ALL); for (func in funcs) { - var block:TokenTree = func.access().firstChild().is(BrOpen).token; + var block:Null = func.access().firstChild().is(BrOpen).token; if (block == null) { block = func.access().firstChild().firstOf(BrOpen).token; } @@ -871,7 +890,7 @@ class MarkEmptyLines extends MarkerBase { continue; } var idx:LineIds = parsedCode.linesIdx[emptyLine]; - var tokenInf:TokenInfo = findTokenAtOffset(idx.l); + var tokenInf:Null = findTokenAtOffset(idx.l); if (tokenInf == null) { continue; } @@ -881,7 +900,7 @@ class MarkEmptyLines extends MarkerBase { } function markFileHeader() { - var info:TokenInfo = getTokenAt(0); + var info:Null = getTokenAt(0); if (info == null) { return; diff --git a/src/formatter/marker/MarkLineEnds.hx b/src/formatter/marker/MarkLineEnds.hx index e21acc2f..04f0e085 100644 --- a/src/formatter/marker/MarkLineEnds.hx +++ b/src/formatter/marker/MarkLineEnds.hx @@ -37,7 +37,7 @@ class MarkLineEnds extends MarkerBase { for (token in commentTokens) { switch (token.tok) { case CommentLine(_): - var prev:TokenInfo = getPreviousToken(token); + var prev:Null = getPreviousToken(token); if (prev != null) { if (parsedCode.isOriginalSameLine(token, prev.token)) { noLineEndBefore(token); @@ -45,7 +45,7 @@ class MarkLineEnds extends MarkerBase { } lineEndAfter(token); case Comment(_): - var prev:TokenInfo = getPreviousToken(token); + var prev:Null = getPreviousToken(token); if (prev != null) { if (parsedCode.isOriginalSameLine(token, prev.token)) { if (prev.whitespaceAfter == Newline) { @@ -76,11 +76,11 @@ class MarkLineEnds extends MarkerBase { }); for (brOpen in brTokens) { - var brClose:TokenTree = brOpen.access().firstOf(BrClose).token; + var brClose:Null = brOpen.access().firstOf(BrClose).token; if (brClose == null) { continue; } - var prev:TokenInfo = getPreviousToken(brOpen); + var prev:Null = getPreviousToken(brOpen); if (prev != null) { switch (prev.token.tok) { case Dollar(name): @@ -105,7 +105,7 @@ class MarkLineEnds extends MarkerBase { default: } } - var next:TokenInfo = getNextToken(brOpen); + var next:Null = getNextToken(brOpen); var isEmpty:Bool = false; if ((next != null) && next.token.is(BrClose) && (config.lineEnds.emptyCurly == NoBreak)) { isEmpty = true; @@ -145,7 +145,7 @@ class MarkLineEnds extends MarkerBase { } function beforeLeftCurly(token:TokenTree) { - var prevToken:TokenInfo = getPreviousToken(token); + var prevToken:Null = getPreviousToken(token); if (prevToken == null) { return; } @@ -162,7 +162,7 @@ class MarkLineEnds extends MarkerBase { } function beforeRightCurly(token:TokenTree) { - var prevToken:TokenInfo = getPreviousToken(token); + var prevToken:Null = getPreviousToken(token); if (prevToken == null) { return; } @@ -181,7 +181,7 @@ class MarkLineEnds extends MarkerBase { lineEndAfter(token); return; } - var nextToken:TokenInfo = getTokenAt(next); + var nextToken:Null = getTokenAt(next); if (nextToken == null) { lineEndAfter(token); return; @@ -202,7 +202,7 @@ class MarkLineEnds extends MarkerBase { var atTokens:Array = parsedCode.root.filter([At], ALL); for (token in atTokens) { var metadataPolicy:AtLineEndPolicy = determineMetadataPolicy(token); - var lastChild:TokenTree = TokenTreeCheckUtils.getLastToken(token); + var lastChild:Null = TokenTreeCheckUtils.getLastToken(token); if (lastChild == null) { continue; } @@ -214,7 +214,7 @@ class MarkLineEnds extends MarkerBase { // only look at first metadata continue; } - var next:TokenTree = token.nextSibling; + var next:Null = token.nextSibling; var metadata:Array = [token]; while ((next != null) && (next.is(At))) { metadata.push(next); @@ -227,7 +227,7 @@ class MarkLineEnds extends MarkerBase { } switch (metadataPolicy) { case None: - var next:TokenInfo = getNextToken(lastChild); + var next:Null = getNextToken(lastChild); if ((next != null) && (!parsedCode.isOriginalSameLine(lastChild, next.token))) { lineEndAfter(lastChild); continue; @@ -236,7 +236,7 @@ class MarkLineEnds extends MarkerBase { case After: lineEndAfter(lastChild); case AfterLast: - var next:TokenInfo = getNextToken(lastChild); + var next:Null = getNextToken(lastChild); if ((next != null) && (!parsedCode.isOriginalSameLine(lastChild, next.token))) { lineEndAfter(lastChild); continue; @@ -291,7 +291,7 @@ class MarkLineEnds extends MarkerBase { if (config.lineEnds.caseColon != None) { lineEndAfter(token); } - var lastChild:TokenTree = TokenTreeCheckUtils.getLastToken(token); + var lastChild:Null = TokenTreeCheckUtils.getLastToken(token); if (lastChild == null) { continue; } @@ -337,7 +337,7 @@ class MarkLineEnds extends MarkerBase { case Sharp(SHARP_END): if (isInlineSharp(token)) { noLineEndBefore(token); - var next:TokenInfo = getNextToken(token); + var next:Null = getNextToken(token); if (next != null) { switch (next.token.tok) { case Comma, Semicolon: @@ -390,7 +390,7 @@ class MarkLineEnds extends MarkerBase { if (!isOnlyWhitespaceBeforeToken(token)) { return true; } - var prev:TokenInfo = getPreviousToken(token); + var prev:Null = getPreviousToken(token); if (prev == null) { return !isOnlyWhitespaceBeforeToken(token); } @@ -430,8 +430,8 @@ class MarkLineEnds extends MarkerBase { return (~/^\s*$/.match(prefix)); } - function findTypedefBrOpen(token:TokenTree):TokenTree { - var assign:TokenTree = token.access().firstChild().isCIdent().firstOf(Binop(OpAssign)).token; + function findTypedefBrOpen(token:TokenTree):Null { + var assign:Null = token.access().firstChild().isCIdent().firstOf(Binop(OpAssign)).token; if (assign == null) { return null; } @@ -442,21 +442,21 @@ class MarkLineEnds extends MarkerBase { var typedefTokens:Array = parsedCode.root.filter([Kwd(KwdTypedef)], ALL); for (token in typedefTokens) { markAfterTypedef(token); - var brOpen:TokenTree = findTypedefBrOpen(token); + var brOpen:Null = findTypedefBrOpen(token); if (brOpen == null) { continue; } if ((brOpen.children == null) || (brOpen.children.length <= 0)) { continue; } - var assignParent:TokenTree = brOpen.parent; + var assignParent:Null = brOpen.parent; if (assignParent.children.length > 1) { for (child in assignParent.children) { var lastChild:TokenTree = TokenTreeCheckUtils.getLastToken(child); if (lastChild == null) { continue; } - var next:TokenInfo = getNextToken(lastChild); + var next:Null = getNextToken(lastChild); if (next == null) { continue; } @@ -490,7 +490,7 @@ class MarkLineEnds extends MarkerBase { } lineEndAfter(lastChild); case BrClose: - var next:TokenInfo = getNextToken(child); + var next:Null = getNextToken(child); if (next == null) { continue; } @@ -511,7 +511,7 @@ class MarkLineEnds extends MarkerBase { if (lastChild == null) { return; } - var next:TokenInfo = getNextToken(lastChild); + var next:Null = getNextToken(lastChild); if ((next != null) && next.token.is(Semicolon)) { whitespace(lastChild, NoneAfter); return; diff --git a/src/formatter/marker/MarkSameLine.hx b/src/formatter/marker/MarkSameLine.hx index 10d5ad5a..a7b6c35a 100644 --- a/src/formatter/marker/MarkSameLine.hx +++ b/src/formatter/marker/MarkSameLine.hx @@ -45,7 +45,7 @@ class MarkSameLine extends MarkerBase { }); } - function isExpression(token:TokenTree):Bool { + function isExpression(token:Null):Bool { if (token == null) { return false; } @@ -77,6 +77,7 @@ class MarkSameLine extends MarkerBase { return isReturnExpression(parent); default: } + return false; } @@ -115,34 +116,36 @@ class MarkSameLine extends MarkerBase { return false; } - function shouldIfBeSameLine(token:TokenTree):Bool { + function shouldIfBeSameLine(token:Null):Bool { if (token == null) { return false; } if (!token.is(Kwd(KwdIf))) { return false; } - var body:TokenTree = getBodyAfterCondition(token); + var body:Null = getBodyAfterCondition(token); if (body == null) { return false; } if (!parsedCode.isOriginalSameLine(token, body)) { return false; } + return isExpression(token); } - function shouldElseBeSameLine(token:TokenTree):Bool { + function shouldElseBeSameLine(token:Null):Bool { if (token == null) { return false; } if (!token.is(Kwd(KwdElse))) { return false; } + return shouldIfBeSameLine(token.parent); } - function shouldTryBeSameLine(token:TokenTree):Bool { + function shouldTryBeSameLine(token:Null):Bool { if (token == null) { return false; } @@ -152,7 +155,7 @@ class MarkSameLine extends MarkerBase { return isExpression(token); } - function shouldCatchBeSameLine(token:TokenTree):Bool { + function shouldCatchBeSameLine(token:Null):Bool { if (token == null) { return false; } @@ -163,28 +166,52 @@ class MarkSameLine extends MarkerBase { } function markIf(token:TokenTree) { - if (shouldIfBeSameLine(token) && config.sameLine.expressionIf == Same) { - markBodyAfterPOpen(token, Same, config.sameLine.expressionIfWithBlocks); - return; + if (shouldIfBeSameLine(token)) { + switch (config.sameLine.expressionIf) { + case Same: + markBodyAfterPOpen(token, Same, config.sameLine.expressionIfWithBlocks); + return; + case Keep: + markBodyAfterPOpen(token, Keep, config.sameLine.expressionIfWithBlocks); + return; + case Next: + } } markBodyAfterPOpen(token, config.sameLine.ifBody, false); - var prev:TokenInfo = getPreviousToken(token); + var prev:Null = getPreviousToken(token); if ((prev != null) && (prev.token.is(Kwd(KwdElse)))) { applySameLinePolicy(token, config.sameLine.elseIf); } } function markElse(token:TokenTree) { - if (shouldElseBeSameLine(token) && config.sameLine.expressionIf == Same) { - markBody(token, Same, config.sameLine.expressionIfWithBlocks); - var prev:TokenInfo = getPreviousToken(token); - if (prev == null) { - return; - } - if (prev.token.is(BrClose)) { - applySameLinePolicyChained(token, config.sameLine.ifBody, config.sameLine.ifElse); + if (shouldElseBeSameLine(token)) { + switch (config.sameLine.expressionIf) { + case Same: + markBody(token, Same, config.sameLine.expressionIfWithBlocks); + var prev:Null = getPreviousToken(token); + if (prev == null) { + return; + } + if (prev.token.is(BrClose)) { + applySameLinePolicyChained(token, config.sameLine.ifBody, config.sameLine.ifElse); + } + return; + case Keep: + markBody(token, Keep, config.sameLine.expressionIfWithBlocks); + if (parsedCode.isOriginalNewlineBefore(token)) { + lineEndBefore(token); + } + var prev:Null = getPreviousToken(token); + if (prev == null) { + return; + } + if (prev.token.is(BrClose)) { + applySameLinePolicyChained(token, Keep, Keep); + } + return; + case Next: } - return; } markBody(token, config.sameLine.elseBody, false); @@ -234,8 +261,8 @@ class MarkSameLine extends MarkerBase { case Next: return; } - var first:TokenTree = dblDot.getFirstChild(); - var last:TokenTree = TokenTreeCheckUtils.getLastToken(first); + var first:Null = dblDot.getFirstChild(); + var last:Null = TokenTreeCheckUtils.getLastToken(first); if (parsedCode.linesBetweenOriginal(first, last) > 2) { return; } @@ -257,10 +284,10 @@ class MarkSameLine extends MarkerBase { return; } if (dblDot.children.length == 2) { - var second:TokenTree = dblDot.children[1]; + var second:Null = dblDot.children[1]; switch (second.tok) { case CommentLine(_): - var prev:TokenInfo = getPreviousToken(second); + var prev:Null = getPreviousToken(second); if (prev != null) { if (!parsedCode.isOriginalSameLine(dblDot, prev.token)) { return; @@ -280,7 +307,7 @@ class MarkSameLine extends MarkerBase { if (token == null) { return; } - var parent:TokenTree = token.parent; + var parent:Null = token.parent; if ((parent == null) || (parent.tok == null)) { return; } @@ -289,7 +316,7 @@ class MarkSameLine extends MarkerBase { markArrayComprehension(token, parent); return; case Kwd(KwdMacro): - var lastToken:TokenTree = TokenTreeCheckUtils.getLastToken(token); + var lastToken:Null = TokenTreeCheckUtils.getLastToken(token); if (lastToken == null) { return; } @@ -306,7 +333,7 @@ class MarkSameLine extends MarkerBase { if (token == null) { return; } - var parent:TokenTree = token.parent; + var parent:Null = token.parent; if ((parent == null) || (parent.tok == null)) { return; } @@ -320,7 +347,7 @@ class MarkSameLine extends MarkerBase { } function markArrayComprehension(token:TokenTree, bkOpen:TokenTree) { - var bkClose:TokenTree = bkOpen.access().firstOf(BkClose).token; + var bkClose:Null = bkOpen.access().firstOf(BkClose).token; switch (config.sameLine.comprehensionFor) { case Keep: if (parsedCode.isOriginalNewlineBefore(token)) { @@ -348,8 +375,8 @@ class MarkSameLine extends MarkerBase { } } - function getBodyAfterCondition(token:TokenTree):TokenTree { - var body:TokenTree = token.access().firstOf(POpen).nextSibling().token; + function getBodyAfterCondition(token:TokenTree):Null { + var body:Null = token.access().firstOf(POpen).nextSibling().token; if (body != null) { return body; } @@ -372,7 +399,7 @@ class MarkSameLine extends MarkerBase { } function markBodyAfterPOpen(token:TokenTree, policy:SameLinePolicy, includeBrOpen:Bool) { - var body:TokenTree = getBodyAfterCondition(token); + var body:Null = getBodyAfterCondition(token); while (body != null) { switch (body.tok) { case BrOpen: @@ -391,7 +418,7 @@ class MarkSameLine extends MarkerBase { } body = body.nextSibling; case CommentLine(_): - var prev:TokenInfo = getPreviousToken(body); + var prev:Null = getPreviousToken(body); if (prev != null) { if (!parsedCode.isOriginalSameLine(body, prev.token)) { applySameLinePolicy(body, policy); @@ -411,7 +438,7 @@ class MarkSameLine extends MarkerBase { } function markBody(token:TokenTree, policy:SameLinePolicy, includeBrOpen:Bool) { - var body:TokenTree = token.access().firstChild().token; + var body:Null = token.access().firstChild().token; if (body == null) { return; } @@ -445,7 +472,7 @@ class MarkSameLine extends MarkerBase { return; } - var lastChild:TokenTree = token.getLastChild(); + var lastChild:Null = token.getLastChild(); if (lastChild.is(Semicolon)) { if (token.children.length > 3) { return; @@ -459,7 +486,7 @@ class MarkSameLine extends MarkerBase { for (child in token.children) { switch (child.tok) { case BrClose: - var next:TokenInfo = getNextToken(child); + var next:Null = getNextToken(child); switch (next.token.tok) { case Kwd(KwdElse): noLineEndAfter(child); @@ -484,7 +511,7 @@ class MarkSameLine extends MarkerBase { function applySameLinePolicyChained(token:TokenTree, previousBlockPolicy:SameLinePolicy, policy:SameLinePolicy) { if (policy == Same) { - var prev:TokenInfo = getPreviousToken(token); + var prev:Null = getPreviousToken(token); if (prev == null) { policy = Next; } @@ -505,7 +532,7 @@ class MarkSameLine extends MarkerBase { } case Same: wrapBefore(token, true); - var prev:TokenInfo = getPreviousToken(token); + var prev:Null = getPreviousToken(token); if (prev == null) { noLineEndBefore(token); } else { @@ -516,11 +543,11 @@ class MarkSameLine extends MarkerBase { noLineEndBefore(token); } } - var lastToken:TokenTree = TokenTreeCheckUtils.getLastToken(token); + var lastToken:Null = TokenTreeCheckUtils.getLastToken(token); if (lastToken == null) { return; } - var next:TokenInfo = getNextToken(lastToken); + var next:Null = getNextToken(lastToken); if (next == null) { return; } @@ -545,7 +572,7 @@ class MarkSameLine extends MarkerBase { } }); for (token in tokens) { - var brOpen:TokenTree = token.access().firstChild().is(BrOpen).token; + var brOpen:Null = token.access().firstChild().is(BrOpen).token; if (brOpen == null) { continue; } @@ -554,7 +581,7 @@ class MarkSameLine extends MarkerBase { continue; } whitespace(brOpen, None); - var next:TokenInfo = getNextToken(brClose); + var next:Null = getNextToken(brClose); if (next != null) { switch (next.token.tok) { case BrClose: @@ -577,7 +604,7 @@ class MarkSameLine extends MarkerBase { } function markFunction(token:TokenTree) { - var body:TokenTree = token.access().firstChild().isCIdent().token; + var body:Null = token.access().firstChild().isCIdent().token; if (body == null) { body = token.access().firstChild().is(Kwd(KwdNew)).token; } @@ -619,7 +646,7 @@ class MarkSameLine extends MarkerBase { function markDoWhile(token:TokenTree) { markBody(token, config.sameLine.doWhileBody, false); - var whileTok:TokenTree = token.access().firstOf(Kwd(KwdWhile)).token; + var whileTok:Null = token.access().firstOf(Kwd(KwdWhile)).token; if (whileTok == null) { return; } @@ -627,7 +654,7 @@ class MarkSameLine extends MarkerBase { } function markMacro(token:TokenTree) { - var brOpen:TokenInfo = getNextToken(token); + var brOpen:Null = getNextToken(token); if ((brOpen == null) || (!brOpen.token.is(BrOpen))) { return; } diff --git a/src/formatter/marker/MarkTokenText.hx b/src/formatter/marker/MarkTokenText.hx index 142c0d7f..398ce7dc 100644 --- a/src/formatter/marker/MarkTokenText.hx +++ b/src/formatter/marker/MarkTokenText.hx @@ -26,7 +26,7 @@ class MarkTokenText extends MarkerBase { }); } - public function finalRun(lines:CodeLines) { + public function finalRun() { parsedCode.root.filterCallback(function(token:TokenTree, index:Int):FilterResult { switch (token.tok) { case Comment(text): @@ -194,7 +194,7 @@ class MarkTokenText extends MarkerBase { function removeCommentPrefix(lines:Array):Array { var prefixReg:EReg = ~/^(\s*)/; - var prefix:String = null; + var prefix:Null = null; var linesNew:Array = []; var endIndex:Int = lines.length - 1; var lastLine:String = lines[lines.length - 1]; diff --git a/src/formatter/marker/MarkWhitespace.hx b/src/formatter/marker/MarkWhitespace.hx index c5e3de20..e24676b2 100644 --- a/src/formatter/marker/MarkWhitespace.hx +++ b/src/formatter/marker/MarkWhitespace.hx @@ -77,16 +77,16 @@ class MarkWhitespace extends MarkerBase { case Const(CIdent(MarkEmptyLines.FINAL)): whitespace(token, After); case Const(CIdent("is")): - var parent:TokenTree = token.access().parent().is(POpen).token; + var parent:Null = token.access().parent().is(POpen).token; if (parent != null) { - var prev:TokenInfo = getPreviousToken(parent); + var prev:Null = getPreviousToken(parent); if ((prev != null) && (prev.token.is(POpen))) { whitespace(token, Around); } } fixConstAfterConst(token); case Const(CIdent("from")), Const(CIdent("to")): - var parent:TokenTree = token.access().parent().parent().is(Kwd(KwdAbstract)).token; + var parent:Null = token.access().parent().parent().is(Kwd(KwdAbstract)).token; if (parent != null) { whitespace(token, Around); } @@ -112,7 +112,7 @@ class MarkWhitespace extends MarkerBase { } if (TokenTreeCheckUtils.isTypeParameter(token)) { var policy:WhitespacePolicy = config.whitespace.typeParamClosePolicy; - var next:TokenInfo = getNextToken(token); + var next:Null = getNextToken(token); if (next != null) { switch (next.token.tok) { case Kwd(_): @@ -131,7 +131,7 @@ class MarkWhitespace extends MarkerBase { } function fixConstAfterConst(token:TokenTree) { - var next:TokenInfo = getNextToken(token); + var next:Null = getNextToken(token); if (next != null) { switch (next.token.tok) { case Const(_), Kwd(_): @@ -142,7 +142,7 @@ class MarkWhitespace extends MarkerBase { } public function successiveParenthesis(token:TokenTree, closing:Bool, policy:WhitespacePolicy, compress:Bool) { - var next:TokenInfo = getNextToken(token); + var next:Null = getNextToken(token); if (next != null) { switch (next.token.tok) { case Dot, Comma, DblDot, Semicolon: @@ -188,7 +188,7 @@ class MarkWhitespace extends MarkerBase { } } } else { - var prev:TokenInfo = getPreviousToken(token); + var prev:Null = getPreviousToken(token); if (prev != null) { switch (prev.token.tok) { case POpen, BrOpen, BkOpen: @@ -207,6 +207,12 @@ class MarkWhitespace extends MarkerBase { } case Arrow: return; + case Comma: + switch (config.whitespace.commaPolicy) { + case After, OnlyAfter, Around: + policy = policy.add(Before); + default: + } default: } } @@ -215,7 +221,7 @@ class MarkWhitespace extends MarkerBase { } function markKeyword(token:TokenTree) { - var prev:TokenInfo = getPreviousToken(token); + var prev:Null = getPreviousToken(token); if (prev != null) { switch (prev.token.tok) { case PClose: @@ -229,7 +235,7 @@ class MarkWhitespace extends MarkerBase { } switch (token.tok) { case Kwd(KwdNull), Kwd(KwdTrue), Kwd(KwdFalse), Kwd(KwdThis), Kwd(KwdDefault), Kwd(KwdContinue): - var next:TokenInfo = getNextToken(token); + var next:Null = getNextToken(token); if (next != null) { switch (next.token.tok) { case Kwd(_): @@ -267,7 +273,7 @@ class MarkWhitespace extends MarkerBase { case Kwd(KwdUntyped): whitespace(token, After); case Kwd(_): - var next:TokenInfo = getNextToken(token); + var next:Null = getNextToken(token); if (next != null) { switch (next.token.tok) { case POpen: @@ -283,7 +289,7 @@ class MarkWhitespace extends MarkerBase { } function markUnop(token:TokenTree) { - var next:TokenInfo = getNextToken(token); + var next:Null = getNextToken(token); if (next != null) { switch (next.token.tok) { case Comma, Semicolon: @@ -293,7 +299,7 @@ class MarkWhitespace extends MarkerBase { default: } } - var prev:TokenInfo = getPreviousToken(token); + var prev:Null = getPreviousToken(token); if (prev == null) { return; } @@ -305,7 +311,7 @@ class MarkWhitespace extends MarkerBase { } function markDollar(token:TokenTree) { - var next:TokenInfo = getNextToken(token); + var next:Null = getNextToken(token); if (next == null) { return; } @@ -339,7 +345,7 @@ class MarkWhitespace extends MarkerBase { } function markSemicolon(token:TokenTree) { - var next:TokenInfo = getNextToken(token); + var next:Null = getNextToken(token); var policy:WhitespacePolicy = config.whitespace.semicolonPolicy; if (next != null) { switch (next.token.tok) { @@ -355,7 +361,7 @@ class MarkWhitespace extends MarkerBase { switch (token.tok) { case Sharp(MarkLineEnds.SHARP_IF): whitespace(token, After); - var prev:TokenInfo = getPreviousToken(token); + var prev:Null = getPreviousToken(token); if (prev != null) { switch (prev.token.tok) { case Const(_), Kwd(_): @@ -368,7 +374,7 @@ class MarkWhitespace extends MarkerBase { case Sharp(MarkLineEnds.SHARP_ELSE): whitespace(token, Around); case Sharp(MarkLineEnds.SHARP_END): - var prev:TokenInfo = getPreviousToken(token); + var prev:Null = getPreviousToken(token); if (prev != null) { switch (prev.token.tok) { case POpen, BrOpen, BkOpen: @@ -376,7 +382,7 @@ class MarkWhitespace extends MarkerBase { whitespace(token, Before); } } - var next:TokenInfo = getNextToken(token); + var next:Null = getNextToken(token); if (next != null) { switch (next.token.tok) { case Comma, Semicolon: @@ -431,7 +437,7 @@ class MarkWhitespace extends MarkerBase { function markPOpen(token:TokenTree) { var openClosePolicy:OpenClosePolicy = determinePOpenPolicy(token); var policy:WhitespacePolicy = openClosePolicy.openingPolicy; - var prev:TokenInfo = getPreviousToken(token); + var prev:Null = getPreviousToken(token); if (prev != null) { switch (prev.token.tok) { case Unop(_): @@ -444,7 +450,7 @@ class MarkWhitespace extends MarkerBase { } } if (openClosePolicy.removeInnerWhenEmpty) { - var next:TokenInfo = getNextToken(token); + var next:Null = getNextToken(token); if (next != null) { switch (next.token.tok) { case PClose: @@ -460,7 +466,7 @@ class MarkWhitespace extends MarkerBase { var openClosePolicy:OpenClosePolicy = determinePOpenPolicy(token.parent); var policy:WhitespacePolicy = openClosePolicy.closingPolicy; if (openClosePolicy.removeInnerWhenEmpty) { - var prev:TokenInfo = getPreviousToken(token); + var prev:Null = getPreviousToken(token); if (prev != null) { switch (prev.token.tok) { case POpen: @@ -493,7 +499,7 @@ class MarkWhitespace extends MarkerBase { var openClosePolicy:OpenClosePolicy = determineBrOpenPolicy(token); var policy:WhitespacePolicy = openClosePolicy.openingPolicy; if (openClosePolicy.removeInnerWhenEmpty) { - var next:TokenInfo = getNextToken(token); + var next:Null = getNextToken(token); if (next != null) { switch (next.token.tok) { case BrClose: @@ -509,7 +515,7 @@ class MarkWhitespace extends MarkerBase { var openClosePolicy:OpenClosePolicy = determineBrOpenPolicy(token.parent); var policy:WhitespacePolicy = openClosePolicy.closingPolicy; if (openClosePolicy.removeInnerWhenEmpty) { - var prev:TokenInfo = getPreviousToken(token); + var prev:Null = getPreviousToken(token); if (prev != null) { switch (prev.token.tok) { case BrOpen: @@ -523,7 +529,7 @@ class MarkWhitespace extends MarkerBase { function markComment(token:TokenTree) { var policy:WhitespacePolicy = Around; - var next:TokenInfo = getNextToken(token); + var next:Null = getNextToken(token); if (next == null) { whitespace(token, policy); return; diff --git a/src/formatter/marker/MarkerBase.hx b/src/formatter/marker/MarkerBase.hx index 4576aea2..70142516 100644 --- a/src/formatter/marker/MarkerBase.hx +++ b/src/formatter/marker/MarkerBase.hx @@ -17,19 +17,19 @@ class MarkerBase { this.indenter = indenter; } - function getNextToken(token:TokenTree):TokenInfo { + function getNextToken(token:TokenTree):Null { return parsedCode.tokenList.getNextToken(token); } - function getPreviousToken(token:TokenTree):TokenInfo { + function getPreviousToken(token:TokenTree):Null { return parsedCode.tokenList.getPreviousToken(token); } - function getTokenInfo(token:TokenTree):TokenInfo { + function getTokenInfo(token:TokenTree):Null { return parsedCode.tokenList.getTokenAt(token.index); } - function getTokenAt(index:Int):TokenInfo { + function getTokenAt(index:Int):Null { return parsedCode.tokenList.getTokenAt(index); } @@ -93,7 +93,7 @@ class MarkerBase { parsedCode.tokenList.additionalIndent(token, indent, pos); } - public function findTokenAtOffset(offset:Int):TokenInfo { + public function findTokenAtOffset(offset:Int):Null { return parsedCode.tokenList.findTokenAtOffset(offset); } diff --git a/src/formatter/marker/wrapping/MarkWrapping.hx b/src/formatter/marker/wrapping/MarkWrapping.hx index 35fdb0ee..44b2bc2b 100644 --- a/src/formatter/marker/wrapping/MarkWrapping.hx +++ b/src/formatter/marker/wrapping/MarkWrapping.hx @@ -58,7 +58,7 @@ class MarkWrapping extends MarkWrappingBase { } function wrapTypeParameter(token:TokenTree) { - var close:TokenTree = token.access().firstOf(Binop(OpGt)).token; + var close:Null = token.access().firstOf(Binop(OpGt)).token; if ((token.children == null) || (token.children.length <= 1)) { return; } @@ -67,11 +67,11 @@ class MarkWrapping extends MarkWrappingBase { whitespace(close, NoneBefore); return; } - var next:TokenInfo = getNextToken(close); + var next:Null = getNextToken(close); if (next != null) { switch (next.token.tok) { case BrOpen: - var info:TokenInfo = getTokenInfo(close); + var info:Null = getTokenInfo(close); if (info.whitespaceAfter != Newline) { whitespace(close, After); } @@ -134,7 +134,10 @@ class MarkWrapping extends MarkWrappingBase { } function typedefWrapping(token:TokenTree) { - var brClose:TokenTree = token.access().firstOf(BrClose).token; + var brClose:Null = token.access().firstOf(BrClose).token; + if (isNewLineBefore(token)) { + return; + } if (parsedCode.isOriginalSameLine(token, brClose)) { noWrap(token, brClose); return; @@ -142,7 +145,7 @@ class MarkWrapping extends MarkWrappingBase { } function anonTypeWrapping(token:TokenTree) { - var brClose:TokenTree = token.access().firstOf(BrClose).token; + var brClose:Null = token.access().firstOf(BrClose).token; if ((token.children == null) || (token.children.length <= 0)) { return; } @@ -151,7 +154,7 @@ class MarkWrapping extends MarkWrappingBase { whitespace(brClose, NoneBefore); return; } - var next:TokenInfo = getNextToken(brClose); + var next:Null = getNextToken(brClose); if (next != null) { switch (next.token.tok) { case BrOpen: @@ -203,7 +206,7 @@ class MarkWrapping extends MarkWrappingBase { wrapFillLine(token, brClose, config.wrapping.maxLineLength, rule.additionalIndent); case NoWrap: noWrap(token, brClose); - var prev:TokenInfo = getPreviousToken(token); + var prev:Null = getPreviousToken(token); if (prev == null) { return; } @@ -217,7 +220,7 @@ class MarkWrapping extends MarkWrappingBase { } function objectLiteralWrapping(token:TokenTree) { - var brClose:TokenTree = token.access().firstOf(BrClose).token; + var brClose:Null = token.access().firstOf(BrClose).token; if ((token.children == null) || (token.children.length <= 1)) { return; } @@ -288,7 +291,7 @@ class MarkWrapping extends MarkWrappingBase { } function markPWrapping(token:TokenTree) { - var pClose:TokenTree = token.access().firstOf(PClose).token; + var pClose:Null = token.access().firstOf(PClose).token; switch (TokenTreeCheckUtils.getPOpenType(token)) { case AT: if (token.children != null) { @@ -327,7 +330,7 @@ class MarkWrapping extends MarkWrappingBase { } function arrayWrapping(token:TokenTree) { - var bkClose:TokenTree = token.access().firstOf(BkClose).token; + var bkClose:Null = token.access().firstOf(BkClose).token; if ((token.children == null) || (token.children.length <= 0)) { return; } diff --git a/src/formatter/marker/wrapping/MarkWrappingBase.hx b/src/formatter/marker/wrapping/MarkWrappingBase.hx index b49fc07a..b2d883c8 100644 --- a/src/formatter/marker/wrapping/MarkWrappingBase.hx +++ b/src/formatter/marker/wrapping/MarkWrappingBase.hx @@ -4,7 +4,7 @@ import formatter.config.WrapConfig; class MarkWrappingBase extends MarkerBase { public function noWrap(open:TokenTree, close:TokenTree) { - var colon:TokenTree = open.access().is(BrOpen).parent().is(DblDot).token; + var colon:Null = open.access().is(BrOpen).parent().is(DblDot).token; if (colon != null) { var type:ColonType = TokenTreeCheckUtils.getColonType(colon); switch (type) { @@ -29,7 +29,7 @@ class MarkWrappingBase extends MarkerBase { continue; default: } - var lastChild:TokenTree = TokenTreeCheckUtils.getLastToken(child); + var lastChild:Null = TokenTreeCheckUtils.getLastToken(child); if (lastChild == null) { continue; } else { @@ -43,9 +43,20 @@ class MarkWrappingBase extends MarkerBase { noLineEndBefore(close); } - public function keep2(open:TokenTree, close:TokenTree, items:Array, addIndent:Int) { + public function keep2(open:TokenTree, close:TokenTree, items:Array, addIndent:Int, location:WrappingLocation) { noWrappingBetween(open, close); - var tokens:Array = [for (item in items) item.first]; + var tokens:Array = []; + switch (location) { + case BeforeLast: + tokens = [for (item in items) item.last]; + tokens.pop(); + if (items.length > 0) { + tokens.unshift(items[0].first); + } + case AfterLast: + tokens = [for (item in items) item.first]; + } + tokens.push(close); for (token in tokens) { if (parsedCode.isOriginalNewlineBefore(token)) { @@ -84,13 +95,27 @@ class MarkWrappingBase extends MarkerBase { } } - public function wrapChildOneLineEach2(open:TokenTree, close:TokenTree, items:Array, addIndent:Int = 0, keepFirst:Bool = false) { + public function wrapChildOneLineEach2(open:TokenTree, close:TokenTree, items:Array, addIndent:Int = 0, location:WrappingLocation, + keepFirst:Bool = false) { if (items.length <= 0) { return; } - for (item in items) { - additionalIndent(item.first, addIndent); - lineEndBefore(item.first); + switch (location) { + case BeforeLast: + var item:WrappableItem = items[0]; + additionalIndent(item.first, addIndent); + lineEndBefore(item.first); + item = items.pop(); + for (item in items) { + additionalIndent(item.last, addIndent); + lineEndBefore(item.last); + } + items.push(item); + case AfterLast: + for (item in items) { + additionalIndent(item.first, addIndent); + lineEndBefore(item.first); + } } if (keepFirst) { noLineEndAfter(open); @@ -122,7 +147,7 @@ class MarkWrappingBase extends MarkerBase { case Sharp(_): wrapChildOneLineEachSharp(child, addIndent, keepFirst); case CommentLine(_): - var prev:TokenInfo = getPreviousToken(child); + var prev:Null = getPreviousToken(child); if (prev != null) { if (parsedCode.isOriginalSameLine(child, prev.token)) { noLineEndBefore(child); @@ -134,7 +159,7 @@ class MarkWrappingBase extends MarkerBase { default: additionalIndent(child, addIndent); } - var lastChild:TokenTree = TokenTreeCheckUtils.getLastToken(child); + var lastChild:Null = TokenTreeCheckUtils.getLastToken(child); if (lastChild == null) { lineEndAfter(child); } else { @@ -180,7 +205,7 @@ class MarkWrappingBase extends MarkerBase { case Sharp(_): wrapChildOneLineEachSharp(child, addIndent, keepFirst); case CommentLine(_): - var prev:TokenInfo = getPreviousToken(child); + var prev:Null = getPreviousToken(child); if (prev != null) { if (parsedCode.isOriginalSameLine(child, prev.token)) { noLineEndBefore(child); @@ -195,7 +220,7 @@ class MarkWrappingBase extends MarkerBase { } } - public function wrapFillLine2(open:TokenTree, close:TokenTree, items:Array, maxLineLength:Int, addIndent:Int = 0, + public function wrapFillLine2AfterLast(open:TokenTree, close:TokenTree, items:Array, maxLineLength:Int, addIndent:Int = 0, useTrailing:Bool = false) { noWrappingBetween(open, close); if (items.length <= 0) { @@ -237,6 +262,60 @@ class MarkWrappingBase extends MarkerBase { wrapAfter(open, false); } + public function wrapFillLine2BeforeLast(open:TokenTree, close:TokenTree, items:Array, maxLineLength:Int, addIndent:Int = 0, + useTrailing:Bool = false) { + noWrappingBetween(open, close); + if (items.length <= 0) { + return; + } + var indent:Int = indenter.calcIndent(open); + var lineLength:Int = calcLineLengthBefore(open) + indenter.calcAbsoluteIndent(indent) + calcTokenLength(open); + var first:Bool = true; + for (item in items) { + var tokenLength:Int = item.firstLineLength; + if (!first && (lineLength + tokenLength >= maxLineLength)) { + lineLength = indenter.calcAbsoluteIndent(indent + 1 + addIndent); + var prev:TokenInfo = getPreviousToken(item.first); + if (prev != null) { + lineEndBefore(prev.token); + additionalIndent(prev.token, addIndent); + lineLength += prev.text.length; + } + if (item.multiline) { + lineLength += item.lastLineLength; + } else { + lineLength += item.firstLineLength; + } + continue; + } else { + if (first) { + noLineEndBefore(item.first); + } else { + var prev:TokenInfo = getPreviousToken(item.first); + if (prev != null) { + noLineEndBefore(prev.token); + } + } + lineLength += tokenLength; + first = false; + if (item.multiline) { + lineLength = indenter.calcAbsoluteIndent(indent + 1 + addIndent) + item.lastLineLength; + } + } + } + if (useTrailing) { + var lastItem:WrappableItem = items[items.length - 1]; + var lengthAfter:Int = calcLineLengthAfter(lastItem.last); + var prev:TokenInfo = getPreviousToken(lastItem.first); + if ((prev != null) && (lineLength + lengthAfter >= maxLineLength)) { + lineEndBefore(prev.token); + additionalIndent(prev.token, addIndent); + } + } + noLineEndAfter(open); + wrapAfter(open, false); + } + public function wrapFillLine(open:TokenTree, close:TokenTree, maxLineLength:Int, addIndent:Int = 0, useTrailing:Bool = false) { noWrappingBetween(open, close); var indent:Int = indenter.calcIndent(open); @@ -263,7 +342,7 @@ class MarkWrappingBase extends MarkerBase { whitespace(child, NoneBefore); return; case CommentLine(_): - var prev:TokenInfo = getPreviousToken(child); + var prev:Null = getPreviousToken(child); if (prev != null) { if (parsedCode.isOriginalSameLine(child, prev.token)) { noLineEndBefore(child); @@ -280,7 +359,7 @@ class MarkWrappingBase extends MarkerBase { additionalIndent(child, addIndent); } var tokenLength:Int = calcLength(child); - var lastChild:TokenTree = TokenTreeCheckUtils.getLastToken(child); + var lastChild:Null = TokenTreeCheckUtils.getLastToken(child); if (lastChild == null) { lastChild = child; } @@ -306,7 +385,7 @@ class MarkWrappingBase extends MarkerBase { } function hasEmptyFunctionBody(token:TokenTree):Bool { - var last:TokenTree = token.getLastChild(); + var last:Null = token.getLastChild(); switch (last.tok) { case Semicolon: return true; @@ -329,7 +408,7 @@ class MarkWrappingBase extends MarkerBase { case Semicolon: return true; case BrOpen: - var brClose:TokenTree = body.getFirstChild(); + var brClose:Null = body.getFirstChild(); if (brClose == null) { return false; } @@ -347,7 +426,7 @@ class MarkWrappingBase extends MarkerBase { return items; default: } - var endToken:TokenTree = TokenTreeCheckUtils.getLastToken(child); + var endToken:Null = TokenTreeCheckUtils.getLastToken(child); var sameLine:Bool = isSameLineBetween(child, endToken, false); var firstLineLength:Int = calcLengthUntilNewline(child); var lastLineLength:Int = 0; @@ -371,6 +450,7 @@ class MarkWrappingBase extends MarkerBase { return { conditions: [], type: rules.defaultWrap, + location: rules.defaultLocation, additionalIndent: rules.defaultAdditionalIndent }; } @@ -394,6 +474,7 @@ class MarkWrappingBase extends MarkerBase { return { conditions: [], type: rules.defaultWrap, + location: rules.defaultLocation, additionalIndent: rules.defaultAdditionalIndent }; } @@ -407,6 +488,7 @@ class MarkWrappingBase extends MarkerBase { return { conditions: [], type: rules.defaultWrap, + location: rules.defaultLocation, additionalIndent: rules.defaultAdditionalIndent }; } @@ -452,16 +534,22 @@ class MarkWrappingBase extends MarkerBase { } function applyRule(rule:WrapRule, open:TokenTree, close:TokenTree, items:Array, addIndent:Int, useTrailing:Bool) { + var location:WrappingLocation = rule.location.or(AfterLast); switch (rule.type) { case OnePerLine: - wrapChildOneLineEach2(open, close, items, addIndent); + wrapChildOneLineEach2(open, close, items, addIndent, location); case OnePerLineAfterFirst: - wrapChildOneLineEach2(open, close, items, addIndent, true); + wrapChildOneLineEach2(open, close, items, addIndent, location, true); case Keep: - keep2(open, close, items, addIndent); + keep2(open, close, items, addIndent, location); case EqualNumber: case FillLine: - wrapFillLine2(open, close, items, config.wrapping.maxLineLength, addIndent, useTrailing); + switch (location) { + case AfterLast: + wrapFillLine2AfterLast(open, close, items, config.wrapping.maxLineLength, addIndent, useTrailing); + case BeforeLast: + wrapFillLine2BeforeLast(open, close, items, config.wrapping.maxLineLength, addIndent, useTrailing); + } case NoWrap: noWrappingBetween(open, close); } diff --git a/test/import.hx b/test/import.hx index 7a45a87a..bf631308 100644 --- a/test/import.hx +++ b/test/import.hx @@ -1 +1,2 @@ +using Safety; using StringTools; diff --git a/test/testcases/emptylines/issue_307_empty_line_after_class_metadata.hxtest b/test/testcases/emptylines/issue_307_empty_line_after_class_metadata.hxtest new file mode 100644 index 00000000..461d63b4 --- /dev/null +++ b/test/testcases/emptylines/issue_307_empty_line_after_class_metadata.hxtest @@ -0,0 +1,38 @@ +{ +} + +--- + +@:jsonParse(function() return null) +class Car { + var speed:Int; +} + +@:jsonParse(function(json) return new Car(json.speed, json.make)) +class Car { + public var speed(default, null):Int; + public var make(default, null):String; + + public function new(speed:Int, make:String) { + this.speed = speed; + this.make = make; + } +} + +--- + +@:jsonParse(function() return null) +class Car { + var speed:Int; +} + +@:jsonParse(function(json) return new Car(json.speed, json.make)) +class Car { + public var speed(default, null):Int; + public var make(default, null):String; + + public function new(speed:Int, make:String) { + this.speed = speed; + this.make = make; + } +} diff --git a/test/testcases/indentation/issue_298_sharp_error_indent_aligned.hxtest b/test/testcases/indentation/issue_298_sharp_error_indent_aligned.hxtest new file mode 100644 index 00000000..c604d25a --- /dev/null +++ b/test/testcases/indentation/issue_298_sharp_error_indent_aligned.hxtest @@ -0,0 +1,38 @@ +{ + "indentation": { + "conditionalPolicy": "aligned" + } +} + +--- + +#if cs +#error 'should be indented if using indentation.conditionalPolicy = "alignedDecrease"' +#end +class Main { +#if cs +#error 'should be indented if using indentation.conditionalPolicy = "alignedDecrease"' +#end + public function new (){ + #if cs +#error 'should be indented if using indentation.conditionalPolicy = "alignedDecrease"' +#end + + } +} + +--- + +#if cs +#error 'should be indented if using indentation.conditionalPolicy = "alignedDecrease"' +#end +class Main { + #if cs + #error 'should be indented if using indentation.conditionalPolicy = "alignedDecrease"' + #end + public function new() { + #if cs + #error 'should be indented if using indentation.conditionalPolicy = "alignedDecrease"' + #end + } +} diff --git a/test/testcases/indentation/issue_298_sharp_error_indent_aligned_decrease.hxtest b/test/testcases/indentation/issue_298_sharp_error_indent_aligned_decrease.hxtest new file mode 100644 index 00000000..eef0ae23 --- /dev/null +++ b/test/testcases/indentation/issue_298_sharp_error_indent_aligned_decrease.hxtest @@ -0,0 +1,38 @@ +{ + "indentation": { + "conditionalPolicy": "alignedDecrease" + } +} + +--- + +#if cs +#error 'should be indented if using indentation.conditionalPolicy = "alignedDecrease"' +#end +class Main { +#if cs +#error 'should be indented if using indentation.conditionalPolicy = "alignedDecrease"' +#end + public function new (){ + #if cs +#error 'should be indented if using indentation.conditionalPolicy = "alignedDecrease"' +#end + + } +} + +--- + +#if cs +#error 'should be indented if using indentation.conditionalPolicy = "alignedDecrease"' +#end +class Main { +#if cs + #error 'should be indented if using indentation.conditionalPolicy = "alignedDecrease"' +#end + public function new() { + #if cs + #error 'should be indented if using indentation.conditionalPolicy = "alignedDecrease"' + #end + } +} diff --git a/test/testcases/indentation/issue_298_sharp_error_indent_aligned_increase.hxtest b/test/testcases/indentation/issue_298_sharp_error_indent_aligned_increase.hxtest new file mode 100644 index 00000000..eee4987a --- /dev/null +++ b/test/testcases/indentation/issue_298_sharp_error_indent_aligned_increase.hxtest @@ -0,0 +1,38 @@ +{ + "indentation": { + "conditionalPolicy": "alignedIncrease" + } +} + +--- + +#if cs +#error 'should be indented if using indentation.conditionalPolicy = "alignedDecrease"' +#end +class Main { +#if cs +#error 'should be indented if using indentation.conditionalPolicy = "alignedDecrease"' +#end + public function new (){ + #if cs +#error 'should be indented if using indentation.conditionalPolicy = "alignedDecrease"' +#end + + } +} + +--- + +#if cs + #error 'should be indented if using indentation.conditionalPolicy = "alignedDecrease"' +#end +class Main { + #if cs + #error 'should be indented if using indentation.conditionalPolicy = "alignedDecrease"' + #end + public function new() { + #if cs + #error 'should be indented if using indentation.conditionalPolicy = "alignedDecrease"' + #end + } +} diff --git a/test/testcases/indentation/issue_304_expression_if_indentation_keep.hxtest b/test/testcases/indentation/issue_304_expression_if_indentation_keep.hxtest new file mode 100644 index 00000000..b68150a6 --- /dev/null +++ b/test/testcases/indentation/issue_304_expression_if_indentation_keep.hxtest @@ -0,0 +1,27 @@ +{ + "sameLine": { + "expressionIf": "keep" + } +} + +--- + +class Main { + public function new (){ + var a = if (true) 10; else 20; + var a = if (true) 10 else 20; + return if (true) 10 else 20; + return if (true) 10; else 20; + } +} + +--- + +class Main { + public function new() { + var a = if (true) 10; else 20; + var a = if (true) 10 else 20; + return if (true) 10 else 20; + return if (true) 10; else 20; + } +} diff --git a/test/testcases/indentation/issue_304_expression_if_indentation_next.hxtest b/test/testcases/indentation/issue_304_expression_if_indentation_next.hxtest new file mode 100644 index 00000000..9b358461 --- /dev/null +++ b/test/testcases/indentation/issue_304_expression_if_indentation_next.hxtest @@ -0,0 +1,24 @@ +{ + "sameLine": { + "expressionIf": "next" + } +} + +--- + +class Main { + public function new (){ + var a = if (true) 10; else 20; + } +} + +--- + +class Main { + public function new() { + var a = if (true) + 10; + else + 20; + } +} diff --git a/test/testcases/indentation/issue_305_object_literal.hxtest b/test/testcases/indentation/issue_305_object_literal.hxtest new file mode 100644 index 00000000..f625a1a8 --- /dev/null +++ b/test/testcases/indentation/issue_305_object_literal.hxtest @@ -0,0 +1,31 @@ +{ + "indentation": { + "indentObjectLiteral": false + } +} + +--- + +class Main { + public function new (){ + var mockFunc:Function = + { + expr: macro [], + ret: ret.toComplexType(), + args: arg.map(function (a) return (( + {name: a.name, type: a.t.toComplexType()}):FunctionArg)) + } + } +} + +--- + +class Main { + public function new() { + var mockFunc:Function = { + expr: macro [], + ret: ret.toComplexType(), + args: arg.map(function(a) return (({name: a.name, type: a.t.toComplexType()}):FunctionArg)) + } + } +} diff --git a/test/testcases/indentation/issue_305_object_literal_curly_both.hxtest b/test/testcases/indentation/issue_305_object_literal_curly_both.hxtest new file mode 100644 index 00000000..85f75f8a --- /dev/null +++ b/test/testcases/indentation/issue_305_object_literal_curly_both.hxtest @@ -0,0 +1,37 @@ +{ + "indentation": { + "indentObjectLiteral": false + }, + "lineEnds": { + "leftCurly": "both" + } +} + +--- + +class Main { + public function new (){ + var mockFunc:Function = + { + expr: macro [], + ret: ret.toComplexType(), + args: arg.map(function (a) return (( + {name: a.name, type: a.t.toComplexType()}):FunctionArg)) + } + } +} + +--- + +class Main +{ + public function new() + { + var mockFunc:Function = + { + expr: macro [], + ret: ret.toComplexType(), + args: arg.map(function(a) return (({name: a.name, type: a.t.toComplexType()}):FunctionArg)) + } + } +} diff --git a/test/testcases/indentation/issue_305_object_literal_indent_curly_both.hxtest b/test/testcases/indentation/issue_305_object_literal_indent_curly_both.hxtest new file mode 100644 index 00000000..63c3bef0 --- /dev/null +++ b/test/testcases/indentation/issue_305_object_literal_indent_curly_both.hxtest @@ -0,0 +1,37 @@ +{ + "indentation": { + "indentObjectLiteral": true + }, + "lineEnds": { + "leftCurly": "both" + } +} + +--- + +class Main { + public function new (){ + var mockFunc:Function = + { + expr: macro [], + ret: ret.toComplexType(), + args: arg.map(function (a) return (( + {name: a.name, type: a.t.toComplexType()}):FunctionArg)) + } + } +} + +--- + +class Main +{ + public function new() + { + var mockFunc:Function = + { + expr: macro [], + ret: ret.toComplexType(), + args: arg.map(function(a) return (({name: a.name, type: a.t.toComplexType()}):FunctionArg)) + } + } +} diff --git a/test/testcases/lineends/issue_301_typedef_anon_type.hxtest b/test/testcases/lineends/issue_301_typedef_anon_type.hxtest new file mode 100644 index 00000000..f83ad85b --- /dev/null +++ b/test/testcases/lineends/issue_301_typedef_anon_type.hxtest @@ -0,0 +1,48 @@ +{ + "lineEnds": { + "leftCurly": "both" + } +} + +--- + +typedef Point2D = { + x:Int, + y:Int + }; +typedef Point3D = {x:Int, y:Int, z:Int}; + +class A { + var a:{x:Int, y:Int, z:Int}; + var a:{ + x:Int, + y:Int, + z:Int + }; +} + +--- + +typedef Point2D = +{ + x:Int, + y:Int +}; + +typedef Point3D = +{ + x:Int, + y:Int, + z:Int +}; + +class A +{ + var a:{x:Int, y:Int, z:Int}; + var a: + { + x:Int, + y:Int, + z:Int + }; +} diff --git a/test/testcases/sameline/issue_306_case_bropen_keep.hxtest b/test/testcases/sameline/issue_306_case_bropen_keep.hxtest new file mode 100644 index 00000000..feb2fddb --- /dev/null +++ b/test/testcases/sameline/issue_306_case_bropen_keep.hxtest @@ -0,0 +1,73 @@ +{ + "wrapping": { + "maxLineLength": 1600 + }, + "sameLine": { + "caseBody": "keep", + "expressionCase": "keep" + } +} + +--- + +class Main { + public static function main() { + switch f + { + case + {name: name, kind: FVar(AccCall, AccCall)} + : macro callbacks.push(model.observables.$name.bind({direct: direct}, onPropertyChange.bind($v{name}))); + case _: continue; + } + switch f + { + case + {name: name, kind: FVar(AccCall, AccCall)} + : macro callbacks.push(model.observables.$name.bind({direct: direct}, onPropertyChange.bind($v{name}))); + case _: continue; + } + return switch f + { + case + {name: name, kind: FVar(AccCall, AccCall)}: + macro callbacks.push(model.observables.$name.bind({direct: direct}, onPropertyChange.bind($v{name}))); + case _: + continue; + } + return switch f + { + case + {name: name, kind: FVar(AccCall, AccCall)}: + macro callbacks.push(model.observables.$name.bind({direct: direct}, onPropertyChange.bind($v{name}))); + case _: + continue; + } + } +} + +--- + +class Main { + public static function main() { + switch f { + case {name: name, kind: FVar(AccCall, AccCall)}: macro callbacks.push(model.observables.$name.bind({direct: direct}, onPropertyChange.bind($v{name}))); + case _: continue; + } + switch f { + case {name: name, kind: FVar(AccCall, AccCall)}: macro callbacks.push(model.observables.$name.bind({direct: direct}, onPropertyChange.bind($v{name}))); + case _: continue; + } + return switch f { + case {name: name, kind: FVar(AccCall, AccCall)}: + macro callbacks.push(model.observables.$name.bind({direct: direct}, onPropertyChange.bind($v{name}))); + case _: + continue; + } + return switch f { + case {name: name, kind: FVar(AccCall, AccCall)}: + macro callbacks.push(model.observables.$name.bind({direct: direct}, onPropertyChange.bind($v{name}))); + case _: + continue; + } + } +} diff --git a/test/testcases/sameline/issue_306_case_bropen_next.hxtest b/test/testcases/sameline/issue_306_case_bropen_next.hxtest new file mode 100644 index 00000000..955a63ff --- /dev/null +++ b/test/testcases/sameline/issue_306_case_bropen_next.hxtest @@ -0,0 +1,49 @@ +{ + "wrapping": { + "maxLineLength": 1600 + }, + "sameLine": { + "caseBody": "next", + "expressionCase": "next" + } +} + +--- + +class Main { + public static function main() { + switch f + { + case + {name: name, kind: FVar(AccCall, AccCall)} + : macro callbacks.push(model.observables.$name.bind({direct: direct}, onPropertyChange.bind($v{name}))); + case _: continue; + } + return switch f + { + case + {name: name, kind: FVar(AccCall, AccCall)} + : macro callbacks.push(model.observables.$name.bind({direct: direct}, onPropertyChange.bind($v{name}))); + case _: continue; + } + } +} + +--- + +class Main { + public static function main() { + switch f { + case {name: name, kind: FVar(AccCall, AccCall)}: + macro callbacks.push(model.observables.$name.bind({direct: direct}, onPropertyChange.bind($v{name}))); + case _: + continue; + } + return switch f { + case {name: name, kind: FVar(AccCall, AccCall)}: + macro callbacks.push(model.observables.$name.bind({direct: direct}, onPropertyChange.bind($v{name}))); + case _: + continue; + } + } +} diff --git a/test/testcases/sameline/issue_306_case_bropen_same.hxtest b/test/testcases/sameline/issue_306_case_bropen_same.hxtest new file mode 100644 index 00000000..24eb37c8 --- /dev/null +++ b/test/testcases/sameline/issue_306_case_bropen_same.hxtest @@ -0,0 +1,45 @@ +{ + "wrapping": { + "maxLineLength": 1600 + }, + "sameLine": { + "caseBody": "same", + "expressionCase": "same" + } +} + +--- + +class Main { + public static function main() { + switch f + { + case + {name: name, kind: FVar(AccCall, AccCall)} + : macro callbacks.push(model.observables.$name.bind({direct: direct}, onPropertyChange.bind($v{name}))); + case _: continue; + } + return switch f + { + case + {name: name, kind: FVar(AccCall, AccCall)} + : macro callbacks.push(model.observables.$name.bind({direct: direct}, onPropertyChange.bind($v{name}))); + case _: continue; + } + } +} + +--- + +class Main { + public static function main() { + switch f { + case {name: name, kind: FVar(AccCall, AccCall)}: macro callbacks.push(model.observables.$name.bind({direct: direct}, onPropertyChange.bind($v{name}))); + case _: continue; + } + return switch f { + case {name: name, kind: FVar(AccCall, AccCall)}: macro callbacks.push(model.observables.$name.bind({direct: direct}, onPropertyChange.bind($v{name}))); + case _: continue; + } + } +} diff --git a/test/testcases/whitespace/issue_308_whitespace_after_comma.hxtest b/test/testcases/whitespace/issue_308_whitespace_after_comma.hxtest new file mode 100644 index 00000000..7d4fb6f4 --- /dev/null +++ b/test/testcases/whitespace/issue_308_whitespace_after_comma.hxtest @@ -0,0 +1,18 @@ +{} + + +--- + +class Main { + public static function main() { + foo(a, (b, c) -> d); + } +} + +--- + +class Main { + public static function main() { + foo(a, (b, c) -> d); + } +} diff --git a/test/testcases/wrapping/issue_299_opboolchain_fill.hxtest b/test/testcases/wrapping/issue_299_opboolchain_fill.hxtest new file mode 100644 index 00000000..d732231e --- /dev/null +++ b/test/testcases/wrapping/issue_299_opboolchain_fill.hxtest @@ -0,0 +1,44 @@ +{ + "wrapping": { + "maxLineLength": 160, + "opBoolChain": { + "defaultWrap": "fillLine", + "defaultLocation": "beforeLast" + } + } +} + +--- + +class Main { + static function main() { + return INSECURE_PORT == 10 + && SECURE_PORT == 20 + && INSECURE_PORT == 10 + && SECURE_PORT == 20 + && INSECURE_PORT == 10 + && SECURE_PORT == 20 + && INSECURE_PORT == 10 + && SECURE_PORT == 20; + return + INSECURE_PORT == 10 + && SECURE_PORT == 20 + && INSECURE_PORT == 10 + && SECURE_PORT == 20 + && INSECURE_PORT == 10 + && SECURE_PORT == 20 + && INSECURE_PORT == 10 + && SECURE_PORT == 20; + } +} + +--- + +class Main { + static function main() { + return INSECURE_PORT == 10 && SECURE_PORT == 20 && INSECURE_PORT == 10 && SECURE_PORT == 20 && INSECURE_PORT == 10 && SECURE_PORT == 20 + && INSECURE_PORT == 10 && SECURE_PORT == 20; + return INSECURE_PORT == 10 && SECURE_PORT == 20 && INSECURE_PORT == 10 && SECURE_PORT == 20 && INSECURE_PORT == 10 && SECURE_PORT == 20 + && INSECURE_PORT == 10 && SECURE_PORT == 20; + } +} diff --git a/test/testcases/wrapping/issue_299_opboolchain_keep.hxtest b/test/testcases/wrapping/issue_299_opboolchain_keep.hxtest new file mode 100644 index 00000000..6003483c --- /dev/null +++ b/test/testcases/wrapping/issue_299_opboolchain_keep.hxtest @@ -0,0 +1,41 @@ +{ + "wrapping": { + "maxLineLength": 160, + "opBoolChain": { + "defaultWrap": "keep", + "defaultLocation": "beforeLast" + } + } +} + +--- + +class Main { + static function main() { + return INSECURE_PORT == 10 + && SECURE_PORT == 20 + && INSECURE_PORT == 10 + && SECURE_PORT == 20; + return + INSECURE_PORT == 10 + && SECURE_PORT == 20 + && INSECURE_PORT == 10 + && SECURE_PORT == 20; + } +} + +--- + +class Main { + static function main() { + return INSECURE_PORT == 10 + && SECURE_PORT == 20 + && INSECURE_PORT == 10 + && SECURE_PORT == 20; + return + INSECURE_PORT == 10 + && SECURE_PORT == 20 + && INSECURE_PORT == 10 + && SECURE_PORT == 20; + } +} diff --git a/test/testcases/wrapping/issue_299_opboolchain_one_line.hxtest b/test/testcases/wrapping/issue_299_opboolchain_one_line.hxtest new file mode 100644 index 00000000..125fbfd7 --- /dev/null +++ b/test/testcases/wrapping/issue_299_opboolchain_one_line.hxtest @@ -0,0 +1,42 @@ +{ + "wrapping": { + "maxLineLength": 160, + "opBoolChain": { + "defaultWrap": "onePerLine", + "defaultLocation": "beforeLast" + } + } +} + +--- + +class Main { + static function main() { + return INSECURE_PORT == 10 + && SECURE_PORT == 20 + && INSECURE_PORT == 10 + && SECURE_PORT == 20; + return + INSECURE_PORT == 10 + && SECURE_PORT == 20 + && INSECURE_PORT == 10 + && SECURE_PORT == 20; + } +} + +--- + +class Main { + static function main() { + return + INSECURE_PORT == 10 + && SECURE_PORT == 20 + && INSECURE_PORT == 10 + && SECURE_PORT == 20; + return + INSECURE_PORT == 10 + && SECURE_PORT == 20 + && INSECURE_PORT == 10 + && SECURE_PORT == 20; + } +} diff --git a/test/testcases/wrapping/issue_299_opboolchain_one_line_after.hxtest b/test/testcases/wrapping/issue_299_opboolchain_one_line_after.hxtest new file mode 100644 index 00000000..a08ce747 --- /dev/null +++ b/test/testcases/wrapping/issue_299_opboolchain_one_line_after.hxtest @@ -0,0 +1,40 @@ +{ + "wrapping": { + "maxLineLength": 160, + "opBoolChain": { + "defaultWrap": "onePerLineAfterFirst", + "defaultLocation": "beforeLast" + } + } +} + +--- + +class Main { + static function main() { + return INSECURE_PORT == 10 + && SECURE_PORT == 20 + && INSECURE_PORT == 10 + && SECURE_PORT == 20; + return + INSECURE_PORT == 10 + && SECURE_PORT == 20 + && INSECURE_PORT == 10 + && SECURE_PORT == 20; + } +} + +--- + +class Main { + static function main() { + return INSECURE_PORT == 10 + && SECURE_PORT == 20 + && INSECURE_PORT == 10 + && SECURE_PORT == 20; + return INSECURE_PORT == 10 + && SECURE_PORT == 20 + && INSECURE_PORT == 10 + && SECURE_PORT == 20; + } +}