<?xml version="1.0"?>

<ruleset name="String and StringBuffer Rules"
    xmlns="http://pmd.sf.net/ruleset/1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
    xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
  <description>
These rules deal with different problems that can occur with manipulation of the class String or StringBuffer.
  </description>


    <rule name="AvoidDuplicateLiterals"
    	  since="1.0"
        message="The String literal {0} appears {1} times in this file; the first occurrence is on line {2}"
        class="net.sourceforge.pmd.rules.strings.AvoidDuplicateLiteralsRule"
        externalInfoUrl="http://pmd.sourceforge.net/rules/strings.html#AvoidDuplicateLiterals">
    <description>
Code containing duplicate String literals can usually be improved by declaring the String as a constant field.
    </description>
        <priority>3</priority>
   <properties>
    <property name="threshold" description="The number of duplicate literals reporting threshold" value="4"/>
    <property name="skipAnnotations" description="Skip literals within Annotations" value="false"/>
    <property name="exceptionlist" description="Strings in that list are skipped"/>
    <property name="separator" description="Separator used in the exceptionlist" value=","/>
    <property name="exceptionfile" description="File containing strings to skip (one string per line), only used if exceptionlist is not set"/>
   </properties>
    <example>
<![CDATA[
public class Foo {
 private void bar() {
    buz("Howdy");
    buz("Howdy");
    buz("Howdy");
    buz("Howdy");
 }
 private void buz(String x) {}
}
]]>
    </example>
  </rule>

    <rule name="StringInstantiation"
    	  since="1.0"
        message="Avoid instantiating String objects; this is usually unnecessary."
        class="net.sourceforge.pmd.rules.strings.StringInstantiation"
        externalInfoUrl="http://pmd.sourceforge.net/rules/strings.html#StringInstantiation">
    <description>
Avoid instantiating String objects; this is usually unnecessary.
    </description>
       <priority>2</priority>
    <example>
<![CDATA[
public class Foo {
 private String bar = new String("bar"); // just do a String bar = "bar";
}
]]>
    </example>
    </rule>

   <rule name="StringToString"
   	  since="1.0"
        message="Avoid calling toString() on String objects; this is unnecessary."
        class="net.sourceforge.pmd.rules.strings.StringToStringRule"
        externalInfoUrl="http://pmd.sourceforge.net/rules/strings.html#StringToString">
    <description>
    Avoid calling toString() on String objects; this is unnecessary.
    </description>
       <priority>3</priority>
    <example>
<![CDATA[
public class Foo {
 private String baz() {
  String bar = "howdy";
  return bar.toString();
 }
}
]]>
    </example>
    </rule>

    <rule name="InefficientStringBuffering"
   	  since="3.4"
        message="Avoid concatenating nonliterals in a StringBuffer constructor or append()."
        class="net.sourceforge.pmd.rules.strings.InefficientStringBuffering"
        externalInfoUrl="http://pmd.sourceforge.net/rules/strings.html#InefficientStringBuffering">
    <description>
Avoid concatenating non literals in a StringBuffer constructor or append().
    </description>
       <priority>3</priority>
    <example>
<![CDATA[
public class Foo {
 void bar() {
  // Avoid this
  StringBuffer sb=new StringBuffer("tmp = "+System.getProperty("java.io.tmpdir"));
  // use instead something like this
  StringBuffer sb = new StringBuffer("tmp = ");
  sb.append(System.getProperty("java.io.tmpdir"));
 }
}
]]>
    </example>
    </rule>

    <rule name="UnnecessaryCaseChange"
          since="3.3"
          message="Using equalsIgnoreCase() is cleaner than using toUpperCase/toLowerCase().equals()."
           class="net.sourceforge.pmd.rules.strings.UnnecessaryCaseChange"
          externalInfoUrl="http://pmd.sourceforge.net/rules/strings.html#UnnecessaryCaseChange">
       <description>
Using equalsIgnoreCase() is faster than using toUpperCase/toLowerCase().equals()
       </description>
       <priority>3</priority>
       <example>
                 <![CDATA[
 public class Foo {
  public boolean bar(String buz) {
    // should be buz.equalsIgnoreCase("baz")
    return buz.toUpperCase().equals("baz");
    // another unnecessary toUpperCase()
    // return buz.toUpperCase().equalsIgnoreCase("baz");
  }
 }
                 ]]>
       </example>
     </rule>

    <rule name="UseStringBufferLength"
          since="3.4"
          message="This is an inefficient use of StringBuffer.toString; call StringBuffer.length instead."
          class="net.sourceforge.pmd.rules.strings.UseStringBufferLength"
          externalInfoUrl="http://pmd.sourceforge.net/rules/strings.html#UseStringBufferLength">
      <description>
 Use StringBuffer.length() to determine StringBuffer length rather than using StringBuffer.toString().equals("")
          or StringBuffer.toString().length() ==.
      </description>
      <priority>3</priority>
      <example>
  <![CDATA[
public class Foo {
 void bar() {
  StringBuffer sb = new StringBuffer();
  // this is bad
  if(sb.toString().equals("")) {}
  // this is good
  if(sb.length() == 0) {}
 }
}

  ]]>
      </example>
    </rule>


    <rule name="AppendCharacterWithChar"
        since="3.5"
        message="Avoid appending characters as strings in StringBuffer.append."
        class="net.sourceforge.pmd.rules.strings.AppendCharacterWithChar"
        externalInfoUrl="http://pmd.sourceforge.net/rules/strings.html#AppendCharacterWithChar">
    <description>
Avoid concatenating characters as strings in StringBuffer.append.
    </description>
       <priority>3</priority>
    <example>
<![CDATA[
public class Foo {
 void bar() {
  StringBuffer sb=new StringBuffer();
  // Avoid this
  sb.append("a");

  // use instead something like this
  StringBuffer sb=new StringBuffer();
  sb.append('a');
 }
}
]]>
    </example>
    </rule>

        <rule name="ConsecutiveLiteralAppends"
        since="3.5"
        message="StringBuffer.append is called {0} consecutive times with literal Strings. Use a single append with a single String."
        class="net.sourceforge.pmd.rules.strings.ConsecutiveLiteralAppends"
        externalInfoUrl="http://pmd.sourceforge.net/rules/strings.html#ConsecutiveLiteralAppends">
    <description>
Consecutively calling StringBuffer.append with String literals
    </description>
        <priority>3</priority>
   <properties>
    <property name="threshold" description="The report threshold" value="1"/>
   </properties>
    <example>
<![CDATA[
public class Foo {
 private void bar() {
   StringBuffer buf = new StringBuffer();
   buf.append("Hello").append(" ").append("World"); //bad
   buf.append("Hello World");//good
 }
}
]]>
    </example>
  </rule>


    <rule name="UseIndexOfChar"
        since="3.5"
        message="String.indexOf(char) is faster than String.indexOf(String)."
        class="net.sourceforge.pmd.rules.strings.UseIndexOfChar"
        externalInfoUrl="http://pmd.sourceforge.net/rules/strings.html#UseIndexOfChar">
    <description>
Use String.indexOf(char) when checking for the index of a single character; it executes faster.
    </description>
       <priority>3</priority>
    <example>
<![CDATA[
public class Foo {
 void bar() {
  String s = "hello world";
  // avoid this
  if (s.indexOf("d") {}
  // instead do this
  if (s.indexOf('d') {}
 }
}
]]>
    </example>
    </rule>

    <rule name="InefficientEmptyStringCheck"
        since="3.6"
        message="String.trim().length()==0 is an inefficient way to validate an empty String."
        class="net.sourceforge.pmd.rules.strings.InefficientEmptyStringCheck"
        externalInfoUrl="http://pmd.sourceforge.net/rules/strings.html#InefficientEmptyStringCheck">
    <description>
String.trim().length() is an inefficient way to check if a String is really empty, as it
creates a new String object just to check its size. Consider creating a static function that
loops through a string, checking Character.isWhitespace() on each character and returning
false if a non-whitespace character is found.
    </description>
       <priority>3</priority>
    <example>
<![CDATA[
public class Foo {
    void bar(String string) {
        if (string != null && string.trim().size() > 0) {
		    doSomething();
        }
    }
}
]]>
    </example>
    </rule>

    <rule name="InsufficientStringBufferDeclaration"
        since="3.6"
        message="StringBuffer constructor is initialized with size {0}, but has at least {1} characters appended."
        class="net.sourceforge.pmd.rules.strings.InsufficientStringBufferDeclaration"
        externalInfoUrl="http://pmd.sourceforge.net/rules/strings.html#InsufficientStringBufferDeclaration">
    <description>
Failing to pre-size a StringBuffer properly could cause it to re-size many times
during runtime. This rule checks the characters that are actually passed into
StringBuffer.append(), but represents a best guess "worst case" scenario. An
empty StringBuffer constructor initializes the object to 16 characters. This default
is assumed if the length of the constructor can not be determined.
    </description>
       <priority>3</priority>
    <example>
<![CDATA[
public class Foo {
    void bar() {
        StringBuffer bad = new StringBuffer();
        bad.append("This is a long string, will exceed the default 16 characters");//bad
        StringBuffer good = new StringBuffer(41);
        good.append("This is a long string, which is pre-sized");//good
    }
}
]]>
    </example>
    </rule>

    <rule name="UselessStringValueOf"
          since="3.8"
          message="No need to call String.valueOf to append to a string."
          class="net.sourceforge.pmd.rules.strings.UselessStringValueOf"
          externalInfoUrl="http://pmd.sourceforge.net/rules/strings.html#UselessStringValueOf">
      <description>
No need to call String.valueOf to append to a string; just use the valueOf() argument directly.
      </description>
        <priority>3</priority>
      <example>
<![CDATA[
public String convert(int i) {
  String s;
  s = "a" + String.valueOf(i); // Bad
  s = "a" + i; // Better
  return s;
}
]]>
          </example>
    </rule>


<rule   name="StringBufferInstantiationWithChar"
        since="3.9"
        message="Do not instantiate a StringBuffer with a char"
        class="net.sourceforge.pmd.rules.XPathRule"
        externalInfoUrl="http://pmd.sourceforge.net/rules/strings.html#StringBufferInstantiationWithChar">
    <description>
StringBuffer sb = new StringBuffer('c'); The
char will be converted into int to intialize
StringBuffer size.
    </description>
    <priority>4</priority>
    <properties>
        <property name="xpath">
            <value>
<![CDATA[
//AllocationExpression/ClassOrInterfaceType
[@Image='StringBuffer']
/../Arguments/ArgumentList/Expression/PrimaryExpression
/PrimaryPrefix/
Literal
  [starts-with(@Image, "'")]
  [ends-with(@Image, "'")]
]]>
            </value>
        </property>
    </properties>
    <example>
<![CDATA[
class Foo {
  StringBuffer sb1 = new StringBuffer('c'); //Bad
  StringBuffer sb2 = new StringBuffer("c"); //Better
}
]]>
    </example>
    </rule>

<rule   name="UseEqualsToCompareStrings"
        since="4.1"
        message="Use equals() to compare strings instead of ''=='' or ''!=''"
        class="net.sourceforge.pmd.rules.XPathRule"
        externalInfoUrl="http://pmd.sourceforge.net/rules/strings.html#UseEqualsToCompareStrings">
    <description>
Using '==' or '!=' to compare strings only works if intern version is used on both sides
    </description>
    <priority>3</priority>
    <properties>
        <property name="xpath">
            <value>
<![CDATA[
//EqualityExpression/PrimaryExpression
[(PrimaryPrefix/Literal
   [starts-with(@Image, '"')]
   [ends-with(@Image, '"')]
and count(PrimarySuffix) = 0)]
]]>
            </value>
        </property>
    </properties>
    <example>
<![CDATA[
class Foo {
  boolean test(String s) {
    if (s == "one") return true; //Bad
    if ("two".equals(s)) return true; //Better
    return false;
  }
}
]]>
    </example>
    </rule>

	<rule   name="AvoidStringBufferField"
	      since="4.2"
        	message="StringBuffers can grow quite a lot, and so may become a source of memory leak (if the owning class has a long life time)."
        	class="net.sourceforge.pmd.rules.XPathRule"
        	externalInfoUrl="http://pmd.sourceforge.net/rules/strings.html#AvoidStringBufferField">
    <description>
		<![CDATA[[
			StringBuffers can grow quite a lot, and so may become a source of memory leak (if the owning class has a long life time).
		]]>
    </description>
    <priority>3</priority>
    <properties>
        <property name="xpath">
            <value>
<![CDATA[
//FieldDeclaration/Type/ReferenceType/ClassOrInterfaceType[@Image = 'StringBuffer']
]]>
			</value>
		</property>
		</properties>
    	<example>
<![CDATA[
class Foo {
	private StringBuffer memoryLeak;
}
]]>
		</example>
	</rule>



</ruleset>

