1 #include <stdlib.h>
   2 #include <string.h>
   3 #include <jni.h>
   4 #include <clang-c/Index.h>
   5 #include <assert.h>
   6 
   7 static jclass clsStructType;
   8 static jfieldID dataStructType;
   9 
  10 static jclass clsIndex;
  11 static jclass clsCursor;
  12 static jclass clsType;
  13 static jclass clsjavaLangString;
  14 static jclass clsIAE;
  15 static jmethodID ctorIndex;
  16 static jmethodID ctorCursor;
  17 static jmethodID ctorType;
  18 static jmethodID visitorID;
  19 static jclass clsSourceLocation;
  20 static jmethodID ctorSourceLocation;
  21 static jclass clsLocation;
  22 static jmethodID ctorLocation;
  23 static jclass clsSourceRange;
  24 static jmethodID ctorSourceRange;
  25 
  26 jstring CX2JString(JNIEnv *env, CXString str) {
  27     const char* cstr = clang_getCString(str);
  28     jstring rv = env->NewStringUTF(cstr);
  29     clang_disposeString(str);
  30     return rv;
  31 }
  32 
  33 struct LocationFactory {
  34     CXFile file;
  35     unsigned line;
  36     unsigned col;
  37     unsigned offset;
  38 
  39     jobject get(JNIEnv *env, CXSourceLocation * const loc,
  40                 void (*func)(CXSourceLocation, CXFile*, unsigned*, unsigned*, unsigned*)) {
  41         func(*loc, &file, &line, &col, &offset);
  42         return env->NewObject(clsLocation, ctorLocation,
  43             CX2JString(env, clang_getFileName(file)), line, col, offset);
  44     }
  45 };
  46 
  47 #define J2P(env, pojo) \
  48     (env->GetDirectBufferAddress(env->GetObjectField(pojo, dataStructType)))
  49 
  50 #ifdef __cplusplus
  51 extern "C" {
  52 #endif
  53 
  54 jint JNI_OnLoad(JavaVM *vm, void *reserved) {
  55     JNIEnv* env;
  56 
  57     if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
  58         // force unload
  59         return -1;
  60     }
  61 
  62     clsjavaLangString = (jclass) env->NewGlobalRef(env->FindClass("java/lang/String"));
  63     clsIAE = (jclass) env->NewGlobalRef(env->FindClass("java/lang/IllegalArgumentException"));
  64 
  65     clsIndex = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/clang/Index"));
  66     ctorIndex = env->GetMethodID(clsIndex, "<init>", "(J)V");
  67 
  68     clsStructType = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/clang/StructType"));
  69     dataStructType = env->GetFieldID(clsStructType, "data", "Ljava/nio/ByteBuffer;");
  70     assert(dataStructType != NULL);
  71 
  72     clsCursor = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/clang/Cursor"));
  73     ctorCursor = env->GetMethodID(clsCursor, "<init>", "(Ljava/nio/ByteBuffer;)V");
  74     visitorID = env->GetStaticMethodID(clsCursor, "visit",
  75         "(Ljdk/internal/clang/Cursor$Visitor;Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;Ljava/lang/Object;)I");
  76     assert(visitorID != NULL);
  77 
  78     clsType = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/clang/Type"));
  79     ctorType = env->GetMethodID(clsType, "<init>", "(Ljava/nio/ByteBuffer;)V");
  80 
  81     clsSourceLocation = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/clang/SourceLocation"));
  82     ctorSourceLocation = env->GetMethodID(clsSourceLocation, "<init>", "(Ljava/nio/ByteBuffer;)V");
  83 
  84     clsLocation = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/clang/SourceLocation$Location"));
  85     ctorLocation = env->GetMethodID(clsLocation, "<init>", "(Ljava/lang/String;III)V");
  86     assert(ctorLocation != NULL);
  87 
  88     clsSourceRange = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/clang/SourceRange"));
  89     ctorSourceRange = env->GetMethodID(clsSourceRange, "<init>", "(Ljava/nio/ByteBuffer;)V");
  90 
  91     return JNI_VERSION_1_6;
  92 }
  93 
  94 void JNI_OnUnload(JavaVM *vm, void *reserved) {
  95     JNIEnv* env;
  96 
  97     if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
  98         return;
  99     }
 100 
 101     env->DeleteGlobalRef(clsIndex);
 102     env->DeleteGlobalRef(clsCursor);
 103     env->DeleteGlobalRef(clsType);
 104 }
 105 
 106 JNIEXPORT jobject JNICALL Java_jdk_internal_clang_LibClang_createIndex
 107   (JNIEnv *env, jclass cls) {
 108     CXIndex idx = clang_createIndex(0, 0);
 109     clang_toggleCrashRecovery(false);
 110     // CXIndex is a void*
 111     return env->NewObject(clsIndex, ctorIndex, (jlong) idx);
 112 }
 113 
 114 JNIEXPORT jstring JNICALL Java_jdk_internal_clang_LibClang_version
 115   (JNIEnv *env, jclass cls) {
 116     CXString ver = clang_getClangVersion();
 117     return CX2JString(env, ver);
 118 }
 119 
 120 JNIEXPORT void JNICALL Java_jdk_internal_clang_Index_disposeIndex
 121   (JNIEnv *env, jobject obj, jlong addr) {
 122     clang_disposeIndex((CXIndex) addr);
 123 }
 124 
 125 JNIEXPORT jlong JNICALL Java_jdk_internal_clang_Index_parseFile
 126   (JNIEnv *env, jobject obj, jlong addr, jstring path, jboolean detailed, jobjectArray args) {
 127     const char *filename = env->GetStringUTFChars(path, NULL);
 128     jsize argCnt = env->GetArrayLength(args);
 129     const char** cargs = (const char**) calloc(argCnt, sizeof(char*));
 130     jsize i;
 131     jstring arg;
 132     for (i = 0; i < argCnt; i++) {
 133         arg = (jstring) env->GetObjectArrayElement(args, i);
 134         cargs[i] = env->GetStringUTFChars(arg, NULL);
 135     }
 136     CXTranslationUnit tu = clang_parseTranslationUnit((CXIndex) addr,
 137         filename, cargs, argCnt, NULL, 0, detailed ? CXTranslationUnit_DetailedPreprocessingRecord : CXTranslationUnit_None);
 138     env->ReleaseStringUTFChars(path, filename);
 139     for (i = 0; i < argCnt; i++) {
 140         arg = (jstring) env->GetObjectArrayElement(args, i);
 141         env->ReleaseStringUTFChars(arg, cargs[i]);
 142     }
 143     free(cargs);
 144     return (jlong) tu;
 145 }
 146 
 147 JNIEXPORT void JNICALL Java_jdk_internal_clang_Index_disposeTranslationUnit
 148   (JNIEnv *env, jobject obj, jlong tu) {
 149     clang_disposeTranslationUnit((CXTranslationUnit) tu);
 150 }
 151 
 152 JNIEXPORT jobject JNICALL Java_jdk_internal_clang_Index_getTranslationUnitCursor
 153   (JNIEnv *env, jobject obj, jlong tu) {
 154     CXCursor cursor = clang_getTranslationUnitCursor((CXTranslationUnit) tu);
 155     jobject buffer = env->NewDirectByteBuffer(&cursor, sizeof(CXCursor));
 156     return env->NewObject(clsCursor, ctorCursor, buffer);
 157 }
 158 
 159 JNIEXPORT jobjectArray JNICALL Java_jdk_internal_clang_Index_getTranslationUnitDiagnostics
 160   (JNIEnv *env, jobject obj, jlong jtu) {
 161     CXTranslationUnit tu = (CXTranslationUnit) jtu;
 162     unsigned cnt = clang_getNumDiagnostics(tu);
 163     unsigned i;
 164 
 165     if (cnt == 0) {
 166         return NULL;
 167     }
 168 
 169     jclass clsDiagnostic = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/clang/Diagnostic"));
 170     jmethodID ctorDiagnostic = env->GetMethodID(clsDiagnostic, "<init>", "(J)V");
 171 
 172     jobjectArray rv = env->NewObjectArray(cnt, clsDiagnostic, NULL);
 173     jobject jdiag;
 174 
 175     for (i = 0; i < cnt; i++) {
 176         CXDiagnostic diag = clang_getDiagnostic(tu, i);
 177         jdiag = env->NewObject(clsDiagnostic, ctorDiagnostic, (jlong) diag);
 178         env->SetObjectArrayElement(rv, i, jdiag);
 179     }
 180 
 181     return rv;
 182 }
 183 
 184 static int
 185 compareSourceLocation(JNIEnv *env, CXSourceLocation loc1, CXSourceLocation loc2) {
 186   struct {
 187     CXFile file;
 188     unsigned line;
 189     unsigned column;
 190     unsigned offset;
 191   } info1, info2;
 192 
 193   clang_getSpellingLocation(loc1, &info1.file, &info1.line, &info1.column, &info1.offset);
 194   clang_getSpellingLocation(loc2, &info2.file, &info2.line, &info2.column, &info2.offset);
 195 
 196   CXString fileName1 = clang_getFileName(info1.file);
 197   CXString fileName2 = clang_getFileName(info2.file);
 198 
 199   int cmp = strcmp(clang_getCString(fileName1), clang_getCString(fileName2));
 200 
 201   clang_disposeString(fileName1);
 202   clang_disposeString(fileName2);
 203 
 204   if (cmp != 0) {
 205     env->ThrowNew(clsIAE, "Source locations must be in same file");
 206     return 0;
 207   }
 208 
 209   if (info1.line != info2.line) {
 210     return info1.line - info2.line;
 211   } else if (info1.column != info2.column) {
 212     return info1.column - info2.column;
 213   } else if (info1.offset != info2.offset) {
 214     return info1.offset - info2.offset;
 215   }
 216 
 217   return 0;
 218 }
 219 
 220 static jboolean
 221 locationInRange(JNIEnv *env, CXSourceLocation loc, CXSourceRange range) {
 222   CXSourceLocation start = clang_getRangeStart(range);
 223   CXSourceLocation end = clang_getRangeEnd(range);
 224 
 225   return
 226     compareSourceLocation(env, loc, start) >= 0 &&
 227     compareSourceLocation(env, loc, end) <= 0;
 228 }
 229 
 230 JNIEXPORT jobjectArray JNICALL Java_jdk_internal_clang_Index_tokenize
 231   (JNIEnv *env, jobject obj, jlong jtu, jobject range) {
 232   CXTranslationUnit tu = (CXTranslationUnit) jtu;
 233   CXSourceRange *ptr = (CXSourceRange*) J2P(env, range);
 234 
 235   CXToken *tokens;
 236   unsigned nTokens, i;
 237 
 238   clang_tokenize(tu, *ptr, &tokens, &nTokens);
 239 
 240 
 241   // This filtering stuff is to ork-around a bug in libclang which
 242   // includes tokens outside of the range (off-by-one)
 243   // see: https://llvm.org/bugs/show_bug.cgi?id=9069
 244   CXToken* filteredTokens = (CXToken*)alloca(nTokens * sizeof(CXToken));
 245   unsigned nFilteredTokens = 0;
 246   jobjectArray jtokens = NULL;
 247 
 248   for (unsigned i = 0; i < nTokens; i++) {
 249     CXToken token = tokens[i];
 250     CXSourceLocation tokenLocation = clang_getTokenLocation(tu, token);
 251     if (!locationInRange(env, tokenLocation, *ptr)) {
 252       continue;
 253     }
 254     if (env->ExceptionCheck()) {
 255       goto out;
 256     }
 257 
 258     filteredTokens[nFilteredTokens++] = token;
 259   }
 260 
 261   jtokens = env->NewObjectArray(nFilteredTokens, clsjavaLangString, NULL);
 262 
 263   for (unsigned i = 0; i < nFilteredTokens; i++) {
 264     CXString tokenString = clang_getTokenSpelling(tu, filteredTokens[i]);
 265     jstring str = env->NewStringUTF(clang_getCString(tokenString));
 266     env->SetObjectArrayElement(jtokens, i, str);
 267     clang_disposeString(tokenString);
 268   }
 269 
 270  out:
 271   clang_disposeTokens(tu, tokens, nTokens);
 272 
 273   return jtokens;
 274 }
 275 
 276 /*************************************
 277  * Diagnostic/CXDiagnostic functions
 278  *************************************/
 279 JNIEXPORT jint JNICALL Java_jdk_internal_clang_Diagnostic_severity
 280   (JNIEnv *env, jobject obj, jlong diag) {
 281     return clang_getDiagnosticSeverity((CXDiagnostic) diag);
 282 }
 283 
 284 JNIEXPORT jobject JNICALL Java_jdk_internal_clang_Diagnostic_location
 285   (JNIEnv *env, jobject obj, jlong diag) {
 286     CXSourceLocation loc = clang_getDiagnosticLocation((CXDiagnostic) diag);
 287     if (clang_equalLocations(loc, clang_getNullLocation())) {
 288         return NULL;
 289     }
 290 
 291     jobject buffer = env->NewDirectByteBuffer(&loc, sizeof(CXSourceLocation));
 292     return env->NewObject(clsSourceLocation, ctorSourceLocation, buffer);
 293 }
 294 
 295 JNIEXPORT jstring JNICALL Java_jdk_internal_clang_Diagnostic_spelling
 296   (JNIEnv *env, jobject obj, jlong diag) {
 297     CXString str = clang_getDiagnosticSpelling((CXDiagnostic) diag);
 298     return CX2JString(env, str);
 299 }
 300 
 301 JNIEXPORT jstring JNICALL Java_jdk_internal_clang_Diagnostic_format
 302   (JNIEnv *env, jobject obj, jlong diag) {
 303     CXString str = clang_formatDiagnostic((CXDiagnostic) diag,
 304         clang_defaultDiagnosticDisplayOptions());
 305     return CX2JString(env, str);
 306 }
 307 
 308 JNIEXPORT void JNICALL Java_jdk_internal_clang_Diagnostic_dispose
 309   (JNIEnv *env, jobject obj, jlong diag) {
 310     clang_disposeDiagnostic((CXDiagnostic) diag);
 311 }
 312 
 313 /*************************************
 314  * Cursor/CXCursor functions
 315  *************************************/
 316 
 317 JNIEXPORT jboolean JNICALL Java_jdk_internal_clang_Cursor_isDeclaration
 318   (JNIEnv *env, jobject cursor) {
 319     CXCursor *ptr = (CXCursor*) J2P(env, cursor);
 320     return clang_isDeclaration(clang_getCursorKind(*ptr));
 321 }
 322 
 323 JNIEXPORT jboolean JNICALL Java_jdk_internal_clang_Cursor_isPreprocessing
 324   (JNIEnv *env, jobject cursor) {
 325     CXCursor *ptr = (CXCursor*) J2P(env, cursor);
 326     return clang_isPreprocessing(clang_getCursorKind(*ptr));
 327 }
 328 
 329 JNIEXPORT jboolean JNICALL Java_jdk_internal_clang_Cursor_isInvalid
 330   (JNIEnv *env, jobject cursor) {
 331     CXCursor *ptr = (CXCursor*) J2P(env, cursor);
 332     return clang_isInvalid(clang_getCursorKind(*ptr));
 333 }
 334 
 335 JNIEXPORT jboolean JNICALL Java_jdk_internal_clang_Cursor_isDefinition
 336   (JNIEnv *env, jobject cursor) {
 337     CXCursor *ptr = (CXCursor*) J2P(env, cursor);
 338     return clang_isCursorDefinition(*ptr);
 339 }
 340 
 341 JNIEXPORT jboolean JNICALL Java_jdk_internal_clang_Cursor_isAnonymousStruct
 342   (JNIEnv *env, jobject cursor) {
 343     CXCursor *ptr = (CXCursor*) J2P(env, cursor);
 344     return clang_Cursor_isAnonymous(*ptr);
 345 }
 346 
 347 JNIEXPORT jstring JNICALL Java_jdk_internal_clang_Cursor_spelling
 348   (JNIEnv *env, jobject cursor) {
 349     CXCursor *ptr = (CXCursor*) J2P(env, cursor);
 350     CXString spelling = clang_getCursorSpelling(*ptr);
 351     return CX2JString(env, spelling);
 352 }
 353 
 354 JNIEXPORT jstring JNICALL Java_jdk_internal_clang_Cursor_USR
 355   (JNIEnv *env, jobject cursor) {
 356     CXCursor *ptr = (CXCursor*) J2P(env, cursor);
 357     CXString usr = clang_getCursorUSR(*ptr);
 358     return CX2JString(env, usr);
 359 }
 360 
 361 JNIEXPORT jint JNICALL Java_jdk_internal_clang_Cursor_kind1
 362   (JNIEnv *env, jobject cursor) {
 363     CXCursor *ptr = (CXCursor*) J2P(env, cursor);
 364     return clang_getCursorKind(*ptr);
 365 }
 366 
 367 struct visitor_data {
 368     JavaVM *jvm;
 369     jobject visitor;
 370     jobject data;
 371 };
 372 
 373 enum CXChildVisitResult visitorFunc(CXCursor cursor,
 374                                     CXCursor parent,
 375                                     CXClientData data) {
 376     struct visitor_data *pCtx = (struct visitor_data*) data;
 377     // Just to be cautious in case callback from different thread
 378     // although this is likely not the case
 379     JNIEnv *env;
 380     if (JNI_OK != pCtx->jvm->AttachCurrentThread(reinterpret_cast<void**>(&env), NULL)) {
 381         printf("Failed to attach JVM\n");
 382         return CXChildVisit_Break;
 383     };
 384 
 385     jobject jC = env->NewDirectByteBuffer(&cursor, sizeof(CXCursor));
 386     jobject jP = env->NewDirectByteBuffer(&parent, sizeof(CXCursor));
 387     return (CXChildVisitResult) env->CallStaticIntMethod(clsCursor,
 388                                                          visitorID,
 389                                                          pCtx->visitor,
 390                                                          jC, jP,
 391                                                          pCtx->data);
 392 }
 393 
 394 JNIEXPORT jint JNICALL Java_jdk_internal_clang_Cursor_visitChildren
 395   (JNIEnv *env, jobject cursor, jobject visitor, jobject data) {
 396     CXCursor *ptr = (CXCursor*) J2P(env, cursor);
 397     struct visitor_data ctx;
 398     env->GetJavaVM(&(ctx.jvm));
 399     ctx.visitor = visitor;
 400     ctx.data = data;
 401     return clang_visitChildren(*ptr, visitorFunc, &ctx);
 402 }
 403 
 404 JNIEXPORT jboolean JNICALL Java_jdk_internal_clang_Cursor_equalCursor
 405   (JNIEnv *env, jobject cursor, jobject other) {
 406     CXCursor *ptr = (CXCursor*) J2P(env, cursor);
 407     CXCursor *ptrOther = (CXCursor*) J2P(env, other);
 408     return clang_equalCursors(*ptr, *ptrOther);
 409 }
 410 
 411 JNIEXPORT jobject JNICALL Java_jdk_internal_clang_Cursor_type
 412   (JNIEnv *env, jobject cursor) {
 413     CXCursor *ptr = (CXCursor*) J2P(env, cursor);
 414     CXType type = clang_getCursorType(*ptr);
 415     jobject buffer = env->NewDirectByteBuffer(&type, sizeof(CXType));
 416     return env->NewObject(clsType, ctorType, buffer);
 417 }
 418 
 419 JNIEXPORT jobject JNICALL Java_jdk_internal_clang_Cursor_getEnumDeclIntegerType
 420   (JNIEnv *env, jobject cursor) {
 421     CXCursor *ptr = (CXCursor*) J2P(env, cursor);
 422     CXType type = clang_getEnumDeclIntegerType(*ptr);
 423     jobject buffer = env->NewDirectByteBuffer(&type, sizeof(CXType));
 424     return env->NewObject(clsType, ctorType, buffer);
 425 }
 426 
 427 JNIEXPORT jobject JNICALL Java_jdk_internal_clang_Cursor_getDefinition
 428   (JNIEnv *env, jobject cursor) {
 429     CXCursor *ptr = (CXCursor*) J2P(env, cursor);
 430     CXCursor def = clang_getCursorDefinition(*ptr);
 431     jobject buffer = env->NewDirectByteBuffer(&def, sizeof(CXCursor));
 432     return env->NewObject(clsCursor, ctorCursor, buffer);
 433 }
 434 
 435 JNIEXPORT jobject JNICALL Java_jdk_internal_clang_Cursor_getSourceLocation
 436   (JNIEnv *env, jobject cursor) {
 437     CXCursor *ptr = (CXCursor*) J2P(env, cursor);
 438 
 439     // Some CXCursor has no valid location, such as the one from TranslationUnit
 440     CXSourceLocation loc = clang_getCursorLocation(*ptr);
 441     if (clang_equalLocations(loc, clang_getNullLocation())) {
 442         return NULL;
 443     }
 444 
 445     jobject buffer = env->NewDirectByteBuffer(&loc, sizeof(CXSourceLocation));
 446     return env->NewObject(clsSourceLocation, ctorSourceLocation, buffer);
 447 }
 448 
 449 JNIEXPORT jobject JNICALL Java_jdk_internal_clang_Cursor_getExtent
 450   (JNIEnv *env, jobject cursor) {
 451     CXCursor *ptr = (CXCursor*) J2P(env, cursor);
 452 
 453     CXSourceRange range = clang_getCursorExtent(*ptr);
 454     if (clang_Range_isNull(range)) {
 455         return NULL;
 456     }
 457 
 458     jobject buffer = env->NewDirectByteBuffer(&range, sizeof(CXSourceRange));
 459     return env->NewObject(clsSourceRange, ctorSourceRange, buffer);
 460 }
 461 
 462 JNIEXPORT jobject JNICALL Java_jdk_internal_clang_Cursor_getArgument
 463   (JNIEnv *env, jobject _self, jint idx) {
 464     CXCursor *ptr = (CXCursor*) J2P(env, _self);
 465     CXCursor result = clang_Cursor_getArgument(*ptr, idx);
 466     jobject buffer = env->NewDirectByteBuffer(&result, sizeof(CXCursor));
 467     return env->NewObject(clsCursor, ctorCursor, buffer);
 468 }
 469 
 470 JNIEXPORT jint JNICALL Java_jdk_internal_clang_Cursor_numberOfArgs
 471   (JNIEnv *env, jobject _self) {
 472     CXCursor *ptr = (CXCursor*) J2P(env, _self);
 473     return clang_Cursor_getNumArguments(*ptr);
 474 }
 475 
 476 JNIEXPORT jlong JNICALL Java_jdk_internal_clang_Cursor_getEnumConstantValue
 477   (JNIEnv *env, jobject _self) {
 478     CXCursor *ptr = (CXCursor*) J2P(env, _self);
 479     return clang_getEnumConstantDeclValue(*ptr);
 480 }
 481 
 482 JNIEXPORT jlong JNICALL Java_jdk_internal_clang_Cursor_getEnumConstantUnsignedValue
 483   (JNIEnv *env, jobject _self) {
 484     CXCursor *ptr = (CXCursor*) J2P(env, _self);
 485     return clang_getEnumConstantDeclUnsignedValue(*ptr);
 486 }
 487 
 488 JNIEXPORT bool JNICALL Java_jdk_internal_clang_Cursor_isBitField
 489   (JNIEnv *env, jobject _self) {
 490     CXCursor *ptr = (CXCursor*) J2P(env, _self);
 491     return clang_Cursor_isBitField(*ptr);
 492 }
 493 
 494 JNIEXPORT jint JNICALL Java_jdk_internal_clang_Cursor_getBitFieldWidth
 495   (JNIEnv *env, jobject _self) {
 496     CXCursor *ptr = (CXCursor*) J2P(env, _self);
 497     return clang_getFieldDeclBitWidth(*ptr);
 498 }
 499 
 500 JNIEXPORT jlong JNICALL Java_jdk_internal_clang_Cursor_getTranslationUnit0
 501   (JNIEnv *env, jobject _self) {
 502     CXCursor *ptr = (CXCursor*) J2P(env, _self);
 503     return (jlong) clang_Cursor_getTranslationUnit(*ptr);
 504 }
 505 
 506 JNIEXPORT jstring JNICALL Java_jdk_internal_clang_Cursor_getMangling
 507   (JNIEnv *env, jobject _self) {
 508     CXCursor *ptr = (CXCursor*) J2P(env, _self);
 509     CXString mangled = clang_Cursor_getMangling(*ptr);
 510     return CX2JString(env, mangled);
 511 }
 512 
 513 /*************************************
 514  * Type <-> CXType related functions
 515  *************************************/
 516 
 517 JNIEXPORT jboolean JNICALL Java_jdk_internal_clang_Type_isVariadic
 518   (JNIEnv *env, jobject type) {
 519     CXType *ptr = (CXType*) J2P(env, type);
 520     return clang_isFunctionTypeVariadic(*ptr);
 521 }
 522 
 523 JNIEXPORT jobject JNICALL Java_jdk_internal_clang_Type_resultType
 524   (JNIEnv *env, jobject type) {
 525     CXType *ptr = (CXType*) J2P(env, type);
 526     CXType result = clang_getResultType(*ptr);
 527     jobject buffer = env->NewDirectByteBuffer(&result, sizeof(CXType));
 528     return env->NewObject(clsType, ctorType, buffer);
 529 }
 530 
 531 JNIEXPORT jint JNICALL Java_jdk_internal_clang_Type_numberOfArgs
 532   (JNIEnv *env, jobject type) {
 533     CXType *ptr = (CXType*) J2P(env, type);
 534     return clang_getNumArgTypes(*ptr);
 535 }
 536 
 537 JNIEXPORT jobject JNICALL Java_jdk_internal_clang_Type_argType
 538   (JNIEnv *env, jobject type, jint idx) {
 539     CXType *ptr = (CXType*) J2P(env, type);
 540     CXType result = clang_getArgType(*ptr, idx);
 541     jobject buffer = env->NewDirectByteBuffer(&result, sizeof(CXType));
 542     return env->NewObject(clsType, ctorType, buffer);
 543 }
 544 
 545 JNIEXPORT jint JNICALL Java_jdk_internal_clang_Type_getCallingConvention1
 546   (JNIEnv *env, jobject type) {
 547     CXType *ptr = (CXType*) J2P(env, type);
 548     return clang_getFunctionTypeCallingConv(*ptr);
 549 }
 550 
 551 JNIEXPORT jobject JNICALL Java_jdk_internal_clang_Type_getPointeeType
 552   (JNIEnv *env, jobject type) {
 553     CXType *ptr = (CXType*) J2P(env, type);
 554     CXType result = clang_getPointeeType(*ptr);
 555     jobject buffer = env->NewDirectByteBuffer(&result, sizeof(CXType));
 556     return env->NewObject(clsType, ctorType, buffer);
 557 }
 558 
 559 JNIEXPORT jobject JNICALL Java_jdk_internal_clang_Type_getElementType
 560   (JNIEnv *env, jobject type) {
 561     CXType *ptr = (CXType*) J2P(env, type);
 562     CXType result = clang_getElementType(*ptr);
 563     jobject buffer = env->NewDirectByteBuffer(&result, sizeof(CXType));
 564     return env->NewObject(clsType, ctorType, buffer);
 565 }
 566 
 567 JNIEXPORT jlong JNICALL Java_jdk_internal_clang_Type_getNumberOfElements
 568   (JNIEnv *env, jobject type) {
 569     CXType *ptr = (CXType*) J2P(env, type);
 570     return clang_getNumElements(*ptr);
 571 }
 572 
 573 JNIEXPORT jobject JNICALL Java_jdk_internal_clang_Type_canonicalType
 574   (JNIEnv *env, jobject type) {
 575     CXType *ptr = (CXType*) J2P(env, type);
 576     CXType result = clang_getCanonicalType(*ptr);
 577     jobject buffer = env->NewDirectByteBuffer(&result, sizeof(CXType));
 578     return env->NewObject(clsType, ctorType, buffer);
 579 }
 580 
 581 JNIEXPORT jstring JNICALL Java_jdk_internal_clang_Type_spelling
 582   (JNIEnv *env, jobject type) {
 583     CXType *ptr = (CXType*) J2P(env, type);
 584     CXString spelling = clang_getTypeSpelling(*ptr);
 585     return CX2JString(env, spelling);
 586 }
 587 
 588 JNIEXPORT jint JNICALL Java_jdk_internal_clang_Type_kind1
 589   (JNIEnv *env, jobject type) {
 590     CXType *ptr = (CXType*) J2P(env, type);
 591     return ptr->kind;
 592 }
 593 
 594 JNIEXPORT jlong JNICALL Java_jdk_internal_clang_Type_size
 595   (JNIEnv *env, jobject type) {
 596     CXType *ptr = (CXType*) J2P(env, type);
 597     return clang_Type_getSizeOf(*ptr);
 598 }
 599 
 600 JNIEXPORT jlong JNICALL Java_jdk_internal_clang_Type_getOffsetOf
 601   (JNIEnv *env, jobject type, jstring field_name) {
 602     CXType *ptr = (CXType*) J2P(env, type);
 603     const char *name = env->GetStringUTFChars(field_name, NULL);
 604     long long offset = clang_Type_getOffsetOf(*ptr, name);
 605     env->ReleaseStringUTFChars(field_name, name);
 606     return offset;
 607 }
 608 
 609 JNIEXPORT jobject JNICALL Java_jdk_internal_clang_Type_getDeclarationCursor
 610   (JNIEnv *env, jobject type) {
 611     CXType *ptr = (CXType*) J2P(env, type);
 612     CXCursor result = clang_getTypeDeclaration(*ptr);
 613     jobject buffer = env->NewDirectByteBuffer(&result, sizeof(CXCursor));
 614     return env->NewObject(clsCursor, ctorCursor, buffer);
 615 }
 616 
 617 /*************************************
 618  * Location related functions
 619  *************************************/
 620 
 621 JNIEXPORT jobject JNICALL Java_jdk_internal_clang_SourceLocation_getFileLocation
 622   (JNIEnv *env, jobject loc) {
 623     CXSourceLocation *ptr = (CXSourceLocation*) J2P(env, loc);
 624     struct LocationFactory f;
 625     return f.get(env, ptr, clang_getFileLocation);
 626 }
 627 
 628 JNIEXPORT jobject JNICALL Java_jdk_internal_clang_SourceLocation_getExpansionLocation
 629   (JNIEnv *env, jobject loc) {
 630     CXSourceLocation *ptr = (CXSourceLocation*) J2P(env, loc);
 631     struct LocationFactory f;
 632     return f.get(env, ptr, clang_getExpansionLocation);
 633 }
 634 
 635 JNIEXPORT jobject JNICALL Java_jdk_internal_clang_SourceLocation_getSpellingLocation
 636   (JNIEnv *env, jobject loc) {
 637     CXSourceLocation *ptr = (CXSourceLocation*) J2P(env, loc);
 638     struct LocationFactory f;
 639     return f.get(env, ptr, clang_getSpellingLocation);
 640 }
 641 
 642 JNIEXPORT bool JNICALL Java_jdk_internal_clang_SourceLocation_isInSystemHeader
 643   (JNIEnv *env, jobject loc) {
 644     CXSourceLocation *ptr = (CXSourceLocation*) J2P(env, loc);
 645     return clang_Location_isInSystemHeader(*ptr);
 646 }
 647 
 648 JNIEXPORT bool JNICALL Java_jdk_internal_clang_SourceLocation_isFromMainFile
 649   (JNIEnv *env, jobject loc) {
 650     CXSourceLocation *ptr = (CXSourceLocation*) J2P(env, loc);
 651     return clang_Location_isFromMainFile(*ptr);
 652 }
 653 
 654 JNIEXPORT jobject JNICALL Java_jdk_internal_clang_SourceRange_getBegin
 655   (JNIEnv *env, jobject range) {
 656     CXSourceRange *ptr = (CXSourceRange*) J2P(env, range);
 657 
 658     // Some CXCursor has no valid location, such as the one from TranslationUnit
 659     CXSourceLocation loc = clang_getRangeStart(*ptr);
 660     if (clang_equalLocations(loc, clang_getNullLocation())) {
 661         return NULL;
 662     }
 663 
 664     jobject buffer = env->NewDirectByteBuffer(&loc, sizeof(CXSourceLocation));
 665     return env->NewObject(clsSourceLocation, ctorSourceLocation, buffer);
 666 }
 667 
 668 JNIEXPORT jobject JNICALL Java_jdk_internal_clang_SourceRange_getEnd
 669   (JNIEnv *env, jobject range) {
 670     CXSourceRange *ptr = (CXSourceRange*) J2P(env, range);
 671 
 672     // Some CXCursor has no valid location, such as the one from TranslationUnit
 673     CXSourceLocation loc = clang_getRangeEnd(*ptr);
 674     if (clang_equalLocations(loc, clang_getNullLocation())) {
 675         return NULL;
 676     }
 677 
 678     jobject buffer = env->NewDirectByteBuffer(&loc, sizeof(CXSourceLocation));
 679     return env->NewObject(clsSourceLocation, ctorSourceLocation, buffer);
 680 }
 681 
 682 #ifdef __cplusplus
 683 }
 684 #endif