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