mirror of
https://gitee.com/zhangsken/AndroidIDE.git
synced 2026-10-16 07:49:44 +08:00
refactor: remove unused code analyzers
This commit is contained in:
+43
-41
@@ -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}")
|
||||
}
|
||||
-144
@@ -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])
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user