<?xml version="1.0" encoding="UTF-8"?>
<test-data
        xmlns="http://pmd.sourceforge.net/rule-tests"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd">

    <test-code>
        <description>SonarSource example 1</description>
        <rule-property name="reportLevel">1</rule-property>
        <expected-problems>1</expected-problems>
        <expected-messages>
            <message>The method 'overriddenSymbolFrom(JavaSymbol)' has a cognitive complexity of 19, current threshold is 1</message>
        </expected-messages>
        <code><![CDATA[import java.util.List;

public class Foo {

    private JavaSymbol overriddenSymbolFrom(JavaSymbol classType) {
        if (classType.isUnknown()) { // +1
            return null;
        }
        boolean unknownFound = false;
        List<JavaSymbol> symbols = classType.members();
        for (JavaSymbol overrideSymbol : symbols) { // +1
            if (overrideSymbol.isMethod() // +2 (nesting = 1)
                && !overrideSymbol.isStatic()) { // +1

                if (canOverride(overrideSymbol)) { // +3 (nesting = 2)
                    Boolean overriding = checkOverridingParameters(overrideSymbol, classType);
                    if (overriding == null) { // +4 (nesting = 3)
                        if (!unknownFound) { // +5 (nesting = 4)
                            unknownFound = true;
                        }
                    } else if (overriding) { // +1
                        return null;
                    }
                }
            }
        }
        if (unknownFound) { // +1
            return null;
        }
        return null;
    } // total complexity = 19


    boolean canOverride(JavaSymbol s) {}

    Boolean checkOverridingParameters(JavaSymbol s, JavaSymbol s2) {}
}

class JavaSymbol {

    boolean isUnknown() {}

    boolean isMethod() {}

    boolean isStatic() {}

    List<JavaSymbol> members() {}
}

            ]]></code>
    </test-code>

    <test-code>
        <description>SonarSource example 2</description>
        <rule-property name="reportLevel">1</rule-property>
        <expected-problems>1</expected-problems>
        <expected-messages>
            <message>The method 'addVersion(Entry, Transaction, Entry)' has a cognitive complexity of 35, current threshold is 1</message>
        </expected-messages>
        <code><![CDATA[
public class Foo {

    private void addVersion(final Entry entry, final Transaction txn, Entry frst) throws Exception {
        final int ti = getTransactionIndex();
        while (true) { // +1
            try {
                synchronized (this) {
                    if (frst != null) { // +2 (nesting = 1)
                        if (frst.hashCode() > entry.hashCode()) { // +3 (nesting = 2)
                            throw new Exception();
                        }
                        if (txn.isActive()) { // +3 (nesting = 2)
                            for // +4 (nesting = 3)
                            (Entry e = frst; e != null; e = e.getPrevious()) {
                                final long version = e.getVersion();
                                final long depends = ti.wwDependency(version,
                                                                     txn.getTransactionStatus(), 0);
                                if (depends == 1) { // +5 (nesting = 4)
                                    throw new Exception(""+version);
                                }
                                if (depends != 0 // +5 (nesting = 4)
                                    && depends != 5) { // +1
                                    throw new Exception();
                                }
                            }
                        }
                    }
                    entry.setPrevious(frst);
                    frst = entry;
                    break;
                }
            } catch (final Exception re) { // +2 (nesting = 1)
                try {
                    final long depends = getTransactionIndex()
                                                   .wwDependency(re.getVersionHandle(), txn.getTransactionStatus(),
                                                                 0);
                    if (depends != 0 // +3 (nesting = 2)
                        && depends != 5) { // +1
                        throw new Exception();
                    }
                } catch (final InterruptedException ie) { // +3 (nesting = 2)
                    throw new Exception(ie);
                }
            } catch (final InterruptedException ie) { // +2 (nesting = 1)
                throw new Exception(ie);
            }
        }
    } // total complexity = 35
}

class Entry { }
interface Transaction {
boolean isActive() ;
}]]></code>
    </test-code>

    <test-code>
        <description>SonarSource example 3</description>
        <rule-property name="reportLevel">1</rule-property>
        <expected-problems>1</expected-problems>
        <expected-messages>
            <message>The method 'toRegexp(String, String)' has a cognitive complexity of 20, current threshold is 1</message>
        </expected-messages>
        <code>
            <![CDATA[
            public class Foo {
              private static String toRegexp(String antPattern,
                  String directorySeparator) {
                final String escapedDirectorySeparator = '\\' + directorySeparator;
                final StringBuilder sb = new StringBuilder(antPattern.length());
                sb.append('^');
                int i = antPattern.startsWith("/") || // +1
                    antPattern.startsWith("\\") ? 1 : 0; // +1
                while (i < antPattern.length()) { // +1
                  final char ch = antPattern.charAt(i);
                  if ("SPECIAL_CHARS".indexOf(ch) != -1) { // +2 (nesting = 1)
                    sb.append('\\').append(ch);
                  } else if (ch == '*') { // +1
                    if (i + 1 < antPattern.length() // +3 (nesting = 2)
                        && antPattern.charAt(i + 1) == '*') { // +1
                      if (i + 2 < antPattern.length() // +4 (nesting = 3)
                          && isSlash(antPattern.charAt(i + 2))) { // +1
                        sb.append("(?:.*")
                            .append(escapedDirectorySeparator).append("|)");
                        i += 2;
                      } else { // +1
                        sb.append(".*");
                        i += 1;
                      }
                    } else { // +1
                      sb.append("[^").append(escapedDirectorySeparator).append("]*?");
                    }
                  } else if (ch == '?') { // +1
                    sb.append("[^").append(escapedDirectorySeparator).append("]");
                  } else if (isSlash(ch)) { // +1
                    sb.append(escapedDirectorySeparator);
                  } else { // +1
                    sb.append(ch);
                  }
                  i++;
                }
                sb.append('$');
                return sb.toString();
              } // total complexity = 20
            }
            ]]>
        </code>
    </test-code>

    <test-code>
        <description>Rule Doc Example</description>
        <rule-property name="reportLevel">1</rule-property>
        <expected-problems>2</expected-problems>
        <expected-linenumbers>9,19</expected-linenumbers>
        <expected-messages>
            <message>The method 'setPhoneNumberIfNotExisting(Account, String)' has a cognitive complexity of 1, current threshold is 1</message>
            <message>The method 'updateContacts(List&lt;Contact&gt;)' has a cognitive complexity of 4, current threshold is 1</message>
        </expected-messages>
        <code>
            <![CDATA[
public class Foo {
  // Has a cognitive complexity of 0
  public void createAccount() {
    Account account = new Account("PMD");
    // save account
  }

  // Has a cognitive complexity of 1
  public Boolean setPhoneNumberIfNotExisting(Account a, String phone) {
    if (a.phone == null) {                          // +1
      a.phone = phone;
      return true;
    }

    return false;
  }

  // Has a cognitive complexity of 4
  public void updateContacts(List<Contact> contacts) {
    List<Contact> contactsToUpdate = new ArrayList<Contact>();

    for (Contact contact : contacts) {                           // +1
      if (contact.department.equals("Finance")) {                // +2 (nesting = 1)
        contact.title = "Finance Specialist";
        contactsToUpdate.add(contact);
      } else if (contact.department.equals("Sales")) {           // +1
        contact.title = "Sales Specialist";
        contactsToUpdate.add(contact);
      }
    }
    // save contacts
  }
}            ]]>
        </code>
    </test-code>
    
    <test-code>
        <description>[java] CognitiveComplexity: Exception when using Map.of() #5084</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
package net.sourceforge.pmd.lang.java.rule.design.cognitivecomplexity;

import java.util.Map;

public class ReproducerFor5084 {
    private Map<Class, Serializer> serializers;

    public ReproducerFor5084() {
        this.serializers = Map.of(
                HttpRequest.class, new HttpRequestSerializer(),
                HttpResponse.class, new HttpResponseSerializer()
        );
    }

    public abstract static class Body<T> { }

    public abstract static class BodyWithContentType<T> extends Body<T> { }

    public interface HttpMessage<T extends HttpMessage, B extends Body> { }

    public static class HttpRequest implements HttpMessage<HttpRequest, Body> { }

    public static class HttpResponse implements HttpMessage<HttpResponse, BodyWithContentType> { }

    public interface Serializer<T> {
        String serialize(T t);
    }

    public class HttpRequestSerializer implements Serializer<HttpRequest> {
        @Override
        public String serialize(HttpRequest s) {
            return String.valueOf(s);
        }
    }

    public class HttpResponseSerializer implements Serializer<HttpResponse> {
        @Override
        public String serialize(HttpResponse s) {
            return String.valueOf(s);
        }
    }
}
]]></code>
    </test-code>
</test-data>
