eclipse / lsp4jakarta

Language Server for Jakarta EE
Eclipse Public License 2.0
33 stars 50 forks source link

Improve diagnostic support for jakarta.annotation.PostConstruct/PreDestroy checked exception condition #193

Open tiganov opened 2 years ago

tiganov commented 2 years ago

Improve support for #181 and #184. We currently do not know whether the exceptions specified after the throw keyword are checked or unchecked exceptions. To determine whether an exception type is checked, we need to know the type hierarchy (see discussion for #159) to see if it extends Exception and does not extend RuntimeException. Right now, the diagnostic severity is a Warning, but if we can tell which exceptions are checked, we can elevate it to an Error.

kathrynkodama commented 2 years ago

@tiganov does this apply for jakarta.annotation.PreDestroy as well? (#186)

kathrynkodama commented 2 years ago

This issue will also include adding any possible quickfixes for removing checked exceptions.

tiganov commented 2 years ago

@tiganov does this apply for jakarta.annotation.PreDestroy as well? (#186)

Yes. I've updated the issue title and description.

tiganov commented 2 years ago

With the fix for #214, we can use type hierarchy information to see if the exceptions in the method signature are checked exceptions. However, I haven't found a way to get the IType of the exception types specified in the signature. IMethod only provides an array of strings representing the exception types. I don't see a way of converting a string to an IType without having the fully qualified name (if we had the fully qualified name, we could use IJavaProject.findType()). If we had the IType, we could do the following to check whether it is a checked exception:

// Show diagnostic if the type certainly does not extend Exception or certainly extends RuntimeException
if ((TypeHierarchyUtils.doesITypeHaveSuperType(exceptionType, "Exception") < 0) ||
    (TypeHierarchyUtils.doesITypeHaveSuperType(exceptionType, "RuntimeException") > 1)) {
    Diagnostic diagnostic = new Diagnostic(
        methodRange,
        "A method with the annotation @PreDestroy must not throw checked exceptions.");
    diagnostic.setCode(AnnotationConstants.DIAGNOSTIC_CODE_PREDESTROY_EXCEPTION);
    completeDiagnostic(diagnostic);
    diagnostics.add(diagnostic);
}
ajm01 commented 8 months ago

Verified that it is still not possible to get the fully qualified class name of the exception thrown by a given method nor an IType of the exception thrown. Still not able to check if an exception is checked or unchecked using the method described previously. Keeping this issue on hold for now.