mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-21 19:42:14 +00:00
Merge branch 'GP-4816_ryanmkurtz_PR-7120_dc3-tsd_typestubs'
(Closes #7120)
This commit is contained in:
commit
4906b5801d
@ -30,6 +30,7 @@ classifiers = [
|
||||
]
|
||||
dependencies = [
|
||||
"Jpype1>=1.5.0",
|
||||
"packaging"
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
|
@ -28,12 +28,13 @@ import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import threading
|
||||
from importlib.machinery import ModuleSpec
|
||||
from pathlib import Path
|
||||
from typing import List, NoReturn, Tuple, Union
|
||||
|
||||
import jpype
|
||||
from jpype import imports, _jpype
|
||||
from importlib.machinery import ModuleSpec
|
||||
from packaging.version import Version
|
||||
|
||||
from .javac import java_compile
|
||||
from .script import PyGhidraScript
|
||||
@ -199,7 +200,7 @@ class PyGhidraLauncher:
|
||||
msg = "Cannot launch from repo because Ghidra has not been compiled " \
|
||||
"with Eclipse or Gradle."
|
||||
self._report_fatal_error("Ghidra not built", msg, ValueError(msg))
|
||||
|
||||
|
||||
self.class_path = [str(classpath)]
|
||||
if not self._java_home:
|
||||
self._launch_support = launch_support
|
||||
@ -225,10 +226,10 @@ class PyGhidraLauncher:
|
||||
properties = []
|
||||
|
||||
root = self._install_dir
|
||||
|
||||
|
||||
if self._dev_mode:
|
||||
root = root / "Ghidra" / "RuntimeScripts" / "Common"
|
||||
|
||||
|
||||
launch_properties = root / "support" / "launch.properties"
|
||||
|
||||
for line in Path(launch_properties).read_text().splitlines():
|
||||
@ -349,7 +350,7 @@ class PyGhidraLauncher:
|
||||
Checks if the currently installed Ghidra version is 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 + \
|
||||
f"The minimum required version is {MINIMUM_GHIDRA_VERSION}"
|
||||
self._report_fatal_error("Unsupported Version", msg, ValueError(msg))
|
||||
@ -677,15 +678,15 @@ def _run_mac_app():
|
||||
# this runs the event loop
|
||||
# it is required for the GUI to show up
|
||||
from ctypes import c_void_p, c_double, c_uint64, c_int64, c_int32, c_bool, CFUNCTYPE
|
||||
|
||||
|
||||
CoreFoundation = ctypes.cdll.LoadLibrary(ctypes.util.find_library("CoreFoundation"))
|
||||
|
||||
|
||||
def get_function(name, restype, *argtypes):
|
||||
res = getattr(CoreFoundation, name)
|
||||
res.argtypes = [arg for arg in argtypes]
|
||||
res.restype = restype
|
||||
return res
|
||||
|
||||
|
||||
CFRunLoopTimerCallback = CFUNCTYPE(None, c_void_p, c_void_p)
|
||||
kCFRunLoopDefaultMode = c_void_p.in_dll(CoreFoundation, "kCFRunLoopDefaultMode")
|
||||
kCFRunLoopRunFinished = c_int32(1)
|
||||
@ -693,10 +694,10 @@ def _run_mac_app():
|
||||
INF_TIME = c_double(1.0e20)
|
||||
FIRE_ONCE = c_double(0)
|
||||
kCFAllocatorDefault = NULL
|
||||
|
||||
|
||||
CFRunLoopGetCurrent = get_function("CFRunLoopGetCurrent", c_void_p)
|
||||
CFRelease = get_function("CFRelease", None, c_void_p)
|
||||
|
||||
|
||||
CFRunLoopTimerCreate = get_function(
|
||||
"CFRunLoopTimerCreate",
|
||||
c_void_p,
|
||||
@ -708,19 +709,19 @@ def _run_mac_app():
|
||||
CFRunLoopTimerCallback,
|
||||
c_void_p
|
||||
)
|
||||
|
||||
|
||||
CFRunLoopAddTimer = get_function("CFRunLoopAddTimer", None, c_void_p, c_void_p, c_void_p)
|
||||
CFRunLoopRunInMode = get_function("CFRunLoopRunInMode", c_int32, c_void_p, c_double, c_bool)
|
||||
|
||||
|
||||
@CFRunLoopTimerCallback
|
||||
def dummy_timer(timer, info):
|
||||
# this doesn't need to do anything
|
||||
# CFRunLoopTimerCreate just needs a valid callback
|
||||
return
|
||||
|
||||
|
||||
timer = CFRunLoopTimerCreate(kCFAllocatorDefault, INF_TIME, FIRE_ONCE, 0, 0, dummy_timer, NULL)
|
||||
CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode)
|
||||
CFRelease(timer)
|
||||
|
||||
|
||||
while CFRunLoopRunInMode(kCFRunLoopDefaultMode, INF_TIME, False) != kCFRunLoopRunFinished:
|
||||
pass
|
||||
|
@ -188,6 +188,7 @@ class GhidraBuiltinsBuilder {
|
||||
* @param printer the printer
|
||||
*/
|
||||
private void printScriptImports(PrintWriter printer) {
|
||||
printer.println("from __future__ import annotations");
|
||||
printer.println("import collections.abc");
|
||||
printer.println("import typing");
|
||||
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) {
|
||||
Element self = el.getEnclosingElement();
|
||||
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 javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ElementKind;
|
||||
import javax.lang.model.element.Modifier;
|
||||
import javax.lang.model.element.Name;
|
||||
import javax.lang.model.element.PackageElement;
|
||||
@ -106,24 +105,6 @@ abstract class PythonTypeStubElement<T extends Element> {
|
||||
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
|
||||
*
|
||||
@ -248,18 +229,17 @@ abstract class PythonTypeStubElement<T extends Element> {
|
||||
/**
|
||||
* 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 pkg the current package
|
||||
* @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()) {
|
||||
case DECLARED -> throw new RuntimeException(
|
||||
"declared types should use the qualified name");
|
||||
case ARRAY -> {
|
||||
TypeMirror component = ((ArrayType) type).getComponentType();
|
||||
yield "jpype.JArray[" + sanitizeQualifiedName(self, component, pkg) + "]";
|
||||
yield "jpype.JArray[" + sanitizeQualifiedName(component, pkg) + "]";
|
||||
}
|
||||
case BOOLEAN -> "jpype.JBoolean";
|
||||
case BYTE -> "jpype.JByte";
|
||||
@ -270,55 +250,31 @@ abstract class PythonTypeStubElement<T extends Element> {
|
||||
case LONG -> "jpype.JLong";
|
||||
case SHORT -> "jpype.JShort";
|
||||
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());
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* @param self the type to become typing.Self if encountered
|
||||
* @param type the type to make Python safe
|
||||
* @return the Python safe qualified type name
|
||||
*/
|
||||
final String sanitizeQualifiedName(Element self, TypeMirror type) {
|
||||
return sanitizeQualifiedName(self, type, pkg);
|
||||
final String sanitizeQualifiedName(TypeMirror type) {
|
||||
return sanitizeQualifiedName(type, pkg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* 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 pkg the current package
|
||||
* @return the Python safe qualified type name
|
||||
*/
|
||||
static final String sanitizeQualifiedName(Element self, TypeMirror type, PackageElement pkg) {
|
||||
if (isSelfType(self, type)) {
|
||||
return "typing.Self";
|
||||
}
|
||||
static final String sanitizeQualifiedName(TypeMirror type, PackageElement pkg) {
|
||||
if (type instanceof DeclaredType dt) {
|
||||
TypeElement el = (TypeElement) dt.asElement();
|
||||
PackageElement typePkg = getPackage(el);
|
||||
@ -341,11 +297,41 @@ abstract class PythonTypeStubElement<T extends Element> {
|
||||
return name;
|
||||
}
|
||||
Iterable<String> it = () -> args.stream()
|
||||
.map(paramType -> sanitizeQualifiedName(self, paramType, pkg))
|
||||
.map(paramType -> sanitizeQualifiedName(paramType, pkg))
|
||||
.iterator();
|
||||
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
|
||||
*
|
||||
* @param self the type to become typing.Self if encountered
|
||||
* @param type the wildcard type
|
||||
* @param pkg the current package
|
||||
* @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();
|
||||
if (base == null) {
|
||||
base = type.getSuperBound();
|
||||
}
|
||||
if (base != null) {
|
||||
return sanitizeQualifiedName(self, base, pkg);
|
||||
return sanitizeQualifiedName(base, pkg);
|
||||
}
|
||||
return "typing.Any";
|
||||
}
|
||||
|
@ -87,7 +87,6 @@ final class PythonTypeStubMethod extends PythonTypeStubElement<ExecutableElement
|
||||
"java.lang.Short", "int",
|
||||
"java.lang.String", "str"));
|
||||
|
||||
private final PythonTypeStubType parent;
|
||||
private final boolean filterSelf;
|
||||
List<String> typevars;
|
||||
Set<TypeElement> imports;
|
||||
@ -111,7 +110,6 @@ final class PythonTypeStubMethod extends PythonTypeStubElement<ExecutableElement
|
||||
*/
|
||||
PythonTypeStubMethod(PythonTypeStubType parent, ExecutableElement el, boolean filterSelf) {
|
||||
super(parent.doclet, el);
|
||||
this.parent = parent;
|
||||
this.filterSelf = filterSelf;
|
||||
}
|
||||
|
||||
@ -193,20 +191,14 @@ final class PythonTypeStubMethod extends PythonTypeStubElement<ExecutableElement
|
||||
return imports;
|
||||
}
|
||||
|
||||
List<? extends VariableElement> parameters = el.getParameters();
|
||||
TypeMirror resType = el.getReturnType();
|
||||
List<? extends TypeMirror> parameters = getParameterTypes();
|
||||
|
||||
// make the set big enough for all paramters and the return type
|
||||
imports = new HashSet<>(parameters.size() + 1);
|
||||
|
||||
if (resType instanceof DeclaredType dt) {
|
||||
imports.add((TypeElement) dt.asElement());
|
||||
}
|
||||
|
||||
for (VariableElement param : parameters) {
|
||||
if (param.asType() instanceof DeclaredType dt) {
|
||||
imports.add((TypeElement) dt.asElement());
|
||||
}
|
||||
addNeededTypes(imports, getReturnType());
|
||||
for (TypeMirror param : parameters) {
|
||||
addNeededTypes(imports, param);
|
||||
}
|
||||
|
||||
return imports;
|
||||
@ -329,7 +321,7 @@ final class PythonTypeStubMethod extends PythonTypeStubElement<ExecutableElement
|
||||
printer.print(convertedType);
|
||||
}
|
||||
else {
|
||||
printer.print(getTypeString(parent.el, res));
|
||||
printer.print(sanitizeQualifiedName(res));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -398,7 +390,7 @@ final class PythonTypeStubMethod extends PythonTypeStubElement<ExecutableElement
|
||||
if (convertedType != null) {
|
||||
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) {
|
||||
writeJavaDoc(printer, indent, "");
|
||||
printer.println("from __future__ import annotations");
|
||||
printer.println("import collections.abc");
|
||||
printer.println("import datetime");
|
||||
printer.println("import typing");
|
||||
|
@ -125,18 +125,13 @@ class PythonTypeStubType extends PythonTypeStubElement<TypeElement> {
|
||||
imports.add((TypeElement) dt.asElement());
|
||||
}
|
||||
for (TypeMirror iface : el.getInterfaces()) {
|
||||
if (iface instanceof DeclaredType dt) {
|
||||
imports.add((TypeElement) dt.asElement());
|
||||
}
|
||||
addNeededTypes(imports, iface);
|
||||
}
|
||||
for (PythonTypeStubNestedType nested : getNestedTypes()) {
|
||||
imports.addAll(nested.getImportedTypes());
|
||||
}
|
||||
for (VariableElement field : getFields()) {
|
||||
TypeMirror fieldType = field.asType();
|
||||
if (fieldType instanceof DeclaredType dt) {
|
||||
imports.add((TypeElement) dt.asElement());
|
||||
}
|
||||
addNeededTypes(imports, field.asType());
|
||||
}
|
||||
for (PythonTypeStubMethod method : getMethods()) {
|
||||
imports.addAll(method.getImportedTypes());
|
||||
@ -327,7 +322,7 @@ class PythonTypeStubType extends PythonTypeStubElement<TypeElement> {
|
||||
else {
|
||||
TypeMirror type = field.asType();
|
||||
printer.print(": ");
|
||||
String sanitizedType = getTypeString(el, type);
|
||||
String sanitizedType = sanitizeQualifiedName(type);
|
||||
|
||||
// only one of these may be applied
|
||||
// prefer Final over ClassVar
|
||||
@ -648,11 +643,7 @@ class PythonTypeStubType extends PythonTypeStubElement<TypeElement> {
|
||||
}
|
||||
return OBJECT_NAME;
|
||||
}
|
||||
return sanitizeQualifiedName(el, base);
|
||||
}
|
||||
|
||||
private String sanitizeQualifiedName(TypeMirror type) {
|
||||
return sanitizeQualifiedName(el, type);
|
||||
return sanitizeQualifiedName(base);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user