diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
index af5b22e87..84d72f15f 100755
--- a/.idea/jarRepositories.xml
+++ b/.idea/jarRepositories.xml
@@ -36,5 +36,10 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index e7fbdb088..c489ddea4 100755
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -15,9 +15,10 @@
-
+
-
+
+
diff --git a/app/src/main/java/com/itsaky/androidide/DesignerActivity.java b/app/src/main/java/com/itsaky/androidide/DesignerActivity.java
index e042fa15e..a3c8fe829 100755
--- a/app/src/main/java/com/itsaky/androidide/DesignerActivity.java
+++ b/app/src/main/java/com/itsaky/androidide/DesignerActivity.java
@@ -162,7 +162,7 @@ public class DesignerActivity extends StudioActivity implements WidgetItemAdapte
setDragDataToInflatedView(view);
}
- private boolean onLayoutViewLongClick(IView view) {
+ private boolean onLayoutViewLongClick(@NonNull IView view) {
final var shadow = new WidgetDragShadowBuilder(view.asView());
final var item = new ClipData.Item(DesignerActivity.DRAGGING_WIDGET_TAG);
final var clip = new ClipData(DesignerActivity.DRAGGING_WIDGET_TAG, new String[] {DesignerActivity.DRAGGING_WIDGET_MIME}, item);
diff --git a/app/src/main/java/com/itsaky/androidide/syntax/lexer/impls/BaseJavaLexer.java b/app/src/main/java/com/itsaky/androidide/syntax/lexer/impls/BaseJavaLexer.java
index 7fea584ce..58dddb1fe 100755
--- a/app/src/main/java/com/itsaky/androidide/syntax/lexer/impls/BaseJavaLexer.java
+++ b/app/src/main/java/com/itsaky/androidide/syntax/lexer/impls/BaseJavaLexer.java
@@ -22,11 +22,16 @@
package com.itsaky.androidide.syntax.lexer.impls;
import android.graphics.Color;
+
+import androidx.annotation.NonNull;
+
import com.itsaky.androidide.syntax.lexer.DefaultLexer;
import io.github.rosemoe.editor.struct.BlockLine;
import io.github.rosemoe.editor.struct.Span;
import io.github.rosemoe.editor.text.Content;
import io.github.rosemoe.editor.text.TextAnalyzeResult;
+import io.github.rosemoe.editor.widget.EditorColorScheme;
+
import java.util.ArrayList;
import java.util.Stack;
import java.util.regex.Matcher;
@@ -56,17 +61,19 @@ public abstract class BaseJavaLexer extends DefaultLexer {
public final Stack stack = new Stack();
protected ArrayList builtinTypes;
- protected void addHexColorIfPresent(Token token, final Span span) {
- Matcher m = HEX.matcher(token.getText());
- if (m.find()) {
- try {
- span.underlineColor = Color.parseColor(token.getText().substring(m.start(), m.end()));
- span.underlineHeight = Span.HEX_COLOR_UNDERLINE_HEIGHT;
- } catch (Throwable th) {
- // ignored
- // The hex color may not be a valid color code
- }
- }
+ protected void addHexColorIfPresent(@NonNull Token token, final Span span, TextAnalyzeResult result, int endLine, int endColumn) {
+ Matcher m = HEX.matcher(token.getText());
+ if (m.find()) {
+ try {
+ span.underlineColor = Color.parseColor(token.getText().substring(m.start(), m.end()));
+ span.underlineHeight = Span.HEX_COLOR_UNDERLINE_HEIGHT;
+
+ result.addIfNeeded(endLine, endColumn, EditorColorScheme.TEXT_NORMAL);
+ } catch (Throwable th) {
+ // Ignored
+ // May happen because of invalid hex color code
+ }
+ }
}
protected final Pattern HEX = Pattern.compile("#[a-fA-F0-9]{3,8}");
diff --git a/app/src/main/java/com/itsaky/androidide/syntax/lexer/impls/groovy/GroovyLexerImpl.java b/app/src/main/java/com/itsaky/androidide/syntax/lexer/impls/groovy/GroovyLexerImpl.java
index f50b9d2c7..607241a88 100755
--- a/app/src/main/java/com/itsaky/androidide/syntax/lexer/impls/groovy/GroovyLexerImpl.java
+++ b/app/src/main/java/com/itsaky/androidide/syntax/lexer/impls/groovy/GroovyLexerImpl.java
@@ -182,7 +182,7 @@ public class GroovyLexerImpl extends BaseJavaLexer implements Lexer {
type = TokenType.STRING_LITERAL;
span = colors.addIfNeeded(line, column, EditorColorScheme.LITERAL);
wasClassName = false;
- addHexColorIfPresent(currentToken, span);
+ addHexColorIfPresent(currentToken, span, colors, line, column + currentToken.getText().length());
break;
case GroovyLexer.LPAREN :
case GroovyLexer.RPAREN :
diff --git a/app/src/main/java/com/itsaky/androidide/syntax/lexer/impls/java/JavaLexerImpl.java b/app/src/main/java/com/itsaky/androidide/syntax/lexer/impls/java/JavaLexerImpl.java
index 3c7f4cc2f..65f58f017 100755
--- a/app/src/main/java/com/itsaky/androidide/syntax/lexer/impls/java/JavaLexerImpl.java
+++ b/app/src/main/java/com/itsaky/androidide/syntax/lexer/impls/java/JavaLexerImpl.java
@@ -1,20 +1,20 @@
/************************************************************************************
* 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 .
*
-**************************************************************************************/
+ **************************************************************************************/
package com.itsaky.androidide.syntax.lexer.impls.java;
import com.itsaky.androidide.lexers.java.JavaLexer;
@@ -64,30 +64,30 @@ public class JavaLexerImpl extends io.github.rosemoe.editor.langs.AbstractCodeAn
private HighlightRangeHelper helper;
private Map> diagnostics = new HashMap<>();
private final Map> stringMap = new HashMap<>();
-
+
public final MultilineStringHandler stringHandler = new MultilineStringHandler();
private CompletableFuture> lastRequest;
public JavaLexerImpl(EditorLanguage language) {
this.language = language;
}
-
+
@Override
public void setSemanticHighlights(SemanticHighlight highlights) {
this.helper = new HighlightRangeHelper(highlights);
this.helper.sort();
}
-
+
@Override
public void analyze(IDELanguageServer languageServer, File file, CharSequence content, TextAnalyzeResult colors, TextAnalyzer.AnalyzeThread.Delegate delegate) throws Exception {
final JavaLexerAnalyzer lexer = new JavaLexerAnalyzer((Content) content, colors, this.helper);
-
+
try {
lexer.init();
} catch (Throwable th) {
return;
}
-
+
stringMap.clear();
if (languageServer != null && file != null) {
@@ -123,7 +123,7 @@ public class JavaLexerImpl extends io.github.rosemoe.editor.langs.AbstractCodeAn
while (delegate.shouldAnalyze()) {
// null = EOF
- if(lexer.nextToken() == null)
+ if (lexer.nextToken() == null)
break;
}
if (lexer.stack.isEmpty() && lexer.currSwitch > lexer.maxSwitch)
@@ -135,7 +135,7 @@ public class JavaLexerImpl extends io.github.rosemoe.editor.langs.AbstractCodeAn
@Override
public void updateDiagnostics(Map> diagnostics) {
- if(diagnostics == null) {
+ if (diagnostics == null) {
diagnostics = new HashMap<>();
}
this.diagnostics = diagnostics;
@@ -144,17 +144,17 @@ public class JavaLexerImpl extends io.github.rosemoe.editor.langs.AbstractCodeAn
@Override
public Diagnostic findDiagnosticContaining(int line, int column) {
final Map mappedByColumn = diagnostics.get(line);
- if(mappedByColumn != null) {
+ if (mappedByColumn != null) {
Diagnostic diag = mappedByColumn.get(column);
- if(diag != null) {
+ if (diag != null) {
return diag;
} else {
- for(Map.Entry entry : mappedByColumn.entrySet()) {
+ for (Map.Entry entry : mappedByColumn.entrySet()) {
diag = entry.getValue();
final int start = diag.getRange().getStart().getCharacter();
final int end = diag.getRange().getEnd().getCharacter();
-
- if(column >= start && column <= end) {
+
+ if (column >= start && column <= end) {
return diag;
}
}
@@ -166,49 +166,49 @@ public class JavaLexerImpl extends io.github.rosemoe.editor.langs.AbstractCodeAn
@Override
public List findDiagnosticsContainingLine(int line) {
final Map diags = diagnostics.get(line);
- if(diags == null) {
+ if (diags == null) {
return super.findDiagnosticsContainingLine(line);
}
return diags.entrySet().stream()
- .filter(d -> d != null && d.getValue() != null)
- .map(Map.Entry::getValue)
- .collect(Collectors.toList());
+ .filter(d -> d != null && d.getValue() != null)
+ .map(Map.Entry::getValue)
+ .collect(Collectors.toList());
}
@Override
public Map getDiagnosticsAtLine(int line) {
return diagnostics.get(line);
}
-
+
private class MultilineStringHandler implements NewlineHandler {
-
+
@Override
public boolean matchesRequirement(String beforeText, String afterText, CharPosition cursor) {
- if(language == null || stringMap.isEmpty()) {
+ if (language == null || stringMap.isEmpty()) {
return false;
}
-
+
final List ranges = stringMap.get(cursor.line);
- if(ranges == null || ranges.isEmpty()) {
+ if (ranges == null || ranges.isEmpty()) {
return false;
}
-
+
return isInRanges(ranges, cursor.line, cursor.column);
}
-
+
@Override
public NewlineHandler.HandleResult handleNewline(String beforeText, String afterText, int tabSize) {
int count = TextUtils.countLeadingSpaceCount(beforeText, tabSize);
int advance = language.getIndentAdvance(beforeText) + 1;
final StringBuilder sb = new StringBuilder("\\n\" + \n") // Appends: \n" +
- .append(TextUtils.createIndent(count + advance, tabSize, language.useTab()))
- .append("\"");
+ .append(TextUtils.createIndent(count + advance, tabSize, language.useTab()))
+ .append("\"");
return new HandleResult(sb, 0);
}
-
- private boolean isInRanges (List ranges, int line, int column) {
- if(ranges == null || ranges.isEmpty()) {
+ private boolean isInRanges(List ranges, int line, int column) {
+
+ if (ranges == null || ranges.isEmpty()) {
return false;
}
@@ -221,11 +221,11 @@ public class JavaLexerImpl extends io.github.rosemoe.editor.langs.AbstractCodeAn
return false;
}
}
-
+
public class JavaLexerAnalyzer extends BaseJavaLexer implements Lexer {
-
+
private final HighlightRangeHelper helper;
-
+
public JavaLexerAnalyzer(Content content, TextAnalyzeResult colors, HighlightRangeHelper helper) {
this.content = content;
this.colors = colors;
@@ -236,7 +236,7 @@ public class JavaLexerImpl extends io.github.rosemoe.editor.langs.AbstractCodeAn
this.wasClassName = false;
this.isFirst = true;
}
-
+
@Override
public void init() {
lexer = new JavaLexer(CharStreams.fromString(content.toString()));
@@ -245,7 +245,7 @@ public class JavaLexerImpl extends io.github.rosemoe.editor.langs.AbstractCodeAn
@Override
public Token nextToken() {
currentToken = lexer.nextToken();
- if(currentToken.getType() == JavaLexer.EOF) {
+ if (currentToken.getType() == JavaLexer.EOF) {
this.lastLine = line();
return null;
}
@@ -270,19 +270,19 @@ public class JavaLexerImpl extends io.github.rosemoe.editor.langs.AbstractCodeAn
public String text() {
return currentToken.getText();
}
-
+
@Override
public TokenType type() {
final int line = line();
final int column = column();
final int tokenType = currentToken.getType();
TokenType type = TokenType.TEXT;
-
+
Span span = null;
- switch(tokenType) {
- case JavaLexer.WS :
+ switch (tokenType) {
+ case JavaLexer.WS:
type = TokenType.WS;
- if(isFirst)
+ if (isFirst)
colors.addNormalIfNull();
break;
case JavaLexer.ABSTRACT:
@@ -326,7 +326,7 @@ public class JavaLexerImpl extends io.github.rosemoe.editor.langs.AbstractCodeAn
case JavaLexer.VOID:
case JavaLexer.VOLATILE:
case JavaLexer.WHILE:
- case JavaLexer.VAR :
+ case JavaLexer.VAR:
type = TokenType.KEYWORD;
span = colors.addIfNeeded(line, column, EditorColorScheme.KEYWORD);
wasClassName = false;
@@ -344,7 +344,7 @@ public class JavaLexerImpl extends io.github.rosemoe.editor.langs.AbstractCodeAn
span = colors.addIfNeeded(line, column, EditorColorScheme.LITERAL);
wasClassName = false;
break;
- case JavaLexer.STRING_LITERAL :
+ case JavaLexer.STRING_LITERAL:
type = TokenType.STRING_LITERAL;
span = colors.addIfNeeded(line, column, EditorColorScheme.LITERAL);
wasClassName = false;
@@ -352,219 +352,220 @@ public class JavaLexerImpl extends io.github.rosemoe.editor.langs.AbstractCodeAn
Position start = new Position(line, column);
Position end = new Position(line, column + currentToken.getText().length());
colors.addStringRange(line, new Range(start, end));
-
- {
- List ranges = stringMap.get(line);
- if(ranges == null) {
- ranges = new ArrayList<>();
- }
- ranges.add(new Range(start, end));
- stringMap.put(line, ranges);
+
+ {
+ List ranges = stringMap.get(line);
+ if (ranges == null) {
+ ranges = new ArrayList<>();
}
-
- addHexColorIfPresent(currentToken, span);
- break;
- case JavaLexer.LPAREN :
- case JavaLexer.RPAREN :
- case JavaLexer.LBRACK :
- case JavaLexer.RBRACK :
- case JavaLexer.SEMI :
- case JavaLexer.COMMA :
- case JavaLexer.ASSIGN :
- case JavaLexer.GT :
- case JavaLexer.LT :
- case JavaLexer.BANG :
- case JavaLexer.TILDE :
- case JavaLexer.QUESTION :
- case JavaLexer.COLON :
- case JavaLexer.EQUAL :
- case JavaLexer.GE :
- case JavaLexer.LE :
- case JavaLexer.NOTEQUAL :
- case JavaLexer.AND :
- case JavaLexer.OR :
- case JavaLexer.INC :
- case JavaLexer.DEC :
- case JavaLexer.ADD :
- case JavaLexer.SUB :
- case JavaLexer.MUL :
- case JavaLexer.DIV :
- case JavaLexer.BITAND :
- case JavaLexer.BITOR :
- case JavaLexer.CARET :
- case JavaLexer.MOD :
- case JavaLexer.ADD_ASSIGN :
- case JavaLexer.SUB_ASSIGN :
- case JavaLexer.MUL_ASSIGN :
- case JavaLexer.DIV_ASSIGN :
- case JavaLexer.AND_ASSIGN :
- case JavaLexer.OR_ASSIGN :
- case JavaLexer.XOR_ASSIGN :
- case JavaLexer.MOD_ASSIGN :
- case JavaLexer.LSHIFT_ASSIGN :
- case JavaLexer.RSHIFT_ASSIGN :
- case JavaLexer.URSHIFT_ASSIGN :
- case JavaLexer.ARROW :
- case JavaLexer.COLONCOLON :
- case JavaLexer.ELLIPSIS :
- case JavaLexer.DOT :
+ ranges.add(new Range(start, end));
+ stringMap.put(line, ranges);
+ }
+
+ addHexColorIfPresent(currentToken, span, colors, end.getLine(), end.getCharacter());
+ break;
+ case JavaLexer.LPAREN:
+ case JavaLexer.RPAREN:
+ case JavaLexer.LBRACK:
+ case JavaLexer.RBRACK:
+ case JavaLexer.SEMI:
+ case JavaLexer.COMMA:
+ case JavaLexer.ASSIGN:
+ case JavaLexer.GT:
+ case JavaLexer.LT:
+ case JavaLexer.BANG:
+ case JavaLexer.TILDE:
+ case JavaLexer.QUESTION:
+ case JavaLexer.COLON:
+ case JavaLexer.EQUAL:
+ case JavaLexer.GE:
+ case JavaLexer.LE:
+ case JavaLexer.NOTEQUAL:
+ case JavaLexer.AND:
+ case JavaLexer.OR:
+ case JavaLexer.INC:
+ case JavaLexer.DEC:
+ case JavaLexer.ADD:
+ case JavaLexer.SUB:
+ case JavaLexer.MUL:
+ case JavaLexer.DIV:
+ case JavaLexer.BITAND:
+ case JavaLexer.BITOR:
+ case JavaLexer.CARET:
+ case JavaLexer.MOD:
+ case JavaLexer.ADD_ASSIGN:
+ case JavaLexer.SUB_ASSIGN:
+ case JavaLexer.MUL_ASSIGN:
+ case JavaLexer.DIV_ASSIGN:
+ case JavaLexer.AND_ASSIGN:
+ case JavaLexer.OR_ASSIGN:
+ case JavaLexer.XOR_ASSIGN:
+ case JavaLexer.MOD_ASSIGN:
+ case JavaLexer.LSHIFT_ASSIGN:
+ case JavaLexer.RSHIFT_ASSIGN:
+ case JavaLexer.URSHIFT_ASSIGN:
+ case JavaLexer.ARROW:
+ case JavaLexer.COLONCOLON:
+ case JavaLexer.ELLIPSIS:
+ case JavaLexer.DOT:
type = TokenType.OPERATOR;
span = colors.addIfNeeded(line, column, EditorColorScheme.OPERATOR);
wasClassName = false;
break;
case JavaLexer.BOOLEAN:
- case JavaLexer.BYTE :
+ case JavaLexer.BYTE:
case JavaLexer.CHAR:
case JavaLexer.DOUBLE:
- case JavaLexer.ENUM :
+ case JavaLexer.ENUM:
case JavaLexer.FLOAT:
- case JavaLexer.INT :
+ case JavaLexer.INT:
case JavaLexer.LONG:
case JavaLexer.SHORT:
type = TokenType.TYPE;
span = colors.addIfNeeded(line, column, EditorColorScheme.TYPE_NAME);
wasClassName = true;
break;
- case JavaLexer.BLOCK_COMMENT :
- case JavaLexer.LINE_COMMENT :
+ case JavaLexer.BLOCK_COMMENT:
+ case JavaLexer.LINE_COMMENT:
type = TokenType.COMMENT;
span = colors.addIfNeeded(line, column, EditorColorScheme.COMMENT);
wasClassName = false;
-
+
final CharPosition a = content.getIndexer().getCharPosition(currentToken.getStopIndex());
final Position s = new Position(line, column);
final Position e = new Position(a.line, a.column);
colors.addCommentRange(line, new Range(s, e));
-
+
String lineComment = currentToken.getText();
- if(lineComment != null) {
- if(lineComment.startsWith("//")) {
+ if (lineComment != null) {
+ if (lineComment.startsWith("//")) {
lineComment = lineComment.substring(2);
}
-
+
// Trim leading whitespaces
int startsFrom = 0;
- whitespace_checker: for (int i=0;i