JavaScript Libraries FAQ

From Eclipsepedia

Revision as of 12:54, 20 September 2010 by Mstorer3772.gmail.com (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

The following was taken from a pair of posts on the Eclipse forums. The content provided has been formatted and changed hither and yon (all by the original author, User:Mark Storer:

Contents

Adding a new library to the list of available JS Libraries

This was written in September of 2010, using Eclipse 3.6 (Helios), with Eclipse Eb Developer Tools v3.2.1.v20100707180

Code

UPDATE: Success! Cribbing from the IE & FF support plugins dramatically shortened my dev time, though I did make several changes. Both of the support plugins store file names in char arrays rather than Strings because that's what an interface calls for. I had 22 file names, and really didn't feel like wearing my wrists out on a repetitive task like that. I've got so many other things to wear them out on instead...

public class MyLibInitializer extends JsGlobalScopeContainerInitializer {
 private static final String LIBRARY_ID = "com.yourCompany.YourJSLibraryID";
 ...
 // what's plural of "chars"?
 private static char[][] stringsToCharses(String strs[]) {
   char [][]charses = new char[strs.length][];
   for (int i = 0; i < strs.length; ++i) {
     charses[i] = strs[i].toCharArray();
   }
   return charses;
 }
 
 private static final LIB_STRS[] = { "fileA.js", "fileB.js", ... };
 private static final LIB_CHARSES = stringsToCharses(LIB_STRS);

 public char[][] getLibraryFileNames() {
   return LibInitializer.LIB_CHARSES;
 }
 
 //Q: When is an IPath not a path?
 public IPath getPath() {
     //A: When it's a library ID.
     return new Path(LIBRARY_ID);
 }
}

Plus "fileA.js" is much easier to read (and debug) than the equivalent char array. Yow. It'd be easy to miss a dropped character buried in all those commas and quotes.

PS: I suggest overriding getWorkingLibPath in your LibraryLocation implementation. If you don't, you'll end up sharing the same "libraries" directory in the JSDT core plugin... which opens up the possibility of file collisions (with the most recent time stamp winning).

XML

You'll also need to add several extension points to your plugin to identify it as providing a JS library:

  <extension point="org.eclipse.wst.jsdt.ui.JsGlobalScopeContainerPage">
         <JsGlobalScopeContainerPage
           name="YourCompanyWizardPage"
           class="com.yourCompany.YourWizardPage"
           id="com.yourCompany.JSWizardPage">
     </JsGlobalScopeContainerPage>
  </extension>
  <extension
     point="org.eclipse.wst.jsdt.core.JsGlobalScopeContainerInitializer">
     <JsGlobalScopeContainerInitializer
           class="com.yourCompany.LibInitializer"
           id="'com.yourCompany.YourJSLibraryID'">
     </JsGlobalScopeContainerInitializer>
  </extension>
  <! -- Optional? -- >
  <extension point="org.eclipse.wst.jsdt.ui.JsGlobalScopeUIInitializer">
    <JsGlobalScopeUIInitializer
       id="'com.yourCompany.YourJSLibraryID'"
       class="com.yourCompany.YourUIInitializer">
    </JsGlobalScopeUIInitializer>
  </extension>

It is critical that the ID defined in the ContainerInitializer and UIInitializer extension points match, and that they match LIBRARY_ID in the plugin sample code above.

Adding an existing library to a project's include path

To programmatically add a JS library to a project:

   private void addJSLibToProj(IProject proj) {
       IJavaScriptProject jsProj = JavaScriptCore.create(proj);
        
       try {
           IIncludePathEntry entries[] = jsProj.getRawIncludepath();

           // an impl of IJsGlobalScopeContainerInitializer
           LibInitializer jsLib = new LibInitializer();

           // LibInitializer.getPath actually returns the LibraryID defined in the plugin.xml
           // wrapped in a Path object.  Funky, but okay.  
           IPath ourLibPath = jsLib.getPath();
           IIncludePathEntry ourEntry = JavaScriptCore.newContainerEntry(ourLibPath);

           IIncludePathEntry newEntries[] = new IIncludePathEntry[entries.length + 1];
           System.arraycopy(entries, 0, newEntries, 0, entries.length);
           newEntries[entries.length]= ourEntry; 

           jsProj.setRawIncludepath(newEntries, true, null);
       } catch (JavaScriptModelException e) {
           LogError( e );
       }
   }

Important bits to note:

  1. we don't add it as a CPE_LIBRARY (from one of the JavaScriptCore.newLibraryEntry(...) overrides), but a CPE_CONTAINER. A CPE_LIBRARY appears to be a single file, while a CPE_CONTAINER can be any number of other Includable Things. Libraries in this case.
  2. The "path" to that container is the library ID from the plugin.xml... as used in the org.eclipse.wst.jsdt.core.JsGlobalScopeContainerInitializer extension point (and ...UIInitializer).

It would be nice to have an "addLibraryByID" in IJavaScriptProject, but that would probably be too useful. ;) Given the way "PROVISIONAL API" warnings are splashed all over everything, it'd be comforting to have that extra layer of insulation. Ah well... they don't call it "the bleeding edge" for nothing.

Not making IPath's out of things that are clearly not paths might be a good idea as well. Maybe just a subclass that makes it clear what's Actually Going On?