fix(lsp/java): inconsistent indents in generated code

This commit is contained in:
Akash Yadav
2023-03-27 23:37:11 +05:30
parent e7489ed6f2
commit 3a1f5ff3ce
14 changed files with 89 additions and 62 deletions
@@ -20,6 +20,7 @@ package com.itsaky.androidide.utils
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.itsaky.androidide.preferences.internal.tabSize
import com.itsaky.androidide.preferences.utils.indentationString
import com.squareup.javapoet.JavaFile
import com.squareup.javapoet.MethodSpec
import com.squareup.javapoet.TypeSpec
@@ -38,7 +39,7 @@ object ClassBuilder {
block: JavaFile.Builder.() -> Unit = {}
): JavaFile {
return JavaFile.builder(packageName, type)
.indent(" ".repeat(tabSize))
.indent(indentationString)
.apply { block(this) }
.build()
}
@@ -19,6 +19,7 @@ package com.itsaky.androidide.utils
import com.itsaky.androidide.preferences.internal.tabSize
import com.itsaky.androidide.preferences.internal.useSoftTab
import com.itsaky.androidide.preferences.utils.indentationString
import com.itsaky.androidide.ui.SymbolInputView.Symbol
import java.io.File
@@ -133,11 +134,7 @@ object Symbols {
}
private fun createTabChars(): String {
if (!useSoftTab) {
return "\t"
}
return " ".repeat(tabSize)
return indentationString
}
}
}
@@ -30,6 +30,7 @@ import com.itsaky.androidide.lsp.java.actions.FieldBasedAction
import com.itsaky.androidide.lsp.java.compiler.CompileTask
import com.itsaky.androidide.lsp.java.utils.EditHelper
import com.itsaky.androidide.lsp.java.utils.ShortTypePrinter.NO_PACKAGE
import com.itsaky.androidide.preferences.utils.indentationString
import com.itsaky.androidide.projects.ProjectManager
import com.itsaky.androidide.resources.R.string
import com.itsaky.androidide.utils.ILogger
@@ -123,7 +124,7 @@ class GenerateConstructorAction : FieldBasedAction() {
val insertAt = EditHelper.insertAfter(task.task, task.root(), paths.last().leaf)
val indent = EditHelper.indent(task.task, task.root(), paths.last().leaf)
var text = constructor.toString()
text = text.replace("\n", "\n${EditHelper.repeatSpaces(indent)}")
text = text.replace("\n", "\n${indentationString(indent)}")
text += "\n"
ThreadUtils.runOnUiThread {
@@ -35,17 +35,18 @@ import com.itsaky.androidide.lsp.java.utils.EditHelper
import com.itsaky.androidide.lsp.java.utils.JavaParserUtils
import com.itsaky.androidide.lsp.java.utils.TypeUtils.toType
import com.itsaky.androidide.preferences.internal.tabSize
import com.itsaky.androidide.preferences.utils.indentationString
import com.itsaky.androidide.projects.ProjectManager
import com.itsaky.androidide.resources.R
import com.itsaky.androidide.utils.ILogger
import com.itsaky.androidide.utils.flashError
import io.github.rosemoe.sora.widget.CodeEditor
import jdkx.lang.model.element.Modifier.FINAL
import jdkx.lang.model.element.VariableElement
import openjdk.source.tree.ClassTree
import openjdk.source.util.TreePath
import openjdk.source.util.Trees
import io.github.rosemoe.sora.widget.CodeEditor
import java.util.concurrent.CompletableFuture
import jdkx.lang.model.element.Modifier.FINAL
import jdkx.lang.model.element.VariableElement
/**
* Allows the user to select fields from the current class, then generates setters and getters for
@@ -138,7 +139,7 @@ class GenerateSettersAndGettersAction : FieldBasedAction() {
body.addStatement(createReturnStmt(name))
}
var text = "\n" + JavaParserUtils.prettyPrint(method) { false }
text = text.replace("\n", "\n${EditHelper.repeatSpaces(indent)}")
text = text.replace("\n", "\n${indentationString(indent)}")
return text
}
@@ -154,7 +155,7 @@ class GenerateSettersAndGettersAction : FieldBasedAction() {
}
var text = "\n" + JavaParserUtils.prettyPrint(method) { false }
text = text.replace("\n", "\n${EditHelper.repeatSpaces(indent)}")
text = text.replace("\n", "\n${indentationString(indent)}")
return text
}
@@ -30,11 +30,15 @@ import com.itsaky.androidide.lsp.java.actions.FieldBasedAction
import com.itsaky.androidide.lsp.java.compiler.CompileTask
import com.itsaky.androidide.lsp.java.utils.EditHelper
import com.itsaky.androidide.preferences.internal.tabSize
import com.itsaky.androidide.preferences.utils.indentationString
import com.itsaky.androidide.projects.ProjectManager
import com.itsaky.androidide.resources.R
import com.itsaky.androidide.resources.R.string
import com.itsaky.androidide.utils.ILogger
import com.itsaky.androidide.utils.flashError
import io.github.rosemoe.sora.widget.CodeEditor
import java.util.concurrent.CompletableFuture
import jdkx.lang.model.element.VariableElement
import openjdk.source.tree.ClassTree
import openjdk.source.tree.VariableTree
import openjdk.source.util.TreePath
@@ -44,9 +48,6 @@ import openjdk.tools.javac.code.Symbol.MethodSymbol
import openjdk.tools.javac.tree.JCTree
import openjdk.tools.javac.tree.TreeInfo
import openjdk.tools.javac.util.Names
import io.github.rosemoe.sora.widget.CodeEditor
import java.util.concurrent.CompletableFuture
import jdkx.lang.model.element.VariableElement
/**
* Generates the `toString()` method for the current class.
@@ -149,7 +150,7 @@ class GenerateToStringMethodAction : FieldBasedAction() {
body.addStatement(createReturnStatement(string.toString()))
var text = "\n" + method.toString()
text = text.replace("\n", "\n${EditHelper.repeatSpaces(indent)}")
text = text.replace("\n", "\n${indentationString(indent)}")
text += "\n"
ThreadUtils.runOnUiThread {
@@ -36,14 +36,12 @@ import com.itsaky.androidide.lsp.java.utils.JavaParserUtils
import com.itsaky.androidide.lsp.java.utils.MethodPtr
import com.itsaky.androidide.lsp.java.visitors.FindTypeDeclarationAt
import com.itsaky.androidide.preferences.internal.tabSize
import com.itsaky.androidide.preferences.utils.indentationString
import com.itsaky.androidide.projects.ProjectManager
import com.itsaky.androidide.resources.R
import com.itsaky.androidide.utils.ILogger
import com.itsaky.androidide.utils.flashError
import io.github.rosemoe.sora.widget.CodeEditor
import java.util.Arrays
import java.util.Optional
import java.util.concurrent.CompletableFuture
import jdkx.lang.model.element.ElementKind
import jdkx.lang.model.element.ExecutableElement
import jdkx.lang.model.element.Modifier
@@ -53,6 +51,9 @@ import jdkx.lang.model.type.ExecutableType
import jdkx.tools.JavaFileObject
import openjdk.source.tree.MethodTree
import openjdk.source.util.Trees
import java.util.Arrays
import java.util.Optional
import java.util.concurrent.CompletableFuture
/**
* Allows the user to override multiple methods from superclass at once.
@@ -231,7 +232,7 @@ class OverrideSuperclassMethodsAction : BaseJavaCodeAction() {
val newImports = JavaParserUtils.collectImports(executableType)
sb.append("\n")
sb.append(method.toString())
sb.replace(Regex(Regex.escape("\n")), "\n${EditHelper.repeatSpaces(indent)}")
sb.replace(Regex(Regex.escape("\n")), "\n${indentationString(indent)}")
sb.append("\n")
newImports.removeIf {
@@ -23,8 +23,6 @@ import com.itsaky.androidide.lsp.java.compiler.CompileTask
import com.itsaky.androidide.lsp.java.compiler.JavaCompilerService
import com.itsaky.androidide.lsp.java.edits.MultipleClassImportEditHandler
import com.itsaky.androidide.lsp.java.models.JavaCompletionItem
import com.itsaky.androidide.lsp.java.utils.EditHelper
import com.itsaky.androidide.lsp.java.utils.EditHelper.repeatSpaces
import com.itsaky.androidide.lsp.java.utils.JavaPoetUtils.Companion.buildMethod
import com.itsaky.androidide.lsp.java.utils.JavaPoetUtils.Companion.print
import com.itsaky.androidide.lsp.java.utils.ScopeHelper
@@ -34,10 +32,7 @@ import com.itsaky.androidide.lsp.models.InsertTextFormat.SNIPPET
import com.itsaky.androidide.lsp.models.MatchLevel
import com.itsaky.androidide.lsp.models.MatchLevel.NO_MATCH
import com.itsaky.androidide.progress.ProgressManager.Companion.abortIfCancelled
import com.itsaky.androidide.projects.FileManager
import com.squareup.javapoet.MethodSpec.Builder
import java.nio.file.Path
import java.util.function.Predicate
import jdkx.lang.model.element.ElementKind.METHOD
import jdkx.lang.model.element.ExecutableElement
import jdkx.lang.model.element.Modifier.FINAL
@@ -48,6 +43,8 @@ import openjdk.source.tree.ClassTree
import openjdk.source.tree.Tree.Kind.CLASS
import openjdk.source.util.TreePath
import openjdk.source.util.Trees
import java.nio.file.Path
import java.util.function.Predicate
/**
* Provides completions using [openjdk.source.tree.Scope].
@@ -156,7 +153,6 @@ class ScopeCompletionProvider(
// Print the method details and the annotations
// Print the method details and the annotations
val indent = EditHelper.indent(FileManager.getDocumentContents(file), cursor.toInt())
val builder: Builder
try {
builder = buildMethod(method, types, type)
@@ -26,6 +26,7 @@ import com.itsaky.androidide.lsp.java.utils.FindHelper;
import com.itsaky.androidide.models.Position;
import com.itsaky.androidide.models.Range;
import com.itsaky.androidide.lsp.models.TextEdit;
import com.itsaky.androidide.preferences.utils.EditorUtilKt;
import openjdk.source.tree.LineMap;
import openjdk.source.tree.MethodTree;
import openjdk.source.util.SourcePositions;
@@ -67,7 +68,7 @@ public class AddSuppressWarningAnnotation extends Rewrite {
int line = (int) lines.getLineNumber(startMethod);
int column = (int) lines.getColumnNumber(startMethod);
int startLine = (int) lines.getStartPosition(line);
String indent = EditHelper.repeatSpaces(startMethod - startLine);
String indent = EditorUtilKt.indentationString(startMethod - startLine);
String insertText = "@SuppressWarnings(\"unchecked\")\n" + indent;
Position insertPoint = new Position(line - 1, column - 1);
TextEdit insert = new TextEdit(new Range(insertPoint, insertPoint), insertText);
@@ -20,7 +20,6 @@ package com.itsaky.androidide.lsp.java.rewrite;
import static com.itsaky.androidide.lsp.java.utils.EditHelper.indent;
import static com.itsaky.androidide.lsp.java.utils.EditHelper.insertAfter;
import static com.itsaky.androidide.lsp.java.utils.EditHelper.insertAtEndOfClass;
import static com.itsaky.androidide.lsp.java.utils.EditHelper.repeatSpaces;
import androidx.annotation.NonNull;
import com.itsaky.androidide.lsp.java.compiler.CompileTask;
@@ -32,6 +31,7 @@ import com.itsaky.androidide.lsp.models.TextEdit;
import com.itsaky.androidide.models.Position;
import com.itsaky.androidide.models.Range;
import com.itsaky.androidide.preferences.internal.EditorPreferencesKt;
import com.itsaky.androidide.preferences.utils.EditorUtilKt;
import com.itsaky.androidide.utils.ILogger;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -84,8 +84,7 @@ public class CreateMissingMethod extends Rewrite {
MethodTree currentMethod = surroundingMethod(path);
final var insertTextBuilder = new StringBuilder("\n");
final var tabWidth = EditorPreferencesKt.getTabSize();
final var tab = repeatSpaces(tabWidth);
final var indent = EditorUtilKt.getIndentationString();
final var isStatic = currentMethod.getModifiers().getFlags().contains(Modifier.STATIC) ||
methodFinder.isStaticAccess();
@@ -93,10 +92,10 @@ public class CreateMissingMethod extends Rewrite {
insertTextBuilder.append(
printMethodHeader(task, call, returnType, methodFinder.isMemberSelect(), isStatic))
.append(" {\n")
.append(tab)
.append(indent)
.append(TODO_COMMENT)
.append("\n")
.append(tab)
.append(indent)
.append(createReturnStatement(returnType))
.append("\n")
.append("}");
@@ -119,11 +118,13 @@ public class CreateMissingMethod extends Rewrite {
insertPoint = insertAfter(task.task, compilationUnit, surroundingMethod(path));
}
final int indent = indent(task.task, compilationUnit, enclosingClass) + tabWidth;
insertText = insertText.replaceAll("\n", "\n" + repeatSpaces(indent));
final int indentSpaces =
indent(task.task, compilationUnit, enclosingClass) + EditorPreferencesKt.getTabSize();
insertText = insertText.replaceAll("\n", "\n" + EditorUtilKt.indentationString(indentSpaces));
insertText += "\n";
final var edits = new TextEdit[]{new TextEdit(new Range(insertPoint, insertPoint), insertText)};
final var edits = new TextEdit[]{
new TextEdit(new Range(insertPoint, insertPoint), insertText)};
return Collections.singletonMap(sourceFile, edits);
});
}
@@ -20,6 +20,7 @@ package com.itsaky.androidide.lsp.java.rewrite;
import androidx.annotation.NonNull;
import com.itsaky.androidide.preferences.internal.EditorPreferencesKt;
import com.itsaky.androidide.preferences.utils.EditorUtilKt;
import com.itsaky.androidide.utils.ILogger;
import com.itsaky.androidide.lsp.java.compiler.CompileTask;
import com.itsaky.androidide.lsp.java.compiler.CompilerProvider;
@@ -89,7 +90,7 @@ public class GenerateRecordConstructor extends Rewrite {
.append("\n}");
String string = buf.toString();
int indent = EditHelper.indent(task.task, task.root(), typeTree) + EditorPreferencesKt.getTabSize();
string = string.replaceAll("\n", "\n" + EditHelper.repeatSpaces(indent));
string = string.replaceAll("\n", "\n" + EditorUtilKt.indentationString(indent));
string = string + "\n\n";
Position insert = insertPoint(task, typeTree);
TextEdit[] edits = {new TextEdit(new Range(insert, insert), string)};
@@ -20,6 +20,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.itsaky.androidide.preferences.internal.EditorPreferencesKt;
import com.itsaky.androidide.preferences.utils.EditorUtilKt;
import com.itsaky.androidide.utils.ILogger;
import com.itsaky.androidide.lsp.java.compiler.CompileTask;
import com.itsaky.androidide.lsp.java.compiler.CompilerProvider;
@@ -112,7 +113,7 @@ public class ImplementAbstractMethods extends Rewrite {
ExecutableElement method = (ExecutableElement) member;
final MethodSpec methodSpec = MethodSpec.overriding(method).build();
String text = "\n" + JavaPoetUtils.print(methodSpec, imports, false);
text = text.replaceAll("\n", "\n" + EditHelper.repeatSpaces(indent));
text = text.replaceAll("\n", "\n" + EditorUtilKt.indentationString(indent));
insertText.add(text);
}
}
@@ -23,7 +23,6 @@ import com.itsaky.androidide.lsp.java.rewrite.AddImport;
import com.itsaky.androidide.lsp.models.TextEdit;
import com.itsaky.androidide.models.Position;
import com.itsaky.androidide.models.Range;
import com.itsaky.androidide.preferences.internal.EditorPreferencesKt;
import com.itsaky.androidide.projects.util.StringSearch;
import java.nio.file.Path;
import java.util.Arrays;
@@ -143,19 +142,6 @@ public class EditHelper {
return (int) (startClass - startLine);
}
public static int indent(final CharSequence contents, final int cursor) {
int indent = 0;
for (int i = 0; i <= cursor && i < contents.length(); i++) {
char c = contents.charAt(i);
if (c == '{') {
indent++;
} else if (c == '}') {
indent--;
}
}
return indent * EditorPreferencesKt.getTabSize();
}
public static Position insertBefore(final JavacTask task, final CompilationUnitTree root,
final Tree member
) {
@@ -176,8 +162,7 @@ public class EditHelper {
return new Position(line, 0);
}
public static Position insertAtEndOfClass(JavacTask task, CompilationUnitTree root,
ClassTree leaf
public static Position insertAtEndOfClass(JavacTask task, CompilationUnitTree root, ClassTree leaf
) {
SourcePositions pos = Trees.instance(task).getSourcePositions();
LineMap lines = root.getLineMap();
@@ -187,14 +172,6 @@ public class EditHelper {
return new Position(line - 1, column - 2);
}
public static String repeatSpaces(int count) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < count; i++) {
result.append(" ");
}
return result.toString();
}
private static String printParameters(final ExecutableType method, final MethodTree source) {
StringJoiner join = new StringJoiner(", ");
for (int i = 0; i < method.getParameterTypes().size(); i++) {
@@ -18,6 +18,7 @@
package com.itsaky.androidide.lsp.java.utils
import com.itsaky.androidide.preferences.internal.tabSize
import com.itsaky.androidide.preferences.utils.indentationString
import com.squareup.javapoet.AnnotationSpec
import com.squareup.javapoet.ImportCollectingCodeWriter
import com.squareup.javapoet.MethodSpec
@@ -39,7 +40,7 @@ class JavaPoetUtils {
qualifiedNames: Boolean = true,
): String {
val sb = StringBuilder()
val writer = ImportCollectingCodeWriter(sb, " ".repeat(tabSize), emptySet(), emptySet())
val writer = ImportCollectingCodeWriter(sb, indentationString, emptySet(), emptySet())
writer.isPrintQualifiedNames = qualifiedNames
writer.emit(method)
@@ -0,0 +1,47 @@
/*
* 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.preferences.utils
import com.itsaky.androidide.preferences.internal.tabSize
import com.itsaky.androidide.preferences.internal.useSoftTab
/** @author Akash Yadav */
/**
* The indentation character to use. If [useSoftTab] is enabled, the character is a space, otherwise
* '\t'.
*/
val indentationChar: Char
get() = if (useSoftTab) ' ' else '\t'
/** Get the string which should be used as indentation while generating code. */
val indentationString: String
get() = if (useSoftTab) " ".repeat(tabSize) else "\t"
/**
* Creates the indentation string for the given number of spaces. The result is simply
* [indentationChar] repeated [spaceCount] times if [useSoftTab] is enabled, otherwise `spaceCount /
* tabSize` times.
*
* @param spaceCount The number of spaces to indent.
* @return The indentation string.
*/
fun indentationString(spaceCount: Int): String {
val count = if (useSoftTab) spaceCount else spaceCount / tabSize
return indentationChar.toString().repeat(count)
}