diff options
author | Senmori <thesenmori@gmail.com> | 2018-07-13 00:28:40 -0400 |
---|---|---|
committer | md_5 <git@md-5.net> | 2018-07-13 15:50:41 +1000 |
commit | 3d4b0c8a117a5ffc54e90b6b3b41f6f24e000cba (patch) | |
tree | 91404cc6b63abe03d441226e04da85f3f642249a /src/main | |
parent | e677cffa5de059d623c03705f9568b57447f5b05 (diff) | |
download | plugin-annotations-3d4b0c8a117a5ffc54e90b6b3b41f6f24e000cba.tar plugin-annotations-3d4b0c8a117a5ffc54e90b6b3b41f6f24e000cba.tar.gz plugin-annotations-3d4b0c8a117a5ffc54e90b6b3b41f6f24e000cba.tar.lz plugin-annotations-3d4b0c8a117a5ffc54e90b6b3b41f6f24e000cba.tar.xz plugin-annotations-3d4b0c8a117a5ffc54e90b6b3b41f6f24e000cba.zip |
Misc changes for v1.2
* Add @ApiVersion and appropriate targets
* Add ability to have @Command and @Permission annotations on classes
that implement CommandExecutor. Thanks Hex for the suggestion.
* Remove last reference to @Main.
* Update README.
* Bump version.
* Remove deprecated annotations.
Diffstat (limited to 'src/main')
22 files changed, 364 insertions, 274 deletions
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/PluginAnnotationProcessor.java b/src/main/java/org/bukkit/plugin/java/annotation/PluginAnnotationProcessor.java index 9557b79..2f0f8d7 100644 --- a/src/main/java/org/bukkit/plugin/java/annotation/PluginAnnotationProcessor.java +++ b/src/main/java/org/bukkit/plugin/java/annotation/PluginAnnotationProcessor.java @@ -2,25 +2,28 @@ package org.bukkit.plugin.java.annotation; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import org.bukkit.command.CommandExecutor; +import org.bukkit.permissions.PermissionDefault; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.annotation.command.Command; +import org.bukkit.plugin.java.annotation.command.Commands; import org.bukkit.plugin.java.annotation.dependency.Dependency; import org.bukkit.plugin.java.annotation.dependency.LoadBefore; import org.bukkit.plugin.java.annotation.dependency.SoftDependency; import org.bukkit.plugin.java.annotation.permission.ChildPermission; import org.bukkit.plugin.java.annotation.permission.Permission; +import org.bukkit.plugin.java.annotation.permission.Permissions; +import org.bukkit.plugin.java.annotation.plugin.ApiVersion; import org.bukkit.plugin.java.annotation.plugin.Description; -import org.bukkit.plugin.java.annotation.plugin.LoadOn; +import org.bukkit.plugin.java.annotation.plugin.LoadOrder; import org.bukkit.plugin.java.annotation.plugin.LogPrefix; import org.bukkit.plugin.java.annotation.plugin.Plugin; -import org.bukkit.plugin.java.annotation.plugin.UsesDatabase; import org.bukkit.plugin.java.annotation.plugin.Website; import org.bukkit.plugin.java.annotation.plugin.author.Author; import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.nodes.Tag; - import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; @@ -31,231 +34,358 @@ import javax.lang.model.element.Modifier; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; -import javax.swing.text.DateFormatter; import javax.tools.Diagnostic; import javax.tools.FileObject; import javax.tools.StandardLocation; import java.io.IOException; -import java.io.InputStream; import java.io.Writer; import java.lang.annotation.Annotation; import java.lang.reflect.Method; -import java.text.DateFormat; -import java.text.SimpleDateFormat; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; -import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; -@SupportedAnnotationTypes("org.bukkit.plugin.java.annotation.*") -@SupportedSourceVersion(SourceVersion.RELEASE_8) +@SupportedAnnotationTypes( "org.bukkit.plugin.java.annotation.*" ) +@SupportedSourceVersion( SourceVersion.RELEASE_8 ) public class PluginAnnotationProcessor extends AbstractProcessor { private boolean hasMainBeenFound = false; - private static final DateTimeFormatter dFormat = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss", Locale.ENGLISH); + private static final DateTimeFormatter dFormat = DateTimeFormatter.ofPattern( "yyyy/MM/dd HH:mm:ss", Locale.ENGLISH ); @Override public boolean process(Set<? extends TypeElement> annots, RoundEnvironment rEnv) { - Element main = null; + Element mainPluginElement = null; hasMainBeenFound = false; - Set<? extends Element> elements = rEnv.getElementsAnnotatedWith(Plugin.class); - if(elements.size() > 1) { - raiseError("Found more than one plugin main class"); + Set<? extends Element> elements = rEnv.getElementsAnnotatedWith( Plugin.class ); + if ( elements.size() > 1 ) { + raiseError( "Found more than one plugin main class" ); return false; } - if(elements.isEmpty()) { + if ( elements.isEmpty() ) { return false; } - if(hasMainBeenFound){ - raiseError("The plugin class has already been located, aborting!"); + if ( hasMainBeenFound ) { + raiseError( "The plugin class has already been located, aborting!" ); return false; } - main = elements.iterator().next(); + mainPluginElement = elements.iterator().next(); hasMainBeenFound = true; - TypeElement mainType; - if(main instanceof TypeElement){ - mainType = (TypeElement) main; + TypeElement mainPluginType; + if ( mainPluginElement instanceof TypeElement ) { + mainPluginType = ( TypeElement ) mainPluginElement; } else { - raiseError("Element annotated with @Main is not a type!", main); + raiseError( "Element annotated with @Plugin is not a type!", mainPluginElement ); return false; } - if(!(mainType.getEnclosingElement() instanceof PackageElement) && !mainType.getModifiers().contains(Modifier.STATIC)){ - raiseError("Element annotated with @Main is not top-level or static nested!", mainType); + if ( !( mainPluginType.getEnclosingElement() instanceof PackageElement ) && !mainPluginType.getModifiers().contains( Modifier.STATIC ) ) { + raiseError( "Element annotated with @Plugin is not top-level or static nested!", mainPluginType ); return false; } - if(!processingEnv.getTypeUtils().isSubtype(mainType.asType(), fromClass(JavaPlugin.class))){ - raiseError("Class annotated with @Main is not an subclass of JavaPlugin!", mainType); + if ( !processingEnv.getTypeUtils().isSubtype( mainPluginType.asType(), fromClass( JavaPlugin.class ) ) ) { + raiseError( "Class annotated with @Plugin is not an subclass of JavaPlugin!", mainPluginType ); } Map<String, Object> yml = Maps.newLinkedHashMap(); // linked so we can maintain the same output into file for sanity // populate mainName - final String mainName = mainType.getQualifiedName().toString(); - yml.put("main", mainName); // always override this so we make sure the main class name is correct + final String mainName = mainPluginType.getQualifiedName().toString(); + yml.put( "main", mainName ); // always override this so we make sure the main class name is correct // populate plugin name - processAndPut(yml, "name", mainType, mainName.substring(mainName.lastIndexOf('.') + 1), Plugin.class, String.class, "name"); + processAndPut( yml, "name", mainPluginType, mainName.substring( mainName.lastIndexOf( '.' ) + 1 ), Plugin.class, String.class, "name" ); // populate version - processAndPut(yml, "version", mainType, Plugin.DEFAULT_VERSION, Plugin.class, String.class, "version"); + processAndPut( yml, "version", mainPluginType, Plugin.DEFAULT_VERSION, Plugin.class, String.class, "version" ); // populate plugin description - processAndPut(yml, "description", mainType, null, Description.class, String.class, "desc"); + processAndPut( yml, "description", mainPluginType, null, Description.class, String.class ); // populate plugin load order - processAndPut(yml, "load", mainType, null, LoadOn.class, String.class,"loadOn"); + processAndPut( yml, "load", mainPluginType, null, LoadOrder.class, String.class ); // authors - Author[] authors = mainType.getAnnotationsByType(Author.class); + Author[] authors = mainPluginType.getAnnotationsByType( Author.class ); List<String> authorMap = Lists.newArrayList(); - for(Author auth : authors) { - authorMap.add(auth.name()); + for ( Author auth : authors ) { + authorMap.add( auth.value() ); } - if(authorMap.size() > 1) { - yml.put("authors", authorMap); - } else if(authorMap.size() == 1) { - yml.put("author", authorMap.iterator().next()); + if ( authorMap.size() > 1 ) { + yml.put( "authors", authorMap ); + } else if ( authorMap.size() == 1 ) { + yml.put( "author", authorMap.iterator().next() ); } // website - processAndPut(yml, "website", mainType, null, Website.class, String.class, "url"); + processAndPut( yml, "website", mainPluginType, null, Website.class, String.class ); // prefix - processAndPut(yml, "prefix", mainType, null, LogPrefix.class, String.class, "prefix"); + processAndPut( yml, "prefix", mainPluginType, null, LogPrefix.class, String.class ); // dependencies - Dependency[] dependencies = mainType.getAnnotationsByType(Dependency.class); + Dependency[] dependencies = mainPluginType.getAnnotationsByType( Dependency.class ); List<String> hardDependencies = Lists.newArrayList(); - for(Dependency dep : dependencies) { - hardDependencies.add(dep.plugin()); + for ( Dependency dep : dependencies ) { + hardDependencies.add( dep.value() ); } - if(!hardDependencies.isEmpty()) yml.putIfAbsent("depend", hardDependencies); + if ( !hardDependencies.isEmpty() ) yml.put( "depend", hardDependencies ); // soft-dependencies - SoftDependency[] softDependencies = mainType.getAnnotationsByType(SoftDependency.class); - String[] softDepArr = new String[softDependencies.length]; - for(int i = 0; i < softDependencies.length; i++) { - softDepArr[i] = softDependencies[i].plugin(); + SoftDependency[] softDependencies = mainPluginType.getAnnotationsByType( SoftDependency.class ); + String[] softDepArr = new String[ softDependencies.length ]; + for ( int i = 0; i < softDependencies.length; i++ ) { + softDepArr[ i ] = softDependencies[ i ].value(); } - if(softDepArr.length > 0) yml.putIfAbsent("softdepend", softDepArr); + if ( softDepArr.length > 0 ) yml.put( "softdepend", softDepArr ); // load-before - LoadBefore[] loadBefore = mainType.getAnnotationsByType(LoadBefore.class); - String[] loadBeforeArr = new String[loadBefore.length]; - for(int i = 0; i < loadBefore.length; i++) { - loadBeforeArr[i] = loadBefore[i].plugin(); + LoadBefore[] loadBefore = mainPluginType.getAnnotationsByType( LoadBefore.class ); + String[] loadBeforeArr = new String[ loadBefore.length ]; + for ( int i = 0; i < loadBefore.length; i++ ) { + loadBeforeArr[ i ] = loadBefore[ i ].value(); } - if(loadBeforeArr.length > 0) yml.putIfAbsent("loadbefore", loadBeforeArr); + if ( loadBeforeArr.length > 0 ) yml.put( "loadbefore", loadBeforeArr ); // commands - Command[] commands = mainType.getAnnotationsByType(Command.class); - Map<String, Object> commandMap = Maps.newLinkedHashMap(); - for(Command command : commands) { - Map<String, Object> desc = Maps.newLinkedHashMap(); - String name = command.name(); - if(!command.desc().isEmpty()) desc.put("description", command.desc()); - if(command.aliases().length != 0) desc.put("aliases", command.aliases()); - if(!command.permission().isEmpty()) desc.put("permission", command.permission()); - if(!command.permissionMessage().isEmpty()) desc.put("permission-message", command.permissionMessage()); - if(!command.usage().isEmpty()) desc.put("usage", command.usage()); - commandMap.put(name, desc); + // Begin processing external command annotations + Map<String, Map<String, Object>> commandMap = Maps.newLinkedHashMap(); + boolean result = processExternalCommands( rEnv.getElementsAnnotatedWith( Command.class ), mainPluginType, commandMap ); + if ( !result ) { + // #processExternalCommand already raised the errors + return false; + } + + Commands commands = mainPluginType.getAnnotation( Commands.class ); + + // Check main class for any command annotations + if ( commands != null ) { + Map<String, Map<String, Object>> merged = Maps.newLinkedHashMap(); + merged.putAll( commandMap ); + merged.putAll( this.processCommands( commands ) ); + commandMap = merged; } - if(!commandMap.isEmpty()) yml.putIfAbsent("commands", commandMap); - - // permissions - Permission[] permissions = mainType.getAnnotationsByType(Permission.class); - Map<String, Object> permMap = Maps.newLinkedHashMap(); - for(Permission perm : permissions) { - Map<String, Object> desc = Maps.newLinkedHashMap(); - String name = perm.name(); - if(!perm.desc().isEmpty()) desc.put("description", perm.desc()); - desc.put("default", perm.defaultValue().toString()); - Map<String, Object> children = Maps.newLinkedHashMap(); - for(ChildPermission child : perm.children()) { - children.put(child.name(), child.inherit()); + + yml.put( "commands", commandMap ); + + // Permissions + Map<String, Map<String, Object>> permissionMetadata = Maps.newLinkedHashMap(); + + Set<? extends Element> permissionAnnotations = rEnv.getElementsAnnotatedWith( Command.class ); + if ( permissionAnnotations.size() > 0 ) { + for ( Element element : permissionAnnotations ) { + if ( element.equals( mainPluginElement ) ) { + continue; + } + if ( element.getAnnotation( Permission.class ) != null ) { + Permission permissionAnnotation = element.getAnnotation( Permission.class ); + permissionMetadata.put( permissionAnnotation.name(), this.processPermission( permissionAnnotation ) ); + } } - if(!children.isEmpty()) desc.put("children", children); - permMap.put(name, desc); } - if(!permMap.isEmpty()) yml.putIfAbsent("permissions", permMap); - // database D: //TODO: Remove me! - if(mainType.getAnnotation(UsesDatabase.class) != null) { - yml.put("database", true); - processingEnv.getMessager().printMessage(Diagnostic.Kind.MANDATORY_WARNING, "Database support was dropped in Bukkit in version 1.12.", mainType); + Permissions permissions = mainPluginType.getAnnotation( Permissions.class ); + if ( permissions != null ) { + Map<String, Map<String, Object>> joined = Maps.newLinkedHashMap(); + joined.putAll( permissionMetadata ); + joined.putAll( this.processPermissions( permissions ) ); + permissionMetadata = joined; + } + yml.put( "permissions", permissionMetadata ); + + // api-version + if ( mainPluginType.getAnnotation( ApiVersion.class ) != null ) { + ApiVersion apiVersion = mainPluginType.getAnnotation( ApiVersion.class ); + if ( apiVersion.value() != ApiVersion.Target.DEFAULT ) { + yml.put( "api-version", apiVersion.value().getVersion() ); + } } - Yaml yaml = new Yaml(); try { - FileObject file = this.processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", "plugin.yml"); - try(Writer w = file.openWriter()) { - w.append("# Auto-generated plugin.yml, generated at ") - .append(LocalDateTime.now().format(dFormat)) - .append(" by ") - .append(this.getClass().getName()) - .append("\n\n"); + Yaml yaml = new Yaml(); + FileObject file = this.processingEnv.getFiler().createResource( StandardLocation.CLASS_OUTPUT, "", "plugin.yml" ); + try ( Writer w = file.openWriter() ) { + w.append( "# Auto-generated plugin.yml, generated at " ) + .append( LocalDateTime.now().format( dFormat ) ) + .append( " by " ) + .append( this.getClass().getName() ) + .append( "\n\n" ); // have to format the yaml explicitly because otherwise it dumps child nodes as maps within braces. - String raw = yaml.dumpAs(yml, Tag.MAP, DumperOptions.FlowStyle.BLOCK); - w.write(raw); + String raw = yaml.dumpAs( yml, Tag.MAP, DumperOptions.FlowStyle.BLOCK ); + w.write( raw ); w.flush(); w.close(); } // try with resources will close the Writer since it implements Closeable - } catch (IOException e) { - throw new RuntimeException(e); + } catch ( IOException e ) { + throw new RuntimeException( e ); } - processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, "NOTE: You are using org.bukkit.plugin.java.annotation, an experimental API!"); + processingEnv.getMessager().printMessage( Diagnostic.Kind.WARNING, "NOTE: You are using org.bukkit.plugin.java.annotation, an experimental API!" ); return true; } private void raiseError(String message) { - this.processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, message); + this.processingEnv.getMessager().printMessage( Diagnostic.Kind.ERROR, message ); } private void raiseError(String message, Element element) { - this.processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, message, element); + this.processingEnv.getMessager().printMessage( Diagnostic.Kind.ERROR, message, element ); } private TypeMirror fromClass(Class<?> clazz) { - return processingEnv.getElementUtils().getTypeElement(clazz.getName()).asType(); + return processingEnv.getElementUtils().getTypeElement( clazz.getName() ).asType(); } private <A extends Annotation, R> R processAndPut( Map<String, Object> map, String name, Element el, R defaultVal, Class<A> annotationType, Class<R> returnType) { - return processAndPut(map, name, el, defaultVal, annotationType, returnType, "value"); + return processAndPut( map, name, el, defaultVal, annotationType, returnType, "value" ); } private <A extends Annotation, R> R processAndPut( Map<String, Object> map, String name, Element el, R defaultVal, Class<A> annotationType, Class<R> returnType, String methodName) { - R result = process(el, defaultVal, annotationType, returnType, methodName); - if(result != null) - map.putIfAbsent(name, result); + R result = process( el, defaultVal, annotationType, returnType, methodName ); + if ( result != null ) + map.put( name, result ); return result; } private <A extends Annotation, R> R process(Element el, R defaultVal, Class<A> annotationType, Class<R> returnType, String methodName) { R result; - A ann = el.getAnnotation(annotationType); - if(ann == null) result = defaultVal; + A ann = el.getAnnotation( annotationType ); + if ( ann == null ) result = defaultVal; else { try { - Method value = annotationType.getMethod(methodName); - Object res = value.invoke(ann); - result = (R) (returnType == String.class ? res.toString() : returnType.cast(res)); - } catch (Exception e) { - throw new RuntimeException(e); // shouldn't happen in theory (blame Choco if it does) + Method value = annotationType.getMethod( methodName ); + Object res = value.invoke( ann ); + result = ( R ) ( returnType == String.class ? res.toString() : returnType.cast( res ) ); + } catch ( Exception e ) { + throw new RuntimeException( e ); // shouldn't happen in theory (blame Choco if it does) } } return result; } + + private boolean processExternalCommands(Set<? extends Element> commandExecutors, TypeElement mainPluginType, Map<String, Map<String, Object>> commandMetadata) { + for ( Element element : commandExecutors ) { + // Check to see if someone annotated a non-class with this + if ( !( element instanceof TypeElement ) ) { + this.raiseError( "Specified Command Executor class is not a class." ); + return false; + } + + TypeElement typeElement = ( TypeElement ) element; + if ( typeElement.equals( mainPluginType ) ) { + continue; + } + + // Check to see if annotated class is actuall a command executor + TypeMirror mirror = this.processingEnv.getElementUtils().getTypeElement( CommandExecutor.class.getName() ).asType(); + if ( !( this.processingEnv.getTypeUtils().isAssignable( typeElement.asType(), mirror ) ) ) { + this.raiseError( "Specified Command Executor class is not assignable from CommandExecutor " ); + return false; + } + + Command annotation = typeElement.getAnnotation( Command.class ); + commandMetadata.put( annotation.name(), this.processCommand( annotation ) ); + } + return true; + } + + /** + * Processes a set of commands. + * + * @param commands The annotation. + * + * @return The generated command metadata. + */ + protected Map<String, Map<String, Object>> processCommands(Commands commands) { + Map<String, Map<String, Object>> commandList = Maps.newLinkedHashMap(); + for ( Command command : commands.value() ) { + commandList.put( command.name(), this.processCommand( command ) ); + } + return commandList; + } + + /** + * Processes a single command. + * + * @param commandAnnotation The annotation. + * + * @return The generated command metadata. + */ + protected Map<String, Object> processCommand(Command commandAnnotation) { + Map<String, Object> command = Maps.newLinkedHashMap(); + + if ( commandAnnotation.aliases().length == 1 ) { + command.put( "aliases", commandAnnotation.aliases()[ 0 ] ); + } else if ( commandAnnotation.aliases().length > 1 ) { + command.put( "aliases", commandAnnotation.aliases() ); + } + + if ( !"".equals( commandAnnotation.desc() ) ) { + command.put( "description", commandAnnotation.desc() ); + } + if ( !"".equals( commandAnnotation.permission() ) ) { + command.put( "permission", commandAnnotation.permission() ); + } + if ( !"".equals( commandAnnotation.permissionMessage() ) ) { + command.put( "permission-message", commandAnnotation.permissionMessage() ); + } + if ( !"".equals( commandAnnotation.usage() ) ) { + command.put( "usage", commandAnnotation.usage() ); + } + + return command; + } + + /** + * Processes a command. + * + * @param permissionAnnotation The annotation. + * + * @return The generated permission metadata. + */ + protected Map<String, Object> processPermission(Permission permissionAnnotation) { + Map<String, Object> permission = Maps.newLinkedHashMap(); + + if ( !"".equals( permissionAnnotation.desc() ) ) { + permission.put( "description", permissionAnnotation.desc() ); + } + if ( PermissionDefault.OP != permissionAnnotation.defaultValue() ) { + permission.put( "default", permissionAnnotation.defaultValue().toString().toLowerCase() ); + } + + if ( permissionAnnotation.children().length > 0 ) { + Map<String, Boolean> childrenList = Maps.newLinkedHashMap(); // maintain order + for ( ChildPermission childPermission : permissionAnnotation.children() ) { + childrenList.put( childPermission.name(), childPermission.inherit() ); + } + permission.put( "children", childrenList ); + } + + return permission; + } + + /** + * Processes a set of permissions. + * + * @param permissions The annotation. + * + * @return The generated permission metadata. + */ + protected Map<String, Map<String, Object>> processPermissions(Permissions permissions) { + Map<String, Map<String, Object>> permissionList = Maps.newLinkedHashMap(); + for ( Permission permission : permissions.value() ) { + permissionList.put( permission.name(), this.processPermission( permission ) ); + } + return permissionList; + } } diff --git a/src/main/java/org/bukkit/plugin/java/annotation/command/Commands.java b/src/main/java/org/bukkit/plugin/java/annotation/command/Commands.java index 6ba1211..df66cc6 100644 --- a/src/main/java/org/bukkit/plugin/java/annotation/command/Commands.java +++ b/src/main/java/org/bukkit/plugin/java/annotation/command/Commands.java @@ -7,9 +7,12 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * Part of the plugin annotations framework. - * <p> - * Represents a list of this plugin's registered command(s). + * Part of the plugin annotations framework. + * <p> + * Represents a list of this plugin's registered command(s). + * <br> + * This specific annotation should not be used by people who do not know + * how repeating annotations work. */ @Documented @Target(ElementType.TYPE) diff --git a/src/main/java/org/bukkit/plugin/java/annotation/dependency/Dependency.java b/src/main/java/org/bukkit/plugin/java/annotation/dependency/Dependency.java index ac6e942..28b045b 100644 --- a/src/main/java/org/bukkit/plugin/java/annotation/dependency/Dependency.java +++ b/src/main/java/org/bukkit/plugin/java/annotation/dependency/Dependency.java @@ -8,7 +8,12 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * Defines a plugin dependency + * Defines a plugin dependency. + * <br> + * The plugin's <b>name</b> attribute is required in order to load the dependency.<br> + * If any plugin listed is not found the plugin will fail to load. <br> + * If multiple plugins list each other as a dependency, so that there are no plugins with an unloadable dependency, + * all plugins will fail to load. */ @Documented @Target(ElementType.TYPE) @@ -18,5 +23,5 @@ public @interface Dependency { /** * A plugin that is required to be present in order for this plugin to load. */ - String plugin(); + String value(); } diff --git a/src/main/java/org/bukkit/plugin/java/annotation/dependency/DependsOn.java b/src/main/java/org/bukkit/plugin/java/annotation/dependency/DependsOn.java index 8d59aaa..54e9e5d 100644 --- a/src/main/java/org/bukkit/plugin/java/annotation/dependency/DependsOn.java +++ b/src/main/java/org/bukkit/plugin/java/annotation/dependency/DependsOn.java @@ -7,9 +7,12 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * Part of the plugin annotations framework. - * <p> - * Represents the plugins a plugin depends on in order to be loaded + * Part of the plugin annotations framework. + * <p> + * Represents the plugins a plugin depends on in order to be loaded + * <br> + * This specific annotation should not be used by people who do not know + * how repeating annotations work. */ @Documented @Target(ElementType.TYPE) diff --git a/src/main/java/org/bukkit/plugin/java/annotation/dependency/LoadBefore.java b/src/main/java/org/bukkit/plugin/java/annotation/dependency/LoadBefore.java index d5ba086..06e3f5b 100644 --- a/src/main/java/org/bukkit/plugin/java/annotation/dependency/LoadBefore.java +++ b/src/main/java/org/bukkit/plugin/java/annotation/dependency/LoadBefore.java @@ -11,6 +11,9 @@ import java.lang.annotation.Target; * Part of the plugin annotations framework. * <p> * Represents the plugin this plugin should be loaded before + * <br> + * The plugin's <b>name</b> attribute is required in order to specify the target. <br> + * The plugin listed will be treated as a {@link SoftDependency}. <br> */ @Documented @Retention(RetentionPolicy.SOURCE) @@ -20,5 +23,5 @@ public @interface LoadBefore { /** * A plugin that should be loaded after your plugin */ - String plugin(); + String value(); } diff --git a/src/main/java/org/bukkit/plugin/java/annotation/dependency/LoadBeforePlugins.java b/src/main/java/org/bukkit/plugin/java/annotation/dependency/LoadBeforePlugins.java index 67991e9..7061622 100644 --- a/src/main/java/org/bukkit/plugin/java/annotation/dependency/LoadBeforePlugins.java +++ b/src/main/java/org/bukkit/plugin/java/annotation/dependency/LoadBeforePlugins.java @@ -8,6 +8,9 @@ import java.lang.annotation.Target; /** * Defines a list of plugin to load after this plugin + * <br> + * This specific annotation should not be used by people who do not know + * how repeating annotations work. */ @Documented @Retention(RetentionPolicy.SOURCE) diff --git a/src/main/java/org/bukkit/plugin/java/annotation/dependency/SoftDependency.java b/src/main/java/org/bukkit/plugin/java/annotation/dependency/SoftDependency.java index a53e16b..9f3c379 100644 --- a/src/main/java/org/bukkit/plugin/java/annotation/dependency/SoftDependency.java +++ b/src/main/java/org/bukkit/plugin/java/annotation/dependency/SoftDependency.java @@ -11,6 +11,9 @@ import java.lang.annotation.Target; /** * Represents a soft (optional) dependency for this plugin. * If this dependency is not present, the plugin will still load. + * <br> + * The <b>name</b> attribute of the plugin is required in order to specify the target. <br> + * Circular soft-dependencies are loaded arbitrarily. */ @Documented @@ -21,5 +24,5 @@ public @interface SoftDependency { /** * A plugin that is required in order for this plugin to have full functionality. */ - String plugin(); + String value(); } diff --git a/src/main/java/org/bukkit/plugin/java/annotation/dependency/SoftDependsOn.java b/src/main/java/org/bukkit/plugin/java/annotation/dependency/SoftDependsOn.java index 038831d..fb53a10 100644 --- a/src/main/java/org/bukkit/plugin/java/annotation/dependency/SoftDependsOn.java +++ b/src/main/java/org/bukkit/plugin/java/annotation/dependency/SoftDependsOn.java @@ -7,10 +7,13 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * Part of the plugin annotations framework. - * <p> - * Represents the plugins this plugin should try to load before this plugin will attempt to load. - * A plugin will still load if a soft dependency is not present. + * Part of the plugin annotations framework. + * <p> + * Represents the plugins this plugin should try to load before this plugin will attempt to load. + * A plugin will still load if a soft dependency is not present. + * <br> + * This specific annotation should not be used by people who do not know + * how repeating annotations work. */ @Documented diff --git a/src/main/java/org/bukkit/plugin/java/annotation/permission/ChildPermission.java b/src/main/java/org/bukkit/plugin/java/annotation/permission/ChildPermission.java index 7fe1a3d..53b6ccf 100644 --- a/src/main/java/org/bukkit/plugin/java/annotation/permission/ChildPermission.java +++ b/src/main/java/org/bukkit/plugin/java/annotation/permission/ChildPermission.java @@ -7,7 +7,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * Defines a child permission for {@link Permission} + * Defines a child permission for a {@link Permission} */ @Documented @Target(ElementType.TYPE) @@ -15,7 +15,7 @@ import java.lang.annotation.Target; public @interface ChildPermission { /** * If true, this child node will inherit the parent {@link Permission}'s permission. - * If false, this child node inherits the inverse parent permission. + * If false, this child node inherits the inverse of the parent permission. */ boolean inherit() default true; diff --git a/src/main/java/org/bukkit/plugin/java/annotation/permission/Permission.java b/src/main/java/org/bukkit/plugin/java/annotation/permission/Permission.java index 58770e2..a00c0f9 100644 --- a/src/main/java/org/bukkit/plugin/java/annotation/permission/Permission.java +++ b/src/main/java/org/bukkit/plugin/java/annotation/permission/Permission.java @@ -19,22 +19,22 @@ import java.lang.annotation.Target; @Repeatable(Permissions.class) public @interface Permission { /** - * This perm's name. + * This permission's name. */ String name(); /** - * This perm's description. + * This permission's description. */ String desc() default ""; /** - * This perm's default {@link PermissionDefault} + * This permission's default {@link PermissionDefault} */ PermissionDefault defaultValue() default PermissionDefault.OP; /** - * This permission's child nodes ({@link ChildPermission}) + * This permission's child nodes ( {@link ChildPermission} ) */ ChildPermission[] children() default {}; } diff --git a/src/main/java/org/bukkit/plugin/java/annotation/permission/Permissions.java b/src/main/java/org/bukkit/plugin/java/annotation/permission/Permissions.java index 8dd8581..644b152 100644 --- a/src/main/java/org/bukkit/plugin/java/annotation/permission/Permissions.java +++ b/src/main/java/org/bukkit/plugin/java/annotation/permission/Permissions.java @@ -7,9 +7,12 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * Part of the plugin annotations framework. - * <p> - * Represents a list of this plugin's registered name. + * Part of the plugin annotations framework. + * <p> + * Represents a list of this plugin's registered name. + * <br> + * This specific annotation should not be used by people who do not know + * how repeating annotations work. */ @Documented @Retention(RetentionPolicy.SOURCE) diff --git a/src/main/java/org/bukkit/plugin/java/annotation/plugin/ApiVersion.java b/src/main/java/org/bukkit/plugin/java/annotation/plugin/ApiVersion.java new file mode 100644 index 0000000..b7f1e24 --- /dev/null +++ b/src/main/java/org/bukkit/plugin/java/annotation/plugin/ApiVersion.java @@ -0,0 +1,62 @@ +package org.bukkit.plugin.java.annotation.plugin; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.Collection; + + +/** + * This annotation specifies the api version of the plugin. + * <br> + * Defaults to {@link ApiVersion.Target#DEFAULT}. + * <br> + * Pre-1.13 plugins do not need to use this annotation. + */ +@Documented +@Retention( RetentionPolicy.SOURCE ) +@Target( ElementType.TYPE ) +public @interface ApiVersion { + + Target value() default Target.DEFAULT; + + /** + * Specifies the target api-version for this plugin. + * + * All pre-1.13 plugins must use {@link #DEFAULT}. + */ + public static enum Target { + /** + * This target version specifies that the plugin was made for pre-1.13 Spigot versions. + */ + DEFAULT( null ), + + /** + * This target version specifies that the plugin was made with 1.13+ versions in mind. + */ + v1_13( "1.13", DEFAULT ); + + + private final String version; + private final Collection<Target> conflictsWith = Sets.newLinkedHashSet(); + + private Target(String version, Target... conflictsWith) { + this.version = version; + this.conflictsWith.addAll( Lists.newArrayList( conflictsWith ) ); + } + + + public String getVersion() { + return version; + } + + public boolean conflictsWith(Target target) { + return this.conflictsWith.contains( target ); + } + } +} diff --git a/src/main/java/org/bukkit/plugin/java/annotation/plugin/Description.java b/src/main/java/org/bukkit/plugin/java/annotation/plugin/Description.java index 137249d..69abeca 100644 --- a/src/main/java/org/bukkit/plugin/java/annotation/plugin/Description.java +++ b/src/main/java/org/bukkit/plugin/java/annotation/plugin/Description.java @@ -19,6 +19,6 @@ public @interface Description { /** * A human friendly description of the functionality this plugin provides. */ - String desc(); + String value(); } diff --git a/src/main/java/org/bukkit/plugin/java/annotation/plugin/LoadOn.java b/src/main/java/org/bukkit/plugin/java/annotation/plugin/LoadOrder.java index 23716f7..528ad1a 100644 --- a/src/main/java/org/bukkit/plugin/java/annotation/plugin/LoadOn.java +++ b/src/main/java/org/bukkit/plugin/java/annotation/plugin/LoadOrder.java @@ -17,11 +17,11 @@ import java.lang.annotation.Target; @Documented @Retention(RetentionPolicy.SOURCE) @Target(ElementType.TYPE) -public @interface LoadOn { +public @interface LoadOrder { /** * Explicitly state when the plugin should be loaded. * If not defined, will default to {@link PluginLoadOrder#POSTWORLD}. * See {@link PluginLoadOrder} */ - PluginLoadOrder loadOn(); + PluginLoadOrder value() default PluginLoadOrder.POSTWORLD; } diff --git a/src/main/java/org/bukkit/plugin/java/annotation/plugin/LogPrefix.java b/src/main/java/org/bukkit/plugin/java/annotation/plugin/LogPrefix.java index baefbff..cdf0838 100644 --- a/src/main/java/org/bukkit/plugin/java/annotation/plugin/LogPrefix.java +++ b/src/main/java/org/bukkit/plugin/java/annotation/plugin/LogPrefix.java @@ -19,5 +19,5 @@ public @interface LogPrefix { /** * The name to use when logging to console instead of the plugin's name. */ - String prefix(); + String value(); } diff --git a/src/main/java/org/bukkit/plugin/java/annotation/plugin/Main.java b/src/main/java/org/bukkit/plugin/java/annotation/plugin/Main.java deleted file mode 100644 index 3a21c6c..0000000 --- a/src/main/java/org/bukkit/plugin/java/annotation/plugin/Main.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.bukkit.plugin.java.annotation.plugin; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * DEPRECATED: Use {@link Plugin} instead. - * Marks this class (which <i>must</i> subclass JavaPlugin) as this plugin's main class. - * <p> - * This class is part of the plugin annotation framework that automates plugin.yml. - * <p> - * Example: - * <pre> - * <code>{@literal @}Main - * {@literal @}Name("Test") - * {@literal @}Version("v1.0") - * {@literal @}Description("A test plugin.") - * {@literal @}LoadOn(PluginLoadOrder.POSTWORLD) - * {@literal @}Author("md_5") - * {@literal @}Website("spigotmc.org") - * {@literal @}UsesDatabase - * {@literal @}DependsOn({"WorldEdit", "Towny"}) - * {@literal @}SoftDependsOn("Vault") - * {@literal @}LogPrefix("Testing") - * {@literal @}LoadBefore("Essentials") - * {@literal @}Commands({ - * {@literal @}Command( - * name = "foo", - * name = "Foo command", - * aliases = {"foobar", "fubar"}, - * permission = "test.foo", - * permissionMessage = "You do not have permission!", - * usage = "/<command> [test|stop]" - * ), - * {@literal @}Command("bar") - * }) - * {@literal @}Permissions({ - * {@literal @}Perm( - * name = "test.foo", - * name = "Allows foo command", - * defaultValue = PermissionDefault.OP, - * ), - * {@literal @}Perm( - * name = "test.*", - * name = "Wildcard perm", - * defaultValue = PermissionDefault.OP, - * children = {"test.foo"} - * ) - * }) - * public class Test extends JavaPlugin { ... } - * </code> - * </pre> - * @deprecated use {@link Plugin} instead. - */ -@Deprecated -@Documented -@Retention(RetentionPolicy.SOURCE) -@Target(ElementType.TYPE) -public @interface Main {} diff --git a/src/main/java/org/bukkit/plugin/java/annotation/plugin/Name.java b/src/main/java/org/bukkit/plugin/java/annotation/plugin/Name.java deleted file mode 100644 index 9a11752..0000000 --- a/src/main/java/org/bukkit/plugin/java/annotation/plugin/Name.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.bukkit.plugin.java.annotation.plugin; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Part of the plugin annotations framework. - * <p> - * Represents the name of the plugin. - * <p> - * If not present in a class annotated with {@link Main} the name defaults to Class.getSimpleName() and will emmit a warning. - * @deprecated use {@link Plugin#name()} instead. - */ -@Deprecated -@Documented -@Retention(RetentionPolicy.SOURCE) -@Target(ElementType.TYPE) -public @interface Name { - String name(); -} diff --git a/src/main/java/org/bukkit/plugin/java/annotation/plugin/UsesDatabase.java b/src/main/java/org/bukkit/plugin/java/annotation/plugin/UsesDatabase.java deleted file mode 100644 index aedb9e4..0000000 --- a/src/main/java/org/bukkit/plugin/java/annotation/plugin/UsesDatabase.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.bukkit.plugin.java.annotation.plugin; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Part of the plugin annotations framework. - * <p> - * Denotes this plugin as using Bukkit's bundled database system. - * @deprecated Bukkit no longer supports database(s) in the plugin.yml - */ - -@Deprecated -@Documented -@Retention(RetentionPolicy.SOURCE) -@Target(ElementType.TYPE) -public @interface UsesDatabase {} diff --git a/src/main/java/org/bukkit/plugin/java/annotation/plugin/Version.java b/src/main/java/org/bukkit/plugin/java/annotation/plugin/Version.java deleted file mode 100644 index ba8c25e..0000000 --- a/src/main/java/org/bukkit/plugin/java/annotation/plugin/Version.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.bukkit.plugin.java.annotation.plugin; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Part of the plugin annotations framework. - * <p> - * Represents the version of the plugin. - * <p> - * If not present in a class annotated with {@link Main} the name defaults to "v0.0" and will emmit a warning. - * @deprecated use {@link Plugin#version()} instead - */ - -@Deprecated -@Documented -@Retention(RetentionPolicy.SOURCE) -@Target(ElementType.TYPE) -public @interface Version { - String version(); - - String DEFAULT_VERSION = "v0.0"; -} diff --git a/src/main/java/org/bukkit/plugin/java/annotation/plugin/Website.java b/src/main/java/org/bukkit/plugin/java/annotation/plugin/Website.java index aa28475..9937138 100644 --- a/src/main/java/org/bukkit/plugin/java/annotation/plugin/Website.java +++ b/src/main/java/org/bukkit/plugin/java/annotation/plugin/Website.java @@ -19,5 +19,5 @@ public @interface Website { /** * The url to the website where a user can download this plugin. */ - String url(); + String value(); } diff --git a/src/main/java/org/bukkit/plugin/java/annotation/plugin/author/Author.java b/src/main/java/org/bukkit/plugin/java/annotation/plugin/author/Author.java index e8172a2..d652259 100644 --- a/src/main/java/org/bukkit/plugin/java/annotation/plugin/author/Author.java +++ b/src/main/java/org/bukkit/plugin/java/annotation/plugin/author/Author.java @@ -21,5 +21,5 @@ public @interface Author { /** * The name of the person who developed this plugin. */ - String name(); + String value(); } diff --git a/src/main/java/org/bukkit/plugin/java/annotation/plugin/author/Authors.java b/src/main/java/org/bukkit/plugin/java/annotation/plugin/author/Authors.java index 08ba1a3..b58e7cb 100644 --- a/src/main/java/org/bukkit/plugin/java/annotation/plugin/author/Authors.java +++ b/src/main/java/org/bukkit/plugin/java/annotation/plugin/author/Authors.java @@ -8,6 +8,9 @@ import java.lang.annotation.Target; /** * Represents a list of author(s) for this plugin. + * <br> + * This specific annotation should not be used by people who do not know + * how repeating annotations work. */ @Documented @Retention(RetentionPolicy.SOURCE) |