refactor: remove unused code analyzers

This commit is contained in:
Akash Yadav
2023-05-25 23:10:38 +05:30
parent ceebaafadf
commit 44b1b4f614
4 changed files with 43 additions and 567 deletions
@@ -25,7 +25,6 @@ import androidx.annotation.NonNull;
import com.blankj.utilcode.util.ArrayUtils;
import com.google.common.base.Preconditions;
import com.google.common.collect.EvictingQueue;
import com.itsaky.androidide.editor.language.java.JavaAnalyzer;
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE;
import com.itsaky.androidide.utils.CharSequenceReader;
import io.github.rosemoe.sora.lang.analysis.AsyncIncrementalAnalyzeManager;
@@ -51,8 +50,8 @@ import org.antlr.v4.runtime.Token;
*
* @author Akash Yadav
*/
public abstract class BaseIncrementalAnalyzeManager
extends AsyncIncrementalAnalyzeManager<LineState, IncrementalToken> {
public abstract class BaseIncrementalAnalyzeManager extends
AsyncIncrementalAnalyzeManager<LineState, IncrementalToken> {
protected final Lexer lexer;
private final int[] multilineStartTypes;
@@ -101,8 +100,8 @@ public abstract class BaseIncrementalAnalyzeManager
}
private void verifyMultilineTypes(@NonNull final int[][] types) {
Preconditions.checkState(
types.length == 2, "There must be exact two inner int[] in multiline token types");
Preconditions.checkState(types.length == 2,
"There must be exact two inner int[] in multiline token types");
final var start = types[0];
final var end = types[1];
@@ -117,7 +116,6 @@ public abstract class BaseIncrementalAnalyzeManager
* multiline token and int[] 1 specifies tokens which end the multiline token. For example,
* <p>[['/', '*'], ['*', '/']].
* <p>But instead of characters, there must be token types.
* @see JavaAnalyzer
*/
protected abstract int[][] getMultilineTokenStartEndTypes();
@@ -139,8 +137,10 @@ public abstract class BaseIncrementalAnalyzeManager
}
@Override
public LineTokenizeResult<LineState, IncrementalToken> tokenizeLine(
final CharSequence lineText, final LineState state, final int line) {
public LineTokenizeResult<LineState, IncrementalToken> tokenizeLine(final CharSequence lineText,
final LineState state,
final int line
) {
final var tokens = new ArrayList<IncrementalToken>();
var newState = 0;
var stateObj = new LineState();
@@ -150,8 +150,8 @@ public abstract class BaseIncrementalAnalyzeManager
final var result = fillIncomplete(lineText, tokens, state.lexerMode);
newState = IntPair.getFirst(result);
if (newState == LineState.NORMAL) {
newState =
tokenizeNormal(lineText, IntPair.getSecond(result), tokens, stateObj, state.lexerMode);
newState = tokenizeNormal(lineText, IntPair.getSecond(result), tokens, stateObj,
state.lexerMode);
} else {
newState = LineState.INCOMPLETE;
}
@@ -163,7 +163,8 @@ public abstract class BaseIncrementalAnalyzeManager
@Override
public List<Span> generateSpansForLine(
final LineTokenizeResult<LineState, IncrementalToken> tokens) {
final LineTokenizeResult<LineState, IncrementalToken> tokens
) {
var result = generateSpans(tokens);
Objects.requireNonNull(result);
@@ -182,13 +183,13 @@ public abstract class BaseIncrementalAnalyzeManager
* @return The spans for the tokens.
*/
protected abstract List<Span> generateSpans(
final LineTokenizeResult<LineState, IncrementalToken> tokens);
final LineTokenizeResult<LineState, IncrementalToken> tokens
);
@Override
public List<CodeBlock> computeBlocks(
final Content text,
final AsyncIncrementalAnalyzeManager<LineState, IncrementalToken>.CodeBlockAnalyzeDelegate
delegate) {
public List<CodeBlock> computeBlocks(final Content text,
final AsyncIncrementalAnalyzeManager<LineState, IncrementalToken>.CodeBlockAnalyzeDelegate delegate
) {
final var stack = new Stack<CodeBlock>();
final var blocks = new ArrayList<CodeBlock>();
var line = 0;
@@ -196,9 +197,8 @@ public abstract class BaseIncrementalAnalyzeManager
var currSwitch = 0;
while (delegate.isNotCancelled() && line < text.getLineCount()) {
final var tokens = getState(line);
final var checkForIdentifiers =
tokens.state.state == LineState.NORMAL
|| (tokens.state.state == LineState.INCOMPLETE && tokens.tokens.size() > 1);
final var checkForIdentifiers = tokens.state.state == LineState.NORMAL ||
(tokens.state.state == LineState.INCOMPLETE && tokens.tokens.size() > 1);
if (!tokens.state.hasBraces && !checkForIdentifiers) {
line++;
continue;
@@ -282,13 +282,15 @@ public abstract class BaseIncrementalAnalyzeManager
* @param incompleteToken The token which is the start of the incomplete token.
* @param tokens The list of tokens from which extra tokens must be removed.
*/
protected void popTokensAfterIncomplete(
@NonNull IncrementalToken incompleteToken, @NonNull List<IncrementalToken> tokens) {
protected void popTokensAfterIncomplete(@NonNull IncrementalToken incompleteToken,
@NonNull List<IncrementalToken> tokens
) {
tokens.remove(tokens.size() - 1);
}
protected void handleLineCommentSpan(
@NonNull IncrementalToken token, @NonNull List<Span> spans, int offset) {
protected void handleLineCommentSpan(@NonNull IncrementalToken token, @NonNull List<Span> spans,
int offset
) {
var commentType = SchemeAndroidIDE.COMMENT;
// highlight special line comments
@@ -306,7 +308,7 @@ public abstract class BaseIncrementalAnalyzeManager
}
/**
* Called when the <code>state</code> in {@link #tokenizeLine(CharSequence, LineState)} is
* Called when the <code>state</code> in {@link #tokenizeLine(CharSequence, LineState, int)} is
* {@link LineState#NORMAL}.
*
* @param line The line source.
@@ -317,12 +319,10 @@ public abstract class BaseIncrementalAnalyzeManager
* @return The new state.
*/
@SuppressWarnings("UnstableApiUsage")
protected int tokenizeNormal(
final CharSequence line,
final int column,
final List<IncrementalToken> tokens,
final LineState st,
final int lexerMode) {
protected int tokenizeNormal(final CharSequence line, final int column,
final List<IncrementalToken> tokens, final LineState st,
final int lexerMode
) {
lexer.setInputStream(createStream(line));
if (lexer._mode != lexerMode) {
lexer.pushMode(lexerMode);
@@ -387,7 +387,7 @@ public abstract class BaseIncrementalAnalyzeManager
}
/**
* Called when the <code>state</code> in {@link #tokenizeLine(CharSequence, LineState)} is
* Called when the <code>state</code> in {@link #tokenizeLine(CharSequence, LineState, int)} is
* {@link LineState#INCOMPLETE}.
*
* @param line The line source.
@@ -395,16 +395,19 @@ public abstract class BaseIncrementalAnalyzeManager
* @return The state and offset.
*/
@SuppressWarnings("UnstableApiUsage")
protected long fillIncomplete(
CharSequence line, final List<IncrementalToken> tokens, final int lexerMode) {
protected long fillIncomplete(CharSequence line, final List<IncrementalToken> tokens,
final int lexerMode
) {
lexer.setInputStream(createStream(line));
if (lexer._mode != lexerMode) {
lexer.pushMode(lexerMode);
}
final var queue = createEvictingQueueForTokens();
final var end = queue.getSecond();
final var allTokens =
lexer.getAllTokens().stream().map(IncrementalToken::new).collect(Collectors.toList());
final var allTokens = lexer.getAllTokens()
.stream()
.map(IncrementalToken::new)
.collect(Collectors.toList());
if (allTokens.isEmpty()) {
return IntPair.pack(LineState.INCOMPLETE, 0);
}
@@ -437,16 +440,15 @@ public abstract class BaseIncrementalAnalyzeManager
@SuppressWarnings("UnstableApiUsage")
@NonNull
private Pair<EvictingQueue<IncrementalToken>, EvictingQueue<IncrementalToken>>
createEvictingQueueForTokens() {
return new Pair<>(
EvictingQueue.create(multilineStartTypes.length),
private Pair<EvictingQueue<IncrementalToken>, EvictingQueue<IncrementalToken>> createEvictingQueueForTokens() {
return new Pair<>(EvictingQueue.create(multilineStartTypes.length),
EvictingQueue.create(multilineEndTypes.length));
}
@SuppressWarnings("UnstableApiUsage")
private boolean matchTokenTypes(
@NonNull int[] types, @NonNull EvictingQueue<IncrementalToken> tokens) {
private boolean matchTokenTypes(@NonNull int[] types,
@NonNull EvictingQueue<IncrementalToken> tokens
) {
final var arr = tokens.toArray(new IncrementalToken[0]);
for (int i = 0; i < types.length; i++) {
if (types[i] != arr[i].getType()) {
@@ -1,193 +0,0 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.editor.language.java
import com.itsaky.androidide.editor.language.incremental.BaseIncrementalAnalyzeManager
import com.itsaky.androidide.editor.language.incremental.IncrementalToken
import com.itsaky.androidide.editor.language.incremental.LineState
import com.itsaky.androidide.lexers.java.JavaLexer
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE.ANNOTATION
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE.LITERAL
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE.OPERATOR
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE.TEXT_NORMAL
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE.TYPE_NAME
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE.forComment
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE.forKeyword
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE.forString
import com.itsaky.androidide.utils.ILogger
import io.github.rosemoe.sora.lang.analysis.IncrementalAnalyzeManager.LineTokenizeResult
import io.github.rosemoe.sora.lang.styling.Span
import io.github.rosemoe.sora.lang.styling.TextStyle.makeStyle
/** @author Akash Yadav */
class JavaAnalyzer : BaseIncrementalAnalyzeManager(JavaLexer::class.java) {
private val log = ILogger.newInstance(javaClass.simpleName)
override fun getCodeBlockTokens(): IntArray = intArrayOf(JavaLexer.LBRACE, JavaLexer.RBRACE)
override fun generateSpans(
tokens: LineTokenizeResult<LineState, IncrementalToken>,
): List<Span> {
val spans = mutableListOf<Span>()
var previous = JavaLexer.WS
var first = true
for (token in tokens.tokens) {
val type = token.type
val offset = token.startIndex
when (type) {
JavaLexer.WS -> {
if (first) {
spans.add(Span.obtain(offset, makeStyle(TEXT_NORMAL)))
first = false
}
}
JavaLexer.ABSTRACT,
JavaLexer.ASSERT,
JavaLexer.BREAK,
JavaLexer.CASE,
JavaLexer.CATCH,
JavaLexer.CLASS,
JavaLexer.CONST,
JavaLexer.CONTINUE,
JavaLexer.DEFAULT,
JavaLexer.DO,
JavaLexer.ELSE,
JavaLexer.EXTENDS,
JavaLexer.FINAL,
JavaLexer.FINALLY,
JavaLexer.FOR,
JavaLexer.IF,
JavaLexer.GOTO,
JavaLexer.IMPLEMENTS,
JavaLexer.IMPORT,
JavaLexer.INSTANCEOF,
JavaLexer.INTERFACE,
JavaLexer.NATIVE,
JavaLexer.NEW,
JavaLexer.PACKAGE,
JavaLexer.PRIVATE,
JavaLexer.PROTECTED,
JavaLexer.PUBLIC,
JavaLexer.RETURN,
JavaLexer.STATIC,
JavaLexer.STRICTFP,
JavaLexer.SUPER,
JavaLexer.SWITCH,
JavaLexer.SYNCHRONIZED,
JavaLexer.THIS,
JavaLexer.THROW,
JavaLexer.THROWS,
JavaLexer.TRANSIENT,
JavaLexer.TRY,
JavaLexer.VOID,
JavaLexer.VOLATILE,
JavaLexer.WHILE,
JavaLexer.VAR, -> spans.add(Span.obtain(offset, forKeyword()))
JavaLexer.DECIMAL_LITERAL,
JavaLexer.HEX_LITERAL,
JavaLexer.OCT_LITERAL,
JavaLexer.BINARY_LITERAL,
JavaLexer.FLOAT_LITERAL,
JavaLexer.HEX_FLOAT_LITERAL,
JavaLexer.BOOL_LITERAL,
JavaLexer.CHAR_LITERAL,
JavaLexer.NULL_LITERAL, -> spans.add(Span.obtain(offset, makeStyle(LITERAL)))
JavaLexer.STRING_LITERAL -> spans.add(Span.obtain(offset, forString()))
JavaLexer.LPAREN,
JavaLexer.RPAREN,
JavaLexer.LBRACK,
JavaLexer.RBRACK,
JavaLexer.SEMI,
JavaLexer.COMMA,
JavaLexer.ASSIGN,
JavaLexer.GT,
JavaLexer.LT,
JavaLexer.BANG,
JavaLexer.TILDE,
JavaLexer.QUESTION,
JavaLexer.COLON,
JavaLexer.EQUAL,
JavaLexer.GE,
JavaLexer.LE,
JavaLexer.NOTEQUAL,
JavaLexer.AND,
JavaLexer.OR,
JavaLexer.INC,
JavaLexer.DEC,
JavaLexer.ADD,
JavaLexer.SUB,
JavaLexer.MUL,
JavaLexer.DIV,
JavaLexer.BITAND,
JavaLexer.BITOR,
JavaLexer.CARET,
JavaLexer.MOD,
JavaLexer.ADD_ASSIGN,
JavaLexer.SUB_ASSIGN,
JavaLexer.MUL_ASSIGN,
JavaLexer.DIV_ASSIGN,
JavaLexer.AND_ASSIGN,
JavaLexer.OR_ASSIGN,
JavaLexer.XOR_ASSIGN,
JavaLexer.MOD_ASSIGN,
JavaLexer.LSHIFT_ASSIGN,
JavaLexer.RSHIFT_ASSIGN,
JavaLexer.URSHIFT_ASSIGN,
JavaLexer.ARROW,
JavaLexer.COLONCOLON,
JavaLexer.ELLIPSIS,
JavaLexer.LBRACE,
JavaLexer.RBRACE,
JavaLexer.DOT, -> spans.add(Span.obtain(offset, makeStyle(OPERATOR)))
JavaLexer.BOOLEAN,
JavaLexer.BYTE,
JavaLexer.CHAR,
JavaLexer.DOUBLE,
JavaLexer.ENUM,
JavaLexer.FLOAT,
JavaLexer.INT,
JavaLexer.LONG,
JavaLexer.SHORT, -> spans.add(Span.obtain(offset, makeStyle(TYPE_NAME)))
JavaLexer.BLOCK_COMMENT -> spans.add(Span.obtain(offset, forComment()))
JavaLexer.LINE_COMMENT -> handleLineCommentSpan(token, spans, offset)
JavaLexer.AT -> spans.add(Span.obtain(offset, makeStyle(ANNOTATION)))
JavaLexer.IDENTIFIER -> {
var colorId = TEXT_NORMAL
if (previous == JavaLexer.AT) {
colorId = ANNOTATION
}
spans.add(Span.obtain(offset, makeStyle(colorId)))
}
else -> spans.add(Span.obtain(offset, makeStyle(TEXT_NORMAL)))
}
previous = type
}
return spans
}
override fun getMultilineTokenStartEndTypes(): Array<IntArray> {
val start = intArrayOf(JavaLexer.DIV, JavaLexer.MUL)
val end = intArrayOf(JavaLexer.MUL, JavaLexer.DIV)
return arrayOf(start, end)
}
override fun handleIncompleteToken(token: IncrementalToken) {
token.type = JavaLexer.BLOCK_COMMENT
}
}
@@ -1,189 +0,0 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.editor.language.xml
import android.graphics.Color
import android.graphics.Color.parseColor
import com.google.common.collect.EvictingQueue
import com.itsaky.androidide.editor.language.incremental.BaseIncrementalAnalyzeManager
import com.itsaky.androidide.editor.language.incremental.IncrementalToken
import com.itsaky.androidide.editor.language.incremental.LineState
import com.itsaky.androidide.lexers.xml.XMLLexer
import com.itsaky.androidide.lexers.xml.XMLLexer.CLOSE
import com.itsaky.androidide.lexers.xml.XMLLexer.COLON
import com.itsaky.androidide.lexers.xml.XMLLexer.COMMENT_END
import com.itsaky.androidide.lexers.xml.XMLLexer.COMMENT_START
import com.itsaky.androidide.lexers.xml.XMLLexer.CommentModeEnd
import com.itsaky.androidide.lexers.xml.XMLLexer.CommentText
import com.itsaky.androidide.lexers.xml.XMLLexer.DASH
import com.itsaky.androidide.lexers.xml.XMLLexer.EQUALS
import com.itsaky.androidide.lexers.xml.XMLLexer.NOT
import com.itsaky.androidide.lexers.xml.XMLLexer.Name
import com.itsaky.androidide.lexers.xml.XMLLexer.OPEN
import com.itsaky.androidide.lexers.xml.XMLLexer.OPEN_SLASH
import com.itsaky.androidide.lexers.xml.XMLLexer.SLASH
import com.itsaky.androidide.lexers.xml.XMLLexer.SLASH_CLOSE
import com.itsaky.androidide.lexers.xml.XMLLexer.SPECIAL_CLOSE
import com.itsaky.androidide.lexers.xml.XMLLexer.STRING
import com.itsaky.androidide.lexers.xml.XMLLexer.TEXT
import com.itsaky.androidide.lexers.xml.XMLLexer.XMLDeclOpen
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE.FIELD
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE.LITERAL
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE.OPERATOR
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE.TEXT_NORMAL
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE.XML_TAG
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE.forComment
import io.github.rosemoe.sora.lang.analysis.IncrementalAnalyzeManager.LineTokenizeResult
import io.github.rosemoe.sora.lang.styling.Span
import io.github.rosemoe.sora.lang.styling.TextStyle.makeStyle
import java.util.regex.Pattern
/**
* Syntax analyzer for XML.
*
* @author Akash Yadav
*/
class XMLAnalyzer : BaseIncrementalAnalyzeManager(XMLLexer::class.java) {
override fun getCodeBlockTokens() = intArrayOf()
override fun getMultilineTokenStartEndTypes(): Array<IntArray> {
val start = intArrayOf(COMMENT_START)
val end = intArrayOf(CommentModeEnd)
return arrayOf(start, end)
}
@Suppress("UnstableApiUsage")
override fun isIncompleteTokenEnd(q: EvictingQueue<IncrementalToken>): Boolean {
return super.isIncompleteTokenEnd(q) || q.peek()!!.getType() == COMMENT_END
}
override fun isCodeBlockStart(token: IncrementalToken): Boolean {
val type = token.getType()
return type == OPEN || type == XMLDeclOpen
}
override fun isCodeBlockEnd(token: IncrementalToken): Boolean {
val type = token.getType()
return type == OPEN_SLASH || type == SPECIAL_CLOSE || type == SLASH_CLOSE
}
override fun popTokensAfterIncomplete(
incompleteToken: IncrementalToken,
tokens: MutableList<IncrementalToken>,
) {
// Do nothing
}
override fun generateSpans(
tokens: LineTokenizeResult<LineState, IncrementalToken>,
): MutableList<Span> {
val spans = mutableListOf<Span>()
var previous = XMLLexer.SEA_WS
spans.add(Span.obtain(0, makeStyle(TEXT_NORMAL)))
for (token in tokens.tokens) {
val type = token.type
val offset = token.startIndex
when (type) {
XMLLexer.COMMENT,
COMMENT_START,
COMMENT_END,
CommentModeEnd,
CommentText, -> spans.add(Span.obtain(offset, forComment()))
OPEN,
DASH,
NOT,
OPEN_SLASH,
SLASH_CLOSE,
CLOSE,
SLASH,
SPECIAL_CLOSE,
EQUALS,
COLON,
XMLDeclOpen, -> spans.add(Span.obtain(offset, makeStyle(OPERATOR)))
STRING -> // highlight hex color line
try {
val text: String = token.text
val textVar = text.replace("\"", "")
if (isColorValue(textVar)) {
val color: Int = parseColor(textVar)
val span = Span.obtain(offset + 1, makeStyle(LITERAL))
span.setUnderlineColor(color)
spans.add(span)
val middle = Span.obtain(offset + text.length - 1, makeStyle(LITERAL))
middle.setUnderlineColor(Color.TRANSPARENT)
spans.add(middle)
val end = Span.obtain(offset + text.length, makeStyle(TEXT_NORMAL))
end.setUnderlineColor(Color.TRANSPARENT)
spans.add(end)
} else {
spans.add(Span.obtain(offset, makeStyle(LITERAL)))
}
} catch (ex: Exception) {
// This color string is not valid
spans.add(Span.obtain(offset, makeStyle(LITERAL)))
}
Name -> {
var colorId = TEXT_NORMAL
if (previous == OPEN) {
colorId = XML_TAG
} else if (previous == OPEN_SLASH) {
colorId = XML_TAG
}
val attribute: String = token.text
if (attribute.contains(":")) {
spans.add(Span.obtain(offset, makeStyle(FIELD)))
spans.add(Span.obtain(offset + attribute.indexOf(":"), makeStyle(TEXT_NORMAL)))
} else {
spans.add(Span.obtain(offset, makeStyle(colorId)))
}
}
TEXT -> // highlight hex color line
try {
val textVar: String = token.text
if (isColorValue(textVar)) {
val color: Int = parseColor(textVar)
val span = Span.obtain(offset, makeStyle(TEXT_NORMAL))
span.setUnderlineColor(color)
spans.add(span)
} else {
spans.add(Span.obtain(offset, makeStyle(TEXT_NORMAL)))
}
} catch (ex: Exception) {
// This color string is not valid
spans.add(Span.obtain(offset, makeStyle(TEXT_NORMAL)))
}
else -> spans.add(Span.obtain(offset, makeStyle(TEXT_NORMAL)))
}
if (token.getType() != XMLLexer.SEA_WS) {
previous = token.getType()
}
}
return spans
}
override fun handleIncompleteToken(token: IncrementalToken) {}
private fun isColorValue(value: String): Boolean {
return hexColorMatcher.matcher(value).matches()
}
private val hexColorMatcher: Pattern = Pattern.compile("#[a-fA-F\\d]{6,8}")
}
@@ -1,144 +0,0 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.editor.language.incremental
import com.google.common.truth.Truth.assertThat
import com.itsaky.androidide.editor.language.incremental.IncrementalToken
import com.itsaky.androidide.editor.language.incremental.LineState
import com.itsaky.androidide.editor.language.java.JavaAnalyzer
import com.itsaky.androidide.lexers.java.JavaLexer
import io.github.rosemoe.sora.lang.analysis.IncrementalAnalyzeManager.LineTokenizeResult
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
@RunWith(RobolectricTestRunner::class)
@Config(manifest = Config.NONE)
internal class BaseIncrementalAnalyzeManagerTest {
@Test
fun testSimpleTokenization() {
val analyzer = JavaAnalyzer()
val result =
analyzer.tokenizeLine(
"public static final String THIS_IS_A_STRING = \"This is a string...!\";",
analyzer.initialState,
0
)
println("New state: ${result.state}")
ensureTokenSequence(
result,
listOf(
JavaLexer.PUBLIC,
JavaLexer.WS,
JavaLexer.STATIC,
JavaLexer.WS,
JavaLexer.FINAL,
JavaLexer.WS,
JavaLexer.IDENTIFIER,
JavaLexer.WS,
JavaLexer.IDENTIFIER,
JavaLexer.WS,
JavaLexer.ASSIGN,
JavaLexer.WS,
JavaLexer.STRING_LITERAL,
JavaLexer.SEMI
)
)
}
@Test
fun testCompleteCommentTokenization() {
val analyzer = JavaAnalyzer()
val result =
analyzer.tokenizeLine("/*This is a */complete multiline comment", analyzer.initialState, 0)
assertThat(result.state.state).isEqualTo(LineState.NORMAL)
ensureTokenSequence(
result,
listOf(
JavaLexer.BLOCK_COMMENT,
JavaLexer.IDENTIFIER,
JavaLexer.WS,
JavaLexer.IDENTIFIER,
JavaLexer.WS,
JavaLexer.IDENTIFIER
)
)
}
@Test
fun testIncompleteCommentTokenization() {
val analyzer = JavaAnalyzer()
var result =
analyzer.tokenizeLine("/*This is an incomplete multiline comment", analyzer.initialState, 0)
println(result.state)
assertThat(result.state.state).isEqualTo(LineState.INCOMPLETE)
result =
analyzer.tokenizeLine(
"/*This is an incomplete*//* multiline comment",
analyzer.initialState,
0
)
println(result.state)
assertThat(result.state.state).isEqualTo(LineState.INCOMPLETE)
result =
analyzer.tokenizeLine("This is an incomplete multiline comment/*", analyzer.initialState, 0)
println(result.state)
assertThat(result.state.state).isEqualTo(LineState.INCOMPLETE)
}
@Test
fun testMultilineCommentTokenization() {
val analyzer = JavaAnalyzer()
// Test a simple multiline comment
run {
var result = analyzer.tokenizeLine("/** This is an", analyzer.initialState, 0)
assertThat(result.state.state).isEqualTo(LineState.INCOMPLETE)
result = analyzer.tokenizeLine(" incomplete comment*/", result.state, 0)
assertThat(result.state.state).isEqualTo(LineState.NORMAL)
}
// Test a multiline comment which is directly followed by tokens of other types.
run {
var result = analyzer.tokenizeLine("/** This is an", analyzer.initialState, 0)
assertThat(result.state.state).isEqualTo(LineState.INCOMPLETE)
assertThat(result.tokens.size).isEqualTo(1)
assertThat(result.tokens.first().type).isEqualTo(JavaLexer.BLOCK_COMMENT)
result = analyzer.tokenizeLine(" incomplete comment*/ public static void", result.state, 0)
assertThat(result.state.state).isEqualTo(LineState.NORMAL)
assertThat(result.tokens.last().type).isEqualTo(JavaLexer.VOID)
assertThat(result.tokens[result.tokens.lastIndex - 1].type).isEqualTo(JavaLexer.WS)
assertThat(result.tokens[result.tokens.lastIndex - 2].type).isEqualTo(JavaLexer.STATIC)
}
}
private fun ensureTokenSequence(
result: LineTokenizeResult<LineState, IncrementalToken>,
types: List<Int>
) {
for (index in types.indices) {
assertThat(result.tokens[index].type).isEqualTo(types[index])
}
}
}