Send build output directly to IToollingApiClient

This commit is contained in:
Akash Yadav
2022-04-30 08:46:33 +05:30
parent 8bbb2f2447
commit b554d5276f
7 changed files with 99 additions and 15 deletions
Binary file not shown.
@@ -155,7 +155,8 @@ public class EditorActivity extends StudioActivity
DiagnosticClickListener,
IDEHandler.Provider,
EditorActivityProvider,
OptionsListFragment.OnOptionsClickListener {
OptionsListFragment.OnOptionsClickListener,
GradleBuildService.OutputHandler {
public static final String EXTRA_PROJECT = "project";
public static final String KEY_BOTTOM_SHEET_SHOWN = "editor_bottomSheetShown";
@@ -191,7 +192,9 @@ public class EditorActivity extends StudioActivity
mBuildService = ((GradleBuildService.GradleServiceBinder) service).getService();
LOG.info("Gradle build service has been started...");
mBuildService.startToolingServer(() -> initializeProject());
mBuildService
.setOutputHandler(EditorActivity.this)
.startToolingServer(() -> initializeProject());
}
@Override
@@ -313,6 +316,19 @@ public class EditorActivity extends StudioActivity
return mViewModel.getAndroidProject();
}
@Override
public void onOutput(String line) {
appendBuildOut(line);
}
public void appendBuildOut(final String str) {
final var frag = bottomSheetTabAdapter.getBuildOutputFragment();
if (frag != null) {
frag.appendOutput(str);
}
}
public void handleSearchResults(Map<File, List<SearchResult>> results) {
setSearchResultAdapter(
new com.itsaky.androidide.adapters.SearchListAdapter(
@@ -340,14 +356,6 @@ public class EditorActivity extends StudioActivity
}
}
public void appendBuildOut(final String str) {
final var frag = bottomSheetTabAdapter.getBuildOutputFragment();
if (frag != null) {
frag.appendOutput(str);
}
}
public void showDaemonStatus() {
ShellServer shell = getApp().newShell(t -> getDaemonStatusFragment().append(t));
shell.bgAppend(String.format("echo '%s'", getString(R.string.msg_getting_daemom_status)));
@@ -916,7 +924,7 @@ public class EditorActivity extends StudioActivity
.show();
}
}
private IDEService getBuildService() {
return mBuildServiceHandler.getService();
}
@@ -70,6 +70,7 @@ public class GradleBuildService extends Service implements BuildService, IToolin
private Thread toolingServerThread;
private NotificationManager notificationManager;
private IToolingApiServer server;
private OutputHandler outputHandler;
@Override
public void onCreate() {
@@ -125,6 +126,13 @@ public class GradleBuildService extends Service implements BuildService, IToolin
SERVER_LOGGER.log(ILogger.priority(line.priorityChar), line.formattedTagAndMessage());
}
@Override
public void logOutput(@NonNull String line) {
if (outputHandler != null) {
outputHandler.onOutput(line);
}
}
@NonNull
@Override
public CompletableFuture<InitializeResult> initializeProject(@NonNull String rootDir) {
@@ -169,6 +177,11 @@ public class GradleBuildService extends Service implements BuildService, IToolin
toolingServerThread.start();
}
public GradleBuildService setOutputHandler(OutputHandler outputHandler) {
this.outputHandler = outputHandler;
return this;
}
protected void onServerExited(int exitCode) {
LOG.warn("Tooling API process terminated with exit code:", exitCode);
stopForeground(true);
@@ -243,4 +256,15 @@ public class GradleBuildService extends Service implements BuildService, IToolin
/** Called when the tooling API server has been successfully started. */
void onServerStarted();
}
/** Handles output received from a Gradle build. */
public interface OutputHandler {
/**
* Called when the output line is received.
*
* @param line The line of the build output.
*/
void onOutput(String line);
}
}
@@ -0,0 +1,38 @@
/*
* 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.tooling.impl
import com.itsaky.androidide.tooling.api.IToolingApiClient
import java.io.OutputStream
/**
* Sends the output received from Gradle build to the [IToolingApiClient].
* @author Akash Yadav
*/
class LoggingOutputStream : OutputStream() {
private val lineBuilder = StringBuilder()
override fun write(b: Int) {
val c = b.toChar()
lineBuilder.append(c)
if (c == '\n' && Main.client != null) {
Main.client.logOutput(c.toString())
lineBuilder.clear()
}
}
}
@@ -39,8 +39,6 @@ import com.itsaky.androidide.tooling.impl.progress.LoggingProgressListener
import com.itsaky.androidide.tooling.impl.util.ProjectReader
import com.itsaky.androidide.tooling.impl.util.StopWatch
import com.itsaky.androidide.utils.ILogger
import java.io.File
import java.util.concurrent.*
import org.eclipse.lsp4j.jsonrpc.CompletableFutures
import org.gradle.tooling.BuildCancelledException
import org.gradle.tooling.BuildException
@@ -50,6 +48,8 @@ import org.gradle.tooling.GradleConnector
import org.gradle.tooling.UnsupportedVersionException
import org.gradle.tooling.exceptions.UnsupportedBuildArgumentException
import org.gradle.tooling.exceptions.UnsupportedOperationConfigurationException
import java.io.File
import java.util.concurrent.*
/**
* Implementation for the Gradle Tooling API server.
@@ -135,9 +135,10 @@ internal class ToolingApiServerImpl : IToolingApiServer {
// System.in and System.out are used for communication between this server and the
// client.
val out = LoggingOutputStream()
builder.setStandardInput("NoOp".byteInputStream())
builder.setStandardError(System.err)
builder.setStandardOutput(System.err)
builder.setStandardError(out)
builder.setStandardOutput(out)
builder.forTasks(*message.tasks.toTypedArray())
applyArguments(builder)
@@ -28,5 +28,18 @@ import org.eclipse.lsp4j.jsonrpc.services.JsonSegment
*/
@JsonSegment("client")
interface IToolingApiClient {
/**
* Log the given log message.
*
* @param line The [LogLine] to log.
*/
@JsonNotification fun logMessage(line: LogLine)
/**
* Log the build output received from Gradle.
*
* @param line The line of the build output to log.
*/
@JsonNotification fun logOutput(line: String)
}