2023-07-27 14:48:05 +00:00
|
|
|
## vim: ft=makojava
|
|
|
|
|
|
2022-05-11 17:05:25 +02:00
|
|
|
<%
|
|
|
|
|
api = java_api
|
|
|
|
|
nat = c_api.get_name
|
|
|
|
|
%>
|
|
|
|
|
|
|
|
|
|
// ==========
|
|
|
|
|
// Define classes to handle project loading
|
|
|
|
|
// ==========
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Exception to represent errors during project manipulation
|
|
|
|
|
*/
|
|
|
|
|
public static final class ProjectManagerException extends RuntimeException {
|
|
|
|
|
ProjectManagerException(
|
|
|
|
|
final String message
|
|
|
|
|
) {
|
|
|
|
|
super(message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Enum to represent the source file mode for a GPR project
|
|
|
|
|
*/
|
|
|
|
|
public static enum SourceFileMode {
|
|
|
|
|
|
|
|
|
|
// ----- Enum values -----
|
|
|
|
|
|
|
|
|
|
DEFAULT(0),
|
|
|
|
|
ROOT_PROJECT(1),
|
|
|
|
|
WHOLE_PROJECT(2),
|
|
|
|
|
WHOLE_PROJECT_WITH_RUNTIME(3),
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
// ----- Class attributes -----
|
|
|
|
|
|
|
|
|
|
/** Singleton that represents the none source file mode */
|
|
|
|
|
public static final SourceFileMode NONE = DEFAULT;
|
|
|
|
|
|
|
|
|
|
/** The map from int to enum values */
|
|
|
|
|
private static final Map<Integer, SourceFileMode> map = new HashMap<>();
|
|
|
|
|
|
|
|
|
|
// ----- Instance attributes -----
|
|
|
|
|
|
|
|
|
|
/** The value of the instance */
|
|
|
|
|
private final int value;
|
|
|
|
|
|
|
|
|
|
// ----- Constructors -----
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The private constructor
|
|
|
|
|
*/
|
|
|
|
|
private SourceFileMode(
|
|
|
|
|
final int value
|
|
|
|
|
) {
|
|
|
|
|
this.value = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static {
|
|
|
|
|
for(SourceFileMode elem : SourceFileMode.values()) {
|
|
|
|
|
map.put(elem.value, elem);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ----- Enum methods -----
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get a source file mode from a native integer value.
|
|
|
|
|
*
|
|
|
|
|
* @param cValue The native value of the enum.
|
|
|
|
|
* @return The Java source file mode.
|
|
|
|
|
* @throws EnumException If the given native value doesn't correspond
|
|
|
|
|
* to an actual enum value.
|
|
|
|
|
*/
|
|
|
|
|
public static SourceFileMode fromC(
|
|
|
|
|
final int cValue
|
|
|
|
|
) throws EnumException {
|
|
|
|
|
if(!map.containsKey(cValue))
|
|
|
|
|
throw new EnumException(
|
|
|
|
|
"Cannot get SourceFileMode from " + cValue
|
|
|
|
|
);
|
|
|
|
|
return (SourceFileMode) map.get(cValue);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the native integer value of the enum instance.
|
|
|
|
|
*
|
|
|
|
|
* @return The native C value.
|
|
|
|
|
*/
|
|
|
|
|
public int toC() {
|
|
|
|
|
return this.value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-12 17:10:33 +02:00
|
|
|
/**
|
|
|
|
|
* This class represents a scenario variable for a GPR project file.
|
|
|
|
|
*/
|
|
|
|
|
public static final class ScenarioVariable {
|
|
|
|
|
|
|
|
|
|
// ----- Class attributes -----
|
|
|
|
|
|
|
|
|
|
/** Singleton that represents the none scenario variable. */
|
|
|
|
|
public static final ScenarioVariable NONE =
|
|
|
|
|
new ScenarioVariable(null, null);
|
|
|
|
|
|
|
|
|
|
// ----- Instance attributes -----
|
|
|
|
|
|
|
|
|
|
/** The name of the variable. */
|
|
|
|
|
public final String name;
|
|
|
|
|
|
|
|
|
|
/** The value of the variable. */
|
|
|
|
|
public final String value;
|
|
|
|
|
|
|
|
|
|
// ----- Constructors -----
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Create a new scenario variable with its name and value.
|
|
|
|
|
*
|
|
|
|
|
* @param name Name of the variable.
|
|
|
|
|
* @param value Value of the variable.
|
|
|
|
|
*/
|
|
|
|
|
ScenarioVariable(
|
|
|
|
|
final String name,
|
|
|
|
|
final String value
|
|
|
|
|
) {
|
|
|
|
|
this.name = name;
|
|
|
|
|
this.value = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Public method to create scenario variable.
|
|
|
|
|
* This method raise a runtime exception if name or value is null.
|
|
|
|
|
*
|
|
|
|
|
* @param name Name of the variable.
|
|
|
|
|
* @param value Value of the variable.
|
|
|
|
|
*/
|
|
|
|
|
public static ScenarioVariable create(
|
|
|
|
|
final String name,
|
|
|
|
|
final String value
|
|
|
|
|
) {
|
|
|
|
|
if(name == null) throw new RuntimeException("Scenario variable name cannot be null");
|
|
|
|
|
if(value == null) throw new RuntimeException("Scenario variable value cannot be null");
|
|
|
|
|
return new ScenarioVariable(name, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ----- Graal C API methods -----
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Wrap the given pointer to a native scenario variable.
|
|
|
|
|
*
|
|
|
|
|
* @param pointer The pointer to the native scenario variable.
|
|
|
|
|
* @return The wrapped scenario variable.
|
|
|
|
|
*/
|
|
|
|
|
public static ScenarioVariable wrap(
|
|
|
|
|
final Pointer pointer
|
|
|
|
|
) {
|
|
|
|
|
return wrap((ScenarioVariableNative) pointer.readWord(0));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Wrap the given native scenario variable.
|
|
|
|
|
*
|
|
|
|
|
* @param scenarioVariableNative The native scenario variable.
|
|
|
|
|
* @return The wrapped scenario variable.
|
|
|
|
|
*/
|
|
|
|
|
public static ScenarioVariable wrap(
|
|
|
|
|
final ScenarioVariableNative scenarioVariableNative
|
|
|
|
|
) {
|
|
|
|
|
final CCharPointer nameNative = scenarioVariableNative.get_name();
|
|
|
|
|
final CCharPointer valueNative = scenarioVariableNative.get_value();
|
|
|
|
|
return new ScenarioVariable(
|
|
|
|
|
nameNative.isNull() ?
|
|
|
|
|
null :
|
|
|
|
|
toJString(nameNative),
|
|
|
|
|
valueNative.isNull() ?
|
|
|
|
|
null :
|
|
|
|
|
toJString(valueNative)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Unwrap the scenario variable in the given native value.
|
|
|
|
|
*
|
|
|
|
|
* @param scenarioVariableNative The native value to fill.
|
|
|
|
|
*/
|
|
|
|
|
public void unwrap(
|
|
|
|
|
final ScenarioVariableNative scenarioVariableNative
|
|
|
|
|
) {
|
|
|
|
|
final CCharPointer nameNative = this.name == null ?
|
|
|
|
|
WordFactory.nullPointer() :
|
|
|
|
|
toCString(this.name);
|
|
|
|
|
final CCharPointer valueNative = this.value == null ?
|
|
|
|
|
WordFactory.nullPointer() :
|
|
|
|
|
toCString(this.value);
|
|
|
|
|
scenarioVariableNative.set_name(nameNative);
|
|
|
|
|
scenarioVariableNative.set_value(valueNative);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Release the given native scenario variable allocated strings.
|
|
|
|
|
*
|
|
|
|
|
* @param scenarioVariableNative The native scenario variable to release.
|
|
|
|
|
*/
|
|
|
|
|
public static void release(
|
|
|
|
|
final ScenarioVariableNative scenarioVariableNative
|
|
|
|
|
) {
|
|
|
|
|
if(scenarioVariableNative.get_name().isNonNull()) {
|
|
|
|
|
UnmanagedMemory.free(scenarioVariableNative.get_name());
|
|
|
|
|
}
|
|
|
|
|
if(scenarioVariableNative.get_value().isNonNull()) {
|
|
|
|
|
UnmanagedMemory.free(scenarioVariableNative.get_value());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-22 12:06:04 +02:00
|
|
|
// ----- Override methods -----
|
|
|
|
|
|
|
|
|
|
/** @see java.lang.Object#toString() */
|
|
|
|
|
public String toString() {
|
|
|
|
|
return "ScenarioVariable(" +
|
|
|
|
|
this.name + " = " + this.value +
|
|
|
|
|
")";
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-12 17:10:33 +02:00
|
|
|
}
|
|
|
|
|
|
2022-05-11 17:05:25 +02:00
|
|
|
/**
|
|
|
|
|
* This class is used for the GPR project loading.
|
|
|
|
|
*/
|
|
|
|
|
public static final class ProjectManager implements AutoCloseable {
|
|
|
|
|
|
|
|
|
|
// ----- Class attributes -----
|
|
|
|
|
|
|
|
|
|
/** Singleton that represents the none project manager. */
|
|
|
|
|
public static final ProjectManager NONE =
|
|
|
|
|
new ProjectManager(PointerWrapper.nullPointer());
|
|
|
|
|
|
|
|
|
|
// ----- Instance attributes -----
|
|
|
|
|
|
|
|
|
|
/** Reference to the native value. */
|
|
|
|
|
private final PointerWrapper reference;
|
|
|
|
|
|
2023-10-16 15:23:18 +02:00
|
|
|
/**
|
|
|
|
|
* List of diagnostics emitted by the native API during the project
|
|
|
|
|
* opening.
|
|
|
|
|
*/
|
|
|
|
|
private final List<String> diagnostics;
|
|
|
|
|
|
2022-05-11 17:05:25 +02:00
|
|
|
// ----- Constructors -----
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Create a new project manager from its native reference.
|
|
|
|
|
*
|
|
|
|
|
* @param reference The reference to the native project manager.
|
|
|
|
|
*/
|
|
|
|
|
ProjectManager(
|
|
|
|
|
final PointerWrapper reference
|
|
|
|
|
) {
|
|
|
|
|
this.reference = reference;
|
2023-10-16 15:23:18 +02:00
|
|
|
this.diagnostics = new ArrayList<>();
|
2022-05-11 17:05:25 +02:00
|
|
|
}
|
|
|
|
|
|
2023-04-12 17:10:33 +02:00
|
|
|
/**
|
|
|
|
|
* Create a project manager for the given project file.
|
|
|
|
|
*
|
|
|
|
|
* @param projectFile The GPR project file to load.
|
|
|
|
|
* @return The newly created project manager.
|
|
|
|
|
*/
|
|
|
|
|
public static ProjectManager create(
|
|
|
|
|
final String projectFile
|
|
|
|
|
) {
|
|
|
|
|
return create(
|
|
|
|
|
projectFile,
|
|
|
|
|
null,
|
|
|
|
|
"",
|
|
|
|
|
""
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-11 17:05:25 +02:00
|
|
|
/**
|
|
|
|
|
* Create a project manager from a project file, target and runtime.
|
|
|
|
|
*
|
|
|
|
|
* @param projectFile The GPR file to load.
|
2023-04-12 17:10:33 +02:00
|
|
|
* @param scenarioVariables The scenario variables for the project, it can be null.
|
2022-05-11 17:05:25 +02:00
|
|
|
* @param target The target to load.
|
|
|
|
|
* @param runtime The runtime to load.
|
|
|
|
|
* @return The newly created project manager.
|
|
|
|
|
*/
|
|
|
|
|
public static ProjectManager create(
|
|
|
|
|
final String projectFile,
|
2023-04-12 17:10:33 +02:00
|
|
|
final ScenarioVariable[] scenarioVariables,
|
2022-05-11 17:05:25 +02:00
|
|
|
final String target,
|
|
|
|
|
final String runtime
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
|
|
if(ImageInfo.inImageCode()) {
|
2023-04-12 17:10:33 +02:00
|
|
|
// Create the scenario variable array
|
|
|
|
|
final Pointer scenarioVariablesNative;
|
|
|
|
|
final int scenarioVariableNativeSize = SizeOf.get(ScenarioVariableNative.class);
|
|
|
|
|
|
|
|
|
|
if(scenarioVariables != null && scenarioVariables.length > 0) {
|
|
|
|
|
final int size = scenarioVariables.length + 1;
|
|
|
|
|
scenarioVariablesNative = UnmanagedMemory.calloc(
|
|
|
|
|
size * scenarioVariableNativeSize
|
|
|
|
|
);
|
|
|
|
|
for(int i = 0 ; i < scenarioVariables.length ; i++) {
|
|
|
|
|
final ScenarioVariableNative scenarioVariableNative = (ScenarioVariableNative)
|
|
|
|
|
scenarioVariablesNative.add(i * scenarioVariableNativeSize);
|
|
|
|
|
scenarioVariables[i].unwrap(scenarioVariableNative);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
scenarioVariablesNative = WordFactory.nullPointer();
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-11 17:05:25 +02:00
|
|
|
// Call the native project loading function
|
|
|
|
|
final CCharPointer projectFileNative = toCString(projectFile);
|
|
|
|
|
final CCharPointer targetNative = toCString(target);
|
|
|
|
|
final CCharPointer runtimeNative = toCString(runtime);
|
|
|
|
|
final Pointer projectPointer = StackValue.get(SizeOf.get(VoidPointer.class));
|
|
|
|
|
projectPointer.writeWord(0, WordFactory.nullPointer());
|
|
|
|
|
final Pointer errorsPointer = StackValue.get(SizeOf.get(VoidPointer.class));
|
|
|
|
|
errorsPointer.writeWord(0, WordFactory.nullPointer());
|
|
|
|
|
NI_LIB.${nat("gpr_project_load")}(
|
|
|
|
|
projectFileNative,
|
2023-04-12 17:10:33 +02:00
|
|
|
scenarioVariablesNative,
|
2022-05-11 17:05:25 +02:00
|
|
|
targetNative,
|
|
|
|
|
runtimeNative,
|
|
|
|
|
projectPointer,
|
|
|
|
|
errorsPointer
|
|
|
|
|
);
|
2023-04-12 17:10:33 +02:00
|
|
|
|
2023-06-22 12:06:04 +02:00
|
|
|
// Check the langkit exception and cast it into a project manager error
|
|
|
|
|
try {
|
|
|
|
|
checkException();
|
|
|
|
|
} catch (LangkitException e) {
|
|
|
|
|
throw new ProjectManagerException(e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get the result of modified values
|
|
|
|
|
final ProjectManagerNative projectManagerNative = (ProjectManagerNative) projectPointer.readWord(0);
|
|
|
|
|
final StringArrayNative errorArrayNative = (StringArrayNative) errorsPointer.readWord(0);
|
|
|
|
|
|
2023-04-12 17:10:33 +02:00
|
|
|
// Free the scenario variables
|
|
|
|
|
if(scenarioVariablesNative.isNonNull()) {
|
|
|
|
|
for(int i = 0 ; i < scenarioVariables.length ; i++) {
|
|
|
|
|
final ScenarioVariableNative scenarioVariableNative = (ScenarioVariableNative)
|
|
|
|
|
scenarioVariablesNative.add(i * scenarioVariableNativeSize);
|
|
|
|
|
ScenarioVariable.release(scenarioVariableNative);
|
|
|
|
|
}
|
|
|
|
|
UnmanagedMemory.free(scenarioVariablesNative);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Free the allocated strings
|
2022-05-11 17:05:25 +02:00
|
|
|
UnmanagedMemory.free(projectFileNative);
|
|
|
|
|
UnmanagedMemory.free(targetNative);
|
|
|
|
|
UnmanagedMemory.free(runtimeNative);
|
|
|
|
|
|
2023-06-22 12:06:04 +02:00
|
|
|
// `errorsPointer` is not allocated if an exception was raised during project file loading
|
2023-10-16 15:23:18 +02:00
|
|
|
String[] errors = new String[0];
|
2023-06-22 12:06:04 +02:00
|
|
|
if (errorArrayNative.isNonNull()) {
|
|
|
|
|
// Translate the error native array into a Java array
|
2023-10-16 15:23:18 +02:00
|
|
|
errors = toJStringArray(errorArrayNative);
|
2022-05-11 17:05:25 +02:00
|
|
|
|
|
|
|
|
// Free the error array
|
2023-06-22 12:06:04 +02:00
|
|
|
NI_LIB.${nat("free_string_array")}(errorArrayNative);
|
2022-05-11 17:05:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check the langkit exception and cast it into a project manager error
|
|
|
|
|
try {
|
|
|
|
|
checkException();
|
|
|
|
|
} catch (LangkitException e) {
|
|
|
|
|
throw new ProjectManagerException(e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-16 15:23:18 +02:00
|
|
|
// Create the result project manager and add diagnostics if any
|
|
|
|
|
final ProjectManager res = wrap(projectManagerNative);
|
|
|
|
|
if (errors.length > 0) {
|
|
|
|
|
res.diagnostics.addAll(List.of(errors));
|
|
|
|
|
}
|
|
|
|
|
return res;
|
2022-05-11 17:05:25 +02:00
|
|
|
} else {
|
2023-10-16 15:23:18 +02:00
|
|
|
final List<String> diagnostics = new ArrayList<>();
|
2022-05-11 17:05:25 +02:00
|
|
|
final PointerWrapper reference = JNI_LIB.${nat("gpr_project_load")}(
|
|
|
|
|
projectFile,
|
2023-04-12 17:10:33 +02:00
|
|
|
scenarioVariables,
|
2022-05-11 17:05:25 +02:00
|
|
|
target,
|
2023-10-16 15:23:18 +02:00
|
|
|
runtime,
|
|
|
|
|
diagnostics
|
2022-05-11 17:05:25 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Check the langkit exceptions
|
|
|
|
|
try {
|
|
|
|
|
checkException();
|
|
|
|
|
} catch (LangkitException e) {
|
|
|
|
|
throw new ProjectManagerException(e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Return the project manager
|
2023-10-16 15:23:18 +02:00
|
|
|
final ProjectManager res = new ProjectManager(reference);
|
|
|
|
|
res.diagnostics.addAll(diagnostics);
|
|
|
|
|
return res;
|
2022-05-11 17:05:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ----- Graal C API methods -----
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Wrap a native project manager in the Java class.
|
|
|
|
|
*
|
|
|
|
|
* @param pointer The pointer to the native project manager.
|
|
|
|
|
* @return The newly wrapped project manager.
|
|
|
|
|
*/
|
|
|
|
|
static ProjectManager wrap(
|
|
|
|
|
final Pointer pointer
|
|
|
|
|
) {
|
|
|
|
|
return wrap((ProjectManagerNative) pointer.readWord(0));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Wrap a native project manager in the Java class.
|
|
|
|
|
*
|
|
|
|
|
* @param projectManagerNative The native project manager to wrap.
|
|
|
|
|
* @return The newly wrapped project manager.
|
|
|
|
|
*/
|
|
|
|
|
static ProjectManager wrap(
|
|
|
|
|
final ProjectManagerNative projectManagerNative
|
|
|
|
|
) {
|
|
|
|
|
return new ProjectManager(new PointerWrapper(projectManagerNative));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Unwrap the project manager inside the given pointer.
|
|
|
|
|
*
|
|
|
|
|
* @param pointer The pointer to write in.
|
|
|
|
|
*/
|
|
|
|
|
public void unwrap(
|
|
|
|
|
final Pointer pointer
|
|
|
|
|
) {
|
|
|
|
|
pointer.writeWord(0, this.unwrap());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the native value of the project manager.
|
|
|
|
|
*
|
|
|
|
|
* @return The native project manager.
|
|
|
|
|
*/
|
|
|
|
|
public ProjectManagerNative unwrap() {
|
|
|
|
|
return (ProjectManagerNative) this.reference.ni();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ----- Class methods -----
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Translate a native string array structure into a Java string
|
|
|
|
|
* array.
|
|
|
|
|
*
|
|
|
|
|
* @param stringArrayNative The native string array structure.
|
|
|
|
|
* @return The Java string array.
|
|
|
|
|
*/
|
|
|
|
|
private static String[] toJStringArray(
|
|
|
|
|
final StringArrayNative stringArrayNative
|
|
|
|
|
) {
|
|
|
|
|
final String[] res = new String[stringArrayNative.get_length()];
|
|
|
|
|
final CCharPointerPointer nativeFilesPointer = stringArrayNative.get_c_ptr();
|
|
|
|
|
for(int i = 0 ; i < res.length ; i++) {
|
|
|
|
|
final CCharPointer nativeFile = nativeFilesPointer.read(i);
|
|
|
|
|
res[i] = toJString(nativeFile);
|
|
|
|
|
}
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ----- Instance methods -----
|
|
|
|
|
|
2023-10-16 15:23:18 +02:00
|
|
|
public List<String> getDiagnostics() {
|
|
|
|
|
return this.diagnostics;
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-11 17:05:25 +02:00
|
|
|
/**
|
2023-07-27 17:24:31 +02:00
|
|
|
* Create a unit provider for the given subproject.
|
2022-05-11 17:05:25 +02:00
|
|
|
*
|
2023-07-27 17:24:31 +02:00
|
|
|
* @param subproject The subproject for which to create a unit provider.
|
2022-05-11 17:05:25 +02:00
|
|
|
* @return The unit provider for the project manager.
|
|
|
|
|
*/
|
2023-07-27 17:24:31 +02:00
|
|
|
public UnitProvider getProvider(final String subproject) {
|
|
|
|
|
final UnitProvider result;
|
|
|
|
|
if(ImageInfo.inImageCode()) {
|
|
|
|
|
final CCharPointer subprojectNative =
|
|
|
|
|
subproject == null ?
|
|
|
|
|
WordFactory.nullPointer() :
|
|
|
|
|
toCString(subproject);
|
2022-05-11 17:05:25 +02:00
|
|
|
|
2023-07-27 17:24:31 +02:00
|
|
|
UnitProviderNative unitProviderNative = NI_LIB.${nat('gpr_project_create_unit_provider')}(
|
|
|
|
|
this.reference.ni(),
|
|
|
|
|
subprojectNative
|
|
|
|
|
);
|
|
|
|
|
result = UnitProvider.wrap(unitProviderNative);
|
|
|
|
|
if (subproject != null) {
|
|
|
|
|
UnmanagedMemory.free(subprojectNative);
|
2022-05-11 17:05:25 +02:00
|
|
|
}
|
2023-07-27 17:24:31 +02:00
|
|
|
} else {
|
|
|
|
|
result = JNI_LIB.${nat("gpr_project_create_unit_provider")}(
|
|
|
|
|
this,
|
|
|
|
|
subproject
|
|
|
|
|
);
|
2022-05-11 17:05:25 +02:00
|
|
|
}
|
2023-07-27 17:24:31 +02:00
|
|
|
return result;
|
|
|
|
|
}
|
2022-05-11 17:05:25 +02:00
|
|
|
|
2023-07-27 17:24:31 +02:00
|
|
|
/**
|
|
|
|
|
* Create a unit provider for root project.
|
|
|
|
|
*/
|
|
|
|
|
public UnitProvider getProvider() {
|
|
|
|
|
return this.getProvider(null);
|
2022-05-11 17:05:25 +02:00
|
|
|
}
|
|
|
|
|
|
2023-07-28 14:48:18 +00:00
|
|
|
${java_doc("libadalang.gpr_project_create_context", 8)}
|
|
|
|
|
public AnalysisContext createContext(
|
|
|
|
|
String subproject,
|
|
|
|
|
EventHandler eventHandler,
|
|
|
|
|
boolean withTrivia,
|
|
|
|
|
int tabStop
|
|
|
|
|
) {
|
|
|
|
|
if(ImageInfo.inImageCode()) {
|
|
|
|
|
// Prepare C values for native calls
|
|
|
|
|
final CCharPointer subproject_c =
|
|
|
|
|
subproject == null
|
|
|
|
|
? WordFactory.nullPointer()
|
|
|
|
|
: toCString(subproject);
|
|
|
|
|
EventHandlerNative eventHandler_c =
|
|
|
|
|
eventHandler == null
|
|
|
|
|
? WordFactory.nullPointer()
|
|
|
|
|
: eventHandler.reference.ni();
|
|
|
|
|
|
|
|
|
|
// Manually allocate a C-level analysis context so that we can
|
|
|
|
|
// initialize it ourselves.
|
|
|
|
|
final PointerWrapper context = new PointerWrapper(
|
|
|
|
|
NI_LIB.${nat("allocate_analysis_context")}()
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Create the Java wrapper, so that we have one ready for
|
|
|
|
|
// event handler callbacks triggered during context
|
|
|
|
|
// initialization.
|
|
|
|
|
AnalysisContext result =
|
|
|
|
|
AnalysisContext.fromReference(context, eventHandler, true);
|
|
|
|
|
|
|
|
|
|
// "result" has its own ownership share: release ours
|
|
|
|
|
NI_LIB.${nat("context_decref")}(context.ni());
|
|
|
|
|
|
|
|
|
|
// TODO: attach "this" to "result" so that the former lives at
|
|
|
|
|
// least as long as the former.
|
|
|
|
|
|
|
|
|
|
// Finally, initialize the analysis context. Note that this
|
|
|
|
|
// step may raise an exception: in that case, the analysis
|
|
|
|
|
// context is considered not initialized: release it.
|
|
|
|
|
NI_LIB.${nat("gpr_project_initialize_context")}(
|
|
|
|
|
this.reference.ni(),
|
|
|
|
|
context.ni(),
|
|
|
|
|
subproject_c,
|
|
|
|
|
eventHandler_c,
|
|
|
|
|
withTrivia ? 1 : 0,
|
|
|
|
|
tabStop
|
|
|
|
|
);
|
|
|
|
|
UnmanagedMemory.free(subproject_c);
|
|
|
|
|
final LangkitExceptionNative exc_c =
|
|
|
|
|
NI_LIB.${nat("get_last_exception")}();
|
|
|
|
|
if (exc_c.isNonNull()) {
|
|
|
|
|
LangkitException exc = wrapException(exc_c);
|
|
|
|
|
NI_LIB.${nat("context_decref")}(context.ni());
|
|
|
|
|
throw exc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
} else {
|
|
|
|
|
return JNI_LIB.${nat("gpr_project_create_context")}(
|
|
|
|
|
this,
|
|
|
|
|
subproject,
|
|
|
|
|
eventHandler,
|
|
|
|
|
withTrivia,
|
|
|
|
|
tabStop
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-11 17:05:25 +02:00
|
|
|
/**
|
2023-07-27 17:23:43 +02:00
|
|
|
* Get the files for the given subprojects in a string array.
|
2022-05-11 17:05:25 +02:00
|
|
|
*
|
|
|
|
|
* @param mode The file getting mode.
|
2023-07-27 17:23:43 +02:00
|
|
|
* @param subprojects The subprojects to consider.
|
2022-05-11 17:05:25 +02:00
|
|
|
* @return The array that contains the project files.
|
|
|
|
|
*/
|
|
|
|
|
public String[] getFiles(
|
2023-07-27 17:23:43 +02:00
|
|
|
final SourceFileMode mode,
|
|
|
|
|
final String[] subprojects
|
2022-05-11 17:05:25 +02:00
|
|
|
) {
|
|
|
|
|
// Verify if the project is null
|
|
|
|
|
if(this.reference.isNull())
|
|
|
|
|
return new String[0];
|
|
|
|
|
|
2023-07-27 17:23:43 +02:00
|
|
|
String[] result = null;
|
2023-08-01 14:27:50 +00:00
|
|
|
LangkitException exc;
|
2023-07-27 17:23:43 +02:00
|
|
|
|
2022-05-11 17:05:25 +02:00
|
|
|
if(ImageInfo.inImageCode()) {
|
2023-08-01 14:27:50 +00:00
|
|
|
// Convert the Java array of subprojects ("subprojects"
|
|
|
|
|
// argument) into the required C array
|
|
|
|
|
// (subprojectCount/subprojectsNative).
|
2023-07-27 17:23:43 +02:00
|
|
|
final int subprojectCount;
|
|
|
|
|
final CCharPointerPointer subprojectsNative;
|
|
|
|
|
|
|
|
|
|
if (subprojects != null && subprojects.length > 0) {
|
|
|
|
|
subprojectCount = subprojects.length;
|
|
|
|
|
subprojectsNative =
|
|
|
|
|
UnmanagedMemory.calloc(
|
|
|
|
|
subprojectCount * SizeOf.get(CCharPointerPointer.class)
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
subprojectCount = 0;
|
|
|
|
|
subprojectsNative = WordFactory.nullPointer();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < subprojectCount; ++i) {
|
|
|
|
|
subprojectsNative.write(i, toCString(subprojects[i]));
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-01 14:27:50 +00:00
|
|
|
// Call the C API. Keep track of a potential native exception.
|
|
|
|
|
StringArrayNative sourceFileArray =
|
2022-05-11 17:05:25 +02:00
|
|
|
NI_LIB.${nat('gpr_project_source_files')}(
|
|
|
|
|
this.reference.ni(),
|
|
|
|
|
mode.toC(),
|
2023-07-27 17:23:43 +02:00
|
|
|
subprojectsNative,
|
|
|
|
|
subprojectCount
|
2022-05-11 17:05:25 +02:00
|
|
|
);
|
2023-08-01 14:27:50 +00:00
|
|
|
exc = getLastException();
|
2023-07-27 17:23:43 +02:00
|
|
|
|
2023-08-01 14:27:50 +00:00
|
|
|
// If the call was successful, create the Java array result and
|
|
|
|
|
// initialize it, and free the C array result.
|
|
|
|
|
if(exc == null) {
|
|
|
|
|
result = toJStringArray(sourceFileArray);
|
|
|
|
|
NI_LIB.${nat("free_string_array")}(sourceFileArray);
|
|
|
|
|
}
|
2023-07-27 17:23:43 +02:00
|
|
|
|
2023-08-01 14:27:50 +00:00
|
|
|
// Release subprojectsNative
|
2023-07-27 17:23:43 +02:00
|
|
|
for (int i = 0; i < subprojectCount; ++i) {
|
|
|
|
|
UnmanagedMemory.free(subprojectsNative.read(i));
|
|
|
|
|
}
|
|
|
|
|
if (subprojectCount > 0) {
|
|
|
|
|
UnmanagedMemory.free(subprojectsNative);
|
|
|
|
|
}
|
2022-05-11 17:05:25 +02:00
|
|
|
} else {
|
2023-07-27 17:23:43 +02:00
|
|
|
result = JNI_LIB.${nat("gpr_project_source_files")}(
|
2022-05-11 17:05:25 +02:00
|
|
|
this,
|
2023-07-27 17:23:43 +02:00
|
|
|
mode.toC(),
|
|
|
|
|
subprojects
|
2022-05-11 17:05:25 +02:00
|
|
|
);
|
2023-08-01 14:27:50 +00:00
|
|
|
exc = getLastException();
|
2022-05-11 17:05:25 +02:00
|
|
|
}
|
|
|
|
|
|
2023-08-01 14:27:50 +00:00
|
|
|
// If we got an exception, turn it into a ProjectManagerException
|
|
|
|
|
// one.
|
|
|
|
|
if(exc != null) {
|
|
|
|
|
throw new ProjectManagerException(exc.getMessage());
|
2023-07-27 17:23:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the files of the root project in a string array.
|
|
|
|
|
*
|
|
|
|
|
* @param mode The file getting mode.
|
|
|
|
|
* @return The array that contains the project files.
|
|
|
|
|
*/
|
|
|
|
|
public String[] getFiles(final SourceFileMode mode) {
|
|
|
|
|
return this.getFiles(mode, null);
|
2022-05-11 17:05:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @see java.lang.AutoCloseable#close() */
|
|
|
|
|
@Override
|
|
|
|
|
public void close() {
|
|
|
|
|
|
|
|
|
|
if(ImageInfo.inImageCode()) {
|
|
|
|
|
NI_LIB.${nat("gpr_project_free")}(this.reference.ni());
|
|
|
|
|
} else {
|
|
|
|
|
JNI_LIB.${nat("gpr_project_free")}(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
2023-06-26 15:11:22 +02:00
|
|
|
|
|
|
|
|
${java_doc("libadalang.create_auto_provider", 4)}
|
|
|
|
|
public static UnitProvider createAutoProvider(
|
|
|
|
|
final String[] sourceFiles,
|
|
|
|
|
final String charset
|
|
|
|
|
) {
|
|
|
|
|
if (ImageInfo.inImageCode()) {
|
|
|
|
|
final CCharPointer charsetNative =
|
|
|
|
|
charset == null ?
|
|
|
|
|
WordFactory.nullPointer() :
|
|
|
|
|
toCString(charset);
|
|
|
|
|
|
|
|
|
|
// Allocate the C array of C strings that will contain decoded
|
|
|
|
|
// source file names. Make room for one additional null pointer
|
|
|
|
|
// to mark the end of the array.
|
|
|
|
|
final CCharPointerPointer sourceFilesNative =
|
|
|
|
|
UnmanagedMemory.calloc(
|
|
|
|
|
(sourceFiles.length + 1) * SizeOf.get(CCharPointerPointer.class)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < sourceFiles.length; ++i) {
|
|
|
|
|
sourceFilesNative.write(i, toCString(sourceFiles[i]));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create the auto provider
|
|
|
|
|
final UnitProviderNative unitProviderNative =
|
|
|
|
|
NI_LIB.${nat('create_auto_provider')}(
|
|
|
|
|
sourceFilesNative,
|
|
|
|
|
charsetNative
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Release all temporarily allocated memory
|
|
|
|
|
for (int i = 0; i < sourceFiles.length; ++i) {
|
|
|
|
|
UnmanagedMemory.free(sourceFilesNative.read(i));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UnmanagedMemory.free(sourceFilesNative);
|
|
|
|
|
|
|
|
|
|
if (charset != null) {
|
|
|
|
|
UnmanagedMemory.free(charsetNative);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return UnitProvider.wrap(unitProviderNative);
|
|
|
|
|
} else {
|
|
|
|
|
return JNI_LIB.${nat("create_auto_provider")}(
|
|
|
|
|
sourceFiles,
|
|
|
|
|
charset
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|