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     public native boolean isMacroFunctionLike();
  64 
  65     public boolean isAnonymousEnum() {
  66         // libclang::clang_Cursor_isAnonymous only applies to struct, not enum
  67         return (type().kind() == TypeKind.Enum && spelling().isEmpty());
  68     }
  69 
  70     public boolean isAnonymous() {
  71         return isAnonymousStruct() || isAnonymousEnum();
  72     }
  73 
  74     public native String spelling();
  75     public native String USR();
  76 
  77     public native int kind1();
  78 
  79     public native int visitChildren(Visitor visitor, Object data);
  80 
  81     public native boolean equalCursor(Cursor other);
  82 
  83     public native Type type();
  84     public native Type getEnumDeclIntegerType();
  85 
  86     public native Cursor getDefinition();
  87 
  88     public native SourceLocation getSourceLocation();
  89     public native SourceRange getExtent();
  90 
  91     public native int numberOfArgs();
  92     public native Cursor getArgument(int idx);
  93 
  94     // C long long, 64-bit
  95     public native long getEnumConstantValue();
  96     // C unsigned long long, 64-bit
  97     public native long getEnumConstantUnsignedValue();
  98 
  99     public native boolean isBitField();
 100     public native int getBitFieldWidth();
 101 
 102     native long getTranslationUnit0();
 103     public final TranslationUnit getTranslationUnit() {
 104         return new TranslationUnit(getTranslationUnit0());
 105     }
 106 
 107     public native String getMangling();
 108 
 109     public CursorKind kind() {
 110         int v = kind1();
 111         // FIXME: assert(v == getData().getInt(0));
 112         return CursorKind.valueOf(v);
 113     }
 114 
 115     public boolean equals(Cursor other) {
 116         return getData().equals(other.getData());
 117     }
 118 
 119     public Stream<Cursor> children() {
 120         ArrayList<Cursor> ar = new ArrayList<>();
 121         visitChildren((c, p, d) -> {
 122             @SuppressWarnings("unchecked")
 123             List<Cursor> a = (List<Cursor>) d;
 124             a.add(c);
 125             return VisitResult.Continue;
 126         }, ar);
 127         return ar.stream();
 128     }
 129 
 130     public Stream<Cursor> stream() {
 131         return children().flatMap(c -> Stream.concat(Stream.of(c), c.children()));
 132     }
 133 }