From 9ba95e906a6509158560495f9565c1c0b7bbd0c6 Mon Sep 17 00:00:00 2001 From: Ole Osterhagen Date: Sat, 18 May 2024 17:49:08 +0200 Subject: [PATCH] Provide syntax highlighting in the compare editor #684 This enables syntax highlighting for build scripts (Groovy and Kotlin DSL) in these areas: * Compare editor * Dialog: Restore from Local History * Opening an old file revision from history --- .../META-INF/MANIFEST.MF | 3 +- .../plugin.xml | 14 +++ org.eclipse.buildship.ui/META-INF/MANIFEST.MF | 3 +- org.eclipse.buildship.ui/plugin.xml | 23 ++++ .../internal/compare/GradleMergeViewer.java | 53 +++++++++ .../compare/GradleMergeViewerCreator.java | 24 +++++ .../ui/internal/compare/GradleViewer.java | 101 ++++++++++++++++++ .../internal/compare/GradleViewerCreator.java | 24 +++++ .../ui/internal/editor/GradleEditor.java | 11 ++ .../ui/internal/i18n/UiMessages.java | 1 + .../ui/internal/i18n/UiMessages.properties | 1 + 11 files changed, 256 insertions(+), 2 deletions(-) create mode 100644 org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/compare/GradleMergeViewer.java create mode 100644 org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/compare/GradleMergeViewerCreator.java create mode 100644 org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/compare/GradleViewer.java create mode 100644 org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/compare/GradleViewerCreator.java diff --git a/org.eclipse.buildship.kotlindsl.provider/META-INF/MANIFEST.MF b/org.eclipse.buildship.kotlindsl.provider/META-INF/MANIFEST.MF index a6a5b760c..8e7e640b6 100644 --- a/org.eclipse.buildship.kotlindsl.provider/META-INF/MANIFEST.MF +++ b/org.eclipse.buildship.kotlindsl.provider/META-INF/MANIFEST.MF @@ -12,6 +12,7 @@ Require-Bundle: org.eclipse.core.contenttype, org.eclipse.tm4e.registry, org.eclipse.jdt.launching, org.eclipse.swt, - org.eclipse.ui.genericeditor + org.eclipse.ui.genericeditor, + org.eclipse.compare Export-Package: org.eclipse.buildship.kotlindsl.provider diff --git a/org.eclipse.buildship.kotlindsl.provider/plugin.xml b/org.eclipse.buildship.kotlindsl.provider/plugin.xml index 25ab6e2e2..0fd24f1ad 100644 --- a/org.eclipse.buildship.kotlindsl.provider/plugin.xml +++ b/org.eclipse.buildship.kotlindsl.provider/plugin.xml @@ -42,5 +42,19 @@ label="Kotlin DSL language server"> + + + + + + + + diff --git a/org.eclipse.buildship.ui/META-INF/MANIFEST.MF b/org.eclipse.buildship.ui/META-INF/MANIFEST.MF index 8bb2997aa..ba325abeb 100644 --- a/org.eclipse.buildship.ui/META-INF/MANIFEST.MF +++ b/org.eclipse.buildship.ui/META-INF/MANIFEST.MF @@ -23,6 +23,7 @@ Require-Bundle: org.eclipse.buildship.core, com.ibm.icu, com.google.guava;bundle-version="33.0.0", org.gradle.toolingapi;bundle-version="[8.6.0,8.7.0)", - org.eclipse.ui.workbench.texteditor + org.eclipse.ui.workbench.texteditor, + org.eclipse.compare Bundle-ActivationPolicy: lazy Bundle-ClassPath: . diff --git a/org.eclipse.buildship.ui/plugin.xml b/org.eclipse.buildship.ui/plugin.xml index 4719cd31e..701a1df62 100644 --- a/org.eclipse.buildship.ui/plugin.xml +++ b/org.eclipse.buildship.ui/plugin.xml @@ -675,4 +675,27 @@ + + + + + + + + + + + + diff --git a/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/compare/GradleMergeViewer.java b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/compare/GradleMergeViewer.java new file mode 100644 index 000000000..0913672cf --- /dev/null +++ b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/compare/GradleMergeViewer.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2024 Gradle Inc. and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************/ +package org.eclipse.buildship.ui.internal.compare; + +import org.eclipse.compare.CompareConfiguration; +import org.eclipse.compare.contentmergeviewer.TextMergeViewer; +import org.eclipse.jface.text.IDocumentPartitioner; +import org.eclipse.jface.text.TextViewer; +import org.eclipse.jface.text.rules.FastPartitioner; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.swt.widgets.Composite; + +import org.eclipse.buildship.ui.internal.editor.GradleEditorConstants; +import org.eclipse.buildship.ui.internal.editor.GradlePartitionScanner; +import org.eclipse.buildship.ui.internal.editor.GradleTextViewerConfiguration; +import org.eclipse.buildship.ui.internal.i18n.UiMessages; + +public final class GradleMergeViewer extends TextMergeViewer { + + public GradleMergeViewer(Composite parent, CompareConfiguration configuration) { + super(parent, configuration); + } + + @Override + public String getTitle() { + return UiMessages.Title_Gradle_Build_Script_Compare; + } + + @Override + protected void configureTextViewer(TextViewer textViewer) { + if (textViewer instanceof ISourceViewer) { + ((ISourceViewer) textViewer).configure(new GradleTextViewerConfiguration()); + } + } + + @Override + protected IDocumentPartitioner getDocumentPartitioner() { + return new FastPartitioner(new GradlePartitionScanner(), GradleEditorConstants.PARTITIONS); + } + + @Override + protected String getDocumentPartitioning() { + return GradleEditorConstants.PARTITIONING; + } + +} diff --git a/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/compare/GradleMergeViewerCreator.java b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/compare/GradleMergeViewerCreator.java new file mode 100644 index 000000000..641cb9b41 --- /dev/null +++ b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/compare/GradleMergeViewerCreator.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2024 Gradle Inc. and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************/ +package org.eclipse.buildship.ui.internal.compare; + +import org.eclipse.compare.CompareConfiguration; +import org.eclipse.compare.IViewerCreator; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.widgets.Composite; + +public final class GradleMergeViewerCreator implements IViewerCreator { + + @Override + public Viewer createViewer(Composite parent, CompareConfiguration config) { + return new GradleMergeViewer(parent, config); + } + +} diff --git a/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/compare/GradleViewer.java b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/compare/GradleViewer.java new file mode 100644 index 000000000..7101e4c7a --- /dev/null +++ b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/compare/GradleViewer.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) 2024 Gradle Inc. and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************/ +package org.eclipse.buildship.ui.internal.compare; + +import java.io.IOException; +import java.io.InputStream; + +import org.eclipse.compare.IEncodedStreamContentAccessor; +import org.eclipse.compare.IStreamContentAccessor; +import org.eclipse.compare.contentmergeviewer.TextMergeViewer; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + +import org.eclipse.buildship.ui.internal.UiPlugin; +import org.eclipse.buildship.ui.internal.editor.GradleDocumentSetupParticipant; +import org.eclipse.buildship.ui.internal.editor.GradleTextViewerConfiguration; + +public final class GradleViewer extends Viewer { + + private final SourceViewer sourceViewer; + + private Object input; + + public GradleViewer(Composite parent) { + this.sourceViewer = new SourceViewer(parent, null, SWT.H_SCROLL | SWT.V_SCROLL); + this.sourceViewer.setEditable(false); + this.sourceViewer.configure(new GradleTextViewerConfiguration()); + + // use the same font as the TextMergeViewer + this.sourceViewer.getTextWidget().setFont(JFaceResources.getFont(TextMergeViewer.class.getName())); + } + + @Override + public Control getControl() { + return this.sourceViewer.getControl(); + } + + @Override + public Object getInput() { + return this.input; + } + + @Override + public ISelection getSelection() { + return StructuredSelection.EMPTY; + } + + @Override + public void refresh() { + // empty implementation + } + + @Override + public void setInput(Object input) { + this.input = input; + + if (!(input instanceof IStreamContentAccessor && input instanceof IEncodedStreamContentAccessor)) { + return; + } + + IEncodedStreamContentAccessor contentAccessor = (IEncodedStreamContentAccessor) input; + try (InputStream contents = contentAccessor.getContents()) { + if (contents == null) { + return; + } + + String charset = contentAccessor.getCharset(); + if (charset == null) { + charset = ResourcesPlugin.getEncoding(); + } + + Document document = new Document(new String(contents.readAllBytes(), charset)); + new GradleDocumentSetupParticipant().setup(document); + this.sourceViewer.setDocument(document); + } catch (CoreException | IOException e) { + UiPlugin.logger().error("Failed to set up input document.", e); + } + } + + @Override + public void setSelection(ISelection selection, boolean reveal) { + // empty implementation + } + +} diff --git a/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/compare/GradleViewerCreator.java b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/compare/GradleViewerCreator.java new file mode 100644 index 000000000..d98af217d --- /dev/null +++ b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/compare/GradleViewerCreator.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2024 Gradle Inc. and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************/ +package org.eclipse.buildship.ui.internal.compare; + +import org.eclipse.compare.CompareConfiguration; +import org.eclipse.compare.IViewerCreator; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.widgets.Composite; + +public final class GradleViewerCreator implements IViewerCreator { + + @Override + public Viewer createViewer(Composite parent, CompareConfiguration config) { + return new GradleViewer(parent); + } + +} diff --git a/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/editor/GradleEditor.java b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/editor/GradleEditor.java index 0a06ea4ae..ef98b31c2 100644 --- a/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/editor/GradleEditor.java +++ b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/editor/GradleEditor.java @@ -10,8 +10,11 @@ package org.eclipse.buildship.ui.internal.editor; import org.eclipse.ui.editors.text.EditorsUI; +import org.eclipse.ui.editors.text.ForwardingDocumentProvider; import org.eclipse.ui.editors.text.TextEditor; +import org.eclipse.ui.editors.text.TextFileDocumentProvider; import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants; +import org.eclipse.ui.texteditor.IDocumentProvider; /** * Editor definition for Gradle build scripts. @@ -19,10 +22,18 @@ * @author Christophe Moine */ public final class GradleEditor extends TextEditor { + + private static final IDocumentProvider DOCUMENT_PROVIDER = new ForwardingDocumentProvider(GradleEditorConstants.PARTITIONING, new GradleDocumentSetupParticipant(), + new TextFileDocumentProvider()); + @Override protected void initializeEditor() { super.initializeEditor(); setSourceViewerConfiguration(new GradleTextViewerConfiguration()); + + // This ensures that the document is set up correctly when it is opened from the History + // View. + setDocumentProvider(DOCUMENT_PROVIDER); } @Override diff --git a/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/i18n/UiMessages.java b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/i18n/UiMessages.java index 3fc0fcab4..3b042be2f 100644 --- a/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/i18n/UiMessages.java +++ b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/i18n/UiMessages.java @@ -19,6 +19,7 @@ public final class UiMessages extends NLS { private static final String BUNDLE_NAME = "org.eclipse.buildship.ui.internal.i18n.UiMessages"; //$NON-NLS-1$ public static String Title_Select_0; + public static String Title_Gradle_Build_Script_Compare; public static String Button_Label_Browse; diff --git a/org.eclipse.buildship.ui/src/main/resources/org/eclipse/buildship/ui/internal/i18n/UiMessages.properties b/org.eclipse.buildship.ui/src/main/resources/org/eclipse/buildship/ui/internal/i18n/UiMessages.properties index a66c102fb..7acac4166 100644 --- a/org.eclipse.buildship.ui/src/main/resources/org/eclipse/buildship/ui/internal/i18n/UiMessages.properties +++ b/org.eclipse.buildship.ui/src/main/resources/org/eclipse/buildship/ui/internal/i18n/UiMessages.properties @@ -8,6 +8,7 @@ # SPDX-License-Identifier: EPL-2.0 #------------------------------------------------------------------------------- Title_Select_0=Select {0} +Title_Gradle_Build_Script_Compare=Gradle Build Script Compare Button_Label_Browse=Browse...