0

I am using the following code while parsing a method invocation:

ITypeBinding typeBinding = node.getExpression().resolveTypeBinding();
if ( typeBinding != null) //type resolution found actual type
    {
        className = typeBinding.getName();
    }

where className is a String containing the name of the type. Is there a way to distinguish between user-defined Java class names and API class names or external/included library class names in a method invocation?

For example, given a complete invocation String.valueOf(c);, I want to detect String as a non-user-defined class name with a method invocation valueOf.

For the following code snippet: MyCalculator calc = new MyCalculator(); calc.add(1,2);

Given the invocation calc.add(1,2), I want to detect MyCalculator as a user-defined class name with a method invocation add

I am including a code snippet showing how I set up parsing. Maybe someone can point put any errors in the setup.

 private static CompilationUnit parse(String unit) {
    ASTParser parser = ASTParser.newParser(AST.JLS8);
    parser.setResolveBindings(true);
    parser.setKind(ASTParser.K_COMPILATION_UNIT);
    parser.setBindingsRecovery(true);

    File f = new File(currentFilePath);        
    String unitName = f.getName();
    parser.setUnitName(unitName);

    String[] sources = {Constants.SOURCES}; 
    String[] classpath = {Constants.CLASSPATH};

    parser.setEnvironment(classpath, sources, new String[] { "UTF-8"}, true);
    parser.setSource(unit.toCharArray());

    return (CompilationUnit) parser.createAST(null); 
}

where Constants.SOURCES is public static String SOURCES = "F:\\BluetoothChat"; the path to the root folder of the Java project being parsed.

Shamsa
  • 67
  • 1
  • 8
  • What do you mean by 'library class'? – greg-449 Feb 16 '20 at 09:53
  • Do you mean [`typeBinding.isFromSource()`](https://help.eclipse.org/2019-12/topic/org.eclipse.jdt.doc.isv/reference/api/org/eclipse/jdt/core/dom/ITypeBinding.html#isFromSource())? – howlger Feb 16 '20 at 13:18
  • @greg-449 I mean any class from imported external packages or included external libraries. For example, the class `MethodDeclaration` is from Eclipse JDT. – Shamsa Feb 17 '20 at 05:23
  • @howlger I used it and got `false` for a user-defined Java class. – Shamsa Feb 17 '20 at 05:43
  • @greg-449 I have replaced _library class_ with _API class_ in the question title. Also, I have add examples in the body of my question to explain my requirement. – Shamsa Feb 17 '20 at 06:54
  • By _user-defined_ class/type do you mean a class/type not of the system library? Which of the following are _user-defined_: `String` (system library), `int` (primitives), `A` of a JAR, `B` of a class folder, `C` of a dependent project and `D` of a source folder? What about classes/types of exported vs. not exported (internal) packages? – howlger Feb 17 '20 at 07:36
  • @howlger I consider class `D` from a source folder of a project as a _user-defined class_ of that project. Dependent project class `C` should be considered as _external user-defined class_. `A` should be considered as _API class_. `String` is also an _API class_. – Shamsa Feb 17 '20 at 08:28
  • @howlger, I have added code for creating an AST in the body of my question. Maybe this setup is affecting the value of `typeBinding.isFromSource()` – Shamsa Feb 17 '20 at 08:39

1 Answers1

2

JDT's Java Model has the notion that every IType is contained in an IPackageFragment which is rooted in an IPackageFragmentRoot. The latter represents either a source folder or a library (jar, class folder etc.).

This means, if you have resolved AST (DOM), you could ask the ITypeBinding representing the method receiver: getJavaElement(). The result should actually be an IType, which will tell you its package fragment root if you just say type.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT).

Looking at the package fragment root there are several options to figure out, what exactly you have, e.g., isArchive(). Also getResolvedClasspathEntry() can tell you, how this thing got pulled into compilation. Based on this information you can draw whatever line you wish between "your" code and "API".

Stephan Herrmann
  • 7,963
  • 2
  • 27
  • 38
  • `IType j = (IType)typeBinding.getJavaElement();` gives me null value for `j`. Also, `typeBinding` has a MissingTypeBinding value for `binding`. Any solutions? – Shamsa Feb 18 '20 at 05:15
  • Seeing a `MissingTypeBinding` looks like the ASTParser doesn't have a sufficient environment for resolving all necessary types. Please double-check your `classpath`. – Stephan Herrmann Feb 18 '20 at 21:57
  • This answers https://stackoverflow.com/a/12791105 provides 2 approaches to instantiate the ASTParser correctly. – Jmini Mar 23 '21 at 09:39