Search in sources :

Example 1 with Function

use of com.laytonsmith.core.functions.Function in project CommandHelper by EngineHub.

the class Script method eval.

/**
 * Given the parse tree and environment, executes the tree.
 *
 * @param c
 * @param env
 * @return
 * @throws CancelCommandException
 */
public Construct eval(ParseTree c, final Environment env) throws CancelCommandException {
    if (env.getEnv(GlobalEnv.class).IsInterrupted()) {
        // unconditionally.
        throw new CancelCommandException("", Target.UNKNOWN);
    }
    final Construct m = c.getData();
    CurrentEnv = env;
    if (m.getCType() != ConstructType.FUNCTION) {
        if (m.getCType() == ConstructType.VARIABLE) {
            return new CString(m.val(), m.getTarget());
        } else {
            return m;
        }
    }
    StackTraceManager stManager = env.getEnv(GlobalEnv.class).GetStackTraceManager();
    boolean addedRootStackElement = false;
    try {
        // If it's an unknown target, this is not user generated code, and we want to skip adding the element here.
        if (stManager.isStackEmpty() && !m.getTarget().equals(Target.UNKNOWN)) {
            stManager.addStackTraceElement(new ConfigRuntimeException.StackTraceElement("<<main code>>", m.getTarget()));
            addedRootStackElement = true;
        }
        stManager.setCurrentTarget(c.getTarget());
        env.getEnv(GlobalEnv.class).SetScript(this);
        if (m.val().charAt(0) == '_' && m.val().charAt(1) != '_') {
            // Not really a function, so we can't put it in Function.
            Procedure p = getProc(m.val());
            if (p == null) {
                throw new CREInvalidProcedureException("Unknown procedure \"" + m.val() + "\"", m.getTarget());
            }
            Environment newEnv = env;
            try {
                newEnv = env.clone();
            } catch (CloneNotSupportedException e) {
            }
            ProfilePoint pp = env.getEnv(GlobalEnv.class).GetProfiler().start(m.val() + " execution", LogLevel.INFO);
            Construct ret;
            try {
                ret = p.cexecute(c.getChildren(), newEnv, m.getTarget());
            } finally {
                pp.stop();
            }
            return ret;
        }
        final Function f;
        try {
            f = (Function) FunctionList.getFunction(m);
        } catch (ConfigCompileException e) {
            // Turn it into a config runtime exception. This shouldn't ever happen though.
            throw ConfigRuntimeException.CreateUncatchableException("Unable to find function " + m.val(), m.getTarget());
        }
        ArrayList<Construct> args = new ArrayList<>();
        try {
            if (f.isRestricted() && !Static.hasCHPermission(f.getName(), env)) {
                throw new CREInsufficientPermissionException("You do not have permission to use the " + f.getName() + " function.", m.getTarget());
            }
            if (f.useSpecialExec()) {
                ProfilePoint p = null;
                if (f.shouldProfile() && env.getEnv(GlobalEnv.class).GetProfiler() != null && env.getEnv(GlobalEnv.class).GetProfiler().isLoggable(f.profileAt())) {
                    p = env.getEnv(GlobalEnv.class).GetProfiler().start(f.profileMessageS(c.getChildren()), f.profileAt());
                }
                Construct ret;
                try {
                    ret = f.execs(m.getTarget(), env, this, c.getChildren().toArray(new ParseTree[] {}));
                } finally {
                    if (p != null) {
                        p.stop();
                    }
                }
                return ret;
            }
            for (ParseTree c2 : c.getChildren()) {
                args.add(eval(c2, env));
            }
            Object[] a = args.toArray();
            Construct[] ca = new Construct[a.length];
            for (int i = 0; i < a.length; i++) {
                ca[i] = (Construct) a[i];
                // CArray, CBoolean, CDouble, CInt, CNull, CString, CVoid, CEntry, CLabel (only to sconcat).
                if (!(ca[i] instanceof CArray || ca[i] instanceof CBoolean || ca[i] instanceof CDouble || ca[i] instanceof CInt || ca[i] instanceof CNull || ca[i] instanceof CString || ca[i] instanceof CVoid || ca[i] instanceof IVariable || ca[i] instanceof CEntry || ca[i] instanceof CLabel) && (!f.getName().equals("__autoconcat__") && (ca[i] instanceof CLabel))) {
                    throw new CRECastException("Invalid Construct (" + ca[i].getClass() + ") being passed as an argument to a function (" + f.getName() + ")", m.getTarget());
                }
                while (f.preResolveVariables() && ca[i] instanceof IVariable) {
                    IVariable cur = (IVariable) ca[i];
                    ca[i] = env.getEnv(GlobalEnv.class).GetVarList().get(cur.getVariableName(), cur.getTarget()).ival();
                }
            }
            {
                // It takes a moment to generate the toString of some things, so lets not do it
                // if we actually aren't going to profile
                ProfilePoint p = null;
                if (f.shouldProfile() && env.getEnv(GlobalEnv.class).GetProfiler() != null && env.getEnv(GlobalEnv.class).GetProfiler().isLoggable(f.profileAt())) {
                    p = env.getEnv(GlobalEnv.class).GetProfiler().start(f.profileMessage(ca), f.profileAt());
                }
                Construct ret;
                try {
                    ret = f.exec(m.getTarget(), env, ca);
                } finally {
                    if (p != null) {
                        p.stop();
                    }
                }
                return ret;
            }
        // We want to catch and rethrow the ones we know how to catch, and then
        // catch and report anything else.
        } catch (ConfigRuntimeException | ProgramFlowManipulationException e) {
            if (e instanceof AbstractCREException) {
                ((AbstractCREException) e).freezeStackTraceElements(stManager);
            }
            throw e;
        } catch (InvalidEnvironmentException e) {
            if (!e.isDataSet()) {
                e.setData(f.getName());
            }
            throw e;
        } catch (Exception e) {
            String brand = Implementation.GetServerType().getBranding();
            SimpleVersion version = Static.getVersion();
            String culprit = brand;
            outer: for (ExtensionTracker tracker : ExtensionManager.getTrackers().values()) {
                for (FunctionBase b : tracker.getFunctions()) {
                    if (b.getName().equals(f.getName())) {
                        // name instead of the core plugin's name.
                        for (Extension extension : tracker.getExtensions()) {
                            culprit = extension.getName();
                            break outer;
                        }
                    }
                }
            }
            String emsg = TermColors.RED + "Uh oh! You've found an error in " + TermColors.CYAN + culprit + TermColors.RED + ".\n" + "This happened while running your code, so you may be able to find a workaround," + " but is ultimately an issue in " + culprit + ".\n" + "The following code caused the error:\n" + TermColors.WHITE;
            List<String> args2 = new ArrayList<>();
            Map<String, String> vars = new HashMap<>();
            for (Construct cc : args) {
                if (cc instanceof IVariable) {
                    Construct ccc = env.getEnv(GlobalEnv.class).GetVarList().get(((IVariable) cc).getVariableName(), cc.getTarget()).ival();
                    String vval = ccc.val();
                    if (ccc instanceof CString) {
                        vval = ccc.asString().getQuote();
                    }
                    vars.put(((IVariable) cc).getVariableName(), vval);
                }
                if (cc == null) {
                    args2.add("java-null");
                } else if (cc instanceof CString) {
                    args2.add(cc.asString().getQuote());
                } else if (cc instanceof IVariable) {
                    args2.add(((IVariable) cc).getVariableName());
                } else {
                    args2.add(cc.val());
                }
            }
            if (!vars.isEmpty()) {
                emsg += StringUtils.Join(vars, " = ", "\n") + "\n";
            }
            emsg += f.getName() + "(";
            emsg += StringUtils.Join(args2, ", ");
            emsg += ")\n";
            emsg += TermColors.RED + "on or around " + TermColors.YELLOW + m.getTarget().file() + TermColors.WHITE + ":" + TermColors.CYAN + m.getTarget().line() + TermColors.RED + ".\n";
            // Server might not be available in this platform, so let's be sure to ignore those exceptions
            String modVersion;
            try {
                modVersion = StaticLayer.GetConvertor().GetServer().getAPIVersion();
            } catch (Exception ex) {
                modVersion = Implementation.GetServerType().name();
            }
            String extensionData = "";
            for (ExtensionTracker tracker : ExtensionManager.getTrackers().values()) {
                for (Extension extension : tracker.getExtensions()) {
                    try {
                        extensionData += TermColors.CYAN + extension.getName() + TermColors.RED + " (" + TermColors.RESET + extension.getVersion() + TermColors.RED + ")\n";
                    } catch (AbstractMethodError ex) {
                        // This happens with an old style extensions. Just skip it.
                        extensionData += TermColors.CYAN + "Unknown Extension" + TermColors.RED + "\n";
                    }
                }
            }
            if (extensionData.isEmpty()) {
                extensionData = "NONE\n";
            }
            emsg += "Please report this to the developers, and be sure to include the version numbers:\n" + TermColors.CYAN + "Server" + TermColors.RED + " version: " + TermColors.RESET + modVersion + TermColors.RED + ";\n" + TermColors.CYAN + brand + TermColors.RED + " version: " + TermColors.RESET + version + TermColors.RED + ";\n" + "Loaded extensions and versions:\n" + extensionData + "Here's the stacktrace:\n" + TermColors.RESET + Static.GetStacktraceString(e);
            Static.getLogger().log(Level.SEVERE, emsg);
            throw new CancelCommandException(null, Target.UNKNOWN);
        }
    } finally {
        if (addedRootStackElement && stManager.isStackSingle()) {
            stManager.popStackTraceElement();
        }
    }
}
Also used : CLabel(com.laytonsmith.core.constructs.CLabel) InvalidEnvironmentException(com.laytonsmith.core.environments.InvalidEnvironmentException) FunctionBase(com.laytonsmith.core.functions.FunctionBase) IVariable(com.laytonsmith.core.constructs.IVariable) ArrayList(java.util.ArrayList) CArray(com.laytonsmith.core.constructs.CArray) CREInvalidProcedureException(com.laytonsmith.core.exceptions.CRE.CREInvalidProcedureException) ExtensionTracker(com.laytonsmith.core.extensions.ExtensionTracker) ConfigRuntimeException(com.laytonsmith.core.exceptions.ConfigRuntimeException) CString(com.laytonsmith.core.constructs.CString) ConfigCompileException(com.laytonsmith.core.exceptions.ConfigCompileException) CString(com.laytonsmith.core.constructs.CString) Function(com.laytonsmith.core.functions.Function) CancelCommandException(com.laytonsmith.core.exceptions.CancelCommandException) SimpleVersion(com.laytonsmith.PureUtilities.SimpleVersion) FunctionList(com.laytonsmith.core.functions.FunctionList) List(java.util.List) ArrayList(java.util.ArrayList) AbstractCREException(com.laytonsmith.core.exceptions.CRE.AbstractCREException) CREInsufficientPermissionException(com.laytonsmith.core.exceptions.CRE.CREInsufficientPermissionException) CRECastException(com.laytonsmith.core.exceptions.CRE.CRECastException) CBoolean(com.laytonsmith.core.constructs.CBoolean) CDouble(com.laytonsmith.core.constructs.CDouble) ProgramFlowManipulationException(com.laytonsmith.core.exceptions.ProgramFlowManipulationException) StackTraceManager(com.laytonsmith.core.exceptions.StackTraceManager) ProfilePoint(com.laytonsmith.core.profiler.ProfilePoint) CRECastException(com.laytonsmith.core.exceptions.CRE.CRECastException) ProgramFlowManipulationException(com.laytonsmith.core.exceptions.ProgramFlowManipulationException) CancelCommandException(com.laytonsmith.core.exceptions.CancelCommandException) InvalidEnvironmentException(com.laytonsmith.core.environments.InvalidEnvironmentException) ConfigCompileException(com.laytonsmith.core.exceptions.ConfigCompileException) AbstractCREException(com.laytonsmith.core.exceptions.CRE.AbstractCREException) CREInsufficientPermissionException(com.laytonsmith.core.exceptions.CRE.CREInsufficientPermissionException) LoopBreakException(com.laytonsmith.core.exceptions.LoopBreakException) CREInvalidProcedureException(com.laytonsmith.core.exceptions.CRE.CREInvalidProcedureException) LoopContinueException(com.laytonsmith.core.exceptions.LoopContinueException) ConfigRuntimeException(com.laytonsmith.core.exceptions.ConfigRuntimeException) FunctionReturnException(com.laytonsmith.core.exceptions.FunctionReturnException) ConfigCompileGroupException(com.laytonsmith.core.exceptions.ConfigCompileGroupException) ProfilePoint(com.laytonsmith.core.profiler.ProfilePoint) CVoid(com.laytonsmith.core.constructs.CVoid) Extension(com.laytonsmith.core.extensions.Extension) CInt(com.laytonsmith.core.constructs.CInt) Construct(com.laytonsmith.core.constructs.Construct) CommandHelperEnvironment(com.laytonsmith.core.environments.CommandHelperEnvironment) Environment(com.laytonsmith.core.environments.Environment) GlobalEnv(com.laytonsmith.core.environments.GlobalEnv) CEntry(com.laytonsmith.core.constructs.CEntry) Map(java.util.Map) HashMap(java.util.HashMap) CNull(com.laytonsmith.core.constructs.CNull)

Example 2 with Function

use of com.laytonsmith.core.functions.Function in project CommandHelper by EngineHub.

the class DocGen method functions.

/**
 * Returns the documentation for a single function.
 *
 * @param type The type of output to use. May be one of: html, wiki, text
 * @param platform The platform we're using
 * @param staged Is this for the staged wiki?
 * @return
 * @throws ConfigCompileException
 */
@SuppressWarnings("StringConcatenationInsideStringBufferAppend")
public static String functions(MarkupType type, api.Platforms platform, boolean staged) throws ConfigCompileException {
    Set<FunctionBase> functions = FunctionList.getFunctionList(platform);
    HashMap<Class, ArrayList<FunctionBase>> functionlist = new HashMap<Class, ArrayList<FunctionBase>>();
    StringBuilder out = new StringBuilder();
    for (FunctionBase f : functions) {
        // Sort the functions into classes
        Class apiClass = (f.getClass().getEnclosingClass() != null ? f.getClass().getEnclosingClass() : null);
        ArrayList<FunctionBase> fl = functionlist.get(apiClass);
        if (fl == null) {
            fl = new ArrayList<FunctionBase>();
            functionlist.put(apiClass, fl);
        }
        fl.add(f);
    }
    if (type == MarkupType.HTML) {
        out.append("Command Helper uses a language called MethodScript, which greatly extend the capabilities of the plugin, " + "and make the plugin a fully " + "<a href=\"http://en.wikipedia.org/wiki/Turing_Complete\">Turing Complete</a> language. " + "There are several functions defined, and they are grouped into \"classes\". \n");
    } else if (type == MarkupType.WIKI) {
        out.append("Command Helper uses a language called MethodScript, which greatly extend the capabilities of the plugin, " + "and make the plugin a fully " + "[http://en.wikipedia.org/wiki/Turing_Complete Turing Complete] language. " + "There are several functions defined, and they are grouped into \"classes\". \n");
        out.append("<p>Each function has its own page for documentation, where you can view examples for how to use a" + " particular function.\n");
    } else if (type == MarkupType.TEXT) {
        out.append("Command Helper uses a language called MethodScript, which greatly extend the capabilities of the plugin, " + "and make the plugin a fully " + "Turing Complete language [http://en.wikipedia.org/wiki/Turing_Complete].\n" + "There are several functions defined, and they are grouped into \"classes\".\n");
    }
    List<Map.Entry<Class, ArrayList<FunctionBase>>> entrySet = new ArrayList<Map.Entry<Class, ArrayList<FunctionBase>>>(functionlist.entrySet());
    Collections.sort(entrySet, new Comparator<Map.Entry<Class, ArrayList<FunctionBase>>>() {

        @Override
        public int compare(Map.Entry<Class, ArrayList<FunctionBase>> o1, Map.Entry<Class, ArrayList<FunctionBase>> o2) {
            return o1.getKey().getName().compareTo(o2.getKey().getName());
        }
    });
    int total = 0;
    int workingExamples = 0;
    for (Map.Entry<Class, ArrayList<FunctionBase>> entry : entrySet) {
        Class apiClass = entry.getKey();
        String className = apiClass.getName().split("\\.")[apiClass.getName().split("\\.").length - 1];
        if (className.equals("Sandbox")) {
            // Skip Sandbox functions
            continue;
        }
        String classDocs = null;
        try {
            Method m = apiClass.getMethod("docs", (Class[]) null);
            Object o = null;
            if ((m.getModifiers() & Modifier.STATIC) == 0) {
                try {
                    o = apiClass.newInstance();
                } catch (InstantiationException ex) {
                }
            }
            classDocs = (String) m.invoke(o, (Object[]) null);
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException ex) {
        } catch (Exception e) {
            e.printStackTrace(StreamUtils.GetSystemErr());
            StreamUtils.GetSystemErr().println("Continuing however.");
        }
        StringBuilder intro = new StringBuilder();
        if (type == MarkupType.HTML) {
            if (className != null) {
                intro.append("<h1>").append(className).append("</h1>" + "\n");
                intro.append(classDocs == null ? "" : classDocs).append("\n");
            } else {
                intro.append("<h1>Other Functions</h1>" + "\n");
            }
            intro.append("<table>" + "\n");
        } else if (type == MarkupType.WIKI) {
            if (className != null) {
                intro.append("===").append(className).append("===" + "\n");
                intro.append(classDocs == null ? "" : classDocs).append("\n");
            } else {
                intro.append("===Other Functions===" + "\n");
            }
            intro.append("{| width=\"100%\" cellspacing=\"1\" cellpadding=\"1\" border=\"1\" class=\"wikitable\"\n" + "|-\n" + "! scope=\"col\" width=\"6%\" | Function Name\n" + "! scope=\"col\" width=\"5%\" | Returns\n" + "! scope=\"col\" width=\"10%\" | Arguments\n" + "! scope=\"col\" width=\"10%\" | Throws\n" + "! scope=\"col\" width=\"61%\" | Description\n" + "! scope=\"col\" width=\"3%\" | Since\n" + "! scope=\"col\" width=\"5%\" | Restricted" + "\n");
        } else if (type == MarkupType.TEXT) {
            intro.append("\n").append(className).append("\n");
            intro.append("**********************************************************************************************" + "\n");
            if (className != null) {
                intro.append(classDocs == null ? "" : classDocs).append("\n");
            } else {
                intro.append("Other Functions" + "\n");
            }
            intro.append("**********************************************************************************************" + "\n");
        }
        List<FunctionBase> documentableFunctions = new ArrayList<FunctionBase>();
        for (FunctionBase f : entry.getValue()) {
            if (f.appearInDocumentation()) {
                documentableFunctions.add(f);
            }
        }
        if (!documentableFunctions.isEmpty()) {
            out.append(intro.toString() + "\n");
        }
        Collections.sort(documentableFunctions, new Comparator<FunctionBase>() {

            @Override
            public int compare(FunctionBase o1, FunctionBase o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });
        for (FunctionBase f : documentableFunctions) {
            total++;
            String doc = f.docs();
            String restricted = (f instanceof Function && ((Function) f).isRestricted()) ? "<div style=\"background-color: red; font-weight: bold; text-align: center;\">Yes</div>" : "<div style=\"background-color: green; font-weight: bold; text-align: center;\">No</div>";
            StringBuilder thrown = new StringBuilder();
            if (f instanceof Function && ((Function) f).thrown() != null) {
                List<Class<? extends CREThrowable>> thrownList = Arrays.asList(((Function) f).thrown());
                for (int i = 0; i < thrownList.size(); i++) {
                    String t = ((Class<? extends CREThrowable>) thrownList.get(i)).getAnnotation(typeof.class).value();
                    if (type == MarkupType.HTML || type == MarkupType.TEXT) {
                        if (i != 0) {
                            thrown.append((type == MarkupType.HTML ? "<br />\n" : " | "));
                        }
                        thrown.append(t);
                    } else {
                        if (i != 0) {
                            thrown.append("<br />\n");
                        }
                        thrown.append("[[CommandHelper/Exceptions#").append(t).append("|").append(t).append("]]");
                    }
                }
            }
            String since = (f instanceof Documentation ? ((Documentation) f).since().toString() : "0.0.0");
            DocInfo di = new DocInfo(doc);
            boolean hasExample = false;
            if (f instanceof Function && ((Function) f).examples() != null && ((Function) f).examples().length > 0) {
                hasExample = true;
                workingExamples++;
            }
            if (di.ret == null || di.args == null || di.desc == null) {
                out.append(f.getName() + "'s documentation is not correctly formatted. Please check it and try again.\n");
            }
            if (type == MarkupType.HTML) {
                out.append("<tr><td>" + di.ret + "</td><td>" + di.args + "</td><td>" + thrown.toString() + "</td><td>" + di.desc + "</td><td>" + since + "</td><td>" + restricted + "</td></tr>\n");
            } else if (type == MarkupType.WIKI) {
                // Turn args into a prettified version
                out.append("|- id=\"" + f.getName() + "\"\n" + "! scope=\"row\" | [[CommandHelper/" + (staged ? "Staged/" : "") + "API/" + f.getName() + "|" + f.getName() + "]]()\n" + "| " + di.ret + "\n" + "| " + di.args + "\n" + "| " + thrown.toString() + "\n" + "| " + (di.topDesc != null ? di.topDesc + " [[CommandHelper/" + (staged ? "Staged/" : "") + "API/" + f.getName() + "#Description|See More...]]" : di.desc) + (hasExample ? "<br />([[CommandHelper/" + (staged ? "Staged/" : "") + "API/" + f.getName() + "#Examples|Examples...]])" : "") + "\n" + "| " + since + "\n" + "| " + restricted + "\n");
            } else if (type == MarkupType.TEXT) {
                out.append(di.ret + " " + f.getName() + "(" + di.args + ")" + " {" + thrown.toString() + "}\n\t" + di.desc + "\n\t" + since + ((f instanceof Function ? ((Function) f).isRestricted() : false) ? "\n\tThis function is restricted" : "\n\tThis function is not restricted\n"));
            }
        }
        if (!documentableFunctions.isEmpty()) {
            if (type == MarkupType.HTML) {
                out.append("</table>\n");
            } else if (type == MarkupType.WIKI) {
                out.append("|}\n{{Back to top}}\n");
            } else if (type == MarkupType.TEXT) {
                out.append("\n");
            }
        }
    }
    if (type == MarkupType.HTML) {
        out.append("" + "<h2>Errors in documentation</h2>\n" + "<em>Please note that this documentation is generated automatically," + " if you notice an error in the documentation, please file a bug report for the" + " plugin itself!</em>" + "<div style='text-size:small; text-decoration:italics; color:grey'>There are " + total + " functions in this API page</div>\n");
    } else if (type == MarkupType.WIKI) {
        out.append("" + "===Errors in documentation===\n" + "''Please note that this documentation is generated automatically," + " if you notice an error in the documentation, please file a bug report for the" + " plugin itself!'' For information on undocumented functions, see [[CommandHelper/Sandbox|this page]]" + "<div style='font-size:xx-small; font-style:italic; color:grey'>There are " + total + " functions in this API page, " + workingExamples + " of which" + " have examples.</div>\n\n{{Back to top}}\n{{LearningTrail}}\n");
    }
    return out.toString();
}
Also used : FunctionBase(com.laytonsmith.core.functions.FunctionBase) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) CREThrowable(com.laytonsmith.core.exceptions.CRE.CREThrowable) CFunction(com.laytonsmith.core.constructs.CFunction) Function(com.laytonsmith.core.functions.Function) com.laytonsmith.annotations.typeof(com.laytonsmith.annotations.typeof) Documentation(com.laytonsmith.core.Documentation) Method(java.lang.reflect.Method) InvocationTargetException(java.lang.reflect.InvocationTargetException) ConfigCompileException(com.laytonsmith.core.exceptions.ConfigCompileException) InvocationTargetException(java.lang.reflect.InvocationTargetException) HashMap(java.util.HashMap) Map(java.util.Map)

Example 3 with Function

use of com.laytonsmith.core.functions.Function in project CommandHelper by EngineHub.

the class DocGen method examples.

public static String examples(String function, boolean staged) throws Exception {
    FunctionBase fb = FunctionList.getFunction(new CFunction(function, Target.UNKNOWN));
    if (fb instanceof Function) {
        Function f = (Function) fb;
        String restricted = (f instanceof Function && ((Function) f).isRestricted()) ? "<div style=\"background-color: red; font-weight: bold; text-align: center;\">Yes</div>" : "<div style=\"background-color: green; font-weight: bold; text-align: center;\">No</div>";
        String optimizationMessage = "None";
        if (f instanceof Optimizable) {
            Set<Optimizable.OptimizationOption> options = ((Optimizable) f).optimizationOptions();
            List<String> list = new ArrayList<String>();
            for (Optimizable.OptimizationOption option : options) {
                list.add("[[CommandHelper/" + (staged ? "Staged/" : "") + "Optimizer#" + option.name() + "|" + option.name() + "]]");
            }
            optimizationMessage = StringUtils.Join(list, "<br />");
        }
        DocInfo di = new DocInfo(f.docs());
        StringBuilder thrown = new StringBuilder();
        if (f instanceof Function && ((Function) f).thrown() != null) {
            List thrownList = Arrays.asList(((Function) f).thrown());
            for (int i = 0; i < thrownList.size(); i++) {
                String t = ((Class<? extends CREThrowable>) thrownList.get(i)).getAnnotation(typeof.class).value();
                if (i != 0) {
                    thrown.append("<br />\n");
                }
                thrown.append("[[CommandHelper/Exceptions#").append(t).append("|").append(t).append("]]");
            }
        }
        String tableUsages = di.originalArgs.replace("|", "<hr />");
        String[] usages = di.originalArgs.split("\\|");
        StringBuilder usageBuilder = new StringBuilder();
        for (String usage : usages) {
            usageBuilder.append("<pre>\n").append(f.getName()).append("(").append(usage.trim()).append(")\n</pre>");
        }
        StringBuilder exampleBuilder = new StringBuilder();
        if (f.examples() != null && f.examples().length > 0) {
            int count = 1;
            // If the output was automatically generated, change the color of the pre
            for (ExampleScript es : f.examples()) {
                exampleBuilder.append("====Example ").append(count).append("====\n").append(es.getDescription()).append("\n\n" + "Given the following code:\n");
                exampleBuilder.append(SimpleSyntaxHighlighter.Highlight(es.getScript(), true)).append("\n");
                String style = "";
                if (es.isAutomatic()) {
                    style = " style=\"background-color: #BDC7E9\"";
                    exampleBuilder.append("\n\nThe output would be:\n<pre");
                } else {
                    exampleBuilder.append("\n\nThe output might be:\n<pre");
                }
                exampleBuilder.append(style).append(">").append(es.getOutput()).append("</pre>\n");
                count++;
            }
        } else {
            exampleBuilder.append("Sorry, there are no examples for this function! :(");
        }
        Class[] seeAlso = f.seeAlso();
        String seeAlsoText = "";
        if (seeAlso != null && seeAlso.length > 0) {
            seeAlsoText += "===See Also===\n";
            boolean first = true;
            for (Class c : seeAlso) {
                if (!first) {
                    seeAlsoText += ", ";
                }
                first = false;
                if (Function.class.isAssignableFrom(c)) {
                    Function f2 = (Function) c.newInstance();
                    seeAlsoText += "<code>[[CommandHelper/" + (staged ? "Staged/" : "") + "API/" + f2.getName() + "|" + f2.getName() + "]]</code>";
                } else if (Template.class.isAssignableFrom(c)) {
                    Template t = (Template) c.newInstance();
                    seeAlsoText += "[[CommandHelper/" + (staged ? "Staged/" : "") + t.getName() + "|Learning Trail: " + t.getDisplayName() + "]]";
                } else {
                    throw new Error("Unsupported class found in @seealso annotation: " + c.getName());
                }
            }
        }
        Map<String, String> templateFields = new HashMap<>();
        templateFields.put("function_name", f.getName());
        templateFields.put("returns", di.ret);
        templateFields.put("tableUsages", tableUsages);
        templateFields.put("throws", thrown.toString());
        templateFields.put("since", f.since().toString());
        templateFields.put("restricted", restricted);
        templateFields.put("optimizationMessage", optimizationMessage);
        templateFields.put("description", di.extendedDesc == null ? di.desc : di.topDesc + "\n\n" + di.extendedDesc);
        templateFields.put("usages", usageBuilder.toString());
        templateFields.put("examples", exampleBuilder.toString());
        templateFields.put("staged", staged ? "Staged/" : "");
        templateFields.put("seeAlso", seeAlsoText);
        String template = StreamUtils.GetString(DocGenTemplates.class.getResourceAsStream("/templates/example_templates"));
        // Find all the %%templates%% in the template
        Matcher m = Pattern.compile("%%(.*?)%%").matcher(template);
        try {
            while (m.find()) {
                String name = m.group(1);
                String templateValue = templateFields.get(name);
                template = template.replaceAll("%%" + Pattern.quote(name) + "%%", templateValue.replace("$", "\\$").replaceAll("\\'", "\\\\'"));
            }
            return template;
        } catch (RuntimeException e) {
            throw new RuntimeException("Caught a runtime exception while generating template for " + function, e);
        }
    } else {
        throw new RuntimeException(function + " does not implement Function");
    }
}
Also used : FunctionBase(com.laytonsmith.core.functions.FunctionBase) HashMap(java.util.HashMap) Matcher(java.util.regex.Matcher) ArrayList(java.util.ArrayList) Template(com.laytonsmith.tools.docgen.templates.Template) CFunction(com.laytonsmith.core.constructs.CFunction) Function(com.laytonsmith.core.functions.Function) ArrayList(java.util.ArrayList) FunctionList(com.laytonsmith.core.functions.FunctionList) List(java.util.List) com.laytonsmith.annotations.typeof(com.laytonsmith.annotations.typeof) ExampleScript(com.laytonsmith.core.functions.ExampleScript) CFunction(com.laytonsmith.core.constructs.CFunction) Optimizable(com.laytonsmith.core.Optimizable)

Example 4 with Function

use of com.laytonsmith.core.functions.Function in project CommandHelper by EngineHub.

the class SingleFunctionDialog method uploadButtonActionPerformed.

// </editor-fold>//GEN-END:initComponents
private void uploadButtonActionPerformed(java.awt.event.ActionEvent evt) {
    // GEN-FIRST:event_uploadButtonActionPerformed
    Function f;
    try {
        f = (Function) FunctionList.getFunction(functionNameField.getText(), Target.UNKNOWN);
        if (!f.appearInDocumentation()) {
            statusLabel.setText("That function is not configured to have documentation.");
            return;
        }
        try {
            String docs = DocGen.examples(f.getName(), parent.handler.isStaged);
            parent.handler.doUpload(docs, "/API/" + f.getName(), true);
        } catch (Exception ex) {
            statusLabel.setText(ex.getMessage());
            ex.printStackTrace(StreamUtils.GetSystemErr());
        }
    } catch (ConfigCompileException ex) {
        statusLabel.setText("That function doesn't exist.");
        return;
    }
}
Also used : Function(com.laytonsmith.core.functions.Function) ConfigCompileException(com.laytonsmith.core.exceptions.ConfigCompileException) ConfigCompileException(com.laytonsmith.core.exceptions.ConfigCompileException)

Example 5 with Function

use of com.laytonsmith.core.functions.Function in project CommandHelper by EngineHub.

the class ExtensionDocGen method generate.

public static void generate(File inputExtension, OutputStream outputStream) throws InstantiationException, IllegalAccessException, MalformedURLException, IOException {
    ClassDiscovery customDiscovery = new ClassDiscovery();
    ClassDiscoveryCache cache = new ClassDiscoveryCache(CommandHelperFileLocations.getDefault().getCacheDirectory());
    customDiscovery.setClassDiscoveryCache(cache);
    URL url = new URL("jar:" + inputExtension.toURI().toURL() + "!/");
    customDiscovery.addDiscoveryLocation(url);
    customDiscovery.setDefaultClassLoader(ExtensionDocGen.class.getClassLoader());
    StringBuilder fdocs = new StringBuilder();
    DynamicClassLoader classloader = new DynamicClassLoader();
    classloader.addJar(url);
    // functions
    HashMap<Class<?>, ArrayList<Class<? extends Function>>> functionMap = new HashMap<>();
    for (Class<? extends Function> cf : customDiscovery.loadClassesWithAnnotationThatExtend(api.class, Function.class, classloader, true)) {
        Class enclosing = cf.getEnclosingClass();
        if (functionMap.containsKey(enclosing)) {
            functionMap.get(enclosing).add(cf);
        } else {
            functionMap.put(enclosing, new ArrayList<Class<? extends Function>>());
            functionMap.get(enclosing).add(cf);
        }
    }
    ArrayList<Entry<Class<?>, ArrayList<Class<? extends Function>>>> functionEntryList = new ArrayList<>(functionMap.entrySet());
    Collections.sort(functionEntryList, new Comparator<Entry<Class<?>, ArrayList<Class<? extends Function>>>>() {

        @Override
        public int compare(Entry<Class<?>, ArrayList<Class<? extends Function>>> o1, Entry<Class<?>, ArrayList<Class<? extends Function>>> o2) {
            return o1.getKey().getName().compareTo(o2.getKey().getName());
        }
    });
    for (Entry<Class<?>, ArrayList<Class<? extends Function>>> e : functionEntryList) {
        Collections.sort(e.getValue(), new Comparator<Class<? extends Function>>() {

            @Override
            public int compare(Class<? extends Function> o1, Class<? extends Function> o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });
    }
    if (!functionEntryList.isEmpty()) {
        fdocs.append("# Functions").append(nl);
    }
    for (Entry<Class<?>, ArrayList<Class<? extends Function>>> entry : functionEntryList) {
        Class enclosingClass = entry.getKey();
        String[] split = enclosingClass.getName().split("\\.");
        fdocs.append("## ").append(split[split.length - 1]).append(nl);
        try {
            Method docsMethod = enclosingClass.getMethod("docs", (Class[]) null);
            Object o = enclosingClass.newInstance();
            fdocs.append((String) docsMethod.invoke(o, (Object[]) null)).append(nl).append(nl);
        } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException exception) {
        }
        for (Class<? extends Function> cf : entry.getValue()) {
            Function f = cf.newInstance();
            if (f.appearInDocumentation()) {
                DocGen.DocInfo di = new DocGen.DocInfo(f.docs());
                String d = "### " + markdownEscape(di.ret) + " " + markdownEscape(f.getName()) + "(" + markdownEscape(di.originalArgs) + "):" + nl + convertWiki(di.topDesc != null ? di.topDesc : di.desc) + nl + convertWiki(di.extendedDesc != null ? nl + di.extendedDesc + nl : "");
                fdocs.append(d).append(nl);
            }
        }
    }
    // events
    HashMap<Class<?>, ArrayList<Class<? extends Event>>> eventMap = new HashMap<>();
    for (Class<? extends Event> ce : customDiscovery.loadClassesWithAnnotationThatExtend(api.class, Event.class, classloader, true)) {
        Class<?> enclosing = ce.getEnclosingClass();
        if (eventMap.containsKey(enclosing)) {
            eventMap.get(enclosing).add(ce);
        } else {
            eventMap.put(enclosing, new ArrayList<Class<? extends Event>>());
            eventMap.get(enclosing).add(ce);
        }
    }
    ArrayList<Entry<Class<?>, ArrayList<Class<? extends Event>>>> eventEntryList = new ArrayList<>(eventMap.entrySet());
    Collections.sort(eventEntryList, new Comparator<Entry<Class<?>, ArrayList<Class<? extends Event>>>>() {

        @Override
        public int compare(Entry<Class<?>, ArrayList<Class<? extends Event>>> o1, Entry<Class<?>, ArrayList<Class<? extends Event>>> o2) {
            return o1.getKey().getName().compareTo(o2.getKey().getName());
        }
    });
    for (Entry<Class<?>, ArrayList<Class<? extends Event>>> e : eventEntryList) {
        Collections.sort(e.getValue(), new Comparator<Class<? extends Event>>() {

            @Override
            public int compare(Class<? extends Event> o1, Class<? extends Event> o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });
    }
    if (!eventEntryList.isEmpty()) {
        fdocs.append("# Events").append(nl);
    }
    for (Entry<Class<?>, ArrayList<Class<? extends Event>>> entry : eventEntryList) {
        Class enclosingClass = entry.getKey();
        String[] split = enclosingClass.getName().split("\\.");
        fdocs.append("## ").append(split[split.length - 1]).append(nl);
        try {
            Method docsMethod = enclosingClass.getMethod("docs", (Class[]) null);
            Object o = enclosingClass.newInstance();
            fdocs.append((String) docsMethod.invoke(o, (Object[]) null)).append(nl).append(nl);
        } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException exception) {
        }
        for (Class<? extends Event> ce : entry.getValue()) {
            Event e = ce.newInstance();
            Pattern p = Pattern.compile("\\{(.*?)\\} *?(.*?) *?\\{(.*?)\\} *?\\{(.*?)\\}");
            Matcher m = p.matcher(e.docs());
            if (m.find()) {
                String name = e.getName();
                String description = m.group(2).trim();
                String prefilter = DocGen.PrefilterData.Get(m.group(1).split("\\|"), DocGen.MarkupType.MARKDOWN);
                String eventData = DocGen.EventData.Get(m.group(3).split("\\|"), DocGen.MarkupType.MARKDOWN);
                String mutability = DocGen.MutabilityData.Get(m.group(4).split("\\|"), DocGen.MarkupType.MARKDOWN);
                // String manualTrigger = ManualTriggerData.Get(m.group(5).split("\\|"), DocGen.MarkupType.MARKDOWN);
                // String since = e.since().toString();
                fdocs.append("### ").append(markdownEscape(name)).append(nl);
                fdocs.append(description).append(nl);
                fdocs.append("#### Prefilters").append(nl).append(prefilter).append(nl);
                fdocs.append("#### Event Data").append(nl).append(eventData).append(nl);
                fdocs.append("#### Mutable Fields").append(nl).append(mutability).append(nl);
            }
        }
    }
    outputStream.write(fdocs.toString().getBytes("UTF-8"));
}
Also used : DynamicClassLoader(com.laytonsmith.PureUtilities.ClassLoading.DynamicClassLoader) HashMap(java.util.HashMap) Matcher(java.util.regex.Matcher) ArrayList(java.util.ArrayList) URL(java.net.URL) Function(com.laytonsmith.core.functions.Function) Entry(java.util.Map.Entry) Pattern(java.util.regex.Pattern) Method(java.lang.reflect.Method) ClassDiscovery(com.laytonsmith.PureUtilities.ClassLoading.ClassDiscovery) InvocationTargetException(java.lang.reflect.InvocationTargetException) Event(com.laytonsmith.core.events.Event) ClassDiscoveryCache(com.laytonsmith.PureUtilities.ClassLoading.ClassDiscoveryCache)

Aggregations

Function (com.laytonsmith.core.functions.Function)14 ArrayList (java.util.ArrayList)10 CFunction (com.laytonsmith.core.constructs.CFunction)6 ConfigCompileException (com.laytonsmith.core.exceptions.ConfigCompileException)6 HashMap (java.util.HashMap)6 FunctionBase (com.laytonsmith.core.functions.FunctionBase)4 List (java.util.List)4 Map (java.util.Map)4 com.laytonsmith.annotations.typeof (com.laytonsmith.annotations.typeof)3 Optimizable (com.laytonsmith.core.Optimizable)3 CString (com.laytonsmith.core.constructs.CString)3 IVariable (com.laytonsmith.core.constructs.IVariable)3 Event (com.laytonsmith.core.events.Event)3 IOException (java.io.IOException)3 DynamicClassLoader (com.laytonsmith.PureUtilities.ClassLoading.DynamicClassLoader)2 SimpleVersion (com.laytonsmith.PureUtilities.SimpleVersion)2 Documentation (com.laytonsmith.core.Documentation)2 Construct (com.laytonsmith.core.constructs.Construct)2 CommandHelperEnvironment (com.laytonsmith.core.environments.CommandHelperEnvironment)2 Environment (com.laytonsmith.core.environments.Environment)2