Remove old build scripts

This commit is contained in:
Johann Bernhardt committed 2021-12-12 14:03:22 +01:00
1 parent 7f3b65c4b7
commit 8bb680471f
31 files changed
-2501

No files matched your search

-14
View File
@@ -1,14 +0,0 @@
import java.io.File
apply plugin: 'java'
apply from: new File('../configuration.gradle')
repositories {
mavenCentral();
}
dependencies {
compile gradleApi()
compile 'org.ow2.asm:asm-debug-all:5.0.3'
compile files(javaToolsJar)
}
@@ -1,170 +0,0 @@
package minetweaker.tasks;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.InputDirectory;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.TaskAction;
/**
* Java preprocessor. Enables conditional modification of Java source files.
*
* @author Stan Hebben
*/
public class JMorph extends DefaultTask {
@InputDirectory
public File inputDir;
@InputFile
public File propertiesFile;
@TaskAction
public void doTask() {
try {
Properties properties = new Properties();
BufferedReader reader = new BufferedReader(new FileReader(propertiesFile));
properties.load(reader);
reader.close();
processDirectory(inputDir, properties);
} catch (IOException ex) {
Logger.getLogger(JMorph.class.getName()).log(Level.SEVERE, null, ex);
}
}
private static void processDirectory(File dir, Properties properties) throws IOException {
for (File file : dir.listFiles()) {
if (file.isFile()) {
if (file.getName().endsWith(".java") || file.getName().endsWith(".java.d")) {
processJavaFile(file, properties);
}
} else if (file.isDirectory()) {
processDirectory(file, properties);
}
}
}
private static void processJavaFile(File file, Properties properties) throws IOException {
StringBuilder output = new StringBuilder();
File outputFile = file.getName().endsWith(".java.d")
? new File(file.getParentFile(), file.getName().substring(0, file.getName().length() - 2))
: file;
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String line = reader.readLine();
if (line == null) return;
Stack<Boolean> conditions = new Stack<>();
conditions.push(Boolean.TRUE);
do {
String trimmed = line.trim();
if (trimmed.startsWith("//#fileifdef")) {
String id = getIdentifier(trimmed, 13);
if (properties.containsKey(id)) {
if (file.getName().endsWith(".java.d")) {
outputFile = new File(file.getParentFile(), file.getName().substring(0, file.getName().length() - 2));
} else {
outputFile = file;
}
} else {
if (file.getName().endsWith(".java")) {
outputFile = new File(file.getParentFile(), file.getName() + ".d");
} else {
outputFile = file;
}
}
} else if (trimmed.startsWith("//#fileifndef")) {
String id = getIdentifier(trimmed, 14);
if (!properties.containsKey(id)) {
outputFile = file.getName().endsWith(".java.d")
? new File(file.getParentFile(), file.getName().substring(0, file.getName().length() - 2))
: file;
} else {
outputFile = file.getName().endsWith(".java")
? new File(file.getParentFile(), file.getName() + ".d")
: file;
}
} else if (trimmed.startsWith("//#ifdef")) {
String id = getIdentifier(trimmed, 9);
conditions.push(properties.containsKey(id));
} else if (trimmed.startsWith("//#ifndef")) {
String id = getIdentifier(trimmed, 10);
conditions.push(!properties.containsKey(id));
} else if (trimmed.startsWith("//#else")) {
conditions.push(!conditions.pop());
} else if (trimmed.startsWith("//#elseif")) {
conditions.pop();
String id = getIdentifier(trimmed, 10);
conditions.push(properties.containsKey(id));
} else if (trimmed.startsWith("//#endif")) {
conditions.pop();
if (conditions.isEmpty()) {
System.err.println("Error: too many #endifs in " + file.getName());
return;
}
} else if (trimmed.startsWith("//+")) {
if (conditions.peek()) line = uncomment(line).toString();
} else if (trimmed.length() != 0) {
if (!conditions.peek()) line = comment(line).toString();
}
output.append(line).append('\n');
line = reader.readLine();
} while (line != null);
}
if (outputFile != file)
file.delete();
try (FileWriter writer = new FileWriter(outputFile)) {
writer.append(output);
}
}
private static CharSequence comment(String line) {
StringBuilder output = new StringBuilder();
for (int i = 0; i < line.length(); i++) {
if (line.charAt(i) == ' ' || line.charAt(i) == '\t') {
output.append(line.charAt(i));
continue;
}
output.append("//+").append(line.substring(i));
break;
}
return output;
}
private static CharSequence uncomment(String line) {
StringBuilder output = new StringBuilder();
for (int i = 0; i < line.length(); i++) {
if (line.charAt(i) == ' ' || line.charAt(i) == '\t') {
output.append(line.charAt(i));
} else if (line.charAt(i) == '/' && line.charAt(i + 1) == '/' && line.charAt(i + 2) == '+') {
output.append(line.substring(i + 3));
break;
} else {
return line;
}
}
return output;
}
private static String getIdentifier(String line, int offset) {
int from = offset;
int to = offset;
if (!Character.isJavaIdentifierStart(line.charAt(to))) return null;
to++;
while (to < line.length() && Character.isJavaIdentifierPart(line.charAt(to))) to++;
return line.substring(from, to);
}
}
@@ -1,35 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package minetweaker.tasks;
import java.io.File;
import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction;
/**
*
* @author Stan
*/
public class MergeJarsTask extends DefaultTask {
@InputFile
public File mainInput;
@InputFile
public File[] inputs;
@OutputFile
public File output;
@TaskAction
public void doTask() {
System.out.println("Main: " + mainInput.toString());
System.out.println("Inputs: " + inputs.length);
System.out.println("Output: " + output.toString());
}
}
@@ -1,206 +0,0 @@
package minetweaker.tasks;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputDirectory;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.TaskAction;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
/**
* Generates a native registrar class. Finds all classes with a @ZenClass or
* @ZenExpansion annotation and generates a class with a single static
* getClasses(List<Class>) method. Overrides existing files if they exist.
* (handy for having a stub in the original source)
*
* @author Stan Hebben
*/
public class RegisterZenClassesTask extends DefaultTask {
@InputDirectory
public File inputDir;
@OutputDirectory
public File outputDir = null;
public void setInputDir(File inputDir) {
this.inputDir = inputDir;
}
public void setOutputDir(File inputDir) {
this.outputDir = inputDir;
}
@Input
public String className;
@TaskAction
public void doTask() {
if (outputDir == null) outputDir = inputDir;
List<String> classNames = new ArrayList<String>();
List<OnRegisterMethod> onRegisterMethods = new ArrayList<OnRegisterMethod>();
iterate(inputDir, null, classNames, onRegisterMethods);
String fullClassName = className.replace('.', '/');
// generate class
ClassWriter output = new ClassWriter(ClassWriter.COMPUTE_MAXS);
output.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC, fullClassName, null, "java/lang/Object", null);
MethodVisitor method = output.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "getClasses", "(Ljava/util/List;)V", null, null);
method.visitCode();
for (String clsName : classNames) {
method.visitVarInsn(Opcodes.ALOAD, 0);
method.visitLdcInsn(Type.getType("L" + clsName + ";"));
method.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/List", "add", "(Ljava/lang/Object;)Z");
}
for (OnRegisterMethod onRegisterMethod : onRegisterMethods) {
method.visitMethodInsn(Opcodes.INVOKESTATIC, onRegisterMethod.className, onRegisterMethod.methodName, "()V");
}
method.visitInsn(Opcodes.RETURN);
method.visitMaxs(0, 0);
method.visitEnd();
output.visitEnd();
// write output file
File outputFile = new File(outputDir, fullClassName + ".class");
File outputFileDir = outputFile.getParentFile();
if (!outputFileDir.exists()) {
outputFileDir.mkdirs();
}
if (outputFile.exists()) {
outputFile.delete();
}
try {
FileOutputStream outputStream = new FileOutputStream(outputFile);
outputStream.write(output.toByteArray());
outputStream.close();
} catch (IOException ex) {
Logger.getLogger(RegisterZenClassesTask.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void iterate(File dir, String pkg, List<String> classNames, List<OnRegisterMethod> onRegisterMethods) {
for (File f : dir.listFiles()) {
if (f.isDirectory()) {
if (pkg == null) {
iterate(f, f.getName(), classNames, onRegisterMethods);
} else {
iterate(f, pkg + "/" + f.getName(), classNames, onRegisterMethods);
}
} else if (f.isFile()) {
if (f.getName().endsWith(".class")) {
processJavaClass(f, pkg, classNames, onRegisterMethods);
}
}
}
}
private void processJavaClass(File cls, String pkg, List<String> classNames, List<OnRegisterMethod> onRegisterMethods) {
try {
InputStream input = new BufferedInputStream(new FileInputStream(cls));
ClassReader reader = new ClassReader(input);
AnnotationDetector detector = new AnnotationDetector();
reader.accept(detector, ClassReader.SKIP_CODE);
input.close();
if (detector.isAnnotated) {
classNames.add(pkg + "/" + cls.getName().substring(0, cls.getName().length() - 6));
}
for (MethodAnnotationDetector onRegisterMethod : detector.onRegister) {
onRegisterMethods.add(new OnRegisterMethod(
pkg + "/" + cls.getName().substring(0, cls.getName().length() - 6),
onRegisterMethod.name));
}
} catch (IOException ex) {
}
}
private static class AnnotationDetector extends ClassVisitor {
private boolean isAnnotated = false;
private List<MethodAnnotationDetector> onRegister = new ArrayList<MethodAnnotationDetector>();
public AnnotationDetector() {
super(Opcodes.ASM4);
}
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
if (desc.equals("Lstanhebben/zenscript/annotations/ZenExpansion;")) {
isAnnotated = true;
} else if (desc.equals("Lstanhebben/zenscript/annotations/ZenClass;")) {
isAnnotated = true;
} else if (desc.equals("Lminetweaker/annotations/BracketHandler;")) {
isAnnotated = true;
}
return super.visitAnnotation(desc, visible);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
return new MethodAnnotationDetector(this, name, desc);
}
}
private static class MethodAnnotationDetector extends MethodVisitor {
private final AnnotationDetector detector;
private final String name;
private final String desc;
public MethodAnnotationDetector(AnnotationDetector detector, String name, String desc) {
super(Opcodes.ASM4);
this.detector = detector;
this.name = name;
this.desc = desc;
}
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
if (desc.equals("Lminetweaker/annotations/OnRegister;")) {
if (this.desc.equals("()V")) {
detector.onRegister.add(this);
} else {
throw new RuntimeException("OnRegister annotation must be used on a static method without arguments or return value");
}
}
return super.visitAnnotation(desc, visible);
}
}
private static class OnRegisterMethod {
private final String className;
private final String methodName;
public OnRegisterMethod(String className, String methodName) {
this.className = className;
this.methodName = methodName;
}
}
}
@@ -1,15 +0,0 @@
package stanhebben.zenscript.annotations;
/**
* Used to indicate comparison types.
*
* @author Stan Hebben
*/
public enum CompareType {
LT,
GT,
EQ,
NE,
LE,
GE
}
@@ -1,17 +0,0 @@
package stanhebben.zenscript.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Makes a class implementing List expose itself as iterable over keys and values.
*
* @author Stan Hebben
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface IterableList {
String value();
}
@@ -1,18 +0,0 @@
package stanhebben.zenscript.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Makes a class implementing Map expose itself as iterable over keys and values.
*
* @author Stan Hebben
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface IterableMap {
String key();
String value();
}
@@ -1,18 +0,0 @@
package stanhebben.zenscript.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Indicates a simple iterable. Annotated class must implement the iterable
* interface.
*
* @author Stan Hebben
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface IterableSimple {
String value();
}
@@ -1,17 +0,0 @@
package stanhebben.zenscript.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Indicates that the given method parameter cannot be null.
*
* @author Stan Hebben
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface NotNull {
}
@@ -1,28 +0,0 @@
package stanhebben.zenscript.annotations;
/**
* Enum used to indicate operator type.
*
* @author Stan Hebben
*/
public enum OperatorType {
ADD,
SUB,
MUL,
DIV,
MOD,
CAT,
OR,
AND,
XOR,
NEG,
NOT,
INDEXSET,
INDEXGET,
RANGE,
CONTAINS,
COMPARE,
MEMBERGETTER,
MEMBERSETTER,
EQUALS
}
@@ -1,19 +0,0 @@
package stanhebben.zenscript.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Denotes that this parameter is optional. Inside the script, this parameter
* may be omitted, in which case it is automatically filled with the default
* value of that parameter type (false, null or 0). Invalid for @NonNull type.
*
* @author Stanneke
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface Optional {
}
@@ -1,21 +0,0 @@
package stanhebben.zenscript.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Denotes a caster. Casters are capable of converting one type into another.
* They implement the 'as' operator.
*
* For a native class, no arguments are provided. For an expansion method, the
* argument is the source value.
*
* @author Stan Hebben
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ZenCaster {
}
@@ -1,24 +0,0 @@
package stanhebben.zenscript.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Exposes this class to ZenScript. The class can then be imported and accessed
* into any script.
*
* @author Stan Hebben
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface ZenClass {
/**
* Contains the class' package and name. If omitted, the java package and
* name will be used.
*
* @return
*/
String value() default "";
}
@@ -1,34 +0,0 @@
package stanhebben.zenscript.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Indicates that the given class contains an expansion for a certain type.
* The expansions themselves are given through annotated static methods.
*
* @author Stan Hebben
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface ZenExpansion {
/**
* Contains the type of the annotated class. May be any kind of ZenScript type.
*
* Examples:
* <ul>
* <li>int</li>
* <li>my.package.MyClass</li>
* <li>my.package.MyClass[]</li>
* <li>any</li>
* <li>any[]</li>
* <li>any[any]</li>
* </li>
* </ul>
*
* @return expanded type
*/
public String value();
}
@@ -1,26 +0,0 @@
package stanhebben.zenscript.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Indicates a getter. Will make the given method accessible as getter, that is,
* it's called when value.name is being used.
*
* For a native class, no arguments are provided. For an expansion, a single
* argument with the source value is provided.
*
* @author Stan Hebben
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ZenGetter {
/**
* Getter name. If omitted, the method name will be used as value name.
*
* @return getter name
*/
String value() default "";
}
@@ -1,23 +0,0 @@
package stanhebben.zenscript.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Indicates a member getter. A member getter is a special kind of operator which
* is a fallback if a member could not be resolved. Can be used to make contents
* available as if they were members.
*
* If this method is a native class, it accepts a single string parameter with
* the member name. If this method is an expansion method, it accepts the source
* value and the member name.
*
* @author Stan Hebben
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ZenMemberGetter {
}
@@ -1,23 +0,0 @@
package stanhebben.zenscript.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Used to indicate a member setter. Companion to member getters, but allow
* setting contents of this object as if they were members.
*
* If this method is a native class, it accepts a string parameter with
* the member name and a second parameter with the value. If this method is an
* expansion method, it accepts the source value, the member name and the value
* to be assigned.
*
* @author Stan Hebben
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ZenMemberSetter {
}
@@ -1,26 +0,0 @@
package stanhebben.zenscript.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Used to indicate an exposed method.
*
* If this method is part of a native class, it will simply accept the parameters
* as provided. If it is part of an expansion method, it will also accept the
* instance value as first parameter.
*
* @author Stan Hebben
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ZenMethod {
/**
* Method name. If omitted, the original method name will be used.
*
* @return method name
*/
public String value() default "";
}
@@ -1,29 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package stanhebben.zenscript.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Used to indicate static methods for expansions. For native classes, use ZenMethod
* instead on a static method.
*
* @author Stan Hebben
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ZenMethodStatic {
/**
* Method name. If omitted, the annotated method name will be used.
*
* @return method name
*/
public String value() default "";
}
@@ -1,22 +0,0 @@
package stanhebben.zenscript.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Used to indicate an operator. The arguments depend on the kind of operator.
*
* @author Stan Hebben
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ZenOperator {
/**
* Operator type for this operator.
*
* @return operator type
*/
OperatorType value();
}
@@ -1,26 +0,0 @@
package stanhebben.zenscript.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Used to annotate setters. Will make the given method accessible as setter, that is,
* it's called when value.name is being assinged a value.
*
* For a native class, a single argument with the assinged value is provided.
* For an expansion, the target object and assigned value are provided.
*
* @author Stan Hebben
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ZenSetter {
/**
* Setter name. If omitted, the method name is used as property name.
*
* @return setter name
*/
String value() default "";
}
@@ -1,25 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package stanhebben.zenscript.docs;
import com.sun.javadoc.MethodDoc;
/**
*
* @author Stan
*/
public class ZenCasterDoc {
private final MethodDoc method;
public ZenCasterDoc(MethodDoc method) {
this.method = method;
}
public MethodDoc getMethod() {
return method;
}
}
@@ -1,43 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package stanhebben.zenscript.docs;
import com.sun.javadoc.ClassDoc;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author Stan
*/
public class ZenClassDoc {
private final ClassDoc cls;
private final String name;
private final List<ZenExpansionDoc> expansions;
public ZenClassDoc(ClassDoc cls, String name) {
this.cls = cls;
this.name = name;
expansions = new ArrayList<ZenExpansionDoc>();
}
public String getName() {
return name;
}
public ClassDoc getDoc() {
return cls;
}
public void addExpansion(ZenExpansionDoc expansion) {
expansions.add(expansion);
}
public List<ZenExpansionDoc> getExpansions() {
return expansions;
}
}
@@ -1,31 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package stanhebben.zenscript.docs;
import com.sun.javadoc.ClassDoc;
/**
*
* @author Stan
*/
public class ZenExpansionDoc {
private final ClassDoc cls;
private final String type;
public ZenExpansionDoc(ClassDoc cls, String type) {
this.cls = cls;
this.type = type;
}
public String getType() {
return type;
}
public ClassDoc getDoc() {
return cls;
}
}
@@ -1,38 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package stanhebben.zenscript.docs;
import com.sun.javadoc.MethodDoc;
import java.util.List;
/**
*
* @author Stan
*/
public class ZenMethodDoc {
private final String name;
private final MethodDoc method;
private final List<ZenParameterDoc> parameters;
public ZenMethodDoc(String name, MethodDoc method, List<ZenParameterDoc> parameters) {
this.name = name;
this.method = method;
this.parameters = parameters;
}
public String getName() {
return name;
}
public MethodDoc getDoc() {
return method;
}
public List<ZenParameterDoc> getParameters() {
return parameters;
}
}
@@ -1,70 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package stanhebben.zenscript.docs;
import com.sun.javadoc.MethodDoc;
import com.sun.javadoc.Type;
import java.util.HashMap;
import java.util.Map;
import static stanhebben.zenscript.docs.ZenOperatorDocType.*;
/**
*
* @author Stan
*/
public class ZenOperatorDoc {
private static Map<String, ZenOperatorDocType> TYPES;
static {
TYPES = new HashMap<String, ZenOperatorDocType>();
TYPES.put("stanhebben.zenscript.annotations.OperatorType.ADD", ADD);
TYPES.put("stanhebben.zenscript.annotations.OperatorType.SUB", SUB);
TYPES.put("stanhebben.zenscript.annotations.OperatorType.MUL", MUL);
TYPES.put("stanhebben.zenscript.annotations.OperatorType.DIV", DIV);
TYPES.put("stanhebben.zenscript.annotations.OperatorType.MOD", MOD);
TYPES.put("stanhebben.zenscript.annotations.OperatorType.CAT", CAT);
TYPES.put("stanhebben.zenscript.annotations.OperatorType.OR", OR);
TYPES.put("stanhebben.zenscript.annotations.OperatorType.AND", AND);
TYPES.put("stanhebben.zenscript.annotations.OperatorType.XOR", XOR);
TYPES.put("stanhebben.zenscript.annotations.OperatorType.NEG", NEG);
TYPES.put("stanhebben.zenscript.annotations.OperatorType.NOT", NOT);
TYPES.put("stanhebben.zenscript.annotations.OperatorType.INDEXSET", INDEXSET);
TYPES.put("stanhebben.zenscript.annotations.OperatorType.INDEXGET", INDEXGET);
TYPES.put("stanhebben.zenscript.annotations.OperatorType.RANGE", RANGE);
TYPES.put("stanhebben.zenscript.annotations.OperatorType.CONTAINS", CONTAINS);
TYPES.put("stanhebben.zenscript.annotations.OperatorType.COMPARE", COMPARE);
TYPES.put("stanhebben.zenscript.annotations.OperatorType.MEMBERGETTER", MEMBERGETTER);
TYPES.put("stanhebben.zenscript.annotations.OperatorType.MEMBERSETTER", MEMBERSETTER);
TYPES.put("stanhebben.zenscript.annotations.OperatorType.EQUALS", EQUALS);
}
private final String operator;
private final MethodDoc method;
private final Type[] types;
public ZenOperatorDoc(String operator, MethodDoc method, Type[] types) {
this.operator = operator;
this.method = method;
this.types = types;
}
public String getOperator() {
return operator;
}
public Type[] getTypes() {
return types;
}
public ZenOperatorDocType getOperatorType() {
return TYPES.get(operator);
}
public MethodDoc getMethod() {
return method;
}
}
@@ -1,43 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package stanhebben.zenscript.docs;
/**
*
* @author Stan
*/
public enum ZenOperatorDocType {
ADD("+ %s"),
SUB("- %s"),
MUL("* %s"),
DIV("/ %s"),
MOD("%% %s"),
CAT("~ %s"),
OR("| %s"),
AND("& %s"),
XOR("^ %s"),
NEG("-"),
NOT("~"),
INDEXSET("[%s] = %s"),
INDEXGET("[%s]"),
RANGE(".. %s"),
CONTAINS("%s in"),
COMPARE("compareTo(%s)"),
MEMBERGETTER(".member"),
MEMBERSETTER(".member = %s"),
EQUALS("== %s");
private final String pattern;
private ZenOperatorDocType(String pattern) {
this.pattern = pattern;
}
public String fill(String... contents) {
return String.format(pattern, (Object[]) contents);
}
}
@@ -1,45 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package stanhebben.zenscript.docs;
import com.sun.javadoc.AnnotationDesc;
import com.sun.javadoc.Parameter;
import com.sun.javadoc.Type;
/**
*
* @author Stan
*/
public class ZenParameterDoc {
private boolean optional;
private final String name;
private final Type type;
public ZenParameterDoc(Parameter parameter) {
optional = false;
name = parameter.name();
type = parameter.type();
for (AnnotationDesc annotation : parameter.annotations()) {
if (annotation.annotationType().qualifiedName().equals("stanhebben.zenscript.annotations.Optional")) {
optional = true;
}
}
}
public boolean isOptional() {
return optional;
}
public String getName() {
return name;
}
public Type getType() {
return type;
}
}
@@ -1,58 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package stanhebben.zenscript.docs;
import com.sun.javadoc.Type;
/**
*
* @author Stan
*/
public class ZenPropertyDoc {
private Type type;
private String name;
private boolean canGet;
private boolean canSet;
private String[] comment;
public ZenPropertyDoc(String name, Type type) {
this.type = type;
this.name = name;
}
public Type getType() {
return type;
}
public String getName() {
return name;
}
public boolean isCanGet() {
return canGet;
}
public void setCanGet(boolean canGet) {
this.canGet = canGet;
}
public boolean isCanSet() {
return canSet;
}
public void setCanSet(boolean canSet) {
this.canSet = canSet;
}
public String[] getComment() {
return comment;
}
public void setComment(String[] comment) {
this.comment = comment;
}
}
@@ -1,856 +0,0 @@
package stanhebben.zenscript.docs;
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
import com.sun.javadoc.AnnotationDesc;
import com.sun.javadoc.ClassDoc;
import com.sun.javadoc.DocErrorReporter;
import com.sun.javadoc.LanguageVersion;
import com.sun.javadoc.MethodDoc;
import com.sun.javadoc.Parameter;
import com.sun.javadoc.RootDoc;
import com.sun.javadoc.Type;
import com.sun.tools.doclets.standard.Standard;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import stanhebben.zenscript.util.StringUtil;
/**
*
* Example usage: (from minetweaker API source dir):
*
* javadoc -doclet stanhebben.zenscript.docs.ZenScriptDoclet -docletpath ..\..\..\..\ZenScript\build\classes\main -cp ..\..\..\..\ZenScript\build\libs\ZenScript.jar -sourcepath . -subpackages minetweaker
*
* @author Stan Hebben
*/
public class ZenScriptDoclet extends Standard {
public static boolean validOptions(String[][] strings, DocErrorReporter der) {
return true;
}
public static int optionLength(String option) {
if(option.equals("-baseurl")) {
return 2;
}
return Standard.optionLength(option);
}
public static boolean start(RootDoc root) {
File output = new File("zendoc");
String baseUrl = "/doc/";
for (String[] options : root.options()) {
//System.out.println(Arrays.toString(options));
if (options[0].equals("-d")) {
output = new File(options[1]);
} else if (options[0].equals("-baseurl")) {
baseUrl = options[1];
}
}
ClassDoc[] classes = root.classes();
List<ZenClassDoc> documentedClasses = new ArrayList<ZenClassDoc>();
List<ZenExpansionDoc> expansionClasses = new ArrayList<ZenExpansionDoc>();
for (int i = 0; i < classes.length; ++i) {
ClassDoc cls = classes[i];
for (AnnotationDesc annotation : cls.annotations()) {
//String fullName = annotation.annotationType().containingPackage().name() + '.' + annotation.annotationType().name();
String fullName = annotation.annotationType().qualifiedName();
if (fullName.equals("stanhebben.zenscript.annotations.ZenClass")) {
documentedClasses.add(new ZenClassDoc(cls, (String) (annotation.elementValues()[0].value().value())));
} else if (fullName.equals("stanhebben.zenscript.annotations.ZenExpansion")) {
expansionClasses.add(new ZenExpansionDoc(cls, (String) (annotation.elementValues()[0].value().value())));
}
}
}
Map<String, ZenClassDoc> classesByName = new HashMap<String, ZenClassDoc>();
Map<String, ZenClassDoc> classesByJavaName = new HashMap<String, ZenClassDoc>();
for (ZenClassDoc documentedClass : documentedClasses) {
classesByName.put(documentedClass.getName(), documentedClass);
classesByJavaName.put(documentedClass.getDoc().qualifiedName(), documentedClass);
}
for (ZenExpansionDoc expansion : expansionClasses) {
if (classesByName.containsKey(expansion.getType())) {
classesByName.get(expansion.getType()).addExpansion(expansion);
} else {
if (expansion.getType().endsWith("]")) {
String baseName = expansion.getType().substring(0, expansion.getType().lastIndexOf('['));
if (classesByName.containsKey(baseName)) {
classesByName.get(baseName).addExpansion(expansion);
}
}
}
}
System.out.println("Number of classes to document: " + classesByName.size());
System.out.println("Output directory: " + output);
if (!output.exists()) output.mkdirs();
String packageList = buildPackageList(documentedClasses, baseUrl);
for (ZenClassDoc doc : classesByName.values()) {
try {
File outputDoc = new File(output, doc.getName().replace('.', '/') + ".html");
File outputDocParent = outputDoc.getParentFile();
if (!outputDocParent.exists()) outputDocParent.mkdirs();
Writer writer = new BufferedWriter(new FileWriter(outputDoc));
String simpleName = doc.getName().substring(doc.getName().lastIndexOf('.') + 1);
writer.append("<!DOCTYPE html>");
writer.append("<html><head>");
writer.append("<title>ZenDoc : " + simpleName + "</title>");
writer.append("<link rel=\"stylesheet\" href=\"/css/bootstrap.min.css\" />");
writer.append("<link rel=\"stylesheet\" href=\"/css/bootstrap-theme.css\" />");
writer.append("<link rel=\"stylesheet\" href=\"/css/font-awesome.min.css\" />");
writer.append("</head><body>");
writer.append("<div class=\"container\"><div class=\"row\">");
writer.append(packageList);
writer.append("<div class=\"col-md-9\">");
String pkgName = doc.getName().substring(0, doc.getName().lastIndexOf('.'));
writer.append("<div class=\"class-package-name\">");
writer.append(pkgName);
writer.append("</div>");
// output class or interface contents
writer.append("<h1>");
if (doc.getDoc().isInterface()) {
writer.append("Interface ");
} else {
writer.append("Class ");
}
writer.append(doc.getDoc().name()).append("</h1>");
if (doc.getDoc().interfaces().length > 0) {
writer.append("<div class=\"implemented-interfaces\">implements ");
boolean first = true;
for (Type itype : doc.getDoc().interfaceTypes()) {
if (first) {
first = false;
} else {
writer.append(", ");
}
outputType(writer, itype, classesByJavaName, baseUrl);
}
writer.append("</div>");
}
writer.append("<hr />");
writer.append("<div class=\"documentation-class\">");
for (String p : StringUtil.splitParagraphs(doc.getDoc().commentText())) {
writer.append("<p>");
writer.append(p);
writer.append("</p>");
}
writer.append("</div>");
if (doc.getDoc().isInterface() && doc.getDoc().methods().length == 1) {
// functional interface
writer.append("<h2>Functional interface</h2>");
MethodDoc method = doc.getDoc().methods()[0];
writer.append("<div class=\"functional-interface-signature\">");
writer.append("function (");
boolean first = true;
for (Parameter parameter : method.parameters()) {
if (first) {
first = false;
} else {
writer.append(", ");
}
ZenParameterDoc paramdoc = new ZenParameterDoc(parameter);
writer.append(paramdoc.getName());
writer.append(" as ");
outputType(writer, paramdoc.getType(), classesByJavaName, baseUrl);
}
writer.append(") as ");
outputType(writer, method.returnType(), classesByJavaName, baseUrl);
writer.append("</div>");
String[] comment = StringUtil.splitParagraphs(method.commentText());
for (String line : comment) {
writer.append("<p>");
writer.append(line);
writer.append("</p>");
}
} else {
writer.append("<h2>Member Overview</h2>");
// collect members
LinkedHashMap<String, ZenPropertyDoc> instanceProperties = new LinkedHashMap<String, ZenPropertyDoc>();
LinkedHashMap<String, ZenPropertyDoc> staticProperties = new LinkedHashMap<String, ZenPropertyDoc>();
List<ZenMethodDoc> instanceMethods = new ArrayList<ZenMethodDoc>();
List<ZenMethodDoc> staticMethods = new ArrayList<ZenMethodDoc>();
List<ZenOperatorDoc> operators = new ArrayList<ZenOperatorDoc>();
List<ZenCasterDoc> casters = new ArrayList<ZenCasterDoc>();
for (MethodDoc method : doc.getDoc().methods()) {
for (AnnotationDesc annotation : method.annotations()) {
String fullName = annotation.annotationType().qualifiedName();
if (fullName.equals("stanhebben.zenscript.annotations.ZenMethod")
|| fullName.equals("stanhebben.zenscript.annotations.ZenMethodStatic")) {
String name = annotation.elementValues().length > 0
? (String) (annotation.elementValues()[0].value().value())
: "";
if (name.length() == 0) {
name = method.name();
}
List<ZenParameterDoc> parameters = new ArrayList<ZenParameterDoc>();
for (Parameter parameter : method.parameters()) {
parameters.add(new ZenParameterDoc(parameter));
}
if (method.isStatic()) {
staticMethods.add(new ZenMethodDoc(name, method, parameters));
} else {
instanceMethods.add(new ZenMethodDoc(name, method, parameters));
}
} else if (fullName.equals("stanhebben.zenscript.annotations.ZenGetter")) {
String name = annotation.elementValues().length > 0
? (String) (annotation.elementValues()[0].value().value())
: "";
if (name.length() == 0) {
name = method.name();
}
Type type = method.returnType();
String[] comment = StringUtil.splitParagraphs(method.commentText());
if (!method.isStatic()) {
if (instanceProperties.containsKey(name)) {
ZenPropertyDoc property = instanceProperties.get(name);
property.setCanGet(true);
property.setComment(comment);
} else {
ZenPropertyDoc property = new ZenPropertyDoc(name, type);
property.setCanGet(true);
property.setComment(comment);
instanceProperties.put(name, property);
}
} else {
if (staticProperties.containsKey(name)) {
ZenPropertyDoc property = staticProperties.get(name);
property.setCanGet(true);
property.setComment(comment);
} else {
ZenPropertyDoc property = new ZenPropertyDoc(name, type);
property.setCanGet(true);
property.setComment(comment);
staticProperties.put(name, property);
}
}
} else if (fullName.equals("stanhebben.zenscript.annotations.ZenSetter")) {
String name = annotation.elementValues().length > 0
? (String) (annotation.elementValues()[0].value().value())
: "";
if (name.length() == 0) {
name = method.name();
}
Type type = method.parameters()[0].type();
String[] comment = StringUtil.splitParagraphs(method.commentText());
if (!method.isStatic()) {
if (instanceProperties.containsKey(name)) {
ZenPropertyDoc property = instanceProperties.get(name);
property.setCanSet(true);
} else {
ZenPropertyDoc property = new ZenPropertyDoc(name, type);
property.setCanGet(true);
property.setComment(comment);
instanceProperties.put(name, property);
}
} else {
if (staticProperties.containsKey(name)) {
ZenPropertyDoc property = staticProperties.get(name);
property.setCanSet(true);
} else {
ZenPropertyDoc property = new ZenPropertyDoc(name, type);
property.setCanGet(true);
property.setComment(comment);
staticProperties.put(name, property);
}
}
} else if (fullName.equals("stanhebben.zenscript.annotations.ZenOperator")) {
String operator = annotation.elementValues()[0].value().value().toString();
Type[] parameterTypes = new Type[method.parameters().length];
for (int i = 0; i < method.parameters().length; i++) {
parameterTypes[i] = method.parameters()[i].type();
}
operators.add(new ZenOperatorDoc(operator, method, parameterTypes));
} else if (fullName.equals("stanhebben.zenscript.annotations.ZenCaster")) {
casters.add(new ZenCasterDoc(method));
}
}
}
for (ZenExpansionDoc expansion : doc.getExpansions()) {
for (MethodDoc method : expansion.getDoc().methods()) {
for (AnnotationDesc annotation : method.annotations()) {
String fullName = annotation.annotationType().qualifiedName();
if (fullName.equals("stanhebben.zenscript.annotations.ZenMethod")
|| fullName.equals("stanhebben.zenscript.annotations.ZenMethodStatic")) {
String name = annotation.elementValues().length > 0
? (String) (annotation.elementValues()[0].value().value())
: "";
if (name.length() == 0) {
name = method.name();
}
List<ZenParameterDoc> parameters = new ArrayList<ZenParameterDoc>();
for (Parameter parameter : method.parameters()) {
parameters.add(new ZenParameterDoc(parameter));
}
if (fullName.equals("stanhebben.zenscript.annotations.ZenMethodStatic")) {
staticMethods.add(new ZenMethodDoc(name, method, parameters));
} else {
instanceMethods.add(new ZenMethodDoc(name, method, parameters.subList(1, parameters.size())));
}
} else if (fullName.equals("stanhebben.zenscript.annotations.ZenGetter")) {
String name = annotation.elementValues().length > 0
? (String) (annotation.elementValues()[0].value().value())
: "";
if (name.length() == 0) {
name = method.name();
}
Type type = method.returnType();
String[] comment = StringUtil.splitParagraphs(method.commentText());
if (!method.isStatic()) {
if (instanceProperties.containsKey(name)) {
ZenPropertyDoc property = instanceProperties.get(name);
property.setCanGet(true);
property.setComment(comment);
} else {
ZenPropertyDoc property = new ZenPropertyDoc(name, type);
property.setCanGet(true);
property.setComment(comment);
instanceProperties.put(name, property);
}
} else {
if (staticProperties.containsKey(name)) {
ZenPropertyDoc property = staticProperties.get(name);
property.setCanGet(true);
property.setComment(comment);
} else {
ZenPropertyDoc property = new ZenPropertyDoc(name, type);
property.setCanGet(true);
property.setComment(comment);
staticProperties.put(name, property);
}
}
} else if (fullName.equals("stanhebben.zenscript.annotations.ZenSetter")) {
String name = annotation.elementValues().length > 0
? (String) (annotation.elementValues()[0].value().value())
: "";
if (name.length() == 0) {
name = method.name();
}
Type type = method.parameters()[1].type();
String[] comment = StringUtil.splitParagraphs(method.commentText());
if (!method.isStatic()) {
if (instanceProperties.containsKey(name)) {
ZenPropertyDoc property = instanceProperties.get(name);
property.setCanSet(true);
} else {
ZenPropertyDoc property = new ZenPropertyDoc(name, type);
property.setCanGet(true);
property.setComment(comment);
instanceProperties.put(name, property);
}
} else {
if (staticProperties.containsKey(name)) {
ZenPropertyDoc property = staticProperties.get(name);
property.setCanSet(true);
} else {
ZenPropertyDoc property = new ZenPropertyDoc(name, type);
property.setCanGet(true);
property.setComment(comment);
staticProperties.put(name, property);
}
}
} else if (fullName.equals("stanhebben.zenscript.annotations.ZenOperator")) {
String operator = annotation.elementValues()[0].value().value().toString();
Type[] parameterTypes = new Type[method.parameters().length - 1];
for (int i = 1; i < method.parameters().length; i++) {
parameterTypes[i - 1] = method.parameters()[i].type();
}
operators.add(new ZenOperatorDoc(operator, method, parameterTypes));
} else if (fullName.equals("stanhebben.zenscript.annotations.ZenCaster")) {
casters.add(new ZenCasterDoc(method));
}
}
}
}
if (!staticProperties.isEmpty()) {
writer.append("<div class=\"panel panel-info panel-memberlist\">");
writer.append("<div class=\"panel-heading\">Static Properties</div>");
writer.append("<div class=\"panel-body\">");
writer.append("<table class=\"table table-properties table-bordered\"><tbody>");
String[] names = new String[staticProperties.size()];
int namei = 0;
for (String name : staticProperties.keySet()) {
names[namei++] = name;
}
Arrays.sort(names);
for (String name : names) {
ZenPropertyDoc property = staticProperties.get(name);
writer.append("<tr>");
writer.append("<td class=\"property-type\">");
outputType(writer, property.getType(), classesByJavaName, baseUrl);
writer.append("</td>");
writer.append("<td>");
writer.append("<div class=\"property-name\">");
if (!property.isCanSet()) writer.append("<span class=\"fa fa-lock\" style=\"color: #ccc;\" title=\"cannot be set\"></span> ");
writer.append("<a href=\"#property-staticvalue\">")
.append(property.getName())
.append("</a></div>");
if (property.getComment() != null && property.getComment().length > 0) {
writer.append("<div class=\"property-intro\">")
.append(property.getComment()[0])
.append("</div>");
}
writer.append("</td></tr>");
}
writer.append("</tbody></table></div></div>");
}
if (!instanceProperties.isEmpty()) {
writer.append("<div class=\"panel panel-info panel-memberlist\">");
writer.append("<div class=\"panel-heading\">Properties</div>");
writer.append("<div class=\"panel-body\">");
writer.append("<table class=\"table table-properties table-bordered\"><tbody>");
String[] names = new String[instanceProperties.size()];
int namei = 0;
for (String name : instanceProperties.keySet()) {
names[namei++] = name;
}
Arrays.sort(names);
for (String name : names) {
ZenPropertyDoc property = instanceProperties.get(name);
writer.append("<tr>");
writer.append("<td class=\"property-type\">");
outputType(writer, property.getType(), classesByJavaName, baseUrl);
writer.append("</td>");
writer.append("<td>");
writer.append("<div class=\"property-name\">");
if (!property.isCanSet()) writer.append("<span class=\"fa fa-lock\" style=\"color: #ccc;\" title=\"cannot be set\"></span> ");
writer.append("<a href=\"#property-staticvalue\">")
.append(property.getName())
.append("</a></div>");
if (property.getComment() != null && property.getComment().length > 0) {
writer.append("<div class=\"property-intro\">")
.append(property.getComment()[0])
.append("</div>");
}
writer.append("</td></tr>");
}
writer.append("</tbody></table></div></div>");
}
if (!staticMethods.isEmpty()) {
writer.append("<div class=\"panel panel-info panel-memberlist\">");
writer.append("<div class=\"panel-heading\">Static Methods</div>");
writer.append("<div class=\"panel-body\">");
writer.append("<table class=\"table table-properties table-bordered\"><tbody>");
for (ZenMethodDoc method : staticMethods) {
writer.append("<tr>");
writer.append("<td class=\"property-type\">");
outputType(writer, method.getDoc().returnType(), classesByJavaName, baseUrl);
writer.append("</td>");
writer.append("<td>");
writer.append("<div class=\"property-name\">");
writer.append("<a href=\"#property-staticvalue\">")
.append(method.getName())
.append("</a>(");
boolean first = true;
for (ZenParameterDoc param : method.getParameters()) {
if (param.isOptional()) writer.append("<span class=\"param-optional\">");
if (first) {
first = false;
} else {
writer.append(", ");
}
writer.append(param.getName());
writer.append(" as ");
outputType(writer, param.getType(), classesByJavaName, baseUrl);
}
writer.append(")</div>");
String[] comment = StringUtil.splitParagraphs(method.getDoc().commentText());
if (comment.length > 0) {
writer.append("<div class=\"property-intro\">")
.append(comment[0])
.append("</div>");
}
writer.append("</td></tr>");
}
writer.append("</tbody></table></div></div>");
}
if (!instanceMethods.isEmpty()) {
writer.append("<div class=\"panel panel-info panel-memberlist\">");
writer.append("<div class=\"panel-heading\">Methods</div>");
writer.append("<div class=\"panel-body\">");
writer.append("<table class=\"table table-properties table-bordered\"><tbody>");
for (ZenMethodDoc method : instanceMethods) {
writer.append("<tr>");
writer.append("<td class=\"property-type\">");
outputType(writer, method.getDoc().returnType(), classesByJavaName, baseUrl);
writer.append("</td>");
writer.append("<td>");
writer.append("<div class=\"property-name\">");
writer.append("<a href=\"#property-staticvalue\">")
.append(method.getName())
.append("</a>(");
boolean first = true;
for (ZenParameterDoc param : method.getParameters()) {
if (param.isOptional()) writer.append("<span class=\"param-optional\">");
if (first) {
first = false;
} else {
writer.append(", ");
}
writer.append(param.getName());
writer.append(" as ");
outputType(writer, param.getType(), classesByJavaName, baseUrl);
}
writer.append(")</div>");
String[] comment = StringUtil.splitParagraphs(method.getDoc().commentText());
if (comment.length > 0) {
writer.append("<div class=\"property-intro\">")
.append(comment[0])
.append("</div>");
}
writer.append("</td></tr>");
}
writer.append("</tbody></table></div></div>");
}
if (!operators.isEmpty()) {
writer.append("<div class=\"panel panel-info panel-memberlist\">");
writer.append("<div class=\"panel-heading\">Operators</div>");
writer.append("<div class=\"panel-body\">");
writer.append("<table class=\"table table-properties table-bordered\"><tbody>");
for (ZenOperatorDoc operator : operators) {
writer.append("<tr>");
writer.append("<td>");
writer.append("<div class=\"property-name\">");
/*writer.append("as <a href=\"#property-staticvalue\">");
outputTypeRaw(writer, caster.getMethod().returnType(), classesByJavaName);
writer.append("</a></div>");*/
String[] types = new String[operator.getTypes().length];
for (int i = 0; i < types.length; i++) {
types[i] = outputTypeString(operator.getTypes()[i], classesByJavaName, baseUrl);
}
writer.append(operator.getOperatorType().fill(types));
String[] comment = StringUtil.splitParagraphs(operator.getMethod().commentText());
if (comment.length > 0) {
writer.append("<div class=\"property-intro\">")
.append(comment[0])
.append("</div>");
}
writer.append("</td></tr>");
}
writer.append("</tbody></table></div></div>");
}
if (!casters.isEmpty()) {
writer.append("<div class=\"panel panel-info panel-memberlist\">");
writer.append("<div class=\"panel-heading\">Casters</div>");
writer.append("<div class=\"panel-body\">");
writer.append("<table class=\"table table-properties table-bordered\"><tbody>");
for (ZenCasterDoc caster : casters) {
writer.append("<tr>");
writer.append("<td>");
writer.append("<div class=\"property-name\">");
writer.append("as <a href=\"#property-staticvalue\">");
outputTypeRaw(writer, caster.getMethod().returnType(), classesByJavaName);
writer.append("</a></div>");
String[] comment = StringUtil.splitParagraphs(caster.getMethod().commentText());
if (comment.length > 0) {
writer.append("<div class=\"property-intro\">")
.append(comment[0])
.append("</div>");
}
writer.append("</td></tr>");
}
writer.append("</tbody></table></div></div>");
}
}
writer.append("</div></div></div>");
writer.append("<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js\"></script>");
writer.append("<script src=\"/js/bootstrap.min.js\"></script>");
writer.append("<script type=\"application/javascript\">");
writer.append("$('#collapse-");
writer.append(pkgName.replace('.', '-'));
writer.append("').collapse('show');");
writer.append("</script>");
writer.append("</body></html>");
writer.close();
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
return true;
}
/**
* NOTE: Without this method present and returning LanguageVersion.JAVA_1_5,
* Javadoc will not process generics because it assumes LanguageVersion.JAVA_1_1
* @return language version (hard coded to LanguageVersion.JAVA_1_5)
*/
public static LanguageVersion languageVersion() {
return LanguageVersion.JAVA_1_5;
}
private static String buildPackageList(List<ZenClassDoc> classes, String baseurl) {
// collect package list
Map<String, List<ZenClassDoc>> packages = new HashMap<String, List<ZenClassDoc>>();
for (ZenClassDoc cls : classes) {
String pkg = cls.getName().substring(0, cls.getName().lastIndexOf('.'));
if (packages.containsKey(pkg)) {
packages.get(pkg).add(cls);
} else {
ArrayList<ZenClassDoc> classList = new ArrayList<ZenClassDoc>();
classList.add(cls);
packages.put(pkg, classList);
}
}
String[] packageSorted = new String[packages.size()];
int packageIndex = 0;
for (String packageName : packages.keySet()) {
packageSorted[packageIndex++] = packageName;
}
Arrays.sort(packageSorted);
// output data
StringBuilder output = new StringBuilder();
output.append("<div class=\"col-md-3\">");
output.append("<div class=\"panel panel-group\"><div class=\"panel-body\">");
output.append("<div class=\"panel-heading\"><h3>Packages</h3></div>");
output.append("<div class=\"panel-scroll\">");
for (int i = 0; i < packageSorted.length; i++) {
String pkgId = extractId(packageSorted[i]);
String pkgDir = baseurl + packageSorted[i].replace('.', '/');
output.append("<div class=\"panel panel-default\">");
output.append("<div class=\"panel-heading\"><h4 class=\"panel-title package-title\">");
output.append("<a data-toggle=\"collapse\" data-parent=\"#accordion\" href=\"#collapse-")
.append(pkgId)
.append("\"><span class=\"glyphicon glyphicon-th-large\"></span> ")
.append(packageSorted[i])
.append("</a>");
output.append("</h4></div>");
output.append("<div id=\"collapse-")
.append(pkgId)
.append("\" class=\"panel-collapse collapse\">");
output.append("<div class=\"panel-body\">");
// assemble lists
List<String> interfaceNames = new ArrayList<String>();
List<String> classNames = new ArrayList<String>();
for (ZenClassDoc cls : packages.get(packageSorted[i])) {
if (cls.getDoc().isInterface()) {
interfaceNames.add(cls.getDoc().name());
} else {
classNames.add(cls.getDoc().name());
}
}
Collections.sort(interfaceNames);
Collections.sort(classNames);
if (!interfaceNames.isEmpty()) {
output.append("<h4 class=\"interfaces-title\">Interfaces</h4>");
output.append("<table class=\"table table-classes\"><tbody>");
for (String ifaceName : interfaceNames) {
output.append("<tr><td><a href=\"")
.append(pkgDir).append('/').append(ifaceName).append(".html")
.append("\">")
.append(ifaceName)
.append("</a></td></tr>");
}
output.append("</tbody></table>");
}
if (!classNames.isEmpty()) {
output.append("<h4 class=\"classes-title\">Classes</h4>");
output.append("<table class=\"table table-classes\"><tbody>");
for (String className : classNames) {
output.append("<tr><td><a href=\"")
.append(pkgDir).append('/').append(className).append(".html")
.append("\">")
.append(className)
.append("</a></td></tr>");
}
output.append("</tbody></table>");
}
output.append("</div></div></div>");
}
output.append("</div></div></div></div>");
return output.toString();
}
private static String extractId(String pkg) {
return pkg.replace('.', '-');
}
private static void outputType(Writer output, Type type, Map<String, ZenClassDoc> javaClasses, String baseUrl) throws IOException {
if (javaClasses.containsKey(type.qualifiedTypeName())) {
ZenClassDoc doc = javaClasses.get(type.qualifiedTypeName());
output.append("<a href=\"");
output.append(makeLink(doc.getName(), baseUrl));
output.append("\">");
output.append(doc.getName().substring(doc.getName().lastIndexOf('.') + 1));
output.append("</a>");
} else if (type.qualifiedTypeName().equals("java.util.List")) {
Type base = type.asParameterizedType().typeArguments()[0];
outputType(output, base, javaClasses, baseUrl);
output.append("[]");
} else if (type.qualifiedTypeName().equals("java.util.Map")) {
Type key = type.asParameterizedType().typeArguments()[0];
Type value = type.asParameterizedType().typeArguments()[1];
outputType(output, value, javaClasses, baseUrl);
output.append('[');
outputType(output, key, javaClasses, baseUrl);
output.append(']');
} else if (type.qualifiedTypeName().equals("java.lang.String")) {
output.append("string");
} else {
output.append(type.qualifiedTypeName());
}
output.append(type.dimension());
}
private static String outputTypeString(Type type, Map<String, ZenClassDoc> javaClasses, String baseUrl) throws IOException {
StringBuilder result = new StringBuilder();
if (javaClasses.containsKey(type.qualifiedTypeName())) {
ZenClassDoc doc = javaClasses.get(type.qualifiedTypeName());
result.append("<a href=\"");
result.append(makeLink(doc.getName(), baseUrl));
result.append("\">");
result.append(doc.getName().substring(doc.getName().lastIndexOf('.') + 1));
result.append("</a>");
} else if (type.qualifiedTypeName().equals("java.util.List")) {
Type base = type.asParameterizedType().typeArguments()[0];
result.append(outputTypeString(base, javaClasses, baseUrl));
result.append("[]");
} else if (type.qualifiedTypeName().equals("java.util.Map")) {
Type key = type.asParameterizedType().typeArguments()[0];
Type value = type.asParameterizedType().typeArguments()[1];
result.append(outputTypeString(value, javaClasses, baseUrl));
result.append('[');
result.append(outputTypeString(key, javaClasses, baseUrl));
result.append(']');
} else if (type.qualifiedTypeName().equals("java.lang.String")) {
result.append("string");
} else {
result.append(type.qualifiedTypeName());
}
result.append(type.dimension());
return result.toString();
}
private static void outputTypeRaw(Writer output, Type type, Map<String, ZenClassDoc> javaClasses) throws IOException {
if (javaClasses.containsKey(type.qualifiedTypeName())) {
ZenClassDoc doc = javaClasses.get(type.qualifiedTypeName());
output.append(doc.getName().substring(doc.getName().lastIndexOf('.') + 1));
} else if (type.qualifiedTypeName().equals("java.util.List")) {
Type base = type.asParameterizedType().typeArguments()[0];
outputTypeRaw(output, base, javaClasses);
output.append("[]");
} else if (type.qualifiedTypeName().equals("java.util.Map")) {
Type key = type.asParameterizedType().typeArguments()[0];
Type value = type.asParameterizedType().typeArguments()[1];
outputTypeRaw(output, value, javaClasses);
output.append('[');
outputTypeRaw(output, key, javaClasses);
output.append(']');
} else if (type.qualifiedTypeName().equals("java.lang.String")) {
output.append("string");
} else {
output.append(type.qualifiedTypeName());
}
}
private static String makeLink(String className, String baseUrl) {
return baseUrl + className.replace('.', '/') + ".html";
}
}
@@ -1,481 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package stanhebben.zenscript.util;
import java.util.ArrayList;
/**
*
* @author Stanneke
*/
public class StringUtil {
private StringUtil() {}
public static String join(String[] values, String separator) {
StringBuilder result = new StringBuilder();
boolean first = true;
for (String value : values) {
if (first) {
first = false;
} else {
result.append('.');
}
result.append(value);
}
return result.toString();
}
public static String join(Iterable<String> values, String separator) {
StringBuilder result = new StringBuilder();
boolean first = true;
for (String value : values) {
if (first) {
first = false;
} else {
result.append('.');
}
result.append(value);
}
return result.toString();
}
/**
* Splits a string in parts, given a specified delimiter.
*
* @param value string to be split
* @param delimiter delimiter
* @return
*/
public static String[] split(String value, char delimiter) {
if (value == null) return null;
ArrayList<String> result = new ArrayList<String>();
int start = 0;
outer: for (int i = 0; i < value.length(); i++) {
if (value.charAt(i) == delimiter) {
result.add(value.substring(start, i));
start = i + 1;
}
}
result.add(value.substring(start));
return result.toArray(new String[result.size()]);
}
/**
* Processes a doc comment into paragraphs.
*
* @param value input value
* @return output paragraphs
*/
public static String[] splitParagraphs(String value) {
String[] lines = split(value, '\n');
for (int i = 0; i < lines.length; i++) {
lines[i] = lines[i].trim();
}
ArrayList<String> output = new ArrayList<String>();
StringBuilder current = new StringBuilder();
for (int i = 0; i < lines.length; i++) {
if (lines[i].length() == 0) {
if (current.length() > 0) {
output.add(current.toString());
current = new StringBuilder();
}
} else {
current.append(' ').append(lines[i]);
}
}
if (current.length() > 0) {
output.add(current.toString());
}
return output.toArray(new String[output.size()]);
}
// ########################
// ### String utilities ###
// ########################
/**
*
* unescape_perl_string()
*
* Tom Christiansen <tchrist@perl.com> Sun Nov 28 12:55:24 MST 2010
*
* It's completely ridiculous that there's no standard unescape_java_string
* function. Since I have to do the damn thing myself, I might as well make
* it halfway useful by supporting things Java was too stupid to consider in
* strings:
*
* => "?" items are additions to Java string escapes but normal in Java
* regexes
*
* => "!" items are also additions to Java regex escapes
*
* Standard singletons: ?\a ?\e \f \n \r \t
*
* NB: \b is unsupported as backspace so it can pass-through to the regex
* translator untouched; I refuse to make anyone doublebackslash it as
* doublebackslashing is a Java idiocy I desperately wish would die out.
* There are plenty of other ways to write it:
*
* \cH, \12, \012, \x08 \x{8}, \u0008, \U00000008
*
* Octal escapes: \0 \0N \0NN \N \NN \NNN Can range up to !\777 not \377
*
* TODO: add !\o{NNNNN} last Unicode is 4177777 maxint is 37777777777
*
* Control chars: ?\cX Means: ord(X) ^ ord('@')
*
* Old hex escapes: \xXX unbraced must be 2 xdigits
*
* Perl hex escapes: !\x{XXX} braced may be 1-8 xdigits NB: proper Unicode
* never needs more than 6, as highest valid codepoint is 0x10FFFF, not
* maxint 0xFFFFFFFF
*
* Lame Java escape: \[IDIOT JAVA PREPROCESSOR]uXXXX must be exactly 4
* xdigits;
*
* I can't write XXXX in this comment where it belongs because the damned
* Java Preprocessor can't mind its own business. Idiots!
*
* Lame Python escape: !\UXXXXXXXX must be exactly 8 xdigits
*
* TODO: Perl translation escapes: \Q \U \L \E \[IDIOT JAVA PREPROCESSOR]u
* \l These are not so important to cover if you're passing the result to
* Pattern.compile(), since it handles them for you further downstream. Hm,
* what about \[IDIOT JAVA PREPROCESSOR]u?
*
* @param oldstr
* @return
*/
public static String unescapeString(String oldstr) {
if (oldstr.charAt(0) != '"' || oldstr.charAt(oldstr.length() - 1) != '"') {
// TODO: error
//throw new TweakerExecuteException("Not a valid string constant: "
// + oldstr);
}
oldstr = oldstr.substring(1, oldstr.length() - 1);
/*
* In contrast to fixing Java's broken regex charclasses, this one need
* be no bigger, as unescaping shrinks the string here, where in the
* other one, it grows it.
*/
StringBuilder newstr = new StringBuilder(oldstr.length());
boolean saw_backslash = false;
for (int i = 0; i < oldstr.length(); i++) {
int cp = oldstr.codePointAt(i);
if (oldstr.codePointAt(i) > Character.MAX_VALUE) {
i++;
/**** WE HATES UTF-16! WE HATES IT FOREVERSES!!! ****/
}
if (!saw_backslash) {
if (cp == '\\') {
saw_backslash = true;
} else {
newstr.append(Character.toChars(cp));
}
continue; /* switch */
}
if (cp == '\\') {
saw_backslash = false;
newstr.append('\\');
newstr.append('\\');
continue; /* switch */
}
switch (cp) {
case 'r':
newstr.append('\r');
break; /* switch */
case 'n':
newstr.append('\n');
break; /* switch */
case 'f':
newstr.append('\f');
break; /* switch */
/* PASS a \b THROUGH!! */
case 'b':
newstr.append("\\b");
break; /* switch */
case 't':
newstr.append('\t');
break; /* switch */
case 'a':
newstr.append('\007');
break; /* switch */
case 'e':
newstr.append('\033');
break; /* switch */
/*
* A "control" character is what you get when you xor its codepoint
* with '@'==64. This only makes sense for ASCII, and may not yield
* a "control" character after all.
*
* Strange but true: "\c{" is ";", "\c}" is "=", etc.
*/
case 'c': {
if (++i == oldstr.length()) {
// TODO: error
//throw new TweakerExecuteException("trailing \\c");
}
cp = oldstr.codePointAt(i);
/*
* don't need to grok surrogates, as next line blows them up
*/
if (cp > 0x7f) {
// TODO: error
//throw new TweakerExecuteException(
// "expected ASCII after \\c");
}
newstr.append(Character.toChars(cp ^ 64));
break; /* switch */
}
case '8':
case '9':
// TODO: error
//throw new TweakerExecuteException("illegal octal digit");
/* NOTREACHED */
/*
* may be 0 to 2 octal digits following this one so back up one
* for fallthrough to next case; unread this digit and fall
* through to next case.
*/
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
--i;
/* FALLTHROUGH */
/*
* Can have 0, 1, or 2 octal digits following a 0 this permits
* larger values than octal 377, up to octal 777.
*/
case '0': {
if (i + 1 == oldstr.length()) {
/* found \0 at end of string */
newstr.append(Character.toChars(0));
break; /* switch */
}
i++;
int digits = 0;
int j;
for (j = 0; j <= 2; j++) {
if (i + j == oldstr.length()) {
break; /* for */
}
/* safe because will unread surrogate */
int ch = oldstr.charAt(i + j);
if (ch < '0' || ch > '7') {
break; /* for */
}
digits++;
}
if (digits == 0) {
--i;
newstr.append('\0');
break; /* switch */
}
int value = 0;
try {
value = Integer
.parseInt(oldstr.substring(i, i + digits), 8);
} catch (NumberFormatException nfe) {
// TODO: error
//throw new TweakerExecuteException(
// "invalid octal value for \\0 escape");
}
newstr.append(Character.toChars(value));
i += digits - 1;
break; /* switch */
} /* end case '0' */
case 'x': {
if (i + 2 > oldstr.length()) {
// TODO: error
//throw new TweakerExecuteException(
// "string too short for \\x escape");
}
i++;
boolean saw_brace = false;
if (oldstr.charAt(i) == '{') {
/* ^^^^^^ ok to ignore surrogates here */
i++;
saw_brace = true;
}
int j;
for (j = 0; j < 8; j++) {
if (!saw_brace && j == 2) {
break; /* for */
}
/*
* ASCII test also catches surrogates
*/
int ch = oldstr.charAt(i + j);
if (ch > 127) {
// TODO: error
//throw new TweakerExecuteException(
// "illegal non-ASCII hex digit in \\x escape");
}
if (saw_brace && ch == '}') {
break; /* for */
}
if (!((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'))) {
// TODO: error
//throw new TweakerExecuteException(String.format(
// "illegal hex digit #%d '%c' in \\x", ch, ch));
}
}
if (j == 0) {
// TODO: error
//throw new TweakerExecuteException(
// "empty braces in \\x{} escape");
}
int value = 0;
try {
value = Integer.parseInt(oldstr.substring(i, i + j), 16);
} catch (NumberFormatException nfe) {
// TODO: error
//throw new TweakerExecuteException(
// "invalid hex value for \\x escape");
}
newstr.append(Character.toChars(value));
if (saw_brace) {
j++;
}
i += j - 1;
break; /* switch */
}
case 'u': {
if (i + 4 > oldstr.length()) {
// TODO: error
//throw new TweakerExecuteException(
// "string too short for \\u escape");
}
i++;
int j;
for (j = 0; j < 4; j++) {
/* this also handles the surrogate issue */
if (oldstr.charAt(i + j) > 127) {
// TODO: error
//throw new TweakerExecuteException(
// "illegal non-ASCII hex digit in \\u escape");
}
}
int value = 0;
try {
value = Integer.parseInt(oldstr.substring(i, i + j), 16);
} catch (NumberFormatException nfe) {
// TODO: error
//throw new TweakerExecuteException(
// "invalid hex value for \\u escape");
}
newstr.append(Character.toChars(value));
i += j - 1;
break; /* switch */
}
case 'U': {
if (i + 8 > oldstr.length()) {
// TODO: error
//throw new TweakerExecuteException(
// "string too short for \\U escape");
}
i++;
int j;
for (j = 0; j < 8; j++) {
/* this also handles the surrogate issue */
if (oldstr.charAt(i + j) > 127) {
// TODO: error
//throw new TweakerExecuteException(
// "illegal non-ASCII hex digit in \\U escape");
}
}
int value = 0;
try {
value = Integer.parseInt(oldstr.substring(i, i + j), 16);
} catch (NumberFormatException nfe) {
// TODO: error
//throw new TweakerExecuteException(
// "invalid hex value for \\U escape");
}
newstr.append(Character.toChars(value));
i += j - 1;
break; /* switch */
}
default:
newstr.append('\\');
newstr.append(Character.toChars(cp));
/*
* say(String.format(
* "DEFAULT unrecognized escape %c passed through", cp));
*/
break; /* switch */
}
saw_backslash = false;
}
/* weird to leave one at the end */
if (saw_backslash) {
newstr.append('\\');
}
return newstr.toString();
}
/*
* Return a string "U+XX.XXX.XXXX" etc, where each XX set is the xdigits of
* the logical Unicode code point. No bloody brain-damaged UTF-16 surrogate
* crap, just true logical characters.
*/
private static String uniplus(String s) {
if (s.length() == 0) {
return "";
}
/* This is just the minimum; sb will grow as needed. */
StringBuilder sb = new StringBuilder(2 + 3 * s.length());
sb.append("U+");
for (int i = 0; i < s.length(); i++) {
sb.append(String.format("%X", s.codePointAt(i)));
if (s.codePointAt(i) > Character.MAX_VALUE) {
i++;
/**** WE HATES UTF-16! WE HATES IT FOREVERSES!!! ****/
}
if (i + 1 < s.length()) {
sb.append(".");
}
}
return sb.toString();
}
}