Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLucas Bullen2017-07-12 14:08:58 -0400
committerLucas Bullen2017-07-20 10:41:35 -0400
commit798ba99e71d97835741ac91d068afc2130c66bcc (patch)
treed69af12998dbb3279b999d63c71c05432c0acc45
parent8773dabab911ce83b5a7a4d9a5661e932a3fea4d (diff)
downloadeclipse.platform.text-798ba99e71d97835741ac91d068afc2130c66bcc.tar.gz
eclipse.platform.text-798ba99e71d97835741ac91d068afc2130c66bcc.tar.xz
eclipse.platform.text-798ba99e71d97835741ac91d068afc2130c66bcc.zip
Bug 508829 - [Generic Editor] provide a way to customize reconcilerI20170723-2000I20170722-2000I20170722-0045I20170721-2000I20170720-2000
- Extension point for reconcilers added - Example of use with folding Change-Id: I966e0fa4e5711fb85aa792361184fd7ddbcf0620 Signed-off-by: Lucas Bullen <lbullen@redhat.com>
-rw-r--r--org.eclipse.ui.genericeditor.examples/plugin.xml10
-rw-r--r--org.eclipse.ui.genericeditor.examples/src/org/eclipse/ui/genericeditor/examples/dotproject/FoldingReconciler.java33
-rw-r--r--org.eclipse.ui.genericeditor.examples/src/org/eclipse/ui/genericeditor/examples/dotproject/FoldingStrategy.java143
-rw-r--r--org.eclipse.ui.genericeditor.examples/src/org/eclipse/ui/genericeditor/examples/dotproject/SpellCheckDocumentListener.java8
-rw-r--r--org.eclipse.ui.genericeditor.tests/plugin.xml10
-rw-r--r--org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/GenericEditorTestSuite.java3
-rw-r--r--org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/ReconcilerTest.java74
-rw-r--r--org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/ReconcilerStrategy.java59
-rw-r--r--org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/TheReconciler.java21
-rw-r--r--org.eclipse.ui.genericeditor/plugin.properties2
-rw-r--r--org.eclipse.ui.genericeditor/plugin.xml4
-rw-r--r--org.eclipse.ui.genericeditor/schema/reconcilers.exsd116
-rw-r--r--org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/ExtensionBasedTextEditor.java30
-rw-r--r--org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/ExtensionBasedTextViewerConfiguration.java10
-rw-r--r--org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/GenericEditorPlugin.java15
-rw-r--r--org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/ReconcilerRegistry.java121
16 files changed, 649 insertions, 10 deletions
diff --git a/org.eclipse.ui.genericeditor.examples/plugin.xml b/org.eclipse.ui.genericeditor.examples/plugin.xml
index 60f20e05b..2ce9bebe1 100644
--- a/org.eclipse.ui.genericeditor.examples/plugin.xml
+++ b/org.eclipse.ui.genericeditor.examples/plugin.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<!-- ====================================================================== -->
-<!-- Copyright (c) 2016 Red Hat Inc. and others. -->
+<!-- Copyright (c) 2016, 2017 Red Hat Inc. and others. -->
<!-- All rights reserved. This program and the accompanying materials -->
<!-- are made available under the terms of the Eclipse Public License v1.0 -->
<!-- which accompanies this distribution, and is available at -->
@@ -9,6 +9,7 @@
<!-- -->
<!-- Contributors: -->
<!-- Sopot Cela & Mickael Istria (Red Hat Inc). -initial implementation -->
+<!-- Lucas Bullen (Red Hat Inc.) - Bug 508829 custom reconciler support -->
<!-- ====================================================================== -->
<plugin>
<extension
@@ -44,6 +45,13 @@
</presentationReconciler>
</extension>
<extension
+ point="org.eclipse.ui.genericeditor.reconcilers">
+ <reconciler
+ class="org.eclipse.ui.genericeditor.examples.dotproject.FoldingReconciler"
+ contentType="org.eclipse.ui.genericeditor.examples.dotproject">
+ </reconciler>
+ </extension>
+ <extension
point="org.eclipse.ui.editors">
<editorContentTypeBinding
contentTypeId="org.eclipse.ui.genericeditor.examples.dotproject"
diff --git a/org.eclipse.ui.genericeditor.examples/src/org/eclipse/ui/genericeditor/examples/dotproject/FoldingReconciler.java b/org.eclipse.ui.genericeditor.examples/src/org/eclipse/ui/genericeditor/examples/dotproject/FoldingReconciler.java
new file mode 100644
index 000000000..1db68ec8d
--- /dev/null
+++ b/org.eclipse.ui.genericeditor.examples/src/org/eclipse/ui/genericeditor/examples/dotproject/FoldingReconciler.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Red Hat Inc. and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Lucas Bullen (Red Hat Inc.) - initial implementation
+ *******************************************************************************/
+package org.eclipse.ui.genericeditor.examples.dotproject;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.reconciler.Reconciler;
+import org.eclipse.jface.text.source.projection.ProjectionViewer;
+
+public class FoldingReconciler extends Reconciler {
+
+ private FoldingStrategy fStrategy;
+
+ public FoldingReconciler() {
+ fStrategy = new FoldingStrategy();
+ this.setReconcilingStrategy(fStrategy, IDocument.DEFAULT_CONTENT_TYPE);
+ }
+
+ @Override
+ public void install(ITextViewer textViewer) {
+ super.install(textViewer);
+ ProjectionViewer pViewer =(ProjectionViewer)textViewer;
+ fStrategy.setProjectionViewer(pViewer);
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.ui.genericeditor.examples/src/org/eclipse/ui/genericeditor/examples/dotproject/FoldingStrategy.java b/org.eclipse.ui.genericeditor.examples/src/org/eclipse/ui/genericeditor/examples/dotproject/FoldingStrategy.java
new file mode 100644
index 000000000..42c36be84
--- /dev/null
+++ b/org.eclipse.ui.genericeditor.examples/src/org/eclipse/ui/genericeditor/examples/dotproject/FoldingStrategy.java
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Red Hat Inc. and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Lucas Bullen (Red Hat Inc.) - initial implementation
+ *******************************************************************************/
+package org.eclipse.ui.genericeditor.examples.dotproject;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.reconciler.DirtyRegion;
+import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
+import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.projection.ProjectionAnnotation;
+import org.eclipse.jface.text.source.projection.ProjectionViewer;
+
+public class FoldingStrategy implements IReconcilingStrategy, IReconcilingStrategyExtension {
+
+ private IDocument document;
+ private ProjectionViewer projectionViewer;
+ private Annotation[] oldAnnotations;
+
+ @Override
+ public void setDocument(IDocument document) {
+ this.document = document;
+ }
+
+ public void setProjectionViewer(ProjectionViewer projectionViewer) {
+ this.projectionViewer = projectionViewer;
+ }
+
+ @Override
+ public void reconcile(DirtyRegion dirtyRegion, IRegion subRegion) {
+ initialReconcile();
+ }
+
+ @Override
+ public void reconcile(IRegion partition) {
+ initialReconcile();
+ }
+
+ @Override
+ public void initialReconcile() {
+ List<Position> positions = getNewPositionsOfAnnotations();
+ Annotation[] annotations = new Annotation[positions.size()];
+
+ HashMap<Annotation, Position> newAnnotations = new HashMap<>();
+
+ for(int i =0;i<positions.size();i++)
+ {
+ ProjectionAnnotation annotation = new ProjectionAnnotation();
+ newAnnotations.put(annotation,positions.get(i));
+ annotations[i]=annotation;
+ }
+
+ projectionViewer.getProjectionAnnotationModel().modifyAnnotations(oldAnnotations,newAnnotations,null);
+ oldAnnotations=annotations;
+ }
+
+ private static enum SearchingFor {
+ START_OF_TAG, START_OF_WORD, END_OF_WORD, END_OF_LINE
+ }
+
+ private List<Position> getNewPositionsOfAnnotations(){
+ List<Position> positions = new ArrayList<>();
+ Map<String, Integer> startOfAnnotation = new HashMap<>();
+ SearchingFor searchingFor = SearchingFor.START_OF_TAG;
+
+ int characters = document.getLength();
+ int currentCharIndex = 0;
+
+ int wordStartIndex = 0;
+ int sectionStartIndex = 0;
+ String word = "";
+
+ try {
+ while (currentCharIndex < characters) {
+ char currentChar = document.getChar(currentCharIndex);
+ switch (searchingFor) {
+ case START_OF_TAG:
+ if(currentChar == '<') {
+ char nextChar = document.getChar(currentCharIndex+1);
+ if(nextChar != '?') {
+ sectionStartIndex = currentCharIndex;
+ searchingFor = SearchingFor.START_OF_WORD;
+ }
+ }
+ break;
+ case START_OF_WORD:
+ if(Character.isLetter(currentChar)) {
+ wordStartIndex = currentCharIndex;
+ searchingFor = SearchingFor.END_OF_WORD;
+ }
+ break;
+ case END_OF_WORD:
+ if(!Character.isLetter(currentChar)) {
+ word = document.get(wordStartIndex, currentCharIndex - wordStartIndex);
+ if(startOfAnnotation.containsKey(word)) {
+ searchingFor = SearchingFor.END_OF_LINE;
+ }else {
+ startOfAnnotation.put(word, sectionStartIndex);
+ searchingFor = SearchingFor.START_OF_TAG;
+ }
+ }
+ break;
+ case END_OF_LINE:
+ if(currentChar == '\n') {
+ int start = startOfAnnotation.get(word);
+ if(document.getLineOfOffset(start) != document.getLineOfOffset(currentCharIndex)) {
+ positions.add(new Position(start,currentCharIndex + 1 - start));
+ }
+ startOfAnnotation.remove(word);
+ searchingFor = SearchingFor.START_OF_TAG;
+ }
+ break;
+ }
+ currentCharIndex++;
+ }
+ } catch (BadLocationException e) {
+ // skip the remainder of file due to error
+ }
+ return positions;
+ }
+
+ @Override
+ public void setProgressMonitor(IProgressMonitor monitor) {
+ // no progress monitor used
+ }
+
+} \ No newline at end of file
diff --git a/org.eclipse.ui.genericeditor.examples/src/org/eclipse/ui/genericeditor/examples/dotproject/SpellCheckDocumentListener.java b/org.eclipse.ui.genericeditor.examples/src/org/eclipse/ui/genericeditor/examples/dotproject/SpellCheckDocumentListener.java
index 9ea533fef..9b247fd9c 100644
--- a/org.eclipse.ui.genericeditor.examples/src/org/eclipse/ui/genericeditor/examples/dotproject/SpellCheckDocumentListener.java
+++ b/org.eclipse.ui.genericeditor.examples/src/org/eclipse/ui/genericeditor/examples/dotproject/SpellCheckDocumentListener.java
@@ -7,6 +7,7 @@
*
* Contributors:
* - Mickael Istria (Red Hat Inc.)
+ * - Lucas Bullen (Red Hat Inc.) - avoid NPE for when TextFileBuffer does not exist
*******************************************************************************/
package org.eclipse.ui.genericeditor.examples.dotproject;
@@ -15,6 +16,7 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+import org.eclipse.core.filebuffers.ITextFileBuffer;
import org.eclipse.core.filebuffers.ITextFileBufferManager;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
@@ -50,7 +52,11 @@ public class SpellCheckDocumentListener implements IDocumentListener {
this.lastJob = new Job("Spellcheck") {
@Override
protected IStatus run(IProgressMonitor monitor) {
- IAnnotationModel model = ITextFileBufferManager.DEFAULT.getTextFileBuffer(event.getDocument()).getAnnotationModel();
+ ITextFileBuffer iTextFileBuffer = ITextFileBufferManager.DEFAULT.getTextFileBuffer(event.getDocument());
+ if(iTextFileBuffer == null) {
+ return Status.CANCEL_STATUS;
+ }
+ IAnnotationModel model = iTextFileBuffer.getAnnotationModel();
String text = event.getDocument().get();
int commentStart = text.indexOf("<comment>");
if (commentStart < 0) {
diff --git a/org.eclipse.ui.genericeditor.tests/plugin.xml b/org.eclipse.ui.genericeditor.tests/plugin.xml
index 4f199ed08..a6b412453 100644
--- a/org.eclipse.ui.genericeditor.tests/plugin.xml
+++ b/org.eclipse.ui.genericeditor.tests/plugin.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<!-- ====================================================================== -->
-<!-- Copyright (c) 2016 Red Hat Inc. and others. -->
+<!-- Copyright (c) 2016, 2017 Red Hat Inc. and others. -->
<!-- All rights reserved. This program and the accompanying materials -->
<!-- are made available under the terms of the Eclipse Public License v1.0 -->
<!-- which accompanies this distribution, and is available at -->
@@ -9,6 +9,7 @@
<!-- -->
<!-- Contributors: -->
<!-- Sopot Cela & Mickael Istria (Red Hat Inc). -initial implementation -->
+<!-- Lucas Bullen (Red Hat Inc.) - Bug 508829 custom reconciler support -->
<!-- ====================================================================== -->
<plugin>
<extension
@@ -29,6 +30,13 @@
contentType="org.eclipse.ui.genericeditor.tests.content-type">
</hoverProvider>
</extension>
+ <extension
+ point="org.eclipse.ui.genericeditor.reconcilers">
+ <reconciler
+ class="org.eclipse.ui.genericeditor.tests.contributions.TheReconciler"
+ contentType="org.eclipse.ui.genericeditor.tests.content-type">
+ </reconciler>
+ </extension>
<extension
point="org.eclipse.ui.genericeditor.presentationReconcilers">
<presentationReconciler
diff --git a/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/GenericEditorTestSuite.java b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/GenericEditorTestSuite.java
index 96361db40..bf987dcca 100644
--- a/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/GenericEditorTestSuite.java
+++ b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/GenericEditorTestSuite.java
@@ -20,7 +20,8 @@ import org.junit.runners.Suite.SuiteClasses;
StylingTest.class,
HoverTest.class,
EditorTest.class,
- AutoEditTest.class
+ AutoEditTest.class,
+ ReconcilerTest.class
})
public class GenericEditorTestSuite {
// see @SuiteClasses
diff --git a/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/ReconcilerTest.java b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/ReconcilerTest.java
new file mode 100644
index 000000000..294ba6831
--- /dev/null
+++ b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/ReconcilerTest.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Red Hat Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Lucas Bullen (Red Hat Inc.) - initial implementation
+ *******************************************************************************/
+package org.eclipse.ui.genericeditor.tests;
+
+import java.io.ByteArrayInputStream;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.eclipse.swt.widgets.Display;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.tests.util.DisplayHelper;
+
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.internal.genericeditor.ExtensionBasedTextEditor;
+import org.eclipse.ui.part.FileEditorInput;
+
+import org.eclipse.ui.texteditor.IDocumentProvider;
+
+public class ReconcilerTest extends AbstratGenericEditorTest {
+
+ protected ExtensionBasedTextEditor secondEditor;
+
+ @Test
+ public void testReconciler() throws Exception {
+ performTestOnEditor();
+ }
+
+ @Test
+ public void testMultipleEditors() throws Exception {
+ IProject secondProject = ResourcesPlugin.getWorkspace().getRoot().getProject(getClass().getName() + System.currentTimeMillis());
+ secondProject.create(null);
+ secondProject.open(null);
+ IFile secondFile = secondProject.getFile("foo.txt");
+ secondFile.create(new ByteArrayInputStream("bar 'bar'".getBytes()), true, null);
+ secondEditor = (ExtensionBasedTextEditor) PlatformUI.getWorkbench().getActiveWorkbenchWindow()
+ .getActivePage().openEditor(new FileEditorInput(secondFile), "org.eclipse.ui.genericeditor.GenericEditor");
+ performTestOnEditor();
+ }
+
+ private void performTestOnEditor() throws Exception {
+ IDocumentProvider dp = editor.getDocumentProvider();
+ IDocument doc = dp.getDocument(editor.getEditorInput());
+
+ doc.set("foo");
+
+ new DisplayHelper() {
+ @Override
+ protected boolean condition() {
+ try {
+ return !doc.get(0, doc.getLineLength(0)).contains("foo");
+ } catch (BadLocationException e) {
+ return false;
+ }
+ }
+ }.waitForCondition(Display.getDefault().getActiveShell().getDisplay(), 2000);
+ Assert.assertTrue("file was not affected by reconciler", doc.get().contains("BAR"));
+ }
+
+}
diff --git a/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/ReconcilerStrategy.java b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/ReconcilerStrategy.java
new file mode 100644
index 000000000..dcb531448
--- /dev/null
+++ b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/ReconcilerStrategy.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Red Hat Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Lucas Bullen (Red Hat Inc.) - initial implementation
+ *******************************************************************************/
+package org.eclipse.ui.genericeditor.tests.contributions;
+
+import org.eclipse.swt.widgets.Display;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.reconciler.DirtyRegion;
+import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
+import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension;
+
+public class ReconcilerStrategy implements IReconcilingStrategy, IReconcilingStrategyExtension{
+
+ IDocument document;
+ static final String SEARCH_TERM = "foo";
+ static final String REPLACEMENT = "BAR";
+
+ @Override
+ public void setDocument(IDocument document) {
+ this.document = document;
+ }
+
+ @Override
+ public void reconcile(DirtyRegion dirtyRegion, IRegion subRegion) {
+ initialReconcile();
+ }
+
+ @Override
+ public void reconcile(IRegion partition) {
+ initialReconcile();
+ }
+
+ @Override
+ public void setProgressMonitor(IProgressMonitor monitor) {
+ // no progress monitor in use
+ }
+
+ @Override
+ public void initialReconcile() {
+ String doc = document.get();
+ if(doc.contains(SEARCH_TERM)) {
+ Display.getDefault().asyncExec(() -> {
+ document.set(document.get().replaceAll(SEARCH_TERM, REPLACEMENT));
+ });
+ }
+ }
+
+}
diff --git a/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/TheReconciler.java b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/TheReconciler.java
new file mode 100644
index 000000000..1e051433f
--- /dev/null
+++ b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/TheReconciler.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Red Hat Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Lucas Bullen (Red Hat Inc.) - initial implementation
+ *******************************************************************************/
+package org.eclipse.ui.genericeditor.tests.contributions;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.reconciler.Reconciler;
+
+public class TheReconciler extends Reconciler{
+ public TheReconciler() {
+ ReconcilerStrategy signStrategy = new ReconcilerStrategy();
+ this.setReconcilingStrategy(signStrategy, IDocument.DEFAULT_CONTENT_TYPE);
+ }
+}
diff --git a/org.eclipse.ui.genericeditor/plugin.properties b/org.eclipse.ui.genericeditor/plugin.properties
index 48fe4e7c6..eee5f9897 100644
--- a/org.eclipse.ui.genericeditor/plugin.properties
+++ b/org.eclipse.ui.genericeditor/plugin.properties
@@ -7,8 +7,10 @@
#
# Contributors:
# Sopot Cela & Mickael Istria (Red Hat Inc.) - initial implementation
+# Lucas Bullen (Red Hat Inc.) - Bug 508829 custom reconciler support
###############################################################################
genericEditor_name=Generic Text Editor
+ExtPoint.reconciliers=Reconciliers
ExtPoint.presentationReconciliers=Presentation Reconciliers
ExtPoint.hoverProviders= Hover Providers
ExtPoint.contentAssistProcessors=Content Assist Providers
diff --git a/org.eclipse.ui.genericeditor/plugin.xml b/org.eclipse.ui.genericeditor/plugin.xml
index c58bfc082..28e7a1dd9 100644
--- a/org.eclipse.ui.genericeditor/plugin.xml
+++ b/org.eclipse.ui.genericeditor/plugin.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<!-- ====================================================================== -->
-<!-- Copyright (c) 2016 Red Hat Inc. and others. -->
+<!-- Copyright (c) 2016, 2017 Red Hat Inc. and others. -->
<!-- All rights reserved. This program and the accompanying materials -->
<!-- are made available under the terms of the Eclipse Public License v1.0 -->
<!-- which accompanies this distribution, and is available at -->
@@ -9,8 +9,10 @@
<!-- -->
<!-- Contributors: -->
<!-- Sopot Cela & Mickael Istria (Red Hat Inc). -initial implementation -->
+<!-- Lucas Bullen (Red Hat Inc.) - Bug 508829 custom reconciler support -->
<!-- ====================================================================== -->
<plugin>
+ <extension-point id="reconcilers" name="%ExtPoint.reconciliers" schema="schema/reconcilers.exsd"/>
<extension-point id="presentationReconcilers" name="%ExtPoint.presentationReconciliers" schema="schema/presentationReconcilers.exsd"/>
<extension-point id="contentAssistProcessors" name="%ExtPoint.contentAssistProcessors" schema="schema/contentAssistProcessors.exsd"/>
<extension-point id="hoverProviders" name="%ExtPoint.hoverProviders" schema="schema/hoverProviders.exsd"/>
diff --git a/org.eclipse.ui.genericeditor/schema/reconcilers.exsd b/org.eclipse.ui.genericeditor/schema/reconcilers.exsd
new file mode 100644
index 000000000..5b36bc98d
--- /dev/null
+++ b/org.eclipse.ui.genericeditor/schema/reconcilers.exsd
@@ -0,0 +1,116 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.ui.genericeditor" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+ <appinfo>
+ <meta.schema plugin="org.eclipse.ui.genericeditor" id="reconcilers" name="Reconcilers"/>
+ </appinfo>
+ <documentation>
+ This extension point is used to contribute reconcilers for controlling the presentation on a file with a given content type.
+ </documentation>
+ </annotation>
+
+ <include schemaLocation="schema://org.eclipse.core.expressions/schema/expressionLanguage.exsd"/>
+
+ <element name="extension">
+ <annotation>
+ <appinfo>
+ <meta.element />
+ </appinfo>
+ </annotation>
+ <complexType>
+ <sequence minOccurs="1" maxOccurs="unbounded">
+ <element ref="reconciler"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+ a fully qualified identifier of the target extension point
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+ an optional identifier of the extension instance
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+ an optional name of the extension instance
+ </documentation>
+ <appinfo>
+ <meta.attribute translatable="true"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="reconciler">
+ <complexType>
+ <attribute name="class" type="string" use="required">
+ <annotation>
+ <documentation>
+ The fully qualified class name implementing the interface &lt;code&gt;org.eclipse.jface.text.reconciler.IReconciler&lt;/code&gt;
+ </documentation>
+ <appinfo>
+ <meta.attribute kind="java" basedOn=":org.eclipse.jface.text.reconciler.IReconciler"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ <attribute name="contentType" type="string" use="required">
+ <annotation>
+ <documentation>
+ The target content-type for this extension. Content-types are defined as extension to the org.eclipse.core.contenttype.contentTypes extension point.
+ </documentation>
+ <appinfo>
+ <meta.attribute kind="identifier" basedOn="org.eclipse.core.contenttype.contentTypes/content-type/@id"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="since"/>
+ </appinfo>
+ <documentation>
+ 1.1
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="examples"/>
+ </appinfo>
+ <documentation>
+ Below is an example of how to use the Reconciler extension point:
+
+&lt;pre&gt;
+&lt;extension point=&quot;org.eclipse.ui.genericeditor.reconcilers&quot;&gt;
+ &lt;reconciler
+ class=&quot;org.eclipse.ui.genericeditor.examples.TPReconciler&quot;
+ contentType=&quot;org.eclipse.pde.targetFile&quot;&gt;
+ &lt;/reconciler&gt;
+&lt;/extension&gt;
+&lt;/pre&gt;
+ </documentation>
+ </annotation>
+
+
+
+ <annotation>
+ <appinfo>
+ <meta.section type="copyright"/>
+ </appinfo>
+ <documentation>
+ Copyright (c) 2017 Red Hat Inc. and others
+All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at &lt;a href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+ </documentation>
+ </annotation>
+
+</schema>
diff --git a/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/ExtensionBasedTextEditor.java b/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/ExtensionBasedTextEditor.java
index 26140d3b6..dbdc3b840 100644
--- a/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/ExtensionBasedTextEditor.java
+++ b/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/ExtensionBasedTextEditor.java
@@ -7,17 +7,23 @@
*
* Contributors:
* Sopot Cela, Mickael Istria (Red Hat Inc.) - initial implementation
+ * Lucas Bullen (Red Hat Inc.) - Bug 508829 custom reconciler support
*******************************************************************************/
package org.eclipse.ui.internal.genericeditor;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.IVerticalRuler;
+import org.eclipse.jface.text.source.projection.ProjectionSupport;
+import org.eclipse.jface.text.source.projection.ProjectionViewer;
+import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.editors.text.TextEditor;
/**
* A generic code editor that is aimed at being extended by contributions. Behavior
* is supposed to be added via extensions, not by inheritance.
- *
+ *
* @since 1.0
*/
public class ExtensionBasedTextEditor extends TextEditor {
@@ -32,7 +38,7 @@ public class ExtensionBasedTextEditor extends TextEditor {
configuration = new ExtensionBasedTextViewerConfiguration(this, getPreferenceStore());
setSourceViewerConfiguration(configuration);
}
-
+
@Override
protected void setKeyBindingScopes(String[] scopes) {
super.setKeyBindingScopes(new String[] { CONTEXT_ID });
@@ -44,4 +50,24 @@ public class ExtensionBasedTextEditor extends TextEditor {
configuration.watchDocument(getDocumentProvider().getDocument(input));
}
+ @Override
+ protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) {
+ fAnnotationAccess= getAnnotationAccess();
+ fOverviewRuler= createOverviewRuler(getSharedColors());
+
+ ProjectionViewer viewer= new ProjectionViewer(parent, ruler, getOverviewRuler(), isOverviewRulerVisible(), styles);
+ getSourceViewerDecorationSupport(viewer);
+ return viewer;
+ }
+
+
+ @Override
+ public void createPartControl(Composite parent)
+ {
+ super.createPartControl(parent);
+ ProjectionViewer viewer =(ProjectionViewer)getSourceViewer();
+
+ new ProjectionSupport(viewer,getAnnotationAccess(),getSharedColors()).install();
+ viewer.doOperation(ProjectionViewer.TOGGLE);
+ }
}
diff --git a/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/ExtensionBasedTextViewerConfiguration.java b/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/ExtensionBasedTextViewerConfiguration.java
index 7c1a3364b..47f7daf66 100644
--- a/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/ExtensionBasedTextViewerConfiguration.java
+++ b/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/ExtensionBasedTextViewerConfiguration.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2016 Red Hat Inc. and others.
+ * Copyright (c) 2016, 2017 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,6 +7,7 @@
*
* Contributors:
* Sopot Cela, Mickael Istria (Red Hat Inc.) - initial implementation
+ * Lucas Bullen (Red Hat Inc.) - Bug 508829 custom reconciler support
*******************************************************************************/
package org.eclipse.ui.internal.genericeditor;
@@ -188,7 +189,12 @@ public final class ExtensionBasedTextViewerConfiguration extends TextSourceViewe
@Override
public IReconciler getReconciler(ISourceViewer sourceViewer) {
- return null; // to disable spell-checker
+ ReconcilerRegistry registry = GenericEditorPlugin.getDefault().getReconcilerRegistry();
+ List<IReconciler> reconciliers = registry.getReconcilers(sourceViewer, getContentTypes());
+ if (!reconciliers.isEmpty()) {
+ return reconciliers.get(0);
+ }
+ return null;
}
@Override
diff --git a/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/GenericEditorPlugin.java b/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/GenericEditorPlugin.java
index ef8a0145c..8bdf7a4cf 100644
--- a/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/GenericEditorPlugin.java
+++ b/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/GenericEditorPlugin.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2016 Red Hat Inc. and others.
+ * Copyright (c) 2016, 2017 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,6 +7,7 @@
*
* Contributors:
* Sopot Cela, Mickael Istria (Red Hat Inc.) - initial implementation
+ * Lucas Bullen (Red Hat Inc.) - Bug 508829 custom reconciler support
*******************************************************************************/
package org.eclipse.ui.internal.genericeditor;
@@ -29,6 +30,7 @@ public class GenericEditorPlugin extends AbstractUIPlugin {
private TextHoverRegistry textHoversRegistry;
private ContentAssistProcessorRegistry contentAssistProcessorsRegistry;
+ private ReconcilerRegistry reconcilierRegistry;
private PresentationReconcilerRegistry presentationReconcilierRegistry;
private AutoEditStrategyRegistry autoEditStrategyRegistry;
@@ -69,6 +71,17 @@ public class GenericEditorPlugin extends AbstractUIPlugin {
}
return this.contentAssistProcessorsRegistry;
}
+
+ /**
+ * @return the registry allowing to access contributed {@link IReconciler}s.
+ * @since 1.1
+ */
+ public synchronized ReconcilerRegistry getReconcilerRegistry() {
+ if (this.reconcilierRegistry == null) {
+ this.reconcilierRegistry = new ReconcilerRegistry();
+ }
+ return this.reconcilierRegistry;
+ }
/**
* @return the registry allowing to access contributed {@link IPresentationReconciler}s.
diff --git a/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/ReconcilerRegistry.java b/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/ReconcilerRegistry.java
new file mode 100644
index 000000000..c942335a0
--- /dev/null
+++ b/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/ReconcilerRegistry.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Red Hat Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Lucas Bullen (Red Hat Inc.) - initial implementation
+ *******************************************************************************/
+package org.eclipse.ui.internal.genericeditor;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IRegistryChangeEvent;
+import org.eclipse.core.runtime.IRegistryChangeListener;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.jface.text.reconciler.IReconciler;
+import org.eclipse.jface.text.source.ISourceViewer;
+
+/**
+ * A registry of reconciliers provided by extension <code>org.eclipse.ui.genericeditor.reconcilers</code>.
+ * Those extensions are specific to a given {@link IContentType}.
+ *
+ * @since 1.1
+ */
+public class ReconcilerRegistry {
+
+ private static final String EXTENSION_POINT_ID = GenericEditorPlugin.BUNDLE_ID + ".reconcilers"; //$NON-NLS-1$
+
+ /**
+ * This class wraps and proxies an {@link IReconciler} provided through extensions
+ * and loads it lazily when it can contribute to the editor, then delegates all operations to
+ * actual reconcilier.
+ */
+ private static class ReconcilerExtension {
+ private static final String CLASS_ATTRIBUTE = "class"; //$NON-NLS-1$
+ private static final String CONTENT_TYPE_ATTRIBUTE = "contentType"; //$NON-NLS-1$
+
+ private IConfigurationElement extension;
+ private IContentType targetContentType;
+
+ private ReconcilerExtension(IConfigurationElement element) throws Exception {
+ this.extension = element;
+ this.targetContentType = Platform.getContentTypeManager().getContentType(element.getAttribute(CONTENT_TYPE_ATTRIBUTE));
+ }
+
+ public IReconciler createDelegate() {
+ try {
+ return (IReconciler) extension.createExecutableExtension(CLASS_ATTRIBUTE);
+ } catch (CoreException e) {
+ GenericEditorPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, GenericEditorPlugin.BUNDLE_ID, e.getMessage(), e));
+ }
+ return null;
+ }
+
+ }
+ private Map<IConfigurationElement, ReconcilerExtension> extensions = new HashMap<>();
+ private boolean outOfSync = true;
+
+ /**
+ * Creates the registry and binds it to the extension point.
+ */
+ public ReconcilerRegistry() {
+ Platform.getExtensionRegistry().addRegistryChangeListener(new IRegistryChangeListener() {
+ @Override
+ public void registryChanged(IRegistryChangeEvent event) {
+ outOfSync = true;
+ }
+ }, EXTENSION_POINT_ID);
+ }
+
+ /**
+ * Get the contributed {@link IReconciliers}s that are relevant to hook on source viewer according
+ * to document content types.
+ * @param sourceViewer the source viewer we're hooking completion to.
+ * @param contentTypes the content types of the document we're editing.
+ * @return the list of {@link IReconciler} contributed for at least one of the content types.
+ */
+ public List<IReconciler> getReconcilers(ISourceViewer sourceViewer, Set<IContentType> contentTypes) {
+ if (this.outOfSync) {
+ sync();
+ }
+ List<IReconciler> res = new ArrayList<>();
+ for (ReconcilerExtension ext : this.extensions.values()) {
+ if (contentTypes.contains(ext.targetContentType)) {
+ res.add(ext.createDelegate());
+ }
+ }
+ return res;
+ }
+
+ private void sync() {
+ Set<IConfigurationElement> toRemoveExtensions = new HashSet<>(this.extensions.keySet());
+ for (IConfigurationElement extension : Platform.getExtensionRegistry().getConfigurationElementsFor(EXTENSION_POINT_ID)) {
+ toRemoveExtensions.remove(extension);
+ if (!this.extensions.containsKey(extension)) {
+ try {
+ this.extensions.put(extension, new ReconcilerExtension(extension));
+ } catch (Exception ex) {
+ GenericEditorPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, GenericEditorPlugin.BUNDLE_ID, ex.getMessage(), ex));
+ }
+ }
+ }
+ for (IConfigurationElement toRemove : toRemoveExtensions) {
+ this.extensions.remove(toRemove);
+ }
+ this.outOfSync = false;
+ }
+
+}

Back to the top