diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/AnnotationMirrorUtil.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/AnnotationMirrorUtil.java index 90ac6a62c..7275dc4a5 100644 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/AnnotationMirrorUtil.java +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/AnnotationMirrorUtil.java @@ -22,21 +22,4 @@ public static AnnotationMirror getMirror(Element element, TypeElement typeElemen return getMirror(element, typeElement.getQualifiedName().toString()); } - public static AnnotationMirror getMirror(Element element, Class cls) { - return getMirror(element, cls.getCanonicalName()); - } - - public static String getAnnotationValue(AnnotationMirror annotationMirror, String name) { - return getAnnotationValueObject(annotationMirror, name).toString(); - } - - public static Object getAnnotationValueObject(AnnotationMirror annotationMirror, String name) { - return annotationMirror.getElementValues() - .entrySet() - .stream() - .filter(entry -> entry.getKey().getSimpleName().contentEquals(name)) - .map(entry -> entry.getValue().getValue()) - .findAny() - .orElse(null); - } } diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/ReflectionReader.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/ReflectionReader.java deleted file mode 100644 index 63470b7a8..000000000 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/ReflectionReader.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.blamejared.crafttweaker_annotation_processors.processors; - -import com.blamejared.crafttweaker_annotations.annotations.*; -import org.reflections.*; -import org.reflections.util.*; - -import java.util.*; - -public class ReflectionReader { - private ReflectionReader(){} - - private static Set> scannedClasses = null; - - public static Set> getClassesWithZenWrapper(ClassLoader loader) { - if(scannedClasses == null) { - final ConfigurationBuilder configuration = new ConfigurationBuilder() - .addUrls(ClasspathHelper.forJavaClassPath()) - .addClassLoaders(ClasspathHelper.contextClassLoader(), ClasspathHelper.staticClassLoader(), loader) - .addUrls(ClasspathHelper.forClassLoader()); - scannedClasses = new Reflections(configuration).getTypesAnnotatedWith(ZenWrapper.class, true); - } - - return scannedClasses; - } -} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/CrafttweakerDocumentationPage.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/CrafttweakerDocumentationPage.java deleted file mode 100644 index bad990aac..000000000 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/CrafttweakerDocumentationPage.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.blamejared.crafttweaker_annotation_processors.processors.document; - -import com.blamejared.crafttweaker_annotation_processors.processors.document.documented_class.DocumentedClass; -import com.blamejared.crafttweaker_annotation_processors.processors.document.documented_expansion.DocumentedExpansion; -import org.openzen.zencode.java.ZenCodeType; - -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.TypeElement; -import javax.tools.Diagnostic; -import java.io.File; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -/** - * Anything that can be written to file as a MD page. - * Can be a {@link DocumentedClass} or a {@link DocumentedExpansion} - */ -public abstract class CrafttweakerDocumentationPage { - public static Map knownTypes = new HashMap<>(); - public static Map typesByZSName = new HashMap<>(); - - public static CrafttweakerDocumentationPage convertType(TypeElement element, ProcessingEnvironment environment) { - if (knownTypes.containsKey(element.toString())) { - return knownTypes.get(element.toString()); - } - - final CrafttweakerDocumentationPage documentationPage; - if (element.getAnnotation(ZenCodeType.Name.class) != null) { - documentationPage = DocumentedClass.convertClass(element, environment, false); - } else if (element.getAnnotation(ZenCodeType.Expansion.class) != null) { - documentationPage = DocumentedExpansion.convertExpansion(element, environment, false); - } else { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "@Documented requires either @Expansion or @Name to be set as well!", element); - return null; - } - - if (!knownTypes.containsKey(element.toString())) { - knownTypes.put(element.toString(), documentationPage); - } - - return documentationPage; - } - - public abstract String getDocPath(); - - public abstract void write(File docsDirectory, ProcessingEnvironment environment) throws IOException; - - public abstract String getZSName(); - - public abstract String getDocParamThis(); - - public abstract String getDocumentTitle(); -} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/DocumentProcessor.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/DocumentProcessor.java new file mode 100644 index 000000000..725f439cf --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/DocumentProcessor.java @@ -0,0 +1,116 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.ElementConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.element.KnownElementList; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.mods.KnownModList; +import com.blamejared.crafttweaker_annotation_processors.processors.document.dependencies.DependencyContainer; +import com.blamejared.crafttweaker_annotation_processors.processors.document.dependencies.SingletonDependencyContainer; +import com.blamejared.crafttweaker_annotation_processors.processors.document.file.DocsJsonWriter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.file.PageWriter; +import com.sun.source.util.Trees; +import org.reflections.Reflections; +import org.reflections.util.ClasspathHelper; +import org.reflections.util.ConfigurationBuilder; + +import javax.annotation.processing.*; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.TypeElement; +import javax.lang.model.util.Elements; +import javax.lang.model.util.Types; +import java.io.File; +import java.io.IOException; +import java.util.Set; + +@SupportedAnnotationTypes({"com.blamejared.crafttweaker_annotations.annotations.Document", "net.minecraftforge.fml.common.Mod"}) +@SupportedSourceVersion(SourceVersion.RELEASE_8) +public class DocumentProcessor extends AbstractProcessor { + + private static final File outputDirectory = new File("docsOut"); + + private final DependencyContainer dependencyContainer = new SingletonDependencyContainer(); + private KnownElementList knownElementList; + private KnownModList knownModList; + + @Override + public synchronized void init(ProcessingEnvironment processingEnv) { + super.init(processingEnv); + setupDependencyContainer(processingEnv); + + knownElementList = dependencyContainer.getInstanceOfClass(KnownElementList.class); + knownModList = dependencyContainer.getInstanceOfClass(KnownModList.class); + } + + private void setupDependencyContainer(ProcessingEnvironment processingEnv) { + dependencyContainer.addInstanceAs(dependencyContainer, DependencyContainer.class); + dependencyContainer.addInstanceAs(processingEnv, ProcessingEnvironment.class); + dependencyContainer.addInstanceAs(processingEnv.getMessager(), Messager.class); + dependencyContainer.addInstanceAs(processingEnv.getElementUtils(), Elements.class); + dependencyContainer.addInstanceAs(processingEnv.getTypeUtils(), Types.class); + + setupTrees(processingEnv); + setupReflections(); + } + + private void setupReflections() { + final ConfigurationBuilder configuration = new ConfigurationBuilder().addUrls(ClasspathHelper + .forJavaClassPath()) + .addClassLoaders(ClasspathHelper.contextClassLoader(), ClasspathHelper.staticClassLoader(), getClass() + .getClassLoader()) + .addUrls(ClasspathHelper.forClassLoader()); + + final Reflections reflections = new Reflections(configuration); + dependencyContainer.addInstanceAs(reflections, Reflections.class); + } + + private void setupTrees(ProcessingEnvironment processingEnv) { + final Trees instance = Trees.instance(processingEnv); + dependencyContainer.addInstanceAs(instance, Trees.class); + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + if(roundEnv.processingOver()) { + handleLastRound(); + } else { + handleIntermediateRound(roundEnv); + } + + return false; + } + + public void handleIntermediateRound(RoundEnvironment roundEnvironment) { + knownModList.fillModIdInfo(roundEnvironment); + knownElementList.addAllForIntermediateRound(roundEnvironment); + } + + public void handleLastRound() { + convertPages(); + writePages(); + writeDocsJsonFile(); + } + + private void writeDocsJsonFile() { + final DocumentRegistry documentRegistry = dependencyContainer.getInstanceOfClass(DocumentRegistry.class); + final DocsJsonWriter docsJsonWriter = new DocsJsonWriter(outputDirectory, documentRegistry); + try { + docsJsonWriter.write(); + } catch(IOException exception) { + exception.printStackTrace(); + } + } + + private void convertPages() { + final ElementConverter elementConverter = dependencyContainer.getInstanceOfClass(ElementConverter.class); + elementConverter.handleElements(knownElementList); + } + + private void writePages() { + final DocumentRegistry documentRegistry = dependencyContainer.getInstanceOfClass(DocumentRegistry.class); + final PageWriter pageWriter = new PageWriter(documentRegistry, new File(outputDirectory, "docs")); + try { + pageWriter.write(); + } catch(IOException exception) { + exception.printStackTrace(); + } + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/DocumentProcessorNew.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/DocumentProcessorNew.java deleted file mode 100644 index 4980db820..000000000 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/DocumentProcessorNew.java +++ /dev/null @@ -1,352 +0,0 @@ -package com.blamejared.crafttweaker_annotation_processors.processors.document; - -import com.blamejared.crafttweaker_annotations.annotations.*; -import com.google.gson.*; -import com.google.gson.stream.*; -import com.sun.source.util.*; - -import javax.annotation.processing.*; -import javax.lang.model.*; -import javax.lang.model.element.*; -import javax.tools.*; -import java.io.*; -import java.nio.file.*; -import java.nio.file.attribute.*; -import java.util.*; -import java.util.stream.*; - -@SupportedAnnotationTypes({"com.blamejared.crafttweaker_annotations.annotations.Document", "net.minecraftforge.fml.common.Mod"}) -@SupportedSourceVersion(SourceVersion.RELEASE_8) -public class DocumentProcessorNew extends AbstractProcessor { - - private final Collection allElements = new HashSet<>(); - - private static final File docsOut = new File("docsOut"); - private static final Set pages = new TreeSet<>(Comparator.comparing(CrafttweakerDocumentationPage::getDocumentTitle)); - public static Map modIdByPackage = new HashMap<>(); - public static Trees tree = null; - - - public static String getModIdForPackage(Element element, ProcessingEnvironment environment) { - final String packageName = environment.getElementUtils().getPackageOf(element).getQualifiedName().toString(); - for(String knownPackName : modIdByPackage.keySet()) { - if(packageName.startsWith(knownPackName)) { - return modIdByPackage.get(knownPackName); - } - } - return null; - } - - @Override - public synchronized void init(ProcessingEnvironment processingEnv) { - super.init(processingEnv); - tree = Trees.instance(processingEnv); - } - - @Override - public boolean process(Set annotations, RoundEnvironment roundEnv) { - fillModIdInfo(roundEnv); - allElements.addAll(roundEnv.getElementsAnnotatedWith(Document.class)); - if(!roundEnv.processingOver()) { - return false; - } - - //Update each element to its latest state, then handle them all - allElements.stream() - .map(Object::toString) //Get names - .map(processingEnv.getElementUtils()::getTypeElement) - .forEach(this::handleElement); - - clearOutputDir(); - writeToFiles(); - allElements.clear(); - return false; - } - - private void handleElement(TypeElement typeElement) { - final Document document = typeElement.getAnnotation(Document.class); - if(document == null) { - this.processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Internal error! Document annotation null", typeElement); - return; - } - - if(!typeElement.getKind().isClass() && !typeElement.getKind().isInterface()) { - this.processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "How is this annotated", typeElement); - return; - } - - - final CrafttweakerDocumentationPage documentationPage = CrafttweakerDocumentationPage.convertType(typeElement, this.processingEnv); - if(documentationPage != null) { - pages.add(documentationPage); - } - } - - private void clearOutputDir() { - if(docsOut.exists()) { - if(!docsOut.isDirectory()) { - throw new IllegalStateException("File " + docsOut + " exists and is not a directory!"); - } - - try { - Files.walkFileTree(docsOut.getAbsoluteFile().toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - Files.delete(file); - return super.visitFile(file, attrs); - } - - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { - Files.delete(dir); - return super.postVisitDirectory(dir, exc); - } - }); - } catch(IOException e) { - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.toString()); - } - } - } - - private void fillModIdInfo(RoundEnvironment roundEnv) { - final TypeElement typeElement = processingEnv.getElementUtils().getTypeElement("net.minecraftforge.fml.common.Mod"); - outer: - for(Element element : roundEnv.getElementsAnnotatedWith(typeElement)) { - for(AnnotationMirror annotationMirror : element.getAnnotationMirrors()) { - if(annotationMirror.getAnnotationType().asElement().equals(typeElement)) { - final Map elementValues = annotationMirror.getElementValues(); - - for(ExecutableElement executableElement : elementValues.keySet()) { - if(executableElement.getSimpleName().toString().equals("value")) { - final String packageName = processingEnv.getElementUtils().getPackageOf(element).getQualifiedName().toString(); - modIdByPackage.put(packageName, elementValues.get(executableElement).getValue().toString()); - continue outer; - } - } - } - } - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Internal error: Could not find mod-id for this element!", element); - } - } - - private void writeToFiles() { - final File docsFolder = new File(docsOut, "docs"); - - //Create folder - if(!docsFolder.exists() && !docsFolder.mkdirs()) { - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Could not create folder " + docsFolder.getAbsolutePath()); - return; - } - - //Create files - try { - for(CrafttweakerDocumentationPage page : pages) { - page.write(docsFolder, processingEnv); - } - writeYAML(); - } catch(IOException e) { - e.printStackTrace(); - } - } - - private void writeYAML() throws IOException { - - final List values = new ArrayList<>(CrafttweakerDocumentationPage.knownTypes.values()); - values.sort(Comparator.comparing(CrafttweakerDocumentationPage::getDocPath)); - final Map files = new HashMap<>(); - for(CrafttweakerDocumentationPage value : values) { - - String path = value.getDocPath().contains("/") ? value.getDocPath().substring(0, value.getDocPath().lastIndexOf("/")) : value.getDocPath(); - String[] topFolders = path.split("/"); - for(int i = 0; i < topFolders.length; i++) { - topFolders[i] = topFolders[i].toUpperCase().charAt(0) + topFolders[i].substring(1); - } - YAMLFolder folder = files.computeIfAbsent(topFolders[0], YAMLFolder::new); - if(topFolders.length > 1) { - for(int i = 1; i < topFolders.length; i++) { - YAMLFolder file = folder.getOrCreate(topFolders[i]); - folder.addFile(file); - folder = file; - } - } - folder.addFile(new YAMLFile(value.getDocumentTitle(), value.getDocPath())); - } - - Gson gson = new GsonBuilder().setPrettyPrinting().registerTypeAdapter(YAMLFolder.class, new TypeAdapter() { - @Override - public void write(JsonWriter out, YAMLFolder value) throws IOException { - out.beginObject(); - for(YAMLObject yamlObject : value.getFiles()) { - - if(yamlObject instanceof YAMLFile) { - YAMLFile file = (YAMLFile) yamlObject; - out.name(file.getName()).value(file.getPath() + ".md"); - } else if(yamlObject instanceof YAMLFolder) { - YAMLFolder folder = (YAMLFolder) yamlObject; - out.name(folder.name); - write(out, folder); - } - } - ; - out.endObject(); - } - - @Override - public YAMLFolder read(JsonReader in) throws IOException { - // We don't really need to read here... - return null; - } - }).create(); - try(BufferedWriter writer = new BufferedWriter(new FileWriter(new File(docsOut, "docs.json")))) { - Map> nav = new HashMap<>(); - nav.put("nav", files); - writer.write(gson.toJson(nav)); - } - final File mkdocsFile = new File(docsOut, "mkdocs.yml"); - try(final PrintWriter writer = new PrintWriter(new FileWriter(mkdocsFile))) { - - for(String s : files.keySet()) { - writer.println(files.get(s).getOutput(0)); - } - } - } - - - private abstract static class YAMLObject { - - protected final String name; - - public YAMLObject(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public abstract String getOutput(int subLevel); - - @Override - public boolean equals(Object o) { - if(this == o) - return true; - if(!(o instanceof YAMLObject)) - return false; - - YAMLObject that = (YAMLObject) o; - - return getName().equals(that.getName()); - } - - @Override - public int hashCode() { - return getName().hashCode(); - } - - @Override - public String toString() { - return getName(); - } - } - - private static class YAMLFolder extends YAMLObject { - - private final List files; - - public YAMLFolder(String name) { - super(name); - this.files = new ArrayList<>(); - } - - @Override - public String getOutput(int subLevel) { - //TODO add layer stuff to get spacing right - StringBuilder sb = new StringBuilder(); - for(int i = 0; i < subLevel; i++) { - sb.append(" "); - } - sb.append(" ").append(name).append(":\n"); - for(YAMLObject file : getFiles()) { - sb.append(" ").append(file.getOutput(subLevel + 1)); - } - return sb.toString(); - } - - public YAMLFolder getOrCreate(String name) { - // Having this be a full stream one line method was giving me errors and wasn't working as intended - for(YAMLFolder object : files.stream().filter(yamlObject -> yamlObject instanceof YAMLFolder).map(yamlObject -> (YAMLFolder) yamlObject).collect(Collectors.toSet())) { - if(object.getName().equals(name)) { - return object; - } - } - return new YAMLFolder(name); - } - - public boolean contains(String name) { - - for(YAMLFolder object : files.stream().filter(yamlObject -> yamlObject instanceof YAMLFolder).map(yamlObject -> (YAMLFolder) yamlObject).collect(Collectors.toSet())) { - if(object.getName().equals(name)) { - return true; - } - } - return false; - } - - public void addFile(YAMLObject file) { - if(contains(file.getName())) { - return; - } - this.files.add(file); - } - - public List getFiles() { - return files; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("YAMLFolder{"); - sb.append("name='").append(name).append('\''); - sb.append(", files=").append(files); - sb.append('}'); - return sb.toString(); - } - - - } - - private static class YAMLFile extends YAMLObject { - - private final String path; - - public YAMLFile(String name, String path) { - super(name); - this.path = path; - } - - - public String getPath() { - return path; - } - - - @Override - public String getOutput(int subLevel) { - StringBuilder subBuilder = new StringBuilder(); - for(int i = 0; i < subLevel; i++) { - subBuilder.append(" "); - } - return subBuilder.toString() + String.format(" %s: '%s.md'%n", name, path); - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("YAMLFile{"); - sb.append("name='").append(name).append('\''); - sb.append(", path='").append(path).append('\''); - sb.append('}'); - return sb.toString(); - } - } - -} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/DocumentRegistry.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/DocumentRegistry.java new file mode 100644 index 000000000..06873c0d8 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/DocumentRegistry.java @@ -0,0 +1,63 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.DocumentationPageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.TypeName; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.TypePageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.page.DocumentationPage; + +import javax.lang.model.element.TypeElement; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +public class DocumentRegistry { + + private final Map documentationPages = new HashMap<>(); + private final Map elementsToInfo = new HashMap<>(); + + public void addDocumentationPage(DocumentationPage page) { + this.documentationPages.put(page.pageInfo, page); + } + + public void addInfo(TypeElement typeElement, DocumentationPageInfo pageInfo) { + elementsToInfo.put(typeElement, pageInfo); + } + + public DocumentationPageInfo getPageInfoFor(TypeElement typeElement) { + if(hasPageInfoFor(typeElement)) { + return elementsToInfo.get(typeElement); + } + + throw new IllegalArgumentException("Invalid typeElement: " + typeElement); + } + + public Optional getPageInfoByName(TypeName name) { + return elementsToInfo.values() + .stream() + .filter(pageInfo -> pageInfo instanceof TypePageInfo) + .map(pageInfo -> (TypePageInfo) pageInfo) + .filter(pageInfo -> pageInfo.zenCodeName.equals(name)) + .findFirst(); + } + + public DocumentationPage getPage(DocumentationPageInfo info) { + if(hasPageFor(info)) { + return documentationPages.get(info); + } + + throw new IllegalArgumentException("No such pageInfo registered yet: " + info); + } + + public Collection getAllPages() { + return documentationPages.values(); + } + + public boolean hasPageFor(DocumentationPageInfo info) { + return documentationPages.containsKey(info); + } + + public boolean hasPageInfoFor(TypeElement typeElement) { + return elementsToInfo.containsKey(typeElement); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/NativeConversionRegistry.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/NativeConversionRegistry.java new file mode 100644 index 000000000..79b2f692a --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/NativeConversionRegistry.java @@ -0,0 +1,69 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.dependencies.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.native_types.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.*; + +import javax.lang.model.element.*; +import java.util.*; +import java.util.function.*; + +public class NativeConversionRegistry implements IHasPostCreationCall { + + private final Map nativeTypeToTypeInfo = new HashMap<>(); + private final DependencyContainer dependencyContainer; + + public NativeConversionRegistry(DependencyContainer dependencyContainer) { + this.dependencyContainer = dependencyContainer; + } + + public void addNativeConversion(TypeElement nativeType, AbstractTypeInfo typeInfo) { + nativeTypeToTypeInfo.put(nativeType, typeInfo); + } + + public boolean hasNativeTypeInfo(TypeElement nativeType) { + return nativeTypeToTypeInfo.containsKey(nativeType); + } + + public AbstractTypeInfo getNativeTypeInfo(TypeElement nativeType) { + return nativeTypeToTypeInfo.get(nativeType); + } + + @Override + public void afterCreation() { + addCodedNativeTypes(); + } + + private void addCodedNativeTypes() { + addNativeTypeInformationFrom(StdLibsNativeTypeProvider.class); + addNativeTypeInformationFrom(JavaLangNativeTypeProvider.class); + addNativeTypeInformationFrom(ModDependencyTypeProvider.class); + } + + private void addNativeTypeInformationFrom(Class providerClass) { + final NativeTypeProvider provider = dependencyContainer.getInstanceOfClass(providerClass); + addNativeTypeInformationFrom(provider); + } + + private void addNativeTypeInformationFrom(NativeTypeProvider provider) { + final Map typeInfos = provider.getTypeInfos(); + nativeTypeToTypeInfo.putAll(typeInfos); + } + + public boolean hasNativeTypeInfoWithName(TypeName name) { + return tryGetNativeTypeInfoWithName(name).isPresent(); + } + + private Predicate typeNameMatches(TypeName name) { + return typeInfo -> typeInfo instanceof TypePageTypeInfo && ((TypePageTypeInfo) typeInfo).getZenCodeName().equals(name); + } + + public AbstractTypeInfo getNativeTypeInfoWithName(TypeName name) { + return tryGetNativeTypeInfoWithName(name).orElseThrow(() -> new IllegalArgumentException("Could not find type with name: " + name)); + } + + public Optional tryGetNativeTypeInfoWithName(TypeName name) { + return nativeTypeToTypeInfo.values().stream().filter(typeNameMatches(name)).findFirst(); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/ElementConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/ElementConverter.java new file mode 100644 index 000000000..fc9bb8bce --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/ElementConverter.java @@ -0,0 +1,54 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.DocumentConversionRegistry; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.element.KnownElementList; + +import javax.lang.model.element.TypeElement; +import java.util.Collection; + +public class ElementConverter { + + private final DocumentConversionRegistry conversionRegistry; + + public ElementConverter(DocumentConversionRegistry conversionRegistry) { + this.conversionRegistry = conversionRegistry; + } + + public void handleElements(KnownElementList knownElementList) { + prepareElements(knownElementList); + convertElements(knownElementList); + } + + private void prepareElements(KnownElementList knownElementList) { + final Collection elementsForTypeDocumentation = knownElementList.getElementsForTypeDocumentation(); + final Collection elementsForExpansionDocumentation = knownElementList.getElementsForExpansionDocumentation(); + + prepareDocumentation(elementsForTypeDocumentation); + prepareDocumentation(elementsForExpansionDocumentation); + } + + private void convertElements(KnownElementList knownElementList) { + final Collection elementsForTypeDocumentation = knownElementList.getElementsForTypeDocumentation(); + final Collection elementsForExpansionDocumentation = knownElementList.getElementsForExpansionDocumentation(); + + handleDocumentation(elementsForTypeDocumentation); + handleDocumentation(elementsForExpansionDocumentation); + } + + private void prepareDocumentation(Collection elementsToPrepare) { + for(TypeElement typeElement : elementsToPrepare) { + conversionRegistry.prepareTypePageFor(typeElement); + } + for(TypeElement typeElement : elementsToPrepare) { + conversionRegistry.setCommentInfoFor(typeElement); + } + } + + private void handleDocumentation(Collection elementsForExpansionDocumentation) { + for(TypeElement typeElement : elementsForExpansionDocumentation) { + conversionRegistry.convert(typeElement); + } + } + + +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/DocumentConversionRegistry.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/DocumentConversionRegistry.java new file mode 100644 index 000000000..c250d3a5c --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/DocumentConversionRegistry.java @@ -0,0 +1,73 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.DocumentRegistry; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.expansion.ExpansionConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.named_type.NamedTypeConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.native_registration.NativeRegistrationConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.dependencies.DependencyContainer; + +import javax.annotation.Nonnull; +import javax.lang.model.element.TypeElement; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; + +public class DocumentConversionRegistry { + + private final List converters = new ArrayList<>(); + private final DocumentRegistry documentRegistry; + + public DocumentConversionRegistry(DocumentRegistry documentRegistry, DependencyContainer dependencyContainer) { + this.documentRegistry = documentRegistry; + // + // TODO: Add converters + converters.add(dependencyContainer.getInstanceOfClass(NativeRegistrationConverter.class)); + converters.add(dependencyContainer.getInstanceOfClass(ExpansionConverter.class)); + converters.add(dependencyContainer.getInstanceOfClass(NamedTypeConverter.class)); + } + + public void prepareTypePageFor(TypeElement typeElement) { + setPageInfo(typeElement); + } + + public void setCommentInfoFor(TypeElement typeElement) { + setCommentData(typeElement); + } + + public void convert(TypeElement typeElement) { + convertAndAddToRegistry(typeElement); + } + + private void convertAndAddToRegistry(TypeElement typeElement) { + converters.stream() + .filter(converter -> documentRegistry.hasPageInfoFor(typeElement)) + .filter(converter -> converter.canConvert(typeElement)) + .map(converter -> converter.convert(typeElement, documentRegistry.getPageInfoFor(typeElement))) + .filter(Objects::nonNull) + .findFirst() + .ifPresent(documentRegistry::addDocumentationPage); + } + + private void setCommentData(TypeElement typeElement) { + converters.stream() + .filter(converter -> documentRegistry.hasPageInfoFor(typeElement)) + .filter(converter -> converter.canConvert(typeElement)) + .forEach(setCommentInfo(typeElement)); + + } + + @Nonnull + private Consumer setCommentInfo(TypeElement typeElement) { + return converter -> converter.setDocumentationCommentTo(typeElement, documentRegistry.getPageInfoFor(typeElement)); + } + + private void setPageInfo(TypeElement typeElement) { + converters.stream() + .filter(converter -> converter.canConvert(typeElement)) + .map(converter -> converter.prepareConversion(typeElement)) + .filter(Objects::nonNull) + .findFirst() + .ifPresent(pageInfo -> documentRegistry.addInfo(typeElement, pageInfo)); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/DocumentConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/DocumentConverter.java new file mode 100644 index 000000000..efb815f81 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/DocumentConverter.java @@ -0,0 +1,55 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.CommentConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.mods.KnownModList; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment.DocumentationComment; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.DocumentationPageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.examples.Example; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.examples.ExampleData; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.page.DocumentationPage; +import com.blamejared.crafttweaker_annotations.annotations.Document; + +import javax.lang.model.element.TypeElement; + +public abstract class DocumentConverter { + + protected final KnownModList knownModList; + protected final CommentConverter commentConverter; + + protected DocumentConverter(KnownModList knownModList, CommentConverter commentConverter) { + this.knownModList = knownModList; + this.commentConverter = commentConverter; + } + + public abstract boolean canConvert(TypeElement typeElement); + + public abstract DocumentationPage convert(TypeElement typeElement, DocumentationPageInfo pageInfo); + + protected DocumentationPageInfo prepareConversion(TypeElement element) { + final Document annotation = element.getAnnotation(Document.class); + if(annotation == null) { + throw new IllegalStateException("No Document annotation present!"); + } + + final String outputPath = annotation.value(); + final String declaringModId = knownModList.getModIdForPackage(element); + return new DocumentationPageInfo(declaringModId, outputPath); + } + + + public void setDocumentationCommentTo(TypeElement typeElement, DocumentationPageInfo pageInfo) { + final DocumentationComment typeComment = commentConverter.convertForType(typeElement); + addThisInformationIfNotPresent(typeComment, typeElement); + pageInfo.setTypeComment(typeComment); + } + + private void addThisInformationIfNotPresent(DocumentationComment commentFor, TypeElement typeElement) { + final ExampleData examples = commentFor.getExamples(); + if(!examples.hasExampleFor("this")) { + final Example expandedTypeThisExample = getFallbackThisInformationFor(typeElement); + examples.addExample(expandedTypeThisExample); + } + } + + protected abstract Example getFallbackThisInformationFor(TypeElement typeElement); +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/CommentConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/CommentConverter.java new file mode 100644 index 000000000..9decdf2dc --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/CommentConverter.java @@ -0,0 +1,102 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.example.ExampleDataConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.header.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment.DocumentationComment; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.DocumentationPageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.examples.ExampleData; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.*; + +public class CommentConverter { + + private final ProcessingEnvironment processingEnv; + private final CommentMerger commentMerger; + private final ExampleDataConverter exampleDataConverter; + private final DescriptionConverter descriptionConverter; + private final ParameterDescriptionConverter parameterDescriptionConverter; + + public CommentConverter(ProcessingEnvironment processingEnv, CommentMerger commentMerger, ExampleDataConverter exampleDataConverter, DescriptionConverter descriptionConverter, ParameterDescriptionConverter parameterDescriptionConverter) { + this.processingEnv = processingEnv; + this.commentMerger = commentMerger; + this.exampleDataConverter = exampleDataConverter; + this.descriptionConverter = descriptionConverter; + this.parameterDescriptionConverter = parameterDescriptionConverter; + } + + public DocumentationComment convertForType(TypeElement typeElement) { + return convertElement(typeElement); + } + + public DocumentationComment convertForConstructor(ExecutableElement constructor, DocumentationPageInfo pageInfo) { + final DocumentationComment comment = convertElement(constructor); + fillExampleForThisParameterFromPageInfo(comment, pageInfo); + return comment; + } + + public DocumentationComment convertForMethod(ExecutableElement method, DocumentationPageInfo pageInfo) { + final DocumentationComment comment = convertElement(method); + return fillExampleForThisParameterFromPageInfo(comment, pageInfo); + } + + public DocumentationComment convertForParameter(VariableElement variableElement) { + final DocumentationComment parameterDescription = convertParameterDescription(variableElement); + final DocumentationComment comment = convertElement(variableElement.getEnclosingElement()); + return mergeComments(parameterDescription, comment); + } + + private DocumentationComment convertParameterDescription(Element element) { + return parameterDescriptionConverter.convertDescriptionOf(element); + } + + public DocumentationComment convertForTypeParameter(TypeParameterElement typeParameterElement) { + final DocumentationComment parameterDescription = convertParameterDescription(typeParameterElement); + final DocumentationComment comment = convertElement(typeParameterElement.getEnclosingElement()); + return mergeComments(parameterDescription, comment); + } + + private DocumentationComment convertElement(Element element) { + final DocumentationComment comment = getCommentForElement(element); + final DocumentationComment enclosingElementComment = getCommentFromEnclosingElement(element); + return mergeComments(comment, enclosingElementComment); + } + + @Nonnull + private DocumentationComment getCommentForElement(Element element) { + final String docComment = processingEnv.getElementUtils().getDocComment(element); + final String description = extractDescriptionFrom(docComment, element); + final ExampleData exampleData = extractExampleDataFrom(docComment, element); + + return new DocumentationComment(description, exampleData); + } + + @Nullable + private String extractDescriptionFrom(@Nullable String docComment, Element element) { + return descriptionConverter.convertFromCommentString(docComment, element); + } + + private ExampleData extractExampleDataFrom(String docComment, Element element) { + return exampleDataConverter.convertFromCommentString(docComment, element); + } + + private DocumentationComment getCommentFromEnclosingElement(Element element) { + final Element enclosingElement = element.getEnclosingElement(); + if(enclosingElement == null) { + return DocumentationComment.empty(); + } + + return convertElement(enclosingElement); + } + + private DocumentationComment mergeComments(DocumentationComment comment, DocumentationComment enclosingElementComment) { + return commentMerger.merge(comment, enclosingElementComment); + } + + private DocumentationComment fillExampleForThisParameterFromPageInfo(DocumentationComment comment, DocumentationPageInfo pageInfo) { + final DocumentationComment classComment = pageInfo.getClassComment(); + return mergeComments(comment, classComment); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/CommentMerger.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/CommentMerger.java new file mode 100644 index 000000000..11dc20489 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/CommentMerger.java @@ -0,0 +1,42 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment.DocumentationComment; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.examples.Example; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.examples.ExampleData; + +import java.util.HashMap; +import java.util.Map; + +public class CommentMerger { + + public DocumentationComment merge(DocumentationComment childComment, DocumentationComment parentComment) { + final String description = mergeDescription(childComment); + final ExampleData exampleData = mergeCommentExamples(childComment, parentComment); + return new DocumentationComment(description, exampleData); + } + + private String mergeDescription(DocumentationComment childComment) { + return childComment.getOptionalDescription().orElse(null); + } + + private ExampleData mergeCommentExamples(DocumentationComment childComment, DocumentationComment parentComment) { + final ExampleData childExamples = childComment.getExamples(); + final ExampleData parentExamples = parentComment.getExamples(); + + return mergeExampleData(childExamples, parentExamples); + } + + private ExampleData mergeExampleData(ExampleData childExamples, ExampleData parentExamples) { + final Map childExampleMap = childExamples.getExampleMap(); + final Map parentExampleMap = parentExamples.getExampleMap(); + final HashMap resultExampleMap = mergeExampleDataMap(childExampleMap, parentExampleMap); + return new ExampleData(resultExampleMap); + } + + private HashMap mergeExampleDataMap(Map childExampleMap, Map parentExampleMap) { + final HashMap result = new HashMap<>(parentExampleMap); + result.putAll(childExampleMap); + + return result; + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/DescriptionConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/DescriptionConverter.java new file mode 100644 index 000000000..9b985b86a --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/DescriptionConverter.java @@ -0,0 +1,45 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.documentation_parameter.ParameterRemover; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.linktag.LinkTagReplacer; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.lang.model.element.Element; + +public class DescriptionConverter { + + private final LinkTagReplacer linkTagReplacer; + private final ParameterRemover parameterRemover; + + public DescriptionConverter(LinkTagReplacer linkTagReplacer, ParameterRemover parameterRemover) { + this.linkTagReplacer = linkTagReplacer; + this.parameterRemover = parameterRemover; + } + + @Nullable + public String convertFromCommentString(@Nullable String docComment, Element element) { + if(docComment == null) { + return null; + } + + return convertNonNullCommentString(docComment, element); + } + + @Nonnull + private String convertNonNullCommentString(String docComment, Element element) { + docComment = replaceLinkTagsWithClickableMarkdown(docComment, element); + docComment = removeDocumentationParameters(docComment); + return docComment.trim(); + } + + private String replaceLinkTagsWithClickableMarkdown(String docComment, Element element) { + return linkTagReplacer.replaceLinkTagsFrom(docComment, element); + } + + private String removeDocumentationParameters(String docComment) { + return parameterRemover.removeDocumentationParametersFrom(docComment); + } + + +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/documentation_parameter/ParameterInfo.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/documentation_parameter/ParameterInfo.java new file mode 100644 index 000000000..c9c69392b --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/documentation_parameter/ParameterInfo.java @@ -0,0 +1,47 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.documentation_parameter; + +import java.util.ArrayList; +import java.util.List; + +public class ParameterInfo { + + private final String name; + private final List occurrences = new ArrayList<>(); + + private ParameterInfo(String name) { + this.name = name; + } + + public ParameterInfo(String name, String text) { + this.name = name; + addOccurrence(text); + } + + public static ParameterInfo merge(ParameterInfo left, ParameterInfo right) { + if(!left.name.equals(right.name)) { + throw new IllegalArgumentException("Parameter names do not match! " + left.name + " != " + right.name); + } + + final ParameterInfo result = new ParameterInfo(left.name); + result.occurrences.addAll(left.occurrences); + result.occurrences.addAll(right.occurrences); + + return result; + } + + public void addOccurrence(String text) { + this.occurrences.add(text); + } + + public String getAnyOccurrence() { + return this.occurrences.get(0); + } + + public String getName() { + return name; + } + + public List getOccurrences() { + return occurrences; + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/documentation_parameter/ParameterInformationList.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/documentation_parameter/ParameterInformationList.java new file mode 100644 index 000000000..1d4df75dd --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/documentation_parameter/ParameterInformationList.java @@ -0,0 +1,34 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.documentation_parameter; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +public class ParameterInformationList { + + private final Map parameterInformation = new HashMap<>(); + + public ParameterInformationList(Map parameterInformation) { + this.parameterInformation.putAll(parameterInformation); + } + + public void addParameterInfo(ParameterInfo parameterInfo) { + this.parameterInformation.put(parameterInfo.getName(), parameterInfo); + } + + public boolean hasParameterInfoWithName(String name) { + return this.parameterInformation.containsKey(name); + } + + public Optional tryGetParameterInfoWithName(String name) { + if(hasParameterInfoWithName(name)) { + return Optional.of(this.parameterInformation.get(name)); + } else { + return Optional.empty(); + } + } + + public ParameterInfo getParameterInfoWithName(String name) { + return tryGetParameterInfoWithName(name).orElseThrow(() -> new IllegalArgumentException("No such parameter registered: " + name)); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/documentation_parameter/ParameterReader.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/documentation_parameter/ParameterReader.java new file mode 100644 index 000000000..f4758d0ad --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/documentation_parameter/ParameterReader.java @@ -0,0 +1,94 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.documentation_parameter; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.linktag.LinkTagReplacer; + +import javax.annotation.Nonnull; +import javax.lang.model.element.Element; +import java.util.HashMap; +import java.util.Map; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.regex.MatchResult; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collector; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class ParameterReader { + + private static final Pattern parameterPattern = Pattern.compile("@(\\w+)\\s+([^@]+)"); + + + private final LinkTagReplacer linkTagReplacer; + + public ParameterReader(LinkTagReplacer linkTagReplacer) { + this.linkTagReplacer = linkTagReplacer; + } + + public ParameterInformationList readParametersFrom(String from, Element element) { + if(from == null) { + return emptyInformationList(); + } + + return readParametersFromNonNull(from, element); + } + + @Nonnull + private ParameterInformationList emptyInformationList() { + return new ParameterInformationList(new HashMap<>()); + } + + @Nonnull + private ParameterInformationList readParametersFromNonNull(String from, Element element) { + final Map parameterInformation = readParameterInformation(from, element); + return new ParameterInformationList(parameterInformation); + } + + private Map readParameterInformation(String from, Element element) { + from = prepareDocComment(from, element); + final Matcher matcher = parameterPattern.matcher(from); + return readParameterInformationFromMatcher(matcher); + } + + + private String prepareDocComment(String from, Element element) { + return linkTagReplacer.replaceLinkTagsFrom(from, element); + } + + private Map readParameterInformationFromMatcher(Matcher matcher) { + return getMatchResultsFrom(matcher).map(this::readParameterInfoFromMatchResult) + .collect(asMapWithMergedParameterInformation()); + } + + private Collector> asMapWithMergedParameterInformation() { + final Function keyMapper = ParameterInfo::getName; + final Function valueMapper = Function.identity(); + final BinaryOperator mergerFunction = ParameterInfo::merge; + + return Collectors.toMap(keyMapper, valueMapper, mergerFunction); + } + + private Stream getMatchResultsFrom(Matcher matcher) { + final Stream.Builder builder = Stream.builder(); + while(matcher.find()) { + builder.add(matcher.toMatchResult()); + } + return builder.build(); + } + + private ParameterInfo readParameterInfoFromMatchResult(MatchResult toMatchResult) { + final String name = getParameterNameFromMatchResult(toMatchResult); + final String text = getParameterTextFromMatchResult(toMatchResult); + + return new ParameterInfo(name, text); + } + + private String getParameterNameFromMatchResult(MatchResult toMatchResult) { + return toMatchResult.group(1).trim(); + } + + private String getParameterTextFromMatchResult(MatchResult toMatchResult) { + return toMatchResult.group(2).trim(); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/documentation_parameter/ParameterRemover.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/documentation_parameter/ParameterRemover.java new file mode 100644 index 000000000..938635fa5 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/documentation_parameter/ParameterRemover.java @@ -0,0 +1,22 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.documentation_parameter; + +public class ParameterRemover { + + public String removeDocumentationParametersFrom(String docComment) { + if(!hasDocumentationParameters(docComment)) { + return docComment; + } + + final int index = getIndexOfFirstDocumentationParameter(docComment); + return docComment.substring(0, index); + } + + private boolean hasDocumentationParameters(String docComment) { + final int index = getIndexOfFirstDocumentationParameter(docComment); + return index > 0; + } + + private int getIndexOfFirstDocumentationParameter(String docComment) { + return docComment.indexOf('@'); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/documentation_parameter/ReturnTypeInfoReader.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/documentation_parameter/ReturnTypeInfoReader.java new file mode 100644 index 000000000..e2b061b91 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/documentation_parameter/ReturnTypeInfoReader.java @@ -0,0 +1,30 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.documentation_parameter; + +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.util.Elements; +import java.util.Optional; + +public class ReturnTypeInfoReader { + + private final ParameterReader parameterReader; + private final Elements elementUtils; + + public ReturnTypeInfoReader(ParameterReader parameterReader, Elements elementUtils) { + this.parameterReader = parameterReader; + this.elementUtils = elementUtils; + } + + public Optional readForMethod(ExecutableElement method) { + final String docComment = elementUtils.getDocComment(method); + final ParameterInformationList parameterInformationList = parameterReader.readParametersFrom(docComment, method); + return Optional.ofNullable(getReturnTypeInfoFrom(parameterInformationList)); + } + + private String getReturnTypeInfoFrom(ParameterInformationList parameterInformationList) { + if(!parameterInformationList.hasParameterInfoWithName("return")) { + return null; + } + + return parameterInformationList.getParameterInfoWithName("return").getAnyOccurrence(); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/example/ExampleDataConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/example/ExampleDataConverter.java new file mode 100644 index 000000000..b03a0dd30 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/example/ExampleDataConverter.java @@ -0,0 +1,89 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.example; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.documentation_parameter.ParameterInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.documentation_parameter.ParameterInformationList; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.documentation_parameter.ParameterReader; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.examples.Example; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.examples.ExampleData; + +import javax.lang.model.element.Element; +import java.util.Map; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.stream.Collector; +import java.util.stream.Collectors; + +public class ExampleDataConverter { + + private static final String DOC_PARAM = "docParam"; + + private final ParameterReader reader; + + public ExampleDataConverter(ParameterReader reader) { + this.reader = reader; + } + + public ExampleData convertFromCommentString(String docComment, Element element) { + final ParameterInformationList parameterInformationList = reader.readParametersFrom(docComment, element); + if(hasExampleData(parameterInformationList)) { + return getExampleDataFrom(parameterInformationList); + } + return ExampleData.empty(); + } + + private boolean hasExampleData(ParameterInformationList parameterInformationList) { + return parameterInformationList.hasParameterInfoWithName(DOC_PARAM); + } + + private ExampleData getExampleDataFrom(ParameterInformationList parameterInformationList) { + final ParameterInfo docParamInfo = parameterInformationList.getParameterInfoWithName(DOC_PARAM); + return getExampleDataFromParameterInfo(docParamInfo); + } + + private ExampleData getExampleDataFromParameterInfo(ParameterInfo docParamInfo) { + final Map examples = getExamplesFrom(docParamInfo); + return new ExampleData(examples); + } + + private Map getExamplesFrom(ParameterInfo docParamInfo) { + return docParamInfo.getOccurrences() + .stream() + .map(this::getExampleFromOccurrence) + .collect(asMapWithMergedExamples()); + } + + private Collector> asMapWithMergedExamples() { + final Function keyMapper = Example::getName; + final Function valueMapper = Function.identity(); + final BinaryOperator mergeFunction = Example::merge; + + return Collectors.toMap(keyMapper, valueMapper, mergeFunction); + } + + private Example getExampleFromOccurrence(String occurrence) { + verifyThatOccurenceCanBeSplit(occurrence); + + final String exampleName = getExampleNameFrom(occurrence); + final String textValue = getExampleTextValueFrom(occurrence); + + return new Example(exampleName, textValue); + } + + private void verifyThatOccurenceCanBeSplit(String occurrence) { + if(splitOccurence(occurrence).length != 2) { + throw new IllegalArgumentException("Cannot split exampleData " + occurrence); + } + } + + private String[] splitOccurence(String occurrence) { + return occurrence.split(" ", 2); + } + + private String getExampleNameFrom(String occurrence) { + return splitOccurence(occurrence)[0]; + } + + private String getExampleTextValueFrom(String occurrence) { + return splitOccurence(occurrence)[1]; + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/linktag/LinkConversionRule.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/linktag/LinkConversionRule.java new file mode 100644 index 000000000..709669e41 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/linktag/LinkConversionRule.java @@ -0,0 +1,9 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.linktag; + +import javax.lang.model.element.Element; + +public interface LinkConversionRule { + boolean canConvert(String link); + + String convertToClickableMarkdown(String link, Element element); +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/linktag/LinkConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/linktag/LinkConverter.java new file mode 100644 index 000000000..cc9315445 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/linktag/LinkConverter.java @@ -0,0 +1,55 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.linktag; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.linktag.rules.ElementLinkConversionRule; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.linktag.rules.ImportedTypeLinkConversionRule; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.linktag.rules.QualifiedNameLinkConversionRule; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.linktag.rules.ThisTypeConversionRule; +import com.blamejared.crafttweaker_annotation_processors.processors.document.dependencies.DependencyContainer; +import com.blamejared.crafttweaker_annotation_processors.processors.document.dependencies.IHasPostCreationCall; + +import javax.annotation.processing.*; +import javax.lang.model.element.Element; +import javax.tools.*; +import java.util.ArrayList; +import java.util.List; + +public class LinkConverter implements IHasPostCreationCall { + private final List conversionRules = new ArrayList<>(); + private final DependencyContainer dependencyContainer; + private final Messager messager; + + public LinkConverter(DependencyContainer dependencyContainer, Messager messager) { + this.dependencyContainer = dependencyContainer; + this.messager = messager; + } + + public String convertLinkToClickableMarkdown(String link, Element element) { + try { + final LinkConversionRule rule = findRuleFor(link); + return rule.convertToClickableMarkdown(link, element); + }catch(Exception e) { + messager.printMessage(Diagnostic.Kind.WARNING, "Could not convert link '" + link + "': " + e.getMessage()); + return link; + } + } + + private LinkConversionRule findRuleFor(String link) { + return conversionRules.stream() + .filter(rule -> rule.canConvert(link)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("Cannot convert link: " + link)); + } + + @Override + public void afterCreation() { + addConversionRule(ElementLinkConversionRule.class); + addConversionRule(ThisTypeConversionRule.class); + addConversionRule(ImportedTypeLinkConversionRule.class); + addConversionRule(QualifiedNameLinkConversionRule.class); + } + + private void addConversionRule(Class ruleClass) { + final LinkConversionRule rule = dependencyContainer.getInstanceOfClass(ruleClass); + conversionRules.add(rule); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/linktag/LinkTagReplacer.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/linktag/LinkTagReplacer.java new file mode 100644 index 000000000..08d543e78 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/linktag/LinkTagReplacer.java @@ -0,0 +1,60 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.linktag; + +import javax.annotation.Nonnull; +import javax.lang.model.element.Element; +import java.util.regex.MatchResult; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class LinkTagReplacer { + + private static final Pattern linkPattern = Pattern.compile("\\{@link ([^}]+)}"); + + private final LinkConverter linkConverter; + + public LinkTagReplacer(LinkConverter linkConverter) { + this.linkConverter = linkConverter; + } + + public String replaceLinkTagsFrom(String docComment, Element element) { + if(docComment == null) { + return null; + } + + return replaceLinkTagsFromNonNullComment(docComment, element); + } + + @Nonnull + private String replaceLinkTagsFromNonNullComment(String docComment, Element element) { + final Matcher matcher = linkPattern.matcher(docComment); + return replaceLinksWithMatcher(matcher, element); + } + + private String replaceLinksWithMatcher(Matcher matcher, Element element) { + final StringBuffer result = new StringBuffer(); + + while(matcher.find()) { + final MatchResult matchResult = matcher.toMatchResult(); + final String replacement = getReplacementForMatchResult(matchResult, element); + matcher.appendReplacement(result, replacement); + } + + matcher.appendTail(result); + return result.toString(); + } + + private String getReplacementForMatchResult(MatchResult result, Element element) { + final String linkTagContent = getLinkTagContent(result); + return getReplacementFor(linkTagContent, element); + } + + private String getLinkTagContent(MatchResult result) { + return result.group(1); + } + + private String getReplacementFor(String linkTagContent, Element element) { + return linkConverter.convertLinkToClickableMarkdown(linkTagContent, element); + } + + +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/linktag/rules/AccessibleTypesFinder.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/linktag/rules/AccessibleTypesFinder.java new file mode 100644 index 000000000..9aa9c649c --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/linktag/rules/AccessibleTypesFinder.java @@ -0,0 +1,119 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.linktag.rules; + +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.tree.ImportTree; +import com.sun.source.tree.Tree; +import com.sun.source.util.TreePath; +import com.sun.source.util.Trees; + +import javax.lang.model.element.Element; +import javax.lang.model.element.PackageElement; +import javax.lang.model.util.Elements; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class AccessibleTypesFinder { + + private final Trees trees; + private final Elements elementUtils; + + public AccessibleTypesFinder(Trees trees, Elements elementUtils) { + this.trees = trees; + this.elementUtils = elementUtils; + } + + + public List getAllAccessibleTypesAt(Element element) { + final List typesInSamePackage = getTypesInSamePackageAs(element); + final List importedTypes = getImportedTypes(element); + + return combineTypes(typesInSamePackage, importedTypes); + } + + private List getTypesInSamePackageAs(Element element) { + final PackageElement packageElement = getPackageOf(element); + return getTypeNamesInPackage(packageElement).collect(Collectors.toList()); + } + + private PackageElement getPackageOf(Element element) { + return elementUtils.getPackageOf(element); + } + + private List combineTypes(List typesInSamePackage, List importedTypes) { + final List result = new ArrayList<>(typesInSamePackage); + result.addAll(importedTypes); + return result; + } + + private List getImportedTypes(Element element) { + final List importTreeList = getImportTreeList(element); + + return convertImportTreeList(importTreeList); + } + + private List getImportTreeList(Element element) { + final TreePath path = trees.getPath(element); + final CompilationUnitTree compilationUnit = path.getCompilationUnit(); + return compilationUnit.getImports(); + } + + private List convertImportTreeList(List importTreeList) { + return importTreeList.stream() + .map(this::qualifyImportStatement) + .sorted(wildcardImportsLast()) + .flatMap(this::getAllImportedTypesFor) + .collect(Collectors.toList()); + } + + private Comparator wildcardImportsLast() { + return Comparator.comparing(this::isWildcardImport); + } + + private boolean isWildcardImport(String name) { + return name.endsWith("*"); + } + + private String qualifyImportStatement(ImportTree tree) { + final Tree qualifiedIdentifier = tree.getQualifiedIdentifier(); + return qualifiedIdentifier.toString(); + } + + private Stream getAllImportedTypesFor(String name) { + if(isWildcardImport(name)) { + return getAllImportedTypesForWildcard(name); + } else { + return Stream.of(name); + } + } + + private Stream getAllImportedTypesForWildcard(String name) { + final PackageElement packageElement = getImportedPackageForWildcard(name); + return getTypeNamesInPackage(packageElement); + } + + private PackageElement getImportedPackageForWildcard(String name) { + final String packageName = name.substring(0, name.lastIndexOf('.')); + final PackageElement packageElement = getPackageWithName(packageName); + validatePackageExists(packageName); + return packageElement; + } + + private PackageElement getPackageWithName(String packageName) { + return elementUtils.getPackageElement(packageName); + } + + private void validatePackageExists(String name) { + if(getPackageWithName(name) == null) { + throw new IllegalArgumentException("Cannot find package " + name); + } + } + + private Stream getTypeNamesInPackage(PackageElement packageElement) { + final List enclosedElements = packageElement.getEnclosedElements(); + return enclosedElements.stream().map(Objects::toString); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/linktag/rules/ElementLinkConversionRule.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/linktag/rules/ElementLinkConversionRule.java new file mode 100644 index 000000000..ebeca934c --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/linktag/rules/ElementLinkConversionRule.java @@ -0,0 +1,48 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.linktag.rules; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.linktag.LinkConversionRule; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.linktag.LinkConverter; + +import javax.lang.model.element.Element; + +public class ElementLinkConversionRule implements LinkConversionRule { + + private final LinkConverter linkConverter; + + public ElementLinkConversionRule(LinkConverter linkConverter) { + this.linkConverter = linkConverter; + } + + @Override + public boolean canConvert(String link) { + return link.contains("#"); + } + + @Override + public String convertToClickableMarkdown(String link, Element element) { + final String prefix = getPrefix(link, element); + final String suffix = getSuffix(link); + + return merge(prefix, suffix); + } + + private String getPrefix(String link, Element element) { + final int indexOfSeparator = getIndexOfSeparator(link); + final String substring = link.substring(0, indexOfSeparator); + + return linkConverter.convertLinkToClickableMarkdown(substring, element); + } + + private String getSuffix(String link) { + final int indexOfSeparator = getIndexOfSeparator(link); + return link.substring(indexOfSeparator + 1); + } + + private int getIndexOfSeparator(String link) { + return link.indexOf('#'); + } + + private String merge(String prefix, String suffix) { + return String.format("%s#%s", prefix, suffix); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/linktag/rules/ImportedTypeLinkConversionRule.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/linktag/rules/ImportedTypeLinkConversionRule.java new file mode 100644 index 000000000..31699c4c0 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/linktag/rules/ImportedTypeLinkConversionRule.java @@ -0,0 +1,56 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.linktag.rules; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.linktag.LinkConversionRule; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.linktag.LinkConverter; + +import javax.lang.model.element.Element; +import java.util.List; + +public class ImportedTypeLinkConversionRule implements LinkConversionRule { + + private final LinkConverter linkConverter; + private final AccessibleTypesFinder accessibleTypesFinder; + + public ImportedTypeLinkConversionRule(LinkConverter linkConverter, AccessibleTypesFinder accessibleTypesFinder) { + this.linkConverter = linkConverter; + this.accessibleTypesFinder = accessibleTypesFinder; + } + + + @Override + public boolean canConvert(String link) { + return isDirectlyReferenced(link); + } + + private boolean isDirectlyReferenced(String link) { + return !link.contains("."); + } + + @Override + public String convertToClickableMarkdown(String link, Element element) { + final String importedTypeQualifiedName = getQualifiedNameFor(link, element); + return linkConverter.convertLinkToClickableMarkdown(importedTypeQualifiedName, element); + } + + private String getQualifiedNameFor(String link, Element element) { + final List importedTypes = getImportedTypesAt(element); + return qualifyName(link, importedTypes); + } + + private List getImportedTypesAt(Element element) { + return accessibleTypesFinder.getAllAccessibleTypesAt(element); + } + + private String qualifyName(String link, List importedTypes) { + for(String importedType : importedTypes) { + if(doesImportMatchLink(importedType, link)) { + return importedType; + } + } + throw new IllegalArgumentException("Could not qualify " + link); + } + + private boolean doesImportMatchLink(String importedType, String link) { + return importedType.endsWith("." + link); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/linktag/rules/QualifiedNameLinkConversionRule.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/linktag/rules/QualifiedNameLinkConversionRule.java new file mode 100644 index 000000000..17d9f1afa --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/linktag/rules/QualifiedNameLinkConversionRule.java @@ -0,0 +1,54 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.linktag.rules; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.linktag.LinkConversionRule; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; + +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Elements; + +public class QualifiedNameLinkConversionRule implements LinkConversionRule { + + private final Elements elementUtils; + private final TypeConverter typeConverter; + + public QualifiedNameLinkConversionRule(Elements elementUtils, TypeConverter typeConverter) { + this.elementUtils = elementUtils; + this.typeConverter = typeConverter; + } + + @Override + public boolean canConvert(String link) { + return isQualifiedName(link); + } + + private boolean isQualifiedName(String link) { + return link.contains("."); + } + + @Override + public String convertToClickableMarkdown(String link, Element element) { + final AbstractTypeInfo typeInfo = getTypeInfo(link); + return typeInfo.getClickableMarkdown(); + } + + private AbstractTypeInfo getTypeInfo(String link) { + final TypeMirror typeMirror = getTypeMirror(link); + return typeConverter.convertType(typeMirror); + } + + private TypeMirror getTypeMirror(String link) { + final TypeElement typeElement = getTypeElement(link); + return typeElement.asType(); + } + + private TypeElement getTypeElement(String link) { + final TypeElement typeElement = elementUtils.getTypeElement(link); + if(typeElement == null) { + throw new IllegalArgumentException("Could not find type " + link); + } + return typeElement; + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/linktag/rules/ThisTypeConversionRule.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/linktag/rules/ThisTypeConversionRule.java new file mode 100644 index 000000000..ed7538ccf --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/comment/linktag/rules/ThisTypeConversionRule.java @@ -0,0 +1,18 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.linktag.rules; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.linktag.LinkConversionRule; + +import javax.lang.model.element.Element; + +public class ThisTypeConversionRule implements LinkConversionRule { + + @Override + public boolean canConvert(String link) { + return link.isEmpty(); + } + + @Override + public String convertToClickableMarkdown(String link, Element element) { + return "[this](.)"; + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/expansion/ExpansionConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/expansion/ExpansionConverter.java new file mode 100644 index 000000000..8352084fa --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/expansion/ExpansionConverter.java @@ -0,0 +1,104 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.expansion; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.DocumentRegistry; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.DocumentConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.CommentConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.expansion.member.ExpansionVirtualMemberConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.static_member.StaticMemberConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.mods.KnownModList; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment.DocumentationComment; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.DocumentationPageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.TypeName; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.TypePageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.examples.Example; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.static_member.DocumentedStaticMembers; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member.DocumentedVirtualMembers; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.page.DocumentationPage; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.page.ExpansionPage; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.GenericTypeInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.TypePageTypeInfo; +import org.openzen.zencode.java.ZenCodeType; + +import javax.lang.model.element.TypeElement; +import java.util.Optional; + +public class ExpansionConverter extends DocumentConverter { + + private final StaticMemberConverter staticMemberConverter; + private final ExpansionVirtualMemberConverter virtualMemberConverter; + private final TypeConverter typeConverter; + private final DocumentRegistry documentRegistry; + + public ExpansionConverter(KnownModList knownModList, CommentConverter commentConverter, DocumentRegistry documentRegistry, TypeConverter typeConverter, StaticMemberConverter staticMemberConverter, ExpansionVirtualMemberConverter virtualMemberConverter, DocumentRegistry documentRegistry1) { + super(knownModList, commentConverter); + this.staticMemberConverter = staticMemberConverter; + this.virtualMemberConverter = virtualMemberConverter; + this.typeConverter = typeConverter; + this.documentRegistry = documentRegistry; + } + + @Override + public boolean canConvert(TypeElement typeElement) { + return typeElement.getAnnotation(ZenCodeType.Expansion.class) != null; + } + + @Override + public DocumentationPage convert(TypeElement typeElement, DocumentationPageInfo pageInfo) { + final AbstractTypeInfo expandedType = getExpandedType(typeElement); + + final DocumentedVirtualMembers virtualMembers = getVirtualMembers(typeElement, expandedType); + final DocumentedStaticMembers staticMembers = getStaticMembers(typeElement, pageInfo); + + return new ExpansionPage(expandedType, pageInfo, virtualMembers, staticMembers); + } + + private AbstractTypeInfo getExpandedType(TypeElement typeElement) { + final ZenCodeType.Expansion expansion = typeElement.getAnnotation(ZenCodeType.Expansion.class); + + final TypeName expandedName = new TypeName(expansion.value()); + return typeConverter.convertByName(expandedName); + } + + private DocumentedVirtualMembers getVirtualMembers(TypeElement typeElement, AbstractTypeInfo expandedType) { + final DocumentationPageInfo pageInfo = getPageInfoForType(expandedType); + return virtualMemberConverter.convertFor(typeElement, pageInfo); + } + + private TypePageInfo getPageInfoForType(AbstractTypeInfo expandedType) { + if(expandedType instanceof TypePageTypeInfo) { + return getPageInfo((TypePageTypeInfo) expandedType); + } + if(expandedType instanceof GenericTypeInfo) { + return getPageInfoForType(((GenericTypeInfo) expandedType).getBaseClass()); + } + throw new IllegalArgumentException("Invalid expanded type! " + expandedType); + } + + private TypePageInfo getPageInfo(TypePageTypeInfo expandedType) { + final TypeName zenCodeName = expandedType.getZenCodeName(); + final Optional pageInfoByName = documentRegistry.getPageInfoByName(zenCodeName); + return pageInfoByName.orElseThrow(() -> new IllegalArgumentException("Invalid Expanded Type! " + zenCodeName)); + } + + private DocumentedStaticMembers getStaticMembers(TypeElement typeElement, DocumentationPageInfo pageInfo) { + return staticMemberConverter.convertFor(typeElement, pageInfo); + } + + @Override + public void setDocumentationCommentTo(TypeElement typeElement, DocumentationPageInfo pageInfo) { + super.setDocumentationCommentTo(typeElement, pageInfo); + } + + @Override + protected Example getFallbackThisInformationFor(TypeElement typeElement) { + return getExpandedTypeThisExample(typeElement); + } + + private Example getExpandedTypeThisExample(TypeElement typeElement) { + final TypePageInfo pageInfoForType = getPageInfoForType(getExpandedType(typeElement)); + final DocumentationComment classComment = pageInfoForType.getClassComment(); + return classComment.getExamples().getExampleFor("this"); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/expansion/member/ExpansionCasterConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/expansion/member/ExpansionCasterConverter.java new file mode 100644 index 000000000..797a9e34f --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/expansion/member/ExpansionCasterConverter.java @@ -0,0 +1,64 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.expansion.member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.CommentConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.AbstractEnclosedElementConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.header.HeaderConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment.DocumentationComment; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.DocumentationPageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.MemberHeader; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member.CasterMember; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member.DocumentedVirtualMembers; +import org.openzen.zencode.java.ZenCodeType; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeParameterElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeMirror; +import java.util.List; + +public class ExpansionCasterConverter extends AbstractEnclosedElementConverter { + + private final HeaderConverter headerConverter; + private final CommentConverter commentConverter; + + public ExpansionCasterConverter(HeaderConverter headerConverter, CommentConverter commentConverter) { + this.headerConverter = headerConverter; + this.commentConverter = commentConverter; + } + + @Override + public boolean canConvert(Element enclosedElement) { + return isAnnotationPresentOn(ZenCodeType.Caster.class, enclosedElement); + } + + @Override + public void convertAndAddTo(Element enclosedElement, DocumentedVirtualMembers result, DocumentationPageInfo pageInfo) { + final ExecutableElement method = (ExecutableElement) enclosedElement; + final CasterMember caster = convertCaster(method, pageInfo); + result.addCaster(caster); + } + + private CasterMember convertCaster(ExecutableElement method, DocumentationPageInfo pageInfo) { + final MemberHeader header = convertHeader(method); + final DocumentationComment comment = convertComment(method, pageInfo); + final boolean implicit = isImplicit(method); + + return new CasterMember(header, comment, implicit); + } + + private MemberHeader convertHeader(ExecutableElement method) { + final List parameters = method.getParameters(); + final List typeParameters = method.getTypeParameters(); + final TypeMirror returnType = method.getReturnType(); + return headerConverter.convertHeaderFor(parameters, typeParameters, returnType); + } + + private DocumentationComment convertComment(ExecutableElement method, DocumentationPageInfo pageInfo) { + return commentConverter.convertForMethod(method, pageInfo); + } + + private boolean isImplicit(ExecutableElement method) { + return method.getAnnotation(ZenCodeType.Caster.class).implicit(); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/expansion/member/ExpansionGetterSetterConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/expansion/member/ExpansionGetterSetterConverter.java new file mode 100644 index 000000000..e160a8ba3 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/expansion/member/ExpansionGetterSetterConverter.java @@ -0,0 +1,86 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.expansion.member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.AbstractEnclosedElementConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.DocumentationPageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.PropertyMember; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member.DocumentedVirtualMembers; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; +import org.openzen.zencode.java.ZenCodeType; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.type.TypeMirror; + +public class ExpansionGetterSetterConverter extends AbstractEnclosedElementConverter { + + private final TypeConverter typeConverter; + + public ExpansionGetterSetterConverter(TypeConverter typeConverter) { + this.typeConverter = typeConverter; + } + + @Override + public boolean canConvert(Element enclosedElement) { + return isGetter(enclosedElement) || isSetter(enclosedElement); + } + + private boolean isGetter(Element enclosedElement) { + return isAnnotationPresentOn(ZenCodeType.Getter.class, enclosedElement); + } + + private boolean isSetter(Element enclosedElement) { + return isAnnotationPresentOn(ZenCodeType.Setter.class, enclosedElement); + } + + @Override + public void convertAndAddTo(Element enclosedElement, DocumentedVirtualMembers result, DocumentationPageInfo pageInfo) { + final PropertyMember propertyMember = convertProperty(enclosedElement); + + result.addProperty(propertyMember); + } + + private PropertyMember convertProperty(Element enclosedElement) { + final ExecutableElement method = (ExecutableElement) enclosedElement; + final String name = getName(method); + final AbstractTypeInfo type = getTypeInfo(method); + final boolean hasGetter = isGetter(method); + final boolean hasSetter = isSetter(method); + + return new PropertyMember(name, type, hasGetter, hasSetter); + } + + private String getName(Element enclosedElement) { + if(isGetter(enclosedElement)) { + return getGetterName(enclosedElement); + } else { + return getSetterName(enclosedElement); + } + } + + private String getGetterName(Element enclosedElement) { + return enclosedElement.getAnnotation(ZenCodeType.Getter.class).value(); + } + + private String getSetterName(Element enclosedElement) { + return enclosedElement.getAnnotation(ZenCodeType.Setter.class).value(); + } + + private AbstractTypeInfo getTypeInfo(ExecutableElement enclosedElement) { + if(isGetter(enclosedElement)) { + return getGetterTypeInfo(enclosedElement); + } else { + return getSetterTypeInfo(enclosedElement); + } + } + + private AbstractTypeInfo getGetterTypeInfo(ExecutableElement enclosedElement) { + final TypeMirror returnType = enclosedElement.getReturnType(); + return typeConverter.convertType(returnType); + } + + private AbstractTypeInfo getSetterTypeInfo(ExecutableElement enclosedElement) { + final TypeMirror typeMirror = enclosedElement.getParameters().get(0).asType(); + return typeConverter.convertType(typeMirror); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/expansion/member/ExpansionMethodConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/expansion/member/ExpansionMethodConverter.java new file mode 100644 index 000000000..266530ec1 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/expansion/member/ExpansionMethodConverter.java @@ -0,0 +1,79 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.expansion.member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.CommentConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.AbstractEnclosedElementConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.header.HeaderConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment.DocumentationComment; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.DocumentationPageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.TypePageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.MemberHeader; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member.DocumentedVirtualMembers; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member.VirtualMethodMember; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; +import org.openzen.zencode.java.ZenCodeType; + +import javax.lang.model.element.*; +import javax.lang.model.type.TypeMirror; +import java.util.Collections; +import java.util.List; + +public class ExpansionMethodConverter extends AbstractEnclosedElementConverter { + + private final CommentConverter commentConverter; + private final HeaderConverter headerConverter; + private final TypeConverter typeConverter; + + public ExpansionMethodConverter(CommentConverter commentConverter, HeaderConverter headerConverter, TypeConverter typeConverter) { + this.commentConverter = commentConverter; + this.headerConverter = headerConverter; + this.typeConverter = typeConverter; + } + + @Override + public boolean canConvert(Element enclosedElement) { + return isAnnotationPresentOn(ZenCodeType.Method.class, enclosedElement); + } + + @Override + public void convertAndAddTo(Element enclosedElement, DocumentedVirtualMembers result, DocumentationPageInfo pageInfo) { + final ExecutableElement method = (ExecutableElement) enclosedElement; + final VirtualMethodMember convertedMethod = convert(method, pageInfo); + final AbstractTypeInfo ownerTypeInfo = getOwnerTypeInfo(pageInfo); + + result.addMethod(convertedMethod, ownerTypeInfo); + } + + private AbstractTypeInfo getOwnerTypeInfo(DocumentationPageInfo pageInfo) { + return typeConverter.convertByName(((TypePageInfo) pageInfo).zenCodeName); + } + + private VirtualMethodMember convert(ExecutableElement method, DocumentationPageInfo pageInfo) { + final String name = method.getSimpleName().toString(); + final DocumentationComment description = commentConverter.convertForMethod(method, pageInfo); + final MemberHeader header = convertHeader(method); + + return new VirtualMethodMember(header, description, name); + } + + private MemberHeader convertHeader(ExecutableElement method) { + final List parameters = getParametersFor(method); + final List typeParameters = getTypeParametersFor(method); + final TypeMirror returnType = method.getReturnType(); + return headerConverter.convertHeaderFor(parameters, typeParameters, returnType); + } + + private List getParametersFor(ExecutableElement method) { + final List parameters = method.getParameters(); + if(parameters.isEmpty()) { + //Error, but caught in Validator AP + return Collections.emptyList(); + } + + return parameters.subList(1, parameters.size()); + } + + private List getTypeParametersFor(ExecutableElement method) { + return method.getTypeParameters(); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/expansion/member/ExpansionVirtualMemberConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/expansion/member/ExpansionVirtualMemberConverter.java new file mode 100644 index 000000000..bfa87f0b3 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/expansion/member/ExpansionVirtualMemberConverter.java @@ -0,0 +1,30 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.expansion.member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.MemberConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.dependencies.DependencyContainer; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.DocumentationPageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member.DocumentedVirtualMembers; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.Modifier; + +public class ExpansionVirtualMemberConverter extends MemberConverter { + + public ExpansionVirtualMemberConverter(DependencyContainer dependencyContainer) { + //TODO: Add converters + addElementConverter(ElementKind.METHOD, dependencyContainer.getInstanceOfClass(ExpansionMethodConverter.class)); + addElementConverter(ElementKind.METHOD, dependencyContainer.getInstanceOfClass(ExpansionCasterConverter.class)); + addElementConverter(ElementKind.METHOD, dependencyContainer.getInstanceOfClass(ExpansionGetterSetterConverter.class)); + } + + @Override + protected DocumentedVirtualMembers createResultObject(DocumentationPageInfo pageInfo) { + return new DocumentedVirtualMembers(); + } + + @Override + protected boolean isCandidate(Element enclosedElement) { + return enclosedElement.getModifiers().contains(Modifier.STATIC); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/AbstractEnclosedElementConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/AbstractEnclosedElementConverter.java new file mode 100644 index 000000000..b5a44e8d1 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/AbstractEnclosedElementConverter.java @@ -0,0 +1,21 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.DocumentationPageInfo; + +import javax.lang.model.element.Element; +import java.lang.annotation.Annotation; + +public abstract class AbstractEnclosedElementConverter { + + + protected AbstractEnclosedElementConverter() { + } + + protected boolean isAnnotationPresentOn(Class annotationClass, Element element) { + return element.getAnnotation(annotationClass) != null; + } + + public abstract boolean canConvert(Element enclosedElement); + + public abstract void convertAndAddTo(Element enclosedElement, T result, DocumentationPageInfo pageInfo); +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/MemberConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/MemberConverter.java new file mode 100644 index 000000000..8f719f69a --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/MemberConverter.java @@ -0,0 +1,52 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.DocumentationPageInfo; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.TypeElement; +import java.util.ArrayList; +import java.util.Collections; +import java.util.EnumMap; +import java.util.List; + +public abstract class MemberConverter { + + private final EnumMap>> elementConverters = new EnumMap<>(ElementKind.class); + + protected abstract boolean isCandidate(Element enclosedElement); + + protected abstract T createResultObject(DocumentationPageInfo pageInfo); + + public T convertFor(TypeElement typeElement, DocumentationPageInfo pageInfo) { + final T result = createResultObject(pageInfo); + for(Element enclosedElement : typeElement.getEnclosedElements()) { + convertMemberFor(enclosedElement, result, pageInfo); + } + + return result; + } + + private void convertMemberFor(Element enclosedElement, T result, DocumentationPageInfo pageInfo) { + if(!isCandidate(enclosedElement)) { + return; + } + + final ElementKind kind = enclosedElement.getKind(); + final List> converters = getConvertersFor(kind); + for(AbstractEnclosedElementConverter converter : converters) { + if(converter.canConvert(enclosedElement)) { + converter.convertAndAddTo(enclosedElement, result, pageInfo); + } + } + } + + private List> getConvertersFor(ElementKind kind) { + return elementConverters.getOrDefault(kind, Collections.emptyList()); + } + + protected void addElementConverter(ElementKind kind, AbstractEnclosedElementConverter expansionMethodConverter) { + elementConverters.computeIfAbsent(kind, ignored -> new ArrayList<>()) + .add(expansionMethodConverter); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/header/GenericParameterConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/header/GenericParameterConverter.java new file mode 100644 index 000000000..f215e6c53 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/header/GenericParameterConverter.java @@ -0,0 +1,44 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.header; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.CommentConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment.DocumentationComment; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.DocumentedGenericParameter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; + +import javax.lang.model.element.TypeParameterElement; +import java.util.List; +import java.util.stream.Collectors; + +public class GenericParameterConverter { + + private final TypeConverter typeConverter; + private final CommentConverter commentConverter; + + public GenericParameterConverter(TypeConverter typeConverter, CommentConverter commentConverter) { + this.typeConverter = typeConverter; + this.commentConverter = commentConverter; + } + + public DocumentedGenericParameter convertGenericParameter(TypeParameterElement typeParameterElement) { + final String name = convertName(typeParameterElement); + final List bounds = convertBounds(typeParameterElement); + final DocumentationComment comment = convertComment(typeParameterElement); + + return new DocumentedGenericParameter(bounds, name, comment); + } + + private String convertName(TypeParameterElement typeParameterElement) { + return typeParameterElement.getSimpleName().toString(); + } + + private DocumentationComment convertComment(TypeParameterElement typeParameterElement) { + return commentConverter.convertForTypeParameter(typeParameterElement); + } + + private List convertBounds(TypeParameterElement typeParameterElement) { + return typeParameterElement.getBounds().stream() + .map(typeConverter::convertType) + .collect(Collectors.toList()); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/header/HeaderConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/header/HeaderConverter.java new file mode 100644 index 000000000..a530ac685 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/header/HeaderConverter.java @@ -0,0 +1,81 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.header; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.DocumentedGenericParameter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.DocumentedParameter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.MemberHeader; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; + +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.TypeParameterElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Types; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class HeaderConverter { + + private final TypeConverter typeConverter; + private final ParameterConverter parameterConverter; + private final GenericParameterConverter genericParameterConverter; + private final Types typeUtils; + + public HeaderConverter(TypeConverter typeConverter, ParameterConverter parameterConverter, GenericParameterConverter genericParameterConverter, Types typeUtils) { + this.typeConverter = typeConverter; + this.parameterConverter = parameterConverter; + this.genericParameterConverter = genericParameterConverter; + this.typeUtils = typeUtils; + } + + public MemberHeader convertHeaderFor(List parameters, List typeParameters, TypeMirror returnType) { + final AbstractTypeInfo returnTypeInfo = convertReturnType(returnType); + final List documentedParameters = convertParameters(parameters, typeParameters); + final List genericParameters = convertGenericParameters(typeParameters); + + return new MemberHeader(returnTypeInfo, documentedParameters, genericParameters); + } + + private AbstractTypeInfo convertReturnType(TypeMirror returnType) { + return typeConverter.convertType(returnType); + } + + private List convertParameters(List parameters, List typeParameters) { + parameters = new ArrayList<>(parameters); + removeClassParametersIfPresent(parameters, typeParameters.size()); + + return parameters.stream() + .map(parameterConverter::convertParameter) + .collect(Collectors.toList()); + } + + private void removeClassParametersIfPresent(List parameters, int maximumNumberOfParameters) { + for(int i = 0; i < maximumNumberOfParameters; i++) { + final VariableElement variableElement = parameters.get(0); + final Element element = typeUtils.asElement(variableElement.asType()); + if(isNoClassParameter(element)) { + return; + } else { + parameters.remove(0); + } + } + } + + private boolean isNoClassParameter(Element element) { + return !(element instanceof TypeElement) || !isClassType((TypeElement) element); + } + + private boolean isClassType(TypeElement element) { + return element.getQualifiedName().toString().equals(Class.class.getCanonicalName()); + } + + private List convertGenericParameters(List typeParameters) { + return typeParameters.stream() + .map(genericParameterConverter::convertGenericParameter) + .collect(Collectors.toList()); + } + + +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/header/OptionalParameterConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/header/OptionalParameterConverter.java new file mode 100644 index 000000000..2766b6255 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/header/OptionalParameterConverter.java @@ -0,0 +1,61 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.header; + +import org.openzen.zencode.java.*; + +import javax.lang.model.element.*; +import java.lang.annotation.*; +import java.util.*; +import java.util.function.*; + +public class OptionalParameterConverter { + + private final Map, Function> optionalAnnotations; + + public OptionalParameterConverter() { + optionalAnnotations = new HashMap<>(); + addOptionalAnnotations(); + } + + private void addOptionalAnnotations() { + addOptionalAnnotation(ZenCodeType.Optional.class, ZenCodeType.Optional::value); + addOptionalAnnotation(ZenCodeType.OptionalInt.class, ZenCodeType.OptionalInt::value); + addOptionalAnnotation(ZenCodeType.OptionalDouble.class, ZenCodeType.OptionalDouble::value); + addOptionalAnnotation(ZenCodeType.OptionalLong.class, ZenCodeType.OptionalLong::value); + addOptionalAnnotation(ZenCodeType.OptionalFloat.class, ZenCodeType.OptionalFloat::value); + addOptionalAnnotation(ZenCodeType.OptionalString.class, ZenCodeType.OptionalString::value); + } + + private void addOptionalAnnotation(Class annotationClass, Function converter) { + optionalAnnotations.put(annotationClass, converter); + } + + public boolean isOptional(VariableElement variableElement) { + return optionalAnnotations.keySet().stream().anyMatch(hasAnnotation(variableElement)); + } + + private Predicate> hasAnnotation(VariableElement variableElement) { + return annotationClass -> isAnnotationPresent(variableElement, annotationClass); + } + + private boolean isAnnotationPresent(VariableElement variableElement, Class annotationClass) { + return variableElement.getAnnotation(annotationClass) != null; + } + + public String convertDefaultValue(VariableElement variableElement) { + for(Class aClass : optionalAnnotations.keySet()) { + if(isAnnotationPresent(variableElement, aClass)) { + return getDefaultValue(variableElement, aClass); + } + } + + + throw new IllegalStateException("ConvertDefaultValue should never be called if !isOptional"); + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + private String getDefaultValue(VariableElement variableElement, Class annotationClass) { + final Function objectFunction = optionalAnnotations.get(annotationClass); + final Annotation annotation = variableElement.getAnnotation(annotationClass); + return String.valueOf(objectFunction.apply(annotation)); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/header/ParameterConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/header/ParameterConverter.java new file mode 100644 index 000000000..09a031342 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/header/ParameterConverter.java @@ -0,0 +1,66 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.header; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.*; + +import javax.lang.model.element.*; + +public class ParameterConverter { + + private final CommentConverter commentConverter; + private final TypeConverter typeConverter; + private final OptionalParameterConverter optionalParameterConverter; + + public ParameterConverter(CommentConverter commentConverter, TypeConverter typeConverter, OptionalParameterConverter optionalParameterConverter) { + this.commentConverter = commentConverter; + this.typeConverter = typeConverter; + this.optionalParameterConverter = optionalParameterConverter; + } + + public DocumentedParameter convertParameter(VariableElement variableElement) { + if(isOptional(variableElement)) { + return convertOptionalParameter(variableElement); + } else { + return convertNonOptionalParameter(variableElement); + } + } + + private boolean isOptional(VariableElement variableElement) { + return optionalParameterConverter.isOptional(variableElement); + } + + private String convertDefaultValue(VariableElement variableElement) { + return optionalParameterConverter.convertDefaultValue(variableElement); + } + + private DocumentedParameter convertOptionalParameter(VariableElement variableElement) { + final String name = convertName(variableElement); + final AbstractTypeInfo type = convertType(variableElement); + final DocumentationComment comment = convertComment(variableElement); + final String defaultValue = convertDefaultValue(variableElement); + + return new DocumentedOptionalParameter(name, type, comment, defaultValue); + } + + private DocumentedParameter convertNonOptionalParameter(VariableElement variableElement) { + final String name = convertName(variableElement); + final AbstractTypeInfo type = convertType(variableElement); + final DocumentationComment comment = convertComment(variableElement); + return new DocumentedParameter(name, type, comment); + } + + private String convertName(VariableElement variableElement) { + return variableElement.getSimpleName().toString(); + } + + private AbstractTypeInfo convertType(VariableElement variableElement) { + return typeConverter.convertType(variableElement.asType()); + } + + private DocumentationComment convertComment(VariableElement variableElement) { + return commentConverter.convertForParameter(variableElement); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/header/ParameterDescriptionConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/header/ParameterDescriptionConverter.java new file mode 100644 index 000000000..ecdd87c88 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/header/ParameterDescriptionConverter.java @@ -0,0 +1,68 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.header; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.documentation_parameter.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.examples.*; + +import javax.annotation.*; +import javax.lang.model.element.*; +import javax.lang.model.util.*; + +public class ParameterDescriptionConverter { + + private final ParameterReader parameterReader; + private final Elements elementUtils; + + + public ParameterDescriptionConverter(ParameterReader parameterReader, Elements elementUtils) { + this.parameterReader = parameterReader; + this.elementUtils = elementUtils; + } + + public DocumentationComment convertDescriptionOf(Element parameter) { + final Element method = parameter.getEnclosingElement(); + final String methodDocComment = elementUtils.getDocComment(method); + final ParameterInformationList parameterInformationList = parameterReader.readParametersFrom(methodDocComment, method); + + return readDescriptionOf(parameter, parameterInformationList); + } + + private DocumentationComment readDescriptionOf(Element parameter, ParameterInformationList parameterInformationList) { + if(!parameterInformationList.hasParameterInfoWithName("param")) { + return DocumentationComment.empty(); + } + + final ParameterInfo param = parameterInformationList.getParameterInfoWithName("param"); + return getCommentForName(parameter, param); + } + + private DocumentationComment getCommentForName(Element element, ParameterInfo param) { + final String description = getDescriptionForParameterInfo(element, param); + return new DocumentationComment(description, ExampleData.empty()); + } + + @Nullable + private String getDescriptionForParameterInfo(Element element, ParameterInfo param) { + final String name = getName(element); + + for(String occurrence : param.getOccurrences()) { + if(occurrence.startsWith(name)) { + return occurrence.substring(name.length()).trim(); + } + } + return null; + } + + private String getName(Element element) { + final String simpleName = element.getSimpleName().toString(); + if(isTypeParameter(element)) { + return "<" + simpleName + ">"; + } else { + return simpleName; + } + } + + private boolean isTypeParameter(Element element) { + return element.getKind() == ElementKind.TYPE_PARAMETER; + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/static_member/NamedTypeStaticMethodConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/static_member/NamedTypeStaticMethodConverter.java new file mode 100644 index 000000000..83ae44481 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/static_member/NamedTypeStaticMethodConverter.java @@ -0,0 +1,166 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.static_member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.CommentConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.documentation_parameter.ReturnTypeInfoReader; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.AbstractEnclosedElementConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.header.HeaderConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.element.AnnotationMirrorUtil; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment.DocumentationComment; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.DocumentationPageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.TypeName; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.TypePageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.MemberHeader; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.static_member.BracketExpressionStaticMethodMember; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.static_member.DocumentedStaticMembers; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.static_member.StaticMethodMember; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; +import org.openzen.zencode.java.ZenCodeType; + +import javax.annotation.Nullable; +import javax.lang.model.element.*; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Types; +import java.util.ArrayList; +import java.util.List; + +public class NamedTypeStaticMethodConverter extends AbstractEnclosedElementConverter { + + private static final String BEPAnnotationClass = "com.blamejared.crafttweaker.api.annotations.BracketResolver"; + + private final CommentConverter commentConverter; + private final HeaderConverter headerConverter; + private final TypeConverter typeConverter; + private final AnnotationMirrorUtil annotationMirrorUtil; + private final ReturnTypeInfoReader returnTypeInfoReader; + private final Types typeUtils; + + public NamedTypeStaticMethodConverter(CommentConverter commentConverter, HeaderConverter headerConverter, TypeConverter typeConverter, AnnotationMirrorUtil annotationMirrorUtil, ReturnTypeInfoReader returnTypeInfoReader, Types typeUtils) { + this.commentConverter = commentConverter; + this.headerConverter = headerConverter; + this.typeConverter = typeConverter; + this.annotationMirrorUtil = annotationMirrorUtil; + this.returnTypeInfoReader = returnTypeInfoReader; + this.typeUtils = typeUtils; + } + + @Override + public boolean canConvert(Element enclosedElement) { + return isInNamedType(enclosedElement) && hasMethodAnnotation(enclosedElement); + } + + private boolean isInNamedType(Element enclosedElement) { + final Element enclosingElement = enclosedElement.getEnclosingElement(); + return isAnnotationPresentOn(ZenCodeType.Name.class, enclosingElement); + } + + private boolean hasMethodAnnotation(Element enclosedElement) { + return isAnnotationPresentOn(ZenCodeType.Method.class, enclosedElement); + } + + @Override + public void convertAndAddTo(Element enclosedElement, DocumentedStaticMembers result, DocumentationPageInfo pageInfo) { + final StaticMethodMember staticMethodMember = convertStaticMethodMember(enclosedElement, pageInfo); + final AbstractTypeInfo ownerType = getOwnerType(pageInfo); + + result.addMethod(staticMethodMember, ownerType); + } + + private StaticMethodMember convertStaticMethodMember(Element enclosedElement, DocumentationPageInfo pageInfo) { + ExecutableElement method = (ExecutableElement) enclosedElement; + + if(isBEPMethod(method)) { + return convertBEPMethodMember(method, pageInfo); + } else { + return convertMethodMember(method, pageInfo); + } + } + + private boolean isBEPMethod(ExecutableElement method) { + return annotationMirrorUtil.isAnnotationPresentOn(method, BEPAnnotationClass); + } + + private StaticMethodMember convertBEPMethodMember(ExecutableElement method, DocumentationPageInfo pageInfo) { + final String name = getName(method); + final MemberHeader header = getHeader(method); + final DocumentationComment comment = getComment(method, pageInfo); + final String bepName = getBepName(method); + final String returnTypeInfo = getReturnTypeInfo(method); + + return new BracketExpressionStaticMethodMember(name, header, comment, returnTypeInfo, bepName); + } + + private String getBepName(ExecutableElement method) { + final AnnotationMirror mirror = annotationMirrorUtil.getMirror(method, BEPAnnotationClass); + return annotationMirrorUtil.getAnnotationValue(mirror, "value"); + } + + private StaticMethodMember convertMethodMember(ExecutableElement method, DocumentationPageInfo pageInfo) { + final String name = getName(method); + final MemberHeader header = getHeader(method); + final DocumentationComment comment = getComment(method, pageInfo); + final String returnTypeInfo = getReturnTypeInfo(method); + + return new StaticMethodMember(name, header, comment, returnTypeInfo); + } + + @Nullable + private String getReturnTypeInfo(ExecutableElement method) { + return returnTypeInfoReader.readForMethod(method).orElse(null); + } + + private String getName(ExecutableElement method) { + if(hasCustomName(method)) { + return getCustomName(method); + } + return method.getSimpleName().toString(); + } + + private boolean hasCustomName(ExecutableElement method) { + return !getMethodAnnotation(method).value().isEmpty(); + } + + private String getCustomName(ExecutableElement method) { + return getMethodAnnotation(method).value(); + } + + private ZenCodeType.Method getMethodAnnotation(ExecutableElement method) { + return method.getAnnotation(ZenCodeType.Method.class); + } + + private MemberHeader getHeader(ExecutableElement enclosedElement) { + final List parameters = getParameters(enclosedElement); + final List typeParameters = getTypeParameters(enclosedElement); + final TypeMirror returnType = getReturnType(enclosedElement); + return headerConverter.convertHeaderFor(parameters, typeParameters, returnType); + } + + private List getParameters(ExecutableElement enclosedElement) { + return enclosedElement.getParameters(); + } + + private List getTypeParameters(ExecutableElement enclosedElement) { + return enclosedElement.getTypeParameters(); + } + + private TypeMirror getReturnType(ExecutableElement enclosedElement) { + return enclosedElement.getReturnType(); + } + + private DocumentationComment getComment(ExecutableElement enclosedElement, DocumentationPageInfo pageInfo) { + return commentConverter.convertForMethod(enclosedElement, pageInfo); + } + + private AbstractTypeInfo getOwnerType(DocumentationPageInfo pageInfo) { + if(pageInfo instanceof TypePageInfo) { + return getOwnerType(((TypePageInfo) pageInfo)); + } + + throw new IllegalStateException("Could not get OwnerType!"); + } + + private AbstractTypeInfo getOwnerType(TypePageInfo pageInfo) { + final TypeName zenCodeName = pageInfo.zenCodeName; + return typeConverter.convertByName(zenCodeName); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/static_member/StaticFieldConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/static_member/StaticFieldConverter.java new file mode 100644 index 000000000..7326202b7 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/static_member/StaticFieldConverter.java @@ -0,0 +1,39 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.static_member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.AbstractEnclosedElementConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.DocumentationPageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.PropertyMember; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.static_member.DocumentedStaticMembers; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; +import org.openzen.zencode.java.ZenCodeType; + +import javax.lang.model.element.Element; +import javax.lang.model.element.Modifier; +import javax.lang.model.type.TypeMirror; + +public class StaticFieldConverter extends AbstractEnclosedElementConverter { + + + private final TypeConverter typeConverter; + + public StaticFieldConverter(TypeConverter typeConverter) { + this.typeConverter = typeConverter; + } + + @Override + public boolean canConvert(Element enclosedElement) { + return isAnnotationPresentOn(ZenCodeType.Field.class, enclosedElement); + } + + @Override + public void convertAndAddTo(Element enclosedField, DocumentedStaticMembers result, DocumentationPageInfo pageInfo) { + final boolean isFinal = enclosedField.getModifiers().contains(Modifier.FINAL); + final String name = enclosedField.getSimpleName().toString(); + final TypeMirror typeMirror = enclosedField.asType(); + final AbstractTypeInfo fieldType = typeConverter.convertType(typeMirror); + + final PropertyMember propertyMember = new PropertyMember(name, fieldType, true, !isFinal); + result.addProperty(propertyMember); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/static_member/StaticMemberConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/static_member/StaticMemberConverter.java new file mode 100644 index 000000000..050d098c1 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/member/static_member/StaticMemberConverter.java @@ -0,0 +1,45 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.static_member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.AbstractEnclosedElementConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.MemberConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.dependencies.DependencyContainer; +import com.blamejared.crafttweaker_annotation_processors.processors.document.dependencies.IHasPostCreationCall; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.DocumentationPageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.static_member.DocumentedStaticMembers; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.Modifier; + +public class StaticMemberConverter extends MemberConverter implements IHasPostCreationCall { + + private final DependencyContainer dependencyContainer; + + public StaticMemberConverter(DependencyContainer dependencyContainer) { + this.dependencyContainer = dependencyContainer; + } + + @Override + protected DocumentedStaticMembers createResultObject(DocumentationPageInfo pageInfo) { + return new DocumentedStaticMembers(); + } + + @Override + protected boolean isCandidate(Element enclosedElement) { + return enclosedElement.getModifiers().contains(Modifier.STATIC); + } + + @Override + public void afterCreation() { + addElementConverters(); + } + + private void addElementConverters() { + addElementConverter(ElementKind.FIELD, StaticFieldConverter.class); + addElementConverter(ElementKind.METHOD, NamedTypeStaticMethodConverter.class); + } + + private void addElementConverter(ElementKind kind, Class> converterClass) { + addElementConverter(kind, dependencyContainer.getInstanceOfClass(converterClass)); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/ImplementationConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/ImplementationConverter.java new file mode 100644 index 000000000..5ed3085a9 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/ImplementationConverter.java @@ -0,0 +1,32 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.named_type; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; + +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +public class ImplementationConverter { + + private final TypeConverter typeConverter; + + public ImplementationConverter(TypeConverter typeConverter) { + this.typeConverter = typeConverter; + } + + public List convertInterfacesFor(TypeElement element) { + return element.getInterfaces() + .stream() + .map(this::convertInterface) + .filter(Optional::isPresent) + .map(Optional::get) + .collect(Collectors.toList()); + } + + private Optional convertInterface(TypeMirror typeMirror) { + return typeConverter.tryConvertType(typeMirror); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/NamedTypeConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/NamedTypeConverter.java new file mode 100644 index 000000000..150b308ef --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/NamedTypeConverter.java @@ -0,0 +1,104 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.named_type; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.DocumentConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.CommentConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.header.GenericParameterConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.static_member.StaticMemberConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.named_type.member.NamedTypeVirtualMemberConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.mods.KnownModList; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.DocumentationPageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.TypeName; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.TypePageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.DocumentedGenericParameter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.examples.Example; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.static_member.DocumentedStaticMembers; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member.DocumentedVirtualMembers; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.page.DocumentationPage; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.page.TypePage; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; +import org.openzen.zencode.java.ZenCodeType; + +import javax.annotation.Nonnull; +import javax.lang.model.element.TypeElement; +import java.util.List; +import java.util.stream.Collectors; + +public class NamedTypeConverter extends DocumentConverter { + + private final GenericParameterConverter genericParameterConverter; + private final SuperTypeConverter superTypeConverter; + private final NamedTypeVirtualMemberConverter namedTypeVirtualMemberConverter; + private final ImplementationConverter implementationConverter; + private final StaticMemberConverter staticMemberConverter; + + public NamedTypeConverter(KnownModList knownModList, CommentConverter commentConverter, GenericParameterConverter genericParameterConverter, SuperTypeConverter superTypeConverter, NamedTypeVirtualMemberConverter namedTypeVirtualMemberConverter, ImplementationConverter implementationConverter, StaticMemberConverter staticMemberConverter) { + super(knownModList, commentConverter); + + this.genericParameterConverter = genericParameterConverter; + this.superTypeConverter = superTypeConverter; + this.namedTypeVirtualMemberConverter = namedTypeVirtualMemberConverter; + this.implementationConverter = implementationConverter; + this.staticMemberConverter = staticMemberConverter; + } + + @Override + public boolean canConvert(TypeElement typeElement) { + return typeElement.getAnnotation(ZenCodeType.Name.class) != null; + } + + @Override + protected DocumentationPageInfo prepareConversion(TypeElement element) { + final DocumentationPageInfo documentationPageInfo = super.prepareConversion(element); + + final TypeName name = getName(element); + final String declaringModId = documentationPageInfo.declaringModId; + final String outputPath = documentationPageInfo.getOutputPath(); + return new TypePageInfo(declaringModId, outputPath, name); + } + + @Nonnull + private TypeName getName(TypeElement element) { + return new TypeName(element.getAnnotation(ZenCodeType.Name.class).value()); + } + + @Override + protected Example getFallbackThisInformationFor(TypeElement typeElement) { + final String text = "my" + getName(typeElement).getSimpleName(); + return new Example("this", text); + } + + @Override + public DocumentationPage convert(TypeElement typeElement, DocumentationPageInfo pageInfo) { + final TypePageInfo typePageInfo = (TypePageInfo) pageInfo; + final DocumentedVirtualMembers virtualMembers = convertVirtualMembers(typeElement, typePageInfo); + final DocumentedStaticMembers staticMembers = convertStaticMembers(typeElement, typePageInfo); + final AbstractTypeInfo superType = convertSuperType(typeElement); + final List implementations = convertImplementations(typeElement); + final List genericParameters = convertGenericParameters(typeElement); + + return new TypePage(typePageInfo, virtualMembers, superType, implementations, staticMembers, genericParameters); + } + + private DocumentedVirtualMembers convertVirtualMembers(TypeElement typeElement, TypePageInfo typePageInfo) { + return namedTypeVirtualMemberConverter.convertFor(typeElement, typePageInfo); + } + + private DocumentedStaticMembers convertStaticMembers(TypeElement typeElement, TypePageInfo typePageInfo) { + return staticMemberConverter.convertFor(typeElement, typePageInfo); + } + + private AbstractTypeInfo convertSuperType(TypeElement typeElement) { + return superTypeConverter.convertSuperTypeFor(typeElement).orElse(null); + } + + private List convertImplementations(TypeElement typeElement) { + return implementationConverter.convertInterfacesFor(typeElement); + } + + private List convertGenericParameters(TypeElement typeElement) { + return typeElement.getTypeParameters() + .stream() + .map(genericParameterConverter::convertGenericParameter) + .collect(Collectors.toList()); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/SuperTypeConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/SuperTypeConverter.java new file mode 100644 index 000000000..744f26e4e --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/SuperTypeConverter.java @@ -0,0 +1,39 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.named_type; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; + +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import java.util.Optional; + +public class SuperTypeConverter { + + private final TypeConverter typeConverter; + + public SuperTypeConverter(TypeConverter typeConverter) { + this.typeConverter = typeConverter; + } + + public Optional convertSuperTypeFor(TypeElement element) { + if(!hasSuperType(element)) { + return Optional.empty(); + } + + return convertSuperType(element); + } + + private Optional convertSuperType(TypeElement element) { + return typeConverter.tryConvertType(element.getSuperclass()); + } + + private boolean hasSuperType(TypeElement element) { + final TypeMirror superclass = element.getSuperclass(); + return !superTypeIsObject(superclass) && superclass.getKind() != TypeKind.NONE; + } + + private boolean superTypeIsObject(TypeMirror superclass) { + return superclass.toString().equals("java.lang.Object"); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/member/NamedTypeVirtualCasterConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/member/NamedTypeVirtualCasterConverter.java new file mode 100644 index 000000000..d19986f8b --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/member/NamedTypeVirtualCasterConverter.java @@ -0,0 +1,77 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.named_type.member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.CommentConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.AbstractEnclosedElementConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.header.HeaderConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment.DocumentationComment; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.DocumentationPageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.MemberHeader; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member.CasterMember; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member.DocumentedTypeVirtualMembers; +import org.openzen.zencode.java.ZenCodeType; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeParameterElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeMirror; +import java.util.List; + +public class NamedTypeVirtualCasterConverter extends AbstractEnclosedElementConverter { + + private final HeaderConverter headerConverter; + private final CommentConverter commentConverter; + + public NamedTypeVirtualCasterConverter(HeaderConverter headerConverter, CommentConverter commentConverter) { + this.headerConverter = headerConverter; + this.commentConverter = commentConverter; + } + + @Override + public boolean canConvert(Element enclosedElement) { + return isAnnotationPresentOn(ZenCodeType.Caster.class, enclosedElement); + } + + @Override + public void convertAndAddTo(Element enclosedElement, DocumentedTypeVirtualMembers result, DocumentationPageInfo pageInfo) { + ExecutableElement method = (ExecutableElement) enclosedElement; + final CasterMember casterMember = convertCaster(method, pageInfo); + result.addCaster(casterMember); + } + + private CasterMember convertCaster(ExecutableElement method, DocumentationPageInfo pageInfo) { + final MemberHeader header = convertHeader(method); + final DocumentationComment comment = convertComment(method, pageInfo); + final boolean isImplicit = checkIfImplicit(method); + + return new CasterMember(header, comment, isImplicit); + } + + private MemberHeader convertHeader(ExecutableElement method) { + final List parameters = convertParameters(method); + final List typeParameters = convertTypeParameters(method); + final TypeMirror returnType = convertReturnType(method); + + return headerConverter.convertHeaderFor(parameters, typeParameters, returnType); + } + + private List convertParameters(ExecutableElement method) { + return method.getParameters(); + } + + private List convertTypeParameters(ExecutableElement method) { + return method.getTypeParameters(); + } + + private TypeMirror convertReturnType(ExecutableElement method) { + return method.getReturnType(); + } + + private DocumentationComment convertComment(ExecutableElement method, DocumentationPageInfo pageInfo) { + return commentConverter.convertForMethod(method, pageInfo); + } + + private boolean checkIfImplicit(ExecutableElement method) { + return method.getAnnotation(ZenCodeType.Caster.class).implicit(); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/member/NamedTypeVirtualConstructorConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/member/NamedTypeVirtualConstructorConverter.java new file mode 100644 index 000000000..c86d1a935 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/member/NamedTypeVirtualConstructorConverter.java @@ -0,0 +1,68 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.named_type.member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.header.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member.*; +import org.openzen.zencode.java.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import java.util.*; + +public class NamedTypeVirtualConstructorConverter extends AbstractEnclosedElementConverter { + + private final HeaderConverter headerConverter; + private final CommentConverter commentConverter; + + public NamedTypeVirtualConstructorConverter(HeaderConverter headerConverter, CommentConverter commentConverter) { + this.headerConverter = headerConverter; + this.commentConverter = commentConverter; + } + + @Override + public boolean canConvert(Element enclosedElement) { + return isAnnotationPresentOn(ZenCodeType.Constructor.class, enclosedElement); + } + + @Override + public void convertAndAddTo(Element enclosedElement, DocumentedTypeVirtualMembers result, DocumentationPageInfo pageInfo) { + final ConstructorMember constructorMember = convertConstructor(enclosedElement, pageInfo); + result.addConstructor(constructorMember); + } + + private ConstructorMember convertConstructor(Element enclosedElement, DocumentationPageInfo pageInfo) { + ExecutableElement constructor = (ExecutableElement) enclosedElement; + final MemberHeader header = convertHeader(constructor); + final DocumentationComment comment = convertComment(constructor, pageInfo); + + return new ConstructorMember(header, comment); + } + + private MemberHeader convertHeader(ExecutableElement constructor) { + final List parameters = convertParameters(constructor); + final List typeParameters = convertTypeParameters(constructor); + final TypeMirror returnType = convertReturnType(constructor); + + return headerConverter.convertHeaderFor(parameters, typeParameters, returnType); + } + + private List convertParameters(ExecutableElement constructor) { + return constructor.getParameters(); + } + + private List convertTypeParameters(ExecutableElement constructor) { + return constructor.getTypeParameters(); + } + + private TypeMirror convertReturnType(ExecutableElement element) { + return element.getEnclosingElement().asType(); + } + + private DocumentationComment convertComment(ExecutableElement enclosedElement, DocumentationPageInfo pageInfo) { + return commentConverter.convertForConstructor(enclosedElement, pageInfo); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/member/NamedTypeVirtualFieldConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/member/NamedTypeVirtualFieldConverter.java new file mode 100644 index 000000000..7fd6166ca --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/member/NamedTypeVirtualFieldConverter.java @@ -0,0 +1,61 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.named_type.member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.AbstractEnclosedElementConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.DocumentationPageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.PropertyMember; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member.DocumentedTypeVirtualMembers; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; +import org.openzen.zencode.java.ZenCodeType; + +import javax.lang.model.element.Element; +import javax.lang.model.element.Modifier; + +public class NamedTypeVirtualFieldConverter extends AbstractEnclosedElementConverter { + + private final TypeConverter typeConverter; + + public NamedTypeVirtualFieldConverter(TypeConverter typeConverter) { + this.typeConverter = typeConverter; + } + + @Override + public boolean canConvert(Element enclosedElement) { + return isAnnotationPresentOn(ZenCodeType.Field.class, enclosedElement); + } + + @Override + public void convertAndAddTo(Element enclosedElement, DocumentedTypeVirtualMembers result, DocumentationPageInfo pageInfo) { + final PropertyMember property = convertProperty(enclosedElement); + result.addProperty(property); + } + + private PropertyMember convertProperty(Element enclosedElement) { + final String name = convertName(enclosedElement); + final AbstractTypeInfo type = convertType(enclosedElement); + final boolean hasGetter = convertHasGetter(); + final boolean hasSetter = convertHasSetter(enclosedElement); + + return new PropertyMember(name, type, hasGetter, hasSetter); + } + + private String convertName(Element enclosedElement) { + return enclosedElement.getSimpleName().toString(); + } + + private AbstractTypeInfo convertType(Element enclosedElement) { + return typeConverter.convertType(enclosedElement.asType()); + } + + private boolean convertHasGetter() { + return true; + } + + private boolean convertHasSetter(Element enclosedElement) { + return isMutable(enclosedElement); + } + + private boolean isMutable(Element enclosedElement) { + return !enclosedElement.getModifiers().contains(Modifier.FINAL); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/member/NamedTypeVirtualGetterSetterConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/member/NamedTypeVirtualGetterSetterConverter.java new file mode 100644 index 000000000..1bde98e87 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/member/NamedTypeVirtualGetterSetterConverter.java @@ -0,0 +1,65 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.named_type.member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.AbstractEnclosedElementConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.DocumentationPageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.PropertyMember; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member.DocumentedTypeVirtualMembers; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; +import org.openzen.zencode.java.ZenCodeType; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.type.TypeMirror; + +public class NamedTypeVirtualGetterSetterConverter extends AbstractEnclosedElementConverter { + + private final TypeConverter typeConverter; + + public NamedTypeVirtualGetterSetterConverter(TypeConverter typeConverter) { + this.typeConverter = typeConverter; + } + + @Override + public boolean canConvert(Element enclosedElement) { + return isAnnotationPresentOn(ZenCodeType.Setter.class, enclosedElement) || isAnnotationPresentOn(ZenCodeType.Getter.class, enclosedElement); + } + + @Override + public void convertAndAddTo(Element enclosedElement, DocumentedTypeVirtualMembers result, DocumentationPageInfo pageInfo) { + final ExecutableElement method = (ExecutableElement) enclosedElement; + final PropertyMember propertyMember = convertMember(method); + + result.addProperty(propertyMember); + } + + private PropertyMember convertMember(ExecutableElement method) { + final String name = convertName(method); + final AbstractTypeInfo typeInfo = convertType(method); + final boolean hasGetter = convertHasGetter(method); + final boolean hasSetter = convertHasSetter(method); + + return new PropertyMember(name, typeInfo, hasGetter, hasSetter); + } + + private String convertName(ExecutableElement enclosedElement) { + if(isAnnotationPresentOn(ZenCodeType.Getter.class, enclosedElement)) { + return enclosedElement.getAnnotation(ZenCodeType.Getter.class).value(); + } else { + return enclosedElement.getAnnotation(ZenCodeType.Setter.class).value(); + } + } + + private AbstractTypeInfo convertType(ExecutableElement enclosedElement) { + final TypeMirror returnType = enclosedElement.getReturnType(); + return typeConverter.convertType(returnType); + } + + private boolean convertHasGetter(ExecutableElement enclosedElement) { + return isAnnotationPresentOn(ZenCodeType.Getter.class, enclosedElement); + } + + private boolean convertHasSetter(ExecutableElement enclosedElement) { + return isAnnotationPresentOn(ZenCodeType.Setter.class, enclosedElement); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/member/NamedTypeVirtualMemberConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/member/NamedTypeVirtualMemberConverter.java new file mode 100644 index 000000000..703c086ae --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/member/NamedTypeVirtualMemberConverter.java @@ -0,0 +1,52 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.named_type.member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.MemberConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.dependencies.DependencyContainer; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.DocumentationPageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member.DocumentedTypeVirtualMembers; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.Modifier; + +public class NamedTypeVirtualMemberConverter extends MemberConverter { + + public NamedTypeVirtualMemberConverter(DependencyContainer dependencyContainer) { + addConverters(dependencyContainer); + } + + @Override + protected boolean isCandidate(Element enclosedElement) { + return isVirtual(enclosedElement); + } + + @Override + protected DocumentedTypeVirtualMembers createResultObject(DocumentationPageInfo pageInfo) { + return new DocumentedTypeVirtualMembers(); + } + + private void addConverters(DependencyContainer dependencyContainer) { + addMethodConverters(dependencyContainer); + addFieldConverters(dependencyContainer); + addConstructorConverters(dependencyContainer); + } + + private void addMethodConverters(DependencyContainer dependencyContainer) { + addElementConverter(ElementKind.METHOD, dependencyContainer.getInstanceOfClass(NamedTypeVirtualMethodConverter.class)); + addElementConverter(ElementKind.METHOD, dependencyContainer.getInstanceOfClass(NamedTypeVirtualCasterConverter.class)); + addElementConverter(ElementKind.METHOD, dependencyContainer.getInstanceOfClass(NamedTypeVirtualGetterSetterConverter.class)); + addElementConverter(ElementKind.METHOD, dependencyContainer.getInstanceOfClass(NamedTypeVirtualOperatorConverter.class)); + } + + private void addFieldConverters(DependencyContainer dependencyContainer) { + addElementConverter(ElementKind.FIELD, dependencyContainer.getInstanceOfClass(NamedTypeVirtualFieldConverter.class)); + } + + private void addConstructorConverters(DependencyContainer dependencyContainer) { + addElementConverter(ElementKind.CONSTRUCTOR, dependencyContainer.getInstanceOfClass(NamedTypeVirtualConstructorConverter.class)); + } + + private boolean isVirtual(Element enclosedElement) { + return !enclosedElement.getModifiers().contains(Modifier.STATIC); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/member/NamedTypeVirtualMethodConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/member/NamedTypeVirtualMethodConverter.java new file mode 100644 index 000000000..317c23f6a --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/member/NamedTypeVirtualMethodConverter.java @@ -0,0 +1,90 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.named_type.member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.CommentConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.AbstractEnclosedElementConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.header.HeaderConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment.DocumentationComment; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.DocumentationPageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.TypePageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.MemberHeader; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member.DocumentedTypeVirtualMembers; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member.VirtualMethodMember; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; +import org.openzen.zencode.java.ZenCodeType; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeParameterElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Types; +import java.util.List; + +public class NamedTypeVirtualMethodConverter extends AbstractEnclosedElementConverter { + + private final TypeConverter typeConverter; + private final HeaderConverter headerConverter; + private final CommentConverter commentConverter; + private final Types typeUtils; + + public NamedTypeVirtualMethodConverter(TypeConverter typeConverter, HeaderConverter headerConverter, CommentConverter commentConverter, Types typeUtils) { + this.typeConverter = typeConverter; + this.headerConverter = headerConverter; + this.commentConverter = commentConverter; + this.typeUtils = typeUtils; + } + + @Override + public boolean canConvert(Element enclosedElement) { + return isAnnotationPresentOn(ZenCodeType.Method.class, enclosedElement); + } + + @Override + public void convertAndAddTo(Element enclosedElement, DocumentedTypeVirtualMembers result, DocumentationPageInfo pageInfo) { + ExecutableElement methodElement = (ExecutableElement) enclosedElement; + final AbstractTypeInfo ownerType = getOwnerType(pageInfo); + final VirtualMethodMember methodMember = convertMethod(methodElement, pageInfo); + result.addMethod(methodMember, ownerType); + } + + private VirtualMethodMember convertMethod(ExecutableElement enclosedElement, DocumentationPageInfo pageInfo) { + final String name = convertName(enclosedElement); + final MemberHeader header = convertHeader(enclosedElement); + final DocumentationComment comment = convertComment(enclosedElement, pageInfo); + + return new VirtualMethodMember(header, comment, name); + } + + private DocumentationComment convertComment(ExecutableElement enclosedElement, DocumentationPageInfo pageInfo) { + return commentConverter.convertForMethod(enclosedElement, pageInfo); + } + + private MemberHeader convertHeader(ExecutableElement enclosedElement) { + final List parameters = getParameters(enclosedElement); + final List typeParameters = enclosedElement.getTypeParameters(); + final TypeMirror returnType = enclosedElement.getReturnType(); + + return headerConverter.convertHeaderFor(parameters, typeParameters, returnType); + } + + private List getParameters(ExecutableElement enclosedElement) { + return enclosedElement.getParameters(); + } + + private String convertName(ExecutableElement enclosedElement) { + return enclosedElement.getSimpleName().toString(); + } + + private AbstractTypeInfo getOwnerType(DocumentationPageInfo pageInfo) { + if(pageInfo instanceof TypePageInfo) { + return getOwnerType((TypePageInfo) pageInfo); + } + + throw new IllegalStateException("Could not get OwnerType!"); + } + + private AbstractTypeInfo getOwnerType(TypePageInfo pageInfo) { + return typeConverter.convertByName(pageInfo.zenCodeName); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/member/NamedTypeVirtualOperatorConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/member/NamedTypeVirtualOperatorConverter.java new file mode 100644 index 000000000..7f6023a93 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/named_type/member/NamedTypeVirtualOperatorConverter.java @@ -0,0 +1,92 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.named_type.member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.CommentConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.AbstractEnclosedElementConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.header.HeaderConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment.DocumentationComment; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.DocumentationPageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.TypePageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.MemberHeader; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member.DocumentedTypeVirtualMembers; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member.OperatorMember; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; +import org.openzen.zencode.java.ZenCodeType; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeParameterElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeMirror; +import java.util.List; + +public class NamedTypeVirtualOperatorConverter extends AbstractEnclosedElementConverter { + + private final CommentConverter commentConverter; + private final HeaderConverter headerConverter; + private final TypeConverter typeConverter; + + public NamedTypeVirtualOperatorConverter(CommentConverter commentConverter, HeaderConverter headerConverter, TypeConverter typeConverter) { + this.commentConverter = commentConverter; + this.headerConverter = headerConverter; + this.typeConverter = typeConverter; + } + + @Override + public boolean canConvert(Element enclosedElement) { + return isAnnotationPresentOn(ZenCodeType.Operator.class, enclosedElement); + } + + @Override + public void convertAndAddTo(Element enclosedElement, DocumentedTypeVirtualMembers result, DocumentationPageInfo pageInfo) { + ExecutableElement method = (ExecutableElement) enclosedElement; + final OperatorMember operatorMember = convertOperator(method, pageInfo); + + result.addOperator(operatorMember); + } + + private OperatorMember convertOperator(ExecutableElement method, DocumentationPageInfo pageInfo) { + final MemberHeader header = convertHeader(method); + final DocumentationComment comment = convertComment(method, pageInfo); + final ZenCodeType.OperatorType type = convertType(method); + final AbstractTypeInfo ownerType = convertOwnerType(pageInfo); + + return new OperatorMember(header, comment, type, ownerType); + } + + private AbstractTypeInfo convertOwnerType(DocumentationPageInfo pageInfo) { + if(pageInfo instanceof TypePageInfo) { + return typeConverter.convertByName(((TypePageInfo) pageInfo).zenCodeName); + } + + throw new IllegalArgumentException("Cannot get ownerType from " + pageInfo.getSimpleName()); + } + + private MemberHeader convertHeader(ExecutableElement method) { + final List parameters = convertParameters(method); + final List typeParameters = convertTypeParameters(method); + final TypeMirror returnType = convertReturnType(method); + + return headerConverter.convertHeaderFor(parameters, typeParameters, returnType); + } + + private List convertParameters(ExecutableElement method) { + return method.getParameters(); + } + + private List convertTypeParameters(ExecutableElement method) { + return method.getTypeParameters(); + } + + private TypeMirror convertReturnType(ExecutableElement method) { + return method.getReturnType(); + } + + private DocumentationComment convertComment(ExecutableElement method, DocumentationPageInfo pageInfo) { + return commentConverter.convertForMethod(method, pageInfo); + } + + private ZenCodeType.OperatorType convertType(ExecutableElement method) { + return method.getAnnotation(ZenCodeType.Operator.class).value(); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/native_registration/NativeRegistrationConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/native_registration/NativeRegistrationConverter.java new file mode 100644 index 000000000..d2b7b8ee0 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/native_registration/NativeRegistrationConverter.java @@ -0,0 +1,150 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.native_registration; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.NativeConversionRegistry; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.DocumentConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.comment.CommentConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.header.GenericParameterConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.member.static_member.StaticMemberConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.named_type.ImplementationConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.named_type.SuperTypeConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.native_registration.member.NativeTypeVirtualMemberConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.mods.KnownModList; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.DocumentationPageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.TypeName; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.TypePageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.DocumentedGenericParameter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.examples.Example; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.static_member.DocumentedStaticMembers; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member.DocumentedVirtualMembers; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.page.DocumentationPage; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.page.TypePage; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.TypePageTypeInfo; +import com.blamejared.crafttweaker_annotations.annotations.NativeTypeRegistration; + +import javax.annotation.Nonnull; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.MirroredTypeException; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Elements; +import javax.lang.model.util.Types; +import java.util.List; +import java.util.stream.Collectors; + +public class NativeRegistrationConverter extends DocumentConverter { + + private final StaticMemberConverter staticMemberConverter; + private final NativeTypeVirtualMemberConverter virtualMemberConverter; + private final SuperTypeConverter superTypeConverter; + private final ImplementationConverter implementationConverter; + private final GenericParameterConverter genericParameterConverter; + private final NativeConversionRegistry nativeConversionRegistry; + private final Elements elementUtils; + private final Types typeUtils; + + public NativeRegistrationConverter(KnownModList knownModList, CommentConverter commentConverter, StaticMemberConverter staticMemberConverter, NativeTypeVirtualMemberConverter virtualMemberConverter, SuperTypeConverter superTypeConverter, ImplementationConverter implementationConverter, GenericParameterConverter genericParameterConverter, NativeConversionRegistry nativeConversionRegistry, Elements elementUtils, Types typeUtils) { + super(knownModList, commentConverter); + this.staticMemberConverter = staticMemberConverter; + this.virtualMemberConverter = virtualMemberConverter; + this.superTypeConverter = superTypeConverter; + this.implementationConverter = implementationConverter; + this.genericParameterConverter = genericParameterConverter; + this.nativeConversionRegistry = nativeConversionRegistry; + this.elementUtils = elementUtils; + this.typeUtils = typeUtils; + } + + @Override + public boolean canConvert(TypeElement typeElement) { + return getNativeAnnotation(typeElement) != null; + } + + private NativeTypeRegistration getNativeAnnotation(TypeElement typeElement) { + return typeElement.getAnnotation(NativeTypeRegistration.class); + } + + @Override + protected TypePageInfo prepareConversion(TypeElement element) { + final TypePageInfo typePageInfo = createTypePageInfo(element); + registerNativeType(element, typePageInfo); + return typePageInfo; + } + + @Override + protected Example getFallbackThisInformationFor(TypeElement typeElement) { + final String text = "my" + getName(typeElement).getSimpleName(); + return new Example("this", text); + } + + private void registerNativeType(TypeElement element, TypePageInfo typePageInfo) { + final AbstractTypeInfo typeInfo = new TypePageTypeInfo(typePageInfo); + final TypeElement nativeType = getNativeType(element); + + nativeConversionRegistry.addNativeConversion(nativeType, typeInfo); + } + + private TypeElement getNativeType(TypeElement element) { + try { + final NativeTypeRegistration nativeAnnotation = getNativeAnnotation(element); + return getNativeTypeFromClass(nativeAnnotation.value()); + } catch(MirroredTypeException exception) { + final TypeMirror typeMirror = exception.getTypeMirror(); + return (TypeElement) typeUtils.asElement(typeMirror); + } + } + + private TypeElement getNativeTypeFromClass(Class cls) { + return elementUtils.getTypeElement(cls.getCanonicalName()); + } + + @Nonnull + private TypePageInfo createTypePageInfo(TypeElement element) { + final DocumentationPageInfo documentationPageInfo = super.prepareConversion(element); + + final TypeName name = getName(element); + final String declaringModId = documentationPageInfo.declaringModId; + final String outputPath = documentationPageInfo.getOutputPath(); + return new TypePageInfo(declaringModId, outputPath, name); + } + + @Nonnull + private TypeName getName(TypeElement element) { + return new TypeName(getNativeAnnotation(element).zenCodeName()); + } + + @Override + public DocumentationPage convert(TypeElement typeElement, DocumentationPageInfo pageInfo) { + final DocumentedVirtualMembers virtualMembers = convertVirtualMembers(typeElement, pageInfo); + final AbstractTypeInfo superType = convertSuperType(typeElement); + final List implementedInterfaces = convertImplementedInterfaces(typeElement); + final DocumentedStaticMembers staticMembers = convertStaticMembers(typeElement, pageInfo); + final List genericParameters = convertGenericParameters(typeElement); + + return new TypePage((TypePageInfo) pageInfo, virtualMembers, superType, implementedInterfaces, staticMembers, genericParameters); + } + + private DocumentedVirtualMembers convertVirtualMembers(TypeElement typeElement, DocumentationPageInfo pageInfo) { + return virtualMemberConverter.convertFor(typeElement, pageInfo); + } + + private AbstractTypeInfo convertSuperType(TypeElement typeElement) { + final TypeElement nativeType = getNativeType(typeElement); + return superTypeConverter.convertSuperTypeFor(nativeType).orElse(null); + } + + private List convertImplementedInterfaces(TypeElement typeElement) { + final TypeElement nativeType = getNativeType(typeElement); + return implementationConverter.convertInterfacesFor(nativeType); + } + + private DocumentedStaticMembers convertStaticMembers(TypeElement typeElement, DocumentationPageInfo pageInfo) { + return staticMemberConverter.convertFor(typeElement, pageInfo); + } + + private List convertGenericParameters(TypeElement typeElement) { + return typeElement.getTypeParameters() + .stream() + .map(genericParameterConverter::convertGenericParameter) + .collect(Collectors.toList()); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/native_registration/member/NativeTypeVirtualMemberConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/native_registration/member/NativeTypeVirtualMemberConverter.java new file mode 100644 index 000000000..1b3ad1cc5 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/native_registration/member/NativeTypeVirtualMemberConverter.java @@ -0,0 +1,147 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.native_registration.member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.expansion.member.ExpansionVirtualMemberConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.dependencies.DependencyContainer; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment.DocumentationComment; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.DocumentationPageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.TypePageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.DocumentedGenericParameter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.DocumentedParameter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.MemberHeader; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.examples.Example; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.examples.ExampleData; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member.ConstructorMember; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member.DocumentedTypeVirtualMembers; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member.DocumentedVirtualMembers; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; +import com.blamejared.crafttweaker_annotations.annotations.NativeConstructor; +import com.blamejared.crafttweaker_annotations.annotations.NativeTypeRegistration; + +import javax.annotation.Nonnull; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.MirroredTypeException; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Elements; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public class NativeTypeVirtualMemberConverter extends ExpansionVirtualMemberConverter { + + private final TypeConverter typeConverter; + private final Elements elementUtils; + + public NativeTypeVirtualMemberConverter(DependencyContainer dependencyContainer, TypeConverter typeConverter, Elements elementUtils) { + super(dependencyContainer); + this.typeConverter = typeConverter; + this.elementUtils = elementUtils; + } + + @Override + protected DocumentedVirtualMembers createResultObject(DocumentationPageInfo pageInfo) { + return new DocumentedTypeVirtualMembers(); + } + + @Override + public DocumentedVirtualMembers convertFor(TypeElement typeElement, DocumentationPageInfo pageInfo) { + final DocumentedVirtualMembers virtualMembers = super.convertFor(typeElement, pageInfo); + return addInjectedConstructors((DocumentedTypeVirtualMembers) virtualMembers, typeElement, (TypePageInfo) pageInfo); + } + + private DocumentedVirtualMembers addInjectedConstructors(DocumentedTypeVirtualMembers virtualMembers, TypeElement typeElement, TypePageInfo pageInfo) { + final NativeTypeRegistration nativeAnnotation = getNativeAnnotation(typeElement); + for(NativeConstructor constructor : nativeAnnotation.constructors()) { + final ConstructorMember constructorMember = getInjectedConstructor(constructor, pageInfo); + virtualMembers.addConstructor(constructorMember); + } + return virtualMembers; + } + + private ConstructorMember getInjectedConstructor(NativeConstructor constructor, TypePageInfo pageInfo) { + final MemberHeader header = getHeader(constructor.value(), pageInfo); + final DocumentationComment description = getDescription(constructor); + + + return new ConstructorMember(header, description); + } + + private DocumentationComment getDescription(NativeConstructor constructor) { + final String description = constructor.description(); + final ExampleData exampleData = ExampleData.empty(); + return new DocumentationComment(description, exampleData); + } + + private MemberHeader getHeader(NativeConstructor.ConstructorParameter[] parameters, TypePageInfo pageInfo) { + final List convertedParameters = getParameters(parameters); + final AbstractTypeInfo returnType = getReturnType(pageInfo); + final List genericParameters = Collections.emptyList(); + + return new MemberHeader(returnType, convertedParameters, genericParameters); + } + + private AbstractTypeInfo getReturnType(TypePageInfo pageInfo) { + return typeConverter.convertByName(pageInfo.zenCodeName); + } + + @Nonnull + private List getParameters(NativeConstructor.ConstructorParameter[] parameters) { + return Arrays.stream(parameters).map(this::convertParameter).collect(Collectors.toList()); + } + + private DocumentedParameter convertParameter(NativeConstructor.ConstructorParameter constructorParameter) { + final String name = getParameterName(constructorParameter); + final AbstractTypeInfo type = getParameterType(constructorParameter); + final DocumentationComment description = getParameterDescription(constructorParameter); + + return new DocumentedParameter(name, type, description); + } + + private AbstractTypeInfo getParameterType(NativeConstructor.ConstructorParameter constructorParameter) { + final TypeMirror mirror = getParameterTypeMirror(constructorParameter); + return typeConverter.convertType(mirror); + } + + private DocumentationComment getParameterDescription(NativeConstructor.ConstructorParameter constructorParameter) { + final String description = constructorParameter.description(); + final ExampleData exampleData = extractExampleDataForParameter(constructorParameter); + + return new DocumentationComment(description, exampleData); + } + + private ExampleData extractExampleDataForParameter(NativeConstructor.ConstructorParameter constructorParameter) { + final Example parameterExample = getParameterExample(constructorParameter); + return new ExampleData(parameterExample); + } + + private Example getParameterExample(NativeConstructor.ConstructorParameter constructorParameter) { + final String name = getParameterName(constructorParameter); + final Example result = new Example(name); + for(String textValue : constructorParameter.examples()) { + result.addTextValue(textValue); + } + return result; + } + + private TypeMirror getParameterTypeMirror(NativeConstructor.ConstructorParameter constructorParameter) { + try { + final Class type = constructorParameter.type(); + return getTypeMirrorFromClass(type); + } catch(MirroredTypeException exception) { + return exception.getTypeMirror(); + } + } + + private TypeMirror getTypeMirrorFromClass(Class type) { + return elementUtils.getTypeElement(type.getCanonicalName()).asType(); + } + + private String getParameterName(NativeConstructor.ConstructorParameter constructorParameter) { + return constructorParameter.name(); + } + + private NativeTypeRegistration getNativeAnnotation(TypeElement typeElement) { + return typeElement.getAnnotation(NativeTypeRegistration.class); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/TypeConversionRule.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/TypeConversionRule.java new file mode 100644 index 000000000..dc7fb1229 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/TypeConversionRule.java @@ -0,0 +1,14 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; + +import javax.annotation.Nullable; +import javax.lang.model.type.TypeMirror; + +public interface TypeConversionRule { + + boolean canConvert(TypeMirror mirror); + + @Nullable + AbstractTypeInfo convert(TypeMirror mirror); +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/TypeConverter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/TypeConverter.java new file mode 100644 index 000000000..82536c04d --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/TypeConverter.java @@ -0,0 +1,124 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.rules.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.rules.generic.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.dependencies.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.*; + +import javax.annotation.Nonnull; +import javax.lang.model.type.*; +import java.util.*; +import java.util.regex.MatchResult; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +public class TypeConverter implements IHasPostCreationCall { + + private final NativeConversionRegistry nativeConversionRegistry; + private final DocumentRegistry registry; + private final DependencyContainer dependencyContainer; + private final List rules = new ArrayList<>(); + + public TypeConverter(NativeConversionRegistry nativeConversionRegistry, DocumentRegistry registry, DependencyContainer dependencyContainer) { + this.nativeConversionRegistry = nativeConversionRegistry; + this.registry = registry; + this.dependencyContainer = dependencyContainer; + } + + public AbstractTypeInfo convertByName(TypeName name) { + final Optional pageInfoByName = registry.getPageInfoByName(name); + if(pageInfoByName.isPresent()) { + return new TypePageTypeInfo(pageInfoByName.get()); + } + + if(hasNativePageInfo(name)) { + return getNativePageInfo(name); + } + + if(isGeneric(name)) { + return getGeneric(name); + } + + //Problem: When preparing the ATIs we already convert the comments :thinking: + throw new UnsupportedOperationException("TODO: " + name.getZenCodeName()); + } + + private AbstractTypeInfo getGeneric(TypeName name) { + final Matcher matcher = getGenericMatcher(name); + if(!matcher.find()) { + throw new IllegalArgumentException("Could not extract generic types from name: " + name.getZenCodeName()); + } + final MatchResult matchResult = matcher.toMatchResult(); + final AbstractTypeInfo baseType = getGenericBaseType(matchResult); + final List parameters = getGenericParameters(matcher); + return new GenericTypeInfo(baseType, parameters); + } + + private AbstractTypeInfo getGenericBaseType(MatchResult matchResult) { + final String zenCodeName = matchResult.group(1).trim(); + return convertByName(new TypeName(zenCodeName)); + } + + private List getGenericParameters(Matcher matcher) { + return Arrays.stream(matcher.group(2).split(",")) + .map(String::trim) + .map(TypeName::new) + .map(this::convertByName) + .collect(Collectors.toList()); + } + + @Nonnull + private Matcher getGenericMatcher(TypeName name) { + final Pattern compile = Pattern.compile("([^<]+)<([^>]+)>"); + final Matcher matcher = compile.matcher(name.getZenCodeName()); + return matcher; + } + + private boolean isGeneric(TypeName name) { + return name.getZenCodeName().contains("<"); + } + + private AbstractTypeInfo getNativePageInfo(TypeName name) { + return nativeConversionRegistry.getNativeTypeInfoWithName(name); + } + + + private boolean hasNativePageInfo(TypeName name) { + return nativeConversionRegistry.hasNativeTypeInfoWithName(name); + } + + public AbstractTypeInfo convertType(TypeMirror typeMirror) { + return tryConvertType(typeMirror) + .orElseThrow(() -> new IllegalArgumentException("Could not convert " + typeMirror)); + } + + public Optional tryConvertType(TypeMirror typeMirror) { + return rules.stream().filter(rule -> rule.canConvert(typeMirror)).map(rule -> rule.convert(typeMirror)).filter(Objects::nonNull).findFirst(); + } + + @Override + public void afterCreation() { + addConversionRules(); + } + + private void addConversionRules() { + addConversionRule(TypeParameterConversionRule.class); + addConversionRule(VoidConversionRule.class); + addConversionRule(MapConversionRule.class); + addConversionRule(GenericTypeConversionRule.class); + addConversionRule(NativeTypeConversionRule.class); + addConversionRule(ArrayConversionRule.class); + addConversionRule(NamedTypeConversionRule.class); + addConversionRule(JavaLangConversionRule.class); + addConversionRule(JavaFunctionConversionRule.class); + addConversionRule(PrimitiveConversionRule.class); + //addConversionRule(FallbackConversionRule.class); + } + + private void addConversionRule(Class ruleClass) { + rules.add(dependencyContainer.getInstanceOfClass(ruleClass)); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/ArrayConversionRule.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/ArrayConversionRule.java new file mode 100644 index 000000000..b09bf514b --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/ArrayConversionRule.java @@ -0,0 +1,38 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.rules; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConversionRule; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.ArrayTypeInfo; + +import javax.annotation.Nullable; +import javax.lang.model.type.ArrayType; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; + +public class ArrayConversionRule implements TypeConversionRule { + + private final TypeConverter typeConverter; + + public ArrayConversionRule(TypeConverter typeConverter) { + this.typeConverter = typeConverter; + } + + @Override + public boolean canConvert(TypeMirror mirror) { + return mirror.getKind() == TypeKind.ARRAY; + } + + @Nullable + @Override + public AbstractTypeInfo convert(TypeMirror mirror) { + final ArrayType arrayType = (ArrayType) mirror; + final AbstractTypeInfo baseType = convertBaseType(arrayType); + + return new ArrayTypeInfo(baseType); + } + + private AbstractTypeInfo convertBaseType(ArrayType arrayType) { + return typeConverter.convertType(arrayType.getComponentType()); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/FallbackConversionRule.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/FallbackConversionRule.java new file mode 100644 index 000000000..4a527bfd3 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/FallbackConversionRule.java @@ -0,0 +1,35 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.rules; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConversionRule; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.ExistingTypeInfo; + +import javax.annotation.Nullable; +import javax.annotation.processing.Messager; +import javax.lang.model.type.TypeMirror; +import javax.tools.Diagnostic; + +/** + * @deprecated Only used to catch what other conversionRules are missing + */ +@Deprecated +public class FallbackConversionRule implements TypeConversionRule { + + private final Messager messager; + + public FallbackConversionRule(Messager messager) { + this.messager = messager; + } + + @Override + public boolean canConvert(TypeMirror mirror) { + return true; + } + + @Nullable + @Override + public AbstractTypeInfo convert(TypeMirror mirror) { + messager.printMessage(Diagnostic.Kind.WARNING, "Unsupported type found: " + mirror); + return new ExistingTypeInfo(mirror.toString()); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/JavaFunctionConversionRule.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/JavaFunctionConversionRule.java new file mode 100644 index 000000000..e0e496a7b --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/JavaFunctionConversionRule.java @@ -0,0 +1,30 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.rules; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.*; +import org.jetbrains.annotations.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; + +public class JavaFunctionConversionRule implements TypeConversionRule { + + private final Types typeUtils; + + public JavaFunctionConversionRule(Types typeUtils) { + this.typeUtils = typeUtils; + } + + @Override + public boolean canConvert(TypeMirror mirror) { + return mirror.toString().startsWith("java.util.function"); + } + + @Nullable + @Override + public AbstractTypeInfo convert(TypeMirror mirror) { + final Element element = typeUtils.asElement(mirror); + return new ExistingTypeInfo(element.getSimpleName().toString()); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/JavaLangConversionRule.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/JavaLangConversionRule.java new file mode 100644 index 000000000..197f8d37e --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/JavaLangConversionRule.java @@ -0,0 +1,45 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.rules; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConversionRule; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.*; + +import javax.annotation.Nullable; +import javax.lang.model.element.Element; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Types; + +public class JavaLangConversionRule implements TypeConversionRule { + + private final Types typeUtils; + + public JavaLangConversionRule(Types typeUtils) { + this.typeUtils = typeUtils; + } + + @Override + public boolean canConvert(TypeMirror mirror) { + return mirror.toString().startsWith("java.lang"); + } + + @Nullable + @Override + public AbstractTypeInfo convert(TypeMirror mirror) { + final Element element = typeUtils.asElement(mirror); + if(isString(element)) { + return getStringTypeInfo(); + } + return getExistingTypeInfo(element); + } + + private AbstractTypeInfo getStringTypeInfo() { + return new PrimitiveTypeInfo("string"); + } + + private AbstractTypeInfo getExistingTypeInfo(Element element) { + return new ExistingTypeInfo(element.getSimpleName().toString()); + } + + private boolean isString(Element mirror) { + return mirror.getSimpleName().contentEquals(String.class.getSimpleName()); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/NamedTypeConversionRule.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/NamedTypeConversionRule.java new file mode 100644 index 000000000..f4fd4fd33 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/NamedTypeConversionRule.java @@ -0,0 +1,56 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.rules; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConversionRule; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.TypeName; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; +import org.openzen.zencode.java.ZenCodeType; + +import javax.annotation.Nullable; +import javax.lang.model.element.Element; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Types; +import java.util.Objects; + +public class NamedTypeConversionRule implements TypeConversionRule { + + private final TypeConverter typeConverter; + private final Types typeUtils; + + public NamedTypeConversionRule(TypeConverter typeConverter, Types typeUtils) { + this.typeConverter = typeConverter; + this.typeUtils = typeUtils; + } + + + @Override + public boolean canConvert(TypeMirror mirror) { + return getNameAnnotation(mirror) != null; + } + + private ZenCodeType.Name getNameAnnotation(TypeMirror mirror) { + final ZenCodeType.Name annotation = mirror.getAnnotation(ZenCodeType.Name.class); + if(annotation != null) { + return annotation; + } + + final Element typeElement = typeUtils.asElement(mirror); + if(typeElement == null) { + return null; + } else { + return typeElement.getAnnotation(ZenCodeType.Name.class); + } + } + + @Nullable + @Override + public AbstractTypeInfo convert(TypeMirror mirror) { + final TypeName name = convertTypeName(mirror); + return typeConverter.convertByName(name); + } + + private TypeName convertTypeName(TypeMirror mirror) { + final ZenCodeType.Name annotation = getNameAnnotation(mirror); + return new TypeName(Objects.requireNonNull(annotation).value()); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/NativeTypeConversionRule.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/NativeTypeConversionRule.java new file mode 100644 index 000000000..914377a8e --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/NativeTypeConversionRule.java @@ -0,0 +1,52 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.rules; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.NativeConversionRegistry; +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConversionRule; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; + +import javax.annotation.Nullable; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Types; + +public class NativeTypeConversionRule implements TypeConversionRule { + + private final NativeConversionRegistry nativeConversionRegistry; + private final Types typeUtils; + + public NativeTypeConversionRule(NativeConversionRegistry nativeConversionRegistry, Types typeUtils) { + this.nativeConversionRegistry = nativeConversionRegistry; + this.typeUtils = typeUtils; + } + + @Override + public boolean canConvert(TypeMirror mirror) { + return isNativeType(mirror); + } + + private boolean isNativeType(TypeMirror mirror) { + return isTypeElement(mirror) && isTypeElementNative(mirror); + } + + private boolean isTypeElementNative(TypeMirror mirror) { + final TypeElement element = getTypeElement(mirror); + return nativeConversionRegistry.hasNativeTypeInfo(element); + } + + private TypeElement getTypeElement(TypeMirror mirror) { + return (TypeElement) typeUtils.asElement(mirror); + } + + private boolean isTypeElement(TypeMirror mirror) { + final Element element = typeUtils.asElement(mirror); + return element instanceof TypeElement; + } + + @Nullable + @Override + public AbstractTypeInfo convert(TypeMirror mirror) { + final TypeElement nativeType = getTypeElement(mirror); + return nativeConversionRegistry.getNativeTypeInfo(nativeType); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/PrimitiveConversionRule.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/PrimitiveConversionRule.java new file mode 100644 index 000000000..8655287ef --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/PrimitiveConversionRule.java @@ -0,0 +1,23 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.rules; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConversionRule; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.PrimitiveTypeInfo; + +import javax.annotation.Nullable; +import javax.lang.model.type.TypeMirror; +import java.util.Locale; + +public class PrimitiveConversionRule implements TypeConversionRule { + + @Override + public boolean canConvert(TypeMirror mirror) { + return mirror.getKind().isPrimitive(); + } + + @Nullable + @Override + public AbstractTypeInfo convert(TypeMirror mirror) { + return new PrimitiveTypeInfo(mirror.getKind().name().toLowerCase(Locale.ROOT)); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/TypeParameterConversionRule.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/TypeParameterConversionRule.java new file mode 100644 index 000000000..e0f39ff33 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/TypeParameterConversionRule.java @@ -0,0 +1,23 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.rules; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConversionRule; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.TypeParameterTypeInfo; + +import javax.annotation.Nullable; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; + +public class TypeParameterConversionRule implements TypeConversionRule { + + @Override + public boolean canConvert(TypeMirror mirror) { + return mirror.getKind() == TypeKind.TYPEVAR; + } + + @Nullable + @Override + public AbstractTypeInfo convert(TypeMirror mirror) { + return new TypeParameterTypeInfo(mirror.toString()); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/VoidConversionRule.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/VoidConversionRule.java new file mode 100644 index 000000000..5084362e3 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/VoidConversionRule.java @@ -0,0 +1,23 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.rules; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConversionRule; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.PrimitiveTypeInfo; + +import javax.annotation.Nullable; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; + +public class VoidConversionRule implements TypeConversionRule { + + @Override + public boolean canConvert(TypeMirror mirror) { + return mirror.getKind() == TypeKind.VOID; + } + + @Nullable + @Override + public AbstractTypeInfo convert(TypeMirror mirror) { + return new PrimitiveTypeInfo("void"); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/generic/AbstractGenericTypeConversionRule.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/generic/AbstractGenericTypeConversionRule.java new file mode 100644 index 000000000..cfc4f925f --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/generic/AbstractGenericTypeConversionRule.java @@ -0,0 +1,77 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.rules.generic; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.*; +import org.jetbrains.annotations.*; + +import javax.lang.model.type.*; +import javax.lang.model.util.*; +import java.util.*; +import java.util.stream.*; + +public abstract class AbstractGenericTypeConversionRule implements TypeConversionRule { + + protected final TypeConverter typeConverter; + protected final Types typeUtils; + + public AbstractGenericTypeConversionRule(TypeConverter typeConverter, Types typeUtils) { + this.typeConverter = typeConverter; + this.typeUtils = typeUtils; + } + + protected boolean isGenericType(TypeMirror mirror) { + return isDeclaredType(mirror) && isGenericMirror((DeclaredType) mirror); + + } + + private boolean isGenericMirror(DeclaredType typeElement) { + return !typeElement.getTypeArguments().isEmpty(); + } + + private boolean isDeclaredType(TypeMirror mirror) { + return mirror instanceof DeclaredType; + } + + + protected Optional convertBaseClass(TypeMirror mirror) { + final TypeMirror baseTypeMirror = getBaseType(mirror); + return typeConverter.tryConvertType(baseTypeMirror); + } + + protected TypeMirror getBaseType(TypeMirror mirror) { + return typeUtils.erasure(mirror); + } + + protected boolean isBaseTypeOfClass(TypeMirror mirror, Class cls) { + return getBaseType(mirror).toString().equals(cls.getCanonicalName()); + } + + protected Optional> convertTypeArguments(TypeMirror mirror) { + final List typeArguments = getTypeArguments(mirror); + final List> typeArgumentOptionalList = getTypeArgumentOptionalList(typeArguments); + return unwrapOptionalList(typeArgumentOptionalList); + } + + private Optional> unwrapOptionalList(List> typeArgumentOptionalList) { + final List result = new ArrayList<>(); + for(Optional abstractTypeInfo : typeArgumentOptionalList) { + if(abstractTypeInfo.isPresent()) { + result.add(abstractTypeInfo.get()); + } else { + return Optional.empty(); + } + } + return Optional.of(result); + } + + @NotNull + private List> getTypeArgumentOptionalList(List typeArguments) { + return typeArguments.stream().map(typeConverter::tryConvertType).collect(Collectors.toList()); + } + + private List getTypeArguments(TypeMirror mirror) { + return ((DeclaredType) mirror).getTypeArguments(); + } + + +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/generic/GenericTypeConversionRule.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/generic/GenericTypeConversionRule.java new file mode 100644 index 000000000..ca5885c23 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/generic/GenericTypeConversionRule.java @@ -0,0 +1,34 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.rules.generic; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.GenericTypeInfo; + +import javax.annotation.Nullable; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Types; +import java.util.*; + +public class GenericTypeConversionRule extends AbstractGenericTypeConversionRule { + + public GenericTypeConversionRule(TypeConverter typeConverter, Types typeUtils) { + super(typeConverter, typeUtils); + } + + @Override + public boolean canConvert(TypeMirror mirror) { + return isGenericType(mirror); + } + + @Nullable + @Override + public AbstractTypeInfo convert(TypeMirror mirror) { + final Optional baseClass = convertBaseClass(mirror); + final Optional> typeArguments = convertTypeArguments(mirror); + if(!baseClass.isPresent() || !typeArguments.isPresent()) { + return null; + } + + return new GenericTypeInfo(baseClass.get(), typeArguments.get()); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/generic/MapConversionRule.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/generic/MapConversionRule.java new file mode 100644 index 000000000..2d243b62b --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/converter/type/rules/generic/MapConversionRule.java @@ -0,0 +1,52 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.rules.generic; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.converter.type.TypeConverter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.MapTypeInfo; +import org.jetbrains.annotations.*; + +import javax.annotation.Nullable; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Types; +import java.util.*; + +public class MapConversionRule extends AbstractGenericTypeConversionRule { + + + public MapConversionRule(TypeConverter typeConverter, Types typeUtils) { + super(typeConverter, typeUtils); + } + + @Override + public boolean canConvert(TypeMirror mirror) { + return isMapType(mirror); + } + + private boolean isMapType(TypeMirror mirror) { + return isGenericType(mirror) && isBaseTypeOfClass(mirror, Map.class); + } + + @Nullable + @Override + public AbstractTypeInfo convert(TypeMirror mirror) { + final Optional> typeArguments = convertTypeArguments(mirror); + return typeArguments.map(this::getMapTypeInfo).orElse(null); + + } + + @NotNull + private MapTypeInfo getMapTypeInfo(List typeArguments) { + final AbstractTypeInfo keyType = getKeyTypeFrom(typeArguments); + final AbstractTypeInfo valueType = getValueTypeFrom(typeArguments); + + return new MapTypeInfo(keyType, valueType); + } + + private AbstractTypeInfo getKeyTypeFrom(List typeArguments) { + return typeArguments.get(0); + } + + private AbstractTypeInfo getValueTypeFrom(List typeArguments) { + return typeArguments.get(1); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/element/AnnotationMirrorUtil.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/element/AnnotationMirrorUtil.java new file mode 100644 index 000000000..5c580082b --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/element/AnnotationMirrorUtil.java @@ -0,0 +1,54 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.element; + +import javax.annotation.Nonnull; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import java.util.Optional; +import java.util.function.Predicate; + +public class AnnotationMirrorUtil { + + public boolean isAnnotationPresentOn(Element element, String annotationName) { + return tryGetMirror(element, annotationName).isPresent(); + } + + public AnnotationMirror getMirror(Element element, String annotationName) { + return tryGetMirror(element, annotationName).orElseThrow(() -> new IllegalArgumentException("Element has no annotation " + annotationName)); + } + + @Nonnull + public Optional tryGetMirror(Element element, String annotationName) { + return element.getAnnotationMirrors() + .stream() + .filter(annotationTypeIs(annotationName)) + .findAny(); + } + + + private Predicate annotationTypeIs(String name) { + return mirror -> mirror.getAnnotationType().asElement().toString().contentEquals(name); + } + + public AnnotationMirror getMirror(Element element, TypeElement typeElement) { + return getMirror(element, typeElement.getQualifiedName().toString()); + } + + public String getAnnotationValue(AnnotationMirror annotationMirror, String name) { + return getAnnotationValueObject(annotationMirror, name).toString(); + } + + public Object getAnnotationValueObject(AnnotationMirror annotationMirror, String name) { + return tryGetAnnotationValue(annotationMirror, name).orElseThrow(() -> new IllegalArgumentException("Could not get value " + name)); + } + + @Nonnull + private Optional tryGetAnnotationValue(AnnotationMirror annotationMirror, String name) { + return annotationMirror.getElementValues() + .entrySet() + .stream() + .filter(entry -> entry.getKey().getSimpleName().contentEquals(name)) + .map(entry -> entry.getValue().getValue()) + .findAny(); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/element/KnownElementList.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/element/KnownElementList.java new file mode 100644 index 000000000..95ce31d48 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/element/KnownElementList.java @@ -0,0 +1,71 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.element; + +import com.blamejared.crafttweaker_annotations.annotations.Document; +import com.blamejared.crafttweaker_annotations.annotations.NativeTypeRegistration; +import com.blamejared.crafttweaker_annotations.annotations.TypedExpansion; +import org.openzen.zencode.java.ZenCodeType; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import java.lang.annotation.Annotation; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +public class KnownElementList { + + private final ProcessingEnvironment processingEnv; + private Collection knownElements; + + public KnownElementList(ProcessingEnvironment processingEnv) { + + this.processingEnv = processingEnv; + this.knownElements = new HashSet<>(); + } + + private void updateElements() { + knownElements = knownElements.stream() + .map(Object::toString) + .map(processingEnv.getElementUtils()::getTypeElement) + .collect(Collectors.toSet()); + } + + public void addAllForIntermediateRound(RoundEnvironment roundEnvironment) { + final Set elementsOfThisRound = roundEnvironment.getElementsAnnotatedWith(Document.class) + .stream() + .map(element -> (TypeElement) element) + .collect(Collectors.toSet()); + this.knownElements.addAll(elementsOfThisRound); + } + + public Collection getElementsForTypeDocumentation() { + updateElements(); + + return knownElements.stream() + .filter(this::isElementForTypeDocumentation) + .collect(Collectors.toList()); + } + + public Collection getElementsForExpansionDocumentation() { + updateElements(); + + return knownElements.stream() + .filter(this::isElementForExpansionDocumentation) + .collect(Collectors.toList()); + } + + private boolean isElementForTypeDocumentation(TypeElement element) { + return isAnnotationPresent(element, ZenCodeType.Name.class) || isAnnotationPresent(element, NativeTypeRegistration.class); + } + + private boolean isElementForExpansionDocumentation(TypeElement element) { + return isAnnotationPresent(element, ZenCodeType.Expansion.class) || isAnnotationPresent(element, TypedExpansion.class); + } + + private boolean isAnnotationPresent(Element element, Class annotation) { + return element.getAnnotation(annotation) != null; + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/mods/KnownModList.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/mods/KnownModList.java new file mode 100644 index 000000000..694b831d8 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/conversion/mods/KnownModList.java @@ -0,0 +1,52 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.mods; + + +import com.blamejared.crafttweaker_annotation_processors.processors.document.conversion.element.AnnotationMirrorUtil; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.util.Elements; +import java.util.HashMap; +import java.util.Map; + +public class KnownModList { + + private final Map modIdByPackage = new HashMap<>(); + + private final ProcessingEnvironment environment; + private final AnnotationMirrorUtil annotationMirrorUtil; + + public KnownModList(ProcessingEnvironment environment, AnnotationMirrorUtil annotationMirrorUtil) { + this.environment = environment; + this.annotationMirrorUtil = annotationMirrorUtil; + } + + public String getModIdForPackage(Element element) { + final PackageElement elementPackage = environment.getElementUtils().getPackageOf(element); + final String packageName = elementPackage.getQualifiedName().toString(); + + for(String knownPackName : modIdByPackage.keySet()) { + if(packageName.startsWith(knownPackName)) { + return modIdByPackage.get(knownPackName); + } + } + return null; + } + + public void fillModIdInfo(RoundEnvironment roundEnv) { + final Elements elementUtils = environment.getElementUtils(); + final TypeElement typeElement = elementUtils.getTypeElement("net.minecraftforge.fml.common.Mod"); + + for(Element element : roundEnv.getElementsAnnotatedWith(typeElement)) { + final AnnotationMirror modAnnotation = annotationMirrorUtil.getMirror(element, typeElement); + final String modId = annotationMirrorUtil.getAnnotationValue(modAnnotation, "value"); + + final PackageElement modPackage = elementUtils.getPackageOf(element); + modIdByPackage.put(modPackage.getQualifiedName().toString(), modId); + } + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/dependencies/DependencyContainer.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/dependencies/DependencyContainer.java new file mode 100644 index 000000000..890b734d2 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/dependencies/DependencyContainer.java @@ -0,0 +1,10 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.dependencies; + +public interface DependencyContainer { + + Type getInstanceOfClass(Class cls); + + void addInstance(Type instance); + + void addInstanceAs(Instance instance, Class as); +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/dependencies/IHasPostCreationCall.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/dependencies/IHasPostCreationCall.java new file mode 100644 index 000000000..9a60a17a3 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/dependencies/IHasPostCreationCall.java @@ -0,0 +1,14 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.dependencies; + +/** + * Causes the {@link DependencyContainer} to call this method after the constructor has been invoked + * Used for breaking recursive dependencies + */ +public interface IHasPostCreationCall { + + /** + * The method called after the constructor of the type was invoked. + * At this time the instance will already be in the DI registry, so anything created by this can request an instance of this type. + */ + void afterCreation(); +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/dependencies/SingletonDependencyContainer.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/dependencies/SingletonDependencyContainer.java new file mode 100644 index 000000000..81328e0e0 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/dependencies/SingletonDependencyContainer.java @@ -0,0 +1,105 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.dependencies; + +import javax.annotation.Nonnull; +import javax.annotation.processing.*; +import javax.tools.*; +import java.lang.reflect.Constructor; +import java.lang.reflect.Modifier; +import java.util.*; + +public class SingletonDependencyContainer implements DependencyContainer { + + private final Map, Object> alreadyExistingInstances = new HashMap<>(); + + @Override + public Type getInstanceOfClass(Class cls) { + initializeInstanceIfNotExists(cls); + return getInstance(cls); + } + + @Override + @SuppressWarnings("unchecked") + public void addInstance(Type instance) { + addInstanceAs(instance, (Class) instance.getClass()); + } + + @Override + public void addInstanceAs(Instance instance, Class as) { + validateNoDuplicate(as); + insertInstanceAs(instance, as); + } + + @SuppressWarnings("unchecked") + private Type getInstance(Class cls) { + return (Type) alreadyExistingInstances.get(cls); + } + + private void initializeInstanceIfNotExists(Class cls) { + if(!instanceAlreadyExists(cls)) { + verifyClassCanBeInitialized(cls); + initializeInstance(cls); + callPostInitSteps(cls); + } + } + + private void verifyClassCanBeInitialized(Class cls) { + if(cls.isInterface()) { + throw new IllegalArgumentException("Cannot instantiate interface!"); + } + if(Modifier.isAbstract(cls.getModifiers())) { + throw new IllegalArgumentException("Cannot instantiate abstract class!"); + } + } + + private void callPostInitSteps(Class cls) { + final Type instanceOfClass = getInstanceOfClass(cls); + if(instanceOfClass instanceof IHasPostCreationCall) { + ((IHasPostCreationCall) instanceOfClass).afterCreation(); + } + } + + private void initializeInstance(Class cls) { + final Optional instance = Arrays.stream(cls.getConstructors()). map(this::tryCreateInstanceWith) + .filter(Objects::nonNull) + .findFirst(); + + if(instance.isPresent()) { + insertInstanceAs(instance.get(), cls); + } else { + throw new IllegalArgumentException("Could not initialize class: " + cls.getCanonicalName()); + } + } + + @SuppressWarnings("unchecked") + private Type tryCreateInstanceWith(Constructor constructor) { + try { + final Object[] arguments = getArguments(constructor); + return (Type) constructor.newInstance(arguments); + } catch(Exception e) { + final Messager instanceOfClass = getInstanceOfClass(Messager.class); + instanceOfClass.printMessage(Diagnostic.Kind.ERROR, e.getMessage()); + return null; + } + } + + @Nonnull + private Object[] getArguments(Constructor constructor) { + return Arrays.stream(constructor.getParameterTypes()) + .map(this::getInstanceOfClass) + .toArray(Object[]::new); + } + + private void insertInstanceAs(Type instance, Class as) { + alreadyExistingInstances.put(as, instance); + } + + private void validateNoDuplicate(Class instance) { + if(instanceAlreadyExists(instance)) { + throw new IllegalStateException("Trying to register duplicate!"); + } + } + + private boolean instanceAlreadyExists(Class instanceClass) { + return alreadyExistingInstances.containsKey(instanceClass); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/documented_class/DocumentedClass.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/documented_class/DocumentedClass.java deleted file mode 100644 index d142949c4..000000000 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/documented_class/DocumentedClass.java +++ /dev/null @@ -1,327 +0,0 @@ -package com.blamejared.crafttweaker_annotation_processors.processors.document.documented_class; - -import com.blamejared.crafttweaker_annotation_processors.processors.document.*; -import com.blamejared.crafttweaker_annotation_processors.processors.document.documented_class.members.*; -import com.blamejared.crafttweaker_annotation_processors.processors.document.shared.*; -import com.blamejared.crafttweaker_annotation_processors.processors.document.shared.members.*; -import com.blamejared.crafttweaker_annotation_processors.processors.document.shared.types.*; -import com.blamejared.crafttweaker_annotation_processors.processors.document.shared.util.*; -import org.openzen.zencode.java.*; - -import javax.annotation.processing.*; -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.tools.*; -import java.io.*; -import java.util.*; -import java.util.stream.*; - -/** - * The main part of this. - * Most pages in the wiki will be pages that explain a certain ZS class. - */ -public class DocumentedClass extends CrafttweakerDocumentationPage { - - public static final Comparator byZSName = Comparator.comparing(c -> c.ZSName); - - private final Set implementedInterfaces = new TreeSet<>(DocumentedClass.byZSName); - private final Set constructors = new TreeSet<>(DocumentedConstructor.compareByParameterCount); - private final Set casters = new TreeSet<>(DocumentedCaster.byZSName); - private final Map methods = new TreeMap<>(); - private final Map properties = new TreeMap<>(); - private final Set operators = new TreeSet<>(DocumentedOperator.compareByOp); - - //TODO: Example files - private final Set examples = new HashSet<>(); - private final String ZSName; - private final String docPath; - private final DocumentedClass superClass; - private final String declaringModId; - private final boolean isFunctionalInterface; - private String docComment; - private String docParamThis; - - public DocumentedClass(String ZSName, String docPath, DocumentedClass superClass, String docParamThis, String declaringModId, boolean isFunctionalInterface) { - this.ZSName = ZSName; - this.docPath = docPath; - this.superClass = superClass; - this.docParamThis = docParamThis; - this.declaringModId = declaringModId; - this.isFunctionalInterface = isFunctionalInterface; - } - - public static DocumentedClass convertClass(TypeMirror type, ProcessingEnvironment environment, boolean forComment) { - return convertClass((TypeElement) environment.getTypeUtils().asElement(type), environment, forComment); - } - - public static DocumentedClass convertClass(TypeElement element, ProcessingEnvironment environment, boolean forComment) { - if(element == null || element.equals(environment.getElementUtils() - .getTypeElement("java.lang.Object"))) { - return null; - } - if(knownTypes.containsKey(element.toString())) { - final CrafttweakerDocumentationPage documentationPage = knownTypes.get(element.toString()); - if(!(documentationPage instanceof DocumentedClass)) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Internal error: " + element + " is not a class", element); - return null; - } - return (DocumentedClass) documentationPage; - } - - final ZenCodeType.Name nameAnnotation = element.getAnnotation(ZenCodeType.Name.class); - final String zsName = nameAnnotation != null ? nameAnnotation.value() : element.getQualifiedName() - .toString(); - final String docPath = IDontKnowHowToNameThisUtil.getDocPath(element, environment, forComment); - if(docPath == null) { - return null; - } - - final DocumentedClass superClass = convertClass(element.getSuperclass(), environment, forComment); - //final String docComment = environment.getElementUtils().getDocComment(element); - - final String declaringModId = DocumentProcessorNew.getModIdForPackage(element, environment); - String docParamThis = null; - - { - final String s = CommentUtils.joinDocAnnotation(element, "@docParam this", environment) - .trim(); - if(!s.isEmpty()) { - docParamThis = s; - } - } - final boolean isFunctionalInterface = element.getAnnotation(FunctionalInterface.class) != null; - - final DocumentedClass out = new DocumentedClass(zsName, docPath, superClass, docParamThis, declaringModId, isFunctionalInterface); - knownTypes.put(element.toString(), out); - final String docComment = CommentUtils.formatDocCommentForDisplay(element, environment); - out.setDocComment(docComment); - typesByZSName.put(zsName, element); - - if(!(element.getSuperclass() instanceof NoType)) { - final DocumentedClass documentedClass = convertClass(element.getSuperclass(), environment, forComment); - if(documentedClass != null) { - out.implementedInterfaces.add(documentedClass); - out.implementedInterfaces.addAll(documentedClass.implementedInterfaces); - } - } - - for(final TypeMirror anInterface : element.getInterfaces()) { - final DocumentedClass documentedClass = convertClass(anInterface, environment, forComment); - if(documentedClass != null) { - out.implementedInterfaces.add(documentedClass); - out.implementedInterfaces.addAll(documentedClass.implementedInterfaces); - } - } - - handleEnclosedElements(out, element, environment); - - return out; - } - - private static void handleEnclosedElements(DocumentedClass out, TypeElement element, ProcessingEnvironment environment) { - for(Element enclosedElement : element.getEnclosedElements()) { - //Method - { - final ZenCodeType.Method method = enclosedElement.getAnnotation(ZenCodeType.Method.class); - if(method != null) { - final DocumentedMethod documentedMethod = DocumentedMethod.convertMethod(out, (ExecutableElement) enclosedElement, environment, false); - if(documentedMethod != null) { - out.methods.computeIfAbsent(documentedMethod.getName(), name -> new DocumentedMethodGroup(name, out)) - .add(documentedMethod); - } - } - } - //Field - { - final ZenCodeType.Field method = enclosedElement.getAnnotation(ZenCodeType.Field.class); - if(method != null) { - final DocumentedProperty documentedProperty = DocumentedProperty.fromField(out, enclosedElement, environment); - if(documentedProperty != null) { - out.properties.merge(documentedProperty.getName(), documentedProperty, ((p1, p2) -> DocumentedProperty - .merge(p1, p2, environment))); - } - } - } - //Getter - //Setter - { - if(enclosedElement.getAnnotation(ZenCodeType.Getter.class) != null || enclosedElement - .getAnnotation(ZenCodeType.Setter.class) != null) { - final DocumentedProperty documentedProperty = DocumentedProperty.fromMethod(out, enclosedElement, environment, false); - if(documentedProperty != null) { - out.properties.merge(documentedProperty.getName(), documentedProperty, ((p1, p2) -> DocumentedProperty - .merge(p1, p2, environment))); - } - } - } - //Constructor - { - if(enclosedElement.getAnnotation(ZenCodeType.Constructor.class) != null) { - final DocumentedConstructor documentedConstructor = DocumentedConstructor.fromConstructor(out, ((ExecutableElement) enclosedElement), environment); - if(documentedConstructor != null) { - out.constructors.add(documentedConstructor); - } - } - } - //Operator - { - if(enclosedElement.getAnnotation(ZenCodeType.Operator.class) != null) { - final DocumentedOperator documentedOperator = DocumentedOperator.fromMethod(out, (ExecutableElement) enclosedElement, environment, false); - if(documentedOperator != null) { - out.operators.add(documentedOperator); - } - } - } - - //Caster - { - if(enclosedElement.getAnnotation(ZenCodeType.Caster.class) != null) { - final DocumentedCaster documentedCaster = DocumentedCaster.fromMethod((ExecutableElement) enclosedElement, environment, false); - if(documentedCaster != null) { - out.casters.add(documentedCaster); - } - } - } - } - } - - private static void printSection(String sectionName, Collection writables, PrintWriter writer) { - if(!writables.isEmpty()) { - writer.printf("## %s%n", sectionName); - for(Writable writable : writables) { - writable.write(writer); - } - writer.println(); - } - } - - public void setDocComment(String docComment) { - this.docComment = docComment; - } - - @Override - public String toString() { - return ZSName; - } - - public String getZSName() { - return ZSName; - } - - public String getZSShortName() { - return ZSName.substring(ZSName.lastIndexOf('.') + 1); - } - - @Override - public String getDocPath() { - return docPath; - } - - public String getDocParamThis() { - return docParamThis == null ? "my" + getZSShortName() : docParamThis; - } - - @Override - public String getDocumentTitle() { - return getZSShortName(); - } - - @Override - public void write(File docsDirectory, ProcessingEnvironment environment) throws IOException { - final File file = new File(docsDirectory, getDocPath() + ".md"); - if(!file.getParentFile().exists() && !file.getParentFile().mkdirs()) { - throw new IOException("Could not create folder " + file.getAbsolutePath()); - } - - try(final PrintWriter writer = new PrintWriter(new FileWriter(file))) { - writer.printf("# %s%n", getDocumentTitle()); - writer.println(); - - - if(docComment != null) { - writer.println(docComment); - writer.println(); - } - - if(declaringModId != null) { - writer.printf("This class was added by a mod with mod-id `%s`. So you need to have this mod installed if you want to use this feature.%n", declaringModId); - writer.println(); - } - - writer.println("## Importing the class"); - //TODO: Create Arrays pages and re-add the '[Array](link)' - writer.println("It might be required for you to import the package if you encounter any issues (like casting an Array), so better be safe than sorry and add the import. "); - writer.println("```zenscript"); - writer.println(this.getZSName()); - writer.println("```"); - writer.println(); - - if(!implementedInterfaces.isEmpty()) { - - writer.println("## Implemented Interfaces"); - writer.printf("%s implements the following interfaces. That means any method available to them can also be used on this class. %n", this - .getZSShortName()); - for(DocumentedClass implementedInterface : implementedInterfaces) { - writer.printf("- %s%n", new DocumentedClassType(implementedInterface).getClickableMarkdown()); - - this.constructors.addAll(implementedInterface.constructors); - this.casters.addAll(implementedInterface.casters); - this.operators.addAll(implementedInterface.operators); - implementedInterface.properties.forEach((s, documentedProperty) -> this.properties - .merge(s, documentedProperty, (a, b) -> DocumentedProperty.merge(a, b, environment))); - for(Map.Entry entry : implementedInterface.methods - .entrySet()) { - String s = entry.getKey(); - DocumentedMethodGroup documentedMethodGroup = entry.getValue(); - this.methods.computeIfAbsent(s, s1 -> new DocumentedMethodGroup(s1, this)); - this.methods.merge(s, documentedMethodGroup, DocumentedMethodGroup::merge); - } - - if(this.docParamThis == null) { - //TODO: Do we want this - this.docParamThis = implementedInterface.docParamThis; - } - } - writer.println(); - } - - if(isFunctionalInterface) { - writer.println("## Functional Interface"); - writer.println(); - writer.println("This class is a functional interface. This means that you can use the lambda notation to create an instance of it."); - - if(methods.size() == 1) { - final DocumentedMethodGroup group = methods.values().iterator().next(); - if(group.getMethods().size() == 1) { - final DocumentedMethod method = group.getMethods().iterator().next(); - writer.println("The lambda notation looks like: "); - writer.println("```zenscript"); - final String collect = method.getParameterList() - .stream() - .map(DocumentedParameter::getName) - .collect(Collectors.joining(", ", "(", ") => ")); - writer.print(collect); - final DocumentedType returnType = method.getReturnType(); - writer.println(returnType == null ? "{}" : returnType.getDocParamThis()); - writer.println("```"); - } - } - } - - - printSection("Constructors", this.constructors, writer); - printSection("Methods", this.methods.values(), writer); - DocumentedProperty.printProperties(this.properties.values(), writer); - printSection("Operators", this.operators, writer); - //printSection("Casters", this.casters, writer); - DocumentedCaster.printCasters(this.casters, writer); - } - } - - - public boolean extendsOrImplements(DocumentedClass containingClass) { - return this.equals(containingClass) || this.superClass != null && this.superClass.equals(containingClass) || this.implementedInterfaces - .contains(containingClass); - } -} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/documented_class/members/DocumentedConstructor.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/documented_class/members/DocumentedConstructor.java deleted file mode 100644 index d1c8693cb..000000000 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/documented_class/members/DocumentedConstructor.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.blamejared.crafttweaker_annotation_processors.processors.document.documented_class.members; - -import com.blamejared.crafttweaker_annotation_processors.processors.document.documented_class.DocumentedClass; -import com.blamejared.crafttweaker_annotation_processors.processors.document.shared.Writable; -import com.blamejared.crafttweaker_annotation_processors.processors.document.shared.members.DocumentedParameter; -import com.blamejared.crafttweaker_annotation_processors.processors.document.shared.util.CommentUtils; - -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.tools.Diagnostic; -import java.io.PrintWriter; -import java.util.*; - -public class DocumentedConstructor implements Writable { - - public static final Comparator compareByParameterCount = Comparator.comparingInt(e -> e.parameterList - .size()); - - - private final List parameterList; - private final DocumentedClass containingClass; - private final String docComment; - - public DocumentedConstructor(DocumentedClass containingClass, List parameterList, String docComment) { - this.containingClass = containingClass; - this.parameterList = parameterList; - this.docComment = docComment; - } - - public static DocumentedConstructor fromConstructor(DocumentedClass containingClass, ExecutableElement constructor, ProcessingEnvironment environment) { - if (constructor.getKind() != ElementKind.CONSTRUCTOR) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Internal Error: Expected this to be a constructor", constructor); - return null; - } - - if (!constructor.getModifiers().contains(Modifier.PUBLIC)) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Constructors need to be public!", constructor); - return null; - } - - final List parameters = DocumentedParameter.getMethodParameters(constructor, environment, false); - final String docComment = CommentUtils.formatDocCommentForDisplay(constructor, environment); - return new DocumentedConstructor(containingClass, parameters, docComment); - } - - @Override - public void write(PrintWriter writer) { - if (docComment != null) { - writer.println(docComment); - } - - writer.println("```zenscript"); - DocumentedParameter.printAllCalls("new " + containingClass.getZSName(), parameterList, Collections.emptyList(), writer); - writer.println("```"); - - if (!parameterList.isEmpty()) { - DocumentedParameter.printTable(parameterList, writer); - writer.println(); - } - } -} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/documented_expansion/DocumentedExpansion.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/documented_expansion/DocumentedExpansion.java deleted file mode 100644 index 9190f5215..000000000 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/documented_expansion/DocumentedExpansion.java +++ /dev/null @@ -1,222 +0,0 @@ -package com.blamejared.crafttweaker_annotation_processors.processors.document.documented_expansion; - -import com.blamejared.crafttweaker_annotation_processors.processors.document.CrafttweakerDocumentationPage; -import com.blamejared.crafttweaker_annotation_processors.processors.document.DocumentProcessorNew; -import com.blamejared.crafttweaker_annotation_processors.processors.document.shared.Writable; -import com.blamejared.crafttweaker_annotation_processors.processors.document.shared.members.*; -import com.blamejared.crafttweaker_annotation_processors.processors.document.shared.types.DocumentedType; -import com.blamejared.crafttweaker_annotation_processors.processors.document.shared.util.CommentUtils; -import com.blamejared.crafttweaker_annotation_processors.processors.document.shared.util.IDontKnowHowToNameThisUtil; -import org.openzen.zencode.java.ZenCodeType; - -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.*; -import javax.tools.Diagnostic; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.*; - -public class DocumentedExpansion extends CrafttweakerDocumentationPage { - private final String docPath; - private final String docComment; - private final DocumentedType expandedType; - private final Set operators = new TreeSet<>(DocumentedOperator.compareByOp); - private final Set casters = new TreeSet<>(DocumentedCaster.byZSName); - private final Map methods = new TreeMap<>(); - private final Map properties = new TreeMap<>(); - private final String docParamThis; - private final String declaringModId; - - public DocumentedExpansion(String docPath, String docComment, DocumentedType expandedType, String docParamThis, String declaringModId) { - this.docPath = docPath; - this.docComment = docComment; - this.expandedType = expandedType; - this.docParamThis = docParamThis; - this.declaringModId = declaringModId; - } - - public static DocumentedExpansion convertExpansion(TypeElement element, ProcessingEnvironment environment, boolean forComment) { - if (knownTypes.containsKey(element.toString())) { - final CrafttweakerDocumentationPage documentationPage = knownTypes.get(element.toString()); - if (!(documentationPage instanceof DocumentedExpansion)) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Internal error: " + element + " is not a class", element); - return null; - } - return (DocumentedExpansion) documentationPage; - } - - final ZenCodeType.Expansion expansionAnnotation = element.getAnnotation(ZenCodeType.Expansion.class); - if (expansionAnnotation == null) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Internal error: Expected this to have an Expansion annotation", element); - return null; - } - - final DocumentedType expandedType = findExpandedType(element, expansionAnnotation, environment); - if (expandedType == null) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Internal error: Could not find expanded type!"); - return null; - } - - final String docPath = IDontKnowHowToNameThisUtil.getDocPath(element, environment, forComment); - if (docPath == null) { - return null; - } - final String s = CommentUtils.formatDocCommentForDisplay(element, environment); - String docParamThis = CommentUtils.joinDocAnnotation(element, "docParam this", environment); - - if (docParamThis.isEmpty()) { - docParamThis = null; - } - final String declaringModId = DocumentProcessorNew.getModIdForPackage(element, environment); - final DocumentedExpansion out = new DocumentedExpansion(docPath, (s == null || s.isEmpty()) ? null : s, expandedType, docParamThis, declaringModId); - knownTypes.put(element.toString(), out); - - - handleEnclosedElements(out, element, environment); - - return out; - } - - private static DocumentedType findExpandedType(TypeElement element, ZenCodeType.Expansion expansionAnnotation, ProcessingEnvironment environment) { - if (typesByZSName.containsKey(expansionAnnotation.value())) { - return DocumentedType.fromElement(typesByZSName.get(expansionAnnotation.value()), environment, false); - } - - for (Element enclosedElement : element.getEnclosedElements()) { - if (enclosedElement.getKind() == ElementKind.METHOD && enclosedElement.getAnnotation(ZenCodeType.Method.class) != null) { - final ExecutableElement executableElement = (ExecutableElement) enclosedElement; - if (executableElement.getParameters().size() == 0) { - continue; - } - - final VariableElement variableElement = executableElement.getParameters().get(0); - final DocumentedType type = DocumentedType.fromElement(variableElement, environment, false); - if (type != null) { - if (!type.getZSName().equals(expansionAnnotation.value())) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "First Parameter of this method is not the expanded element, " + expansionAnnotation - .value() + " but " + type.getZSName(), enclosedElement); - - //continue; Should we still use the first method? - } - return type; - } - } - } - return null; - } - - private static void handleEnclosedElements(DocumentedExpansion out, TypeElement element, ProcessingEnvironment environment) { - for (Element enclosedElement : element.getEnclosedElements()) { - //Method - { - final ZenCodeType.Method method = enclosedElement.getAnnotation(ZenCodeType.Method.class); - if (method != null) { - final DocumentedMethod documentedMethod = DocumentedMethod.convertMethod(out, (ExecutableElement) enclosedElement, environment, true); - if (documentedMethod != null) { - out.methods.computeIfAbsent(documentedMethod.getName(), name -> new DocumentedMethodGroup(name, out)) - .add(documentedMethod); - } - } - } - //Getter - //Setter - { - if (enclosedElement.getAnnotation(ZenCodeType.Getter.class) != null || enclosedElement.getAnnotation(ZenCodeType.Setter.class) != null) { - final DocumentedProperty documentedProperty = DocumentedProperty.fromMethod(out, enclosedElement, environment, true); - if (documentedProperty != null) { - out.properties.merge(documentedProperty.getName(), documentedProperty, ((p1, p2) -> DocumentedProperty - .merge(p1, p2, environment))); - } - } - } - //Operator - { - if (enclosedElement.getAnnotation(ZenCodeType.Operator.class) != null) { - final DocumentedOperator documentedOperator = DocumentedOperator.fromMethod(out, (ExecutableElement) enclosedElement, environment, true); - if (documentedOperator != null) { - out.operators.add(documentedOperator); - } - } - } - - //Caster - { - if (enclosedElement.getAnnotation(ZenCodeType.Caster.class) != null) { - final DocumentedCaster documentedCaster = DocumentedCaster.fromMethod((ExecutableElement) enclosedElement, environment, true); - if (documentedCaster != null) { - out.casters.add(documentedCaster); - } - } - } - } - } - - private static void printSection(String sectionName, Collection collectionWritable, PrintWriter writer) { - if (!collectionWritable.isEmpty()) { - writer.printf("## %s%n", sectionName); - for (Writable writable : collectionWritable) { - writable.write(writer); - } - writer.println(); - } - } - - @Override - public String getDocPath() { - return docPath; - } - - @Override - public void write(File docsDirectory, ProcessingEnvironment environment) throws IOException { - final File file = new File(docsDirectory, getDocPath() + ".md"); - if (!file.getParentFile().exists() && !file.getParentFile().mkdirs()) { - throw new IOException("Could not create folder " + file.getAbsolutePath()); - } - - try (final PrintWriter writer = new PrintWriter(new FileWriter(file))) { - writer.printf("# %s%n", this.getDocumentTitle()); - writer.println(); - if (docComment != null) { - writer.println(docComment); - writer.println(); - } - - if (declaringModId != null) { - writer.printf("This expansion was added by a mod with mod-id `%s`. So you need to have this mod installed if you want to use this feature.%n", declaringModId); - writer.println(); - } - - writer.printf("This is an expansion class for %s. %n", this.expandedType.getClickableMarkdown()); - writer.printf("That means that whenever you have an object that is a %s, you can use these methods on it as if they were directly declared in %1$s.%n", this.expandedType - .getClickableMarkdown()); - writer.println("Of course, that only works if the mod that declares this expansion class is also loaded!"); - writer.println(); - - printSection("Methods", this.methods.values(), writer); - DocumentedProperty.printProperties(this.properties.values(), writer); - printSection("Operators", this.operators, writer); - DocumentedCaster.printCasters(this.casters, writer); - } - } - - @Override - public String getZSName() { - return expandedType.getZSName(); - } - - @Override - public String getDocParamThis() { - return docParamThis == null ? "my" + expandedType.getZSShortName() : docParamThis; - } - - @Override - public String getDocumentTitle() { - return "Expansion for " + expandedType.getZSShortName(); - } -} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/file/DocsJsonWriter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/file/DocsJsonWriter.java new file mode 100644 index 000000000..a562541e6 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/file/DocsJsonWriter.java @@ -0,0 +1,48 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.file; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.DocumentRegistry; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.page.DocumentationPage; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +public class DocsJsonWriter { + + private final File outputFile; + private final DocumentRegistry registry; + private final Navigation navigation = new Navigation(); + + public DocsJsonWriter(File outputFile, DocumentRegistry registry) { + this.outputFile = outputFile; + this.registry = registry; + } + + public void write() throws IOException { + fillTableOfContent(); + writeTableOfContent(); + } + + private void writeTableOfContent() throws IOException { + final File outputFile = new File(this.outputFile, "docs.json"); + try(final BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile))) { + final Gson gson = getGson(); + writer.write(gson.toJson(navigation)); + } + } + + private Gson getGson() { + return new GsonBuilder().setPrettyPrinting() + .registerTypeAdapter(TableOfContent.class, new TableOfContentTypeAdapter()) + .create(); + } + + private void fillTableOfContent() { + for(DocumentationPage page : registry.getAllPages()) { + navigation.add(page); + } + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/file/Navigation.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/file/Navigation.java new file mode 100644 index 000000000..67ea11b79 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/file/Navigation.java @@ -0,0 +1,13 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.file; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.page.DocumentationPage; +import com.google.gson.annotations.SerializedName; + +public class Navigation { + @SerializedName("nav") + private final TableOfContent tableOfContent = new TableOfContent(); + + public void add(DocumentationPage page) { + tableOfContent.add(page); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/file/PageWriter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/file/PageWriter.java new file mode 100644 index 000000000..e5e7da90d --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/file/PageWriter.java @@ -0,0 +1,65 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.file; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.DocumentRegistry; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.page.DocumentationPage; +import com.blamejared.crafttweaker_annotation_processors.processors.util.files.DeletingPathVisitor; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.file.Files; + +public class PageWriter { + + public static final String extension = ".md"; + + private final DocumentRegistry documentRegistry; + private final File outputDirectory; + + public PageWriter(DocumentRegistry documentRegistry, File outputDirectory) { + this.documentRegistry = documentRegistry; + this.outputDirectory = outputDirectory; + } + + public void write() throws IOException { + clearOutputDirectory(); + writePages(); + } + + private void clearOutputDirectory() throws IOException { + ensureOutputDirectoryExists(); + Files.walkFileTree(outputDirectory.getAbsoluteFile().toPath(), new DeletingPathVisitor()); + } + + private void ensureOutputDirectoryExists() { + if(!outputDirectory.exists() && !outputDirectory.mkdirs()) { + throw new IllegalStateException("Could not create output directory"); + } + } + + private void writePages() throws IOException { + for(DocumentationPage page : documentRegistry.getAllPages()) { + writePage(page); + } + } + + private void writePage(DocumentationPage page) throws IOException { + final File file = new File(outputDirectory, page.pageInfo.getOutputPathWithExtension(extension)); + ensureDirectoryExistsFor(file); + writePageInfoAt(page, file); + } + + private void ensureDirectoryExistsFor(File file) { + final File parentFile = file.getParentFile(); + if(!parentFile.exists() && !parentFile.mkdirs()) { + throw new IllegalArgumentException("Could not create parent file for " + file); + } + } + + private void writePageInfoAt(DocumentationPage page, File file) throws IOException { + try(final PrintWriter writer = new PrintWriter(new FileWriter(file))) { + page.write(writer); + } + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/file/TableOfContent.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/file/TableOfContent.java new file mode 100644 index 000000000..e7819a190 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/file/TableOfContent.java @@ -0,0 +1,59 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.file; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.page.DocumentationPage; + +import java.util.*; + +public class TableOfContent { + + private final SortedMap subEntries = new TreeMap<>(); + private final SortedSet pagesAtThisLevel = new TreeSet<>(comparingOutputPath()); + + private static Comparator comparingOutputPath() { + return Comparator.comparing(page -> page.pageInfo.getOutputPath()); + } + + public void add(DocumentationPage page) { + final String outputPath = page.pageInfo.getOutputPathWithExtension(PageWriter.extension); + final List split = new LinkedList<>(Arrays.asList(outputPath.split("/"))); + add(split, page); + } + + public void add(List levels, DocumentationPage page) { + if(isAtThisLevel(levels)) { + addAtThisLevel(page); + } else { + addAtNextLevel(levels, page); + } + } + + private boolean isAtThisLevel(List levels) { + return levels.size() <= 1; + } + + private void addAtNextLevel(List levels, DocumentationPage page) { + final String nextLevel = capitalize(levels.remove(0)); + final TableOfContent nextLevelTableOfContent = this.subEntries.computeIfAbsent(nextLevel, ignored -> new TableOfContent()); + nextLevelTableOfContent.add(levels, page); + } + + private String capitalize(String name) { + if(name.isEmpty()) { + return name; + } + + return Character.toUpperCase(name.charAt(0)) + name.substring(1); + } + + private void addAtThisLevel(DocumentationPage page) { + this.pagesAtThisLevel.add(page); + } + + public SortedMap getSubEntries() { + return subEntries; + } + + public SortedSet getPagesAtThisLevel() { + return pagesAtThisLevel; + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/file/TableOfContentTypeAdapter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/file/TableOfContentTypeAdapter.java new file mode 100644 index 000000000..67cecace6 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/file/TableOfContentTypeAdapter.java @@ -0,0 +1,54 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.file; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.page.DocumentationPage; +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; + +import java.io.IOException; +import java.util.Map; +import java.util.SortedMap; +import java.util.SortedSet; + +public class TableOfContentTypeAdapter extends TypeAdapter { + + + @Override + public void write(JsonWriter out, TableOfContent value) throws IOException { + out.beginObject(); + writeSameLevelFiles(out, value); + writeNextLevel(out, value); + out.endObject(); + } + + private void writeNextLevel(JsonWriter out, TableOfContent value) throws IOException { + final SortedMap subEntries = value.getSubEntries(); + for(Map.Entry nextLevelEntry : subEntries.entrySet()) { + final String name = nextLevelEntry.getKey(); + final TableOfContent nextLevel = nextLevelEntry.getValue(); + + out.name(name); + write(out, nextLevel); + } + } + + private void writeSameLevelFiles(JsonWriter out, TableOfContent value) throws IOException { + final SortedSet pagesAtThisLevel = value.getPagesAtThisLevel(); + for(DocumentationPage documentationPage : pagesAtThisLevel) { + writePage(out, documentationPage); + } + } + + private void writePage(JsonWriter out, DocumentationPage documentationPage) throws IOException { + final String name = documentationPage.pageInfo.getSimpleName(); + final String path = documentationPage.pageInfo.getOutputPathWithExtension(PageWriter.extension); + + out.name(name); + out.value(path); + } + + @Override + public TableOfContent read(JsonReader in) { + throw new UnsupportedOperationException("Not needed here"); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/native_types/JavaLangNativeTypeProvider.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/native_types/JavaLangNativeTypeProvider.java new file mode 100644 index 000000000..20ba4652d --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/native_types/JavaLangNativeTypeProvider.java @@ -0,0 +1,46 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.native_types; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.ExistingTypeInfo; + +import javax.lang.model.element.TypeElement; +import javax.lang.model.util.Elements; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class JavaLangNativeTypeProvider implements NativeTypeProvider { + + private final Map typeInfos = new HashMap<>(); + private final Elements elementUtils; + + public JavaLangNativeTypeProvider(Elements elementUtils) { + this.elementUtils = elementUtils; + addNativeClasses(); + } + + @Override + public Map getTypeInfos() { + return typeInfos; + } + + private void addNativeClasses() { + addClass(Collection.class, "Collection"); + addClass(Set.class, "Set"); + } + + private void addClass(Class cls, String stdLibName) { + final TypeElement typeElement = getElementFor(cls); + final AbstractTypeInfo typeInfo = getTypeInfoFor(stdLibName); + typeInfos.put(typeElement, typeInfo); + } + + private TypeElement getElementFor(Class cls) { + return elementUtils.getTypeElement(cls.getCanonicalName()); + } + + private AbstractTypeInfo getTypeInfoFor(String stdLibName) { + return new ExistingTypeInfo(stdLibName); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/native_types/ModDependencyTypeProvider.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/native_types/ModDependencyTypeProvider.java new file mode 100644 index 000000000..9d331b8dc --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/native_types/ModDependencyTypeProvider.java @@ -0,0 +1,44 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.native_types; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.dependencies.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.native_types.dependency_rule.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.*; + +import javax.lang.model.element.*; +import java.util.*; + +public class ModDependencyTypeProvider implements NativeTypeProvider, IHasPostCreationCall { + + private final DependencyContainer dependencyContainer; + private final List conversionRules = new ArrayList<>(); + + public ModDependencyTypeProvider(DependencyContainer dependencyContainer) { + this.dependencyContainer = dependencyContainer; + } + + @Override + public Map getTypeInfos() { + final HashMap result = new HashMap<>(); + addInfosFromRules(result); + return result; + } + + private void addInfosFromRules(HashMap result) { + for(ModDependencyConversionRule conversionRule : conversionRules) { + final Map allFromRule = conversionRule.getAll(); + result.putAll(allFromRule); + } + } + + + @Override + public void afterCreation() { + addConversionRule(NamedTypeConversionRule.class); + addConversionRule(NativeTypeConversionRule.class); + } + + private void addConversionRule(Class ruleClass) { + final ModDependencyConversionRule rule = dependencyContainer.getInstanceOfClass(ruleClass); + this.conversionRules.add(rule); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/native_types/NativeTypeProvider.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/native_types/NativeTypeProvider.java new file mode 100644 index 000000000..6da0daf25 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/native_types/NativeTypeProvider.java @@ -0,0 +1,11 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.native_types; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; + +import javax.lang.model.element.TypeElement; +import java.util.Map; + +public interface NativeTypeProvider { + + Map getTypeInfos(); +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/native_types/StdLibsNativeTypeProvider.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/native_types/StdLibsNativeTypeProvider.java new file mode 100644 index 000000000..37a041d62 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/native_types/StdLibsNativeTypeProvider.java @@ -0,0 +1,48 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.native_types; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.ExistingTypeInfo; + +import javax.lang.model.element.TypeElement; +import javax.lang.model.util.Elements; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +public class StdLibsNativeTypeProvider implements NativeTypeProvider { + + private final Map typeInfos = new HashMap<>(); + private final Elements elementUtils; + + public StdLibsNativeTypeProvider(Elements elementUtils) { + this.elementUtils = elementUtils; + addNativeClasses(); + } + + @Override + public Map getTypeInfos() { + return typeInfos; + } + + private void addNativeClasses() { + addClass(List.class, "stdlib.List"); + addClass(Iterable.class, "stdlib.Iterable"); + addClass(Iterator.class, "stdlib.Iterator"); + addClass(StringBuilder.class, "stdlib.StringBuilder"); + } + + private void addClass(Class cls, String stdLibName) { + final TypeElement typeElement = getElementFor(cls); + final AbstractTypeInfo typeInfo = getTypeInfoFor(stdLibName); + typeInfos.put(typeElement, typeInfo); + } + + private TypeElement getElementFor(Class cls) { + return elementUtils.getTypeElement(cls.getCanonicalName()); + } + + private AbstractTypeInfo getTypeInfoFor(String stdLibName) { + return new ExistingTypeInfo(stdLibName); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/native_types/dependency_rule/ModDependencyConversionRule.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/native_types/dependency_rule/ModDependencyConversionRule.java new file mode 100644 index 000000000..1c5dff808 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/native_types/dependency_rule/ModDependencyConversionRule.java @@ -0,0 +1,10 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.native_types.dependency_rule; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.*; + +import javax.lang.model.element.*; +import java.util.*; + +public interface ModDependencyConversionRule { + Map getAll(); +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/native_types/dependency_rule/NamedTypeConversionRule.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/native_types/dependency_rule/NamedTypeConversionRule.java new file mode 100644 index 000000000..dc5e89931 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/native_types/dependency_rule/NamedTypeConversionRule.java @@ -0,0 +1,72 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.native_types.dependency_rule; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.*; +import com.blamejared.crafttweaker_annotations.annotations.*; +import org.jetbrains.annotations.*; +import org.openzen.zencode.java.*; +import org.reflections.*; + +import javax.lang.model.element.*; +import javax.lang.model.util.*; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +public class NamedTypeConversionRule implements ModDependencyConversionRule { + + private final Reflections reflections; + private final Elements elements; + + public NamedTypeConversionRule(Reflections reflections, Elements elements) { + this.reflections = reflections; + this.elements = elements; + } + + @Override + public Map getAll() { + return getClasses().stream().filter(this::isDocumented).collect(createTypeInfoMap()); + } + + private Collector, ?, Map> createTypeInfoMap() { + final Function, TypeElement> keyMapper = this::getTypeElementFromClass; + final Function, AbstractTypeInfo> valueMapper = this::getTypeInfoFromClass; + + return Collectors.toMap(keyMapper, valueMapper); + } + + private TypeElement getTypeElementFromClass(Class documentedClass) { + return elements.getTypeElement(documentedClass.getCanonicalName()); + } + + private AbstractTypeInfo getTypeInfoFromClass(Class documentedClass) { + final TypePageInfo pageInfo = getPageInfoFromClass(documentedClass); + return new TypePageTypeInfo(pageInfo); + } + + @NotNull + private TypePageInfo getPageInfoFromClass(Class documentedClass) { + final TypeName typeName = getTypeNameFromClass(documentedClass); + final String path = getDocPathFromClass(documentedClass); + + return new TypePageInfo("unknown", path, typeName); + } + + private TypeName getTypeNameFromClass(Class documentedClass) { + final ZenCodeType.Name annotation = documentedClass.getAnnotation(ZenCodeType.Name.class); + return new TypeName(annotation.value()); + } + + private String getDocPathFromClass(Class documentedClass) { + return documentedClass.getAnnotation(Document.class).value(); + } + + private boolean isDocumented(Class aClass) { + return aClass.isAnnotationPresent(Document.class); + } + + + private Set> getClasses() { + return reflections.getTypesAnnotatedWith(ZenCodeType.Name.class); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/native_types/dependency_rule/NativeTypeConversionRule.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/native_types/dependency_rule/NativeTypeConversionRule.java new file mode 100644 index 000000000..3ee09f39b --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/native_types/dependency_rule/NativeTypeConversionRule.java @@ -0,0 +1,75 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.native_types.dependency_rule; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.*; +import com.blamejared.crafttweaker_annotations.annotations.*; +import org.jetbrains.annotations.*; +import org.reflections.*; + +import javax.lang.model.element.*; +import javax.lang.model.util.*; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +public class NativeTypeConversionRule implements ModDependencyConversionRule { + + private final Reflections reflections; + private final Elements elementUtils; + + public NativeTypeConversionRule(Reflections reflections, Elements elementUtils) { + this.reflections = reflections; + this.elementUtils = elementUtils; + } + + @Override + public Map getAll() { + return getNativeExpansionClasses().stream().filter(this::isDocumented).collect(createTypeInfoMap()); + } + + private Collector, ?, Map> createTypeInfoMap() { + final Function, TypeElement> keyMapper = this::getTypeElementFromClass; + final Function, AbstractTypeInfo> valueMapper = this::getTypeInfoFromClass; + + return Collectors.toMap(keyMapper, valueMapper); + } + + private TypeElement getTypeElementFromClass(Class documentedClass) { + final NativeTypeRegistration nativeAnnotation = getNativeAnnotation(documentedClass); + return elementUtils.getTypeElement(nativeAnnotation.value().getCanonicalName()); + } + + private AbstractTypeInfo getTypeInfoFromClass(Class documentedClass) { + final TypePageInfo pageInfo = getPageInfoFromClass(documentedClass); + return new TypePageTypeInfo(pageInfo); + } + + @NotNull + private TypePageInfo getPageInfoFromClass(Class documentedClass) { + final TypeName typeName = getTypeNameFromClass(documentedClass); + final String path = getDocPathFromClass(documentedClass); + + return new TypePageInfo("unknown", path, typeName); + } + + private TypeName getTypeNameFromClass(Class documentedClass) { + final NativeTypeRegistration annotation = getNativeAnnotation(documentedClass); + return new TypeName(annotation.zenCodeName()); + } + + private NativeTypeRegistration getNativeAnnotation(Class documentedClass) { + return documentedClass.getAnnotation(NativeTypeRegistration.class); + } + + private String getDocPathFromClass(Class documentedClass) { + return documentedClass.getAnnotation(Document.class).value(); + } + + private Set> getNativeExpansionClasses() { + return reflections.getTypesAnnotatedWith(NativeTypeRegistration.class); + } + + private boolean isDocumented(Class nativeRegistrationClass) { + return nativeRegistrationClass.isAnnotationPresent(Document.class); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/comment/DocumentationComment.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/comment/DocumentationComment.java new file mode 100644 index 000000000..96959e440 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/comment/DocumentationComment.java @@ -0,0 +1,42 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.examples.Example; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.examples.ExampleData; + +import java.util.Optional; + +public class DocumentationComment { + + private final String description; + private final ExampleData exampleData; + + public DocumentationComment(String description, ExampleData exampleData) { + this.description = description; + this.exampleData = exampleData; + } + + public static DocumentationComment empty() { + return new DocumentationComment(null, ExampleData.empty()); + } + + public ExampleData getExamples() { + return exampleData; + } + + public String getDescription() { + return getOptionalDescription().orElse("No Description Provided"); + } + + public boolean hasDescription() { + return getOptionalDescription().isPresent(); + } + + public Optional getOptionalDescription() { + return Optional.ofNullable(description); + } + + public int numberOfExamplesFor(String name) { + final Optional example = exampleData.tryGetExampleFor(name); + return example.map(Example::numberOfExamples).orElse(0); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/info/DocumentationPageInfo.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/info/DocumentationPageInfo.java new file mode 100644 index 000000000..e2bb51733 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/info/DocumentationPageInfo.java @@ -0,0 +1,45 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.info; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment.DocumentationComment; + +import java.io.File; + +public class DocumentationPageInfo { + + public final String declaringModId; + private final String outputPath; + private DocumentationComment classComment; + + public DocumentationPageInfo(String declaringModId, String outputPath) { + this.declaringModId = declaringModId; + this.outputPath = outputPath; + this.classComment = DocumentationComment.empty(); + } + + public DocumentationComment getClassComment() { + return classComment; + } + + public String getOutputPathWithExtension(String fileExtension) { + if(outputPath.endsWith(fileExtension)) { + return outputPath; + } + return outputPath + fileExtension; + } + + public String getSimpleName() { + final int i = outputPath.lastIndexOf("/"); + if(i < 1) { + return outputPath; + } + return outputPath.substring(i + 1); + } + + public String getOutputPath() { + return outputPath; + } + + public void setTypeComment(DocumentationComment typeComment) { + this.classComment = typeComment; + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/info/TypeName.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/info/TypeName.java new file mode 100644 index 000000000..db2361780 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/info/TypeName.java @@ -0,0 +1,49 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.info; + +import javax.annotation.Nonnull; + +public class TypeName implements Comparable { + + private final String zenCodeName; + + public TypeName(String zenCodeName) { + this.zenCodeName = zenCodeName; + } + + public String getZenCodeName() { + return zenCodeName; + } + + public String getSimpleName() { + final int lastDotIndex = zenCodeName.lastIndexOf('.'); + return zenCodeName.substring(lastDotIndex + 1); + } + + public int compareTo(@Nonnull TypeName other) { + return this.zenCodeName.compareTo(other.zenCodeName); + } + + // + @Override + public String toString() { + return getZenCodeName(); + } + + @Override + public boolean equals(Object o) { + if(this == o) + return true; + if(o == null || getClass() != o.getClass()) + return false; + + TypeName typeName = (TypeName) o; + + return zenCodeName.equals(typeName.zenCodeName); + } + + @Override + public int hashCode() { + return zenCodeName.hashCode(); + } + // +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/info/TypePageInfo.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/info/TypePageInfo.java new file mode 100644 index 000000000..e58f76ecd --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/info/TypePageInfo.java @@ -0,0 +1,23 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.info; + +import javax.annotation.*; + +public class TypePageInfo extends DocumentationPageInfo implements Comparable { + + public final TypeName zenCodeName; + + public TypePageInfo(String declaringModId, String outputPath, TypeName zenCodeName) { + super(declaringModId, outputPath); + this.zenCodeName = zenCodeName; + } + + @Override + public int compareTo(@Nonnull TypePageInfo o) { + return this.zenCodeName.compareTo(o.zenCodeName); + } + + @Override + public String getSimpleName() { + return zenCodeName.getSimpleName(); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/PropertyMember.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/PropertyMember.java new file mode 100644 index 000000000..846f44b4b --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/PropertyMember.java @@ -0,0 +1,39 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; + +import java.io.PrintWriter; + +public class PropertyMember { + + private final AbstractTypeInfo type; + private final String name; + private final boolean hasGetter; + private final boolean hasSetter; + + public PropertyMember(String name, AbstractTypeInfo type, boolean hasGetter, boolean hasSetter) { + this.hasGetter = hasGetter; + this.hasSetter = hasSetter; + this.type = type; + this.name = name; + } + + public static PropertyMember merge(PropertyMember left, PropertyMember right) { + if(!left.name.equals(right.name)) { + throw new IllegalArgumentException("Trying to merge different names!"); + } + + final boolean hasGetter = left.hasGetter || right.hasGetter; + final boolean hasSetter = left.hasSetter || right.hasSetter; + + return new PropertyMember(left.name, left.type, hasGetter, hasSetter); + } + + public void writeTableRow(PrintWriter writer) { + writer.printf("| %s | %s | %s | %s |%n", name, type.getClickableMarkdown(), hasGetter, hasSetter); + } + + public String getName() { + return name; + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/header/DocumentedGenericParameter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/header/DocumentedGenericParameter.java new file mode 100644 index 000000000..c74e2860b --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/header/DocumentedGenericParameter.java @@ -0,0 +1,94 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment.DocumentationComment; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; +import org.jetbrains.annotations.*; + +import javax.annotation.Nonnull; +import java.io.*; +import java.util.List; +import java.util.stream.Collectors; + +public class DocumentedGenericParameter implements Comparable { + + + private final String name; + + private final DocumentationComment comment; + private final List bounds; + + public DocumentedGenericParameter(List bounds, String name, DocumentationComment comment) { + this.bounds = bounds; + this.name = name; + this.comment = comment; + } + + public String formatForSignatureExample() { + if(bounds.isEmpty()) { + return name; + } + + final String prefix = name + " : "; + return prefix + getDisplayNameBounds(); + } + + @NotNull + private String getDisplayNameBounds() { + return bounds.stream() + .map(AbstractTypeInfo::getDisplayName) + .collect(Collectors.joining(", ")); + } + + @NotNull + private String getClickableMarkdownBounds() { + return bounds.stream() + .map(AbstractTypeInfo::getClickableMarkdown) + .collect(Collectors.joining(", ")); + } + + private String getExampleName() { + return "<" + name + ">"; + } + + public int numberOfExamples() { + return comment.numberOfExamplesFor(getExampleName()); + } + + public String getDescription() { + return comment.getDescription(); + } + + public String getExample(int exampleIndex) { + return comment.getExamples().getExampleFor(getExampleName()).getTextValue(exampleIndex); + } + + public void writeParameterInfoIncludeOptionality(PrintWriter writer) { + writer.printf("| %s | %s | %s | N/A | N/A |%n", name, getClickableMarkdownBounds(), getDescription()); + } + + public void writeParameterInfoExcludeOptionality(PrintWriter writer) { + writer.printf("| %s | %s | %s |%n", name, getClickableMarkdownBounds(), getDescription()); + } + + @Override + public int compareTo(@Nonnull DocumentedGenericParameter other) { + int temp = this.name.compareTo(other.name); + if(temp != 0) { + return temp; + } + + temp = this.bounds.size() - other.bounds.size(); + if(temp != 0) { + return temp; + } + + for(int i = 0; i < this.bounds.size(); i++) { + temp = this.bounds.get(i).compareTo(other.bounds.get(i)); + if(temp != 0) { + return temp; + } + } + + return 0; + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/header/DocumentedOptionalParameter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/header/DocumentedOptionalParameter.java new file mode 100644 index 000000000..9d6adeabb --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/header/DocumentedOptionalParameter.java @@ -0,0 +1,32 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment.DocumentationComment; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; + +import javax.annotation.Nullable; +import java.io.PrintWriter; + +public class DocumentedOptionalParameter extends DocumentedParameter { + + @Nullable + private final String defaultValue; + + public DocumentedOptionalParameter(String name, AbstractTypeInfo type, DocumentationComment comment, @Nullable String defaultValue) { + super(name, type, comment); + this.defaultValue = defaultValue; + } + + @Override + public void writeParameterInfoIncludeOptionality(PrintWriter writer) { + writer.printf("| %s | %s | %s | %s | %s |", name, type.getClickableMarkdown(), getDescription(), true, getDefaultValue()); + } + + public String getDefaultValue() { + return defaultValue == null ? "Error: None given" : defaultValue; + } + + @Override + public boolean isOptional() { + return true; + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/header/DocumentedParameter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/header/DocumentedParameter.java new file mode 100644 index 000000000..8a74fa758 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/header/DocumentedParameter.java @@ -0,0 +1,58 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment.DocumentationComment; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; + +import javax.annotation.Nonnull; +import java.io.PrintWriter; + +public class DocumentedParameter implements Comparable { + + protected final String name; + protected final AbstractTypeInfo type; + protected final DocumentationComment comment; + + public DocumentedParameter(String name, AbstractTypeInfo type, DocumentationComment comment) { + this.name = name; + this.type = type; + this.comment = comment; + } + + public String formatForSignatureExample() { + return String.format("%s as %s", name, type.getDisplayName()); + } + + public int numberOfExamples() { + return comment.numberOfExamplesFor(name); + } + + public String getDescription() { + return comment.getDescription(); + } + + public boolean isOptional() { + return false; + } + + public void writeParameterInfoIncludeOptionality(PrintWriter writer) { + writer.printf("| %s | %s | %s | %s | %s |%n", name, type.getClickableMarkdown(), getDescription(), false, ""); + } + + public void writeParameterInfoExcludeOptionality(PrintWriter writer) { + writer.printf("| %s | %s | %s |%n", name, type.getClickableMarkdown(), getDescription()); + } + + public String getExample(int index) { + return comment.getExamples().getExampleFor(name).getTextValue(index); + } + + @Override + public int compareTo(@Nonnull DocumentedParameter other) { + int temp = this.name.compareTo(other.name); + if(temp != 0) { + return temp; + } + + return this.type.compareTo(other.type); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/header/MemberHeader.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/header/MemberHeader.java new file mode 100644 index 000000000..a498e7690 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/header/MemberHeader.java @@ -0,0 +1,170 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.examples.*; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.*; + +import javax.annotation.*; +import java.io.*; +import java.util.*; +import java.util.stream.*; + +public class MemberHeader implements Comparable { + + public final AbstractTypeInfo returnType; + public final List parameters; + public final List genericParameters; + + public MemberHeader(AbstractTypeInfo returnType, List parameters, List genericParameters) { + this.returnType = returnType; + this.parameters = parameters; + this.genericParameters = genericParameters; + } + + public String formatForSignatureExample() { + return formatGenericParametersForSignatureExample() + formatParametersForSignatureExample(); + } + + private String formatGenericParametersForSignatureExample() { + if(genericParameters.isEmpty()) { + return ""; + } + + final StringJoiner stringJoiner = new StringJoiner(", ", "<", ">"); + for(DocumentedGenericParameter genericParameter : genericParameters) { + stringJoiner.add(genericParameter.formatForSignatureExample()); + } + return stringJoiner.toString(); + } + + private String formatParametersForSignatureExample() { + final String displayName = returnType.getDisplayName(); + final StringJoiner stringJoiner = new StringJoiner(", ", "(", ") as " + displayName); + for(DocumentedParameter parameter : parameters) { + stringJoiner.add(parameter.formatForSignatureExample()); + } + return stringJoiner.toString(); + } + + public void writeStaticExamples(PrintWriter writer, AbstractTypeInfo ownerType, String name) { + final String callee = ownerType.getDisplayName(); + writeCallTo(writer, String.format("%s.%s", callee, name)); + } + + public void writeVirtualExamples(PrintWriter writer, ExampleData aThis, String name) { + final String example = aThis.getExampleFor("this").getAnyTextValue(); + writeCallTo(writer, String.format("%s.%s", example, name)); + } + + public void writeConstructorExamples(PrintWriter writer, AbstractTypeInfo constructedType) { + writeCallTo(writer, String.format("new %s", constructedType.getDisplayName())); + } + + private void writeCallTo(PrintWriter writer, String callee) { + int numberOfUsableExamples = getNumberOfUsableExamples(); + if(numberOfUsableExamples == 0) { + return; + } + for(int i = 0; i < numberOfUsableExamples; i++) { + writeExample(writer, callee, i); + } + } + + private void writeExample(PrintWriter writer, String callee, int i) { + final String arguments = getExample(i); + writer.printf("%s%s;%n", callee, arguments); + } + + private String getExample(int exampleIndex) { + final String exampleTypeArgument = getExampleTypeArgument(exampleIndex); + final String exampleArgument = getExampleArgument(exampleIndex); + return String.format("%s(%s)", exampleTypeArgument, exampleArgument); + } + + @Nonnull + public String getExampleArgument(int exampleIndex) { + return parameters.stream().map(parameters -> parameters.getExample(exampleIndex)).collect(Collectors.joining(", ")); + } + + @Nonnull + private String getExampleTypeArgument(int exampleIndex) { + if(genericParameters.isEmpty()) { + return ""; + } + + return genericParameters.stream().map(parameters -> parameters.getExample(exampleIndex)).collect(Collectors.joining(", ", "<", ">")); + } + + public int getNumberOfUsableExamples() { + final IntStream parameterExampleCount = parameters.stream().mapToInt(DocumentedParameter::numberOfExamples); + final IntStream genericParameterExampleCount = genericParameters.stream().mapToInt(DocumentedGenericParameter::numberOfExamples); + + return IntStream.concat(parameterExampleCount, genericParameterExampleCount).min().orElse(1); + } + + public void writeParameterDescriptionTable(PrintWriter writer) { + if(parameters.isEmpty() && genericParameters.isEmpty()) { + return; + } + if(hasOptionalTypes()) { + writeParameterDescriptionTableWithOptionals(writer); + } else { + writeParameterDescriptionTableWithoutOptionals(writer); + } + writer.println(); + } + + private void writeParameterDescriptionTableWithoutOptionals(PrintWriter writer) { + writer.println("| Parameter | Type | Description |"); + writer.println("|-----------|------|-------------|"); + for(DocumentedParameter parameter : parameters) { + parameter.writeParameterInfoExcludeOptionality(writer); + } + + for(DocumentedGenericParameter genericParameter : genericParameters) { + genericParameter.writeParameterInfoExcludeOptionality(writer); + } + } + + private void writeParameterDescriptionTableWithOptionals(PrintWriter writer) { + writer.println("| Parameter | Type | Description | Optional | DefaultValue |"); + writer.println("|-----------|------|-------------|----------|--------------|"); + for(DocumentedParameter parameter : parameters) { + parameter.writeParameterInfoIncludeOptionality(writer); + } + + for(DocumentedGenericParameter parameter : genericParameters) { + parameter.writeParameterInfoIncludeOptionality(writer); + } + } + + private boolean hasOptionalTypes() { + return parameters.stream().anyMatch(DocumentedParameter::isOptional); + } + + @Override + public int compareTo(@Nonnull MemberHeader other) { + int temp = this.parameters.size() - other.parameters.size(); + if(temp != 0) { + return temp; + } + temp = this.genericParameters.size() - other.genericParameters.size(); + if(temp != 0) { + return temp; + } + + for(int i = 0; i < this.parameters.size(); i++) { + temp = this.parameters.get(i).compareTo(other.parameters.get(i)); + if(temp != 0) { + return temp; + } + } + + for(int i = 0; i < this.genericParameters.size(); i++) { + temp = this.genericParameters.get(i).compareTo(other.genericParameters.get(i)); + if(temp != 0) { + return temp; + } + } + return 0; + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/header/examples/Example.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/header/examples/Example.java new file mode 100644 index 000000000..0067eaf70 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/header/examples/Example.java @@ -0,0 +1,53 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.examples; + +import java.util.ArrayList; +import java.util.List; + +public class Example { + + private final List textValues; + private final String name; + + public Example(String name) { + this.name = name; + this.textValues = new ArrayList<>(); + } + + public Example(String name, String text) { + this.textValues = new ArrayList<>(); + this.textValues.add(text); + this.name = name; + } + + public static Example merge(Example left, Example right) { + if(!left.name.equals(right.name)) { + throw new IllegalArgumentException("Names do not match! " + left.name + " != " + right.name); + } + + final Example result = new Example(left.name); + result.textValues.addAll(left.textValues); + result.textValues.addAll(right.textValues); + + return result; + } + + public void addTextValue(String textValue) { + this.textValues.add(textValue); + } + + public int numberOfExamples() { + return textValues.size(); + } + + public String getName() { + return name; + } + + public String getAnyTextValue() { + return getTextValue(0); + } + + public String getTextValue(int index) { + return textValues.get(index); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/header/examples/ExampleData.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/header/examples/ExampleData.java new file mode 100644 index 000000000..2be6330a9 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/header/examples/ExampleData.java @@ -0,0 +1,54 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.examples; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +public class ExampleData { + + private final Map examples; + + private ExampleData() { + this.examples = new HashMap<>(1); + } + + public ExampleData(Example example) { + this(); + this.examples.put(example.getName(), example); + } + + public ExampleData(Map examples) { + this.examples = examples; + } + + public static ExampleData empty() { + return new ExampleData(); + } + + public void addExample(Example example) { + this.examples.put(example.getName(), example); + } + + public int numberOfExamples() { + return examples.values().stream().mapToInt(Example::numberOfExamples).min().orElse(0); + } + + public boolean hasExampleFor(String name) { + return examples.containsKey(name); + } + + public Example getExampleFor(String name) { + return tryGetExampleFor(name).orElseThrow(() -> new IllegalArgumentException("No example registered for: " + name)); + } + + public Optional tryGetExampleFor(String name) { + if(hasExampleFor(name)) { + return Optional.of(examples.get(name)); + } + return Optional.empty(); + } + + public Map getExampleMap() { + return examples; + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/static_member/BracketExpressionStaticMethodMember.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/static_member/BracketExpressionStaticMethodMember.java new file mode 100644 index 000000000..154c4284a --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/static_member/BracketExpressionStaticMethodMember.java @@ -0,0 +1,74 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.static_member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment.DocumentationComment; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.MemberHeader; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.PrintWriter; + +public class BracketExpressionStaticMethodMember extends StaticMethodMember { + + private final String bepName; + + public BracketExpressionStaticMethodMember(String name, MemberHeader header, @Nullable DocumentationComment methodComment, String returntypeInfo, String bepName) { + super(name, header, methodComment, returntypeInfo); + this.bepName = bepName; + } + + public String getBepName() { + return bepName; + } + + @Override + protected void writeExampleBlockContent(PrintWriter writer, AbstractTypeInfo ownerType) { + writeBepExamples(writer); + super.writeExampleBlockContent(writer, ownerType); + } + + private void writeBepExamples(PrintWriter writer) { + final int numberOfUsableExamples = header.getNumberOfUsableExamples(); + if(numberOfUsableExamples < 1) { + return; + } + + for(int exampleIndex = 0; exampleIndex < numberOfUsableExamples; exampleIndex++) { + writeBepExample(writer, exampleIndex); + } + writer.println(); + } + + private void writeBepExample(PrintWriter writer, int exampleIndex) { + final String example = getExampleArgument(exampleIndex); + writer.printf("<%s:%s>%n", bepName, example); + } + + @Nonnull + private String getExampleArgument(int exampleIndex) { + final String exampleArgument = header.getExampleArgument(exampleIndex); + return removeQuotesFrom(exampleArgument); + } + + private String removeQuotesFrom(String exampleArgument) { + exampleArgument = removeQuoteAtFront(exampleArgument); + exampleArgument = removeQuoteAtBack(exampleArgument); + return exampleArgument; + } + + @Nonnull + private String removeQuoteAtFront(String exampleArgument) { + if(exampleArgument.startsWith("\"")) { + return exampleArgument.substring(1); + } + return exampleArgument; + } + + @Nonnull + private String removeQuoteAtBack(String exampleArgument) { + if(exampleArgument.endsWith("\"")) { + return exampleArgument.substring(0, exampleArgument.length() - 1); + } + return exampleArgument; + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/static_member/DocumentedStaticMembers.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/static_member/DocumentedStaticMembers.java new file mode 100644 index 000000000..c31f0b1b9 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/static_member/DocumentedStaticMembers.java @@ -0,0 +1,54 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.static_member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.PropertyMember; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; + +import java.io.PrintWriter; +import java.util.Map; +import java.util.TreeMap; + +public class DocumentedStaticMembers { + + protected final Map properties = new TreeMap<>(); + protected final Map methodGroups = new TreeMap<>(); + + public void write(PrintWriter writer) { + writeStaticMethods(writer); + writeProperties(writer); + } + + + private void writeStaticMethods(PrintWriter writer) { + if(methodGroups.isEmpty()) { + return; + } + + writer.printf("## Methods%n%n"); + + for(StaticMethodGroup value : methodGroups.values()) { + value.writeStaticMethods(writer); + } + } + + protected void writeProperties(PrintWriter writer) { + if(properties.isEmpty()) { + return; + } + + writer.printf("## Properties%n%n"); + writer.println("| Name | Type | Has Getter | Has Setter |"); + writer.println("|------|------|------------|------------|"); + for(PropertyMember value : properties.values()) { + value.writeTableRow(writer); + } + } + + public void addProperty(PropertyMember propertyMember) { + properties.put(propertyMember.getName(), propertyMember); + } + + public void addMethod(StaticMethodMember staticMethodMember, AbstractTypeInfo ownerType) { + final StaticMethodGroup group = methodGroups.computeIfAbsent(staticMethodMember.getName(), name -> new StaticMethodGroup(name, ownerType)); + group.addMethod(staticMethodMember); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/static_member/StaticMethodGroup.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/static_member/StaticMethodGroup.java new file mode 100644 index 000000000..22a2d9e0c --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/static_member/StaticMethodGroup.java @@ -0,0 +1,38 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.static_member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; + +import java.io.PrintWriter; +import java.util.Set; +import java.util.TreeSet; + +public class StaticMethodGroup { + + private final String name; + private final AbstractTypeInfo ownerType; + private final Set staticMethods = new TreeSet<>(); + + public StaticMethodGroup(String name, AbstractTypeInfo ownerType) { + this.name = name; + this.ownerType = ownerType; + } + + public void addMethod(StaticMethodMember member) { + this.staticMethods.add(member); + } + + public void writeStaticMethods(PrintWriter writer) { + writeTitle(writer); + writeMethods(writer); + } + + private void writeMethods(PrintWriter writer) { + for(StaticMethodMember method : staticMethods) { + method.write(writer, ownerType); + } + } + + private void writeTitle(PrintWriter writer) { + writer.printf("### %s%n%n", name); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/static_member/StaticMethodMember.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/static_member/StaticMethodMember.java new file mode 100644 index 000000000..f098ec930 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/static_member/StaticMethodMember.java @@ -0,0 +1,97 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.static_member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment.DocumentationComment; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.MemberHeader; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.PrintWriter; + +public class StaticMethodMember implements Comparable { + + protected final MemberHeader header; + private final String name; + private final DocumentationComment methodComment; + @Nullable + private final String returnTypeInfo; + + public StaticMethodMember(String name, MemberHeader header, DocumentationComment methodComment, @Nullable String returnTypeInfo) { + this.name = name; + this.header = header; + this.methodComment = methodComment; + this.returnTypeInfo = returnTypeInfo; + } + + @Override + public int compareTo(@Nonnull StaticMethodMember other) { + final int compareName = this.name.compareToIgnoreCase(other.name); + if(compareName != 0) { + return compareName; + } + + return this.header.compareTo(other.header); + } + + public void write(PrintWriter writer, AbstractTypeInfo ownerType) { + writeComment(writer); + writeReturnType(writer); + writeCodeBlockWithExamples(writer, ownerType); + writeParameterDescriptionTable(writer); + } + + private void writeParameterDescriptionTable(PrintWriter writer) { + header.writeParameterDescriptionTable(writer); + } + + private void writeReturnType(PrintWriter writer) { + writer.printf("Return Type: %s%n%n", header.returnType.getClickableMarkdown()); + } + + private void writeCodeBlockWithExamples(PrintWriter writer, AbstractTypeInfo ownerType) { + writer.println("```zenscript"); + writeExampleBlockContent(writer, ownerType); + writer.println("```"); + } + + protected void writeExampleBlockContent(PrintWriter writer, AbstractTypeInfo ownerType) { + writeSignatureExample(writer, ownerType); + writeExamples(writer, ownerType); + } + + private void writeSignatureExample(PrintWriter writer, AbstractTypeInfo ownerType) { + final String ownerName = ownerType.getDisplayName(); + final String signature = header.formatForSignatureExample(); + writer.printf("%s.%s%s%n", ownerName, name, signature); + } + + private void writeExamples(PrintWriter writer, AbstractTypeInfo ownerType) { + header.writeStaticExamples(writer, ownerType, name); + } + + private void writeComment(PrintWriter writer) { + writeDescription(writer); + writeReturnTypeInfo(writer); + } + + private void writeReturnTypeInfo(PrintWriter writer) { + if(returnTypeInfoPresent()) { + writer.printf("Returns: %s%n", returnTypeInfo); + } + } + + private boolean returnTypeInfoPresent() { + return returnTypeInfo != null; + } + + private void writeDescription(PrintWriter writer) { + if(methodComment.hasDescription()) { + writer.println(methodComment.getDescription()); + writer.println(); + } + } + + public String getName() { + return name; + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/AbstractVirtualMember.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/AbstractVirtualMember.java new file mode 100644 index 000000000..207946bab --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/AbstractVirtualMember.java @@ -0,0 +1,20 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment.DocumentationComment; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.MemberHeader; + +public abstract class AbstractVirtualMember { + + public final MemberHeader header; + private final DocumentationComment comment; + + protected AbstractVirtualMember(MemberHeader header, DocumentationComment comment) { + this.header = header; + this.comment = comment; + } + + + public DocumentationComment getComment() { + return comment; + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/CasterMember.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/CasterMember.java new file mode 100644 index 000000000..970a80502 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/CasterMember.java @@ -0,0 +1,27 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment.DocumentationComment; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.MemberHeader; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.PrintWriter; + +public class CasterMember extends AbstractVirtualMember implements Comparable { + + private final boolean isImplicit; + + public CasterMember(MemberHeader header, @Nullable DocumentationComment description, boolean isImplicit) { + super(header, description); + this.isImplicit = isImplicit; + } + + @Override + public int compareTo(@Nonnull CasterMember o) { + return this.header.returnType.compareTo(o.header.returnType); + } + + public void writeTableRow(PrintWriter writer) { + writer.printf("| %s | %s |%n", header.returnType.getClickableMarkdown(), isImplicit); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/ConstructorMember.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/ConstructorMember.java new file mode 100644 index 000000000..db0947dca --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/ConstructorMember.java @@ -0,0 +1,53 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment.DocumentationComment; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.MemberHeader; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.PrintWriter; + +public class ConstructorMember extends AbstractVirtualMember implements Comparable { + + public ConstructorMember(MemberHeader header, @Nullable DocumentationComment description) { + super(header, description); + } + + @Override + public int compareTo(@Nonnull ConstructorMember other) { + return this.header.parameters.size() - other.header.parameters.size(); + } + + public void write(PrintWriter writer) { + writeDescription(writer); + writeCodeBlock(writer); + writeParameterDescriptionTable(writer); + } + + private void writeParameterDescriptionTable(PrintWriter writer) { + header.writeParameterDescriptionTable(writer); + } + + private void writeDescription(PrintWriter writer) { + final DocumentationComment comment = getComment(); + writer.println(comment.getDescription()); + } + + private AbstractTypeInfo getConstructedType() { + return header.returnType; + } + + private void writeCodeBlock(PrintWriter writer) { + writer.println("```zenscript"); + writeSignature(writer); + header.writeConstructorExamples(writer, getConstructedType()); + writer.println("```"); + } + + private void writeSignature(PrintWriter writer) { + final String ownerName = getConstructedType().getDisplayName(); + final String signature = header.formatForSignatureExample(); + writer.printf("new %s%s%n", ownerName, signature); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/DocumentedTypeVirtualMembers.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/DocumentedTypeVirtualMembers.java new file mode 100644 index 000000000..1e47c128a --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/DocumentedTypeVirtualMembers.java @@ -0,0 +1,35 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member; + +import java.io.PrintWriter; +import java.util.Set; +import java.util.TreeSet; + +public class DocumentedTypeVirtualMembers extends DocumentedVirtualMembers { + + public final Set constructors = new TreeSet<>(); + + public DocumentedTypeVirtualMembers() { + } + + public void addConstructor(ConstructorMember constructorMember) { + this.constructors.add(constructorMember); + } + + @Override + public void write(PrintWriter writer) { + writeConstructors(writer); + super.write(writer); + } + + private void writeConstructors(PrintWriter writer) { + if(constructors.isEmpty()) { + return; + } + writer.printf("## Constructors%n%n"); + for(ConstructorMember constructor : constructors) { + constructor.write(writer); + } + + writer.println(); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/DocumentedVirtualMembers.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/DocumentedVirtualMembers.java new file mode 100644 index 000000000..569575751 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/DocumentedVirtualMembers.java @@ -0,0 +1,99 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.PropertyMember; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; + +import java.io.PrintWriter; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; + +public class DocumentedVirtualMembers { + + protected final Set casters = new TreeSet<>(); + protected final Map methodGroups = new TreeMap<>(); + protected final Set operators = new TreeSet<>(); + protected final Map properties = new TreeMap<>(); + + public DocumentedVirtualMembers() { + } + + public void addCaster(CasterMember casterMember) { + casters.add(casterMember); + } + + public void addMethod(VirtualMethodMember methodMember, AbstractTypeInfo ownerType) { + final VirtualMethodGroup group = methodGroups.computeIfAbsent(methodMember.getName(), name -> new VirtualMethodGroup(name, ownerType)); + group.addMethod(methodMember); + } + + public void addOperator(OperatorMember operatorMember) { + operators.add(operatorMember); + } + + public void addProperty(PropertyMember propertyMember) { + properties.merge(propertyMember.getName(), propertyMember, PropertyMember::merge); + } + + public void write(PrintWriter writer) { + writeCasters(writer); + writeMethods(writer); + writeOperators(writer); + writeProperties(writer); + } + + protected void writeCasters(PrintWriter writer) { + if(casters.isEmpty()) { + return; + } + + writer.printf("## Casters%n%n"); + writer.println("| Result type | Is Implicit |"); + writer.println("|-------------|-------------|"); + for(CasterMember caster : casters) { + caster.writeTableRow(writer); + } + writer.println(); + } + + protected void writeMethods(PrintWriter writer) { + if(methodGroups.isEmpty()) { + return; + } + writer.printf("## Methods%n%n"); + + for(VirtualMethodGroup value : methodGroups.values()) { + value.writeVirtualMethods(writer); + } + writer.println(); + } + + protected void writeOperators(PrintWriter writer) { + if(operators.isEmpty()) { + return; + } + + writer.printf("## Operators%n%n"); + for(OperatorMember operator : operators) { + operator.write(writer); + } + writer.println(); + } + + protected void writeProperties(PrintWriter writer) { + if(properties.isEmpty()) { + return; + } + + writer.printf("## Properties%n%n"); + writer.println("| Name | Type | Has Getter | Has Setter |"); + writer.println("|------|------|------------|------------|"); + for(PropertyMember value : properties.values()) { + value.writeTableRow(writer); + } + writer.println(); + } + + +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/util/FormattingUtils.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/OperatorFormatProvider.java similarity index 62% rename from Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/util/FormattingUtils.java rename to Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/OperatorFormatProvider.java index 9471ebefa..41cee9cc4 100644 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/util/FormattingUtils.java +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/OperatorFormatProvider.java @@ -1,12 +1,11 @@ -package com.blamejared.crafttweaker_annotation_processors.processors.document.shared.util; +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member; import org.openzen.zencode.java.ZenCodeType; -public class FormattingUtils { - - +public class OperatorFormatProvider { + public static String getOperatorFormat(ZenCodeType.OperatorType operator) { - switch (operator) { + switch(operator) { case ADD: return "%s + %s"; case SUB: @@ -73,59 +72,11 @@ public static String getOperatorFormat(ZenCodeType.OperatorType operator) { return "%s <<= %s"; case SHRASSIGN: return "%s >>= %s"; - - default: - return ""; - } - } - - public static int getOperandCountFor(ZenCodeType.OperatorType operator) { - switch (operator) { - //Unary Operators - case NEG: - case INVERT: - case NOT: - return 1; - - //Binary Operators - case INDEXGET: - case ADD: - case SUB: - case MUL: - case DIV: - case MOD: - case CAT: - case OR: - case AND: - case XOR: - case CONTAINS: - case COMPARE: - case MEMBERGETTER: - case EQUALS: - case NOTEQUALS: - case SHL: - case SHR: - case ADDASSIGN: - case SUBASSIGN: - case MULASSIGN: - case DIVASSIGN: - case MODASSIGN: - case CATASSIGN: - case ORASSIGN: - case ANDASSIGN: - case XORASSIGN: - case SHLASSIGN: - case SHRASSIGN: - return 2; - - //Ternary Operators - case INDEXSET: - case MEMBERSETTER: - return 3; - + default: - return 0; + throw new IllegalArgumentException("Unsupported operator: " + operator); } } - + + } diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/OperatorMember.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/OperatorMember.java new file mode 100644 index 000000000..6a59fb638 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/OperatorMember.java @@ -0,0 +1,123 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment.DocumentationComment; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.DocumentedParameter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.MemberHeader; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; +import org.openzen.zencode.java.ZenCodeType; + +import javax.annotation.Nonnull; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class OperatorMember extends AbstractVirtualMember implements Comparable { + + private final ZenCodeType.OperatorType type; + private final AbstractTypeInfo ownerType; + + public OperatorMember(MemberHeader header, DocumentationComment comment, ZenCodeType.OperatorType type, AbstractTypeInfo ownerType) { + super(header, comment); + this.type = type; + this.ownerType = ownerType; + } + + @Override + public int compareTo(@Nonnull OperatorMember other) { + return this.type.name().compareToIgnoreCase(other.type.name()); + } + + public void write(PrintWriter writer) { + writeTitle(writer); + writeDescription(writer); + writeScriptBlock(writer); + writer.println(); + writer.println(); + } + + private void writeTitle(PrintWriter writer) { + writer.printf("### %s%n%n", type.name()); + } + + private void writeDescription(PrintWriter writer) { + if(getComment().hasDescription()) { + writer.println(getComment().getDescription()); + writer.println(); + } + } + + private void writeScriptBlock(PrintWriter writer) { + writer.println("```zenscript"); + writeScriptBlockInner(writer); + writer.println("```"); + } + + private void writeScriptBlockInner(PrintWriter writer) { + writeHeader(writer); + writeExamples(writer); + } + + private void writeExamples(PrintWriter writer) { + final int numberOfUsableExamples = header.getNumberOfUsableExamples(); + if(numberOfUsableExamples < 1) { + return; + } + + for(int exampleIndex = 0; exampleIndex < numberOfUsableExamples; exampleIndex++) { + writeExample(writer, exampleIndex); + } + } + + private void writeExample(PrintWriter writer, int exampleIndex) { + final List exampleArguments = getExampleArguments(exampleIndex); + + exampleArguments.add(0, getExampleCallee()); + + final String operatorFormat = OperatorFormatProvider.getOperatorFormat(type); + final Object[] arguments = exampleArguments.toArray(); + writer.printf(operatorFormat, arguments); + writer.println(); + } + + @Nonnull + private ArrayList getExampleArguments(int exampleIndex) { + final String exampleArgument = header.getExampleArgument(exampleIndex); + final String[] split = exampleArgument.split(", "); + return new ArrayList<>(Arrays.asList(split)); + } + + private void writeHeader(PrintWriter writer) { + final String operatorFormat = OperatorFormatProvider.getOperatorFormat(type); + final Object[] parameters = getParameters(); + + writer.printf(operatorFormat, parameters); + writer.println(); + } + + @Nonnull + private Object[] getParameters() { + final List parametersFromHeader = getParametersFromHeader(); + final Object callee = getHeaderCallee(); + + parametersFromHeader.add(0, callee); + + return parametersFromHeader.toArray(); + } + + @Nonnull + private List getParametersFromHeader() { + return header.parameters.stream() + .map(DocumentedParameter::formatForSignatureExample) + .collect(Collectors.toList()); + } + + private String getExampleCallee() { + return getComment().getExamples().getExampleFor("this").getAnyTextValue(); + } + + private String getHeaderCallee() { + return "my" + ownerType.getDisplayName(); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/VirtualMethodGroup.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/VirtualMethodGroup.java new file mode 100644 index 000000000..c296a247a --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/VirtualMethodGroup.java @@ -0,0 +1,30 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; + +import java.io.PrintWriter; +import java.util.Set; +import java.util.TreeSet; + +public class VirtualMethodGroup { + + private final String name; + private final AbstractTypeInfo ownerType; + private final Set virtualMethods = new TreeSet<>(); + + public VirtualMethodGroup(String name, AbstractTypeInfo ownerType) { + this.name = name; + this.ownerType = ownerType; + } + + public void addMethod(VirtualMethodMember member) { + this.virtualMethods.add(member); + } + + public void writeVirtualMethods(PrintWriter writer) { + writer.printf("### %s%n%n", name); + for(VirtualMethodMember method : virtualMethods) { + method.write(writer, ownerType); + } + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/VirtualMethodMember.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/VirtualMethodMember.java new file mode 100644 index 000000000..9ac8c9582 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/member/virtual_member/VirtualMethodMember.java @@ -0,0 +1,70 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.comment.DocumentationComment; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.MemberHeader; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.PrintWriter; +import java.util.Optional; + +public class VirtualMethodMember extends AbstractVirtualMember implements Comparable { + + private final String name; + + public VirtualMethodMember(MemberHeader header, @Nullable DocumentationComment description, String name) { + super(header, description); + this.name = name; + } + + @Override + public int compareTo(@Nonnull VirtualMethodMember other) { + final int compareName = this.name.compareToIgnoreCase(other.name); + if(compareName != 0) { + return compareName; + } + + return this.header.compareTo(other.header); + } + + public void write(PrintWriter writer, AbstractTypeInfo ownerType) { + writeComment(writer); + writeReturnType(writer); + writeCodeBlockWithExamples(writer, ownerType); + writeParameterDescriptionTable(writer); + } + + private void writeComment(PrintWriter writer) { + final Optional optionalDescription = getComment().getOptionalDescription(); + + if(optionalDescription.isPresent()) { + writer.println(optionalDescription.get()); + writer.println(); + } + } + + private void writeReturnType(PrintWriter writer) { + writer.printf("Return Type: %s%n%n", header.returnType.getClickableMarkdown()); + } + + private void writeCodeBlockWithExamples(PrintWriter writer, AbstractTypeInfo ownerType) { + writer.println("```zenscript"); + writeSignatureExample(writer, ownerType); + header.writeVirtualExamples(writer, getComment().getExamples(), name); + writer.println("```"); + } + + private void writeSignatureExample(PrintWriter writer, AbstractTypeInfo ownerType) { + final String callee = ownerType.getDisplayName(); + writer.printf("%s.%s%s%n", callee, name, header.formatForSignatureExample()); + } + + private void writeParameterDescriptionTable(PrintWriter writer) { + header.writeParameterDescriptionTable(writer); + } + + public String getName() { + return name; + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/page/DocumentationPage.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/page/DocumentationPage.java new file mode 100644 index 000000000..84f3301c4 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/page/DocumentationPage.java @@ -0,0 +1,50 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.page; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.DocumentationPageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.static_member.DocumentedStaticMembers; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member.DocumentedVirtualMembers; + +import java.io.PrintWriter; +import java.util.Optional; + +public abstract class DocumentationPage { + + public final DocumentationPageInfo pageInfo; + protected final DocumentedVirtualMembers virtualMembers; + protected final DocumentedStaticMembers staticMembers; + + protected DocumentationPage(DocumentationPageInfo pageInfo, DocumentedVirtualMembers virtualMembers, DocumentedStaticMembers staticMembers) { + this.pageInfo = pageInfo; + this.virtualMembers = virtualMembers; + this.staticMembers = staticMembers; + } + + public void write(PrintWriter writer) { + writeTitle(writer); + writeDescription(writer); + writeOwnerModId(writer); + beforeWritingMembers(writer); + writeMembers(writer); + } + + protected abstract void writeTitle(PrintWriter writer); + + protected void writeDescription(PrintWriter writer) { + final Optional description = pageInfo.getClassComment().getOptionalDescription(); + + if(description.isPresent()) { + writer.println(description.get()); + writer.println(); + } + } + + protected abstract void writeOwnerModId(PrintWriter writer); + + protected void beforeWritingMembers(PrintWriter writer) { + } + + protected void writeMembers(PrintWriter writer) { + staticMembers.write(writer); + virtualMembers.write(writer); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/page/ExpansionPage.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/page/ExpansionPage.java new file mode 100644 index 000000000..5ddbf31f4 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/page/ExpansionPage.java @@ -0,0 +1,28 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.page; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.DocumentationPageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.static_member.DocumentedStaticMembers; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member.DocumentedVirtualMembers; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; + +import java.io.PrintWriter; + +public final class ExpansionPage extends DocumentationPage { + + private final AbstractTypeInfo expandedType; + + public ExpansionPage(AbstractTypeInfo expandedType, DocumentationPageInfo pageInfo, DocumentedVirtualMembers members, DocumentedStaticMembers staticMembers) { + super(pageInfo, members, staticMembers); + this.expandedType = expandedType; + } + + @Override + protected void writeTitle(PrintWriter writer) { + writer.printf("# Expansion for %s%n%n", expandedType.getSimpleMarkdown()); + } + + @Override + protected void writeOwnerModId(PrintWriter writer) { + writer.printf("This expansion was added by a mod with mod-id `%s`. So you need to have this mod installed if you want to use this feature.%n%n", pageInfo.declaringModId); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/page/TypePage.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/page/TypePage.java new file mode 100644 index 000000000..ccd0110db --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/page/TypePage.java @@ -0,0 +1,101 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.page; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.TypePageInfo; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.header.DocumentedGenericParameter; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.static_member.DocumentedStaticMembers; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.member.virtual_member.DocumentedVirtualMembers; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.type.AbstractTypeInfo; + +import javax.annotation.Nullable; +import java.io.PrintWriter; +import java.util.List; +import java.util.stream.Collectors; + +public final class TypePage extends DocumentationPage { + + private final TypePageInfo pageInfo; + + @Nullable + private final AbstractTypeInfo superType; + private final List implementedTypes; + private final List genericParameters; + + public TypePage(TypePageInfo pageInfo, DocumentedVirtualMembers members, @Nullable AbstractTypeInfo superType, List implementedTypes, DocumentedStaticMembers staticMembers, List genericParameters) { + super(pageInfo, members, staticMembers); + this.pageInfo = pageInfo; + this.superType = superType; + this.implementedTypes = implementedTypes; + this.genericParameters = genericParameters; + } + + @Override + protected void writeTitle(PrintWriter writer) { + if(genericParameters.isEmpty()) { + writer.printf("# %s%n%n", getSimpleName()); + } else { + final String genericParameters = this.genericParameters.stream() + .map(DocumentedGenericParameter::formatForSignatureExample) + .collect(Collectors.joining(", ")); + writer.printf("# %s<%s>%n%n", getSimpleName(), genericParameters); + } + } + + @Override + protected void writeDescription(PrintWriter writer) { + super.writeDescription(writer); + } + + @Override + protected void writeOwnerModId(PrintWriter writer) { + writer.printf("This class was added by a mod with mod-id `%s`. So you need to have this mod installed if you want to use this feature.%n%n", pageInfo.declaringModId); + } + + @Override + protected void beforeWritingMembers(PrintWriter writer) { + super.beforeWritingMembers(writer); + writeImport(writer); + writeSuperClass(writer); + writeImplementedInterfaces(writer); + } + + private void writeImport(PrintWriter writer) { + writer.printf("## Importing the class%n%n"); + writer.println("It might be required for you to import the package if you encounter any issues (like casting an Array), so better be safe than sorry and add the import at the very top of the file."); + writer.println("```zenscript"); + writer.printf("import %s;%n", pageInfo.zenCodeName.getZenCodeName()); + writer.println("```"); + writer.println(); + writer.println(); + } + + private void writeSuperClass(PrintWriter writer) { + if(superType == null) { + return; + } + + writer.printf("## Extending %s%n%n", superType.getSimpleMarkdown()); + final String simpleName = getSimpleName(); + final String superTypeMarkDown = superType.getClickableMarkdown(); + + final String format = "%1$s extends %2$s. That means all methods available in %2$s are also available in %1$s%n%n"; + writer.printf(format, simpleName, superTypeMarkDown); + } + + private void writeImplementedInterfaces(PrintWriter writer) { + if(implementedTypes.isEmpty()) { + return; + } + + writer.println("## Implemented Interfaces"); + final String format = "%1$s implements the following interfaces. That means all methods defined in these interfaces are also available in %1$s%n%n"; + writer.printf(format, getSimpleName()); + + for(AbstractTypeInfo implementedType : implementedTypes) { + writer.printf("- %s%n", implementedType.getClickableMarkdown()); + } + } + + private String getSimpleName() { + return pageInfo.getSimpleName(); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/type/AbstractTypeInfo.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/type/AbstractTypeInfo.java new file mode 100644 index 000000000..5482ecc96 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/type/AbstractTypeInfo.java @@ -0,0 +1,23 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.type; + +import javax.annotation.Nonnull; + +public abstract class AbstractTypeInfo implements Comparable { + + public abstract String getDisplayName(); + + public abstract String getClickableMarkdown(); + + public String getSimpleMarkdown() { + return getDisplayName(); + } + + public int compareTo(@Nonnull AbstractTypeInfo other) { + return this.getDisplayName().compareToIgnoreCase(other.getDisplayName()); + } + + @Override + public String toString() { + return getDisplayName(); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/type/ArrayTypeInfo.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/type/ArrayTypeInfo.java new file mode 100644 index 000000000..054097477 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/type/ArrayTypeInfo.java @@ -0,0 +1,25 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.type; + +public class ArrayTypeInfo extends AbstractTypeInfo { + + private final AbstractTypeInfo base; + + public ArrayTypeInfo(AbstractTypeInfo base) { + this.base = base; + } + + @Override + public String getDisplayName() { + return base.getDisplayName() + "[]"; + } + + @Override + public String getClickableMarkdown() { + return base.getClickableMarkdown() + "[]"; + } + + @Override + public String getSimpleMarkdown() { + return base.getSimpleMarkdown() + "[]"; + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/type/ExistingTypeInfo.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/type/ExistingTypeInfo.java new file mode 100644 index 000000000..c884d83b0 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/type/ExistingTypeInfo.java @@ -0,0 +1,20 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.type; + +public class ExistingTypeInfo extends AbstractTypeInfo{ + + private final String qualifiedName; + + public ExistingTypeInfo(String qualifiedName) { + this.qualifiedName = qualifiedName; + } + + @Override + public String getDisplayName() { + return qualifiedName; + } + + @Override + public String getClickableMarkdown() { + return getDisplayName(); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/type/GenericTypeInfo.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/type/GenericTypeInfo.java new file mode 100644 index 000000000..e724c5c02 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/type/GenericTypeInfo.java @@ -0,0 +1,47 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.type; + +import java.util.List; +import java.util.stream.Collectors; + +public class GenericTypeInfo extends AbstractTypeInfo { + + private final AbstractTypeInfo baseClass; + private final List typeArguments; + + public GenericTypeInfo(AbstractTypeInfo baseClass, List typeArguments) { + this.baseClass = baseClass; + this.typeArguments = typeArguments; + } + + @Override + public String getSimpleMarkdown() { + final String arguments = typeArguments.stream() + .map(AbstractTypeInfo::getDisplayName) + .collect(Collectors.joining(",", "<", ">")); + return baseClass.getDisplayName() + arguments; + } + + @Override + public String getDisplayName() { + final String arguments = typeArguments.stream() + .map(AbstractTypeInfo::getDisplayName) + .collect(Collectors.joining(",", "<", ">")); + return baseClass.getDisplayName() + arguments; + } + + @Override + public String getClickableMarkdown() { + final String arguments = typeArguments.stream() + .map(AbstractTypeInfo::getClickableMarkdown) + .collect(Collectors.joining(",", "<", ">")); + return baseClass.getClickableMarkdown() + arguments; + } + + public AbstractTypeInfo getBaseClass() { + return baseClass; + } + + public List getTypeArguments() { + return typeArguments; + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/type/MapTypeInfo.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/type/MapTypeInfo.java new file mode 100644 index 000000000..354c38230 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/type/MapTypeInfo.java @@ -0,0 +1,27 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.type; + +public class MapTypeInfo extends AbstractTypeInfo { + + private final AbstractTypeInfo keyType; + private final AbstractTypeInfo valueType; + + public MapTypeInfo(AbstractTypeInfo keyType, AbstractTypeInfo valueType) { + this.keyType = keyType; + this.valueType = valueType; + } + + @Override + public String getDisplayName() { + return String.format("%s[%s]", valueType.getDisplayName(), keyType.getDisplayName()); + } + + @Override + public String getSimpleMarkdown() { + return String.format("%s[%s]", valueType.getSimpleMarkdown(), keyType.getSimpleMarkdown()); + } + + @Override + public String getClickableMarkdown() { + return String.format("%s[%s]", valueType.getClickableMarkdown(), keyType.getClickableMarkdown()); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/type/PrimitiveTypeInfo.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/type/PrimitiveTypeInfo.java new file mode 100644 index 000000000..b7b6f1911 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/type/PrimitiveTypeInfo.java @@ -0,0 +1,20 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.type; + +public class PrimitiveTypeInfo extends AbstractTypeInfo { + + private final String name; + + public PrimitiveTypeInfo(String name) { + this.name = name; + } + + @Override + public String getDisplayName() { + return name; + } + + @Override + public String getClickableMarkdown() { + return getDisplayName(); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/type/TypePageTypeInfo.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/type/TypePageTypeInfo.java new file mode 100644 index 000000000..4dcb74488 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/type/TypePageTypeInfo.java @@ -0,0 +1,27 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.type; + +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.TypeName; +import com.blamejared.crafttweaker_annotation_processors.processors.document.page.info.TypePageInfo; + +public class TypePageTypeInfo extends AbstractTypeInfo { + + private final TypePageInfo pageInfo; + + public TypePageTypeInfo(TypePageInfo pageInfo) { + this.pageInfo = pageInfo; + } + + @Override + public String getDisplayName() { + return pageInfo.zenCodeName.getSimpleName(); + } + + @Override + public String getClickableMarkdown() { + return String.format("[%s](/%s)", pageInfo.getSimpleName(), pageInfo.getOutputPath()); + } + + public TypeName getZenCodeName() { + return pageInfo.zenCodeName; + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/type/TypeParameterTypeInfo.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/type/TypeParameterTypeInfo.java new file mode 100644 index 000000000..a21a1b85d --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/page/type/TypeParameterTypeInfo.java @@ -0,0 +1,20 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.document.page.type; + +public class TypeParameterTypeInfo extends AbstractTypeInfo { + + private final String typeParameterName; + + public TypeParameterTypeInfo(String typeParameterName) { + this.typeParameterName = typeParameterName; + } + + @Override + public String getDisplayName() { + return typeParameterName; + } + + @Override + public String getClickableMarkdown() { + return getDisplayName(); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/DocumentedScriptingExample.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/DocumentedScriptingExample.java deleted file mode 100644 index 42b16b045..000000000 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/DocumentedScriptingExample.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.blamejared.crafttweaker_annotation_processors.processors.document.shared; - -import java.util.ArrayList; -import java.util.List; - -public class DocumentedScriptingExample { - private final List content; - - public DocumentedScriptingExample() { - this(new ArrayList<>()); - } - - public DocumentedScriptingExample(List content) { - this.content = content; - } - - public static DocumentedScriptingExample fromFile(String fileName) { - //TODO - return new DocumentedScriptingExample(); - } - - public List getContent() { - return content; - } -} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/Writable.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/Writable.java deleted file mode 100644 index 6b1929fce..000000000 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/Writable.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.blamejared.crafttweaker_annotation_processors.processors.document.shared; - -import java.io.PrintWriter; - -public interface Writable { - void write(PrintWriter writer); -} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/members/DocumentedCaster.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/members/DocumentedCaster.java deleted file mode 100644 index c8d16acaf..000000000 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/members/DocumentedCaster.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.blamejared.crafttweaker_annotation_processors.processors.document.shared.members; - -import com.blamejared.crafttweaker_annotation_processors.processors.document.shared.types.DocumentedType; -import org.openzen.zencode.java.ZenCodeType; - -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.tools.Diagnostic; -import java.io.PrintWriter; -import java.util.Collection; -import java.util.Comparator; - -public class DocumentedCaster { - - public static Comparator byZSName = Comparator.comparing(DocumentedCaster::getResultType, DocumentedType.byZSName); - - private final DocumentedType resultType; - private final boolean implicit; - - public DocumentedCaster(DocumentedType resultType, boolean implicit) { - this.resultType = resultType; - this.implicit = implicit; - } - - public static DocumentedCaster fromMethod(ExecutableElement element, ProcessingEnvironment environment, boolean isExpansion) { - if (element.getKind() != ElementKind.METHOD) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Internal error: Expected this to be a method!", element); - return null; - } - - final ZenCodeType.Caster caster = element.getAnnotation(ZenCodeType.Caster.class); - if (caster == null) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Internal error: Expected this to have a Caster annotation!", element); - return null; - } - - if (element.getParameters().size() != (isExpansion ? 1 : 0)) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Caster methods may not have any parameters (or exactly one when an expansion)!", element); - return null; - } - - if (!element.getModifiers().contains(Modifier.PUBLIC)) { - environment.getMessager().printMessage(Diagnostic.Kind.ERROR, "Caster methods need to be public!", element); - return null; - } - - if (isExpansion != element.getModifiers().contains(Modifier.STATIC)) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Caster methods need to be nonstatic if not in an expansion and static when in an expansion!", element); - return null; - } - - return new DocumentedCaster(DocumentedType.fromTypeMirror(element.getReturnType(), environment, false), caster.implicit()); - } - - public static void printCasters(Collection casters, PrintWriter writer) { - if (casters.isEmpty()) { - return; - } - - writer.println("## Casters"); - writer.println(); - writer.println("| Result type | Is Implicit |"); - writer.println("|-------------|-------------|"); - for (DocumentedCaster caster : casters) { - caster.writeTable(writer); - } - - writer.println(); - } - - public DocumentedType getResultType() { - return resultType; - } - - private void writeTable(PrintWriter writer) { - writer.printf("| %s | %s |%n", resultType.getClickableMarkdown(), implicit); - } -} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/members/DocumentedMethod.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/members/DocumentedMethod.java deleted file mode 100644 index f99d54b94..000000000 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/members/DocumentedMethod.java +++ /dev/null @@ -1,165 +0,0 @@ -package com.blamejared.crafttweaker_annotation_processors.processors.document.shared.members; - -import com.blamejared.crafttweaker_annotation_processors.processors.*; -import com.blamejared.crafttweaker_annotation_processors.processors.document.*; -import com.blamejared.crafttweaker_annotation_processors.processors.document.shared.*; -import com.blamejared.crafttweaker_annotation_processors.processors.document.shared.types.*; -import com.blamejared.crafttweaker_annotation_processors.processors.document.shared.util.*; -import com.blamejared.crafttweaker_annotation_processors.processors.validation.*; -import org.openzen.zencode.java.*; - -import javax.annotation.processing.*; -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.tools.*; -import java.io.*; -import java.util.*; - -public class DocumentedMethod implements Writable { - - private static final String bracketHandlerAnnotation = "com.blamejared.crafttweaker.api.annotations.BracketResolver"; - - private final String name; - private final List parameterList; - private final CrafttweakerDocumentationPage containingPage; - private final String callee; //full class name if static, else my[Type] or content of docParam this - private final String docComment; - private final DocumentedType returnType; - private final String bracketHandlerName; - private final List typeParameters; - - public DocumentedMethod(CrafttweakerDocumentationPage containingPage, String name, List parameterList, List documentedTypeParameters, String callee, String docComment, DocumentedType returnType, String bracketHandlerName) { - this.containingPage = containingPage; - this.name = name; - this.parameterList = parameterList; - this.callee = callee; - this.docComment = docComment; - this.returnType = returnType; - this.bracketHandlerName = bracketHandlerName; - typeParameters = documentedTypeParameters; - } - - public DocumentedType getReturnType() { - return returnType; - } - - public static DocumentedMethod convertMethod(CrafttweakerDocumentationPage containingPage, ExecutableElement method, ProcessingEnvironment environment, boolean isExpansion) { - final ZenCodeType.Method methodAnnotation = method.getAnnotation(ZenCodeType.Method.class); - if(methodAnnotation == null) { - //Nani? - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Internal error: method has not Method Annotation", method); - return null; - } - - if(!method.getModifiers().contains(Modifier.PUBLIC)) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Methods need to be public!", method); - return null; - } - - final String name = methodAnnotation.value().isEmpty() ? method.getSimpleName() - .toString() : methodAnnotation.value(); - ZenCodeKeywordUtil.checkName(name, method, environment); - - final List parameterList = DocumentedParameter.getMethodParameters(method, environment, isExpansion); - final List documentedTypeParameters = DocumentedTypeParameter.getMethodTypeParameters(method, environment, isExpansion); - final boolean isStatic = method.getModifiers().contains(Modifier.STATIC); - if(isExpansion && !isStatic) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Expansion methods must be static!", method); - } - - String callee = null; - if(!isExpansion && isStatic) { - callee = containingPage.getZSName(); - } else if(isExpansion) { - final String docParam_this = CommentUtils.joinDocAnnotation(method, "docParam " + method - .getParameters() - .get(0) - .getSimpleName(), environment).trim(); - if(!docParam_this.isEmpty()) { - callee = docParam_this; - } - } - if(callee == null) { - final String docParam_this = CommentUtils.joinDocAnnotation(method, "docParam this", environment) - .trim(); - if(!docParam_this.isEmpty()) { - callee = docParam_this; - } - } - if(callee == null) { - callee = containingPage.getDocParamThis(); - } - - final DocumentedType returnType = method.getReturnType() - .getKind() == TypeKind.VOID ? null : DocumentedType.fromTypeMirror(method.getReturnType(), environment, false); - - final AnnotationMirror mirror = AnnotationMirrorUtil.getMirror(method, bracketHandlerAnnotation); - final String bracketHandlerName = mirror == null ? null : AnnotationMirrorUtil.getAnnotationValue(mirror, "value"); - - return new DocumentedMethod(containingPage, name, parameterList, documentedTypeParameters, callee, CommentUtils.formatDocCommentForDisplay(method, environment), returnType, bracketHandlerName); - - } - - public String getName() { - return name; - } - - public DocumentedMethod withCallee(String c) { - if(c != null) { - return new DocumentedMethod(containingPage, name, parameterList, typeParameters, c, docComment, returnType, bracketHandlerName); - } - return this; - } - - @Override - public void write(PrintWriter writer) { - writer.println(); - - if(docComment != null) { - writer.println(docComment); - writer.println(); - } - if(returnType != null) { - writer.println("Return type: " + returnType.getClickableMarkdown()); - writer.println(); - } - writer.println("```zenscript"); - if(bracketHandlerName != null) { - final DocumentedParameter documentedParameter = parameterList.get(0); - final String[] examples = documentedParameter.getExamples(); - if(examples.length == 0) { - writer.printf("<%s:%s>%n", bracketHandlerName, documentedParameter.getName()); - } else { - for(String example : examples) { - writer.printf("<%s:%s>%n", bracketHandlerName, example.replaceAll("\"", "")); - } - writer.println(); - } - } - - DocumentedParameter.printAllCalls(callee + "." + name, parameterList, typeParameters, writer); - writer.println("```"); - writer.println(); - - if(!typeParameters.isEmpty()){ - DocumentedTypeParameter.printTable(typeParameters, writer); - writer.println(); - } - - if(!parameterList.isEmpty()) { - DocumentedParameter.printTable(parameterList, writer); - writer.println(); - } - } - - public CrafttweakerDocumentationPage getContainingPage() { - return containingPage; - } - - public List getParameterList() { - return parameterList; - } -} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/members/DocumentedMethodGroup.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/members/DocumentedMethodGroup.java deleted file mode 100644 index 9fcc7ca02..000000000 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/members/DocumentedMethodGroup.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.blamejared.crafttweaker_annotation_processors.processors.document.shared.members; - -import com.blamejared.crafttweaker_annotation_processors.processors.document.CrafttweakerDocumentationPage; -import com.blamejared.crafttweaker_annotation_processors.processors.document.shared.Writable; - -import java.io.PrintWriter; -import java.util.*; -import java.util.stream.*; - -/** - * Groups one or more methods with the same name. - * Can contain multiple entries when a method name has been overloaded. - */ -public class DocumentedMethodGroup implements Writable { - private final String name; - private final Set methods; - private final CrafttweakerDocumentationPage containingPage; - - public DocumentedMethodGroup(String name, CrafttweakerDocumentationPage containingPage) { - this.name = name; - this.containingPage = containingPage; - this.methods = new TreeSet<>(Comparator. comparingInt(m -> m.getParameterList() - .size()).thenComparing(m -> m.getParameterList() - .stream() - .map(p -> p.getType().getZSName()) - .collect(Collectors.joining()))); - } - - public Set getMethods() { - return methods; - } - - public void add(DocumentedMethod method) { - if (!Objects.equals(this.containingPage, method.getContainingPage())) { - this.methods.add(method.withCallee(this.containingPage.getDocParamThis())); - } else { - this.methods.add(method); - } - } - - public void addAll(Collection methods) { - for (DocumentedMethod method : methods) { - add(method); - } - } - - @Override - public void write(PrintWriter writer) { - writer.printf("### %s%n", name); - for (DocumentedMethod method : methods) { - method.write(writer); - } - } - - public DocumentedMethodGroup merge(DocumentedMethodGroup other) { - - final DocumentedMethodGroup documentedMethodGroup; - if (Objects.equals(this.name, other.name)) { - documentedMethodGroup = new DocumentedMethodGroup(this.name, containingPage); - } else if (this.name == null || other.name == null) { - documentedMethodGroup = new DocumentedMethodGroup(this.name == null ? other.name : this.name, containingPage); - } else { - throw new IllegalStateException("Method groups have different names: " + this.name + " and " + other.name); - } - - documentedMethodGroup.addAll(this.methods); - documentedMethodGroup.addAll(other.methods); - return documentedMethodGroup; - } -} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/members/DocumentedOperator.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/members/DocumentedOperator.java deleted file mode 100644 index 9a2b886e3..000000000 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/members/DocumentedOperator.java +++ /dev/null @@ -1,166 +0,0 @@ -package com.blamejared.crafttweaker_annotation_processors.processors.document.shared.members; - -import com.blamejared.crafttweaker_annotation_processors.processors.document.CrafttweakerDocumentationPage; -import com.blamejared.crafttweaker_annotation_processors.processors.document.shared.Writable; -import com.blamejared.crafttweaker_annotation_processors.processors.document.shared.util.CommentUtils; -import com.blamejared.crafttweaker_annotation_processors.processors.document.shared.util.FormattingUtils; -import org.openzen.zencode.java.ZenCodeType; - -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.VariableElement; -import javax.tools.Diagnostic; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; - -public class DocumentedOperator implements Writable { - public static Comparator compareByOp = Comparator.comparing(DocumentedOperator::getOperator); - private final ZenCodeType.OperatorType operator; - private final List parameterList; - private final String docComment; - private final String callee; - - private DocumentedOperator(ZenCodeType.OperatorType operator, List parameterList, String docComment, String callee) { - this.operator = operator; - this.parameterList = parameterList; - this.docComment = docComment; - this.callee = callee; - } - - public static DocumentedOperator fromMethod(CrafttweakerDocumentationPage containingPage, ExecutableElement method, ProcessingEnvironment environment, boolean isExpansion) { - if (method.getKind() != ElementKind.METHOD) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Internal error: Expected this to be a method!", method); - return null; - } - - final ZenCodeType.Operator operator = method.getAnnotation(ZenCodeType.Operator.class); - if (operator == null) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Internal error: Expected this method to have an Operator annotation1", method); - return null; - } - - if (!method.getModifiers().contains(Modifier.PUBLIC)) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Operator methods need to be public!", method); - return null; - } - - - if (isExpansion != method.getModifiers().contains(Modifier.STATIC)) { - if (isExpansion) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Expansion Operator methods must be static!", method); - } else { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Operator methods must not be static!", method); - } - return null; - } - - //-1 because 'this' is the 1st operand - final int requiredOperands = FormattingUtils.getOperandCountFor(operator.value()) - (isExpansion ? 0 : 1); - final List methodParameters = method.getParameters(); - if (requiredOperands != methodParameters.size()) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, String.format("Operator %s requires %d parameters in the method, received %d.", operator - .value(), requiredOperands, methodParameters.size())); - } - - final List parameters; - String callee = null; - { - final String s = CommentUtils.joinDocAnnotation(method, "@docComment this", environment).trim(); - if (!s.isEmpty()) { - callee = s; - } - } - - - if (isExpansion) { - parameters = new ArrayList<>(methodParameters.size() - 1); - for (VariableElement parameter : methodParameters.subList(1, methodParameters.size())) { - parameters.add(DocumentedParameter.fromElement(parameter, environment)); - } - - if (callee == null) { - final String docParam_this = CommentUtils.joinDocAnnotation(method, "docParam " + methodParameters.get(0) - .getSimpleName(), environment).trim(); - if (!docParam_this.isEmpty()) { - callee = docParam_this; - } - } - } else { - parameters = new ArrayList<>(methodParameters.size()); - for (VariableElement parameter : methodParameters) { - parameters.add(DocumentedParameter.fromElement(parameter, environment)); - } - } - - if (callee == null) { - callee = containingPage.getDocParamThis(); - } - - - return new DocumentedOperator( - operator.value(), - parameters, - CommentUtils.formatDocCommentForDisplay(method, environment), - callee - ); - } - - public ZenCodeType.OperatorType getOperator() { - return operator; - } - - @Override - public void write(PrintWriter writer) { - writer.printf("### %s%n", this.operator); - writer.println(); - if (docComment != null) { - writer.println(docComment); - writer.println(); - } - - final int operandCount = FormattingUtils.getOperandCountFor(operator); - final String operatorFormat = FormattingUtils.getOperatorFormat(operator) + "%n"; - - writer.println("```zenscript"); - { - final List generalDesc = new ArrayList<>(operandCount); - generalDesc.add(callee); - for (DocumentedParameter documentedParameter : parameterList) { - generalDesc.add(documentedParameter.getZSDescription()); - } - writer.printf(operatorFormat, generalDesc.toArray()); - } - { - final int i = parameterList.stream() - .mapToInt(s -> s.getExamples().length) - .reduce((a, b) -> a * b) - .orElse(0); - if (i > 0) { - final List exampleDesc = new ArrayList<>(operandCount); - exampleDesc.add(callee); - for (DocumentedParameter documentedParameter : parameterList) { - exampleDesc.add(documentedParameter.getExamples()[0]); - } - writer.printf(operatorFormat, exampleDesc.toArray()); - } - } - - writer.println("```"); - writer.println(); - writer.println("| Parameter | Type | Description |"); - writer.println("|-----------|------|-------------|"); - for (DocumentedParameter documentedParameter : parameterList) { - documentedParameter.writeTable(writer, false); - } - } -} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/members/DocumentedParameter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/members/DocumentedParameter.java deleted file mode 100644 index 0102ab8f0..000000000 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/members/DocumentedParameter.java +++ /dev/null @@ -1,175 +0,0 @@ -package com.blamejared.crafttweaker_annotation_processors.processors.document.shared.members; - -import com.blamejared.crafttweaker_annotation_processors.processors.document.shared.types.DocumentedType; -import com.blamejared.crafttweaker_annotation_processors.processors.document.shared.util.CommentUtils; - -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.VariableElement; -import javax.tools.Diagnostic; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -/** - * Anything that is gettable or assignable using {@code val = X.name} or {@code X.name = val} - */ -public class DocumentedParameter { - private final String name; - private final DocumentedType type; - private final boolean optional; - private final String defaultValue; - private final String[] examples; - private final String description; - - private DocumentedParameter(String name, DocumentedType type, boolean optional, String defaultValue, String[] examples, String description) { - this.name = name; - this.type = type; - this.optional = optional; - this.defaultValue = defaultValue; - this.examples = examples; - this.description = description; - } - - public static DocumentedParameter fromElement(VariableElement element, ProcessingEnvironment environment) { - if (element.getKind() != ElementKind.PARAMETER) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Internal Error: Expected this to be a parameter!", element); - return null; - } - - if(element.asType().toString().startsWith("java.lang.Class")) { - return null; - } - - final DocumentedType type = DocumentedType.fromElement(element, environment, false); - final String aDefault = getDefault(element); - final boolean optional = aDefault != null; - final String name = element.getSimpleName().toString(); - - - final String methodDocComment = environment.getElementUtils() - .getDocComment(element.getEnclosingElement()); - final String[] examples = CommentUtils.findAllAnnotation(methodDocComment, "@docParam " + name); - - final String description = CommentUtils.joinDocAnnotation(element.getEnclosingElement(), "@param " + name, environment) - .trim(); - - - return new DocumentedParameter(name, type, optional, aDefault, examples, description.isEmpty() ? null : description); - } - - public static List getMethodParameters(ExecutableElement method, ProcessingEnvironment environment, boolean isExpansion) { - final List parameterList = new ArrayList<>(); - boolean optionalsHit = false; - final List parameters = method.getParameters(); - for (VariableElement parameter : isExpansion ? parameters.subList(1, parameters.size()) : parameters) { - final DocumentedParameter e = DocumentedParameter.fromElement(parameter, environment); - if (e == null) { - continue; - } - - if (optionalsHit && !e.isOptional()) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Non-Optional parameter after an optional one!", parameter); - } - optionalsHit = optionalsHit || e.isOptional(); - parameterList.add(e); - } - return parameterList; - } - - - private static String getDefault(VariableElement element) { - for (AnnotationMirror annotationMirror : element.getAnnotationMirrors()) { - final String typeName = annotationMirror.getAnnotationType().toString(); - if (typeName.matches("org\\.openzen\\.zencode\\.java\\.ZenCodeType\\.Optional(Double|String|Int|Float|Long)?")) { - return annotationMirror.getElementValues() - .values() - .stream() - .map(av -> av.getValue().toString()) - .findAny() - //Not the best way since it does not distinct between floats and int numbers but whatever - .orElse(typeName.endsWith("Optional") ? "null" : "0"); - } - } - return null; - } - - public static void printAllCalls(String callee, List parameterList, List typeParameterList, PrintWriter writer) { - - final String collect = parameterList.stream() - .map(DocumentedParameter::getZSDescription) - .collect(Collectors.joining(", ")); - writer.printf("%s%s(%s);%n", callee, DocumentedTypeParameter.formatForDescriptionCall(typeParameterList), collect); - - for(String exampleTypeArgument : DocumentedTypeParameter.getExampleTypeArguments(typeParameterList)) { - final int reduce = parameterList.stream() - .mapToInt(d -> d.getExamples().length) - .reduce((left, right) -> left * right).orElse(0); - if (reduce > 0 || !typeParameterList.isEmpty()) { - List ss = new ArrayList<>(); - List lastCall = new ArrayList<>(); - - for (DocumentedParameter documentedParameter : parameterList) { - if (documentedParameter.isOptional()) { - ss.add(String.join(", ", lastCall)); - } - lastCall.add(documentedParameter.getExamples()[0]); - } - ss.add(String.join(", ", lastCall)); - - for (String s : ss) { - writer.printf("%s%s(%s);%n", callee, exampleTypeArgument, s); - } - } - } - } - - public static void printTable(List parameterList, PrintWriter writer) { - final boolean containsOptionals = parameterList.stream().anyMatch(DocumentedParameter::isOptional); - if (containsOptionals) { - writer.println("| Parameter | Type | Description | IsOptional | Default Value |"); - writer.println("|-----------|------|-------------|------------|---------------|"); - } else { - writer.println("| Parameter | Type | Description |"); - writer.println("|-----------|------|-------------|"); - } - for (DocumentedParameter documentedParameter : parameterList) { - documentedParameter.writeTable(writer, containsOptionals); - } - writer.println(); - } - - public String getName() { - return name; - } - - public DocumentedType getType() { - return type; - } - - public boolean isOptional() { - return optional; - } - - public String[] getExamples() { - return examples; - } - - public String getZSDescription() { - return String.format("%s as %s", getName(), getType().getZSName()); - } - - void writeTable(PrintWriter writer, boolean containsOptionals) { - final String desc = description == null ? "No description provided" : description; - if (containsOptionals) { - writer.printf("| %s | %s | %s | %s | `%s` |%n", getName(), type.getClickableMarkdown(), desc, isOptional(), defaultValue); - } else { - writer.printf("| %s | %s | %s |%n", getName(), type.getClickableMarkdown(), desc); - } - } -} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/members/DocumentedProperty.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/members/DocumentedProperty.java deleted file mode 100644 index cdbf18fca..000000000 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/members/DocumentedProperty.java +++ /dev/null @@ -1,212 +0,0 @@ -package com.blamejared.crafttweaker_annotation_processors.processors.document.shared.members; - -import com.blamejared.crafttweaker_annotation_processors.processors.document.*; -import com.blamejared.crafttweaker_annotation_processors.processors.document.documented_class.*; -import com.blamejared.crafttweaker_annotation_processors.processors.document.shared.types.*; -import com.blamejared.crafttweaker_annotation_processors.processors.validation.*; -import org.openzen.zencode.java.*; - -import javax.annotation.processing.*; -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.tools.*; -import java.io.*; -import java.util.*; - -public class DocumentedProperty { - - private final String name; - private final boolean hasGetter, hasSetter; - private final DocumentedType type; - private final CrafttweakerDocumentationPage containingPage; - - private DocumentedProperty(CrafttweakerDocumentationPage containingPage, String name, boolean hasGetter, boolean hasSetter, DocumentedType type) { - this.containingPage = containingPage; - this.name = name; - this.hasGetter = hasGetter; - this.hasSetter = hasSetter; - this.type = type; - } - - private static boolean cannotBeMerged(DocumentedProperty propertyA, DocumentedProperty propertyB) { - if(propertyA.containingPage == null) { - return false; - } - - if(!(propertyA.containingPage instanceof DocumentedClass)) { - return false; - } - - if(!(propertyB.containingPage instanceof DocumentedClass)) { - return false; - } - - DocumentedClass containingPageA = (DocumentedClass) propertyA.containingPage; - DocumentedClass containingPageB = (DocumentedClass) propertyB.containingPage; - if(containingPageA.extendsOrImplements(containingPageB)) { - return false; - } - return !containingPageB.extendsOrImplements(containingPageA); - } - - public static DocumentedProperty merge(DocumentedProperty propertyA, DocumentedProperty propertyB, ProcessingEnvironment environment) { - if(propertyB.name != null && propertyA.name != null && !propertyB.name.equals(propertyA.name)) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Internal error: Could not merge properties " + propertyA.name + " and " + propertyB.name); - } - - if(!Objects.equals(propertyA.containingPage, propertyB.containingPage)) { - if(cannotBeMerged(propertyA, propertyB)) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Internal error: Could not merge properties from classes " + propertyA.containingPage - .getZSName() + " and " + propertyB.containingPage.getZSName()); - } - } - - return new DocumentedProperty(propertyA.containingPage != null ? propertyA.containingPage : propertyB.containingPage, propertyA.name != null ? propertyA.name : propertyB.name, propertyA.hasGetter || propertyB.hasGetter, propertyA.hasSetter || propertyB.hasSetter, propertyA.type == null ? propertyB.type : propertyA.type); - - } - - public static DocumentedProperty fromField(DocumentedClass containingClass, Element field, ProcessingEnvironment environment) { - if(!field.getKind().isField()) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Internal error: Expected this to be a field!", field); - return null; - } - - final ZenCodeType.Field annotation = field.getAnnotation(ZenCodeType.Field.class); - final String name; - if(annotation != null && !annotation.value().isEmpty()) { - name = annotation.value(); - } else { - name = field.getSimpleName().toString(); - } - - ZenCodeKeywordUtil.checkName(name, field, environment); - if(!field.getModifiers().contains(Modifier.PUBLIC)) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "ZenFields need to be public!", field); - return null; - } - - final DocumentedType type = DocumentedType.fromTypeMirror(field.asType(), environment, false); - return new DocumentedProperty(containingClass, name, true, true, type); - } - - public static DocumentedProperty fromMethod(CrafttweakerDocumentationPage containingClass, Element method, ProcessingEnvironment environment, boolean isExpansion) { - if(method.getKind() != ElementKind.METHOD) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Internal error: Expected this to be a getter or setter method!", method); - return null; - } - - if(isExpansion != method.getModifiers().contains(Modifier.STATIC)) { - if(isExpansion) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Expansion Getters/Setters must be static!", method); - } else { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Getters/Setters must not be static!", method); - } - return null; - } - - final ZenCodeType.Getter getter = method.getAnnotation(ZenCodeType.Getter.class); - if(getter != null) { - return fromGetter(containingClass, (ExecutableElement) method, getter, environment, isExpansion); - } - - final ZenCodeType.Setter setter = method.getAnnotation(ZenCodeType.Setter.class); - if(setter != null) { - return fromSetter(containingClass, (ExecutableElement) method, setter, environment, isExpansion); - } - - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Internal error: Expected this to be either have a setter or getter annotation!", method); - return null; - } - - private static DocumentedProperty fromGetter(CrafttweakerDocumentationPage containingClass, ExecutableElement method, ZenCodeType.Getter annotation, ProcessingEnvironment environment, boolean isExpansion) { - final String name; - if(annotation != null && !annotation.value().isEmpty()) { - name = annotation.value(); - } else { - name = method.getSimpleName().toString(); - } - - ZenCodeKeywordUtil.checkName(name, method, environment); - if(!method.getModifiers().contains(Modifier.PUBLIC)) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Getter methods need to be public!", method); - return null; - } - - - if(method.getParameters().size() != (isExpansion ? 1 : 0)) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Getter methods need to have no parameters!", method); - } - - if(method.getReturnType().getKind() == TypeKind.VOID) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Getter methods may not return void!", method); - } - - DocumentedType type = DocumentedType.fromTypeMirror(method.getReturnType(), environment, false); - return new DocumentedProperty(containingClass, name, true, false, type); - } - - private static DocumentedProperty fromSetter(CrafttweakerDocumentationPage containingClass, ExecutableElement method, ZenCodeType.Setter annotation, ProcessingEnvironment environment, boolean isExpansion) { - final String name; - if(annotation != null && !annotation.value().isEmpty()) { - name = annotation.value(); - } else { - name = method.getSimpleName().toString(); - } - - ZenCodeKeywordUtil.checkName(name, method, environment); - if(!method.getModifiers().contains(Modifier.PUBLIC)) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Setter methods need to be public!", method); - return null; - } - - if(method.getParameters().size() != (isExpansion ? 2 : 1)) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Setter method needs to have exactly one parameter!", method); - } - - if(method.getReturnType().getKind() != TypeKind.VOID) { - environment.getMessager() - .printMessage(Diagnostic.Kind.ERROR, "Setter method need to return void!", method); - } - - DocumentedType type = DocumentedType.fromElement(method.getParameters() - .get(isExpansion ? 1 : 0), environment, false); - return new DocumentedProperty(containingClass, name, false, true, type); - } - - public static void printProperties(Collection properties, PrintWriter writer) { - if(properties.isEmpty()) { - return; - } - - writer.println("## Properties"); - writer.println(); - writer.println("| Name | Type | Has Getter | Has Setter |"); - writer.println("|------|------|------------|------------|"); - for(DocumentedProperty value : properties) { - value.writeTable(writer); - } - - writer.println(); - } - - public String getName() { - return name; - } - - private void writeTable(PrintWriter writer) { - writer.printf("| %s | %s | %s | %s |%n", name, type.getClickableMarkdown(), hasGetter, hasSetter); - } -} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/members/DocumentedTypeParameter.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/members/DocumentedTypeParameter.java deleted file mode 100644 index 04ca33c6d..000000000 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/members/DocumentedTypeParameter.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.blamejared.crafttweaker_annotation_processors.processors.document.shared.members; - -import com.blamejared.crafttweaker_annotation_processors.processors.document.shared.types.*; -import com.blamejared.crafttweaker_annotation_processors.processors.document.shared.util.*; -import com.sun.tools.classfile.*; - -import javax.annotation.processing.*; -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import java.io.*; -import java.util.*; -import java.util.stream.*; - -public class DocumentedTypeParameter { - - private final List bounds; - private final String name; - private final String[] examples; - - private DocumentedTypeParameter(List bounds, String name, String[] examples) { - this.bounds = bounds; - this.name = name; - this.examples = examples; - } - - public static List getMethodTypeParameters(ExecutableElement method, ProcessingEnvironment environment, boolean isExpansion) { - List typeParameters = method.getTypeParameters(); - if(isExpansion) { - final VariableElement variableElement = method.getParameters().get(0); - final TypeMirror typeMirror = variableElement.asType(); - if(typeMirror instanceof Type.ClassType) { - typeParameters = typeParameters.subList(((Type.ClassType) typeMirror).typeArgs.size(), typeParameters - .size()); - } - } - - final List result = new ArrayList<>(); - for(TypeParameterElement typeParameter : typeParameters) { - result.add(getTypeParameter(typeParameter, method, environment)); - } - return result; - } - - private static DocumentedTypeParameter getTypeParameter(TypeParameterElement typeParameter, ExecutableElement method, ProcessingEnvironment environment) { - final String name = typeParameter.getSimpleName().toString(); - final List documentedBounds = new ArrayList<>(); - final String[] examples = CommentUtils.findAllAnnotation(environment.getElementUtils() - .getDocComment(method), "@docParam " + name); - for(TypeMirror bound : typeParameter.getBounds()) { - documentedBounds.add(DocumentedType.fromTypeMirror(bound, environment, false)); - } - return new DocumentedTypeParameter(documentedBounds, name, examples); - } - - public static void printTable(List typeParameters, PrintWriter writer) { - writer.println("| ParameterName | Bounds |"); - writer.println("|---------------|--------|"); - for(DocumentedTypeParameter typeParameter : typeParameters) { - final String bounds = typeParameter.bounds.stream() - .map(DocumentedType::getClickableMarkdown) - .collect(Collectors.joining("
")); - writer.printf("| %s | %s |%n", typeParameter.name, bounds); - } - } - - public static String formatForDescriptionCall(List typeParameterList) { - if(typeParameterList.isEmpty()) { - return ""; - } - return typeParameterList.stream() - .map(d -> d.name) - .collect(Collectors.joining(", ", "<", ">")); - } - - public static String[] getExampleTypeArguments(List typeParameterList) { - if(typeParameterList.isEmpty()) { - return new String[]{""}; - } - final boolean anyWithoutExample = typeParameterList.stream().anyMatch(d -> d.examples.length == 0); - if(anyWithoutExample) { - return new String[]{""}; - } - final String example = typeParameterList.stream() - .map(d -> d.examples[0]) - .collect(Collectors.joining(", ", "<", ">")); - return new String[]{example}; - } -} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/types/DocumentedArrayType.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/types/DocumentedArrayType.java deleted file mode 100644 index bc405797d..000000000 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/types/DocumentedArrayType.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.blamejared.crafttweaker_annotation_processors.processors.document.shared.types; - -public class DocumentedArrayType extends DocumentedType { - private final DocumentedType base; - - public DocumentedArrayType(DocumentedType base) { - this.base = base; - } - - @Override - public String getZSName() { - return base.getZSName() + "[]"; - } - - @Override - public String getClickableMarkdown() { - return base.getClickableMarkdown() + "[]"; - } - - @Override - public String getZSShortName() { - return base.getZSShortName() + "Array"; - } - - @Override - public String getDocParamThis() { - return "[] as " + getZSName(); - } -} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/types/DocumentedClassType.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/types/DocumentedClassType.java deleted file mode 100644 index e6329c9e8..000000000 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/types/DocumentedClassType.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.blamejared.crafttweaker_annotation_processors.processors.document.shared.types; - -import com.blamejared.crafttweaker_annotation_processors.processors.document.documented_class.*; - -import java.util.*; - -public class DocumentedClassType extends DocumentedType { - - private final DocumentedClass documentedClass; - - public DocumentedClassType(DocumentedClass documentedClass) { - this.documentedClass = documentedClass; - } - - public DocumentedClass getDocumentedClass() { - return documentedClass; - } - - @Override - public String getZSName() { - return documentedClass.getZSName(); - } - - @Override - public String getClickableMarkdown() { - //TODO implement. - return String.format(Locale.ENGLISH, "[%s](/%s)", documentedClass.getZSName(), documentedClass - .getDocPath()); - } - - @Override - public String getClickableMarkdown(String member) { - final String anchor = member.toLowerCase(Locale.ENGLISH).split("[(]", 2)[0]; - return String.format(Locale.ENGLISH, "[%s#%s](/%s/#%s)", documentedClass.getZSName(), member, documentedClass - .getDocPath(), anchor); - } - - @Override - public String getZSShortName() { - return this.documentedClass.getZSShortName(); - } - - @Override - public String getDocParamThis() { - return documentedClass.getDocParamThis(); - } - -} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/types/DocumentedGenericType.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/types/DocumentedGenericType.java deleted file mode 100644 index 94391f5ab..000000000 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/types/DocumentedGenericType.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.blamejared.crafttweaker_annotation_processors.processors.document.shared.types; - -import java.util.List; -import java.util.stream.Collectors; - -public class DocumentedGenericType extends DocumentedType { - - private final DocumentedType baseType; - private final List genericTypes; - - public DocumentedGenericType(DocumentedType baseType, List genericTypes) { - this.baseType = baseType; - this.genericTypes = genericTypes; - } - - - @Override - public String getZSName() { - return genericTypes.stream() - .map(DocumentedType::getZSName) - .collect(Collectors.joining(", ", baseType.getZSName() + "<", ">")); - } - - @Override - public String getClickableMarkdown() { - return genericTypes.stream() - .map(DocumentedType::getClickableMarkdown) - .collect(Collectors.joining(", ", baseType.getClickableMarkdown() + "<", ">")); - } - - @Override - public String getZSShortName() { - return baseType.getZSShortName(); - } - - @Override - public String getDocParamThis() { - return "my" + baseType.getZSShortName(); - } -} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/types/DocumentedMapType.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/types/DocumentedMapType.java deleted file mode 100644 index 35e081353..000000000 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/types/DocumentedMapType.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.blamejared.crafttweaker_annotation_processors.processors.document.shared.types; - -public class DocumentedMapType extends DocumentedType { - private final DocumentedType keyType, valueType; - - public DocumentedMapType(DocumentedType keyType, DocumentedType valueType) { - this.keyType = keyType; - this.valueType = valueType; - } - - @Override - public String getZSName() { - return valueType.getZSName() + "[" + keyType.getZSName() + "]"; - } - - @Override - public String getClickableMarkdown() { - return valueType.getClickableMarkdown() + "[" + keyType.getClickableMarkdown() + "]"; - } - - @Override - public String getZSShortName() { - return keyType.getZSShortName() + valueType.getZSShortName() + "Map"; - } - - @Override - public String getDocParamThis() { - return "{} as " + getZSName(); - } -} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/types/DocumentedNativeType.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/types/DocumentedNativeType.java deleted file mode 100644 index e7302b197..000000000 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/types/DocumentedNativeType.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.blamejared.crafttweaker_annotation_processors.processors.document.shared.types; - -public class DocumentedNativeType extends DocumentedType { - public final String ZSName; - - public DocumentedNativeType(String zsName) { - ZSName = zsName; - } - - @Override - public String getZSName() { - return ZSName; - } - - @Override - public String getClickableMarkdown() { - //We don't interlink to native pages, do we? - return ZSName; - } - - @Override - public String getZSShortName() { - return ZSName; - } - - @Override - public String getDocParamThis() { - return "my" + ZSName; - } -} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/types/DocumentedPrimitiveType.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/types/DocumentedPrimitiveType.java deleted file mode 100644 index 38a5230df..000000000 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/types/DocumentedPrimitiveType.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.blamejared.crafttweaker_annotation_processors.processors.document.shared.types; - -import javax.lang.model.type.*; - -public class DocumentedPrimitiveType extends DocumentedType { - - private final TypeMirror typeMirror; - - public DocumentedPrimitiveType(TypeMirror typeMirror) { - super(); - this.typeMirror = typeMirror; - } - - @Override - public String getZSName() { - return typeMirror.toString().toLowerCase(); - } - - @Override - public String getClickableMarkdown() { - return getZSName(); - } - - @Override - public String getZSShortName() { - return getZSName(); - } - - @Override - public String getDocParamThis() { - switch(typeMirror.getKind()) { - case BOOLEAN: - return "false"; - case BYTE: - case SHORT: - case INT: - case LONG: - return "0 as " + getZSName(); - case CHAR: - return "'\\0' as char"; - case FLOAT: - return "0.0F"; - case DOUBLE: - return "0.0D"; - } - return "my" + getZSName(); - } -} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/types/DocumentedType.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/types/DocumentedType.java deleted file mode 100644 index 433f67159..000000000 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/types/DocumentedType.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.blamejared.crafttweaker_annotation_processors.processors.document.shared.types; - -import com.blamejared.crafttweaker_annotation_processors.processors.document.*; -import com.blamejared.crafttweaker_annotation_processors.processors.document.documented_class.*; - -import javax.annotation.processing.*; -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.tools.*; -import java.util.*; - -/** - * Any type that can be referenced. - */ -public abstract class DocumentedType { - - - public static final Comparator byZSName = Comparator.comparing(DocumentedType::getZSName); - - public static DocumentedType fromElement(Element element, ProcessingEnvironment environment, boolean forComment) { - if(element instanceof TypeElement) { - final DocumentedClass documentedClass = DocumentedClass.convertClass((TypeElement) element, environment, forComment); - if(documentedClass != null) - return new DocumentedClassType(documentedClass); - } - if(element == null) { - return null; - } - return fromTypeMirror(element.asType(), environment, forComment); - } - - public static DocumentedType fromTypeMirror(TypeMirror typeMirror, ProcessingEnvironment environment, boolean forComment) { - if(typeMirror.getKind().isPrimitive()) { - return new DocumentedPrimitiveType(typeMirror); - } - - if(typeMirror.getKind() == TypeKind.ARRAY) { - return new DocumentedArrayType(fromTypeMirror(((ArrayType) typeMirror).getComponentType(), environment, forComment)); - } - - - if(typeMirror instanceof DeclaredType) { - DeclaredType declaredType = (DeclaredType) typeMirror; - final List typeArguments = declaredType.getTypeArguments(); - if(!typeArguments.isEmpty()) { - final TypeMirror erasure = environment.getTypeUtils().erasure(typeMirror); - - if(erasure.toString().equals("java.util.Map")) { - final DocumentedType keyType = fromTypeMirror(typeArguments.get(0), environment, forComment); - final DocumentedType valueType = fromTypeMirror(typeArguments.get(1), environment, forComment); - return new DocumentedMapType(keyType, valueType); - } - - final DocumentedType base = fromTypeMirror(erasure, environment, forComment); - - final List arguments = new ArrayList<>(); - for(TypeMirror typeArgument : typeArguments) { - arguments.add(fromTypeMirror(typeArgument, environment, forComment)); - } - return new DocumentedGenericType(base, arguments); - } else { - final DocumentedClass documentedClass = DocumentedClass.convertClass(typeMirror, environment, forComment); - if(documentedClass != null) { - return new DocumentedClassType(documentedClass); - } - - if(typeMirror.toString().startsWith("java.util.") || typeMirror.toString() - .startsWith("java.lang.")) { - //java.util. and java.lang. both are 10 chars, otherwise I'd put them in different calls - return new DocumentedNativeType(typeMirror.toString().substring(10)); - } - } - } - - - boolean showWarning = true; - final Element element = environment.getTypeUtils().asElement(typeMirror); - - if(typeMirror instanceof TypeVariable) { - showWarning = false; - } else if(DocumentProcessorNew.tree != null) { - //getTree( returns null if it's not part of the compilation tree, e.g. part of a lib - showWarning = element == null || DocumentProcessorNew.tree.getTree(element) != null; - } - - - if(showWarning) { - environment.getMessager() - .printMessage(Diagnostic.Kind.WARNING, "Found a type without a Name Annotation: " + element, element); - } - return new DocumentedNativeType(typeMirror.toString()); - } - - - public abstract String getZSName(); - - public abstract String getClickableMarkdown(); - - public String getClickableMarkdown(String member) { - return getClickableMarkdown(); - } - - @Override - public String toString() { - return getZSName(); - } - - public abstract String getZSShortName(); - - public abstract String getDocParamThis(); -} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/util/CommentUtils.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/util/CommentUtils.java deleted file mode 100644 index e9c18dc99..000000000 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/util/CommentUtils.java +++ /dev/null @@ -1,172 +0,0 @@ -package com.blamejared.crafttweaker_annotation_processors.processors.document.shared.util; - -import com.blamejared.crafttweaker_annotation_processors.processors.document.*; -import com.blamejared.crafttweaker_annotation_processors.processors.document.shared.types.*; -import com.sun.source.tree.*; -import com.sun.source.util.*; - -import javax.annotation.processing.*; -import javax.lang.model.element.*; -import javax.tools.*; -import java.util.*; -import java.util.regex.*; -import java.util.stream.*; - -public class CommentUtils { - - private CommentUtils() { - } - - /** - * Puts all document annotations starting with the given string into one line. - * - * @param element The element in whose documentation string to search in - * @param annotation The Start of the annotation, e.g. {@code @docParam this} - * @param environment ProcessingEnvironment, used for type lookups and warning reports. - * @return String with all found docAnnotations in one line, newlines replaced with single spaces. - */ - public static String joinDocAnnotation(Element element, String annotation, ProcessingEnvironment environment) { - final String parentDoc = environment.getElementUtils().getDocComment(element); - - if(parentDoc == null) - return ""; - final StringBuilder sb = new StringBuilder(); - final Matcher matcher = Pattern.compile(annotation + " (?(?:\\{@link ([\\w. ]*)}|[^@{]*)*)") - .matcher(parentDoc); - while(matcher.find()) { - final String content = matcher.group("content"); - final String s = StringReplaceUtil.replaceWithMatcher(content, "\\{@link (?[\\w. ]*)}", matcher1 -> { - final String type = matcher1.group("type"); - return getMarkDownFor(type, environment, element); - }); - sb.append(s); - } - - return sb.toString().replaceAll("[\\n\\r]+", " ").trim(); - } - - /** - * Puts all document annotations starting with the given string into one line. - * - * @param parentDoc The documentation string to search in - * @param annotation The Start of the annotation, e.g. {@code @docParam this} - * @return String with all found docAnnotations in one line, newlines replaced with single spaces. - */ - public static String[] findAllAnnotation(String parentDoc, String annotation) { - if(parentDoc == null) { - return new String[0]; - } - - final List out = new ArrayList<>(); - final Matcher matcher = Pattern.compile(annotation + " (?[^@]*)") - .matcher(parentDoc); - while(matcher.find()) { - out.add(matcher.group("content").replaceAll("[\\n\\r]+", " ").trim()); - } - - return out.toArray(new String[0]); - } - - /** - * Changes a JavaDoc comment to match the md format - * - * @return The formatted Javadoc comment, or null - */ - public static String formatDocCommentForDisplay(Element element, ProcessingEnvironment environment) { - String parentDoc = environment.getElementUtils().getDocComment(element); - if(parentDoc == null) - return null; - - //Replace links to types with their MD equivalents - parentDoc = StringReplaceUtil.replaceWithMatcher(parentDoc, "\\{@link (?[^}]*)}", matcher -> getMarkDownFor(matcher - .group("type") - .trim(), environment, element)); - - //Replace returns call - //Remove docParam and param - parentDoc = StringReplaceUtil.replaceWithMatcher(parentDoc, "@(?return|docParam|param) (?[^@]*)", m -> m - .group("type") - .equals("return") ? "Returns: `" + m.group("content").trim() + "`\n" : ""); - - - return parentDoc.trim(); - } - - private static DocumentedType getDocumentedType(String type, ProcessingEnvironment environment, Element documentedElement) { - if(type.contains("#")) { - if(documentedElement.getEnclosingElement().getKind() == ElementKind.PACKAGE) { - return getDocumentedType(documentedElement.asType().toString(), environment, documentedElement); - } else { - return getDocumentedType(type.split("#", 2)[0], environment, documentedElement); - } - } - - if(type.isEmpty()) { - return DocumentedType.fromElement(documentedElement.getEnclosingElement(), environment, true); - } - - { - TypeElement typeElement = environment.getElementUtils().getTypeElement(type); - if(typeElement != null) { - final DocumentedType documentedType = DocumentedType.fromElement(typeElement, environment, true); - if(documentedType != null) { - return documentedType; - } - } - } - - final PackageElement packageOf = environment.getElementUtils() - .getPackageOf(documentedElement); - for(Element enclosedElement : packageOf.getEnclosedElements()) { - if(enclosedElement.getSimpleName().contentEquals(type)) { - final DocumentedType documentedType = DocumentedType.fromElement(enclosedElement, environment, true); - if(documentedType != null) { - return documentedType; - } - } - } - - if(DocumentProcessorNew.tree != null) { - final TreePath path = DocumentProcessorNew.tree.getPath(documentedElement); - if(path != null) { - final Optional any = path.getCompilationUnit() - .getImports() - .stream() - .map(ImportTree::getQualifiedIdentifier) - .map(Object::toString) - .sorted(Comparator.comparing(s -> s.endsWith("*"))) //Wildcard imports last - .flatMap(s -> !s.endsWith("*") ? Stream.of(s) : environment.getElementUtils() - .getPackageElement(s.substring(0, s.lastIndexOf('.'))) - .getEnclosedElements() - .stream() - .map(Objects::toString)) - .map(environment.getElementUtils()::getTypeElement) - .filter(Objects::nonNull) //not sure just in case - .filter(e -> e.getSimpleName().contentEquals(type)) - .map(e -> DocumentedType.fromElement(e, environment, true)) - .filter(Objects::nonNull) - .findAny(); - if(any.isPresent()) { - return any.get(); - } - } - } - - environment.getMessager() - .printMessage(Diagnostic.Kind.WARNING, "Could not resolve link to " + type, documentedElement); - return null; - } - - public static String getMarkDownFor(String type, ProcessingEnvironment environment, Element documentedElement) { - final DocumentedType documentedType = getDocumentedType(type, environment, documentedElement); - if(documentedType != null) { - if(type.contains("#")) { - return documentedType.getClickableMarkdown(type.split("#", 2)[1]); - } else { - return documentedType.getClickableMarkdown(); - } - } - - return ""; - } -} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/util/IDontKnowHowToNameThisUtil.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/util/IDontKnowHowToNameThisUtil.java deleted file mode 100644 index e4bbacba6..000000000 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/util/IDontKnowHowToNameThisUtil.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.blamejared.crafttweaker_annotation_processors.processors.document.shared.util; - -import com.blamejared.crafttweaker_annotation_processors.processors.*; -import com.blamejared.crafttweaker_annotations.annotations.*; -import org.openzen.zencode.java.*; - -import javax.annotation.processing.*; -import javax.lang.model.element.*; -import javax.tools.*; -import java.util.*; - -public class IDontKnowHowToNameThisUtil { - - /** - * Suppress the "Custom Type without ZenAnnotation used" error for types starting with this name - */ - private static final Set internalClassNamePrefixes = new HashSet<>(); - - static { - internalClassNamePrefixes.add("java.lang"); - internalClassNamePrefixes.add("java.util"); - internalClassNamePrefixes.add("org.openzen"); - } - - private IDontKnowHowToNameThisUtil() { - } - - - /** - * Returns the path where the documentation md file for this type lies. - * Logs an error if that type as no ZC Annotations, unless annotated with forComment - * - * @param forComment Is this lookup only to resolve a {@code {@link }} then errors will eb suppressed - * @return The docPath, or {@code null} - */ - public static String getDocPath(TypeElement element, ProcessingEnvironment environment, boolean forComment) { - final Document document = element.getAnnotation(Document.class); - final Messager messager = environment.getMessager(); - - if(document == null) { - if(forComment) { - return null; - } - - if(element.getAnnotation(ZenCodeType.Name.class) != null || element.getAnnotation(ZenCodeType.Expansion.class) != null) { - messager.printMessage(Diagnostic.Kind.ERROR, "ZenType/Expansion without a Document annotation!", element); - } else if(!isInternalClass(element)) { - messager.printMessage(Diagnostic.Kind.ERROR, "Custom Type without Zen annotations used! " + element - .getQualifiedName(), element); - } - return null; - } - - if(document.value().isEmpty()) { - final AnnotationMirror mirror = AnnotationMirrorUtil.getMirror(element, Document.class); - messager.printMessage(Diagnostic.Kind.ERROR, "Empty Doc Path provided!", element, mirror); - } - return document.value(); - } - - private static boolean isInternalClass(TypeElement element) { - final String qualifiedName = element.getQualifiedName().toString(); - return internalClassNamePrefixes.stream().anyMatch(qualifiedName::startsWith); - } - -} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/util/StringReplaceUtil.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/util/StringReplaceUtil.java deleted file mode 100644 index 64776d17d..000000000 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/document/shared/util/StringReplaceUtil.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.blamejared.crafttweaker_annotation_processors.processors.document.shared.util; - -import org.intellij.lang.annotations.Language; -import org.jetbrains.annotations.Contract; - -import java.util.function.Function; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class StringReplaceUtil { - @Contract("null, _, _ -> null") - public static String replaceAll(String s, @Language("regexp") String regex, Function mappingFunction) { - if (s == null) { - return null; - } - final Matcher matcher = Pattern.compile(regex).matcher(s); - final StringBuffer stringBuffer = new StringBuffer(); - - while (matcher.find()) { - matcher.appendReplacement(stringBuffer, mappingFunction.apply(matcher.group())); - } - matcher.appendTail(stringBuffer); - return stringBuffer.toString(); - } - - @Contract("null, _, _ -> null") - public static String replaceWithMatcher(String s, @Language("regexp") String regex, Function mappingFunction) { - if (s == null) - return null; - final Matcher matcher = Pattern.compile(regex).matcher(s); - final StringBuffer stringBuffer = new StringBuffer(); - - while (matcher.find()) { - matcher.appendReplacement(stringBuffer, mappingFunction.apply(matcher)); - } - matcher.appendTail(stringBuffer); - return stringBuffer.toString(); - } -} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/util/files/DeletingPathVisitor.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/util/files/DeletingPathVisitor.java new file mode 100644 index 000000000..8877fb248 --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/util/files/DeletingPathVisitor.java @@ -0,0 +1,22 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.util.files; + +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; + +public class DeletingPathVisitor extends SimpleFileVisitor { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + Files.delete(file); + return super.visitFile(file, attrs); + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + Files.delete(dir); + return super.postVisitDirectory(dir, exc); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/validation/keywords/KeywordValidator.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/validation/keywords/KeywordValidator.java new file mode 100644 index 000000000..d991fb32a --- /dev/null +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/validation/keywords/KeywordValidator.java @@ -0,0 +1,45 @@ +package com.blamejared.crafttweaker_annotation_processors.processors.validation.keywords; + +import org.openzen.zencode.java.ZenCodeType; + +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import java.lang.annotation.Annotation; +import java.util.HashSet; +import java.util.Set; + +public class KeywordValidator extends AbstractProcessor { + + private final ZenCodeKeywordUtil keywordUtil = new ZenCodeKeywordUtil(); + + @Override + public Set getSupportedAnnotationTypes() { + final HashSet result = new HashSet<>(); + addSupportedType(result, ZenCodeType.Method.class); + addSupportedType(result, ZenCodeType.Getter.class); + addSupportedType(result, ZenCodeType.Setter.class); + addSupportedType(result, ZenCodeType.Field.class); + return result; + } + + private void addSupportedType(HashSet result, Class supportedType) { + result.add(supportedType.getCanonicalName()); + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + for(TypeElement annotation : annotations) { + for(Element element : roundEnv.getElementsAnnotatedWith(annotation)) { + verifyElementNameUseNoKeywordAsName(element); + } + } + + return false; + } + + private void verifyElementNameUseNoKeywordAsName(Element element) { + keywordUtil.checkName(element, processingEnv.getMessager()); + } +} diff --git a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/validation/ZenCodeKeywordUtil.java b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/validation/keywords/ZenCodeKeywordUtil.java similarity index 87% rename from Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/validation/ZenCodeKeywordUtil.java rename to Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/validation/keywords/ZenCodeKeywordUtil.java index e1a715f88..a3c7dd40d 100644 --- a/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/validation/ZenCodeKeywordUtil.java +++ b/Crafttweaker_Annotation_Processors/src/main/java/com/blamejared/crafttweaker_annotation_processors/processors/validation/keywords/ZenCodeKeywordUtil.java @@ -1,14 +1,15 @@ -package com.blamejared.crafttweaker_annotation_processors.processors.validation; +package com.blamejared.crafttweaker_annotation_processors.processors.validation.keywords; -import javax.annotation.processing.*; -import javax.lang.model.element.*; -import javax.tools.*; -import java.util.*; +import javax.annotation.processing.Messager; +import javax.lang.model.element.Element; +import javax.tools.Diagnostic; +import java.util.Set; +import java.util.TreeSet; public class ZenCodeKeywordUtil { - private static final Set knownKeywords; - static { + private final Set knownKeywords; + { knownKeywords = new TreeSet<>(); knownKeywords.add("import"); knownKeywords.add("alias"); @@ -83,13 +84,13 @@ public class ZenCodeKeywordUtil { knownKeywords.add("new"); } - public static boolean isKeyword(String name) { + public boolean isKeyword(String name) { return knownKeywords.contains(name); } - public static void checkName(String name, Element element, ProcessingEnvironment environment) { + public void checkName(Element element, Messager messager) { + final String name = element.getSimpleName().toString(); if(isKeyword(name)) { - final Messager messager = environment.getMessager(); final String message = String.format("Name '%s' is a ZenCode keyword!", name); messager.printMessage(Diagnostic.Kind.ERROR, message, element); } diff --git a/Crafttweaker_Annotation_Processors/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/Crafttweaker_Annotation_Processors/src/main/resources/META-INF/services/javax.annotation.processing.Processor index 739fad15e..c5d2ba9d4 100644 --- a/Crafttweaker_Annotation_Processors/src/main/resources/META-INF/services/javax.annotation.processing.Processor +++ b/Crafttweaker_Annotation_Processors/src/main/resources/META-INF/services/javax.annotation.processing.Processor @@ -1,3 +1,4 @@ com.blamejared.crafttweaker_annotation_processors.processors.validation.BracketHandlerCheckValidationProcessor com.blamejared.crafttweaker_annotation_processors.processors.validation.PreprocessorAnnotationValidationProcessor -com.blamejared.crafttweaker_annotation_processors.processors.document.DocumentProcessorNew +com.blamejared.crafttweaker_annotation_processors.processors.document.DocumentProcessor +com.blamejared.crafttweaker_annotation_processors.processors.validation.keywords.KeywordValidator