1 /*
   2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 package jdk.internal.clang;
  25 
  26 import java.nio.ByteBuffer;
  27 import java.util.ArrayList;
  28 import java.util.List;
  29 import java.util.stream.Stream;
  30 
  31 public class Cursor extends StructType {
  32     public static enum VisitResult {
  33         Break,
  34         Continue,
  35         Recurse;
  36     }
  37 
  38     @FunctionalInterface
  39     public static interface Visitor {
  40         /**
  41          * Callback function for visitChildren
  42          * @param parent
  43          * @param current
  44          * @param data
  45          * @return 0 - break, 1 - continue, 2 - recurse
  46          */
  47         VisitResult visit(Cursor current, Cursor parent, Object data);
  48     }
  49 
  50     private static int visit(Visitor v, ByteBuffer c, ByteBuffer p, Object data) {
  51         return v.visit(new Cursor(c), new Cursor(p), data).ordinal();
  52     }
  53 
  54     Cursor(ByteBuffer buf) {
  55         super(buf);
  56     }
  57 
  58     public native boolean isDeclaration();
  59     public native boolean isPreprocessing();
  60     public native boolean isInvalid();
  61     public native boolean isDefinition();
  62     public native boolean isAnonymousStruct();
  63 
  64     public boolean isAnonymousEnum() {
  65         // libclang::clang_Cursor_isAnonymous only applies to struct, not enum
  66         if (type().kind() == TypeKind.Enum) {
  67             return spelling().isEmpty() &&
  68                     type().spelling().startsWith("enum (anonymous");
  69         }
  70         return false;
  71     }
  72 
  73     public boolean isAnonymous() {
  74         return isAnonymousStruct() || isAnonymousEnum();
  75     }
  76 
  77     public native String spelling();
  78     public native String USR();
  79 
  80     public native int kind1();
  81 
  82     public native int visitChildren(Visitor visitor, Object data);
  83 
  84     public native boolean equalCursor(Cursor other);
  85 
  86     public native Type type();
  87     public native Type getEnumDeclIntegerType();
  88 
  89     public native Cursor getDefinition();
  90 
  91     public native SourceLocation getSourceLocation();
  92     public native SourceRange getExtent();
  93 
  94     public native int numberOfArgs();
  95     public native Cursor getArgument(int idx);
  96 
  97     // C long long, 64-bit
  98     public native long getEnumConstantValue();
  99     // C unsigned long long, 64-bit
 100     public native long getEnumConstantUnsignedValue();
 101 
 102     public native boolean isBitField();
 103     public native int getBitFieldWidth();
 104 
 105     native long getTranslationUnit0();
 106     public final TranslationUnit getTranslationUnit() {
 107         return new TranslationUnit(getTranslationUnit0());
 108     }
 109 
 110     public native String getMangling();
 111 
 112     public CursorKind kind() {
 113         int v = kind1();
 114         // FIXME: assert(v == getData().getInt(0));
 115         return CursorKind.valueOf(v);
 116     }
 117 
 118     public boolean equals(Cursor other) {
 119         return getData().equals(other.getData());
 120     }
 121 
 122     public Stream<Cursor> children() {
 123         ArrayList<Cursor> ar = new ArrayList<>();
 124         visitChildren((c, p, d) -> {
 125             @SuppressWarnings("unchecked")
 126             List<Cursor> a = (List<Cursor>) d;
 127             a.add(c);
 128             return VisitResult.Continue;
 129         }, ar);
 130         return ar.stream();
 131     }
 132 
 133     public Stream<Cursor> stream() {
 134         return children().flatMap(c -> Stream.concat(Stream.of(c), c.children()));
 135     }
 136 }