diff options
author | Lucas Bullen | 2017-07-12 18:08:58 +0000 |
---|---|---|
committer | Lucas Bullen | 2017-07-20 14:41:35 +0000 |
commit | 798ba99e71d97835741ac91d068afc2130c66bcc (patch) | |
tree | d69af12998dbb3279b999d63c71c05432c0acc45 | |
parent | 8773dabab911ce83b5a7a4d9a5661e932a3fea4d (diff) | |
download | eclipse.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>
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 60f20e05bd5..2ce9bebe1ef 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 00000000000..1db68ec8d59 --- /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 00000000000..42c36be84bc --- /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 9ea533fef7d..9b247fd9c75 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 4f199ed08d8..a6b4124536f 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 96361db40d1..bf987dcca97 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 00000000000..294ba6831ac --- /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 00000000000..dcb531448a6 --- /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 00000000000..1e051433f7f --- /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 48fe4e7c61a..eee5f989794 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 c58bfc082ab..28e7a1dd96c 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 00000000000..5b36bc98d76 --- /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 <code>org.eclipse.jface.text.reconciler.IReconciler</code> + </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: + +<pre> +<extension point="org.eclipse.ui.genericeditor.reconcilers"> + <reconciler + class="org.eclipse.ui.genericeditor.examples.TPReconciler" + contentType="org.eclipse.pde.targetFile"> + </reconciler> +</extension> +</pre> + </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 <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a> + </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 26140d3b646..dbdc3b840ef 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 7c1a3364bf1..47f7daf6690 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 ef8a0145c96..8bdf7a4cf52 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 00000000000..c942335a0dc --- /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; + } + +} |