Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Language IDEs » Java Development Tools (JDT) » Programatically setting Javadoc and Source
Programatically setting Javadoc and Source [message #708882] Wed, 03 August 2011 04:54 Go to next message
Phil  is currently offline Phil
Messages: 6
Registered: August 2011
Junior Member
I am writing a plugin that
1: finds the jar associated with the item you clicked on
2: finds the digest of the jar
3: looks up the digest in a database
4: finds relevant javadoc/source locations
5: attaches them to the jar

I have sorted out items 1 through 4, and am now trying to work out how to attach the source/javadoc. I would like this to be the same effect as right clicking on the jar, clicking properties, and setting the location source paths.

My JDT skills are not great, but I have found the IJavaModel and the IPackageFragmentRoot . Interestingly the IPackageFragmentRoot has a method called getSourceAttachmentPath, and attachSource. I have used these, and I can set and get a value, but when I examine the location source path in the IDE, I don't find the values that I set.

I am starting with an IBinding. Could someone advise me of the route to get from there to being able to set the javadoc/source locations

Many thanks
Re: Programatically setting Javadoc and Source [message #712334 is a reply to message #708882] Sun, 07 August 2011 02:08 Go to previous messageGo to next message
Michael Pellaton is currently offline Michael Pellaton
Messages: 289
Registered: July 2009
Senior Member
Hi

After writing the reply to your other post yesterday, I had an idea of
how you could find out: look at the source code of either the property
page of the java project properties or the build path action you
described.

To find the source use, plugin spy:
https://scratsh.wordpress.com/2009/06/09/eclipse-3-5-plug-in-spy-and-menus/

To get the sources:
http://www.vogella.de/articles/EclipseCodeAccess/article.html

HTH,
Michael
Re: Programatically setting Javadoc and Source [message #712568 is a reply to message #712334] Sun, 07 August 2011 08:46 Go to previous messageGo to next message
Phil  is currently offline Phil
Messages: 6
Registered: August 2011
Junior Member
Thanks I am doing that. The Plugin spy is very helpful, I didn't know about it, and its very helpful

I have successfully located where the data is held:

IJavaElement element = binding.getJavaElement();
IJavaProject javaProject = element.getJavaProject();
IPackageFragmentRoot packageFragmentRoot = javaProject.findPackageFragmentRoot(element.getPath());
IClasspathEntry classpathEntry = packageFragmentRoot.getResolvedClasspathEntry();
IClasspathAttribute[] extraAttributes = classpathEntry.getExtraAttributes();

One of the class path attributes has name javadoc_location and the value is the path for the javadoc. The classpathEntry has a sourceAttachmentPath, and this is where the source code is attached.

Hurrah! Half the problem solved. With a bit of luck, those urls you posted should help me track down how to set them.

[Updated on: Sun, 07 August 2011 08:48]

Report message to a moderator

Re: Programatically setting Javadoc and Source [message #712619 is a reply to message #712568] Sun, 07 August 2011 09:49 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas Schindl
Messages: 5292
Registered: July 2009
Senior Member
Am 07.08.11 14:46, schrieb Phil:
> Thanks I am doing that.
>
> I have successfully located where the data is held:
>
> IJavaElement element = binding.getJavaElement();
> IJavaProject javaProject = element.getJavaProject();
> IPackageFragmentRoot packageFragmentRoot =
> javaProject.findPackageFragmentRoot(element.getPath());
> IClasspathEntry classpathEntry =
> packageFragmentRoot.getResolvedClasspathEntry();
> IClasspathAttribute[] extraAttributes =
> classpathEntry.getExtraAttributes();
>
> One of the class path attributes has name javadoc_location and the
> value is the path for the javadoc. The classpathEntry has a
> sourceAttachmentPath, and this is where the source code is attached.
>
> Hurrah! Half the problem solved. With a bit of luck, those urls you
> posted should help me track down how to set them.
>
>

This code sets the JavaDoc for an classpathentry:
https://github.com/tomsontom/e-fx-clipse/blob/master/at.bestsolution.efxclipse.tooling.jdt.core/src/at/bestsolution/efxclipse/tooling/jdt/core/internal/BuildPathSupport.java

Tom
Re: Programatically setting Javadoc and Source [message #712702 is a reply to message #712619] Sun, 07 August 2011 12:17 Go to previous messageGo to next message
Phil  is currently offline Phil
Messages: 6
Registered: August 2011
Junior Member
Thank you Tom that is yet another piece of the puzzle. That nice piece of code makes an IClassPathEntry which is suitable for storing within a IClassPathContainer, plus it confirms that this is the right track.

I am now working out how to add the IClassPathEntry that your snippet made to the IJavaProject.

My other worry is how to ensure that I follow any lifecycle / persistence rules: will I need to save something afterwards, or mark it as "dirty" or something? Hopefully some more code snippets will have the answer!

Re: Programatically setting Javadoc and Source [message #713442 is a reply to message #712702] Mon, 08 August 2011 09:29 Go to previous message
Phil  is currently offline Phil
Messages: 6
Registered: August 2011
Junior Member
OK I have it. Thank you for the help.

I have only made it work for jars in libraries, but I suspect the same approach will work.

In essence you need to make a new container that is just like the container that holds the classpathentry representing your jar, except that the class path entry needs to be changed to have an extra attribute with name (IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME which has to point to a legitimate url.

You then find the ClasspathContainerInitializer that corresponds to this classpath container, and request it to update the class path container.

I have tried adding to the JRE rt.jar using this approach and it now appears in the property page, and persists across sessions.




/**The IClassPathEntry is the one found in the code snippet above. */

private void setJavadocLocationAttribute(IJavaProject project, IClasspathEntry entry, String text) {
		assert ripped != null;
		FoundClassPathEntry found = JavaProjects.findClassPathEntry(project, entry);
		System.out.println("Setting. Found: " + found);
		JavaProjects.updateFoundClassPath(found, new IFunction1<IClasspathEntry, IClasspathEntry>() {
			@Override
			public IClasspathEntry apply(IClasspathEntry from) throws Exception {
				IClasspathAttribute[] extraAttributes = from.getExtraAttributes();
				List<IClasspathAttribute> newAttributes = new ArrayList<IClasspathAttribute>();
				boolean found = false;
				IClasspathAttribute newClasspathAttribute = JavaCore.newClasspathAttribute(IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME, text);
				for (IClasspathAttribute oldAttribute : extraAttributes)
					if (oldAttribute.getName().equals(IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME)) {
						newAttributes.add(newClasspathAttribute);
						found = true;
					} else
						newAttributes.add(oldAttribute);
				if (!found)
					newAttributes.add(newClasspathAttribute);
				IClasspathEntry newLibraryEntry = JavaCore.newLibraryEntry(from.getPath(), from.getSourceAttachmentPath(), from.getSourceAttachmentRootPath(), from.getAccessRules(), newAttributes.toArray(new IClasspathAttribute[0]), from.isExported());
				return newLibraryEntry;
			}
		});
	}
public class FoundClassPathEntry {

	public static enum FoundIn {
		NOT_FOUND, FOUND_IN_RAW, FOUND_IN_LIBRARY
	}

	public final IJavaProject javaProject;
	public final FoundIn foundIn;
	public final IClasspathEntry rawClassPath;
	public final IClasspathEntry classPathEntry;
	public final IClasspathContainer container;

	public FoundClassPathEntry(IJavaProject javaProject, FoundIn foundIn, IClasspathEntry classPathEntry) {
		this.javaProject = javaProject;
		this.foundIn = foundIn;
		this.rawClassPath = classPathEntry;
		this.container = null;
		this.classPathEntry = classPathEntry;
	}

	public FoundClassPathEntry(IJavaProject javaProject, FoundIn foundIn, IClasspathEntry rawClassPath, IClasspathContainer container, IClasspathEntry classPathEntry) {
		this.javaProject = javaProject;
		this.foundIn = foundIn;
		this.rawClassPath = rawClassPath;
		this.container = container;
		this.classPathEntry = classPathEntry;
	}

	@Override
	public String toString() {
		return "FoundClassPathEntry [project=" + javaProject.getElementName() + ", foundIn=" + foundIn + "]";
	}

}
public class JavaProjects {

	public static FoundClassPathEntry findClassPathEntry(IJavaProject project, IClasspathEntry entry) {
		try {
			IClasspathEntry[] rawClasspaths = project.getRawClasspath();
			for (IClasspathEntry rawClassPath : rawClasspaths) {
				if (rawClassPath == entry)
					return new FoundClassPathEntry(project, FoundIn.FOUND_IN_RAW, entry);
				else if (rawClassPath.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
					IClasspathContainer container = JavaCore.getClasspathContainer(rawClassPath.getPath(), project);
					for (IClasspathEntry contained : container.getClasspathEntries()) {
						if (contained == entry)
							return new FoundClassPathEntry(project, FoundIn.FOUND_IN_LIBRARY, rawClassPath, container, entry);
					}
				}
			}
			return new FoundClassPathEntry(project, FoundIn.NOT_FOUND, entry);
		} catch (JavaModelException e) {
			throw WrappedException.wrap(e);
		}
	}

	public static void updateFoundClassPath(final FoundClassPathEntry found, final IFunction1<IClasspathEntry, IClasspathEntry> mutator) {
		try {
			switch (found.foundIn) {
			case FOUND_IN_LIBRARY:				
				ClasspathContainerInitializer initializer = JavaCore.getClasspathContainerInitializer(found.container.getPath().segment(0));
				final IClasspathEntry[] newEntries = ArrayHelper.map(IClasspathEntry.class, found.container.getClasspathEntries(), new IFunction1<IClasspathEntry, IClasspathEntry>() {
					@Override
					public IClasspathEntry apply(IClasspathEntry from) throws Exception {
						if (from == found.classPathEntry)
							return mutator.apply(from);
						else
							return from;
					}
				});
				IClasspathContainer containerSuggestion = new IClasspathContainer() {

					@Override
					public IPath getPath() {
						return found.container.getPath();
					}

					@Override
					public int getKind() {
						return found.container.getKind();
					}

					@Override
					public String getDescription() {
						return found.container.getDescription();
					}

					@Override
					public IClasspathEntry[] getClasspathEntries() {
						return newEntries;
					}
				};

				initializer.requestClasspathContainerUpdate(found.container.getPath(), found.javaProject, containerSuggestion);
				break;
			default:
				throw new IllegalStateException(found.toString());
			}
		} catch (Exception e) {
			throw WrappedException.wrap(e);
		}
	}
}

public class ArrayHelper {

	public static <From, To> To[] map(Class<To> clazz, From[] old, IFunction1<From, To> mutator) {
		try {
			@SuppressWarnings({ "unchecked" })
			To[] result = (To[]) Array.newInstance(clazz, old.length);
			for (int i = 0; i < old.length; i++)
				result[i] = mutator.apply(old[i]);
			return result;
		} catch (Exception e) {
			throw WrappedException.wrap(e);
		}
	}
}



[Updated on: Mon, 08 August 2011 09:33]

Report message to a moderator

Previous Topic:Accessing Debugging Information
Next Topic:How to import plug-ins from Eclipse CDT with source
Goto Forum:
  


Current Time: Wed Aug 27 13:23:11 EDT 2014

Powered by FUDForum. Page generated in 0.02038 seconds