Compare commits
20
Commits
main
...
chore/checkstyle
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
64107df246 | ||
|
|
5e2d34c096 | ||
|
|
a0bec2312c | ||
|
|
849d6107a9 | ||
|
|
1c35f64788 | ||
|
|
cb005e4559 | ||
|
|
08370f6416 | ||
|
|
6d981e0f10 | ||
|
|
ed5d703779 | ||
|
|
7920bd0568 | ||
|
|
7a85e6cdfc | ||
|
|
d86abcf028 | ||
|
|
d6c754a520 | ||
|
|
af3882662f | ||
|
|
8078445228 | ||
|
|
3af3c9b773 | ||
|
|
a95608398b | ||
|
|
d7799ff7e8 | ||
|
|
6c6e412974 | ||
|
|
b27cc5ddd4 |
No files matched your search
+16
-1
@@ -8,6 +8,7 @@ ij_any_block_comment_add_space = false
|
||||
ij_any_block_comment_at_first_column = false
|
||||
ij_any_line_comment_at_first_column = false
|
||||
ij_any_line_comment_add_space = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.tiny]
|
||||
indent_style=tab
|
||||
@@ -18,7 +19,7 @@ end_of_line=crlf
|
||||
[*.yml]
|
||||
indent_size=2
|
||||
|
||||
[*.patch]
|
||||
[{*.patch,*.md}]
|
||||
trim_trailing_whitespace=false
|
||||
|
||||
[*.java]
|
||||
@@ -27,12 +28,26 @@ ij_java_class_count_to_use_import_on_demand = 999999
|
||||
ij_java_insert_inner_class_imports = false
|
||||
ij_java_names_count_to_use_import_on_demand = 999999
|
||||
ij_java_imports_layout = *,|,$*
|
||||
ij_java_layout_static_imports_separately = true
|
||||
ij_java_generate_final_locals = true
|
||||
ij_java_generate_final_parameters = true
|
||||
ij_java_method_parameters_new_line_after_left_paren = true
|
||||
ij_java_method_parameters_right_paren_on_new_line = true
|
||||
ij_java_use_fq_class_names = false
|
||||
ij_java_class_names_in_javadoc = 1
|
||||
# javadoc
|
||||
ij_java_doc_add_blank_line_after_description = true
|
||||
ij_java_doc_add_blank_line_after_param_comments = false
|
||||
ij_java_doc_add_blank_line_after_return = false
|
||||
ij_java_doc_add_p_tag_on_empty_lines = true
|
||||
ij_java_doc_align_exception_comments = true
|
||||
ij_java_doc_align_param_comments = true
|
||||
ij_java_doc_do_not_wrap_if_one_line = false
|
||||
ij_java_doc_enable_formatting = true
|
||||
ij_java_doc_enable_leading_asterisks = true
|
||||
ij_java_doc_indent_on_continuation = true
|
||||
ij_java_doc_param_description_on_new_line = false
|
||||
ij_java_doc_use_throws_not_exception_tag = true
|
||||
|
||||
[paper-server/src/minecraft/java/**/*.java]
|
||||
ij_java_use_fq_class_names = true
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ import java.nio.file.Path
|
||||
import kotlin.random.Random
|
||||
|
||||
plugins {
|
||||
id("io.papermc.paperweight.core") version "2.0.0-beta.10" apply false
|
||||
id("io.papermc.paperweight.core") version "2.0.0-SNAPSHOT" apply false
|
||||
}
|
||||
|
||||
subprojects {
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
<!DOCTYPE module PUBLIC
|
||||
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
|
||||
"https://checkstyle.org/dtds/configuration_1_3.dtd">
|
||||
<module name="Checker">
|
||||
<module name="SuppressionFilter">
|
||||
<property name="file" value="${config_loc}/suppressions.xml"/>
|
||||
<property name="optional" value="false"/>
|
||||
</module>
|
||||
|
||||
<!--Single Suppression Filters-->
|
||||
<module name="SuppressionSingleFilter">
|
||||
<!--Suppresses warnings except for common TYPE_USE that should be on same line-->
|
||||
<property name="checks" value="AnnotationOnSameLine"/>
|
||||
<property name="message" value="^Annotation '(?!(${type_use_annotations}))"/>
|
||||
</module>
|
||||
<module name="SuppressionSingleFilter">
|
||||
<property name="checks" value="Javadoc(Method|Type)"/>
|
||||
<!--[A-Z].* check is for java annotations inside code blocks inside javadocs-->
|
||||
<property name="message" value="^Unknown tag '(${custom_javadoc_tags}|[A-Z].*)'.$"/>
|
||||
</module>
|
||||
|
||||
<!--Javadoc Comments-->
|
||||
<module name="JavadocPackage"/>
|
||||
<!--Misc-->
|
||||
<module name="NewlineAtEndOfFile"/>
|
||||
<module name="OrderedProperties"/>
|
||||
<!--Whitespace-->
|
||||
<module name="FileTabCharacter"/>
|
||||
|
||||
<module name="TreeWalker">
|
||||
<module name="SuppressionXpathFilter">
|
||||
<property name="file" value="${config_loc}/xpath-suppressions.xml"/>
|
||||
<property name="optional" value="false"/>
|
||||
</module>
|
||||
|
||||
<!--Annotations-->
|
||||
<module name="AnnotationOnSameLine">
|
||||
<!--matches all annotations, but most are suppressed in above-->
|
||||
<property name="tokens" value="METHOD_DEF"/>
|
||||
</module>
|
||||
<module name="AnnotationUseStyle"/>
|
||||
<module name="MissingDeprecated"/>
|
||||
|
||||
<!--Block Checks-->
|
||||
<module name="AvoidNestedBlocks"/>
|
||||
<module name="EmptyBlock"/>
|
||||
<module name="LeftCurly"/>
|
||||
<module name="RightCurly"/>
|
||||
<module name="OneTopLevelClass"/>
|
||||
<module name="SealedShouldHavePermitsList"/>
|
||||
|
||||
<!--Class Design-->
|
||||
<module name="FinalClass"/>
|
||||
<module name="HideUtilityClassConstructor"/>
|
||||
<module name="InterfaceIsType"/>
|
||||
|
||||
<!--Coding-->
|
||||
<module name="ArrayTrailingComma"/>
|
||||
<module name="AvoidDoubleBraceInitialization"/>
|
||||
<module name="AvoidNoArgumentSuperConstructorCall"/>
|
||||
<module name="ConstructorsDeclarationGrouping"/>
|
||||
<module name="CovariantEquals"/>
|
||||
<module name="DeclarationOrder"/>
|
||||
<module name="DefaultComesLast"/>
|
||||
<module name="EmptyStatement"/>
|
||||
<module name="EqualsAvoidNull"/>
|
||||
<module name="EqualsHashCode"/>
|
||||
<module name="FallThrough"/>
|
||||
<!--<module name="FinalLocalVariable">
|
||||
<property name="validateEnhancedForLoopVariable" value="true"/>
|
||||
<property name="validateUnnamedVariables" value="true"/>
|
||||
<!–TODO atm, PARAMETER_DEF doesn't seem to function inside interfaces–>
|
||||
<!–https://github.com/checkstyle/checkstyle/issues/16081–>
|
||||
<property name="tokens" value="PARAMETER_DEF,VARIABLE_DEF"/>
|
||||
</module>-->
|
||||
<module name="IllegalToken"/> <!--just labels by default-->
|
||||
<module name="IllegalType"/>
|
||||
<module name="RequireThis">
|
||||
<property name="validateOnlyOverlapping" value="false"/>
|
||||
</module>
|
||||
<module name="SimplifyBooleanExpression"/>
|
||||
<module name="SimplifyBooleanReturn"/>
|
||||
<module name="StringLiteralEquality"/>
|
||||
<module name="UnnecessarySemicolonAfterOuterTypeDeclaration"/>
|
||||
<module name="UnnecessarySemicolonAfterTypeMemberDeclaration"/>
|
||||
<module name="UnnecessarySemicolonInEnumeration"/>
|
||||
<module name="UnnecessarySemicolonInTryWithResources"/>
|
||||
<module name="UnusedCatchParameterShouldBeUnnamed"/>
|
||||
<module name="UnusedLambdaParameterShouldBeUnnamed"/>
|
||||
<module name="UnusedLocalVariable"/>
|
||||
<module name="WhenShouldBeUsed"/>
|
||||
|
||||
<!--Headers--> <!--N/A-->
|
||||
|
||||
<!--Imports-->
|
||||
<module name="AvoidStarImport"/>
|
||||
<module name="CustomImportOrder">
|
||||
<property name="customImportOrderRules" value="THIRD_PARTY_PACKAGE,STATIC"/>
|
||||
<property name="standardPackageRegExp" value="^$"/>
|
||||
<property name="sortImportsInGroupAlphabetically" value="true"/>
|
||||
</module>
|
||||
<module name="IllegalImport">
|
||||
<property name="regexp" value="true"/>
|
||||
<!--checker-qual nullability-->
|
||||
<property name="illegalClasses" value="org\.checkerframework\.checker\.nullness\.qual\.(Nullable|NonNull|DefaultQualifier)"/>
|
||||
<!--jetbrains nullability-->
|
||||
<property name="illegalClasses" value="org\.jetbrains\.annotations\.(NotNull|Nullable|NotNullByDefault)"/>
|
||||
<!--javax nullability-->
|
||||
</module>
|
||||
<module name="IllegalImport">
|
||||
<property name="regexp" value="true"/>
|
||||
<!--attempts to guard against nested imports (by looking for capital letters in imports)-->
|
||||
<property name="illegalClasses" value="^[^\.A-Z]+(\.[^\.A-Z]+)+?(\.[A-Z][^\.]*)(\.[A-Z][^\.]*)+$"/>
|
||||
<message key="import.illegal" value="Illegal nested import - {0}"/>
|
||||
</module>
|
||||
<module name="RedundantImport"/>
|
||||
<module name="UnusedImports"/>
|
||||
|
||||
<!--Javadoc Comments-->
|
||||
<module name="AtclauseOrder">
|
||||
<property name="tagOrder" value="@param, @return, @throws, @see, @deprecated, @hidden"/>
|
||||
</module>
|
||||
<module name="InvalidJavadocPosition"/>
|
||||
<module name="JavadocBlockTagLocation"/>
|
||||
<module name="JavadocContentLocation"/>
|
||||
<module name="JavadocLeadingAsteriskAlign"/>
|
||||
<module name="JavadocMethod">
|
||||
<!--checks all, but doesn't require. If we have a doc, it should be valid-->
|
||||
<property name="validateThrows" value="true"/>
|
||||
</module>
|
||||
<module name="JavadocMissingLeadingAsterisk"/>
|
||||
<module name="JavadocMissingWhitespaceAfterAsterisk"/>
|
||||
<module name="JavadocStyle"/> <!--checks all, but doesn't require. If we have a doc, it should be valid-->
|
||||
<module name="JavadocTagContinuationIndentation"/>
|
||||
<module name="JavadocType"/> <!--checks all, but doesn't require. If we have a doc, it should be valid-->
|
||||
<module name="MissingJavadocMethod">
|
||||
<property name="allowedAnnotations" value="Override, ApiStatus.Internal"/>
|
||||
<property name="ignoreMethodNamesRegex" value="^getHandlerList$"/>
|
||||
</module>
|
||||
<module name="MissingJavadocPackage"/>
|
||||
<module name="MissingJavadocType">
|
||||
<property name="skipAnnotations" value="Generated, ApiStatus.Internal" />
|
||||
</module>
|
||||
<module name="NonEmptyAtclauseDescription"/>
|
||||
<module name="RequireEmptyLineBeforeBlockTagGroup"/>
|
||||
|
||||
<!--Metrics--> <!--N/A-->
|
||||
|
||||
<!--Miscellaneous-->
|
||||
<module name="ArrayTypeStyle"/>
|
||||
<module name="AvoidEscapedUnicodeCharacters"/>
|
||||
<module name="CommentsIndentation"/>
|
||||
<module name="FinalParameters"/>
|
||||
|
||||
<module name="NoCodeInFile"/>
|
||||
<module name="OuterTypeFilename"/>
|
||||
<module name="UpperEll"/>
|
||||
|
||||
<!--Modifiers-->
|
||||
<module name="ModifierOrder"/>
|
||||
<module name="RedundantModifier"/>
|
||||
|
||||
<!--Naming Conventions-->
|
||||
<module name="AbbreviationAsWordInName">
|
||||
<property name="allowedAbbreviations" value="JSON,UUID"/>
|
||||
<property name="ignoreFinal" value="false"/>
|
||||
</module>
|
||||
<module name="ClassTypeParameterName"/>
|
||||
<module name="ConstantName"/>
|
||||
<module name="IllegalIdentifierName"/>
|
||||
<module name="InterfaceTypeParameterName"/>
|
||||
<module name="LambdaParameterName"/>
|
||||
<module name="LocalFinalVariableName"/>
|
||||
<module name="LocalVariableName"/>
|
||||
<module name="MemberName"/>
|
||||
<module name="MethodName"/>
|
||||
<module name="MethodTypeParameterName"/>
|
||||
<module name="PackageName">
|
||||
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
|
||||
</module>
|
||||
<module name="ParameterName"/>
|
||||
<module name="PatternVariableName"/>
|
||||
<module name="RecordComponentName"/>
|
||||
<module name="RecordTypeParameterName"/>
|
||||
<module name="StaticVariableName"/>
|
||||
<module name="TypeName"/>
|
||||
|
||||
<!--Regexp--> <!--N/A-->
|
||||
<!--Size Violations--> <!--N/A-->
|
||||
|
||||
<!--Whitespace-->
|
||||
<module name="EmptyForInitializerPad"/>
|
||||
<module name="EmptyForIteratorPad"/>
|
||||
<module name="EmptyLineSeparator">
|
||||
<property name="allowNoEmptyLineBetweenFields" value="true"/>
|
||||
<property name="tokens" value="IMPORT,STATIC_IMPORT,CLASS_DEF,INTERFACE_DEF,ENUM_DEF,STATIC_INIT,INSTANCE_INIT,METHOD_DEF,CTOR_DEF,VARIABLE_DEF,RECORD_DEF,COMPACT_CTOR_DEF"/>
|
||||
</module>
|
||||
<module name="GenericWhitespace"/>
|
||||
<module name="MethodParamPad"/>
|
||||
<module name="NoLineWrap"/> <!--just imports and packages-->
|
||||
<module name="NoWhitespaceAfter"/>
|
||||
<module name="NoWhitespaceBefore"/>
|
||||
<module name="NoWhitespaceBeforeCaseDefaultColon"/>
|
||||
<module name="ParenPad"/>
|
||||
<module name="SingleSpaceSeparator"/>
|
||||
<module name="TypecastParenPad"/>
|
||||
<module name="WhitespaceAfter"/>
|
||||
<module name="WhitespaceAround"/>
|
||||
|
||||
<!--Custom-->
|
||||
<module name="JavadocAlignParameterDescription"/>
|
||||
<module name="NullabilityAnnotations"/>
|
||||
</module>
|
||||
</module>
|
||||
@@ -0,0 +1,182 @@
|
||||
paper-api-generator/generated/com/destroystokyo/paper/entity/ai/
|
||||
paper-api-generator/generated/io/papermc/paper/registry/keys/
|
||||
paper-api-generator/generated/io/papermc/paper/registry/keys/tags/
|
||||
paper-api/src/main/java/co/aikar/timings/
|
||||
paper-api/src/main/java/co/aikar/util/
|
||||
paper-api/src/main/java/com/destroystokyo/paper/
|
||||
paper-api/src/main/java/com/destroystokyo/paper/block/
|
||||
paper-api/src/main/java/com/destroystokyo/paper/brigadier/
|
||||
paper-api/src/main/java/com/destroystokyo/paper/entity/
|
||||
paper-api/src/main/java/com/destroystokyo/paper/entity/ai/
|
||||
paper-api/src/main/java/com/destroystokyo/paper/entity/villager/
|
||||
paper-api/src/main/java/com/destroystokyo/paper/event/block/
|
||||
paper-api/src/main/java/com/destroystokyo/paper/event/brigadier/
|
||||
paper-api/src/main/java/com/destroystokyo/paper/event/entity/
|
||||
paper-api/src/main/java/com/destroystokyo/paper/event/inventory/
|
||||
paper-api/src/main/java/com/destroystokyo/paper/event/player/
|
||||
paper-api/src/main/java/com/destroystokyo/paper/event/profile/
|
||||
paper-api/src/main/java/com/destroystokyo/paper/event/server/
|
||||
paper-api/src/main/java/com/destroystokyo/paper/exception/
|
||||
paper-api/src/main/java/com/destroystokyo/paper/inventory/meta/
|
||||
paper-api/src/main/java/com/destroystokyo/paper/loottable/
|
||||
paper-api/src/main/java/com/destroystokyo/paper/network/
|
||||
paper-api/src/main/java/com/destroystokyo/paper/profile/
|
||||
paper-api/src/main/java/com/destroystokyo/paper/util/
|
||||
paper-api/src/main/java/com/destroystokyo/paper/utils/
|
||||
paper-api/src/main/java/io/papermc/paper/advancement/
|
||||
paper-api/src/main/java/io/papermc/paper/annotation/
|
||||
paper-api/src/main/java/io/papermc/paper/ban/
|
||||
paper-api/src/main/java/io/papermc/paper/block/
|
||||
paper-api/src/main/java/io/papermc/paper/block/fluid/
|
||||
paper-api/src/main/java/io/papermc/paper/block/fluid/type/
|
||||
paper-api/src/main/java/io/papermc/paper/brigadier/
|
||||
paper-api/src/main/java/io/papermc/paper/chat/
|
||||
paper-api/src/main/java/io/papermc/paper/command/
|
||||
paper-api/src/main/java/io/papermc/paper/command/brigadier/
|
||||
paper-api/src/main/java/io/papermc/paper/command/brigadier/argument/
|
||||
paper-api/src/main/java/io/papermc/paper/command/brigadier/argument/predicate/
|
||||
paper-api/src/main/java/io/papermc/paper/command/brigadier/argument/range/
|
||||
paper-api/src/main/java/io/papermc/paper/command/brigadier/argument/resolvers/
|
||||
paper-api/src/main/java/io/papermc/paper/command/brigadier/argument/resolvers/selector/
|
||||
paper-api/src/main/java/io/papermc/paper/datacomponent/
|
||||
paper-api/src/main/java/io/papermc/paper/datacomponent/item/
|
||||
paper-api/src/main/java/io/papermc/paper/datacomponent/item/consumable/
|
||||
paper-api/src/main/java/io/papermc/paper/datapack/
|
||||
paper-api/src/main/java/io/papermc/paper/enchantments/
|
||||
paper-api/src/main/java/io/papermc/paper/entity/
|
||||
paper-api/src/main/java/io/papermc/paper/event/block/
|
||||
paper-api/src/main/java/io/papermc/paper/event/entity/
|
||||
paper-api/src/main/java/io/papermc/paper/event/executor/
|
||||
paper-api/src/main/java/io/papermc/paper/event/packet/
|
||||
paper-api/src/main/java/io/papermc/paper/event/player/
|
||||
paper-api/src/main/java/io/papermc/paper/event/server/
|
||||
paper-api/src/main/java/io/papermc/paper/event/world/
|
||||
paper-api/src/main/java/io/papermc/paper/event/world/border/
|
||||
paper-api/src/main/java/io/papermc/paper/generated/
|
||||
paper-api/src/main/java/io/papermc/paper/inventory/
|
||||
paper-api/src/main/java/io/papermc/paper/inventory/tooltip/
|
||||
paper-api/src/main/java/io/papermc/paper/item/
|
||||
paper-api/src/main/java/io/papermc/paper/math/
|
||||
paper-api/src/main/java/io/papermc/paper/persistence/
|
||||
paper-api/src/main/java/io/papermc/paper/plugin/
|
||||
paper-api/src/main/java/io/papermc/paper/plugin/bootstrap/
|
||||
paper-api/src/main/java/io/papermc/paper/plugin/configuration/
|
||||
paper-api/src/main/java/io/papermc/paper/plugin/lifecycle/event/
|
||||
paper-api/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/
|
||||
paper-api/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/
|
||||
paper-api/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/
|
||||
paper-api/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/
|
||||
paper-api/src/main/java/io/papermc/paper/plugin/loader/
|
||||
paper-api/src/main/java/io/papermc/paper/plugin/loader/library/
|
||||
paper-api/src/main/java/io/papermc/paper/plugin/loader/library/impl/
|
||||
paper-api/src/main/java/io/papermc/paper/plugin/provider/classloader/
|
||||
paper-api/src/main/java/io/papermc/paper/plugin/provider/entrypoint/
|
||||
paper-api/src/main/java/io/papermc/paper/plugin/provider/util/
|
||||
paper-api/src/main/java/io/papermc/paper/potion/
|
||||
paper-api/src/main/java/io/papermc/paper/registry/
|
||||
paper-api/src/main/java/io/papermc/paper/registry/data/
|
||||
paper-api/src/main/java/io/papermc/paper/registry/event/
|
||||
paper-api/src/main/java/io/papermc/paper/registry/event/type/
|
||||
paper-api/src/main/java/io/papermc/paper/registry/set/
|
||||
paper-api/src/main/java/io/papermc/paper/registry/tag/
|
||||
paper-api/src/main/java/io/papermc/paper/scoreboard/numbers/
|
||||
paper-api/src/main/java/io/papermc/paper/tag/
|
||||
paper-api/src/main/java/io/papermc/paper/text/
|
||||
paper-api/src/main/java/io/papermc/paper/threadedregions/scheduler/
|
||||
paper-api/src/main/java/io/papermc/paper/util/
|
||||
paper-api/src/main/java/io/papermc/paper/world/
|
||||
paper-api/src/main/java/io/papermc/paper/world/flag/
|
||||
paper-api/src/main/java/org/bukkit/
|
||||
paper-api/src/main/java/org/bukkit/advancement/
|
||||
paper-api/src/main/java/org/bukkit/attribute/
|
||||
paper-api/src/main/java/org/bukkit/ban/
|
||||
paper-api/src/main/java/org/bukkit/block/
|
||||
paper-api/src/main/java/org/bukkit/block/banner/
|
||||
paper-api/src/main/java/org/bukkit/block/data/
|
||||
paper-api/src/main/java/org/bukkit/block/data/type/
|
||||
paper-api/src/main/java/org/bukkit/block/sign/
|
||||
paper-api/src/main/java/org/bukkit/block/spawner/
|
||||
paper-api/src/main/java/org/bukkit/block/structure/
|
||||
paper-api/src/main/java/org/bukkit/boss/
|
||||
paper-api/src/main/java/org/bukkit/command/
|
||||
paper-api/src/main/java/org/bukkit/command/defaults/
|
||||
paper-api/src/main/java/org/bukkit/configuration/
|
||||
paper-api/src/main/java/org/bukkit/configuration/file/
|
||||
paper-api/src/main/java/org/bukkit/configuration/serialization/
|
||||
paper-api/src/main/java/org/bukkit/conversations/
|
||||
paper-api/src/main/java/org/bukkit/damage/
|
||||
paper-api/src/main/java/org/bukkit/enchantments/
|
||||
paper-api/src/main/java/org/bukkit/entity/
|
||||
paper-api/src/main/java/org/bukkit/entity/boat/
|
||||
paper-api/src/main/java/org/bukkit/entity/memory/
|
||||
paper-api/src/main/java/org/bukkit/entity/minecart/
|
||||
paper-api/src/main/java/org/bukkit/event/
|
||||
paper-api/src/main/java/org/bukkit/event/block/
|
||||
paper-api/src/main/java/org/bukkit/event/command/
|
||||
paper-api/src/main/java/org/bukkit/event/enchantment/
|
||||
paper-api/src/main/java/org/bukkit/event/entity/
|
||||
paper-api/src/main/java/org/bukkit/event/hanging/
|
||||
paper-api/src/main/java/org/bukkit/event/inventory/
|
||||
paper-api/src/main/java/org/bukkit/event/player/
|
||||
paper-api/src/main/java/org/bukkit/event/raid/
|
||||
paper-api/src/main/java/org/bukkit/event/server/
|
||||
paper-api/src/main/java/org/bukkit/event/vehicle/
|
||||
paper-api/src/main/java/org/bukkit/event/weather/
|
||||
paper-api/src/main/java/org/bukkit/event/world/
|
||||
paper-api/src/main/java/org/bukkit/generator/
|
||||
paper-api/src/main/java/org/bukkit/generator/structure/
|
||||
paper-api/src/main/java/org/bukkit/help/
|
||||
paper-api/src/main/java/org/bukkit/inventory/
|
||||
paper-api/src/main/java/org/bukkit/inventory/meta/
|
||||
paper-api/src/main/java/org/bukkit/inventory/meta/components/
|
||||
paper-api/src/main/java/org/bukkit/inventory/meta/tags/
|
||||
paper-api/src/main/java/org/bukkit/inventory/meta/trim/
|
||||
paper-api/src/main/java/org/bukkit/inventory/recipe/
|
||||
paper-api/src/main/java/org/bukkit/inventory/view/
|
||||
paper-api/src/main/java/org/bukkit/loot/
|
||||
paper-api/src/main/java/org/bukkit/map/
|
||||
paper-api/src/main/java/org/bukkit/material/
|
||||
paper-api/src/main/java/org/bukkit/material/types/
|
||||
paper-api/src/main/java/org/bukkit/metadata/
|
||||
paper-api/src/main/java/org/bukkit/packs/
|
||||
paper-api/src/main/java/org/bukkit/permissions/
|
||||
paper-api/src/main/java/org/bukkit/persistence/
|
||||
paper-api/src/main/java/org/bukkit/plugin/
|
||||
paper-api/src/main/java/org/bukkit/plugin/java/
|
||||
paper-api/src/main/java/org/bukkit/plugin/messaging/
|
||||
paper-api/src/main/java/org/bukkit/potion/
|
||||
paper-api/src/main/java/org/bukkit/profile/
|
||||
paper-api/src/main/java/org/bukkit/projectiles/
|
||||
paper-api/src/main/java/org/bukkit/scheduler/
|
||||
paper-api/src/main/java/org/bukkit/scoreboard/
|
||||
paper-api/src/main/java/org/bukkit/spawner/
|
||||
paper-api/src/main/java/org/bukkit/structure/
|
||||
paper-api/src/main/java/org/bukkit/tag/
|
||||
paper-api/src/main/java/org/bukkit/util/
|
||||
paper-api/src/main/java/org/bukkit/util/io/
|
||||
paper-api/src/main/java/org/bukkit/util/noise/
|
||||
paper-api/src/main/java/org/bukkit/util/permissions/
|
||||
paper-api/src/main/java/org/spigotmc/
|
||||
paper-api/src/main/java/org/spigotmc/event/player/
|
||||
paper-api/src/test/java/com/destroystokyo/paper/
|
||||
paper-api/src/test/java/io/papermc/paper/
|
||||
paper-api/src/test/java/io/papermc/paper/adventure/
|
||||
paper-api/src/test/java/io/papermc/paper/registry/
|
||||
paper-api/src/test/java/io/papermc/paper/testing/
|
||||
paper-api/src/test/java/io/papermc/paper/util/
|
||||
paper-api/src/test/java/org/bukkit/
|
||||
paper-api/src/test/java/org/bukkit/configuration/
|
||||
paper-api/src/test/java/org/bukkit/configuration/file/
|
||||
paper-api/src/test/java/org/bukkit/conversations/
|
||||
paper-api/src/test/java/org/bukkit/entity/memory/
|
||||
paper-api/src/test/java/org/bukkit/event/
|
||||
paper-api/src/test/java/org/bukkit/materials/
|
||||
paper-api/src/test/java/org/bukkit/metadata/
|
||||
paper-api/src/test/java/org/bukkit/plugin/
|
||||
paper-api/src/test/java/org/bukkit/plugin/messaging/
|
||||
paper-api/src/test/java/org/bukkit/scoreboard/
|
||||
paper-api/src/test/java/org/bukkit/support/
|
||||
paper-api/src/test/java/org/bukkit/support/provider/
|
||||
paper-api/src/test/java/org/bukkit/support/test/
|
||||
paper-api/src/test/java/org/bukkit/util/
|
||||
paper-api/src/test/java/org/bukkit/util/io/
|
||||
@@ -0,0 +1,6 @@
|
||||
<!DOCTYPE suppressions PUBLIC
|
||||
"-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN"
|
||||
"https://checkstyle.org/dtds/suppressions_1_2.dtd">
|
||||
<suppressions>
|
||||
<suppress checks="MissingJavadoc.*" files="src[\\/]test[\\/]java[^\\/]*[\\/].*"/>
|
||||
</suppressions>
|
||||
@@ -0,0 +1,9 @@
|
||||
NonNull
|
||||
NotNull
|
||||
Nullable
|
||||
UnknownNullability
|
||||
Unmodifiable
|
||||
UnmodifiableView
|
||||
Range
|
||||
Positive
|
||||
NonNegative
|
||||
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE suppressions PUBLIC
|
||||
"-//Checkstyle//DTD SuppressionXpathFilter Experimental Configuration 1.2//EN"
|
||||
"https://checkstyle.org/dtds/suppressions_1_2_xpath_experimental.dtd">
|
||||
<suppressions>
|
||||
<!--ignores all checks for @Deprecated(forRemoval=*) children-->
|
||||
<suppress-xpath checks=".*" query="//*[MODIFIERS/ANNOTATION[(@text = 'Deprecated' or *[@text = 'Deprecated'] and ANNOTATION_MEMBER_VALUE_PAIR/IDENT[@text='forRemoval'])]]/descendant-or-self::node()"/>
|
||||
<!--special case to ignore extra checks outside the root CLASS_DEF if the root CLASS_DEF is marked as deprecated for removal-->
|
||||
<suppress-xpath checks=".*" query="/COMPILATION_UNIT[CLASS_DEF/MODIFIERS/ANNOTATION[IDENT[@text = 'Deprecated'] and ANNOTATION_MEMBER_VALUE_PAIR/IDENT[@text='forRemoval']]]/descendant-or-self::node()"/>
|
||||
<!--ignores MissingJavadoc for ApiStatus.Internal children-->
|
||||
<suppress-xpath checks="MissingJavadoc(Method|Type)" query="//*[MODIFIERS/ANNOTATION/DOT[@text = 'Internal' or *[@text = 'Internal']]]/descendant-or-self::node()"/>
|
||||
|
||||
<!--skip for private classes-->
|
||||
<suppress-xpath checks="FinalClass" query="//CLASS_DEF[MODIFIERS/LITERAL_PRIVATE]"/>
|
||||
|
||||
<!--skip for classes inside of methods-->
|
||||
<suppress-xpath checks="HideUtilityClassConstructor|MissingJavadoc(Method|Type)" query="//CLASS_DEF[ancestor::METHOD_DEF]"/>
|
||||
</suppressions>
|
||||
@@ -1,7 +1,12 @@
|
||||
import io.papermc.paperweight.checkstyle.JavadocTag
|
||||
import io.papermc.paperweight.checkstyle.PaperCheckstyleTask
|
||||
import io.papermc.paperweight.checkstyle.setCustomJavadocTags
|
||||
|
||||
plugins {
|
||||
`java-library`
|
||||
`maven-publish`
|
||||
idea
|
||||
id("io.papermc.paperweight.paper-checkstyle")
|
||||
}
|
||||
|
||||
java {
|
||||
@@ -9,6 +14,22 @@ java {
|
||||
withJavadocJar()
|
||||
}
|
||||
|
||||
val customJavadocTags = setOf(
|
||||
JavadocTag("apiNote", "a", "API Note:"),
|
||||
)
|
||||
|
||||
paperCheckstyle {
|
||||
val packagesToSkipSource = providers.fileContents(projectLocalCheckstyleConfig.file("packages.txt")).asText.map { it.trim().split("\n").toSet() }
|
||||
val typeUseAnnotationsProvider = providers.fileContents(projectLocalCheckstyleConfig.file("type-use-annotations.txt")).asText.map { it.trim().split("\n").toSet() }
|
||||
|
||||
directoriesToSkip.set(packagesToSkipSource)
|
||||
typeUseAnnotations.set(typeUseAnnotationsProvider)
|
||||
}
|
||||
|
||||
tasks.withType<PaperCheckstyleTask> {
|
||||
setCustomJavadocTags(customJavadocTags)
|
||||
}
|
||||
|
||||
val annotationsVersion = "26.0.1"
|
||||
val bungeeCordChatVersion = "1.20-R0.2"
|
||||
val adventureVersion = "4.18.0"
|
||||
@@ -39,6 +60,7 @@ abstract class MockitoAgentProvider : CommandLineArgumentProvider {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
checkstyle(project(":paper-api:custom-checkstyle"))
|
||||
|
||||
// api dependencies are listed transitively to API consumers
|
||||
api("com.google.guava:guava:33.3.1-jre")
|
||||
@@ -190,7 +212,7 @@ tasks.withType<Javadoc> {
|
||||
"https://javadoc.io/doc/org.apache.logging.log4j/log4j-api/$log4jVersion/",
|
||||
"https://javadoc.io/doc/org.apache.maven.resolver/maven-resolver-api/1.7.3",
|
||||
)
|
||||
options.tags("apiNote:a:API Note:")
|
||||
options.tags(customJavadocTags.map { it.toOptionString() })
|
||||
|
||||
inputs.files(apiAndDocs).ignoreEmptyDirectories().withPropertyName(apiAndDocs.name + "-configuration")
|
||||
val apiAndDocsElements = apiAndDocs.elements
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
plugins {
|
||||
java
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("com.puppycrawl.tools:checkstyle:10.21.1")
|
||||
implementation("org.jspecify:jspecify:1.0.0")
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package io.papermc.checkstyle;
|
||||
|
||||
import com.puppycrawl.tools.checkstyle.api.DetailAST;
|
||||
import com.puppycrawl.tools.checkstyle.api.DetailNode;
|
||||
import com.puppycrawl.tools.checkstyle.utils.JavadocUtil;
|
||||
import com.puppycrawl.tools.checkstyle.utils.TokenUtil;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Utility class containing utility methods for custom checkstyle checks.
|
||||
*/
|
||||
public final class Util {
|
||||
|
||||
private Util() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the previous sibling of the given node with the given type.
|
||||
*
|
||||
* @param node the node
|
||||
* @param type the type
|
||||
* @return the previous sibling with the given type, or {@code null} if not found
|
||||
*/
|
||||
public static @Nullable DetailNode getPreviousSibling(final DetailNode node, final int type) {
|
||||
DetailNode sibling = JavadocUtil.getPreviousSibling(node);
|
||||
while (sibling != null && sibling.getType() != type) {
|
||||
sibling = JavadocUtil.getPreviousSibling(sibling);
|
||||
}
|
||||
return sibling;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next sibling of the given node with the given type.
|
||||
*
|
||||
* @param node the node
|
||||
* @param type the type
|
||||
* @return the next sibling with the given type, or {@code null} if not found
|
||||
*/
|
||||
public static @Nullable DetailAST getNextSibling(final DetailAST node, final int type) {
|
||||
DetailAST sibling = node.getNextSibling();
|
||||
while (sibling != null && sibling.getType() != type) {
|
||||
sibling = sibling.getNextSibling();
|
||||
}
|
||||
return sibling;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the enclosing type declaration of the given node.
|
||||
*
|
||||
* @param node the node
|
||||
* @return the enclosing type declaration, or {@code null} if not found
|
||||
*/
|
||||
public static @Nullable DetailAST getEnclosingTypeDeclaration(final DetailAST node) {
|
||||
DetailAST parent = node.getParent();
|
||||
while (parent != null && !TokenUtil.isTypeDeclaration(parent.getType())) {
|
||||
parent = parent.getParent();
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an iterator over the children of the given node with the given type.
|
||||
*
|
||||
* @param ast the node
|
||||
* @param type the type
|
||||
* @return the iterator
|
||||
*/
|
||||
public static Iterable<DetailAST> childrenIterator(final DetailAST ast, final int type) {
|
||||
return () -> new Iterator<>() {
|
||||
private @Nullable DetailAST current = TokenUtil.findFirstTokenByPredicate(ast, child -> child.getType() == type).orElse(null);
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return this.current != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DetailAST next() {
|
||||
if (this.current == null) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
final DetailAST result = this.current;
|
||||
this.current = getNextSibling(this.current, type);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
package io.papermc.checkstyle.checks;
|
||||
|
||||
import com.puppycrawl.tools.checkstyle.api.DetailNode;
|
||||
import com.puppycrawl.tools.checkstyle.api.JavadocTokenTypes;
|
||||
import com.puppycrawl.tools.checkstyle.checks.javadoc.AbstractJavadocCheck;
|
||||
import com.puppycrawl.tools.checkstyle.utils.JavadocUtil;
|
||||
import io.papermc.checkstyle.Util;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Checks that parameter descriptions in Javadoc are aligned.
|
||||
*/
|
||||
public final class JavadocAlignParameterDescriptionCheck extends AbstractJavadocCheck {
|
||||
|
||||
@Override
|
||||
public int[] getDefaultJavadocTokens() {
|
||||
return new int[]{JavadocTokenTypes.JAVADOC};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJavadocToken(final DetailNode detailNode) {
|
||||
final List<DetailNode> params = new ArrayList<>();
|
||||
int maxColumn = -1;
|
||||
for (final DetailNode child : detailNode.getChildren()) {
|
||||
final DetailNode paramLiteralNode = JavadocUtil.findFirstToken(child, JavadocTokenTypes.PARAM_LITERAL);
|
||||
if (child.getType() != JavadocTokenTypes.JAVADOC_TAG || paramLiteralNode == null) {
|
||||
continue;
|
||||
}
|
||||
final DetailNode paramDescription = JavadocUtil.getNextSibling(paramLiteralNode, JavadocTokenTypes.DESCRIPTION);
|
||||
maxColumn = Math.max(maxColumn, paramDescription.getColumnNumber());
|
||||
params.add(paramDescription);
|
||||
}
|
||||
|
||||
for (final DetailNode param : params) {
|
||||
if (param.getColumnNumber() != maxColumn) {
|
||||
final DetailNode paramNameNode = Util.getPreviousSibling(param, JavadocTokenTypes.PARAMETER_NAME);
|
||||
if (paramNameNode == null) {
|
||||
continue;
|
||||
}
|
||||
this.log(
|
||||
param.getLineNumber(),
|
||||
param.getColumnNumber() - 1,
|
||||
"Param description for %s should start at column %d".formatted(paramNameNode.getText(), maxColumn)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
package io.papermc.checkstyle.checks;
|
||||
|
||||
import com.puppycrawl.tools.checkstyle.JavaParser;
|
||||
import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
|
||||
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
|
||||
import com.puppycrawl.tools.checkstyle.api.DetailAST;
|
||||
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
|
||||
import io.papermc.checkstyle.Util;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Checks that nullability annotations are present where required.
|
||||
*/
|
||||
public final class NullabilityAnnotationsCheck extends AbstractCheck {
|
||||
|
||||
@Override
|
||||
public int[] getDefaultTokens() {
|
||||
return this.getRequiredTokens();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getAcceptableTokens() {
|
||||
return this.getRequiredTokens();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getRequiredTokens() {
|
||||
return new int[]{
|
||||
TokenTypes.METHOD_DEF,
|
||||
TokenTypes.PARAMETER_DEF,
|
||||
TokenTypes.ANNOTATION_FIELD_DEF,
|
||||
TokenTypes.RECORD_COMPONENT_DEF, // annotations are in ANNOTATIONS token block
|
||||
};
|
||||
}
|
||||
|
||||
private static final Set<String> NULLABILITY_ANNOTATIONS = Set.of("Nullable", "NonNull");
|
||||
|
||||
// for checking for annotations on nested types like "OuterType.@Nullable InnerType"
|
||||
private static boolean typeHasNullabilityAnnotation(final @Nullable DetailAST type) {
|
||||
final DetailAST dot;
|
||||
if (type == null || (dot = type.findFirstToken(TokenTypes.DOT)) == null) {
|
||||
return false;
|
||||
}
|
||||
return hasNullabilityAnnotationChild(dot.findFirstToken(TokenTypes.ANNOTATIONS));
|
||||
}
|
||||
|
||||
private static boolean hasNullabilityAnnotationChild(final @Nullable DetailAST ast) {
|
||||
if (ast == null) {
|
||||
return false;
|
||||
}
|
||||
for (final DetailAST annotation : Util.childrenIterator(ast, TokenTypes.ANNOTATION)) {
|
||||
if (annotation.getChildCount(TokenTypes.IDENT) != 1) {
|
||||
// skip `.` annotations like ApiStatus.Internal as these aren't nullability annotations
|
||||
continue;
|
||||
}
|
||||
final String ident = annotation.findFirstToken(TokenTypes.IDENT).getText();
|
||||
if (NULLABILITY_ANNOTATIONS.contains(ident)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean hasNullabilityAnnotation(final DetailAST inputAst) {
|
||||
if (inputAst.getType() == TokenTypes.RECORD_COMPONENT_DEF && hasNullabilityAnnotationChild(inputAst.findFirstToken(TokenTypes.ANNOTATIONS))) {
|
||||
return true;
|
||||
} else if (inputAst.getType() != TokenTypes.RECORD_COMPONENT_DEF && hasNullabilityAnnotationChild(inputAst.findFirstToken(TokenTypes.MODIFIERS))) {
|
||||
return true;
|
||||
} else {
|
||||
return typeHasNullabilityAnnotation(inputAst.findFirstToken(TokenTypes.TYPE));
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isNullMarkedAnnotation(final DetailAST annotation) {
|
||||
if (annotation.getChildCount(TokenTypes.IDENT) != 1) {
|
||||
return false;
|
||||
}
|
||||
final String ident = annotation.findFirstToken(TokenTypes.IDENT).getText();
|
||||
return "NullMarked".equals(ident);
|
||||
}
|
||||
|
||||
private static boolean isTypeDeclarationNullMarked(final DetailAST typeDeclaration) {
|
||||
final DetailAST modifiers = typeDeclaration.findFirstToken(TokenTypes.MODIFIERS);
|
||||
if (modifiers == null) {
|
||||
return false;
|
||||
}
|
||||
for (final DetailAST annotation : Util.childrenIterator(modifiers, TokenTypes.ANNOTATION)) {
|
||||
if (isNullMarkedAnnotation(annotation)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isPackageInfoNullMarked() {
|
||||
final Path currentPath = Path.of(this.getFilePath());
|
||||
final Path packageInfo = currentPath.getParent().resolve("package-info.java");
|
||||
if (Files.notExists(packageInfo)) {
|
||||
return false;
|
||||
}
|
||||
final DetailAST packageInfoAst;
|
||||
try {
|
||||
packageInfoAst = JavaParser.parseFile(packageInfo.toFile(), JavaParser.Options.WITHOUT_COMMENTS);
|
||||
} catch (final IOException | CheckstyleException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
final DetailAST firstToken = packageInfoAst.findFirstToken(TokenTypes.PACKAGE_DEF);
|
||||
if (firstToken == null) {
|
||||
return false;
|
||||
}
|
||||
final DetailAST annotations = firstToken.findFirstToken(TokenTypes.ANNOTATIONS);
|
||||
for (final DetailAST annotation : Util.childrenIterator(annotations, TokenTypes.ANNOTATION)) {
|
||||
if (isNullMarkedAnnotation(annotation)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitToken(final DetailAST ast) {
|
||||
if (hasNullabilityAnnotation(ast)) {
|
||||
return;
|
||||
}
|
||||
for (DetailAST parentDef = Util.getEnclosingTypeDeclaration(ast); parentDef != null; parentDef = Util.getEnclosingTypeDeclaration(parentDef)) {
|
||||
if (isTypeDeclarationNullMarked(parentDef)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (this.isPackageInfoNullMarked()) {
|
||||
return;
|
||||
}
|
||||
this.recordViolation(ast);
|
||||
}
|
||||
|
||||
private static DetailAST getTypeAstForViolation(final DetailAST inputAst) {
|
||||
final DetailAST typeToken = inputAst.findFirstToken(TokenTypes.TYPE);
|
||||
final DetailAST dot;
|
||||
if (typeToken != null && (dot = typeToken.findFirstToken(TokenTypes.DOT)) != null) {
|
||||
return Objects.requireNonNullElse(dot.getLastChild(), inputAst);
|
||||
}
|
||||
return Objects.requireNonNullElse(typeToken, inputAst);
|
||||
}
|
||||
|
||||
private void recordViolation(final DetailAST ast) {
|
||||
final DetailAST typeAst = getTypeAstForViolation(ast);
|
||||
this.log(typeAst.getLineNo(), typeAst.getColumnNo() - 1, "Missing nullability annotation");
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Custom checkstyle checks for PaperMC projects.
|
||||
*/
|
||||
@NullMarked
|
||||
@SuppressWarnings("unused")
|
||||
package io.papermc.checkstyle.checks;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* This package contains custom checkstyle rules for PaperMC projects.
|
||||
*/
|
||||
@NullMarked
|
||||
package io.papermc.checkstyle;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!DOCTYPE checkstyle-packages PUBLIC
|
||||
"-//Checkstyle//DTD Package Names Configuration 1.0//EN"
|
||||
"https://checkstyle.org/dtds/packages_1_0.dtd">
|
||||
|
||||
<checkstyle-packages>
|
||||
<package name="io.papermc.checkstyle.checks"/>
|
||||
</checkstyle-packages>
|
||||
@@ -3,7 +3,6 @@ package io.papermc.paper;
|
||||
import net.kyori.adventure.util.Services;
|
||||
import org.bukkit.damage.DamageEffect;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Static bridge to the server internals.
|
||||
@@ -12,7 +11,6 @@ import org.jspecify.annotations.NullMarked;
|
||||
* cause issues when called under unexpected circumstances.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@NullMarked
|
||||
public interface InternalAPIBridge {
|
||||
|
||||
/**
|
||||
@@ -36,4 +34,3 @@ public interface InternalAPIBridge {
|
||||
*/
|
||||
DamageEffect getDamageEffect(String key);
|
||||
}
|
||||
|
||||
@@ -6,12 +6,10 @@ import java.util.OptionalInt;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.util.Services;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Information about the current server build.
|
||||
*/
|
||||
@NullMarked
|
||||
@ApiStatus.NonExtendable
|
||||
public interface ServerBuildInfo {
|
||||
/**
|
||||
@@ -30,6 +28,7 @@ public interface ServerBuildInfo {
|
||||
static final Optional<ServerBuildInfo> INSTANCE = Services.service(ServerBuildInfo.class);
|
||||
}
|
||||
//</editor-fold>
|
||||
|
||||
return Holder.INSTANCE.orElseThrow();
|
||||
}
|
||||
|
||||
@@ -47,7 +46,7 @@ public interface ServerBuildInfo {
|
||||
* @return {@code true} if the server supports the specified brand
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
boolean isBrandCompatible(final Key brandId);
|
||||
boolean isBrandCompatible(Key brandId);
|
||||
|
||||
/**
|
||||
* Gets the brand name of the server.
|
||||
@@ -104,7 +103,7 @@ public interface ServerBuildInfo {
|
||||
* @param representation the type of representation
|
||||
* @return a string
|
||||
*/
|
||||
String asString(final StringRepresentation representation);
|
||||
String asString(StringRepresentation representation);
|
||||
|
||||
/**
|
||||
* String representation types.
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Root package for the Paper API.
|
||||
*/
|
||||
@NullMarked
|
||||
package io.papermc.paper;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
@@ -1,370 +0,0 @@
|
||||
package org.bukkit;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.tree.AnnotationNode;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
import org.objectweb.asm.tree.ParameterNode;
|
||||
|
||||
public class AnnotationTest {
|
||||
|
||||
private static final String[] ACCEPTED_ANNOTATIONS = {
|
||||
"Lorg/jetbrains/annotations/Nullable;",
|
||||
"Lorg/jetbrains/annotations/NotNull;",
|
||||
"Lorg/jetbrains/annotations/Contract;",
|
||||
"Lorg/bukkit/UndefinedNullability;",
|
||||
// Paper start
|
||||
"Lorg/checkerframework/checker/nullness/qual/MonotonicNonNull;",
|
||||
"Lorg/checkerframework/checker/nullness/qual/NonNull;",
|
||||
"Lorg/checkerframework/checker/nullness/qual/Nullable;",
|
||||
"Lorg/checkerframework/checker/nullness/qual/PolyNull;",
|
||||
// Paper end
|
||||
};
|
||||
|
||||
private static final String[] EXCLUDED_CLASSES = {
|
||||
// Internal technical classes
|
||||
"org/bukkit/plugin/java/JavaPluginLoader",
|
||||
"org/bukkit/util/io/BukkitObjectInputStream",
|
||||
"org/bukkit/util/io/BukkitObjectOutputStream",
|
||||
"org/bukkit/util/io/Wrapper",
|
||||
"org/bukkit/plugin/java/PluginClassLoader",
|
||||
// Generic functional interface
|
||||
"org/bukkit/util/Consumer",
|
||||
// Paper start
|
||||
"io/papermc/paper/util/TransformingRandomAccessList",
|
||||
"io/papermc/paper/util/TransformingRandomAccessList$TransformedListIterator",
|
||||
// Timings history is broken in terms of nullability due to guavas Function defining that the param is NonNull
|
||||
"co/aikar/timings/TimingHistory$2",
|
||||
"co/aikar/timings/TimingHistory$2$1",
|
||||
"co/aikar/timings/TimingHistory$2$1$1",
|
||||
"co/aikar/timings/TimingHistory$2$1$2",
|
||||
"co/aikar/timings/TimingHistory$3",
|
||||
"co/aikar/timings/TimingHistory$4",
|
||||
"co/aikar/timings/TimingHistoryEntry$1"
|
||||
// Paper end
|
||||
};
|
||||
|
||||
@Test
|
||||
public void testAll() throws IOException, URISyntaxException {
|
||||
URL loc = Bukkit.class.getProtectionDomain().getCodeSource().getLocation();
|
||||
File file = new File(loc.toURI());
|
||||
|
||||
// Running from jar is not supported yet
|
||||
assertTrue(file.isDirectory(), "code must be in a directory");
|
||||
|
||||
final HashMap<String, ClassNode> foundClasses = new HashMap<>();
|
||||
collectClasses(file, foundClasses);
|
||||
|
||||
final ArrayList<String> errors = new ArrayList<>();
|
||||
|
||||
for (ClassNode clazz : foundClasses.values()) {
|
||||
if (!isClassIncluded(clazz, foundClasses)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Paper start - skip class if it's @NullMarked
|
||||
if (isClassNullMarked(clazz, foundClasses)) {
|
||||
continue;
|
||||
}
|
||||
// Paper end - skip class if it's @NullMarked
|
||||
|
||||
for (MethodNode method : clazz.methods) {
|
||||
if (!isMethodIncluded(clazz, method, foundClasses)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mustBeAnnotated(Type.getReturnType(method.desc)) && !isWellAnnotated(method.invisibleAnnotations)) {
|
||||
// Paper start - Allow use of TYPE_USE annotations
|
||||
boolean warn = true;
|
||||
if (isWellAnnotated(method.visibleTypeAnnotations)) {
|
||||
warn = false;
|
||||
} else if (method.invisibleTypeAnnotations != null) {
|
||||
dance: for (final org.objectweb.asm.tree.TypeAnnotationNode invisibleTypeAnnotation : method.invisibleTypeAnnotations) {
|
||||
final org.objectweb.asm.TypeReference ref = new org.objectweb.asm.TypeReference(invisibleTypeAnnotation.typeRef);
|
||||
if (ref.getSort() == org.objectweb.asm.TypeReference.METHOD_RETURN && java.util.Arrays.asList(ACCEPTED_ANNOTATIONS).contains(invisibleTypeAnnotation.desc)) {
|
||||
warn = false;
|
||||
break dance; // cha cha real smooth
|
||||
}
|
||||
}
|
||||
}
|
||||
if (warn)
|
||||
// Paper end
|
||||
warn(errors, clazz, method, "return value");
|
||||
}
|
||||
|
||||
Type[] paramTypes = Type.getArgumentTypes(method.desc);
|
||||
List<ParameterNode> parameters = method.parameters;
|
||||
|
||||
dancing: // Paper
|
||||
for (int i = 0; i < paramTypes.length; i++) {
|
||||
if (mustBeAnnotated(paramTypes[i]) ^ isWellAnnotated(method.invisibleParameterAnnotations == null ? null : method.invisibleParameterAnnotations[i])) {
|
||||
// Paper start
|
||||
if (method.invisibleTypeAnnotations != null) {
|
||||
for (final org.objectweb.asm.tree.TypeAnnotationNode invisibleTypeAnnotation : method.invisibleTypeAnnotations) {
|
||||
final org.objectweb.asm.TypeReference ref = new org.objectweb.asm.TypeReference(invisibleTypeAnnotation.typeRef);
|
||||
if (ref.getSort() == org.objectweb.asm.TypeReference.METHOD_FORMAL_PARAMETER && ref.getTypeParameterIndex() == i && java.util.Arrays.asList(ACCEPTED_ANNOTATIONS).contains(invisibleTypeAnnotation.desc)) {
|
||||
continue dancing;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (method.visibleTypeAnnotations != null) {
|
||||
for (final org.objectweb.asm.tree.TypeAnnotationNode invisibleTypeAnnotation : method.visibleTypeAnnotations) {
|
||||
final org.objectweb.asm.TypeReference ref = new org.objectweb.asm.TypeReference(invisibleTypeAnnotation.typeRef);
|
||||
if (ref.getSort() == org.objectweb.asm.TypeReference.METHOD_FORMAL_PARAMETER && ref.getTypeParameterIndex() == i && java.util.Arrays.asList(ACCEPTED_ANNOTATIONS).contains(invisibleTypeAnnotation.desc)) {
|
||||
continue dancing;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Paper end - Allow use of TYPE_USE annotations
|
||||
ParameterNode paramNode = parameters == null ? null : parameters.get(i);
|
||||
String paramName = paramNode == null ? null : paramNode.name;
|
||||
|
||||
warn(errors, clazz, method, "parameter " + i + (paramName == null ? "" : ": " + paramName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.isEmpty()) {
|
||||
// Success
|
||||
return;
|
||||
}
|
||||
|
||||
Collections.sort(errors);
|
||||
|
||||
StringBuilder builder = new StringBuilder()
|
||||
.append("There ")
|
||||
.append(errors.size() != 1 ? "are " : "is ")
|
||||
.append(errors.size())
|
||||
.append(" missing annotation")
|
||||
.append(errors.size() != 1 ? "s:\n" : ":\n");
|
||||
|
||||
for (String message : errors) {
|
||||
builder.append("\t").append(message).append("\n");
|
||||
}
|
||||
|
||||
fail(builder.toString());
|
||||
}
|
||||
|
||||
private static void collectClasses(@NotNull File from, @NotNull Map<String, ClassNode> to) throws IOException {
|
||||
if (from.isDirectory()) {
|
||||
// Paper start - skip packages with @NullMarked
|
||||
final File packageInfo = new File(from, "package-info.class");
|
||||
if (packageInfo.exists()) {
|
||||
try (final FileInputStream in = new FileInputStream(packageInfo)) {
|
||||
final ClassReader cr = new ClassReader(in);
|
||||
|
||||
final ClassNode node = new ClassNode();
|
||||
cr.accept(node, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
|
||||
|
||||
if (isClassNullMarked0(node)) {
|
||||
return; // skip packages with @NullMarked
|
||||
}
|
||||
}
|
||||
}
|
||||
// Paper end - skip packages with @NullMarked
|
||||
final File[] files = from.listFiles();
|
||||
assert files != null;
|
||||
|
||||
for (File file : files) {
|
||||
collectClasses(file, to);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!from.getName().endsWith(".class")) {
|
||||
return;
|
||||
}
|
||||
|
||||
try (FileInputStream in = new FileInputStream(from)) {
|
||||
final ClassReader cr = new ClassReader(in);
|
||||
|
||||
final ClassNode node = new ClassNode();
|
||||
cr.accept(node, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
|
||||
|
||||
to.put(node.name, node);
|
||||
}
|
||||
}
|
||||
|
||||
// Paper start - skip class if it's @NullMarked
|
||||
private static boolean isClassNullMarked(@NotNull ClassNode clazz, @NotNull Map<String, ClassNode> allClasses) {
|
||||
if (isClassNullMarked0(clazz)) {
|
||||
return true;
|
||||
}
|
||||
if (clazz.nestHostClass != null) {
|
||||
final ClassNode nestHostNode = allClasses.get(clazz.nestHostClass);
|
||||
if (nestHostNode != null) {
|
||||
return isClassNullMarked(nestHostNode, allClasses);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isClassNullMarked0(@NotNull ClassNode clazz) {
|
||||
return clazz.visibleAnnotations != null && clazz.visibleAnnotations.stream().anyMatch(node -> "Lorg/jspecify/annotations/NullMarked;".equals(node.desc));
|
||||
}
|
||||
// Paper end - skip class if it's @NullMarked
|
||||
|
||||
private static boolean isClassIncluded(@NotNull ClassNode clazz, @NotNull Map<String, ClassNode> allClasses) {
|
||||
// Exclude private, synthetic or deprecated classes and annotations, since their members can't be null
|
||||
if ((clazz.access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_DEPRECATED | Opcodes.ACC_ANNOTATION)) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isSubclassOf(clazz, "org/bukkit/material/MaterialData", allClasses)) {
|
||||
throw new AssertionError("Subclass of MaterialData must be deprecated: " + clazz.name);
|
||||
}
|
||||
|
||||
if (isSubclassOf(clazz, "java/lang/Exception", allClasses)
|
||||
|| isSubclassOf(clazz, "java/lang/RuntimeException", allClasses)) {
|
||||
// Exceptions are excluded
|
||||
return false;
|
||||
}
|
||||
// Paper start
|
||||
if (isInternal(clazz.invisibleAnnotations)) {
|
||||
return false;
|
||||
}
|
||||
// Paper end
|
||||
|
||||
for (String excludedClass : EXCLUDED_CLASSES) {
|
||||
if (excludedClass.equals(clazz.name)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isMethodIncluded(@NotNull ClassNode clazz, @NotNull MethodNode method, @NotNull Map<String, ClassNode> allClasses) {
|
||||
// Exclude private, synthetic and deprecated methods
|
||||
if ((method.access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_DEPRECATED)) != 0 || (method.access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED | Opcodes.ACC_PUBLIC)) == 0) { // Paper - ignore package-private
|
||||
return false;
|
||||
}
|
||||
|
||||
// Exclude Java methods
|
||||
if (is(method, "toString", 0) || is(method, "clone", 0) || is(method, "equals", 1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Exclude generated Enum methods
|
||||
if (isSubclassOf(clazz, "java/lang/Enum", allClasses) && (is(method, "values", 0) || is(method, "valueOf", 1))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Anonymous classes have generated constructors, which can't be annotated nor invoked
|
||||
if ("<init>".equals(method.name) && isAnonymous(clazz)) {
|
||||
return false;
|
||||
}
|
||||
// Paper start
|
||||
if (isInternal(method.invisibleAnnotations)) {
|
||||
return false;
|
||||
}
|
||||
// Paper end
|
||||
|
||||
return true;
|
||||
}
|
||||
// Paper start
|
||||
private static boolean isInternal(List<? extends AnnotationNode> annotations) {
|
||||
if (annotations == null) {
|
||||
return false;
|
||||
}
|
||||
for (AnnotationNode node : annotations) {
|
||||
if (node.desc.equals("Lorg/jetbrains/annotations/ApiStatus$Internal;")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
// Paper end
|
||||
|
||||
private static boolean isWellAnnotated(@Nullable List<? extends AnnotationNode> annotations) { // Paper
|
||||
if (annotations == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (AnnotationNode node : annotations) {
|
||||
for (String acceptedAnnotation : ACCEPTED_ANNOTATIONS) {
|
||||
if (acceptedAnnotation.equals(node.desc)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean mustBeAnnotated(@NotNull Type type) {
|
||||
return type.getSort() == Type.ARRAY || type.getSort() == Type.OBJECT;
|
||||
}
|
||||
|
||||
private static boolean is(@NotNull MethodNode method, @NotNull String name, int parameters) {
|
||||
final List<ParameterNode> params = method.parameters;
|
||||
return method.name.equals(name) && (params == null || params.size() == parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the class is anonymous.
|
||||
*
|
||||
* @param clazz the class to check
|
||||
* @return true if given class is anonymous
|
||||
*/
|
||||
private static boolean isAnonymous(@NotNull ClassNode clazz) {
|
||||
final String name = clazz.name;
|
||||
if (name == null) {
|
||||
return false;
|
||||
}
|
||||
final int nestedSeparator = name.lastIndexOf('$');
|
||||
if (nestedSeparator == -1 || nestedSeparator + 1 == name.length()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Nested classes have purely numeric names. Java classes can't begin with a number,
|
||||
// so if first character is a number, the class must be anonymous
|
||||
final char c = name.charAt(nestedSeparator + 1);
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
private static boolean isSubclassOf(@NotNull ClassNode what, @NotNull String ofWhat, @NotNull Map<String, ClassNode> allClasses) {
|
||||
if (ofWhat.equals(what.name)
|
||||
// Not only optimization: Super class may not be present in allClasses, so it is checked here
|
||||
|| ofWhat.equals(what.superName)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final ClassNode parent = allClasses.get(what.superName);
|
||||
if (parent != null && isSubclassOf(parent, ofWhat, allClasses)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (String superInterface : what.interfaces) {
|
||||
final ClassNode interfaceParent = allClasses.get(superInterface);
|
||||
if (interfaceParent != null && isSubclassOf(interfaceParent, ofWhat, allClasses)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void warn(@NotNull Collection<String> out, @NotNull ClassNode clazz, @NotNull MethodNode method, @NotNull String description) {
|
||||
out.add(clazz.name + " \t" + method.name + " \t" + description);
|
||||
}
|
||||
}
|
||||
+6
-4
@@ -2,6 +2,7 @@ import java.util.Locale
|
||||
|
||||
pluginManagement {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
gradlePluginPortal()
|
||||
maven("https://repo.papermc.io/repository/maven-public/")
|
||||
}
|
||||
@@ -13,17 +14,17 @@ plugins {
|
||||
|
||||
if (!file(".git").exists()) {
|
||||
val errorText = """
|
||||
|
||||
|
||||
=====================[ ERROR ]=====================
|
||||
The Paper project directory is not a properly cloned Git repository.
|
||||
|
||||
|
||||
In order to build Paper from source you must clone
|
||||
the Paper repository using Git, not download a code
|
||||
zip from GitHub.
|
||||
|
||||
|
||||
Built Paper jars are available for download at
|
||||
https://papermc.io/downloads/paper
|
||||
|
||||
|
||||
See https://github.com/PaperMC/Paper/blob/main/CONTRIBUTING.md
|
||||
for further information on building and modifying Paper.
|
||||
===================================================
|
||||
@@ -42,6 +43,7 @@ for (name in listOf("paper-api", "paper-server")) {
|
||||
|
||||
optionalInclude("test-plugin")
|
||||
optionalInclude("paper-api-generator")
|
||||
include("paper-api:custom-checkstyle")
|
||||
|
||||
fun optionalInclude(name: String, op: (ProjectDescriptor.() -> Unit)? = null) {
|
||||
val settingsFile = file("$name.settings.gradle.kts")
|
||||
|
||||
Reference in new issue
Block a user