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 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 JNIEXPORT jboolean JNICALL Java_jdk_internal_clang_Cursor_equalCursor
 514   (JNIEnv *env, jobject cursor, jobject other) {
 515     CXCursor *ptr = (CXCursor*) J2P(env, cursor);
 516     CXCursor *ptrOther = (CXCursor*) J2P(env, other);
 517     return clang_equalCursors(*ptr, *ptrOther);
 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 jboolean JNICALL Java_jdk_internal_clang_Type_equalType
 617   (JNIEnv *env, jobject type, jobject other) {
 618     CXType *ptr = (CXType*) J2P(env, type);
 619     CXType *ptrOther = (CXType*) J2P(env, other);
 620     return clang_equalTypes(*ptr, *ptrOther);
 621 }
 622 
 623 JNIEXPORT jobject JNICALL Java_jdk_internal_clang_Type_getDeclarationCursor
 624   (JNIEnv *env, jobject type) {
 625     CXType *ptr = (CXType*) J2P(env, type);
 626     CXCursor result = clang_getTypeDeclaration(*ptr);
 627     jobject buffer = env->NewDirectByteBuffer(&result, sizeof(CXCursor));
 628     return env->NewObject(clsCursor, ctorCursor, buffer);
 629 }
 630 
 631 /*************************************
 632  * Location related functions
 633  *************************************/
 634 
 635 JNIEXPORT jobject JNICALL Java_jdk_internal_clang_SourceLocation_getFileLocation
 636   (JNIEnv *env, jobject loc) {
 637     CXSourceLocation *ptr = (CXSourceLocation*) J2P(env, loc);
 638     struct LocationFactory f;
 639     return f.get(env, ptr, clang_getFileLocation);
 640 }
 641 
 642 JNIEXPORT jobject JNICALL Java_jdk_internal_clang_SourceLocation_getExpansionLocation
 643   (JNIEnv *env, jobject loc) {
 644     CXSourceLocation *ptr = (CXSourceLocation*) J2P(env, loc);
 645     struct LocationFactory f;
 646     return f.get(env, ptr, clang_getExpansionLocation);
 647 }
 648 
 649 JNIEXPORT jobject JNICALL Java_jdk_internal_clang_SourceLocation_getSpellingLocation
 650   (JNIEnv *env, jobject loc) {
 651     CXSourceLocation *ptr = (CXSourceLocation*) J2P(env, loc);
 652     struct LocationFactory f;
 653     return f.get(env, ptr, clang_getSpellingLocation);
 654 }
 655 
 656 JNIEXPORT bool JNICALL Java_jdk_internal_clang_SourceLocation_isInSystemHeader
 657   (JNIEnv *env, jobject loc) {
 658     CXSourceLocation *ptr = (CXSourceLocation*) J2P(env, loc);
 659     return clang_Location_isInSystemHeader(*ptr);
 660 }
 661 
 662 JNIEXPORT bool JNICALL Java_jdk_internal_clang_SourceLocation_isFromMainFile
 663   (JNIEnv *env, jobject loc) {
 664     CXSourceLocation *ptr = (CXSourceLocation*) J2P(env, loc);
 665     return clang_Location_isFromMainFile(*ptr);
 666 }
 667 
 668 JNIEXPORT jobject JNICALL Java_jdk_internal_clang_SourceRange_getBegin
 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_getRangeStart(*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 JNIEXPORT jobject JNICALL Java_jdk_internal_clang_SourceRange_getEnd
 683   (JNIEnv *env, jobject range) {
 684     CXSourceRange *ptr = (CXSourceRange*) J2P(env, range);
 685 
 686     // Some CXCursor has no valid location, such as the one from TranslationUnit
 687     CXSourceLocation loc = clang_getRangeEnd(*ptr);
 688     if (clang_equalLocations(loc, clang_getNullLocation())) {
 689         return NULL;
 690     }
 691 
 692     jobject buffer = env->NewDirectByteBuffer(&loc, sizeof(CXSourceLocation));
 693     return env->NewObject(clsSourceLocation, ctorSourceLocation, buffer);
 694 }
 695 
 696 #ifdef __cplusplus
 697 }
 698 #endif