diff options
author | Lucas Bullen | 2017-08-25 19:13:15 +0000 |
---|---|---|
committer | Lucas Bullen | 2017-08-31 15:25:27 +0000 |
commit | 15d0d12802084f3141bfdff8fe9136d1e3d691bb (patch) | |
tree | e5c2640d5936d25edd116d0feb3e914518dd6ff5 | |
parent | 153d18f2ec4f8ffa11eadcd344ab8e0135574abb (diff) | |
download | eclipse.platform.text-15d0d12802084f3141bfdff8fe9136d1e3d691bb.tar.gz eclipse.platform.text-15d0d12802084f3141bfdff8fe9136d1e3d691bb.tar.xz eclipse.platform.text-15d0d12802084f3141bfdff8fe9136d1e3d691bb.zip |
Bug 521418 - [GE] support multiple reconcilers for same contentTypeI20170904-0230I20170903-2000I20170902-1500I20170901-2000I20170831-2000
Adds all reconcilers to the editor in ascending order of specificity
Change-Id: I2abc3097b517176333a758b0a0025e12ac47a21e
Signed-off-by: Lucas Bullen <lbullen@redhat.com>
10 files changed, 265 insertions, 21 deletions
diff --git a/org.eclipse.ui.genericeditor.tests/plugin.xml b/org.eclipse.ui.genericeditor.tests/plugin.xml index 4d02c03dfc1..d2c3f4580ae 100644 --- a/org.eclipse.ui.genericeditor.tests/plugin.xml +++ b/org.eclipse.ui.genericeditor.tests/plugin.xml @@ -33,9 +33,13 @@ <extension point="org.eclipse.ui.genericeditor.reconcilers"> <reconciler - class="org.eclipse.ui.genericeditor.tests.contributions.TheReconciler" - contentType="org.eclipse.ui.genericeditor.tests.content-type"> + class="org.eclipse.ui.genericeditor.tests.contributions.TheReconcilerFirst" + contentType="org.eclipse.core.runtime.text"> </reconciler> + <reconciler + class="org.eclipse.ui.genericeditor.tests.contributions.TheReconcilerSecond" + contentType="org.eclipse.ui.genericeditor.tests.reconciled-content-type"> + </reconciler> </extension> <extension point="org.eclipse.ui.genericeditor.presentationReconcilers"> @@ -75,6 +79,13 @@ name="Specialized Generic Editor content-type" priority="normal"> </content-type> + <content-type + base-type="org.eclipse.core.runtime.text" + file-names="bar.txt" + id="org.eclipse.ui.genericeditor.tests.reconciled-content-type" + name="Generic Editor Reconciler Test content-type" + priority="normal"> + </content-type> </extension> <extension point="org.eclipse.ui.genericeditor.autoEditStrategies"> 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 index 294ba6831ac..56c4a7cd43a 100644 --- 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 @@ -26,6 +26,8 @@ import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.tests.util.DisplayHelper; import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.genericeditor.tests.contributions.ReconcilerStrategyFirst; +import org.eclipse.ui.genericeditor.tests.contributions.ReconcilerStrategySecond; import org.eclipse.ui.internal.genericeditor.ExtensionBasedTextEditor; import org.eclipse.ui.part.FileEditorInput; @@ -37,7 +39,7 @@ public class ReconcilerTest extends AbstratGenericEditorTest { @Test public void testReconciler() throws Exception { - performTestOnEditor(); + performTestOnEditor(ReconcilerStrategyFirst.SEARCH_TERM, editor, ReconcilerStrategyFirst.REPLACEMENT); } @Test @@ -49,26 +51,35 @@ public class ReconcilerTest extends AbstratGenericEditorTest { 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(); + performTestOnEditor(ReconcilerStrategyFirst.SEARCH_TERM, editor, ReconcilerStrategyFirst.REPLACEMENT); + } + + @Test + public void testMultipleReconcilers() throws Exception { + IFile secondFile = project.getFile("bar.txt"); + secondFile.create(new ByteArrayInputStream("".getBytes()), true, null); + secondEditor = (ExtensionBasedTextEditor) PlatformUI.getWorkbench().getActiveWorkbenchWindow() + .getActivePage().openEditor(new FileEditorInput(secondFile), "org.eclipse.ui.genericeditor.GenericEditor"); + performTestOnEditor(ReconcilerStrategyFirst.SEARCH_TERM, secondEditor, ReconcilerStrategySecond.REPLACEMENT); } - private void performTestOnEditor() throws Exception { - IDocumentProvider dp = editor.getDocumentProvider(); - IDocument doc = dp.getDocument(editor.getEditorInput()); + private void performTestOnEditor(String startingText, ExtensionBasedTextEditor textEditor, String expectedText) throws Exception { + IDocumentProvider dp = textEditor.getDocumentProvider(); + IDocument doc = dp.getDocument(textEditor.getEditorInput()); - doc.set("foo"); + doc.set(startingText); new DisplayHelper() { @Override protected boolean condition() { try { - return !doc.get(0, doc.getLineLength(0)).contains("foo"); + return doc.get(0, doc.getLineLength(0)).contains(expectedText); } catch (BadLocationException e) { return false; } } }.waitForCondition(Display.getDefault().getActiveShell().getDisplay(), 2000); - Assert.assertTrue("file was not affected by reconciler", doc.get().contains("BAR")); + Assert.assertTrue("file was not affected by reconciler", doc.get().contains(expectedText)); } } 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/ReconcilerStrategyFirst.java index dcb531448a6..8e86820ea43 100644 --- 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/ReconcilerStrategyFirst.java @@ -20,11 +20,11 @@ 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{ +public class ReconcilerStrategyFirst implements IReconcilingStrategy, IReconcilingStrategyExtension{ IDocument document; - static final String SEARCH_TERM = "foo"; - static final String REPLACEMENT = "BAR"; + public static final String SEARCH_TERM = "foo"; + public static final String REPLACEMENT = "BAR"; @Override public void setDocument(IDocument document) { diff --git a/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/ReconcilerStrategySecond.java b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/ReconcilerStrategySecond.java new file mode 100644 index 00000000000..eee876687e1 --- /dev/null +++ b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/ReconcilerStrategySecond.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 ReconcilerStrategySecond implements IReconcilingStrategy, IReconcilingStrategyExtension{ + + IDocument document; + public static final String SEARCH_TERM = "BAR"; + public static final String REPLACEMENT = "second"; + + @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/TheReconcilerFirst.java index 1e051433f7f..d7487027bdd 100644 --- 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/TheReconcilerFirst.java @@ -13,9 +13,8 @@ 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); +public class TheReconcilerFirst extends Reconciler{ + public TheReconcilerFirst() { + this.setReconcilingStrategy(new ReconcilerStrategyFirst(), IDocument.DEFAULT_CONTENT_TYPE); } } diff --git a/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/TheReconcilerSecond.java b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/TheReconcilerSecond.java new file mode 100644 index 00000000000..2d3bf4038ac --- /dev/null +++ b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/TheReconcilerSecond.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * 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 TheReconcilerSecond extends Reconciler{ + public TheReconcilerSecond() { + this.setReconcilingStrategy(new ReconcilerStrategySecond(), IDocument.DEFAULT_CONTENT_TYPE); + } +} diff --git a/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/CompositeReconciler.java b/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/CompositeReconciler.java new file mode 100644 index 00000000000..eb3f9f07cc5 --- /dev/null +++ b/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/CompositeReconciler.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * 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.List; +import java.util.Objects; + +import org.eclipse.jface.text.IDocumentExtension3; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.reconciler.IReconciler; +import org.eclipse.jface.text.reconciler.IReconcilerExtension; +import org.eclipse.jface.text.reconciler.IReconcilingStrategy; + +public class CompositeReconciler implements IReconciler, IReconcilerExtension { + private List<IReconciler> fReconcilers; + + public CompositeReconciler(List<IReconciler> reconcilers) { + fReconcilers = reconcilers; + } + + @Override + public String getDocumentPartitioning() { + boolean defaultFound = false; + String[] types = (String[]) fReconcilers.stream() + .filter(IReconcilerExtension.class::isInstance) + .map(IReconcilerExtension.class::cast) + .map(IReconcilerExtension::getDocumentPartitioning) + .filter(Objects::nonNull) + .toArray(); + for (String type : types) { + if (type.equals(IDocumentExtension3.DEFAULT_PARTITIONING)) { + defaultFound = true; + } else { + return type; + } + } + return defaultFound ? IDocumentExtension3.DEFAULT_PARTITIONING : null; + } + + @Override + public void install(ITextViewer textViewer) { + for (IReconciler iReconciler : fReconcilers) { + iReconciler.install(textViewer); + } + } + + @Override + public void uninstall() { + for (IReconciler iReconciler : fReconcilers) { + iReconciler.uninstall(); + } + } + + @Override + public IReconcilingStrategy getReconcilingStrategy(String contentType) { + return new CompositeReconcilerStrategy(fReconcilers, contentType); + + } +} diff --git a/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/CompositeReconcilerStrategy.java b/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/CompositeReconcilerStrategy.java new file mode 100644 index 00000000000..f302460a3e4 --- /dev/null +++ b/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/CompositeReconcilerStrategy.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * 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.List; + +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.IReconciler; +import org.eclipse.jface.text.reconciler.IReconcilingStrategy; +import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension; + +public class CompositeReconcilerStrategy implements IReconcilingStrategy, IReconcilingStrategyExtension{ + private List<IReconcilingStrategy> fReconcilingStrategies; + + public CompositeReconcilerStrategy(List<IReconciler> reconcilers, String contentType) { + this.fReconcilingStrategies = new ArrayList<>(); + for (IReconciler iReconciler : reconcilers) { + IReconcilingStrategy strategy = iReconciler.getReconcilingStrategy(contentType); + if(strategy != null) { + fReconcilingStrategies.add(strategy); + } + } + } + @Override + public void setProgressMonitor(IProgressMonitor monitor) { + for (IReconcilingStrategy iReconcilingStrategy : fReconcilingStrategies) { + if (iReconcilingStrategy instanceof IReconcilingStrategyExtension) { + ((IReconcilingStrategyExtension) iReconcilingStrategy).setProgressMonitor(monitor); + } + } + } + + @Override + public void initialReconcile() { + for (IReconcilingStrategy iReconcilingStrategy : fReconcilingStrategies) { + if (iReconcilingStrategy instanceof IReconcilingStrategyExtension) { + ((IReconcilingStrategyExtension) iReconcilingStrategy).initialReconcile(); + } + } + } + + @Override + public void setDocument(IDocument document) { + for (IReconcilingStrategy iReconcilingStrategy : fReconcilingStrategies) { + iReconcilingStrategy.setDocument(document); + } + } + + @Override + public void reconcile(DirtyRegion dirtyRegion, IRegion subRegion) { + for (IReconcilingStrategy iReconcilingStrategy : fReconcilingStrategies) { + iReconcilingStrategy.reconcile(dirtyRegion, subRegion); + } + } + + @Override + public void reconcile(IRegion partition) { + for (IReconcilingStrategy iReconcilingStrategy : fReconcilingStrategies) { + iReconcilingStrategy.reconcile(partition); + } + } + +} 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 47f7daf6690..ab43608f518 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 @@ -192,7 +192,7 @@ public final class ExtensionBasedTextViewerConfiguration extends TextSourceViewe ReconcilerRegistry registry = GenericEditorPlugin.getDefault().getReconcilerRegistry(); List<IReconciler> reconciliers = registry.getReconcilers(sourceViewer, getContentTypes()); if (!reconciliers.isEmpty()) { - return reconciliers.get(0); + return new CompositeReconciler(reconciliers); } return null; } 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 index 28d1f39f751..5d52e3cfd65 100644 --- 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 @@ -57,17 +57,19 @@ public class ReconcilerRegistry { * 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. + * @return the list of {@link IReconciler} contributed for at least one of the content types, + * sorted by most generic content type to most specific. */ public List<IReconciler> getReconcilers(ISourceViewer sourceViewer, Set<IContentType> contentTypes) { if (this.outOfSync) { sync(); } - return this.extensions.values().stream() + List<IReconciler> reconcilers = this.extensions.values().stream() .filter(ext -> contentTypes.contains(ext.targetContentType)) - .sorted(new ContentTypeSpecializationComparator<IReconciler>()) + .sorted(new ContentTypeSpecializationComparator<IReconciler>().reversed()) .map(GenericContentTypeRelatedExtension<IReconciler>::createDelegate) .collect(Collectors.toList()); + return reconcilers; } private void sync() { |