Skip to content

Commit

Permalink
fix: handle grammar registrations to the same scope by different plugins
Browse files Browse the repository at this point in the history
Without this change grammar registrations from different plugins sharing
the same scope name could unpredictably overwrite each other.

With this change, grammars are registered using fully qualified scope
names (scopeName + '@' + pluginId). If plugin A supplies a
content-type-to-scope and registers a grammar to that scope, it is
ensured that if another plugin B also registers a grammar using the same
scope, there won't be accidental usage of the plugin B's grammar via
plugin A's content-type-to-scope binding.

The change also makes multiple grammar registrations for the same scope
visible in the Preferences>TextMate>Grammars table.
  • Loading branch information
sebthom committed Dec 23, 2023
1 parent 52fd736 commit 4199ad9
Show file tree
Hide file tree
Showing 14 changed files with 303 additions and 127 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Local work folder that is not checked in
_LOCAL/

# Eclipse
/bin
/*/bin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tm4e.registry.internal.TMScope;

/**
* Grammar definition defined by the "org.eclipse.tm4e.registry.grammars"
Expand All @@ -31,20 +32,15 @@
*/
public class GrammarDefinition extends TMResource implements IGrammarDefinition {

@Nullable
private String scopeName;
private String scopeName = "<set-by-gson>";
private transient @Nullable ITMScope scope;

/**
* Constructor for user preferences (loaded from Json with Gson).
*/
public GrammarDefinition() {
}

/**
* Constructor for extension point.
*
* @param scopeName
*/
public GrammarDefinition(final String scopeName, final String path) {
super(path);
this.scopeName = scopeName;
Expand All @@ -56,8 +52,11 @@ public GrammarDefinition(final IConfigurationElement ce) {
}

@Override
public String getScopeName() {
assert scopeName != null;
return scopeName;
public ITMScope getScope() {
ITMScope scope = this.scope;
if (scope == null) {
this.scope = scope = new TMScope(scopeName, getPluginId());
}
return scope;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,11 @@

/**
* TextMate grammar definition API.
*
*/
public interface IGrammarDefinition extends ITMResource {

/**
* Returns the scope name of the TextMate grammar.
*
* @return the scope name of the TextMate grammar.
* @return the scope of the TextMate grammar.
*/
String getScopeName();
ITMScope getScope();
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
package org.eclipse.tm4e.registry;

import java.util.Collection;
import java.util.List;

import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.jdt.annotation.Nullable;
Expand Down Expand Up @@ -65,7 +64,7 @@ public interface IGrammarRegistryManager {
* @return the {@link IGrammar} for the given scope name and null otherwise.
*/
@Nullable
IGrammar getGrammarForScope(String scopeName);
IGrammar getGrammarForScope(ITMScope scope);

/**
* <b>NOTE:</b> This method can be very expensive as it potentially results in eagerly loading of all registered grammar files,
Expand All @@ -82,7 +81,7 @@ public interface IGrammarRegistryManager {
* @return the list of content types bound with the given scope name and null otherwise.
*/
@Nullable
List<IContentType> getContentTypesForScope(String scopeName);
Collection<IContentType> getContentTypesForScope(ITMScope scope);

/**
* @return list of scope names to inject for the given <code>scopeName</code> and null otherwise.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Copyright (c) 2023 Sebastian Thomschke and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* - Sebastian Thomschke - initial API and implementation
*/
package org.eclipse.tm4e.registry;

import org.eclipse.jdt.annotation.Nullable;

/**
* TextMate grammar scope API
*/
public interface ITMScope {

String getName();

String getQualifiedName();

@Nullable
String getPluginId();

boolean isQualified();
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ public WorkingCopyGrammarRegistryManager(final IGrammarRegistryManager manager)
}

@Override
public @Nullable List<IContentType> getContentTypesForScope(String scopeName) {
return manager.getContentTypesForScope(scopeName);
public @Nullable Collection<IContentType> getContentTypesForScope(ITMScope scope) {
return manager.getContentTypesForScope(scope);
}

@Override
Expand Down
Loading

0 comments on commit 4199ad9

Please sign in to comment.