Support logging build output (#1366)
This commit is contained in:
Родитель
6302a49e8d
Коммит
6815ddc7e4
|
@ -12,6 +12,7 @@ Import-Package: org.eclipse.jdt.core,
|
|||
Require-Bundle: org.eclipse.core.runtime,
|
||||
org.eclipse.jdt.ls.core,
|
||||
org.eclipse.jdt.core,
|
||||
org.eclipse.lsp4j,
|
||||
org.eclipse.lsp4j.jsonrpc,
|
||||
org.eclipse.core.resources,
|
||||
org.eclipse.jdt.launching,
|
||||
|
|
|
@ -1,16 +1,26 @@
|
|||
package com.microsoft.gradle.bs.importer;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin;
|
||||
|
||||
import ch.epfl.scala.bsp4j.BuildClient;
|
||||
import ch.epfl.scala.bsp4j.DidChangeBuildTarget;
|
||||
import ch.epfl.scala.bsp4j.LogMessageParams;
|
||||
import ch.epfl.scala.bsp4j.PublishDiagnosticsParams;
|
||||
import ch.epfl.scala.bsp4j.ShowMessageParams;
|
||||
import ch.epfl.scala.bsp4j.TaskDataKind;
|
||||
import ch.epfl.scala.bsp4j.TaskFinishParams;
|
||||
import ch.epfl.scala.bsp4j.TaskProgressParams;
|
||||
import ch.epfl.scala.bsp4j.TaskStartParams;
|
||||
|
||||
public class GradleBuildClient implements BuildClient {
|
||||
|
||||
private static final String CLIENT_APPEND_BUILD_LOG_CMD = "_java.gradle.buildServer.appendBuildLog";
|
||||
|
||||
@Override
|
||||
public void onBuildLogMessage(LogMessageParams arg0) {
|
||||
// TODO Auto-generated method stub
|
||||
|
@ -35,22 +45,32 @@ public class GradleBuildClient implements BuildClient {
|
|||
throw new UnsupportedOperationException("Unimplemented method 'onBuildTargetDidChange'");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onBuildTaskFinish(TaskFinishParams arg0) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'onBuildTaskFinish'");
|
||||
public void onBuildTaskStart(TaskStartParams params) {
|
||||
if (Objects.equals(params.getDataKind(), TaskDataKind.COMPILE_TASK)) {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
Date now = new Date();
|
||||
String msg = "> Build starts at " + dateFormat.format(now) + "\n" + params.getMessage();
|
||||
JavaLanguageServerPlugin.getInstance().getClientConnection().sendNotification(
|
||||
CLIENT_APPEND_BUILD_LOG_CMD, Arrays.asList(msg));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBuildTaskProgress(TaskProgressParams arg0) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'onBuildTaskProgress'");
|
||||
public void onBuildTaskProgress(TaskProgressParams params) {
|
||||
if (Objects.equals(params.getDataKind(), TaskDataKind.COMPILE_TASK)) {
|
||||
JavaLanguageServerPlugin.getInstance().getClientConnection().sendNotification(
|
||||
CLIENT_APPEND_BUILD_LOG_CMD, Arrays.asList(params.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBuildTaskStart(TaskStartParams arg0) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'onBuildTaskStart'");
|
||||
public void onBuildTaskFinish(TaskFinishParams params) {
|
||||
if (Objects.equals(params.getDataKind(), TaskDataKind.COMPILE_REPORT)) {
|
||||
String msg = params.getMessage() + "\n------\n";
|
||||
JavaLanguageServerPlugin.getInstance().getClientConnection().sendNotification(
|
||||
CLIENT_APPEND_BUILD_LOG_CMD, Arrays.asList(msg));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -55,6 +55,9 @@
|
|||
"Gradle"
|
||||
],
|
||||
"configuration": "./gradle-language-configuration.json"
|
||||
},
|
||||
{
|
||||
"id": "gradle-build"
|
||||
}
|
||||
],
|
||||
"grammars": [
|
||||
|
@ -62,6 +65,11 @@
|
|||
"language": "gradle",
|
||||
"scopeName": "source.groovy",
|
||||
"path": "./syntaxes/groovy.tmLanguage.json"
|
||||
},
|
||||
{
|
||||
"language": "gradle-build",
|
||||
"scopeName": "source.gradle-build",
|
||||
"path": "./syntaxes/GradleBuild.tmLanguage.json"
|
||||
}
|
||||
],
|
||||
"problemMatchers": [
|
||||
|
|
|
@ -34,6 +34,7 @@ import {
|
|||
} from "./constant";
|
||||
import { instrumentOperation, sendInfo } from "vscode-extension-telemetry-wrapper";
|
||||
import { GradleBuildContentProvider } from "./client/GradleBuildContentProvider";
|
||||
import { BuildServerController } from "./bs/BuildServerController";
|
||||
|
||||
export class Extension {
|
||||
private readonly client: GradleClient;
|
||||
|
@ -64,6 +65,7 @@ export class Extension {
|
|||
new vscode.EventEmitter<vscode.Terminal>();
|
||||
private readonly onDidTerminalOpen: vscode.Event<vscode.Terminal> = this._onDidTerminalOpen.event;
|
||||
private recentTerminal: vscode.Terminal | undefined;
|
||||
private readonly buildServerController: BuildServerController;
|
||||
|
||||
public constructor(private readonly context: vscode.ExtensionContext) {
|
||||
const loggingChannel = vscode.window.createOutputChannel("Gradle for Java");
|
||||
|
@ -161,6 +163,8 @@ export class Extension {
|
|||
this.gradleTasksTreeView
|
||||
);
|
||||
|
||||
this.buildServerController = new BuildServerController(context);
|
||||
|
||||
this.storeSubscriptions();
|
||||
this.registerCommands();
|
||||
this.handleTaskEvents();
|
||||
|
@ -217,7 +221,8 @@ export class Extension {
|
|||
this.gradleDaemonsTreeView,
|
||||
this.gradleTasksTreeView,
|
||||
this.recentTasksTreeView,
|
||||
this.defaultProjectsTreeView
|
||||
this.defaultProjectsTreeView,
|
||||
this.buildServerController
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
import { Disposable, ExtensionContext, OutputChannel, commands, languages, window } from "vscode";
|
||||
import { GradleBuildLinkProvider } from "./GradleBuildLinkProvider";
|
||||
|
||||
const APPEND_BUILD_LOG_CMD = "_java.gradle.buildServer.appendBuildLog";
|
||||
export class BuildServerController implements Disposable {
|
||||
private disposable: Disposable;
|
||||
private buildOutputChannel: OutputChannel;
|
||||
|
||||
public constructor(readonly context: ExtensionContext) {
|
||||
this.buildOutputChannel = window.createOutputChannel("Build Server for Gradle (Build)", "gradle-build");
|
||||
this.disposable = Disposable.from(
|
||||
this.buildOutputChannel,
|
||||
languages.registerDocumentLinkProvider({ language: "gradle-build", scheme: 'output' }, new GradleBuildLinkProvider()),
|
||||
commands.registerCommand(APPEND_BUILD_LOG_CMD, (msg: string) => {
|
||||
if (msg) {
|
||||
this.buildOutputChannel.appendLine(msg);
|
||||
if (/^BUILD (SUCCESSFUL|FAILED)/m.test(msg)) {
|
||||
this.buildOutputChannel.show(true);
|
||||
}
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
public dispose() {
|
||||
this.disposable.dispose();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
import {DocumentLink, DocumentLinkProvider, ProviderResult, Range, TextDocument, Uri } from "vscode";
|
||||
|
||||
export class GradleBuildLinkProvider implements DocumentLinkProvider {
|
||||
provideDocumentLinks(document: TextDocument): ProviderResult<DocumentLink[]> {
|
||||
const links: DocumentLink[] = [];
|
||||
const content = document.getText();
|
||||
let searchPosition = 0;
|
||||
const lines = content.split(/\r?\n/g);
|
||||
for (const line of lines) {
|
||||
const match = line.match(/(.*\.java):(\d+)/);
|
||||
if (match) {
|
||||
const startOffset = content.indexOf(match[0], searchPosition);
|
||||
const start = document.positionAt(startOffset);
|
||||
const endOffset = startOffset + match[0].length;
|
||||
const end = document.positionAt(endOffset);
|
||||
searchPosition += endOffset;
|
||||
|
||||
const file = match[1];
|
||||
const line = parseInt(match[2]);
|
||||
const uri = Uri.file(file).with({ fragment: `L${line}` });
|
||||
links.push(new DocumentLink(new Range(start, end), uri));
|
||||
// TODO: support column recognition
|
||||
}
|
||||
}
|
||||
return links;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"name": "Gradle Build",
|
||||
"scopeName": "source.gradle-build",
|
||||
"fileTypes": ["gradle-build"],
|
||||
"patterns": [
|
||||
{
|
||||
"name": "FAILURE",
|
||||
"match": "(^FAILURE: .+$)",
|
||||
"captures": {
|
||||
"1": {"name": "invalid.illegal.failure"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "error",
|
||||
"match": "(^\\d+\\serror$)",
|
||||
"captures": {
|
||||
"1": {"name": "invalid.illegal.error"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "error.description",
|
||||
"match": "(error:\\s.+$)",
|
||||
"captures": {
|
||||
"1": {"name": "invalid.illegal.error.description"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "BUILD FAILED",
|
||||
"match": "(^BUILD FAILED)",
|
||||
"captures": {
|
||||
"1": {"name": "invalid.illegal.bold.buildFailed"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
Загрузка…
Ссылка в новой задаче