Eclipse JDT: How to get java package name of a non-existing IFolder - eclipse-rcp

Given an IFolder instsance fd (fd may or may not exist), how to get the java package name if fd represents a java package? Currently I coded in this way
IJavaProject jp = JavaCore.create(fd.getProject());
IPackageFragment pf = jp.findPackageFragment(f.getFullPath());
String pname = pf.getElementName();
The code failed when fd does not exist (for example it was just deleted and the deletion was caught in IResourceDelta of an IResourceChangeListener), as IJavaProject#findPackageFragment(IPath) returns null for non-existing item. How to get the package name for a non-existing IFolder? Thanks

Does the inexistent IFolder still have a useful parent chain? If so, you may want to find the parent that corresponds to a package fragment root of the current project.
IContainer parent = fd.getParent();
while (parent != null) {
if (JavaCore.create(parent) instanceof IPackageFragmentRoot)
// success: parent is a source folder
else
parent = parent.getParent();
}
Then take the relative path from the package fragment root to the folder as the package name.
IPath myPath = fd.getFullPath();
IPath parentPath = parent.getFullPath();
IPath packagePath = myPath.makeRelativeTo(parentPath);
PS: per JLS a package is only observable if a compilation unit in the package is observable. Ergo an inexistent folder can never represent a package (but I admit this is picking on words).

Related

AOSP build: Api check failed when replacing public java files under frameworks/base/core with prebuilt .jar

I am compiling Android 8.1 AOSP, I want to remove any specified java files under frameworks/base/services and frameworks/base/core, and build the removed java files into .jar libraries, then add the library to framework to make it compile successfully. I succeeded in frameworks/base/services, but failed with API check when do it in frameworks/base/core.
What I did:
Disable JACK compile tool, modify file build/make/core/combo/javac.mk
ANDROID_COMPILE_WITH_JACK := false
Copy frameworks/base/core/java/android/app/ActivityManager.java to frameworks/base/core/mytest/core/java/ActivityManager.java
Create frameworks/base/core/mytest/Android.mk:
include $(CLEAR_VARS)
LOCAL_MODULE := frameworks.base.core.mytest
LOCAL_SRC_FILES += \
$(call all-java-files-under,core/java)
# depends on it to make compilition success
LOCAL_JAVA_LIBRARIES := services
include $(BUILD_STATIC_JAVA_LIBRARY)
Run command: mmm frameworks/base/core/mytest
Then it will generat a .jar file: out/target/product/mydevice/obj/JAVA_LIBRARIES/frameworks.base.core.mytest_intermediates/javalib.jar, copy it into prebuilt/mylibs/
Create prebuilt/mylibs/Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
# my lib is named as 'myam'
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES += myam:javalib.jar
include $(BUILD_MULTI_PREBUILT)
Modify frameworks/base/Android.mk, in framework module, add line:
LOCAL_MODULE := framework
# add my lib to framework.jar
LOCAL_STATIC_JAVA_LIBRARIES += myam
REMOVE the original file: rm frameworks/base/core/java/android/app/ActivityManager.java
Run make command to build the AOSP project, I got the error log:
javadoc: error - In doclet class com.google.doclava.Doclava, method start has thrown an exception java.lang.reflect.InvocationTargetException
java.lang.IllegalArgumentException: Unable to find ActivityManager.java. This is usually because doclava has been asked to generate stubs for a file that isn't present in the list of input source files but exists in the input classpath.
at com.google.doclava.Stubs.parseLicenseHeader(Stubs.java:656)
at com.google.doclava.Stubs.writeClassFile(Stubs.java:635)
Where throws the exception is in external/doclava/src/com/google/doclava/Stubs.java:
private static String parseLicenseHeader(/* #Nonnull */ SourcePositionInfo positionInfo) {
//...
File sourceFile = new File(positionInfo.file);
if (!sourceFile.exists()) {
throw new IllegalArgumentException("Unable to find " + sourceFile +
". This is usually because doclava has been asked to generate stubs for a file " +
"that isn't present in the list of input source files but exists in the input " +
"classpath.");
}
Since the source file has been removed, so I specified the source file path to a Stub file that generated by a previous successful built:
out/target/common/obj/JAVA_LIBRARIES/android_system_stubs_current_intermediates/src/android/app/ActivityManager.java, copy it to /data1/myAOSProot/generated/stubs/ActivityManager.java,
private static String parseLicenseHeader(/* #Nonnull */ SourcePositionInfo positionInfo) {
//...
File sourceFile = new File(positionInfo.file);
if (!sourceFile.exists()) {
// As it can't find the source file, I specified it as below:
if (positionInfo.file.equals("ActivityManager.java") || positionInfo.file.endsWith("/ActivityManager.java")) {
sourceFile = new File("/data1/myAOSProot/generated/stubs/ActivityManager.java");
} else {
throw new IllegalArgumentException("Unable to find " + sourceFile +
". This is usually because doclava has been asked to generate stubs for a file " +
"that isn't present in the list of input source files but exists in the input " +
"classpath.");
}
}
But I got a new error:
ActivityManager.java:0: warning: Method android.app.ActivityManager.TaskSnapshot.getSnapshot returns unavailable type GraphicBuffer m.position? ActivityManager.java [110]
ActivityManager.java:0: warning: Method android.app.ActivityManager.getGrantedUriPermissions returns unavailable type ParceledListSlice m.position? ActivityManager.java [110]
ActivityManager.java:0: warning: Method android.app.ActivityManager.getService returns unavailable type IActivityManager m.position? ActivityManager.java [110]
ActivityManager.java:0: warning: Parameter of unavailable type android.content.pm.IPackageDataObserver in android.app.ActivityManager.clearApplicationUserData() [110]
out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/core/java/android/app/IActivityManager.java:10691: warning: Parameter of hidden type android.app.ContentProviderHolder in android.app.IActivityManager.publishContentProviders() [110]
out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/core/java/android/app/IApplicationThread.java:2321: warning: Parameter of hidden type android.app.ResultInfo in android.app.IApplicationThread.scheduleSendResult() [110]
out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/core/java/android/app/IApplicationThread.java:2322: warning: Parameter of hidden type android.app.ResultInfo in android.app.IApplicationThread.scheduleLaunchActivity() [110]
out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/core/java/android/app/IApplicationThread.java:2341: warning: Parameter of hidden type android.app.ResultInfo in android.app.IApplicationThread.scheduleRelaunchActivity() [110]
This is because of the #hide or #removed comments in GraphicBuffer.java etc., I try ignoring the errors by comment the codes reporting error in external/doclava/src/com/google/doclava/Errors.java:
public static void error(Error error, SourcePositionInfo where, String text) {
// all commented
}
But still, another error:
out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/src/android/content/pm/ParceledListSlice.java:19: error: cannot find symbol
extends android.content.pm.BaseParceledListSlice<T>
^
symbol: class BaseParceledListSlice
location: package android.content.pm
out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/src/android/app/IApplicationThread.java:13: error: cannot find symbol
public abstract void scheduleSendResult(android.os.IBinder token, java.util.List<android.app.ResultInfo> results) throws android.os.RemoteException;
^
symbol: class ResultInfo
location: package android.app
out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/src/android/app/IApplicationThread.java:14: error: cannot find symbol
public abstract void scheduleLaunchActivity(android.content.Intent intent, android.os.IBinder token, int ident, android.content.pm.ActivityInfo info, android.content.res.Configuration curConfig, android.content.res.Configuration overrideConfig, android.content.res.CompatibilityInfo compatInfo, java.lang.String referrer, com.android.internal.app.IVoiceInteractor voiceInteractor, int procState, android.os.Bundle state, android.os.PersistableBundle persistentState, java.util.List<android.app.ResultInfo> pendingResults, java.util.List<com.android.internal.content.ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward, android.app.ProfilerInfo profilerInfo) throws android.os.RemoteException;
^
symbol: class ResultInfo
location: package android.app
out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/src/android/app/IApplicationThread.java:33: error: cannot find symbol
public abstract void scheduleRelaunchActivity(android.os.IBinder token, java.util.List<android.app.ResultInfo> pendingResults, java.util.List<com.android.internal.content.ReferrerIntent> pendingNewIntents, int configChanges, boolean notResumed, android.content.res.Configuration config, android.content.res.Configuration overrideConfig, boolean preserveWindow) throws android.os.RemoteException;
^
symbol: class ResultInfo
location: package android.app
The files reporting error like out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/src/android/content/pm/ParceledListSlice.java actually is NOT existed in a NORMAL AOSP compiling, and the file it refers like BaseParceledListSlice.java is just under the same directory as ParceledListSlice.java, I am confused why would this error happen.
Did I miss anything or is there a different way to achieve my goal? I just want to replace java files to .jar libraries.
Anyone could help me out? Thanks a lot!

Resolve bindings for new created types?

I am developing an Eclipse plug-in to refactor Java source code with JDT. I create some new classes, but experienced problems with the resolving of these new types. Therefore is my question: is it possible to resolve new created types without reparsing them?
ASTParser parser = ASTParser.newParser(AST.JLS4);
parser.setResolveBindings(true);
parser.setKind(ASTParser.K_COMPILATION_UNIT);
parser.setSource(existingCompilationUnit);
CompilationUnit unit = (CompilationUnit)parser.createAST(null);
AST ast = unit.getAST();
// create a new type
TypeDeclaration newCreatedType = ast.newTypeDeclaration();
// fill type declaration with methods, fields, etc.
// ...
// create new compilation unit for the new type
CompilationUnit newCreatedCompilationUnit = ast.newCompilationUnit();
newCreatedCompilationUnit.types().add(newCreatedType);
newCreatedType.resolveBinding(); // returns null
It is of course possible to reparse it, but then it is contained within another AST, which causes problems when I try to rewrite elements of the AST:
parser.setSource(newCreatedCompilationUnit);
CompilationUnit newParsedCompilationUnit = (CompilationUnit)parser.createAST(null);
TypeDeclaration newParsedType = (TypeDeclaration)newParsedCompilationUnit.types().get(0);
newParsedType.resolveBinding() // returns a correct binding, but newParsedType.getAST() != ast
Then I tried to copy the new type to the old AST, which corrects the AST, but the binding informations are lost again:
CompilationUnit copiedCompilationUnit = (CompilationUnit) newUnit.copySubtree(ast, newParsedCompilationUnit);
// (copiedCompilationUnit.getAST() == ast) is true
TypeDeclaration copiedType = (TypeDeclaration)copiedCompilationUnit.types().get(0);
copiedType.resolveBinding() // returns null
By now I must decide between no binding or the wrong AST and I cannot find a solution to that.

In Install4j, How to set a relative path in varfile?

I have an install4j project that I'm running from both GUI and command line.
As you might know it is possible to pass installer parameters in varfile.
I would like to know if there is a simple way to give a relative path in the varfile in the form:
my.variable=${installer:installerDir}\a.txt
I can see a workaround where I can ask the user to specify the file name only and I will put the directory path in the code. but I would still like to know if this is possible.
Thanks.
Ika.
You cannot use installer variables in the variable file. That file is read at startup before any other installer variables are defined, so you would not have a chance to set up the "installerDir" variable first.
The only option I see here is to use your own token, say
my.variable=#installerDir#\a.txt
and use a "Run script" action in the "Startup" node to replace that token with a particular directory. Here's some which checks all defined variables:
String installerDir = null;
InstallerContext context = null;
for (Object o : context.getVariableNames()) {
String variableName = (String)o;
Object variableValue = context.getVariable(variableName);
if (variableValue instanceof String) {
String replacedValue = ((String)variableValue).replaceAll("#installerDir#", installerDir);
if (!replacedValue.equals(variableValue)) {
context.setVariable(variableName, replacedValue);
}
}
}

How could I search references to a field on a AST or a CompilationUnit in eclipse?

Hi,
I'm developing an Eclipse plugin. I
need to find all the references in the
source using AST's or jdt.core.dom
or something like that. I need this
references like ASTNodes in order to
get the parent node and check several
things in the expression where
references are involved.
Thanks beforehand.
Edited:
I want to concrete a little more, My problem is that I try to catch some references to a constant but... I have not idea how I can do to catch in the matches this references. I need check the expressions which the references to a determined constant are involved. I only get the source of the method where they are used.
I think the problem is the scope or the pattern:
pattern = SearchPattern.createPattern(field, IJavaSearchConstants.REFERENCES);
scope = SearchEngine.createJavaSearchScope(declaringType.getMethods());
Thanks beforehand!
I used something like:
Search for the declaration of an
method, returns an IMethod
Search for references to the
IMethod, record those IMethods
For each IMethod returned, create an
AST from its compilation unit
Searching for declarations or references looks like the following code.
SearchRequestor findMethod = ...; // do something with the search results
SearchEngine engine = new SearchEngine();
IJavaSearchScope workspaceScope = SearchEngine.createWorkspaceScope();
SearchPattern pattern = SearchPattern.createPattern(searchString,
IJavaSearchConstants.METHOD, IJavaSearchConstants.DECLARATIONS,
SearchPattern.R_EXACT_MATCH);
SearchParticipant[] participant = new SearchParticipant[] { SearchEngine
.getDefaultSearchParticipant() };
engine.search(pattern, participant, workspaceScope, findMethod,
monitor);
Once you have your IMethod references, you can get to the AST using:
ASTParser parser = ASTParser.newParser(AST.JLS3);
parser.setResolveBindings(true);
if (methodToSearch.isBinary()) {
parser.setSource(methodToSearch.getClassFile());
} else {
parser.setSource(methodToSearch.getCompilationUnit());
}
CompilationUnit cu = (CompilationUnit) parser.createAST(null);
See http://help.eclipse.org/helios/index.jsp?topic=/org.eclipse.jdt.doc.isv/guide/jdt_int_core.htm for more details on java search, the java model, and the AST.

Can we contribute a new plugin.xml to ExtensionRegistry

I have a some additional xml files(containing standard eclipse extensions) that lie outside the bundle. Is there a way that I could contribute the extns/extnpoints in those files to the platform's extension registry?
I tried
`Platform.getExtensionRegistry.addContribution(..)`
But the method takes a masterToken object, which I dont have access to, and without which it gives me an exception.
You have to use some internal methods. Here is what I do:
IExtensionRegistry reg = Platform.getExtensionRegistry();
Object ut = ((ExtensionRegistry)reg).getTemporaryUserToken();
IContributor cont = ContributorFactoryOSGi.createContributor(Platform
.getBundle(editor.getPluginId()));
if (!reg.addContribution(is, cont, false, null, null, ut))
Util.impossible("Contribution not added due to error"); //$NON-NLS-1$