mirror of
https://hub.spigotmc.org/stash/scm/spigot/plugin-annotations.git
synced 2025-08-05 16:48:43 +00:00
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.
This commit is contained in:
parent
e677cffa5d
commit
3d4b0c8a11
24 changed files with 405 additions and 311 deletions
74
README.md
74
README.md
|
@ -6,66 +6,70 @@ See the [wiki](https://www.spigotmc.org/wiki/plugin-yml/) for more information.
|
|||
|
||||
## Example Usage
|
||||
```
|
||||
package org.spigotmc.annotationtest;
|
||||
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import org.bukkit.plugin.PluginLoadOrder;
|
||||
import org.bukkit.plugin.java.*;
|
||||
import org.bukkit.plugin.java.annotation.*;
|
||||
import org.bukkit.plugin.java.annotation.Commands.Cmd;
|
||||
import org.bukkit.plugin.java.annotation.Permissions.Perm;
|
||||
|
||||
@Plugin(name = "TestPlugin", version = "1.0")
|
||||
@Description(desc = "A test plugin")
|
||||
@LoadOn(loadOn = PluginLoadOrder.POSTWORLD) // defaults to PluginLoadOrder.POSTWORLD if not preset
|
||||
@Author(name = "md_5")
|
||||
@Website(url = "spigotmc.org")
|
||||
@LogPrefix(prefix = "Testing")
|
||||
@Dependency(plugin = "WorldEdit")
|
||||
@Dependency(plugin = "Towny")
|
||||
@LoadBefore(plugin = "Essentials")
|
||||
@SoftDependency(plugin = "FAWE")
|
||||
@Description("A test plugin")
|
||||
@LoadOrder(PluginLoadOrder.STARTUP)
|
||||
@Author("md_5")
|
||||
@Website("www.spigotmc.org")
|
||||
@LogPrefix("Testing")
|
||||
@Dependency("WorldEdit")
|
||||
@Dependency("Towny")
|
||||
@LoadBefore("Towny")
|
||||
@SoftDependency("EssentialsX")
|
||||
@Command(name = "foo", desc = "Foo command", aliases = {"foobar", "fubar"}, permission = "test.foo", permissionMessage = "You do not have permission!", usage = "/<command> [test|stop]")
|
||||
@Permission(name = "test.foo", desc = "Allows foo command", defaultValue = PermissionDefault.OP)
|
||||
@Permission(name = "test.*", desc = "Wildcard permission", defaultValue = PermissionDefault.OP, children = {@ChildPermission(name ="test.foo")})
|
||||
public class Test extends JavaPlugin {}
|
||||
@ApiVersion(ApiVersion.Target.v1_13)
|
||||
public class TestPlugin extends JavaPlugin {
|
||||
```
|
||||
Output:
|
||||
|
||||
```
|
||||
# Auto-generated plugin.yml, generated at 2018/03/06 18:15:44 by org.bukkit.plugin.java.annotation.PluginAnnotationProcessor
|
||||
# Auto-generated plugin.yml, generated at 2018/07/12 22:16:27 by org.bukkit.plugin.java.annotation.PluginAnnotationProcessor
|
||||
|
||||
main: org.spigotmc.annotationtest.Test
|
||||
# Auto-generated plugin.yml, generated at 2018/07/13 00:16:24 by org.bukkit.plugin.java.annotation.PluginAnnotationProcessor
|
||||
|
||||
main: org.spigotmc.spigot.TestPlugin
|
||||
name: TestPlugin
|
||||
version: '1.0'
|
||||
description: A test plugin
|
||||
load: POSTWORLD
|
||||
load: STARTUP
|
||||
author: md_5
|
||||
website: spigotmc.org
|
||||
website: www.spigotmc.org
|
||||
prefix: Testing
|
||||
depend:
|
||||
- WorldEdit
|
||||
- Towny
|
||||
softdepend:
|
||||
- FAWE
|
||||
- EssentialsX
|
||||
loadbefore:
|
||||
- Essentials
|
||||
- Towny
|
||||
commands:
|
||||
foo:
|
||||
description: Foo command
|
||||
aliases:
|
||||
- foobar
|
||||
- fubar
|
||||
permission: test.foo
|
||||
permission-message: You do not have permission!
|
||||
usage: /<command> [test|stop]
|
||||
TestCommand:
|
||||
aliases: testext2
|
||||
permission: test.testext
|
||||
permission-message: Oopsy!
|
||||
usage: /testext test test
|
||||
permissions:
|
||||
test.foo:
|
||||
description: Allows foo command
|
||||
default: op
|
||||
test.*:
|
||||
description: Wildcard permission
|
||||
default: op
|
||||
children:
|
||||
test.foo: true
|
||||
api-version: '1.13'
|
||||
```
|
||||
|
||||
As of version 1.2.0-SNAPSHOT you can now also use the ```@Command``` and ```@Permission```
|
||||
annotations on classes that implement CommandExecutor.
|
||||
|
||||
For example:
|
||||
```
|
||||
@Command(name = "TestCommand", aliases = "testext2", permission = "test.testext", permissionMessage = "Oopsy!", usage = "/testext test test")
|
||||
@Permission(name = "test.testext", desc = "Provides access to /textext command", defaultValue = PermissionDefault.TRUE)
|
||||
public class TestCommand implements CommandExecutor {
|
||||
```
|
||||
|
||||
As of version 1.2.0-SNAPSHOT the ```@ApiVersion``` annotation was introduced to bring compatibility for
|
||||
Bukkit's new ```api-version``` plugin.yml option. This defaults to ```ApiVersion.Target.DEFAULT``` if not specified or included.
|
||||
All pre-1.13 plugins MUST use ```ApiVersion.Target.DEFAULT``` in order for the plugin to be loaded correctly.
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -10,7 +10,7 @@
|
|||
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>plugin-annotations</artifactId>
|
||||
<version>1.1.0-SNAPSHOT</version>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Plugin Annotations</name>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
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());
|
||||
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;
|
||||
}
|
||||
|
||||
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 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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() );
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 {};
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,6 +19,6 @@ public @interface Description {
|
|||
/**
|
||||
* A human friendly description of the functionality this plugin provides.
|
||||
*/
|
||||
String desc();
|
||||
String value();
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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 {}
|
|
@ -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();
|
||||
}
|
|
@ -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 {}
|
|
@ -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";
|
||||
}
|
|
@ -19,5 +19,5 @@ public @interface Website {
|
|||
/**
|
||||
* The url to the website where a user can download this plugin.
|
||||
*/
|
||||
String url();
|
||||
String value();
|
||||
}
|
||||
|
|
|
@ -21,5 +21,5 @@ public @interface Author {
|
|||
/**
|
||||
* The name of the person who developed this plugin.
|
||||
*/
|
||||
String name();
|
||||
String value();
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue