From ba76d002e197030c69036dcda772f5bc49bd74d8 Mon Sep 17 00:00:00 2001 From: AlexHaxe Date: Fri, 6 Sep 2019 21:11:52 +0200 Subject: [PATCH] fixed TokenList.getTokenAtOffset (#526) --- src/formatter/codedata/TokenList.hx | 26 ++------- test/TestSuite.hx | 2 + test/formatter/codedata/TokenListTest.hx | 71 ++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 21 deletions(-) create mode 100644 test/formatter/codedata/TokenListTest.hx diff --git a/src/formatter/codedata/TokenList.hx b/src/formatter/codedata/TokenList.hx index 95ed3248..99320836 100644 --- a/src/formatter/codedata/TokenList.hx +++ b/src/formatter/codedata/TokenList.hx @@ -91,38 +91,22 @@ class TokenList { } public function getTokenAtOffset(off:Int):Null { - var lowerBound:Int = 0; - var upperBound:Int = tokens.length - 1; if (tokens.length <= 0) { throw BAD_OFFSET; } - if (off < 0) { throw BAD_OFFSET; } - - if (off > tokens[upperBound].token.pos.max) { + if (off > tokens[tokens.length - 1].token.pos.max) { throw BAD_OFFSET; } - while (true) { - if (lowerBound > upperBound) { - throw BAD_OFFSET; - } - - var center:Int = lowerBound + Math.floor((upperBound - lowerBound) / 2); - var matchLeft:Bool = tokens[center].token.pos.min <= off; - var matchRight:Bool = tokens[center].token.pos.max >= off; - if (matchLeft && matchRight) { - return tokens[center]; - } - if (matchLeft) { - lowerBound = center + 1; + for (token in tokens) { + if (token == null) { continue; } - if (matchRight) { - upperBound = center - 1; - continue; + if (token.token.pos.max >= off) { + return token; } } throw BAD_OFFSET; diff --git a/test/TestSuite.hx b/test/TestSuite.hx index 368eb0ca..128b3918 100644 --- a/test/TestSuite.hx +++ b/test/TestSuite.hx @@ -1,4 +1,5 @@ import formatter.FormatStatsTest; +import formatter.codedata.TokenListTest; import testcases.EmptyLinesTestCases; import testcases.ExpressionLevelTestCases; import testcases.IndentationTestCases; @@ -17,6 +18,7 @@ class TestSuite extends massive.munit.TestSuite { if (!singleRun.isSingleRun()) { add(SelfTest); add(FormatStatsTest); + add(TokenListTest); } add(EmptyLinesTestCases); diff --git a/test/formatter/codedata/TokenListTest.hx b/test/formatter/codedata/TokenListTest.hx new file mode 100644 index 00000000..01b9fa1d --- /dev/null +++ b/test/formatter/codedata/TokenListTest.hx @@ -0,0 +1,71 @@ +package formatter.codedata; + +import haxe.PosInfos; +import haxe.io.Bytes; +import massive.munit.Assert; + +class TokenListTest { + @Test + public function testGetTokenAt() { + var tokenList:TokenList = makeTokenList(FormatStatsTestCode.CodeSample); + checkToken(tokenList, 0, 0, "class"); + checkToken(tokenList, 5, 0, "class"); + checkToken(tokenList, 7, 1, "Main"); + checkToken(tokenList, 12, 2, "{"); + checkToken(tokenList, 13, 2, "{"); + checkToken(tokenList, 14, 3, "public"); + checkToken(tokenList, 41, 9, "trace"); + } + + @Test + public function testInvalidGetTokenAt() { + var tokenList:TokenList = makeTokenList(FormatStatsTestCode.CodeSample); + try { + tokenList.getTokenAtOffset(-1); + Assert.fail("previous call should not succeed"); + } catch (e:Any) {} + try { + tokenList.getTokenAtOffset(64); + Assert.fail("previous call should not succeed"); + } catch (e:Any) {} + tokenList = makeTokenList(""); + try { + tokenList.getTokenAtOffset(1); + Assert.fail("previous call should not succeed"); + } catch (e:Any) {} + } + + function checkToken(tokenList:TokenList, offset:Int, expectedIndex:Int, expectedText:String, ?pos:PosInfos) { + var tokenInfo:Null = tokenList.getTokenAtOffset(offset); + Assert.isNotNull(tokenInfo, pos); + Assert.isNotNull(tokenInfo.token, pos); + Assert.areEqual(expectedIndex, tokenInfo.token.index, pos); + Assert.areEqual(expectedText, tokenInfo.token.toString()); + } + + function makeTokenList(code:String):TokenList { + var content:Bytes = Bytes.ofString(code); + var input:FormatterInputData = { + fileName: "test.hx", + content: content, + config: null, + entryPoint: TYPE_LEVEL, + lineSeparator: null, + range: null + } + var parsedCode:ParsedCode = new ParsedCode(input); + return parsedCode.tokenList; + } +} + +@:enum +abstract FormatStatsTestCode(String) to String { + var CodeSample = " +class Main { + + public function new () { + trace('foo'); + } +} + "; +}