All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.tools.oldlets.javadoc.main.SymbolKind Maven / Gradle / Ivy

There is a newer version: 1.0
Show newest version
/**
 * Codesnippet Javadoc Doclet
 * Copyright (C) 2015-2018 Jaroslav Tulach - [email protected]
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3.0 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. Look for COPYING file in the top folder.
 * If not, see http://opensource.org/licenses/GPL-3.0.
 */
package com.sun.tools.oldlets.javadoc.main;

import com.sun.tools.javac.code.Scope;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.PackageSymbol;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.jvm.ClassReader;
import com.sun.tools.javac.util.Convert;
import com.sun.tools.javac.util.JavacMessages;
import com.sun.tools.javac.util.Name;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;

public enum SymbolKind {
    NIL(0),
    PCK(1),
    TYP(2),
    VAR(4),
    MTH(8),
    POLY(16),
    MDL(32),
    ERR(63);

    final int value;

    private SymbolKind(int v) {
        this.value = v;
    }

    private static final Field kind;
    static {
        try {
            kind = Symbol.class.getField("kind");
        } catch (Exception ex) {
            throw new IllegalStateException(ex);
        }
    }

    boolean is(Symbol s) {
        int ordinal = kindValue(s);
        return (this.value & ordinal) != 0;
    }

    private static int kindValue(Symbol s) throws IllegalStateException {
        Object value;
        try {
            value = kind.get(s);
        } catch (Exception ex) {
            throw new IllegalStateException(ex);
        }
        int ordinal;
        if (value instanceof Enum) {
            final int at = ((Enum) value).ordinal();
            if (at == 0) {
                ordinal = 0;
            } else {
                ordinal = 1 << (at - 1);
            }
        } else {
            ordinal = (Integer) value;
        }
        return ordinal;
    }

    boolean same(Symbol s) {
        int ordinal = kindValue(s);
        return value == ordinal;
    }

    private static final Object RECURSIVE;
    private static final Object NON_RECURSIVE;
    private static final Method GET_SYMBOLS;
    private static final Field ELEMS;
    private static final Field SYM;
    private static final Field SIBLING;
    private static final Method NEXT;
    static {
        Object rec, nonRec, getSym;
        try {
            Class LookupKind = Class.forName("com.sun.tools.javac.code.Scope$LookupKind").asSubclass(Enum.class);
            rec = findKind(LookupKind, "RECURSIVE");
            nonRec = findKind(LookupKind, "NON_RECURSIVE");
            getSym = Scope.class.getMethod("getSymbols", LookupKind);
        } catch (ClassNotFoundException ex) {
            rec = null;
            nonRec = null;
            getSym = null;
        } catch (Exception ex) {
            throw new IllegalStateException(ex);
        }
        RECURSIVE = rec;
        NON_RECURSIVE = nonRec;
        GET_SYMBOLS = (Method) getSym;

        Field elems;
        Field sym;
        Field sibling;
        Method next;
        try {
            elems = Scope.class.getField("elems");
            Class Entry = Class.forName("com.sun.tools.javac.code.Scope$Entry");
            sym = Entry.getField("sym");
            sibling = Entry.getField("sibling");
            next = Entry.getMethod("next");
        } catch (Exception ex) {
            elems = null;
            sym = null;
            sibling = null;
            next = null;
        }

        ELEMS = elems;
        SYM = sym;
        SIBLING = sibling;
        NEXT = next;
    }

    @SuppressWarnings("unchecked")
    private static  E findKind(Class enumType, String name) {
        Enum value = Enum.valueOf(enumType, name);
        return enumType.cast(value);
    }

    static Iterable getSymbolsByName(Scope members, boolean recursive, Name name) {
        List arr = new ArrayList<>();
        for (Symbol s : getSymbols(members, recursive)) {
            if (s.name.equals(name)) {
                arr.add(s);
            }
        }
        return arr;
    }

    @SuppressWarnings("unchecked")
    static Iterable getSymbols(Scope members, boolean recursive) {
        try {
            if (GET_SYMBOLS != null) {
                return (Iterable) GET_SYMBOLS.invoke(members, recursive ? RECURSIVE : NON_RECURSIVE);
            } else {
                List arr = new ArrayList<>();
                Object e = ELEMS.get(members);
                while (e != null) {
                    arr.add(Symbol.class.cast(SYM.get(e)));
                    e = recursive ? NEXT.invoke(e) : SIBLING.get(e);
                }
                return arr;
            }
        } catch (Exception ex) {
            throw new IllegalStateException(ex);
        }
    }

    private static final Method ENTER_CLASS;
    private static final Method SYMS_ENTER_CLASS;
    private static final Field SYMS_JAVA_BASE;
    static {
        Method e;
        Method se;
        Field sjb;
        try {
            e = ClassReader.class.getMethod("enterClass", Name.class);
            se = null;
            sjb = null;
        } catch (NoSuchMethodException ex) {
            e = null;
            try {
                Class ModuleSymbol = Class.forName("com.sun.tools.javac.code.Symbol$ModuleSymbol");
                se = Symtab.class.getMethod("enterClass", ModuleSymbol, Name.class);
                sjb = Symtab.class.getField("java_base");
            } catch (ClassNotFoundException | NoSuchMethodException | NoSuchFieldException ex2) {
                throw new IllegalStateException(ex2);
            }
        }
        ENTER_CLASS = e;
        SYMS_ENTER_CLASS = se;
        SYMS_JAVA_BASE = sjb;
    }
    static Symbol enterClass(DocEnv env, Symtab syms, Name n) {
        try {
            if (ENTER_CLASS != null) {
                Object reader = READER.get(env);
                return (Symbol) ENTER_CLASS.invoke(reader, n);
            } else {
                Object base = SYMS_JAVA_BASE.get(syms);
                return (Symbol) SYMS_ENTER_CLASS.invoke(syms, base, n);
            }
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
            throw new IllegalStateException(ex);
        }
    }
    private static final Field READER;
    private static final Method ENTER_PACKAGE;
    static {
        Method ep;
        Field rf;
        try {
            ep = ClassReader.class.getMethod("enterPackage", Name.class);
            rf = DocEnv.class.getField("reader");
        } catch (ReflectiveOperationException ex) {
            ep = null;
            rf = null;
        }
        ENTER_PACKAGE = ep;
        READER = rf;
    }
    static PackageSymbol enterPackage(DocEnv env, Name n) {
        try {
            Object reader = READER.get(env);
            return (PackageSymbol) ENTER_PACKAGE.invoke(reader, n);
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
            throw new IllegalStateException(ex);
        }
    }


    static Symbol.ClassSymbol loadClass(DocEnv env, Symtab syms, Name n) {
        return (Symbol.ClassSymbol) enterClass(env, syms, n);
    }

    private static final Field PACKAGES;
    private static final Method INFER_MODULE;
    private static final Method GET_PACKAGE;
    private static final Method GET_CLASS;
    private static final Field CLASSES;
    static {
        Field f;
        Method i, p, c;
        try {
            f = Symtab.class.getField("packages");
            i = null;
            p = null;
            c = null;
        } catch (NoSuchFieldException ex) {
            try {
                i = Symtab.class.getMethod("inferModule", Name.class);
                p = Symtab.class.getMethod("getPackage", i.getReturnType(), Name.class);
                c = Symtab.class.getMethod("getClass", i.getReturnType(), Name.class);
                f = null;
            } catch (NoSuchMethodException ex1) {
                throw new IllegalStateException(ex1);
            }
        }
        PACKAGES = f;
        INFER_MODULE = i;
        GET_PACKAGE = p;
        GET_CLASS = c;
    }
    static {
        Field f;
        try {
            f = Symtab.class.getField("classes");
        } catch (NoSuchFieldException ex) {
            f = null;
        }
        CLASSES = f;
    }
    static Symbol.PackageSymbol lookupPackage(Symtab syms, Name nameImpl) {
        try {
            PackageSymbol p;
            if (PACKAGES != null) {
                Map packages = (Map) PACKAGES.get(syms);
                p = (PackageSymbol) packages.get(nameImpl);
            } else {
                Object mod = INFER_MODULE.invoke(syms, nameImpl);
                p = mod != null ? (PackageSymbol) GET_PACKAGE.invoke(syms, mod, nameImpl) : null;
            }
            return p;
        } catch (ReflectiveOperationException ex) {
            throw new IllegalStateException(ex);
        }
    }

    static Symbol.ClassSymbol getClass(Symtab syms, Name nameImpl) {
        try {
            if (CLASSES != null) {
                Map packages = (Map) CLASSES.get(syms);
                return (ClassSymbol) packages.get(nameImpl);
            } else {
                Name packageImpl = Convert.packagePart(nameImpl);
                Object mod = INFER_MODULE.invoke(syms, packageImpl);
                return mod != null ? (Symbol.ClassSymbol) GET_CLASS.invoke(syms, mod, nameImpl) : null;
            }
        } catch (ReflectiveOperationException ex) {
            throw new IllegalStateException(ex);
        }
    }

    static void addResourceBundle(JavacMessages messages, String bundle) {
        for (Method m : JavacMessages.class.getMethods()) {
            if (m.getName().equals("add") && m.getParameterCount() == 1 && m.getParameterTypes()[0] != String.class) {
                try {
                    InvocationHandler handler = (___, __, args) -> {
                        Locale locale = (Locale) args[0];
                        return ResourceBundle.getBundle("com.sun.tools.oldlets.javadoc.main.javadoc", locale);
                    };
                    Object bundleProvider = Proxy.newProxyInstance(SymbolKind.class.getClassLoader(), m.getParameterTypes(), handler);
                    m.invoke(messages, bundleProvider);
                    return;
                } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
                    throw new IllegalStateException(ex);
                }
            }
        }
        messages.add(bundle);
    }

    public static  T invokeOrNull(Object thiz, String name, Object... args) {
        return invokeOrNull(thiz, thiz.getClass(), name, args);
    }

    @SuppressWarnings("unchecked")
    static  T invokeOrNull(Object thiz, Class type, String name, Object... args) {
        for (Method m : type.getMethods()) {
            if (name.equals(m.getName()) && m.getParameterCount() == args.length) {
                try {
                    return (T) m.invoke(thiz, args);
                } catch (ReflectiveOperationException ex) {
                    throw new IllegalStateException("Cannot call " + m + " with " + Arrays.toString(args), ex);
                }
            }
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    static  T invokeStaticOrNull(Class type, String name, Object... args) {
        for (Method m : type.getMethods()) {
            if (name.equals(m.getName())) {
                try {
                    return (T) m.invoke(null, args);
                } catch (ReflectiveOperationException ex) {
                    throw new IllegalStateException(ex);
                }
            }
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    static  T getStaticOrElse(Class type, String fieldName, T defaultValue) {
        try {
            return (T) type.getField(fieldName).get(null);
        } catch (ReflectiveOperationException ex) {
            return defaultValue;
        }
    }

    @SuppressWarnings("unchecked")
    static  T getOrElse(Class type, Object thiz, String fieldName, T defaultValue) {
        if (type == null) {
            type = thiz.getClass();
        }
        try {
            final Field f = type.getDeclaredField(fieldName);
            return (T) f.get(thiz);
        } catch (ReflectiveOperationException ex) {
            return defaultValue;
        }
    }

    static void setOrNothing(Object thiz, String fieldName, Object value) {
        try {
            thiz.getClass().getField(fieldName).set(thiz, value);
        } catch (ReflectiveOperationException ex) {
            // nothing
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy