mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
typestub bug fixes
This commit is contained in:
parent
afa8676dea
commit
0ab139eb79
8 changed files with 69 additions and 97 deletions
|
@ -30,6 +30,7 @@ classifiers = [
|
||||||
]
|
]
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"Jpype1>=1.5.0",
|
"Jpype1>=1.5.0",
|
||||||
|
"packaging"
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
|
|
|
@ -28,12 +28,13 @@ import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import threading
|
import threading
|
||||||
|
from importlib.machinery import ModuleSpec
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, NoReturn, Tuple, Union
|
from typing import List, NoReturn, Tuple, Union
|
||||||
|
|
||||||
import jpype
|
import jpype
|
||||||
from jpype import imports, _jpype
|
from jpype import imports, _jpype
|
||||||
from importlib.machinery import ModuleSpec
|
from packaging.version import Version
|
||||||
|
|
||||||
from .javac import java_compile
|
from .javac import java_compile
|
||||||
from .script import PyGhidraScript
|
from .script import PyGhidraScript
|
||||||
|
@ -349,7 +350,7 @@ class PyGhidraLauncher:
|
||||||
Checks if the currently installed Ghidra version is supported.
|
Checks if the currently installed Ghidra version is supported.
|
||||||
The launcher will report the problem and terminate if it is not supported.
|
The launcher will report the problem and terminate if it is not supported.
|
||||||
"""
|
"""
|
||||||
if self.app_info.version < MINIMUM_GHIDRA_VERSION:
|
if Version(self.app_info.version) < Version(MINIMUM_GHIDRA_VERSION):
|
||||||
msg = f"Ghidra version {self.app_info.version} is not supported" + os.linesep + \
|
msg = f"Ghidra version {self.app_info.version} is not supported" + os.linesep + \
|
||||||
f"The minimum required version is {MINIMUM_GHIDRA_VERSION}"
|
f"The minimum required version is {MINIMUM_GHIDRA_VERSION}"
|
||||||
self._report_fatal_error("Unsupported Version", msg, ValueError(msg))
|
self._report_fatal_error("Unsupported Version", msg, ValueError(msg))
|
||||||
|
|
|
@ -188,6 +188,7 @@ class GhidraBuiltinsBuilder {
|
||||||
* @param printer the printer
|
* @param printer the printer
|
||||||
*/
|
*/
|
||||||
private void printScriptImports(PrintWriter printer) {
|
private void printScriptImports(PrintWriter printer) {
|
||||||
|
printer.println("from __future__ import annotations");
|
||||||
printer.println("import collections.abc");
|
printer.println("import collections.abc");
|
||||||
printer.println("import typing");
|
printer.println("import typing");
|
||||||
printer.println("from warnings import deprecated # type: ignore");
|
printer.println("from warnings import deprecated # type: ignore");
|
||||||
|
|
|
@ -553,7 +553,7 @@ public class JavadocConverter extends DocConverter {
|
||||||
private static String sanitizeQualifiedName(ExecutableElement el, TypeMirror type) {
|
private static String sanitizeQualifiedName(ExecutableElement el, TypeMirror type) {
|
||||||
Element self = el.getEnclosingElement();
|
Element self = el.getEnclosingElement();
|
||||||
PackageElement pkg = PythonTypeStubElement.getPackage(self);
|
PackageElement pkg = PythonTypeStubElement.getPackage(self);
|
||||||
return PythonTypeStubElement.sanitizeQualifiedName(self, type, pkg);
|
return PythonTypeStubElement.sanitizeQualifiedName(type, pkg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -23,7 +23,6 @@ import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.lang.model.element.Element;
|
import javax.lang.model.element.Element;
|
||||||
import javax.lang.model.element.ElementKind;
|
|
||||||
import javax.lang.model.element.Modifier;
|
import javax.lang.model.element.Modifier;
|
||||||
import javax.lang.model.element.Name;
|
import javax.lang.model.element.Name;
|
||||||
import javax.lang.model.element.PackageElement;
|
import javax.lang.model.element.PackageElement;
|
||||||
|
@ -106,24 +105,6 @@ abstract class PythonTypeStubElement<T extends Element> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the type string for the provided type and quotes if necessary<p/>
|
|
||||||
*
|
|
||||||
* This string value is safe to be used as a parameter or return type
|
|
||||||
* as well as for use in a generic type.
|
|
||||||
*
|
|
||||||
* @param self the type to become typing.Self if encountered
|
|
||||||
* @param type the type to get the string for
|
|
||||||
* @return the type string
|
|
||||||
*/
|
|
||||||
String getTypeString(Element self, TypeMirror type) {
|
|
||||||
String typeName = sanitizeQualifiedName(self, type);
|
|
||||||
if (isSamePackage(type) && !typeName.equals("typing.Self")) {
|
|
||||||
typeName = '"' + typeName + '"';
|
|
||||||
}
|
|
||||||
return typeName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the Python safe name for this element
|
* Gets the Python safe name for this element
|
||||||
*
|
*
|
||||||
|
@ -248,18 +229,17 @@ abstract class PythonTypeStubElement<T extends Element> {
|
||||||
/**
|
/**
|
||||||
* Makes the provided type Python safe if necessary
|
* Makes the provided type Python safe if necessary
|
||||||
*
|
*
|
||||||
* @param self the type to become typing.Self if encountered
|
|
||||||
* @param type the type to make Python safe
|
* @param type the type to make Python safe
|
||||||
* @param pkg the current package
|
* @param pkg the current package
|
||||||
* @return the Python safe type name
|
* @return the Python safe type name
|
||||||
*/
|
*/
|
||||||
static String sanitize(Element self, TypeMirror type, PackageElement pkg) {
|
static String sanitize(TypeMirror type, PackageElement pkg) {
|
||||||
return switch (type.getKind()) {
|
return switch (type.getKind()) {
|
||||||
case DECLARED -> throw new RuntimeException(
|
case DECLARED -> throw new RuntimeException(
|
||||||
"declared types should use the qualified name");
|
"declared types should use the qualified name");
|
||||||
case ARRAY -> {
|
case ARRAY -> {
|
||||||
TypeMirror component = ((ArrayType) type).getComponentType();
|
TypeMirror component = ((ArrayType) type).getComponentType();
|
||||||
yield "jpype.JArray[" + sanitizeQualifiedName(self, component, pkg) + "]";
|
yield "jpype.JArray[" + sanitizeQualifiedName(component, pkg) + "]";
|
||||||
}
|
}
|
||||||
case BOOLEAN -> "jpype.JBoolean";
|
case BOOLEAN -> "jpype.JBoolean";
|
||||||
case BYTE -> "jpype.JByte";
|
case BYTE -> "jpype.JByte";
|
||||||
|
@ -270,55 +250,31 @@ abstract class PythonTypeStubElement<T extends Element> {
|
||||||
case LONG -> "jpype.JLong";
|
case LONG -> "jpype.JLong";
|
||||||
case SHORT -> "jpype.JShort";
|
case SHORT -> "jpype.JShort";
|
||||||
case TYPEVAR -> type.toString();
|
case TYPEVAR -> type.toString();
|
||||||
case WILDCARD -> getWildcardVarName(self, (WildcardType) type, pkg);
|
case WILDCARD -> getWildcardVarName((WildcardType) type, pkg);
|
||||||
default -> throw new RuntimeException("unexpected TypeKind " + type.getKind());
|
default -> throw new RuntimeException("unexpected TypeKind " + type.getKind());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the provided type is the same as the provided element
|
|
||||||
*
|
|
||||||
* @param self the element of the type to become typing.Self
|
|
||||||
* @param type the type to check
|
|
||||||
* @return true if the inputs represent the same type
|
|
||||||
*/
|
|
||||||
static final boolean isSelfType(Element self, TypeMirror type) {
|
|
||||||
if (self.getKind() == ElementKind.ENUM) {
|
|
||||||
// typing.Self is usually invalid here
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (type instanceof DeclaredType dt) {
|
|
||||||
return self.equals(dt.asElement());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes the qualified name for the provided type Python safe if necessary
|
* Makes the qualified name for the provided type Python safe if necessary
|
||||||
*
|
*
|
||||||
* @param self the type to become typing.Self if encountered
|
|
||||||
* @param type the type to make Python safe
|
* @param type the type to make Python safe
|
||||||
* @return the Python safe qualified type name
|
* @return the Python safe qualified type name
|
||||||
*/
|
*/
|
||||||
final String sanitizeQualifiedName(Element self, TypeMirror type) {
|
final String sanitizeQualifiedName(TypeMirror type) {
|
||||||
return sanitizeQualifiedName(self, type, pkg);
|
return sanitizeQualifiedName(type, pkg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes the qualified name for the provided type Python safe if necessary<p/>
|
* Makes the qualified name for the provided type Python safe if necessary<p/>
|
||||||
*
|
*
|
||||||
* The provided package is used to check each type and generic components.
|
* The provided package is used to check each type and generic components.
|
||||||
* If they require a "forward declaration", it is handled accordingly.
|
|
||||||
*
|
*
|
||||||
* @param self the type to become typing.Self if encountered
|
|
||||||
* @param type the type to make Python safe
|
* @param type the type to make Python safe
|
||||||
* @param pkg the current package
|
* @param pkg the current package
|
||||||
* @return the Python safe qualified type name
|
* @return the Python safe qualified type name
|
||||||
*/
|
*/
|
||||||
static final String sanitizeQualifiedName(Element self, TypeMirror type, PackageElement pkg) {
|
static final String sanitizeQualifiedName(TypeMirror type, PackageElement pkg) {
|
||||||
if (isSelfType(self, type)) {
|
|
||||||
return "typing.Self";
|
|
||||||
}
|
|
||||||
if (type instanceof DeclaredType dt) {
|
if (type instanceof DeclaredType dt) {
|
||||||
TypeElement el = (TypeElement) dt.asElement();
|
TypeElement el = (TypeElement) dt.asElement();
|
||||||
PackageElement typePkg = getPackage(el);
|
PackageElement typePkg = getPackage(el);
|
||||||
|
@ -341,11 +297,41 @@ abstract class PythonTypeStubElement<T extends Element> {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
Iterable<String> it = () -> args.stream()
|
Iterable<String> it = () -> args.stream()
|
||||||
.map(paramType -> sanitizeQualifiedName(self, paramType, pkg))
|
.map(paramType -> sanitizeQualifiedName(paramType, pkg))
|
||||||
.iterator();
|
.iterator();
|
||||||
return name + "[" + String.join(", ", it) + "]";
|
return name + "[" + String.join(", ", it) + "]";
|
||||||
}
|
}
|
||||||
return sanitize(self, type, pkg);
|
return sanitize(type, pkg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively adds the type and it's generic parameters to the provided imports set.
|
||||||
|
*
|
||||||
|
* @param imports the set of imported types
|
||||||
|
* @param type the type to add to the imports
|
||||||
|
*/
|
||||||
|
static void addNeededTypes(Set<TypeElement> imports, TypeMirror type) {
|
||||||
|
switch (type.getKind()) {
|
||||||
|
case DECLARED:
|
||||||
|
DeclaredType dt = (DeclaredType) type;;
|
||||||
|
imports.add((TypeElement) dt.asElement());
|
||||||
|
for (TypeMirror genericType : dt.getTypeArguments()) {
|
||||||
|
addNeededTypes(imports, genericType);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WILDCARD:
|
||||||
|
WildcardType wt = (WildcardType) type;
|
||||||
|
TypeMirror base = wt.getExtendsBound();
|
||||||
|
if (base == null) {
|
||||||
|
base = wt.getSuperBound();
|
||||||
|
}
|
||||||
|
if (base != null) {
|
||||||
|
addNeededTypes(imports, base);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -411,18 +397,17 @@ abstract class PythonTypeStubElement<T extends Element> {
|
||||||
/**
|
/**
|
||||||
* Gets the name for a wildcard type if possible
|
* Gets the name for a wildcard type if possible
|
||||||
*
|
*
|
||||||
* @param self the type to become typing.Self if encountered
|
|
||||||
* @param type the wildcard type
|
* @param type the wildcard type
|
||||||
* @param pkg the current package
|
* @param pkg the current package
|
||||||
* @return the determined type name if possible otherwise typing.Any
|
* @return the determined type name if possible otherwise typing.Any
|
||||||
*/
|
*/
|
||||||
private static String getWildcardVarName(Element self, WildcardType type, PackageElement pkg) {
|
private static String getWildcardVarName(WildcardType type, PackageElement pkg) {
|
||||||
TypeMirror base = type.getExtendsBound();
|
TypeMirror base = type.getExtendsBound();
|
||||||
if (base == null) {
|
if (base == null) {
|
||||||
base = type.getSuperBound();
|
base = type.getSuperBound();
|
||||||
}
|
}
|
||||||
if (base != null) {
|
if (base != null) {
|
||||||
return sanitizeQualifiedName(self, base, pkg);
|
return sanitizeQualifiedName(base, pkg);
|
||||||
}
|
}
|
||||||
return "typing.Any";
|
return "typing.Any";
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,6 @@ final class PythonTypeStubMethod extends PythonTypeStubElement<ExecutableElement
|
||||||
"java.lang.Short", "int",
|
"java.lang.Short", "int",
|
||||||
"java.lang.String", "str"));
|
"java.lang.String", "str"));
|
||||||
|
|
||||||
private final PythonTypeStubType parent;
|
|
||||||
private final boolean filterSelf;
|
private final boolean filterSelf;
|
||||||
List<String> typevars;
|
List<String> typevars;
|
||||||
Set<TypeElement> imports;
|
Set<TypeElement> imports;
|
||||||
|
@ -111,7 +110,6 @@ final class PythonTypeStubMethod extends PythonTypeStubElement<ExecutableElement
|
||||||
*/
|
*/
|
||||||
PythonTypeStubMethod(PythonTypeStubType parent, ExecutableElement el, boolean filterSelf) {
|
PythonTypeStubMethod(PythonTypeStubType parent, ExecutableElement el, boolean filterSelf) {
|
||||||
super(parent.doclet, el);
|
super(parent.doclet, el);
|
||||||
this.parent = parent;
|
|
||||||
this.filterSelf = filterSelf;
|
this.filterSelf = filterSelf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,20 +191,14 @@ final class PythonTypeStubMethod extends PythonTypeStubElement<ExecutableElement
|
||||||
return imports;
|
return imports;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<? extends VariableElement> parameters = el.getParameters();
|
List<? extends TypeMirror> parameters = getParameterTypes();
|
||||||
TypeMirror resType = el.getReturnType();
|
|
||||||
|
|
||||||
// make the set big enough for all paramters and the return type
|
// make the set big enough for all paramters and the return type
|
||||||
imports = new HashSet<>(parameters.size() + 1);
|
imports = new HashSet<>(parameters.size() + 1);
|
||||||
|
|
||||||
if (resType instanceof DeclaredType dt) {
|
addNeededTypes(imports, getReturnType());
|
||||||
imports.add((TypeElement) dt.asElement());
|
for (TypeMirror param : parameters) {
|
||||||
}
|
addNeededTypes(imports, param);
|
||||||
|
|
||||||
for (VariableElement param : parameters) {
|
|
||||||
if (param.asType() instanceof DeclaredType dt) {
|
|
||||||
imports.add((TypeElement) dt.asElement());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return imports;
|
return imports;
|
||||||
|
@ -329,7 +321,7 @@ final class PythonTypeStubMethod extends PythonTypeStubElement<ExecutableElement
|
||||||
printer.print(convertedType);
|
printer.print(convertedType);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printer.print(getTypeString(parent.el, res));
|
printer.print(sanitizeQualifiedName(res));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -398,7 +390,7 @@ final class PythonTypeStubMethod extends PythonTypeStubElement<ExecutableElement
|
||||||
if (convertedType != null) {
|
if (convertedType != null) {
|
||||||
return name + ": " + convertedType;
|
return name + ": " + convertedType;
|
||||||
}
|
}
|
||||||
return name + ": " + getTypeString(parent.el, type);
|
return name + ": " + sanitizeQualifiedName(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -147,6 +147,7 @@ final class PythonTypeStubPackage extends PythonTypeStubElement<PackageElement>
|
||||||
*/
|
*/
|
||||||
private void process(PrintWriter printer, String indent) {
|
private void process(PrintWriter printer, String indent) {
|
||||||
writeJavaDoc(printer, indent, "");
|
writeJavaDoc(printer, indent, "");
|
||||||
|
printer.println("from __future__ import annotations");
|
||||||
printer.println("import collections.abc");
|
printer.println("import collections.abc");
|
||||||
printer.println("import datetime");
|
printer.println("import datetime");
|
||||||
printer.println("import typing");
|
printer.println("import typing");
|
||||||
|
|
|
@ -125,18 +125,13 @@ class PythonTypeStubType extends PythonTypeStubElement<TypeElement> {
|
||||||
imports.add((TypeElement) dt.asElement());
|
imports.add((TypeElement) dt.asElement());
|
||||||
}
|
}
|
||||||
for (TypeMirror iface : el.getInterfaces()) {
|
for (TypeMirror iface : el.getInterfaces()) {
|
||||||
if (iface instanceof DeclaredType dt) {
|
addNeededTypes(imports, iface);
|
||||||
imports.add((TypeElement) dt.asElement());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (PythonTypeStubNestedType nested : getNestedTypes()) {
|
for (PythonTypeStubNestedType nested : getNestedTypes()) {
|
||||||
imports.addAll(nested.getImportedTypes());
|
imports.addAll(nested.getImportedTypes());
|
||||||
}
|
}
|
||||||
for (VariableElement field : getFields()) {
|
for (VariableElement field : getFields()) {
|
||||||
TypeMirror fieldType = field.asType();
|
addNeededTypes(imports, field.asType());
|
||||||
if (fieldType instanceof DeclaredType dt) {
|
|
||||||
imports.add((TypeElement) dt.asElement());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (PythonTypeStubMethod method : getMethods()) {
|
for (PythonTypeStubMethod method : getMethods()) {
|
||||||
imports.addAll(method.getImportedTypes());
|
imports.addAll(method.getImportedTypes());
|
||||||
|
@ -327,7 +322,7 @@ class PythonTypeStubType extends PythonTypeStubElement<TypeElement> {
|
||||||
else {
|
else {
|
||||||
TypeMirror type = field.asType();
|
TypeMirror type = field.asType();
|
||||||
printer.print(": ");
|
printer.print(": ");
|
||||||
String sanitizedType = getTypeString(el, type);
|
String sanitizedType = sanitizeQualifiedName(type);
|
||||||
|
|
||||||
// only one of these may be applied
|
// only one of these may be applied
|
||||||
// prefer Final over ClassVar
|
// prefer Final over ClassVar
|
||||||
|
@ -648,11 +643,7 @@ class PythonTypeStubType extends PythonTypeStubElement<TypeElement> {
|
||||||
}
|
}
|
||||||
return OBJECT_NAME;
|
return OBJECT_NAME;
|
||||||
}
|
}
|
||||||
return sanitizeQualifiedName(el, base);
|
return sanitizeQualifiedName(base);
|
||||||
}
|
|
||||||
|
|
||||||
private String sanitizeQualifiedName(TypeMirror type) {
|
|
||||||
return sanitizeQualifiedName(el, type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue