Skip to content

Commit

Permalink
added getBkOpenType utils function
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexHaxe committed Feb 10, 2024
1 parent 6f21943 commit 60b579f
Show file tree
Hide file tree
Showing 7 changed files with 257 additions and 7 deletions.
7 changes: 5 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

## dev branch / next version (1.x.x)

- fixed empty switch cases with comments
## version 1.2.11 (2024-02-10)

- Added getBkOpenType utils function
- Fixed empty switch cases with comments

## version 1.2.10 (2023-05-21)

- fixed extends handling in interfaces
- Fixed extends handling in interfaces

## version 1.2.9 (2023-05-21)

Expand Down
4 changes: 2 additions & 2 deletions haxelib.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
"contributors": [
"AlexHaxe"
],
"releasenote": "fixed extends handling in interfaces - see CHANGELOG for details",
"version": "1.2.10",
"releasenote": "fixed empty switch cases with comments; added getBkOpenType utils function - see CHANGELOG for details",
"version": "1.2.11",
"url": "https://github.com/HaxeCheckstyle/tokentree",
"dependencies": {}
}
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tokentree",
"version": "1.2.10",
"version": "1.2.11",
"description": "TokenTree library used by haxe-checkstyle, haxe-formatter and haxe-languageserver",
"repository": {
"type": "git",
Expand Down
2 changes: 2 additions & 0 deletions src/tokentree/TokenTree.hx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package tokentree;

import tokentree.utils.TokenTreeCheckUtils.ArrowType;
import tokentree.utils.TokenTreeCheckUtils.BkOpenType;
import tokentree.utils.TokenTreeCheckUtils.BrOpenType;
import tokentree.utils.TokenTreeCheckUtils.ColonType;
import tokentree.utils.TokenTreeCheckUtils.POpenType;
Expand Down Expand Up @@ -174,6 +175,7 @@ enum FilterResult {

typedef TokenTypeCache = {
@:optional var brOpenType:Null<BrOpenType>;
@:optional var bkOpenType:Null<BkOpenType>;
@:optional var pOpenType:Null<POpenType>;
@:optional var colonType:Null<ColonType>;
@:optional var arrowType:Null<ArrowType>;
Expand Down
77 changes: 77 additions & 0 deletions src/tokentree/utils/TokenTreeCheckUtils.hx
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,75 @@ class TokenTreeCheckUtils {
return ObjectDecl;
}

public static function getBkOpenType(token:TokenTree):BkOpenType {
if (token == null) {
return Unknown;
}
if (token.tokenTypeCache.bkOpenType != null) {
return token.tokenTypeCache.bkOpenType;
}

var type:BkOpenType = determineBkOpenType(token);
token.tokenTypeCache.bkOpenType = type;
return type;
}

static function determineBkOpenType(token:TokenTree):BkOpenType {
if (token == null) {
return Unknown;
}
var parent:TokenTree = token.parent;
if (parent == null || parent.tok == Root) {
return determinBkChildren(token);
}
return switch (parent.tok) {
case Kwd(KwdThis): ArrayAccess;
case BkOpen | BrOpen | POpen: determinBkChildren(token);
case DblDot: determinBkChildren(token);
case Binop(_): determinBkChildren(token);
case Kwd(_): determinBkChildren(token);
case Sharp(_): determinBkChildren(token);
default: ArrayAccess;
}
}

static function determinBkChildren(token:TokenTree):BkOpenType {
if (!token.hasChildren()) {
return Unknown;
}
for (child in token.children) {
switch (child.tok) {
case Comment(_) | CommentLine(_):
case Kwd(KwdFor) | Kwd(KwdWhile):
return Comprehension;
default:
break;
}
}
var bkDepth:Int = -1;
var childArrows:Array<TokenTree> = token.filterCallback(function(token:TokenTree, index:Int):FilterResult {
return switch (token.tok) {
case Binop(OpArrow): if (bkDepth == 0) {
FoundSkipSubtree;
}
else {
SkipSubtree;
}
case BkOpen:
bkDepth++;
GoDeeper;
case BkClose:
bkDepth--;
GoDeeper;
default: GoDeeper;
}
});
if (childArrows.length > 0) {
return MapLiteral;
}
return ArrayLiteral;
}

public static function getPOpenType(token:TokenTree):POpenType {
if (token == null) {
return Expression;
Expand Down Expand Up @@ -1059,6 +1128,14 @@ enum BrOpenType {
Unknown;
}

enum BkOpenType {
ArrayAccess;
ArrayLiteral;
Comprehension;
MapLiteral;
Unknown;
}

enum POpenType {
At;
Parameter;
Expand Down
168 changes: 168 additions & 0 deletions test/tokentree/utils/TokenTreeCheckUtilsTest.hx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import haxe.PosInfos;
import tokentree.TokenTree.FilterResult;
import tokentree.TokenTreeBuilderParsingTest.TokenTreeBuilderParsingTests;
import tokentree.utils.TokenTreeCheckUtils.ArrowType;
import tokentree.utils.TokenTreeCheckUtils.BkOpenType;
import tokentree.utils.TokenTreeCheckUtils.BrOpenType;
import tokentree.utils.TokenTreeCheckUtils.ColonType;
import tokentree.utils.TokenTreeCheckUtils.POpenType;
Expand Down Expand Up @@ -628,6 +629,111 @@ class TokenTreeCheckUtilsTest implements ITest {
Assert.isFalse(TokenTreeCheckUtils.isMetadata(tokens[index++]));
}

public function testMixedBkOpenTypes() {
var root:TokenTree = assertCodeParses(TokenTreeCheckUtilsTests.MIXED_BKOPEN_TYPES);
Assert.isFalse(root.inserted);

var allBk:Array<TokenTree> = root.filterCallback(function(token:TokenTree, depth:Int):FilterResult {
return switch (token.tok) {
case BkOpen: FoundGoDeeper;
default: GoDeeper;
}
});
Assert.equals(43, allBk.length);
var index:Int = 0;

// a[1];
Assert.equals(BkOpenType.ArrayAccess, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
// a['xx'];
Assert.equals(BkOpenType.ArrayAccess, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
// call()['xx'];
Assert.equals(BkOpenType.ArrayAccess, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
// this['xx'];
Assert.equals(BkOpenType.ArrayAccess, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));

// var a = [];
Assert.equals(BkOpenType.ArrayLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));

// var a = [1, 2, 3, 4];
Assert.equals(BkOpenType.ArrayLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
// var a = {a: [1, 2, 3, 4]};
Assert.equals(BkOpenType.ArrayLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));

// var a = [{a:1}, {a:2}, {a:3}, {a:4}];
Assert.equals(BkOpenType.ArrayLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
// var a = [{a: [1, 2, 3]}, {a: [1, 2, 3]}, {a: [1, 2, 3]}, {a: [1, 2, 3]}];
Assert.equals(BkOpenType.ArrayLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
Assert.equals(BkOpenType.ArrayLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
Assert.equals(BkOpenType.ArrayLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
Assert.equals(BkOpenType.ArrayLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
Assert.equals(BkOpenType.ArrayLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));

// var a = [[1], [2], [3], [4]];
Assert.equals(BkOpenType.ArrayLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
Assert.equals(BkOpenType.ArrayLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
Assert.equals(BkOpenType.ArrayLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
Assert.equals(BkOpenType.ArrayLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
Assert.equals(BkOpenType.ArrayLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));

// if (false) return [1, 2, 3, 4];
Assert.equals(BkOpenType.ArrayLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));

// var a = [for (i in 0...10) i];
Assert.equals(BkOpenType.Comprehension, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
// var a = [while (i < 10) i++];
Assert.equals(BkOpenType.Comprehension, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
// var a = [for (a in 1...11) for (b in 2...4) if (a % b == 0) a + "/" + b];
Assert.equals(BkOpenType.Comprehension, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));

// var a = [for (i in 0...5) i => 'number ${i}'];
Assert.equals(BkOpenType.Comprehension, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
// var a = [/* comment */for (i in 0...10) i];
Assert.equals(BkOpenType.Comprehension, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
// var a = [while (i < 5) i => 'number ${i++}'];
Assert.equals(BkOpenType.Comprehension, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
// var a = [/* comment */while (i < 10) i++];
Assert.equals(BkOpenType.Comprehension, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
// var a = [for (x in 0...5) for (y in 0...5) if (x != y) x => y];
Assert.equals(BkOpenType.Comprehension, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));

// var a = ['a' => 'aaa', 'b' => 'bbb', 'c' => 'ccc'];
Assert.equals(BkOpenType.MapLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
// var a = [{a: 1} => 'aaa', {a:2} => 'bbb', {a:3} => 'ccc'];
Assert.equals(BkOpenType.MapLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
// var a = [['a'] => 'aaa', ['b'] => 'bbb', ['c'] => 'ccc'];
Assert.equals(BkOpenType.MapLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
Assert.equals(BkOpenType.ArrayLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
Assert.equals(BkOpenType.ArrayLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
Assert.equals(BkOpenType.ArrayLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));

// var a = [['a' => 'aaa'], ['b' => 'bbb'], ['c' => 'ccc']];
Assert.equals(BkOpenType.ArrayLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
Assert.equals(BkOpenType.MapLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
Assert.equals(BkOpenType.MapLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
Assert.equals(BkOpenType.MapLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));

// var a = [if (foo) bar else foo, if (foo) bar else foo, if (foo) bar else foo];
Assert.equals(BkOpenType.ArrayLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
Assert.equals(BkOpenType.ArrayLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));

// var a = hxargs.Args.generate([
// @doc('Dont format, only check if files are formatted correctly')
// ['--check'] => function() mode = Check,
//
// #if debug
// @doc('Dont format, only check if formatting is stable')
// ['--check-stability'] => function() mode = CheckStability,
// #end
//
// @doc('Dont format, only check if files are formatted correctly')
// ['--check'] => function() mode = Check,
// ]);
Assert.equals(BkOpenType.MapLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
Assert.equals(BkOpenType.ArrayLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
Assert.equals(BkOpenType.ArrayLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
Assert.equals(BkOpenType.ArrayLiteral, TokenTreeCheckUtils.getBkOpenType(allBk[index++]));
}

@Test
public function testFindLastBinop() {
function assertLastBinop(code:String, binop:String, offset:Int = 0, ?pos:PosInfos):Void {
Expand Down Expand Up @@ -1090,4 +1196,66 @@ enum abstract TokenTreeCheckUtilsTests(String) to String {
var foo:Int;
}
";

var MIXED_BKOPEN_TYPES = "
class Main {
static function main() {
a[1];
a['xx'];
call()['xx'];
this['xx'];
var a = [];
var a = [1, 2, 3, 4];
var a = {a: [1, 2, 3, 4]};
var a = [{a:1}, {a:2}, {a:3}, {a:4}];
var a = [{a:[1, 2, 3]}, {a:[1, 2, 3]}, {a:[1, 2, 3]}, {a:[1, 2, 3]}];
var a = [[1], [2], [3], [4]];
if (false) return [1, 2, 3, 4];
var a = [for (i in 0...10) i];
var a = [/* comment */ for (i in 0...10) i];
var a = [while (i < 10) i++];
var a = [/* comment */ while (i < 10) i++];
var a = [for (a in 1...11) for (b in 2...4) if (a % b == 0) a + ' / ' + b];
var a = [for (i in 0...5) i => 'number ${i}'];
var a = [while (i < 5) i => 'number ${i++}'];
var a = [for (x in 0...5) for (y in 0...5) if (x != y) x => y];
var a = ['a' => 'aaa', 'b' => 'bbb', 'c' => 'ccc'];
var a = [{a: 1} => 'aaa', {a:2} => 'bbb', {a:3} => 'ccc'];
var a = [['a'] => 'aaa', ['b'] => 'bbb', ['c'] => 'ccc'];
var a = [['a' => 'aaa'], ['b' => 'bbb'], ['c' => 'ccc']];
var a = [if (foo) bar else foo, if (foo) bar else foo, if (foo) bar else foo];
var a = function () {
[
if (foo) bar else foo,
if (foo) bar else foo,
if (foo) bar else foo,
if (foo) bar else foo,
if (foo) bar else foo
];
}
var a = hxargs.Args.generate([
@doc('Dont format, only check if files are formatted correctly')
['--check'] => function() mode = Check,
#if debug
@doc('Dont format, only check if formatting is stable')
['--check-stability'] => function() mode = CheckStability,
#end
@doc('Dont format, only check if files are formatted correctly')
['--check'] => function() mode = Check,
]);
}
}
";
}

0 comments on commit 60b579f

Please sign in to comment.