Skip to content

Commit 4d8037b

Browse files
committed
Provide the typescriptResourceParticipants to consume tsserver commands
for other files than ts, tsx, jsx files (like html). See angelozerr/angular-eclipse#30
1 parent d29fb1c commit 4d8037b

File tree

8 files changed

+257
-7
lines changed

8 files changed

+257
-7
lines changed

eclipse/jsdt/ts.eclipse.ide.jsdt.ui/src/ts/eclipse/ide/jsdt/internal/ui/editor/contentassist/TypeScriptCompletionProposalComputer.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import ts.eclipse.ide.core.resources.IIDETypeScriptProject;
3131
import ts.eclipse.ide.core.utils.TypeScriptResourceUtil;
3232
import ts.eclipse.ide.jsdt.internal.ui.Trace;
33+
import ts.eclipse.ide.jsdt.ui.editor.contentassist.JSDTCompletionProposalFactory;
3334
import ts.eclipse.ide.jsdt.ui.editor.contentassist.TypeScriptContentAssistInvocationContext;
3435
import ts.resources.ITypeScriptFile;
3536

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Contributors:
99
* Angelo Zerr <[email protected]> - initial API and implementation
1010
*/
11-
package ts.eclipse.ide.jsdt.internal.ui.editor.contentassist;
11+
package ts.eclipse.ide.jsdt.ui.editor.contentassist;
1212

1313
import java.lang.reflect.Constructor;
1414

@@ -19,6 +19,7 @@
1919
import ts.client.completions.CompletionEntry;
2020
import ts.client.completions.ICompletionEntryFactory;
2121
import ts.client.completions.ICompletionEntryMatcher;
22+
import ts.eclipse.ide.jsdt.internal.ui.editor.contentassist.JSDTTypeScriptCompletionProposal;
2223

2324
/**
2425
* TypeScript {@link ICompletionProposal} implementation with JSDT

eclipse/ts.eclipse.ide.core/plugin.properties

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@ TypeScriptProblem.name=TypeScript Problem
2323
TypeScriptBuilder.name=TypeScript Builder
2424

2525
# Extension Points
26-
nodeJSInstallsContribution.name=Node.js Installations
26+
nodeJSInstallsContribution.name=Node.js Installations Extension Points
2727
typeScriptConsoleConnectors.name=TypeScript Console Connector Extension Points
28-
typeScriptRepositoriesContribution.name=TypeScript Repositories
28+
typeScriptRepositoriesContribution.name=TypeScript Repositories Extension Points
29+
typeScriptResourceParticipants.name=TypeScript Resource Participants Extension Points
2930

3031
# Launch
3132
TypeScriptCompilerLaunchConfigurationDelegate.label=TypeScript Compile

eclipse/ts.eclipse.ide.core/plugin.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,12 @@
2020
<extension-point id="nodeJSInstalls"
2121
name="%nodeJSInstallsContribution.name"
2222
schema="schema/nodeJSInstalls.exsd" />
23-
<extension-point id="typeScriptRepositories" name="%typeScriptRepositoriesContribution.name" schema="schema/typeScriptRepositories.exsd"/>
23+
<extension-point id="typeScriptRepositories"
24+
name="%typeScriptRepositoriesContribution.name"
25+
schema="schema/typeScriptRepositories.exsd"/>
26+
<extension-point id="typeScriptResourceParticipants"
27+
name="%typeScriptResourceParticipants.name"
28+
schema="schema/typeScriptResourceParticipants.exsd"/>
2429

2530
<extension point="org.eclipse.core.contenttype.contentTypes">
2631
<content-type
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?xml version='1.0' encoding='UTF-8'?>
2+
<!-- Schema file written by PDE -->
3+
<schema targetNamespace="ts.eclipse.ide.core" xmlns="http://www.w3.org/2001/XMLSchema">
4+
<annotation>
5+
<appInfo>
6+
<meta.schema plugin="ts.eclipse.ide.core" id="typescriptResourceParticpants" name="TypeScript Resource Particpants"/>
7+
</appInfo>
8+
<documentation>
9+
Extension point to provided embedded TypeScript Repositories.
10+
</documentation>
11+
</annotation>
12+
13+
<element name="extension">
14+
<annotation>
15+
<appInfo>
16+
<meta.element />
17+
</appInfo>
18+
</annotation>
19+
<complexType>
20+
<sequence minOccurs="1" maxOccurs="unbounded">
21+
<element ref="participant"/>
22+
</sequence>
23+
<attribute name="point" type="string" use="required">
24+
<annotation>
25+
<documentation>
26+
27+
</documentation>
28+
</annotation>
29+
</attribute>
30+
<attribute name="id" type="string">
31+
<annotation>
32+
<documentation>
33+
34+
</documentation>
35+
</annotation>
36+
</attribute>
37+
<attribute name="name" type="string">
38+
<annotation>
39+
<documentation>
40+
41+
</documentation>
42+
<appInfo>
43+
<meta.attribute translatable="true"/>
44+
</appInfo>
45+
</annotation>
46+
</attribute>
47+
</complexType>
48+
</element>
49+
50+
<element name="participant">
51+
<annotation>
52+
<documentation>
53+
This extension point allows developers to supply a repository containing a TypeScript installation as well as the TSLint tool.
54+
&lt;p&gt;
55+
A repository is represented by a root directory containing a &lt;i&gt;node_modules&lt;/i&gt; directory, itself containing the &lt;i&gt;typescript&lt;/i&gt; and &lt;i&gt;tslit&lt;/i&gt; packages.
56+
&lt;p&gt;
57+
The version of TypeScript embedded in the repository directory is detected automatically. On first startup, the repository containing the most recent version is selected as active repository. The user is always free to change the active repository.
58+
</documentation>
59+
</annotation>
60+
<complexType>
61+
<attribute name="class" type="string" use="required">
62+
<annotation>
63+
<documentation>
64+
Extension point to know if a given resource can consume tsserver or not.
65+
</documentation>
66+
<appInfo>
67+
<meta.attribute kind="java" basedOn=":ts.eclipse.ide.core.resources.ITypeScriptResourceParticipant"/>
68+
</appInfo>
69+
</annotation>
70+
</attribute>
71+
</complexType>
72+
</element>
73+
74+
<annotation>
75+
<appInfo>
76+
<meta.section type="since"/>
77+
</appInfo>
78+
<documentation>
79+
2.0
80+
</documentation>
81+
</annotation>
82+
83+
84+
85+
<annotation>
86+
<appInfo>
87+
<meta.section type="implementation"/>
88+
</appInfo>
89+
<documentation>
90+
This plugin itself does not have any predefined repositories
91+
</documentation>
92+
</annotation>
93+
94+
95+
</schema>

eclipse/ts.eclipse.ide.core/src/ts/eclipse/ide/core/TypeScriptCorePlugin.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,13 @@ public void start(BundleContext context) throws Exception {
5353
// set up resource management for IDE
5454
ConfigurableTypeScriptResourcesManager resourceManager = ConfigurableTypeScriptResourcesManager.getInstance();
5555
resourceManager.setTypeScriptResourcesManagerDelegate(IDEResourcesManager.getInstance());
56+
IDEResourcesManager.getInstance().initialize();
5657
}
5758

5859
@Override
5960
public void stop(BundleContext context) throws Exception {
6061
ResourcesWatcher.getInstance().dispose();
62+
IDEResourcesManager.getInstance().destroy();
6163
plugin = null;
6264
super.stop(context);
6365
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* Copyright (c) 2015-2017 Angelo ZERR.
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v1.0
5+
* which accompanies this distribution, and is available at
6+
* http://www.eclipse.org/legal/epl-v10.html
7+
*
8+
* Contributors:
9+
* Angelo Zerr <[email protected]> - initial API and implementation
10+
*/
11+
package ts.eclipse.ide.core.resources;
12+
13+
import org.eclipse.core.resources.IProject;
14+
15+
/**
16+
* Extension point to know if a given resource can consume tsserver or not.
17+
*
18+
*/
19+
public interface ITypeScriptResourceParticipant {
20+
21+
/**
22+
* Returns true if the given resource can consume tsserver and false
23+
* otherwise.
24+
*
25+
* @param project
26+
* @param fileObject
27+
* @return true if the given resource can consume tsserver and false
28+
* otherwise.
29+
*/
30+
boolean canConsumeTsserver(IProject project, Object fileObject);
31+
32+
}

eclipse/ts.eclipse.ide.core/src/ts/eclipse/ide/internal/core/resources/IDEResourcesManager.java

Lines changed: 116 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,30 +19,42 @@
1919
import org.eclipse.core.resources.IFile;
2020
import org.eclipse.core.resources.IProject;
2121
import org.eclipse.core.runtime.CoreException;
22+
import org.eclipse.core.runtime.IConfigurationElement;
23+
import org.eclipse.core.runtime.IExtensionDelta;
24+
import org.eclipse.core.runtime.IExtensionRegistry;
25+
import org.eclipse.core.runtime.IRegistryChangeEvent;
26+
import org.eclipse.core.runtime.IRegistryChangeListener;
2227
import org.eclipse.core.runtime.Platform;
2328
import org.eclipse.core.runtime.content.IContentType;
2429
import org.eclipse.core.runtime.content.IContentTypeManager.ContentTypeChangeEvent;
2530
import org.eclipse.core.runtime.content.IContentTypeManager.IContentTypeChangeListener;
2631

2732
import ts.client.ScriptKindName;
33+
import ts.eclipse.ide.core.TypeScriptCorePlugin;
2834
import ts.eclipse.ide.core.preferences.TypeScriptCorePreferenceConstants;
2935
import ts.eclipse.ide.core.resources.IIDETypeScriptProject;
3036
import ts.eclipse.ide.core.resources.ITypeScriptElementChangedListener;
37+
import ts.eclipse.ide.core.resources.ITypeScriptResourceParticipant;
3138
import ts.eclipse.ide.core.resources.UseSalsa;
3239
import ts.eclipse.ide.core.resources.buildpath.ITypeScriptBuildPath;
3340
import ts.eclipse.ide.core.utils.PreferencesHelper;
3441
import ts.eclipse.ide.internal.core.Trace;
3542
import ts.resources.ITypeScriptResourcesManagerDelegate;
3643
import ts.utils.FileUtils;
3744

38-
public class IDEResourcesManager implements ITypeScriptResourcesManagerDelegate {
45+
public class IDEResourcesManager implements ITypeScriptResourcesManagerDelegate, IRegistryChangeListener {
3946

4047
private static IDEResourcesManager instance = new IDEResourcesManager();
41-
4248
private final List<ITypeScriptElementChangedListener> listeners;
4349

4450
private boolean useJsAsJsx;
4551

52+
private static final String EXTENSION_TYPESCRIPT_RESOURCE_PARTICIPANTS = "typeScriptResourceParticipants";
53+
private static final String CLASS_ATTR = "class";
54+
private boolean registryListenerIntialized;
55+
private boolean extensionResourceParticipantsLoaded;
56+
private List<ITypeScriptResourceParticipant> resourceParticipants;
57+
4658
/**
4759
* Contents Types IDS
4860
*/
@@ -52,6 +64,8 @@ public class IDEResourcesManager implements ITypeScriptResourcesManagerDelegate
5264
private static final String JSX_CONTENT_TYPE_ID = "ts.eclipse.ide.core.jsxSource";
5365

5466
private IDEResourcesManager() {
67+
this.registryListenerIntialized = false;
68+
this.resourceParticipants = new ArrayList<>();
5569
this.listeners = new ArrayList<ITypeScriptElementChangedListener>();
5670
updateUseJsAsJsx(Platform.getContentTypeManager().getContentType(JSX_CONTENT_TYPE_ID));
5771

@@ -300,7 +314,17 @@ public boolean canConsumeTsserver(IProject project, Object fileObject) {
300314
if (isJsFile(fileObject)) {
301315
return hasSalsaNature(project);
302316
}
303-
return (isTsOrTsxOrJsxFile(fileObject));
317+
if (isTsOrTsxOrJsxFile(fileObject)) {
318+
return true;
319+
}
320+
// Use extension point
321+
loadExtensionResourceParticipants();
322+
for (ITypeScriptResourceParticipant participant : resourceParticipants) {
323+
if (participant.canConsumeTsserver(project, fileObject)) {
324+
return true;
325+
}
326+
}
327+
return false;
304328
}
305329

306330
@Override
@@ -354,4 +378,93 @@ public void removeTypeScriptElementChangedListener(ITypeScriptElementChangedList
354378
}
355379
}
356380

381+
private synchronized void loadExtensionResourceParticipants() {
382+
if (extensionResourceParticipantsLoaded)
383+
return;
384+
// Immediately set the flag, as to ensure that this method is never
385+
// called twice
386+
extensionResourceParticipantsLoaded = true;
387+
388+
Trace.trace(Trace.EXTENSION_POINT, "->- Loading .typeScriptResourceParticipants extension point ->-");
389+
390+
IExtensionRegistry registry = Platform.getExtensionRegistry();
391+
IConfigurationElement[] cf = registry.getConfigurationElementsFor(TypeScriptCorePlugin.PLUGIN_ID,
392+
EXTENSION_TYPESCRIPT_RESOURCE_PARTICIPANTS);
393+
394+
addExtensionResourceParticipants(cf);
395+
addRegistryListenerIfNeeded();
396+
397+
Trace.trace(Trace.EXTENSION_POINT, "-<- Done loading .typeScriptResourceParticipants extension point -<-");
398+
}
399+
400+
@Override
401+
public void registryChanged(final IRegistryChangeEvent event) {
402+
IExtensionDelta[] deltas = event.getExtensionDeltas(TypeScriptCorePlugin.PLUGIN_ID,
403+
EXTENSION_TYPESCRIPT_RESOURCE_PARTICIPANTS);
404+
if (deltas != null) {
405+
synchronized (this) {
406+
for (IExtensionDelta delta : deltas) {
407+
IConfigurationElement[] cf = delta.getExtension().getConfigurationElements();
408+
if (delta.getKind() == IExtensionDelta.ADDED) {
409+
addExtensionResourceParticipants(cf);
410+
} else {
411+
removeExtensionResourceParticipants(cf);
412+
}
413+
}
414+
}
415+
}
416+
}
417+
418+
private void addExtensionResourceParticipants(IConfigurationElement[] cf) {
419+
for (IConfigurationElement ce : cf) {
420+
try {
421+
String className = ce.getAttribute(CLASS_ATTR);
422+
ITypeScriptResourceParticipant participant = (ITypeScriptResourceParticipant) ce
423+
.createExecutableExtension(CLASS_ATTR);
424+
synchronized (resourceParticipants) {
425+
resourceParticipants.add(participant);
426+
}
427+
Trace.trace(Trace.EXTENSION_POINT, " Loaded typeScriptResourceParticipants: " + className);
428+
} catch (Throwable t) {
429+
Trace.trace(Trace.SEVERE, " Error while loading typeScriptResourceParticipants", t);
430+
}
431+
}
432+
}
433+
434+
private void removeExtensionResourceParticipants(IConfigurationElement[] cf) {
435+
for (IConfigurationElement ce : cf) {
436+
try {
437+
String className = ce.getAttribute(CLASS_ATTR);
438+
synchronized (resourceParticipants) {
439+
for (ITypeScriptResourceParticipant participant : resourceParticipants) {
440+
if (className.equals(participant.getClass().getName())) {
441+
resourceParticipants.remove(participant);
442+
Trace.trace(Trace.EXTENSION_POINT, "Unloaded typeScriptResourceParticipants: " + className);
443+
444+
break;
445+
}
446+
}
447+
}
448+
} catch (Throwable t) {
449+
Trace.trace(Trace.SEVERE, "Error while unloading typeScriptResourceParticipants", t);
450+
}
451+
}
452+
}
453+
454+
private void addRegistryListenerIfNeeded() {
455+
if (registryListenerIntialized)
456+
return;
457+
458+
IExtensionRegistry registry = Platform.getExtensionRegistry();
459+
registry.addRegistryChangeListener(this, TypeScriptCorePlugin.PLUGIN_ID);
460+
registryListenerIntialized = true;
461+
}
462+
463+
public void initialize() {
464+
465+
}
466+
467+
public void destroy() {
468+
Platform.getExtensionRegistry().removeRegistryChangeListener(this);
469+
}
357470
}

0 commit comments

Comments
 (0)