Skip to content

Commit

Permalink
API to Track TextViewer install/uninstall in generic editor contribution
Browse files Browse the repository at this point in the history
Signed-off-by: azerr <[email protected]>
  • Loading branch information
angelozerr committed Nov 1, 2022
1 parent 1900585 commit bd18dd4
Show file tree
Hide file tree
Showing 15 changed files with 357 additions and 101 deletions.
7 changes: 4 additions & 3 deletions org.eclipse.ui.genericeditor/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ Require-Bundle: org.eclipse.ui.workbench.texteditor;bundle-version="3.10.0",
org.eclipse.core.resources;bundle-version="3.11.0",
org.eclipse.core.expressions;bundle-version="3.6.0",
org.eclipse.compare;resolution:=optional
Export-Package: org.eclipse.ui.internal.genericeditor;x-internal:=true,
Export-Package: org.eclipse.ui.genericeditor,
org.eclipse.ui.internal.genericeditor;x-internal:=true,
org.eclipse.ui.internal.genericeditor.compare;x-internal:=true,
org.eclipse.ui.internal.genericeditor.hover;x-internal:=true,
org.eclipse.ui.internal.genericeditor.markers;x-internal:=true,
org.eclipse.ui.internal.genericeditor.preferences;x-internal:=true,
org.eclipse.ui.internal.genericeditor.compare;x-internal:=true
org.eclipse.ui.internal.genericeditor.preferences;x-internal:=true
Bundle-Activator: org.eclipse.ui.internal.genericeditor.GenericEditorPlugin
Bundle-Localization: plugin
Bundle-ActivationPolicy: lazy
Expand Down
28 changes: 28 additions & 0 deletions org.eclipse.ui.genericeditor/schema/foldingReconcilers.exsd
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,34 @@
</complexType>
</element>

<element name="foldingReconcilingStrategy">
<complexType>
<sequence>
<element ref="enabledWhen" minOccurs="0" maxOccurs="1"/>
</sequence>
<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.IReconcilingStrategy&lt;/code&gt;
</documentation>
<appinfo>
<meta.attribute kind="java" basedOn=":org.eclipse.jface.text.reconciler.IReconcilingStrategy"/>
</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>

<element name="enabledWhen">
<annotation>
<documentation>
Expand Down
28 changes: 28 additions & 0 deletions org.eclipse.ui.genericeditor/schema/highlightReconcilers.exsd
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,34 @@
</complexType>
</element>

<element name="highlightReconcilingStrategy">
<complexType>
<sequence>
<element ref="enabledWhen" minOccurs="0" maxOccurs="1"/>
</sequence>
<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.IReconcilingStrategy&lt;/code&gt;
</documentation>
<appinfo>
<meta.attribute kind="java" basedOn=":org.eclipse.jface.text.reconciler.IReconcilingStrategy"/>
</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>

<element name="enabledWhen">
<annotation>
<documentation>
Expand Down
28 changes: 28 additions & 0 deletions org.eclipse.ui.genericeditor/schema/reconcilers.exsd
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,34 @@
</complexType>
</element>

<element name="reconcilingStrategy">
<complexType>
<sequence>
<element ref="enabledWhen" minOccurs="0" maxOccurs="1"/>
</sequence>
<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.IReconcilingStrategy&lt;/code&gt;
</documentation>
<appinfo>
<meta.attribute kind="java" basedOn=":org.eclipse.jface.text.reconciler.IReconcilingStrategy"/>
</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>

<element name="enabledWhen">
<annotation>
<documentation>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*******************************************************************************
* Copyright (c) 2022 Red Hat Inc. and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* - Angelo ZERR (Red Hat Inc.) - initial implementation
*******************************************************************************/
package org.eclipse.ui.genericeditor;

import org.eclipse.jface.text.ITextViewer;

/**
* {@link ITextViewer} lifecycle API to track install / uninstall of a given
* {@link ITextViewer}.
*
* @since 3.21
*
*/
public interface ITextViewerLifecycle {

/**
* Installs a text viewer.
*
* @param textViewer the text viewer
*/
void install(ITextViewer textViewer);

/**
* Uninstalls the registered text viewer.
*/
void uninstall();
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.jface.text.IAutoEditStrategy;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.ui.genericeditor.ITextViewerLifecycle;
import org.eclipse.ui.texteditor.ITextEditor;

/**
Expand Down Expand Up @@ -57,20 +58,22 @@ public AutoEditStrategyRegistry() {
* @param sourceViewer
* the source viewer we're hooking completion to.
* @param editor the text editor
* @param textViewerLifecycles the list of text viewer lifecycle to fill
* @param contentTypes
* the content types of the document we're editing.
* @return the list of {@link IAutoEditStrategy} contributed for at least
* one of the content types.
*/
public List<IAutoEditStrategy> getAutoEditStrategies(ISourceViewer sourceViewer, ITextEditor editor, Set<IContentType> contentTypes) {
public List<IAutoEditStrategy> getAutoEditStrategies(ISourceViewer sourceViewer, ITextEditor editor,
List<ITextViewerLifecycle> textViewerLifecycles, Set<IContentType> contentTypes) {
if (this.outOfSync) {
sync();
}
return this.extensions.values().stream()
.filter(ext -> contentTypes.contains(ext.targetContentType))
.filter(ext -> ext.matches(sourceViewer, editor))
.sorted(new ContentTypeSpecializationComparator<IAutoEditStrategy>())
.map(GenericContentTypeRelatedExtension<IAutoEditStrategy>::createDelegate)
return this.extensions.values().stream() //
.filter(ext -> contentTypes.contains(ext.targetContentType)) //
.filter(ext -> ext.matches(sourceViewer, editor)) //
.sorted(new ContentTypeSpecializationComparator<IAutoEditStrategy>()) //
.map(ext -> ext.createDelegate(textViewerLifecycles)) //
.collect(Collectors.toList());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.jface.text.source.ICharacterPairMatcher;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.ui.genericeditor.ITextViewerLifecycle;
import org.eclipse.ui.texteditor.ITextEditor;

/**
Expand Down Expand Up @@ -51,21 +52,23 @@ public CharacterPairMatcherRegistry() {
* Get the contributed {@link IPresentationReconciliers}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 editor the text editor
* @param contentTypes the content types of the document we're editing.
* @param sourceViewer the source viewer we're hooking completion to.
* @param editor the text editor
* @param textViewerLifecycles the list of text viewer lifecycle to fill
* @param contentTypes the content types of the document we're editing.
* @return the list of {@link ICharacterPairMatcher} contributed for at least
* one of the content types.
*/
public List<ICharacterPairMatcher> getCharacterPairMatchers(ISourceViewer sourceViewer, ITextEditor editor,
Set<IContentType> contentTypes) {
List<ITextViewerLifecycle> textViewerLifecycles, Set<IContentType> contentTypes) {
if (this.outOfSync) {
sync();
}
return this.extensions.values().stream().filter(ext -> contentTypes.contains(ext.targetContentType))
.filter(ext -> ext.matches(sourceViewer, editor))
.sorted(new ContentTypeSpecializationComparator<ICharacterPairMatcher>())
.map(GenericContentTypeRelatedExtension<ICharacterPairMatcher>::createDelegate)
return this.extensions.values().stream() //
.filter(ext -> contentTypes.contains(ext.targetContentType)) //
.filter(ext -> ext.matches(sourceViewer, editor)) //
.sorted(new ContentTypeSpecializationComparator<ICharacterPairMatcher>()) //
.map(ext -> ext.createDelegate(textViewerLifecycles)) //
.collect(Collectors.toList());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@
import org.eclipse.jface.text.contentassist.IContextInformationValidator;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.genericeditor.ITextViewerLifecycle;
import org.eclipse.ui.texteditor.ITextEditor;

/**
* A registry of content assist processors provided by extension <code>org.eclipse.ui.genericeditor.contentAssistProcessors</code>.
* Those extensions are specific to a given {@link IContentType}.
* A registry of content assist processors provided by extension
* <code>org.eclipse.ui.genericeditor.contentAssistProcessors</code>. Those
* extensions are specific to a given {@link IContentType}.
*
* @since 1.0
*/
Expand All @@ -57,19 +59,22 @@ public ContentAssistProcessorDelegate(IContentAssistProcessor delegate, IContent
}

/**
* @return whether the referenced contribution should contribute to the current editor.
* @return whether the referenced contribution should contribute to the current
* editor.
*/
public boolean isActive(ITextViewer viewer) {
String fileName = null;
if (viewer != null && viewer.getDocument() != null) {
IPath location = FileBuffers.getTextFileBufferManager().getTextFileBuffer(viewer.getDocument()).getLocation();
fileName = location.segment(location.segmentCount() - 1);
IPath location = FileBuffers.getTextFileBufferManager().getTextFileBuffer(viewer.getDocument())
.getLocation();
fileName = location.segment(location.segmentCount() - 1);
}
if (fileName == null) {
fileName = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor().getEditorInput().getName();
fileName = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor()
.getEditorInput().getName();
}
if (fileName != null) {
IContentTypeManager contentTypeManager= Platform.getContentTypeManager();
IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
for (IContentType currentContentType : contentTypeManager.findContentTypesFor(fileName)) {
if (currentContentType.isKindOf(targetContentType)) {
return true;
Expand Down Expand Up @@ -139,34 +144,41 @@ public ContentAssistProcessorRegistry() {
}

/**
* Get the contributed {@link IContentAssistProcessor}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 editor the text editor
* @param contentTypes the content types of the document we're editing.
* @return the list of {@link IContentAssistProcessor} contributed for at least one of the content types.
* Get the contributed {@link IContentAssistProcessor}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 editor the text editor
* @param textViewerLifecycles the list of text viewer lifecycle to fill
* @param contentTypes the content types of the document we're editing.
* @return the list of {@link IContentAssistProcessor} contributed for at least
* one of the content types.
*/
public List<IContentAssistProcessor> getContentAssistProcessors(ISourceViewer sourceViewer, ITextEditor editor, Set<IContentType> contentTypes) {
public List<IContentAssistProcessor> getContentAssistProcessors(ISourceViewer sourceViewer, ITextEditor editor,
List<ITextViewerLifecycle> textViewerLifecycles, Set<IContentType> contentTypes) {
if (this.outOfSync) {
sync();
}
return this.extensions.values().stream()
.filter(ext -> contentTypes.contains(ext.targetContentType))
.filter(ext -> ext.matches(sourceViewer, editor))
.sorted(new ContentTypeSpecializationComparator<IContentAssistProcessor>())
.map(GenericContentTypeRelatedExtension<IContentAssistProcessor>::createDelegate)
.collect(Collectors.toList());
return this.extensions.values().stream() //
.filter(ext -> contentTypes.contains(ext.targetContentType)) //
.filter(ext -> ext.matches(sourceViewer, editor)) //
.sorted(new ContentTypeSpecializationComparator<IContentAssistProcessor>()) //
.map(ext -> ext.createDelegate(textViewerLifecycles)) //
.collect(Collectors.toList());
}

private void sync() {
Set<IConfigurationElement> toRemoveExtensions = new HashSet<>(this.extensions.keySet());
for (IConfigurationElement extension : Platform.getExtensionRegistry().getConfigurationElementsFor(EXTENSION_POINT_ID)) {
for (IConfigurationElement extension : Platform.getExtensionRegistry()
.getConfigurationElementsFor(EXTENSION_POINT_ID)) {
toRemoveExtensions.remove(extension);
if (!this.extensions.containsKey(extension)) {
try {
this.extensions.put(extension, new GenericContentTypeRelatedExtension<IContentAssistProcessor>(extension));
this.extensions.put(extension,
new GenericContentTypeRelatedExtension<IContentAssistProcessor>(extension));
} catch (Exception ex) {
GenericEditorPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, GenericEditorPlugin.BUNDLE_ID, ex.getMessage(), ex));
GenericEditorPlugin.getDefault().getLog()
.log(new Status(IStatus.ERROR, GenericEditorPlugin.BUNDLE_ID, ex.getMessage(), ex));
}
}
}
Expand Down
Loading

0 comments on commit bd18dd4

Please sign in to comment.