package org.kohsuke.github;

import com.tngtech.archunit.core.domain.JavaClass;
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.domain.properties.HasAnnotations;
import com.tngtech.archunit.core.domain.properties.HasName.AndFullName;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.core.importer.ImportOption;
import com.tngtech.archunit.lang.ArchCondition;
import com.tngtech.archunit.lang.ArchRule;
import com.tngtech.archunit.lang.ConditionEvents;
import com.tngtech.archunit.lang.SimpleConditionEvent;
import org.junit.Test;

import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;

public class ArchTests {

    private final JavaClasses classFiles = new ClassFileImporter()
            .withImportOption(new ImportOption.DoNotIncludeTests())
            .withImportOption(new ImportOption.DoNotIncludeJars())
            .importPackages("org.kohsuke.github");

    @Test
    public void testPreviewsAreFlaggedAsDeprecated() {

        String description = "annotate all preview APIs as @Deprecated until they are promoted to stable";

        ArchRule rule = classes().should(new ArchCondition<JavaClass>(description) {

            @Override
            public void check(final JavaClass targetClazz, final ConditionEvents events) {
                checkForPreviewAnnotation(targetClazz, events);
                targetClazz.getAllMethods().forEach(method -> {
                    checkForPreviewAnnotation(method, events);
                });
            }

            <T extends HasAnnotations<T> & AndFullName> void checkForPreviewAnnotation(T codeTarget,
                    ConditionEvents events) {

                if (codeTarget.tryGetAnnotationOfType(Preview.class).isPresent()
                        && !codeTarget.tryGetAnnotationOfType(Deprecated.class).isPresent()) {

                    String message = codeTarget.getFullName()
                            + " uses a preview API and is missing the '@Deprecated' annotation.";

                    events.add(new SimpleConditionEvent(codeTarget, false, message));
                }
            }
        });

        rule.check(classFiles);

    }
}

@@ -71,16 +71,18 @@
 avaClass
+es
 ;%0Aimport
@@ -108,34 +108,42 @@
 it.core.
-domain.JavaClasses
+importer.ClassFileImporter
 ;%0Aimport
@@ -173,40 +173,29 @@
 ore.
-domain.properties.HasAnnota
+importer.ImportOp
 tion
-s
 ;%0Aim
@@ -224,223 +224,90 @@
 nit.
-core.domain.properties.HasName.AndFullName;%0Aimport com.tngtech.archunit.core.importer.ClassFileImporter;%0Aimport com.tngtech.archunit.core.importer.ImportOption
+lang.ArchRule;%0Aimport org.junit.BeforeClass;%0Aimport org.junit.Test
 ;%0A
+%0A
 import 
-com.tngtech.archunit.lang.ArchCondition;%0Aimport
+static
  com
@@ -325,32 +325,39 @@
 chunit.lang.
+syntax.
 ArchRule
 ;%0Aimport com
@@ -348,57 +348,25 @@
 Rule
-;%0Aimport com.tngtech.archunit.lang.ConditionEvent
+Definition.classe
 s;%0Ai
@@ -363,32 +363,39 @@
 classes;%0Aimport 
+static 
 com.tngtech.arch
@@ -408,53 +408,41 @@
 ang.
-SimpleConditionEvent;%0Aimport org.junit.Test;%0A
+syntax.ArchRuleDefinition.fields;
 %0Aimp
@@ -504,23 +504,66 @@
 inition.
-classes
+methods;%0Aimport static org.junit.Assert.assertTrue
 ;%0A%0Apubli
@@ -595,16 +595,23 @@
 private 
+static 
 final Ja
@@ -840,24 +840,130 @@
 .github%22);%0A%0A
+    @BeforeClass%0A    public static void beforeClass() %7B%0A        assertTrue(classFiles.size() %3E 0);%0A    %7D%0A%0A
     @Test%0A  
@@ -1035,48 +1035,52 @@
 ing 
-description = %22annotate all preview APIs
+reason = %22all preview APIs must be annotated
  as 
@@ -1145,17 +1145,22 @@
 rchRule 
-r
+classR
 ule = cl
@@ -1171,236 +1171,140 @@
 s().
-should(new ArchCondition%3CJavaClass%3E(description) %7B%0A%0A            @Override%0A            public void check(final JavaClass targetClazz, final ConditionEvents events) %7B%0A                checkForPreviewAnnotation(targetClazz, event
+that()%0A                .areAnnotatedWith(Preview.class)%0A                .should()%0A                .beAnnotatedWith(Deprecated.clas
 s)
-;
 %0A   
@@ -1320,118 +1320,122 @@
     
-targetClazz.getAllMethods().forEach(method -%3E %7B%0A                    checkForPreviewAnnotation(method, event
+.because(reason);%0A%0A        ArchRule methodRule = methods().that()%0A                .areAnnotatedWith(Preview.clas
 s)
-;
 %0A   
@@ -1447,19 +1447,25 @@
         
-%7D);
+.should()
 %0A       
@@ -1473,395 +1473,201 @@
     
-%7D%0A%0A            %3CT extends HasAnnotations%3CT%3E & AndFullName%3E void checkForPreviewAnnotation(T codeTarget,%0A                    ConditionEvents events) %7B%0A%0A                if (codeTarget.tryGetAnnotationOfType(Preview.class).isPresent()%0A                        && !codeTarget.tryGetAnnotationOfType(Deprecated.class).isPresent()) %7B%0A%0A                    String message = codeTarget.getFullName
+    .beAnnotatedWith(Deprecated.class)%0A                .because(reason);%0A%0A        ArchRule enumFieldsRule = fields().that()%0A                .areDeclaredInClassesThat()%0A                .areEnums
 ()%0A 
@@ -1673,32 +1673,39 @@
                 
+.and()%0A
             + %22 
@@ -1704,218 +1704,244 @@
     
-+ %22 uses a preview API and is missing the '@Deprecated' annotation.%22;%0A%0A                    events.add(new SimpleConditionEvent(codeTarget, false, message));%0A                %7D%0A            %7D%0A        %7D
+    .areAnnotatedWith(Preview.class)%0A                .should()%0A                .beAnnotatedWith(Deprecated.class)%0A                .because(reason);%0A%0A        classRule.check(classFiles);%0A        enumFieldsRule.check(classFiles
 );%0A
-%0A
         
 rule
@@ -1936,17 +1936,23 @@
         
-r
+methodR
 ule.chec

update arch tests to add enum checks