Index: lucene/analysis/common/src/test/org/apache/lucene/analysis/shingle/ShingleAnalyzerWrapperTest.java
===================================================================
--- lucene/analysis/common/src/test/org/apache/lucene/analysis/shingle/ShingleAnalyzerWrapperTest.java	(revision 1686523)
+++ lucene/analysis/common/src/test/org/apache/lucene/analysis/shingle/ShingleAnalyzerWrapperTest.java	(working copy)
@@ -103,7 +103,7 @@
    * This shows how to construct a phrase query containing shingles.
    */
   public void testShingleAnalyzerWrapperPhraseQuery() throws Exception {
-    PhraseQuery.Builder builder = new PhraseQuery.Builder();
+    PhraseQuery.Builder builder = new PhraseQuery.Builder("content");
     try (TokenStream ts = analyzer.tokenStream("content", "this sentence")) {
       int j = -1;
     
@@ -114,7 +114,7 @@
       while (ts.incrementToken()) {
         j += posIncrAtt.getPositionIncrement();
         String termText = termAtt.toString();
-        builder.add(new Term("content", termText), j);
+        builder.add(termText, j);
       }
       ts.end();
     }
Index: lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/feeds/SimpleSloppyPhraseQueryMaker.java
===================================================================
--- lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/feeds/SimpleSloppyPhraseQueryMaker.java	(revision 1686523)
+++ lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/feeds/SimpleSloppyPhraseQueryMaker.java	(working copy)
@@ -51,9 +51,9 @@
           // ordered
           int remainedSlop = slop;
           int wind = wd;
-          PhraseQuery.Builder builder = new PhraseQuery.Builder();
+          PhraseQuery.Builder builder = new PhraseQuery.Builder(DocMaker.BODY_FIELD);
           for (int i=0; i<qlen; i++) {
-            builder.add(new Term(DocMaker.BODY_FIELD, words[wind++]), i);
+            builder.add( words[wind++], i);
             if (remainedSlop>0) {
               remainedSlop--;
               wind++;
@@ -65,9 +65,9 @@
           // reversed
           remainedSlop = slop;
           wind = wd+qlen+remainedSlop-1;
-          builder = new PhraseQuery.Builder();
+          builder = new PhraseQuery.Builder(DocMaker.BODY_FIELD);
           for (int i=0; i<qlen; i++) {
-            builder.add(new Term(DocMaker.BODY_FIELD, words[wind--]), i);
+            builder.add(words[wind--], i);
             if (remainedSlop>0) {
               remainedSlop--;
               wind--;
Index: lucene/core/src/java/org/apache/lucene/search/NGramPhraseQuery.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/search/NGramPhraseQuery.java	(revision 1686523)
+++ lucene/core/src/java/org/apache/lucene/search/NGramPhraseQuery.java	(working copy)
@@ -68,10 +68,10 @@
       return phraseQuery.rewrite(reader);
     }
 
-    PhraseQuery.Builder builder = new PhraseQuery.Builder();
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(phraseQuery.getField());
     for (int i = 0; i < terms.length; ++i) {
       if (i % n == 0 || i == terms.length - 1) {
-        builder.add(terms[i], i);
+        builder.add(terms[i].text(),i);
       }
     }
     PhraseQuery rewritten = builder.build();
Index: lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java	(revision 1686523)
+++ lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java	(working copy)
@@ -49,16 +49,16 @@
  * <b>NOTE</b>: Leading holes don't have any particular meaning for this query
  * and will be ignored. For instance this query:
  * <pre class="prettyprint">
- * PhraseQuery.Builder builder = new PhraseQuery.Builder();
- * builder.add(new Term("body", "one"), 4);
- * builder.add(new Term("body", "two"), 5);
+ * PhraseQuery.Builder builder = new PhraseQuery.Builder("body");
+ * builder.add("one"), 4);
+ * builder.add("two"), 5);
  * PhraseQuery pq = builder.build();
  * </pre>
  * is equivalent to the below query:
  * <pre class="prettyprint">
- * PhraseQuery.Builder builder = new PhraseQuery.Builder();
- * builder.add(new Term("body", "one"), 0);
- * builder.add(new Term("body", "two"), 1);
+ * PhraseQuery.Builder builder = new PhraseQuery.Builder("body");
+ * builder.add("one"), 0);
+ * builder.add("two"), 1);
  * PhraseQuery pq = builder.build();
  * </pre>
  */
@@ -70,30 +70,47 @@
     private int slop;
     private final List<Term> terms;
     private final List<Integer> positions;
+    private String field;
 
-    /** Sole constructor. */
-    public Builder() {
+    /** Constructs a Builder with the given field
+     * @param field field's name
+     */
+    public Builder(String field) {
       slop = 0;
       terms = new ArrayList<>();
       positions = new ArrayList<>();
+      this.field = field;
     }
 
     /**
      * Set the slop.
      * @see PhraseQuery#getSlop()
      */
-    public void setSlop(int slop) {
+    public Builder setSlop(int slop) {
       this.slop = slop;
+      return this;
     }
 
     /**
      * Adds a term to the end of the query phrase.
      * The relative position of the term is the one immediately after the last term added.
      */
-    public void add(Term term) {
-      add(term, positions.isEmpty() ? 0 : 1 + positions.get(positions.size() - 1));
+    public Builder add(String termText) {
+      add(termText, positions.isEmpty() ? 0 : 1 + positions.get(positions.size() - 1));
+      return this;
     }
 
+
+    public Builder add(String termText, int position) {
+      add(new BytesRef(termText),position);
+      return this;
+    }
+
+    public Builder add(BytesRef termText) {
+      add(termText, positions.isEmpty() ? 0 : 1 + positions.get(positions.size() - 1));
+      return this;
+    }
+
     /**
      * Adds a term to the end of the query phrase.
      * The relative position of the term within the phrase is specified explicitly.
@@ -101,8 +118,8 @@
      * or phrases with gaps (e.g. in connection with stopwords).
      * 
      */
-    public void add(Term term, int position) {
-      term = new Term(term.field(), BytesRef.deepCopyOf(term.bytes())); // be defensive
+    public Builder add(BytesRef termText, int position) {
+      Term term = new Term(field, BytesRef.deepCopyOf(termText)); // be defensive
       if (position < 0) {
         throw new IllegalArgumentException("Positions must be >= 0, got " + position);
       }
@@ -112,11 +129,9 @@
           throw new IllegalArgumentException("Positions must be added in order, got " + position + " after " + lastPosition);
         }
       }
-      if (terms.isEmpty() == false && term.field().equals(terms.get(0).field()) == false) {
-        throw new IllegalArgumentException("All terms must be on the same field, got " + term.field() + " and " + terms.get(0).field());
-      }
       terms.add(term);
       positions.add(position);
+      return this;
     }
 
     /**
@@ -167,69 +182,7 @@
     this.field = terms.length == 0 ? null : terms[0].field();
   }
 
-  private static int[] incrementalPositions(int length) {
-    int[] positions = new int[length];
-    for (int i = 0; i < length; ++i) {
-      positions[i] = i;
-    }
-    return positions;
-  }
-
-  private static Term[] toTerms(String field, String... termStrings) {
-    Term[] terms = new Term[termStrings.length];
-    for (int i = 0; i < terms.length; ++i) {
-      terms[i] = new Term(field, termStrings[i]);
-    }
-    return terms;
-  }
-
-  private static Term[] toTerms(String field, BytesRef... termBytes) {
-    Term[] terms = new Term[termBytes.length];
-    for (int i = 0; i < terms.length; ++i) {
-      terms[i] = new Term(field, BytesRef.deepCopyOf(termBytes[i]));
-    }
-    return terms;
-  }
-
   /**
-   * Create a phrase query which will match documents that contain the given
-   * list of terms at consecutive positions in {@code field}, and at a
-   * maximum edit distance of {@code slop}. For more complicated use-cases,
-   * use {@link PhraseQuery.Builder}.
-   * @see #getSlop()
-   */
-  public PhraseQuery(int slop, String field, String... terms) {
-    this(slop, toTerms(field, terms), incrementalPositions(terms.length));
-  }
-
-  /**
-   * Create a phrase query which will match documents that contain the given
-   * list of terms at consecutive positions in {@code field}.
-   */
-  public PhraseQuery(String field, String... terms) {
-    this(0, field, terms);
-  }
-
-  /**
-   * Create a phrase query which will match documents that contain the given
-   * list of terms at consecutive positions in {@code field}, and at a
-   * maximum edit distance of {@code slop}. For more complicated use-cases,
-   * use {@link PhraseQuery.Builder}.
-   * @see #getSlop()
-   */
-  public PhraseQuery(int slop, String field, BytesRef... terms) {
-    this(slop, toTerms(field, terms), incrementalPositions(terms.length));
-  }
-
-  /**
-   * Create a phrase query which will match documents that contain the given
-   * list of terms at consecutive positions in {@code field}.
-   */
-  public PhraseQuery(String field, BytesRef... terms) {
-    this(0, field, terms);
-  }
-
-  /**
    * Return the slop for this {@link PhraseQuery}.
    *
    * <p>The slop is an edit distance between respective positions of terms as
@@ -261,6 +214,13 @@
       return positions;
   }
 
+  /**
+   * Return query field
+   */
+  public String getField() {
+    return field;
+  }
+
   @Override
   public Query rewrite(IndexReader reader) throws IOException {
     if (terms.length == 0) {
Index: lucene/core/src/java/org/apache/lucene/util/QueryBuilder.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/util/QueryBuilder.java	(revision 1686523)
+++ lucene/core/src/java/org/apache/lucene/util/QueryBuilder.java	(working copy)
@@ -339,7 +339,7 @@
    * Creates simple phrase query from the cached tokenstream contents 
    */
   private Query analyzePhrase(String field, TokenStream stream, int slop) throws IOException {
-    PhraseQuery.Builder builder = new PhraseQuery.Builder();
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(field);
     builder.setSlop(slop);
     
     TermToBytesRefAttribute termAtt = stream.getAttribute(TermToBytesRefAttribute.class);
@@ -357,7 +357,7 @@
       } else {
         position += 1;
       }
-      builder.add(new Term(field, bytes), position);
+      builder.add(bytes, position);
     }
 
     return builder.build();
Index: lucene/core/src/test/org/apache/lucene/TestDemo.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/TestDemo.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/TestDemo.java	(working copy)
@@ -70,7 +70,10 @@
     }
 
     // Test simple phrase query
-    PhraseQuery phraseQuery = new PhraseQuery("fieldname", "to", "be");
+    PhraseQuery.Builder builder = new PhraseQuery.Builder("fieldname");
+    builder.add("to");
+    builder.add("be");
+    PhraseQuery phraseQuery = builder.build();
     assertEquals(1, isearcher.search(phraseQuery, 1).totalHits);
 
     ireader.close();
Index: lucene/core/src/test/org/apache/lucene/TestSearch.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/TestSearch.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/TestSearch.java	(working copy)
@@ -166,10 +166,10 @@
     booleanAB.add(new TermQuery(new Term("contents", "b")), BooleanClause.Occur.SHOULD);
     queries.add(booleanAB.build());
 
-    PhraseQuery phraseAB = new PhraseQuery("contents", "a", "b");
+    PhraseQuery phraseAB = new PhraseQuery.Builder("contents").add("a").add("b").build();
     queries.add(phraseAB);
 
-    PhraseQuery phraseABC = new PhraseQuery("contents", "a", "b", "c");
+    PhraseQuery phraseABC = new PhraseQuery.Builder("contents").add("a").add("b").add("c").build();
     queries.add(phraseABC);
 
     BooleanQuery.Builder booleanAC = new BooleanQuery.Builder();
@@ -177,10 +177,10 @@
     booleanAC.add(new TermQuery(new Term("contents", "c")), BooleanClause.Occur.SHOULD);
     queries.add(booleanAC.build());
 
-    PhraseQuery phraseAC = new PhraseQuery("contents", "a", "c");
+    PhraseQuery phraseAC = new PhraseQuery.Builder("contents").add("a").add("c").build();
     queries.add(phraseAC);
 
-    PhraseQuery phraseACE = new PhraseQuery("contents", "a", "c", "e");
+    PhraseQuery phraseACE = new PhraseQuery.Builder("contents").add("a").add("b").add("e").build();
     queries.add(phraseACE);
 
     return queries;
Index: lucene/core/src/test/org/apache/lucene/document/TestDocument.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/document/TestDocument.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/document/TestDocument.java	(working copy)
@@ -246,7 +246,7 @@
     IndexReader reader = writer.getReader();
     
     IndexSearcher searcher = newSearcher(reader);
-    PhraseQuery query = new PhraseQuery("indexed_not_tokenized", "test1", "test2");
+    PhraseQuery query = new PhraseQuery.Builder("indexed_not_tokenized").add("test1").add("test2").build();
     
     ScoreDoc[] hits = searcher.search(query, 1000).scoreDocs;
     assertEquals(1, hits.length);
Index: lucene/core/src/test/org/apache/lucene/index/TestAddIndexes.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/index/TestAddIndexes.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/index/TestAddIndexes.java	(working copy)
@@ -172,7 +172,7 @@
       writer.updateDocument(new Term("id", "" + (i%10)), doc);
     }
     // Deletes one of the 10 added docs, leaving 9:
-    PhraseQuery q = new PhraseQuery("content", "bbb", "14");
+    PhraseQuery q = new PhraseQuery.Builder("content").add("bbb").add("14").build();
     writer.deleteDocuments(q);
 
     writer.forceMerge(1);
@@ -208,7 +208,7 @@
     writer.addIndexes(aux);
     
     // Deletes one of the 10 added docs, leaving 9:
-    PhraseQuery q = new PhraseQuery("content", "bbb", "14");
+    PhraseQuery q = new PhraseQuery.Builder("content").add("bbb").add("14").build();
     writer.deleteDocuments(q);
 
     writer.forceMerge(1);
@@ -242,7 +242,7 @@
     }
 
     // Deletes one of the 10 added docs, leaving 9:
-    PhraseQuery q = new PhraseQuery("content", "bbb", "14");
+    PhraseQuery q = new PhraseQuery.Builder("content").add("bbb").add("14").build();
     writer.deleteDocuments(q);
 
     writer.addIndexes(aux);
Index: lucene/core/src/test/org/apache/lucene/index/TestIndexWriter.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/index/TestIndexWriter.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/index/TestIndexWriter.java	(working copy)
@@ -1894,9 +1894,9 @@
     IndexReader ir = iw.getReader();
     iw.close();
     IndexSearcher is = newSearcher(ir);
-    PhraseQuery.Builder builder = new PhraseQuery.Builder();
-    builder.add(new Term("body", "just"), 0);
-    builder.add(new Term("body", "test"), 2);
+    PhraseQuery.Builder builder = new PhraseQuery.Builder("body");
+    builder.add("just", 0);
+    builder.add("test", 2);
     PhraseQuery pq = builder.build();
     // body:"just ? test"
     assertEquals(1, is.search(pq, 5).totalHits);
@@ -1926,9 +1926,9 @@
     IndexReader ir = iw.getReader();
     iw.close();
     IndexSearcher is = newSearcher(ir);
-    PhraseQuery.Builder builder = new PhraseQuery.Builder();
-    builder.add(new Term("body", "just"), 0);
-    builder.add(new Term("body", "test"), 3);
+    PhraseQuery.Builder builder = new PhraseQuery.Builder("body");
+    builder.add("just", 0);
+    builder.add("test", 3);
     PhraseQuery pq = builder.build();
     // body:"just ? ? test"
     assertEquals(1, is.search(pq, 5).totalHits);
Index: lucene/core/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java	(working copy)
@@ -1410,10 +1410,16 @@
     w.close();
 
     final IndexSearcher s = newSearcher(r);
-    PhraseQuery pq = new PhraseQuery("content", "silly", "good");
+    PhraseQuery pq = new PhraseQuery.Builder("content")
+        .add("silly")
+        .add("good")
+        .build();
     assertEquals(0, s.search(pq, 1).totalHits);
 
-    pq = new PhraseQuery("content", "good", "content");
+    pq = new PhraseQuery.Builder("content")
+        .add("good")
+        .add("content")
+        .build();
     assertEquals(numDocs1+numDocs2, s.search(pq, 1).totalHits);
     r.close();
     dir.close();
@@ -1487,10 +1493,16 @@
     w.close();
 
     final IndexSearcher s = newSearcher(r);
-    PhraseQuery pq = new PhraseQuery("content", "silly", "content");
+    PhraseQuery pq = new PhraseQuery.Builder("content")
+        .add("silly")
+        .add("content")
+        .build();
     assertEquals(numDocs2, s.search(pq, 1).totalHits);
 
-    pq = new PhraseQuery("content", "good", "content");
+    pq = new PhraseQuery.Builder("content")
+        .add("good")
+        .add("content")
+        .build();
     assertEquals(numDocs1+numDocs3+numDocs4, s.search(pq, 1).totalHits);
     r.close();
     dir.close();
Index: lucene/core/src/test/org/apache/lucene/index/TestLazyProxSkipping.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/index/TestLazyProxSkipping.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/index/TestLazyProxSkipping.java	(working copy)
@@ -111,7 +111,10 @@
     
     private ScoreDoc[] search() throws IOException {
         // create PhraseQuery "term1 term2" and search
-        PhraseQuery pq = new PhraseQuery(field, term1, term2);
+        PhraseQuery pq = new PhraseQuery.Builder(field)
+            .add(term1)
+            .add(term2)
+            .build();
         return this.searcher.search(pq, 1000).scoreDocs;        
     }
     
Index: lucene/core/src/test/org/apache/lucene/index/TestOmitTf.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/index/TestOmitTf.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/index/TestOmitTf.java	(working copy)
@@ -308,7 +308,7 @@
     TermQuery q3 = new TermQuery(c);
     TermQuery q4 = new TermQuery(d);
 
-    PhraseQuery pq = new PhraseQuery(a.field(), a.bytes(), c.bytes());
+    PhraseQuery pq = new PhraseQuery.Builder(a.field()).add(a.bytes()).add(c.bytes()).build();
     try {
       searcher.search(pq, 10);
       fail("did not hit expected exception");
Index: lucene/core/src/test/org/apache/lucene/search/TestBoolean2.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/search/TestBoolean2.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/search/TestBoolean2.java	(working copy)
@@ -335,7 +335,11 @@
       } else if (qType < 4) {
         String t1 = vals[rnd.nextInt(vals.length)];
         String t2 = vals[rnd.nextInt(vals.length)];
-        q = new PhraseQuery(10, field, t1, t2); // slop increases possibility of matching
+        PhraseQuery.Builder builder = new PhraseQuery.Builder(field)
+            .setSlop(10)
+            .add(t1)
+            .add(t2);
+        q = builder.build(); // slop increases possibility of matching
       } else if (qType < 7) {
         q = new WildcardQuery(new Term(field, "w*"));
       } else {
Index: lucene/core/src/test/org/apache/lucene/search/TestBooleanQuery.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/search/TestBooleanQuery.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/search/TestBooleanQuery.java	(working copy)
@@ -113,7 +113,7 @@
     for (BooleanClause clause : q.build()) {
       qq.add(clause);
     }
-    PhraseQuery phrase = new PhraseQuery("field", "not_in_index", "another_not_in_index");
+    PhraseQuery phrase = createPhraseQuery("field", "not_in_index", "another_not_in_index");
     phrase.setBoost(0);
     qq.add(phrase, BooleanClause.Occur.SHOULD);
     score2 = s.search(qq.build(), 10).getMaxScore();
@@ -127,14 +127,14 @@
     assertEquals(score*(2/3F), score2, 1e-6);
 
     // PhraseQuery w/ no terms added returns a null scorer
-    PhraseQuery pq = new PhraseQuery("field", new String[0]);
+    PhraseQuery pq = createPhraseQuery("field", new String[0]);
     q.add(pq, BooleanClause.Occur.SHOULD);
     assertEquals(1, s.search(q.build(), 10).totalHits);
 
     // A required clause which returns null scorer should return null scorer to
     // IndexSearcher.
     q = new BooleanQuery.Builder();
-    pq = new PhraseQuery("field", new String[0]);
+    pq = createPhraseQuery("field", new String[0]);
     q.add(new TermQuery(new Term("field", "a")), BooleanClause.Occur.SHOULD);
     q.add(pq, BooleanClause.Occur.MUST);
     assertEquals(0, s.search(q.build(), 10).totalHits);
@@ -620,7 +620,7 @@
     final IndexSearcher searcher = new IndexSearcher(reader);
     searcher.setQueryCache(null); // to still have approximations
 
-    PhraseQuery pq = new PhraseQuery("field", "a", "b");
+    PhraseQuery pq = createPhraseQuery("field","a","b");
 
     BooleanQuery.Builder q = new BooleanQuery.Builder();
     q.add(pq, Occur.MUST);
@@ -649,7 +649,7 @@
     final IndexSearcher searcher = new IndexSearcher(reader);
     searcher.setQueryCache(null); // to still have approximations
 
-    PhraseQuery pq = new PhraseQuery("field", "a", "b");
+    PhraseQuery pq = createPhraseQuery("field", "a", "b");
 
     BooleanQuery.Builder q = new BooleanQuery.Builder();
     q.add(pq, Occur.SHOULD);
@@ -680,7 +680,7 @@
     final IndexSearcher searcher = new IndexSearcher(reader);
     searcher.setQueryCache(null); // to still have approximations
 
-    PhraseQuery pq = new PhraseQuery("field", "a", "b");
+    PhraseQuery pq = createPhraseQuery("field", "a", "b");
 
     BooleanQuery.Builder q = new BooleanQuery.Builder();
     q.add(pq, Occur.SHOULD);
@@ -709,7 +709,7 @@
     final IndexSearcher searcher = new IndexSearcher(reader);
     searcher.setQueryCache(null); // to still have approximations
 
-    PhraseQuery pq = new PhraseQuery("field", "a", "b");
+    PhraseQuery pq = createPhraseQuery("field", "a", "b");
 
     BooleanQuery.Builder q = new BooleanQuery.Builder();
     q.add(pq, Occur.SHOULD);
@@ -738,7 +738,7 @@
     final IndexSearcher searcher = new IndexSearcher(reader);
     searcher.setQueryCache(null); // to still have approximations
 
-    PhraseQuery pq = new PhraseQuery("field", "a", "b");
+    PhraseQuery pq = createPhraseQuery("field", "a", "b");
 
     BooleanQuery.Builder q = new BooleanQuery.Builder();
     q.add(pq, Occur.MUST);
@@ -784,4 +784,12 @@
     searcher.createNormalizedWeight(bq, false).extractTerms(matchingTerms);
     assertEquals(new HashSet<>(Arrays.asList(a, b, c)), matchingTerms);
   }
+
+  private PhraseQuery createPhraseQuery(String field, String... terms){
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(field);
+    for(String term : terms){
+      builder.add(term);
+    }
+    return builder.build();
+  }
 }
Index: lucene/core/src/test/org/apache/lucene/search/TestComplexExplanations.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/search/TestComplexExplanations.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/search/TestComplexExplanations.java	(working copy)
@@ -60,7 +60,11 @@
     
     BooleanQuery.Builder q = new BooleanQuery.Builder();
 
-    PhraseQuery phraseQuery = new PhraseQuery(1, FIELD, "w1", "w2");
+    PhraseQuery phraseQuery = new PhraseQuery.Builder(FIELD)
+        .setSlop(1)
+        .add("w1")
+        .add("w2")
+        .build();
     q.add(phraseQuery, Occur.MUST);
     q.add(snear(st("w2"),
                 sor("w5","zz"),
@@ -122,7 +126,11 @@
     
     BooleanQuery.Builder q = new BooleanQuery.Builder();
 
-    PhraseQuery phraseQuery = new PhraseQuery(1, FIELD, "w1", "w2");
+    PhraseQuery phraseQuery = new PhraseQuery.Builder(FIELD)
+        .setSlop(1)
+        .add("w1")
+        .add("w2")
+        .build();
     q.add(phraseQuery, Occur.MUST);
     q.add(snear(st("w2"),
                 sor("w5","zz"),
Index: lucene/core/src/test/org/apache/lucene/search/TestConstantScoreQuery.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/search/TestConstantScoreQuery.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/search/TestConstantScoreQuery.java	(working copy)
@@ -240,7 +240,7 @@
     final IndexSearcher searcher = newSearcher(reader);
     searcher.setQueryCache(null); // to still have approximations
 
-    PhraseQuery pq = new PhraseQuery("field", "a", "b");
+    PhraseQuery pq = new PhraseQuery.Builder("field").add("a").add("b").build();
 
     ConstantScoreQuery q = new ConstantScoreQuery(pq);
 
Index: lucene/core/src/test/org/apache/lucene/search/TestLRUQueryCache.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/search/TestLRUQueryCache.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/search/TestLRUQueryCache.java	(working copy)
@@ -853,7 +853,7 @@
       case 2:
         Term t1 = randomTerm();
         Term t2 = randomTerm();
-        PhraseQuery pq = new PhraseQuery(random().nextInt(2), t1.field(), t1.bytes(), t2.bytes());
+        PhraseQuery pq = new PhraseQuery.Builder(t1.field()).setSlop(random().nextInt(2)).add(t1.bytes()).add(t2.bytes()).build();
         return pq;
       case 3:
         return new MatchAllDocsQuery();
Index: lucene/core/src/test/org/apache/lucene/search/TestMultiPhraseQuery.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/search/TestMultiPhraseQuery.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/search/TestMultiPhraseQuery.java	(working copy)
@@ -496,11 +496,11 @@
    * PQ AND Mode - Manually creating a phrase query
    */
   public void testZeroPosIncrSloppyPqAnd() throws IOException {
-    PhraseQuery.Builder builder = new PhraseQuery.Builder();
+    PhraseQuery.Builder builder = new PhraseQuery.Builder("field");
     int pos = -1;
     for (Token tap : INCR_0_QUERY_TOKENS_AND) {
       pos += tap.getPositionIncrement();
-      builder.add(new Term("field", tap.toString()), pos);
+      builder.add(tap.toString(), pos);
     }
     builder.setSlop(0);
     doTestZeroPosIncrSloppy(builder.build(), 0);
Index: lucene/core/src/test/org/apache/lucene/search/TestNGramPhraseQuery.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/search/TestNGramPhraseQuery.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/search/TestNGramPhraseQuery.java	(working copy)
@@ -49,7 +49,7 @@
   
   public void testRewrite() throws Exception {
     // bi-gram test ABC => AB/BC => AB/BC
-    NGramPhraseQuery pq1 = new NGramPhraseQuery(2, new PhraseQuery("f", "AB", "BC"));
+    NGramPhraseQuery pq1 = new NGramPhraseQuery(2, new PhraseQuery.Builder("f").add("AB").add("BC").build());
     
     Query q = pq1.rewrite(reader);
     assertSame(q.rewrite(reader), q);
@@ -58,7 +58,7 @@
     assertArrayEquals(new int[]{0, 1}, rewritten1.getPositions());
 
     // bi-gram test ABCD => AB/BC/CD => AB//CD
-    NGramPhraseQuery pq2 = new NGramPhraseQuery(2, new PhraseQuery("f", "AB", "BC", "CD"));
+    NGramPhraseQuery pq2 = new NGramPhraseQuery(2, new PhraseQuery.Builder("f").add("AB").add("BC").add("CD").build());
     
     q = pq2.rewrite(reader);
     assertTrue(q instanceof PhraseQuery);
@@ -68,8 +68,8 @@
     assertArrayEquals(new int[]{0, 2}, rewritten2.getPositions());
 
     // tri-gram test ABCDEFGH => ABC/BCD/CDE/DEF/EFG/FGH => ABC///DEF//FGH
-    NGramPhraseQuery pq3 = new NGramPhraseQuery(3, new PhraseQuery("f", "ABC", "BCD", "CDE", "DEF", "EFG", "FGH"));
-    
+    NGramPhraseQuery pq3 = new NGramPhraseQuery(3, new PhraseQuery.Builder("f").add("ABC").add("BCD").add("CDE").add("DEF").add("EFG").add("FGH").build());
+
     q = pq3.rewrite(reader);
     assertTrue(q instanceof PhraseQuery);
     assertNotSame(pq3, q);
@@ -78,7 +78,7 @@
     assertArrayEquals(new int[]{0, 3, 5}, rewritten3.getPositions());
     
     // LUCENE-4970: boosting test
-    NGramPhraseQuery pq4 = new NGramPhraseQuery(2, new PhraseQuery("f", "AB", "BC", "CD"));
+    NGramPhraseQuery pq4 = new NGramPhraseQuery(2, new PhraseQuery.Builder("f").add("AB").add("BC").add("CD").build());
     pq4.setBoost(100.0F);
     
     q = pq4.rewrite(reader);
Index: lucene/core/src/test/org/apache/lucene/search/TestPhraseQuery.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/search/TestPhraseQuery.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/search/TestPhraseQuery.java	(working copy)
@@ -109,14 +109,15 @@
   }
 
   public void testNotCloseEnough() throws Exception {
-    query = new PhraseQuery(2, "field", "one", "five");
+    query = createPhraseQuery(2, "field", "one", "five");
     ScoreDoc[] hits = searcher.search(query, 1000).scoreDocs;
     assertEquals(0, hits.length);
     QueryUtils.check(random(), query,searcher);
   }
 
+
   public void testBarelyCloseEnough() throws Exception {
-    query = new PhraseQuery(3, "field", "one", "five");
+    query = createPhraseQuery(3, "field", "one", "five");
     ScoreDoc[] hits = searcher.search(query, 1000).scoreDocs;
     assertEquals(1, hits.length);
     QueryUtils.check(random(), query,searcher);
@@ -127,13 +128,13 @@
    */
   public void testExact() throws Exception {
     // slop is zero by default
-    query = new PhraseQuery("field", "four", "five");
+    query = createPhraseQuery("field", "four", "five");
     ScoreDoc[] hits = searcher.search(query, 1000).scoreDocs;
     assertEquals("exact match", 1, hits.length);
     QueryUtils.check(random(), query,searcher);
 
 
-    query = new PhraseQuery("field", "two", "one");
+    query = createPhraseQuery("field", "two", "one");
     hits = searcher.search(query, 1000).scoreDocs;
     assertEquals("reverse not exact", 0, hits.length);
     QueryUtils.check(random(), query,searcher);
@@ -141,7 +142,7 @@
 
   public void testSlop1() throws Exception {
     // Ensures slop of 1 works with terms in order.
-    query = new PhraseQuery(1, "field", "one", "two");
+    query = createPhraseQuery(1, "field", "one", "two");
     ScoreDoc[] hits = searcher.search(query, 1000).scoreDocs;
     assertEquals("in order", 1, hits.length);
     QueryUtils.check(random(), query,searcher);
@@ -149,7 +150,7 @@
 
     // Ensures slop of 1 does not work for phrases out of order;
     // must be at least 2.
-    query = new PhraseQuery(1, "field", "two", "one");
+    query = createPhraseQuery(1, "field", "two", "one");
     hits = searcher.search(query, 1000).scoreDocs;
     assertEquals("reversed, slop not 2 or more", 0, hits.length);
     QueryUtils.check(random(), query,searcher);
@@ -160,13 +161,13 @@
    */
   public void testOrderDoesntMatter() throws Exception {
     // must be at least two for reverse order match
-    query = new PhraseQuery(2, "field", "two", "one");
+    query = createPhraseQuery(2, "field", "two", "one");
     ScoreDoc[] hits = searcher.search(query, 1000).scoreDocs;
     assertEquals("just sloppy enough", 1, hits.length);
     QueryUtils.check(random(), query,searcher);
 
 
-    query = new PhraseQuery(2, "field", "three", "one");
+    query = createPhraseQuery(2, "field", "three", "one");
     hits = searcher.search(query, 1000).scoreDocs;
     assertEquals("not sloppy enough", 0, hits.length);
     QueryUtils.check(random(), query,searcher);
@@ -178,19 +179,19 @@
    * to line up a phrase
    */
   public void testMultipleTerms() throws Exception {
-    query = new PhraseQuery(2, "field", "one", "three", "five");
+    query = createPhraseQuery(2, "field", "one", "three", "five");
     ScoreDoc[] hits = searcher.search(query, 1000).scoreDocs;
     assertEquals("two total moves", 1, hits.length);
     QueryUtils.check(random(), query,searcher);
 
     // it takes six moves to match this phrase
-    query = new PhraseQuery(5, "field", "five", "three", "one");
+    query = createPhraseQuery(5, "field", "five", "three", "one");
     hits = searcher.search(query, 1000).scoreDocs;
     assertEquals("slop of 5 not close enough", 0, hits.length);
     QueryUtils.check(random(), query,searcher);
 
 
-    query = new PhraseQuery(6, "field", "five", "three", "one");
+    query = createPhraseQuery(6, "field", "five", "three", "one");
     hits = searcher.search(query, 1000).scoreDocs;
     assertEquals("slop of 6 just right", 1, hits.length);
     QueryUtils.check(random(), query,searcher);
@@ -211,7 +212,7 @@
     IndexSearcher searcher = newSearcher(reader);
 
     // valid exact phrase query
-    PhraseQuery query = new PhraseQuery("field", "stop", "words");
+    PhraseQuery query = createPhraseQuery("field", "stop", "words");
     ScoreDoc[] hits = searcher.search(query, 1000).scoreDocs;
     assertEquals(1, hits.length);
     QueryUtils.check(random(), query,searcher);
@@ -238,7 +239,7 @@
     
     IndexSearcher searcher = newSearcher(reader);
     
-    PhraseQuery phraseQuery = new PhraseQuery("source", "marketing", "info");
+    PhraseQuery phraseQuery = createPhraseQuery("source", "marketing", "info");
     ScoreDoc[] hits = searcher.search(phraseQuery, 1000).scoreDocs;
     assertEquals(2, hits.length);
     QueryUtils.check(random(), phraseQuery,searcher);
@@ -275,7 +276,7 @@
     searcher = newSearcher(reader);
     
     termQuery = new TermQuery(new Term("contents","woo"));
-    phraseQuery = new PhraseQuery("contents", "map", "entry");
+    phraseQuery = createPhraseQuery("contents", "map", "entry");
     
     hits = searcher.search(termQuery, 1000).scoreDocs;
     assertEquals(3, hits.length);
@@ -325,7 +326,7 @@
 
     IndexSearcher searcher = newSearcher(reader);
     searcher.setSimilarity(new DefaultSimilarity());
-    PhraseQuery query = new PhraseQuery(Integer.MAX_VALUE, "field", "firstname", "lastname");
+    PhraseQuery query = createPhraseQuery(Integer.MAX_VALUE, "field", "firstname", "lastname");
     ScoreDoc[] hits = searcher.search(query, 1000).scoreDocs;
     assertEquals(3, hits.length);
     // Make sure that those matches where the terms appear closer to
@@ -342,33 +343,33 @@
   }
   
   public void testToString() throws Exception {
-    PhraseQuery q = new PhraseQuery("field", new String[0]);
+    PhraseQuery q = createPhraseQuery("field", new String[0]);
     assertEquals("\"\"", q.toString());
 
-    PhraseQuery.Builder builder = new PhraseQuery.Builder();
-    builder.add(new Term("field", "hi"), 1);
+    PhraseQuery.Builder builder = new PhraseQuery.Builder("field");
+    builder.add("hi", 1);
     q = builder.build();
     assertEquals("field:\"? hi\"", q.toString());
 
     
-    builder = new PhraseQuery.Builder();
-    builder.add(new Term("field", "hi"), 1);
-    builder.add(new Term("field", "test"), 5);
+    builder = new PhraseQuery.Builder("field");
+    builder.add("hi", 1);
+    builder.add("test", 5);
     q = builder.build(); // Query "this hi this is a test is"
 
     assertEquals("field:\"? hi ? ? ? test\"", q.toString());
 
-    builder = new PhraseQuery.Builder();
-    builder.add(new Term("field", "hi"), 1);
-    builder.add(new Term("field", "hello"), 1);
-    builder.add(new Term("field", "test"), 5);
+    builder = new PhraseQuery.Builder("field");
+    builder.add("hi", 1);
+    builder.add("hello", 1);
+    builder.add("test", 5);
     q = builder.build();
     assertEquals("field:\"? hi|hello ? ? ? test\"", q.toString());
 
-    builder = new PhraseQuery.Builder();
-    builder.add(new Term("field", "hi"), 1);
-    builder.add(new Term("field", "hello"), 1);
-    builder.add(new Term("field", "test"), 5);
+    builder = new PhraseQuery.Builder("field");
+    builder.add("hi", 1);
+    builder.add("hello", 1);
+    builder.add("test", 5);
     builder.setSlop(5);
     q = builder.build();
     assertEquals("field:\"? hi|hello ? ? ? test\"~5", q.toString());
@@ -378,13 +379,13 @@
   }
 
   public void testWrappedPhrase() throws IOException {
-    query = new PhraseQuery(100, "repeated", "first", "part", "second", "part");
+    query = createPhraseQuery(100, "repeated", "first", "part", "second", "part");
 
     ScoreDoc[] hits = searcher.search(query, 1000).scoreDocs;
     assertEquals("slop of 100 just right", 1, hits.length);
     QueryUtils.check(random(), query,searcher);
 
-    query = new PhraseQuery(99, "repeated", "first", "part", "second", "part");
+    query = createPhraseQuery(99, "repeated", "first", "part", "second", "part");
 
     hits = searcher.search(query, 1000).scoreDocs;
     assertEquals("slop of 99 not enough", 0, hits.length);
@@ -394,28 +395,28 @@
   // work on two docs like this: "phrase exist notexist exist found"
   public void testNonExistingPhrase() throws IOException {
     // phrase without repetitions that exists in 2 docs
-    query = new PhraseQuery(2, "nonexist", "phrase", "notexist", "found");
+    query = createPhraseQuery(2, "nonexist", "phrase", "notexist", "found");
 
     ScoreDoc[] hits = searcher.search(query, 1000).scoreDocs;
     assertEquals("phrase without repetitions exists in 2 docs", 2, hits.length);
     QueryUtils.check(random(), query,searcher);
 
     // phrase with repetitions that exists in 2 docs
-    query = new PhraseQuery(1, "nonexist", "phrase", "exist", "exist");
+    query = createPhraseQuery(1, "nonexist", "phrase", "exist", "exist");
 
     hits = searcher.search(query, 1000).scoreDocs;
     assertEquals("phrase with repetitions exists in two docs", 2, hits.length);
     QueryUtils.check(random(), query,searcher);
 
     // phrase I with repetitions that does not exist in any doc
-    query = new PhraseQuery(1000, "nonexist", "phrase", "notexist", "phrase");
+    query = createPhraseQuery(1000, "nonexist", "phrase", "notexist", "phrase");
 
     hits = searcher.search(query, 1000).scoreDocs;
     assertEquals("nonexisting phrase with repetitions does not exist in any doc", 0, hits.length);
     QueryUtils.check(random(), query,searcher);
 
     // phrase II with repetitions that does not exist in any doc
-    query = new PhraseQuery(1000, "nonexist", "phrase", "exist", "exist", "exist");
+    query = createPhraseQuery(1000, "nonexist", "phrase", "exist", "exist", "exist");
 
     hits = searcher.search(query, 1000).scoreDocs;
     assertEquals("nonexisting phrase with repetitions does not exist in any doc", 0, hits.length);
@@ -435,7 +436,7 @@
   public void testPalyndrome2() throws Exception {
     
     // search on non palyndrome, find phrase with no slop, using exact phrase scorer
-    query = new PhraseQuery("field", "two", "three"); // to use exact phrase scorer
+    query = createPhraseQuery("field", "two", "three"); // to use exact phrase scorer
     ScoreDoc[] hits = searcher.search(query, 1000).scoreDocs;
     assertEquals("phrase found with exact phrase scorer", 1, hits.length);
     float score0 = hits[0].score;
@@ -443,7 +444,7 @@
     QueryUtils.check(random(), query,searcher);
 
     // search on non palyndrome, find phrase with slop 2, though no slop required here.
-    query = new PhraseQuery("field", "two", "three"); // to use sloppy scorer 
+    query = createPhraseQuery("field", "two", "three"); // to use sloppy scorer
     hits = searcher.search(query, 1000).scoreDocs;
     assertEquals("just sloppy enough", 1, hits.length);
     float score1 = hits[0].score;
@@ -452,7 +453,7 @@
     QueryUtils.check(random(), query,searcher);
 
     // search ordered in palyndrome, find it twice
-    query = new PhraseQuery(2, "palindrome", "two", "three"); // must be at least two for both ordered and reversed to match
+    query = createPhraseQuery(2, "palindrome", "two", "three"); // must be at least two for both ordered and reversed to match
     hits = searcher.search(query, 1000).scoreDocs;
     assertEquals("just sloppy enough", 1, hits.length);
     //float score2 = hits[0].score;
@@ -463,7 +464,7 @@
     //assertTrue("ordered scores higher in palindrome",score1+SCORE_COMP_THRESH<score2);
 
     // search reveresed in palyndrome, find it twice
-    query = new PhraseQuery(2, "palindrome", "three", "two"); // must be at least two for both ordered and reversed to match
+    query = createPhraseQuery(2, "palindrome", "three", "two"); // must be at least two for both ordered and reversed to match
     hits = searcher.search(query, 1000).scoreDocs;
     assertEquals("just sloppy enough", 1, hits.length);
     //float score3 = hits[0].score;
@@ -488,7 +489,7 @@
     
     // search on non palyndrome, find phrase with no slop, using exact phrase scorer
     // slop=0 to use exact phrase scorer
-    query = new PhraseQuery(0, "field", "one", "two", "three");
+    query = createPhraseQuery(0, "field", "one", "two", "three");
     ScoreDoc[] hits = searcher.search(query, 1000).scoreDocs;
     assertEquals("phrase found with exact phrase scorer", 1, hits.length);
     float score0 = hits[0].score;
@@ -500,7 +501,7 @@
 
     // search on non palyndrome, find phrase with slop 3, though no slop required here.
     // slop=4 to use sloppy scorer
-    query = new PhraseQuery(4, "field", "one", "two", "three");
+    query = createPhraseQuery(4, "field", "one", "two", "three");
     hits = searcher.search(query, 1000).scoreDocs;
     assertEquals("just sloppy enough", 1, hits.length);
     float score1 = hits[0].score;
@@ -510,7 +511,7 @@
 
     // search ordered in palyndrome, find it twice
     // slop must be at least four for both ordered and reversed to match
-    query = new PhraseQuery(4, "palindrome", "one", "two", "three");
+    query = createPhraseQuery(4, "palindrome", "one", "two", "three");
     hits = searcher.search(query, 1000).scoreDocs;
 
     // just make sure no exc:
@@ -526,7 +527,7 @@
 
     // search reveresed in palyndrome, find it twice
     // must be at least four for both ordered and reversed to match
-    query = new PhraseQuery(4, "palindrome", "three", "two", "one");
+    query = createPhraseQuery(4, "palindrome", "three", "two", "one");
     hits = searcher.search(query, 1000).scoreDocs;
     assertEquals("just sloppy enough", 1, hits.length);
     //float score3 = hits[0].score;
@@ -541,13 +542,13 @@
   // LUCENE-1280
   public void testEmptyPhraseQuery() throws Throwable {
     final BooleanQuery.Builder q2 = new BooleanQuery.Builder();
-    q2.add(new PhraseQuery("field", new String[0]), BooleanClause.Occur.MUST);
+    q2.add(createPhraseQuery("field", new String[0]), BooleanClause.Occur.MUST);
     q2.build().toString();
   }
   
   /* test that a single term is rewritten to a term query */
   public void testRewrite() throws IOException {
-    PhraseQuery pq = new PhraseQuery("foo", "bar");
+    PhraseQuery pq = createPhraseQuery("foo", "bar");
     Query rewritten = pq.rewrite(searcher.getIndexReader());
     assertTrue(rewritten instanceof TermQuery);
   }
@@ -621,10 +622,10 @@
       
       final int numTerm = TestUtil.nextInt(r, 2, 20);
       final int start = r.nextInt(doc.size()-numTerm);
-      PhraseQuery.Builder builder = new PhraseQuery.Builder();
+      PhraseQuery.Builder builder = new PhraseQuery.Builder("f");
       StringBuilder sb = new StringBuilder();
       for(int t=start;t<start+numTerm;t++) {
-        builder.add(new Term("f", doc.get(t)), t);
+        builder.add(doc.get(t), t);
         sb.append(doc.get(t)).append(' ');
       }
       PhraseQuery pq = builder.build();
@@ -647,7 +648,7 @@
   
   public void testNegativeSlop() throws Exception {
     try {
-      new PhraseQuery(-2, "field", "two", "one");
+      createPhraseQuery(-2, "field", "two", "one");
       fail("didn't get expected exception");
     } catch (IllegalArgumentException expected) {
       // expected exception
@@ -655,9 +656,9 @@
   }
 
   public void testNegativePosition() throws Exception {
-    PhraseQuery.Builder builder = new PhraseQuery.Builder();
+    PhraseQuery.Builder builder = new PhraseQuery.Builder("field");
     try {
-      builder.add(new Term("field", "two"), -42);
+      builder.add("two", -42);
       fail("didn't get expected exception");
     } catch (IllegalArgumentException expected) {
       // expected exception
@@ -665,14 +666,31 @@
   }
 
   public void testBackwardPositions() throws Exception {
-    PhraseQuery.Builder builder = new PhraseQuery.Builder();
-    builder.add(new Term("field", "one"), 1);
-    builder.add(new Term("field", "two"), 5);
+    PhraseQuery.Builder builder = new PhraseQuery.Builder("field");
+    builder.add("one", 1);
+    builder.add("two", 5);
     try {
-      builder.add(new Term("field", "three"), 4);
+      builder.add("three", 4);
       fail("didn't get expected exception");
     } catch (IllegalArgumentException expected) {
       // expected exception
     }
   }
+
+  private PhraseQuery createPhraseQuery(int slop, String field, String... terms) {
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(field)
+        .setSlop(slop);
+    for (String term : terms){
+      builder.add(term);
+    }
+    return builder.build();
+  }
+
+  private PhraseQuery createPhraseQuery(String field, String... terms) {
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(field);
+    for (String term : terms){
+      builder.add(term);
+    }
+    return builder.build();
+  }
 }
Index: lucene/core/src/test/org/apache/lucene/search/TestPositionIncrement.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/search/TestPositionIncrement.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/search/TestPositionIncrement.java	(working copy)
@@ -123,55 +123,55 @@
     PhraseQuery q;
     ScoreDoc[] hits;
 
-    q = new PhraseQuery("field", "1", "2");
+    q = createPhraseQuery("field", "1", "2");
     hits = searcher.search(q, 1000).scoreDocs;
     assertEquals(0, hits.length);
 
     // same as previous, using the builder with implicit positions
-    PhraseQuery.Builder builder = new PhraseQuery.Builder();
-    builder.add(new Term("field", "1"));
-    builder.add(new Term("field", "2"));
+    PhraseQuery.Builder builder = new PhraseQuery.Builder("field");
+    builder.add("1");
+    builder.add("2");
     q = builder.build();
     hits = searcher.search(q, 1000).scoreDocs;
     assertEquals(0, hits.length);
 
     // same as previous, just specify positions explicitely.
-    builder = new PhraseQuery.Builder();
-    builder.add(new Term("field", "1"), 0);
-    builder.add(new Term("field", "2"), 1);
+    builder = new PhraseQuery.Builder("field");
+    builder.add("1", 0);
+    builder.add("2", 1);
     q = builder.build();
     hits = searcher.search(q, 1000).scoreDocs;
     assertEquals(0, hits.length);
 
     // specifying correct positions should find the phrase.
-    builder = new PhraseQuery.Builder();
-    builder.add(new Term("field", "1"), 0);
-    builder.add(new Term("field", "2"), 2);
+    builder = new PhraseQuery.Builder("field");
+    builder.add("1", 0);
+    builder.add("2", 2);
     q = builder.build();
     hits = searcher.search(q, 1000).scoreDocs;
     assertEquals(1, hits.length);
 
-    q = new PhraseQuery("field", "2", "3");
+    q = createPhraseQuery("field", "2", "3");
     hits = searcher.search(q, 1000).scoreDocs;
     assertEquals(1, hits.length);
 
-    q = new PhraseQuery("field", "3", "4");
+    q = createPhraseQuery("field", "3", "4");
     hits = searcher.search(q, 1000).scoreDocs;
     assertEquals(0, hits.length);
 
     // phrase query would find it when correct positions are specified. 
-    builder = new PhraseQuery.Builder();
-    builder.add(new Term("field", "3"), 0);
-    builder.add(new Term("field", "4"), 0);
+    builder = new PhraseQuery.Builder("field");
+    builder.add("3", 0);
+    builder.add("4", 0);
     q = builder.build();
     hits = searcher.search(q, 1000).scoreDocs;
     assertEquals(1, hits.length);
 
     // phrase query should fail for non existing searched term 
     // even if there exist another searched terms in the same searched position. 
-    builder = new PhraseQuery.Builder();
-    builder.add(new Term("field", "3"), 0);
-    builder.add(new Term("field", "9"), 0);
+    builder = new PhraseQuery.Builder("field");
+    builder.add("3", 0);
+    builder.add("9", 0);
     q = builder.build();
     hits = searcher.search(q, 1000).scoreDocs;
     assertEquals(0, hits.length);
@@ -183,19 +183,19 @@
     hits = searcher.search(mq, 1000).scoreDocs;
     assertEquals(1, hits.length);
 
-    q = new PhraseQuery("field", "2", "4");
+    q = createPhraseQuery("field", "2", "4");
     hits = searcher.search(q, 1000).scoreDocs;
     assertEquals(1, hits.length);
 
-    q = new PhraseQuery("field", "3", "5");
+    q = createPhraseQuery("field", "3", "5");
     hits = searcher.search(q, 1000).scoreDocs;
     assertEquals(1, hits.length);
 
-    q = new PhraseQuery("field", "4", "5");
+    q = createPhraseQuery("field", "4", "5");
     hits = searcher.search(q, 1000).scoreDocs;
     assertEquals(1, hits.length);
 
-    q = new PhraseQuery("field", "2", "5");
+    q = createPhraseQuery("field", "2", "5");
     hits = searcher.search(q, 1000).scoreDocs;
     assertEquals(0, hits.length);
     
@@ -293,4 +293,12 @@
     is.getIndexReader().close();
     dir.close();
   }
+
+  private PhraseQuery createPhraseQuery(String field, String... terms) {
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(field);
+    for (String term : terms){
+      builder.add(term);
+    }
+    return builder.build();
+  }
 }
Index: lucene/core/src/test/org/apache/lucene/search/TestQueryRescorer.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/search/TestQueryRescorer.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/search/TestQueryRescorer.java	(working copy)
@@ -79,7 +79,11 @@
     assertEquals("1", searcher.doc(hits.scoreDocs[1].doc).get("id"));
 
     // Now, resort using PhraseQuery:
-    PhraseQuery pq = new PhraseQuery(5, "field", "wizard", "oz");
+    PhraseQuery pq = new PhraseQuery.Builder("field")
+        .setSlop(5)
+        .add("wizard")
+        .add("oz")
+        .build();
 
     TopDocs hits2 = QueryRescorer.rescore(searcher, hits, pq, 2.0, 10);
 
@@ -173,8 +177,12 @@
 
     // Now, resort using PhraseQuery, but with an
     // opposite-world combine:
-    PhraseQuery pq = new PhraseQuery(5, "field", "wizard", "oz");
-    
+    PhraseQuery pq = new PhraseQuery.Builder("field")
+        .setSlop(5)
+        .add("wizard")
+        .add("oz")
+        .build();
+
     TopDocs hits2 = new QueryRescorer(pq) {
         @Override
         protected float combine(float firstPassScore, boolean secondPassMatches, float secondPassScore) {
@@ -223,7 +231,10 @@
     assertEquals("1", searcher.doc(hits.scoreDocs[1].doc).get("id"));
 
     // Now, resort using PhraseQuery:
-    PhraseQuery pq = new PhraseQuery("field", "wizard", "oz");
+    PhraseQuery pq = new PhraseQuery.Builder("field")
+        .add("wizard")
+        .add("oz")
+        .build();
 
     Rescorer rescorer = new QueryRescorer(pq) {
         @Override
@@ -298,7 +309,10 @@
     assertEquals("1", searcher.doc(hits.scoreDocs[1].doc).get("id"));
 
     // Now, resort using PhraseQuery, no slop:
-    PhraseQuery pq = new PhraseQuery("field", "wizard", "oz");
+    PhraseQuery pq = new PhraseQuery.Builder("field")
+        .add("wizard")
+        .add("oz")
+        .build();
 
     TopDocs hits2 = QueryRescorer.rescore(searcher, hits, pq, 2.0, 10);
 
Index: lucene/core/src/test/org/apache/lucene/search/TestScorerPerf.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/search/TestScorerPerf.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/search/TestScorerPerf.java	(working copy)
@@ -324,10 +324,10 @@
 
     for (int i=0; i<iter; i++) {
       int nClauses = random().nextInt(maxClauses-1)+2; // min 2 clauses
-      PhraseQuery.Builder builder = new PhraseQuery.Builder();
+      PhraseQuery.Builder builder = new PhraseQuery.Builder("f");
       for (int j=0; j<nClauses; j++) {
         int tnum = random().nextInt(termsInIndex);
-        builder.add(new Term("f", Character.toString((char)(tnum+'A'))));
+        builder.add(Character.toString((char)(tnum+'A')));
       }
       // slop could be random too
       builder.setSlop(termsInIndex);
Index: lucene/core/src/test/org/apache/lucene/search/TestSimilarity.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/search/TestSimilarity.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/search/TestSimilarity.java	(working copy)
@@ -118,7 +118,10 @@
          }
        });
 
-    PhraseQuery pq = new PhraseQuery(a.field(), a.bytes(), c.bytes());
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(a.field())
+        .add(a.bytes())
+        .add(c.bytes());
+    PhraseQuery pq = builder.build();
     //System.out.println(pq.toString("field"));
     searcher.search(pq,
        new SimpleCollector() {
@@ -138,7 +141,11 @@
          }
        });
 
-    pq = new PhraseQuery(2, a.field(), a.bytes(), c.bytes());
+    builder = new PhraseQuery.Builder(a.field())
+        .setSlop(2)
+        .add(a.bytes())
+        .add(c.bytes());
+    pq = builder.build();
     //System.out.println(pq.toString("field"));
     searcher.search(pq, new SimpleCollector() {
       private Scorer scorer;
Index: lucene/core/src/test/org/apache/lucene/search/TestSimpleExplanations.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/search/TestSimpleExplanations.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/search/TestSimpleExplanations.java	(working copy)
@@ -54,31 +54,52 @@
   /* some simple phrase tests */
   
   public void testP1() throws Exception {
-    PhraseQuery phraseQuery = new PhraseQuery(FIELD, "w1", "w2");
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(FIELD)
+        .add("w1")
+        .add("w2");
+    PhraseQuery phraseQuery = builder.build();
     qtest(phraseQuery, new int[] { 0 });
   }
   public void testP2() throws Exception {
-    PhraseQuery phraseQuery = new PhraseQuery(FIELD, "w1", "w3");
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(FIELD)
+        .add("w1")
+        .add("w3");
+    PhraseQuery phraseQuery = builder.build();
     qtest(phraseQuery, new int[] { 1,3 });
   }
   public void testP3() throws Exception {
-    PhraseQuery phraseQuery = new PhraseQuery(1, FIELD, "w1", "w2");
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(FIELD)
+        .add("w1")
+        .add("w2");
+    PhraseQuery phraseQuery = builder.build();
     qtest(phraseQuery, new int[] { 0,1,2 });
   }
   public void testP4() throws Exception {
-    PhraseQuery phraseQuery = new PhraseQuery(1, FIELD, "w2", "w3");
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(FIELD)
+        .add("w2")
+        .add("w3");
+    PhraseQuery phraseQuery = builder.build();
     qtest(phraseQuery, new int[] { 0,1,2,3 });
   }
   public void testP5() throws Exception {
-    PhraseQuery phraseQuery = new PhraseQuery(1, FIELD, "w3", "w2");
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(FIELD)
+        .add("w3")
+        .add("w2");
+    PhraseQuery phraseQuery = builder.build();
     qtest(phraseQuery, new int[] { 1,3 });
   }
   public void testP6() throws Exception {
-    PhraseQuery phraseQuery = new PhraseQuery(2, FIELD, "w3", "w2");
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(FIELD)
+        .add("w3")
+        .add("w2");
+    PhraseQuery phraseQuery = builder.build();
     qtest(phraseQuery, new int[] { 0,1,3 });
   }
   public void testP7() throws Exception {
-    PhraseQuery phraseQuery = new PhraseQuery(3, FIELD, "w3", "w2");
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(FIELD)
+        .add("w3")
+        .add("w2");
+    PhraseQuery phraseQuery = builder.build();
     qtest(phraseQuery, new int[] { 0,1,2,3 });
   }
 
@@ -612,10 +633,16 @@
   public void testMultiFieldBQofPQ1() throws Exception {
     BooleanQuery.Builder query = new BooleanQuery.Builder();
 
-    PhraseQuery leftChild = new PhraseQuery(FIELD, "w1", "w2");
+    PhraseQuery.Builder leftChildBuilder = new PhraseQuery.Builder(FIELD)
+        .add("w1")
+        .add("w2");
+    PhraseQuery leftChild = leftChildBuilder.build();
     query.add(leftChild, BooleanClause.Occur.SHOULD);
 
-    PhraseQuery rightChild = new PhraseQuery(ALTFIELD, "w1", "w2");
+    PhraseQuery.Builder rightChildBuilder = new PhraseQuery.Builder(ALTFIELD)
+        .add("w1")
+        .add("w2");
+    PhraseQuery rightChild = rightChildBuilder.build();
     query.add(rightChild, BooleanClause.Occur.SHOULD);
 
     qtest(query.build(), new int[] { 0 });
@@ -623,10 +650,16 @@
   public void testMultiFieldBQofPQ2() throws Exception {
     BooleanQuery.Builder query = new BooleanQuery.Builder();
 
-    PhraseQuery leftChild = new PhraseQuery(FIELD, "w1", "w3");
+    PhraseQuery.Builder leftChildBuilder = new PhraseQuery.Builder(FIELD)
+        .add("w1")
+        .add("w3");
+    PhraseQuery leftChild = leftChildBuilder.build();
     query.add(leftChild, BooleanClause.Occur.SHOULD);
 
-    PhraseQuery rightChild = new PhraseQuery(ALTFIELD, "w1", "w3");
+    PhraseQuery.Builder rightChildBuilder = new PhraseQuery.Builder(ALTFIELD)
+        .add("w1")
+        .add("w3");
+    PhraseQuery rightChild = rightChildBuilder.build();
     query.add(rightChild, BooleanClause.Occur.SHOULD);
 
     qtest(query.build(), new int[] { 1,3 });
@@ -634,10 +667,18 @@
   public void testMultiFieldBQofPQ3() throws Exception {
     BooleanQuery.Builder query = new BooleanQuery.Builder();
 
-    PhraseQuery leftChild = new PhraseQuery(1, FIELD, "w1", "w2");
+    PhraseQuery.Builder leftChildBuilder = new PhraseQuery.Builder(FIELD)
+        .setSlop(1)
+        .add("w1")
+        .add("w2");
+    PhraseQuery leftChild = leftChildBuilder.build();
     query.add(leftChild, BooleanClause.Occur.SHOULD);
 
-    PhraseQuery rightChild = new PhraseQuery(1, ALTFIELD, "w1", "w2");
+    PhraseQuery.Builder rightChildBuilder = new PhraseQuery.Builder(ALTFIELD)
+        .setSlop(1)
+        .add("w1")
+        .add("w3");
+    PhraseQuery rightChild = rightChildBuilder.build();
     query.add(rightChild, BooleanClause.Occur.SHOULD);
 
     qtest(query.build(), new int[] { 0,1,2 });
@@ -645,10 +686,18 @@
   public void testMultiFieldBQofPQ4() throws Exception {
     BooleanQuery.Builder query = new BooleanQuery.Builder();
 
-    PhraseQuery leftChild = new PhraseQuery(1, FIELD, "w2", "w3");
+    PhraseQuery.Builder leftChildBuilder = new PhraseQuery.Builder(FIELD)
+        .setSlop(1)
+        .add("w2")
+        .add("w3");
+    PhraseQuery leftChild = leftChildBuilder.build();
     query.add(leftChild, BooleanClause.Occur.SHOULD);
 
-    PhraseQuery rightChild = new PhraseQuery(1, ALTFIELD, "w2", "w3");
+    PhraseQuery.Builder rightChildBuilder = new PhraseQuery.Builder(ALTFIELD)
+        .setSlop(1)
+        .add("w2")
+        .add("w3");
+    PhraseQuery rightChild = rightChildBuilder.build();
     query.add(rightChild, BooleanClause.Occur.SHOULD);
 
     qtest(query.build(), new int[] { 0,1,2,3 });
@@ -656,10 +705,18 @@
   public void testMultiFieldBQofPQ5() throws Exception {
     BooleanQuery.Builder query = new BooleanQuery.Builder();
 
-    PhraseQuery leftChild = new PhraseQuery(1, FIELD, "w3", "w2");
+    PhraseQuery.Builder leftChildBuilder = new PhraseQuery.Builder(FIELD)
+        .setSlop(1)
+        .add("w3")
+        .add("w2");
+    PhraseQuery leftChild = leftChildBuilder.build();
     query.add(leftChild, BooleanClause.Occur.SHOULD);
 
-    PhraseQuery rightChild = new PhraseQuery(1, ALTFIELD, "w3", "w2");
+    PhraseQuery.Builder rightChildBuilder = new PhraseQuery.Builder(ALTFIELD)
+        .setSlop(1)
+        .add("w3")
+        .add("w2");
+    PhraseQuery rightChild = rightChildBuilder.build();
     query.add(rightChild, BooleanClause.Occur.SHOULD);
 
     qtest(query.build(), new int[] { 1,3 });
@@ -667,10 +724,18 @@
   public void testMultiFieldBQofPQ6() throws Exception {
     BooleanQuery.Builder query = new BooleanQuery.Builder();
 
-    PhraseQuery leftChild = new PhraseQuery(2, FIELD, "w3", "w2");
+    PhraseQuery.Builder leftChildBuilder = new PhraseQuery.Builder(FIELD)
+        .setSlop(2)
+        .add("w3")
+        .add("w2");
+    PhraseQuery leftChild = leftChildBuilder.build();
     query.add(leftChild, BooleanClause.Occur.SHOULD);
 
-    PhraseQuery rightChild = new PhraseQuery(2, ALTFIELD, "w3", "w2");
+    PhraseQuery.Builder rightChildBuilder = new PhraseQuery.Builder(ALTFIELD)
+        .setSlop(2)
+        .add("w3")
+        .add("w2");
+    PhraseQuery rightChild = rightChildBuilder.build();
     query.add(rightChild, BooleanClause.Occur.SHOULD);
 
     qtest(query.build(), new int[] { 0,1,3 });
@@ -678,10 +743,18 @@
   public void testMultiFieldBQofPQ7() throws Exception {
     BooleanQuery.Builder query = new BooleanQuery.Builder();
 
-    PhraseQuery leftChild = new PhraseQuery(3, FIELD, "w3", "w2");
+    PhraseQuery.Builder leftChildBuilder = new PhraseQuery.Builder(FIELD)
+        .setSlop(3)
+        .add("w3")
+        .add("w2");
+    PhraseQuery leftChild = leftChildBuilder.build();
     query.add(leftChild, BooleanClause.Occur.SHOULD);
 
-    PhraseQuery rightChild = new PhraseQuery(1, ALTFIELD, "w3", "w2");
+    PhraseQuery.Builder rightChildBuilder = new PhraseQuery.Builder(ALTFIELD)
+        .setSlop(1)
+        .add("w3")
+        .add("w2");
+    PhraseQuery rightChild = rightChildBuilder.build();
     query.add(rightChild, BooleanClause.Occur.SHOULD);
 
     qtest(query.build(), new int[] { 0,1,2,3 });
Index: lucene/core/src/test/org/apache/lucene/search/TestSimpleSearchEquivalence.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/search/TestSimpleSearchEquivalence.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/search/TestSimpleSearchEquivalence.java	(working copy)
@@ -92,7 +92,10 @@
   public void testExactPhraseVersusBooleanAnd() throws Exception {
     Term t1 = randomTerm();
     Term t2 = randomTerm();
-    PhraseQuery q1 = new PhraseQuery(t1.field(), t1.bytes(), t2.bytes());
+    PhraseQuery q1 = new PhraseQuery.Builder(t1.field())
+        .add(t1.bytes())
+        .add(t2.bytes())
+        .build();
     BooleanQuery.Builder q2 = new BooleanQuery.Builder();
     q2.add(new TermQuery(t1), Occur.MUST);
     q2.add(new TermQuery(t2), Occur.MUST);
@@ -103,9 +106,9 @@
   public void testExactPhraseVersusBooleanAndWithHoles() throws Exception {
     Term t1 = randomTerm();
     Term t2 = randomTerm();
-    PhraseQuery.Builder builder = new PhraseQuery.Builder();
-    builder.add(t1, 0);
-    builder.add(t2, 2);
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(t1.field());
+    builder.add(t1.bytes(), 0);
+    builder.add(t2.bytes(), 2);
     PhraseQuery q1 = builder.build();
     BooleanQuery.Builder q2 = new BooleanQuery.Builder();
     q2.add(new TermQuery(t1), Occur.MUST);
@@ -117,8 +120,15 @@
   public void testPhraseVersusSloppyPhrase() throws Exception {
     Term t1 = randomTerm();
     Term t2 = randomTerm();
-    PhraseQuery q1 = new PhraseQuery(t1.field(), t1.bytes(), t2.bytes());
-    PhraseQuery q2 = new PhraseQuery(1, t1.field(), t1.bytes(), t2.bytes());
+    PhraseQuery q1 = new PhraseQuery.Builder(t1.field())
+        .add(t1.bytes())
+        .add(t2.bytes())
+        .build();
+    PhraseQuery q2 = new PhraseQuery.Builder(t1.field())
+        .setSlop(1)
+        .add(t1.bytes())
+        .add(t2.bytes())
+        .build();
     assertSubsetOf(q1, q2);
   }
   
@@ -126,9 +136,9 @@
   public void testPhraseVersusSloppyPhraseWithHoles() throws Exception {
     Term t1 = randomTerm();
     Term t2 = randomTerm();
-    PhraseQuery.Builder builder = new PhraseQuery.Builder();
-    builder.add(t1, 0);
-    builder.add(t2, 2);
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(t1.field());
+    builder.add(t1.bytes(), 0);
+    builder.add(t2.bytes(), 2);
     PhraseQuery q1 = builder.build();
     builder.setSlop(2);
     PhraseQuery q2 = builder.build();
@@ -139,7 +149,10 @@
   public void testExactPhraseVersusMultiPhrase() throws Exception {
     Term t1 = randomTerm();
     Term t2 = randomTerm();
-    PhraseQuery q1 = new PhraseQuery(t1.field(), t1.bytes(), t2.bytes());
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(t1.field())
+        .add(t1.bytes())
+        .add(t2.bytes());
+    PhraseQuery q1 = builder.build();
     Term t3 = randomTerm();
     MultiPhraseQuery q2 = new MultiPhraseQuery();
     q2.add(t1);
@@ -151,9 +164,9 @@
   public void testExactPhraseVersusMultiPhraseWithHoles() throws Exception {
     Term t1 = randomTerm();
     Term t2 = randomTerm();
-    PhraseQuery.Builder builder = new PhraseQuery.Builder();
-    builder.add(t1, 0);
-    builder.add(t2, 2);
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(t1.field());
+    builder.add(t1.bytes(), 0);
+    builder.add(t2.bytes(), 2);
     PhraseQuery q1 = builder.build();
     Term t3 = randomTerm();
     MultiPhraseQuery q2 = new MultiPhraseQuery();
@@ -171,7 +184,11 @@
     do {
       t2 = randomTerm();
     } while (t1.equals(t2));
-    PhraseQuery q1 = new PhraseQuery(Integer.MAX_VALUE, t1.field(), t1.bytes(), t2.bytes());
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(t1.field())
+        .setSlop(Integer.MAX_VALUE)
+        .add(t1.bytes())
+        .add(t2.bytes());
+    PhraseQuery q1 = builder.build();
     BooleanQuery.Builder q2 = new BooleanQuery.Builder();
     q2.add(new TermQuery(t1), Occur.MUST);
     q2.add(new TermQuery(t2), Occur.MUST);
@@ -182,10 +199,13 @@
   public void testPhraseRelativePositions() throws Exception {
     Term t1 = randomTerm();
     Term t2 = randomTerm();
-    PhraseQuery q1 = new PhraseQuery(t1.field(), t1.bytes(), t2.bytes());
-    PhraseQuery.Builder builder = new PhraseQuery.Builder();
-    builder.add(t1, 10000);
-    builder.add(t2, 10001);
+    PhraseQuery q1 = new PhraseQuery.Builder(t1.field())
+        .add(t1.bytes())
+        .add(t2.bytes())
+        .build();
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(t1.field());
+    builder.add(t1.bytes(), 10000);
+    builder.add(t2.bytes(), 10001);
     PhraseQuery q2 = builder.build();
     assertSameScores(q1, q2);
   }
@@ -194,11 +214,16 @@
   public void testSloppyPhraseRelativePositions() throws Exception {
     Term t1 = randomTerm();
     Term t2 = randomTerm();
-    PhraseQuery q1 = new PhraseQuery(2, t1.field(), t1.bytes(), t2.bytes());
-    PhraseQuery.Builder builder = new PhraseQuery.Builder();
-    builder.add(t1, 10000);
-    builder.add(t2, 10001);
-    builder.setSlop(2);
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(t1.field())
+        .setSlop(2)
+        .add(t1.bytes())
+        .add(t2.bytes());
+    PhraseQuery q1 = builder.build();
+
+    builder = new PhraseQuery.Builder(t1.field())
+        .setSlop(2)
+        .add(t1.bytes(), 10000)
+        .add(t2.bytes(), 10001);
     PhraseQuery q2 = builder.build();
     assertSameScores(q1, q2);
   }
Index: lucene/core/src/test/org/apache/lucene/search/TestSloppyPhraseQuery.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/search/TestSloppyPhraseQuery.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/search/TestSloppyPhraseQuery.java	(working copy)
@@ -135,11 +135,11 @@
   }
   
   private float  checkPhraseQuery(Document doc, PhraseQuery query, int slop, int expectedNumResults) throws Exception {
-    PhraseQuery.Builder builder = new PhraseQuery.Builder();
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(query.getField());
     Term[] terms = query.getTerms();
     int[] positions = query.getPositions();
     for (int i = 0; i < terms.length; ++i) {
-      builder.add(terms[i], positions[i]);
+      builder.add(terms[i].bytes(), positions[i]);
     }
     builder.setSlop(slop);
     query = builder.build();
@@ -176,7 +176,11 @@
 
   private static PhraseQuery makePhraseQuery(String terms) {
     String[] t = terms.split(" +");
-    return new PhraseQuery("f", t);
+    PhraseQuery.Builder builder = new PhraseQuery.Builder("f");
+    for (String term : t){
+      builder.add(term);
+    }
+    return builder.build();
   }
 
   static class MaxFreqCollector extends SimpleCollector {
@@ -246,9 +250,9 @@
     iw.close();
     IndexSearcher is = newSearcher(ir);
 
-    PhraseQuery.Builder builder = new PhraseQuery.Builder();
-    builder.add(new Term("lyrics", "drug"), 1);
-    builder.add(new Term("lyrics", "drug"), 4);
+    PhraseQuery.Builder builder = new PhraseQuery.Builder("lyrics");
+    builder.add("drug", 1);
+    builder.add("drug", 4);
     PhraseQuery pq = builder.build();
     // "drug the drug"~1
     assertEquals(1, is.search(pq, 4).totalHits);
@@ -275,9 +279,9 @@
     iw.close();
     
     IndexSearcher is = newSearcher(ir);
-    PhraseQuery.Builder builder = new PhraseQuery.Builder();
-    builder.add(new Term("lyrics", "drug"), 1);
-    builder.add(new Term("lyrics", "drug"), 3);
+    PhraseQuery.Builder builder = new PhraseQuery.Builder("lyrics");
+    builder.add("drug", 1);
+    builder.add("drug", 3);
     builder.setSlop(1);
     PhraseQuery pq = builder.build();
     // "drug the drug"~1
@@ -330,9 +334,9 @@
         
      IndexSearcher is = newSearcher(ir);
      
-     PhraseQuery.Builder builder = new PhraseQuery.Builder();
-     builder.add(new Term("lyrics", "drug"), 1);
-     builder.add(new Term("lyrics", "drug"), 4);
+     PhraseQuery.Builder builder = new PhraseQuery.Builder("lyrics");
+     builder.add("drug", 1);
+     builder.add("drug", 4);
      builder.setSlop(5);
      PhraseQuery pq = builder.build();
      // "drug the drug"~5
Index: lucene/core/src/test/org/apache/lucene/search/TestSloppyPhraseQuery2.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/search/TestSloppyPhraseQuery2.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/search/TestSloppyPhraseQuery2.java	(working copy)
@@ -31,8 +31,16 @@
     Term t1 = randomTerm();
     Term t2 = randomTerm();
     for (int i = 0; i < 10; i++) {
-      PhraseQuery q1 = new PhraseQuery(i, t1.field(), t1.bytes(), t2.bytes());
-      PhraseQuery q2 = new PhraseQuery(i + 1, t1.field(), t1.bytes(), t2.bytes());
+      PhraseQuery q1 = new PhraseQuery.Builder(t1.field())
+          .setSlop(i)
+          .add(t1.bytes())
+          .add(t2.bytes())
+          .build();
+      PhraseQuery q2 = new PhraseQuery.Builder(t1.field())
+          .setSlop(i+1)
+          .add(t1.bytes())
+          .add(t2.bytes())
+          .build();
       assertSubsetOf(q1, q2);
     }
   }
@@ -42,9 +50,9 @@
     Term t1 = randomTerm();
     Term t2 = randomTerm();
     for (int i = 0; i < 10; i++) {
-      PhraseQuery.Builder builder = new PhraseQuery.Builder();
-      builder.add(t1, 0);
-      builder.add(t2, 2);
+      PhraseQuery.Builder builder = new PhraseQuery.Builder(t1.field());
+      builder.add(t1.bytes(), 0);
+      builder.add(t2.bytes(), 2);
       builder.setSlop(i);
       PhraseQuery q1 = builder.build();
       builder.setSlop(i + 1);
@@ -59,8 +67,18 @@
     Term t2 = randomTerm();
     Term t3 = randomTerm();
     for (int i = 0; i < 10; i++) {
-      PhraseQuery q1 = new PhraseQuery(i, t1.field(), t1.bytes(), t2.bytes(), t3.bytes());
-      PhraseQuery q2 = new PhraseQuery(i + 1, t1.field(), t1.bytes(), t2.bytes(), t3.bytes());
+      PhraseQuery q1 = new PhraseQuery.Builder(t1.field())
+          .setSlop(i)
+          .add(t1.bytes())
+          .add(t2.bytes())
+          .add(t3.bytes())
+          .build();
+      PhraseQuery q2 = new PhraseQuery.Builder(t1.field())
+          .setSlop(i+1)
+          .add(t1.bytes())
+          .add(t2.bytes())
+          .add(t3.bytes())
+          .build();
       assertSubsetOf(q1, q2);
       assertSubsetOf(q1, q2);
     }
@@ -74,10 +92,10 @@
     int pos1 = 1 + random().nextInt(3);
     int pos2 = pos1 + 1 + random().nextInt(3);
     for (int i = 0; i < 10; i++) {
-      PhraseQuery.Builder builder = new PhraseQuery.Builder();
-      builder.add(t1, 0);
-      builder.add(t2, pos1);
-      builder.add(t3, pos2);
+      PhraseQuery.Builder builder = new PhraseQuery.Builder(t1.field());
+      builder.add(t1.bytes(), 0);
+      builder.add(t2.bytes(), pos1);
+      builder.add(t3.bytes(), pos2);
       builder.setSlop(i);
       PhraseQuery q1 = builder.build();
       builder.setSlop(i + 1);
@@ -90,8 +108,16 @@
   public void testRepetitiveIncreasingSloppiness() throws Exception {
     Term t = randomTerm();
     for (int i = 0; i < 10; i++) {
-      PhraseQuery q1 = new PhraseQuery(i, t.field(), t.bytes(), t.bytes());
-      PhraseQuery q2 = new PhraseQuery(i + 1, t.field(), t.bytes(), t.bytes());
+      PhraseQuery q1 = new PhraseQuery.Builder(t.field())
+          .setSlop(i)
+          .add(t.bytes())
+          .add(t.bytes())
+          .build();
+      PhraseQuery q2 = new PhraseQuery.Builder(t.field())
+          .setSlop(i+1)
+          .add(t.bytes())
+          .add(t.bytes())
+          .build();
       assertSubsetOf(q1, q2);
     }
   }
@@ -100,9 +126,9 @@
   public void testRepetitiveIncreasingSloppinessWithHoles() throws Exception {
     Term t = randomTerm();
     for (int i = 0; i < 10; i++) {
-      PhraseQuery.Builder builder = new PhraseQuery.Builder();
-      builder.add(t, 0);
-      builder.add(t, 2);
+      PhraseQuery.Builder builder = new PhraseQuery.Builder(t.field());
+      builder.add(t.bytes(), 0);
+      builder.add(t.bytes(), 2);
       builder.setSlop(i);
       PhraseQuery q1 = builder.build();
       builder.setSlop(i + 1);
@@ -115,8 +141,18 @@
   public void testRepetitiveIncreasingSloppiness3() throws Exception {
     Term t = randomTerm();
     for (int i = 0; i < 10; i++) {
-      PhraseQuery q1 = new PhraseQuery(i, t.field(), t.bytes(), t.bytes(), t.bytes());
-      PhraseQuery q2 = new PhraseQuery(i + 1, t.field(), t.bytes(), t.bytes(), t.bytes());
+      PhraseQuery q1 = new PhraseQuery.Builder(t.field())
+          .setSlop(i)
+          .add(t.bytes())
+          .add(t.bytes())
+          .add(t.bytes())
+          .build();
+      PhraseQuery q2 = new PhraseQuery.Builder(t.field())
+          .setSlop(i+1)
+          .add(t.bytes())
+          .add(t.bytes())
+          .add(t.bytes())
+          .build();
       assertSubsetOf(q1, q2);
       assertSubsetOf(q1, q2);
     }
@@ -128,10 +164,10 @@
     int pos1 = 1 + random().nextInt(3);
     int pos2 = pos1 + 1 + random().nextInt(3);
     for (int i = 0; i < 10; i++) {
-      PhraseQuery.Builder builder = new PhraseQuery.Builder();
-      builder.add(t, 0);
-      builder.add(t, pos1);
-      builder.add(t, pos2);
+      PhraseQuery.Builder builder = new PhraseQuery.Builder(t.field());
+      builder.add(t.bytes(), 0);
+      builder.add(t.bytes(), pos1);
+      builder.add(t.bytes(), pos2);
       builder.setSlop(i);
       PhraseQuery q1 = builder.build();
       builder.setSlop(i + 1);
Index: lucene/core/src/test/org/apache/lucene/search/TestSubScorerFreqs.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/search/TestSubScorerFreqs.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/search/TestSubScorerFreqs.java	(working copy)
@@ -192,7 +192,7 @@
 
   @Test
   public void testPhraseQuery() throws Exception {
-    PhraseQuery q = new PhraseQuery("f", "b", "c");
+    PhraseQuery q = new PhraseQuery.Builder("f").add("b").add("c").build();
     CountingCollector c = new CountingCollector(TopScoreDocCollector.create(10));
     s.search(q, c);
     final int maxDocs = s.getIndexReader().maxDoc();
Index: lucene/core/src/test/org/apache/lucene/search/spans/TestBasics.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/search/spans/TestBasics.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/search/spans/TestBasics.java	(working copy)
@@ -113,14 +113,20 @@
   }
 
   public void testPhrase() throws Exception {
-    PhraseQuery query = new PhraseQuery("field", "seventy", "seven");
+    PhraseQuery.Builder builder = new PhraseQuery.Builder("field")
+        .add("seventy")
+        .add("seven");
+    PhraseQuery query = builder.build();
     checkHits(query, new int[]
       {77, 177, 277, 377, 477, 577, 677, 777, 877,
               977, 1077, 1177, 1277, 1377, 1477, 1577, 1677, 1777, 1877, 1977});
   }
 
   public void testPhrase2() throws Exception {
-    PhraseQuery query = new PhraseQuery("field", "seventish", "sevenon");
+    PhraseQuery.Builder builder = new PhraseQuery.Builder("field")
+        .add("seventish")
+        .add("sevenon");
+    PhraseQuery query = builder.build();
     checkHits(query, new int[] {});
   }
 
Index: lucene/core/src/test/org/apache/lucene/search/spans/TestSpanSearchEquivalence.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/search/spans/TestSpanSearchEquivalence.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/search/spans/TestSpanSearchEquivalence.java	(working copy)
@@ -153,7 +153,10 @@
                              spanQuery(new SpanTermQuery(t2)) 
                            };
     SpanQuery q1 = spanQuery(new SpanNearQuery(subquery, 0, true));
-    PhraseQuery q2 = new PhraseQuery(t1.field(), t1.bytes(), t2.bytes());
+    PhraseQuery q2 = new PhraseQuery.Builder(t1.field())
+        .add(t1.bytes())
+        .add(t2.bytes())
+        .build();
     if (t1.equals(t2)) {
       assertSameSet(q1, q2);
     } else {
Index: lucene/core/src/test/org/apache/lucene/util/TestQueryBuilder.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/util/TestQueryBuilder.java	(revision 1686523)
+++ lucene/core/src/test/org/apache/lucene/util/TestQueryBuilder.java	(working copy)
@@ -103,9 +103,9 @@
   }
   
   public void testPhraseQueryPositionIncrements() throws Exception {
-    PhraseQuery.Builder pqBuilder = new PhraseQuery.Builder();
-    pqBuilder.add(new Term("field", "1"), 0);
-    pqBuilder.add(new Term("field", "2"), 2);
+    PhraseQuery.Builder pqBuilder = new PhraseQuery.Builder("field");
+    pqBuilder.add("1", 0);
+    pqBuilder.add("2", 2);
     PhraseQuery expected = pqBuilder.build();
     CharacterRunAutomaton stopList = new CharacterRunAutomaton(new RegExp("[sS][tT][oO][pP]").toAutomaton());
 
@@ -223,9 +223,12 @@
   public void testCJKPhrase() throws Exception {
     // individual CJK chars as terms
     SimpleCJKAnalyzer analyzer = new SimpleCJKAnalyzer();
+
+    PhraseQuery.Builder phraseQueryBuilder = new PhraseQuery.Builder("field")
+        .add("中")
+        .add("国");
+    PhraseQuery expected = phraseQueryBuilder.build();
     
-    PhraseQuery expected = new PhraseQuery("field", "中", "国");
-    
     QueryBuilder builder = new QueryBuilder(analyzer);
     assertEquals(expected, builder.createPhraseQuery("field", "中国"));
   }
@@ -233,9 +236,13 @@
   public void testCJKSloppyPhrase() throws Exception {
     // individual CJK chars as terms
     SimpleCJKAnalyzer analyzer = new SimpleCJKAnalyzer();
-    
-    PhraseQuery expected = new PhraseQuery(3, "field", "中", "国");
-    
+
+    PhraseQuery.Builder phraseQueryBuilder = new PhraseQuery.Builder("field")
+        .setSlop(3)
+        .add("中")
+        .add("国");
+    PhraseQuery expected = phraseQueryBuilder.build();
+
     QueryBuilder builder = new QueryBuilder(analyzer);
     assertEquals(expected, builder.createPhraseQuery("field", "中国", 3));
   }
Index: lucene/highlighter/src/java/org/apache/lucene/search/vectorhighlight/FieldQuery.java
===================================================================
--- lucene/highlighter/src/java/org/apache/lucene/search/vectorhighlight/FieldQuery.java	(revision 1686523)
+++ lucene/highlighter/src/java/org/apache/lucene/search/vectorhighlight/FieldQuery.java	(working copy)
@@ -28,7 +28,6 @@
 
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.queries.CommonTermsQuery;
 import org.apache.lucene.queries.CustomScoreQuery;
 import org.apache.lucene.search.BooleanClause;
 import org.apache.lucene.search.BooleanQuery;
@@ -226,11 +225,11 @@
         }
       }
       if( overlap && src.length - i < dest.length ){
-        PhraseQuery.Builder pqBuilder = new PhraseQuery.Builder();
+        PhraseQuery.Builder pqBuilder = new PhraseQuery.Builder(src[0].field());
         for( Term srcTerm : src )
-          pqBuilder.add( srcTerm );
+          pqBuilder.add( srcTerm.text() );
         for( int k = src.length - i; k < dest.length; k++ ){
-          pqBuilder.add( new Term( src[0].field(), dest[k].text() ) );
+          pqBuilder.add(dest[k].text() );
         }
         pqBuilder.setSlop( slop );
         PhraseQuery pq = pqBuilder.build();
Index: lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterPhraseTest.java
===================================================================
--- lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterPhraseTest.java	(revision 1686523)
+++ lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterPhraseTest.java	(working copy)
@@ -70,7 +70,7 @@
     try {
       assertEquals(1, indexReader.numDocs());
       final IndexSearcher indexSearcher = newSearcher(indexReader);
-      final PhraseQuery phraseQuery = new PhraseQuery(FIELD, "fox", "jumped");
+      final PhraseQuery phraseQuery = new PhraseQuery.Builder(FIELD).add("fox").add("jumped").build();
       TopDocs hits = indexSearcher.search(phraseQuery, 1);
       assertEquals(1, hits.totalHits);
       final Highlighter highlighter = new Highlighter(
@@ -175,7 +175,7 @@
     try {
       assertEquals(1, indexReader.numDocs());
       final IndexSearcher indexSearcher = newSearcher(indexReader);
-      final PhraseQuery phraseQuery = new PhraseQuery(FIELD, "did", "jump");
+      final PhraseQuery phraseQuery = new PhraseQuery.Builder(FIELD).add("did").add("jump").build();
       TopDocs hits = indexSearcher.search(phraseQuery, 1);
       assertEquals(0, hits.totalHits);
       final Highlighter highlighter = new Highlighter(
@@ -212,7 +212,7 @@
     try {
       assertEquals(1, indexReader.numDocs());
       final IndexSearcher indexSearcher = newSearcher(indexReader);
-      final PhraseQuery phraseQuery = new PhraseQuery(1, FIELD, "did", "jump");
+      final PhraseQuery phraseQuery = new PhraseQuery.Builder(FIELD).setSlop(1).add("did").add("jump").build();
       TopDocs hits = indexSearcher.search(phraseQuery, 1);
       assertEquals(1, hits.totalHits);
       final Highlighter highlighter = new Highlighter(
Index: lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java
===================================================================
--- lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java	(revision 1686523)
+++ lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java	(working copy)
@@ -56,11 +56,9 @@
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
-import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.queries.CommonTermsQuery;
-import org.apache.lucene.queries.CustomScoreProvider;
 import org.apache.lucene.queries.CustomScoreQuery;
 import org.apache.lucene.search.BooleanClause.Occur;
 import org.apache.lucene.search.BooleanQuery;
@@ -167,7 +165,10 @@
   }
 
   public void testQueryScorerHits() throws Exception {
-    PhraseQuery phraseQuery = new PhraseQuery(FIELD_NAME, "very", "long");
+    PhraseQuery phraseQuery = new PhraseQuery.Builder(FIELD_NAME)
+        .add("very")
+        .add("long")
+        .build();
 
     query = phraseQuery;
     searcher = newSearcher(reader);
@@ -289,7 +290,11 @@
     // highlighted
     // regardless of the field name.
 
-    PhraseQuery q = new PhraseQuery(3, FIELD_NAME, "world", "flatland");
+    PhraseQuery q = new PhraseQuery.Builder(FIELD_NAME)
+        .setSlop(3)
+        .add("world")
+        .add("flatland")
+        .build();
 
     String expected = "I call our <B>world</B> <B>Flatland</B>, not because we call it so,";
     String observed = highlightField(q, "SOME_FIELD_NAME", s1);
@@ -302,7 +307,12 @@
     // when the query field name differs from the name of the field being
     // highlighted,
     // which in this example happens to be the default field name.
-    q = new PhraseQuery(3, "text", "world", "flatland");
+    q = new PhraseQuery.Builder(FIELD_NAME)
+        .setSlop(3)
+        .add("text")
+        .add("world")
+        .add("flatland")
+        .build();
 
     expected = s1;
     observed = highlightField(q, FIELD_NAME, s1);
@@ -356,13 +366,13 @@
     String f1 = "f1";
     String f2 = "f2";
 
-    PhraseQuery f1ph1 = new PhraseQuery(f1, "a", "b", "c", "d");
+    PhraseQuery f1ph1 = new PhraseQuery.Builder(f1).add("a").add("b").add("c").add("d").build();
 
-    PhraseQuery f2ph1 = new PhraseQuery(f2, "a", "b", "c", "d");
+    PhraseQuery f2ph1 = new PhraseQuery.Builder(f2).add("a").add("b").add("c").add("d").build();
 
-    PhraseQuery f1ph2 = new PhraseQuery(f1, "b", "c", "g");
+    PhraseQuery f1ph2 = new PhraseQuery.Builder(f1).add("a").add("b").add("c").add("g").build();
 
-    PhraseQuery f2ph2 = new PhraseQuery(f2, "b", "c", "g");
+    PhraseQuery f2ph2 = new PhraseQuery.Builder(f2).add("a").add("b").add("c").add("g").build();
 
     BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder();
     BooleanQuery.Builder leftChild = new BooleanQuery.Builder();
@@ -389,10 +399,10 @@
   }
 
   public void testSimpleQueryScorerPhraseHighlighting() throws Exception {
-    PhraseQuery.Builder builder = new PhraseQuery.Builder();
-    builder.add(new Term(FIELD_NAME, "very"), 0);
-    builder.add(new Term(FIELD_NAME, "long"), 1);
-    builder.add(new Term(FIELD_NAME, "contains"), 3);
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(FIELD_NAME);
+    builder.add("very", 0);
+    builder.add("long", 1);
+    builder.add("contains", 3);
     PhraseQuery phraseQuery = builder.build();
     doSearching(phraseQuery);
 
@@ -419,11 +429,11 @@
     
     numHighlights = 0;
 
-    builder = new PhraseQuery.Builder();
-    builder.add(new Term(FIELD_NAME, "piece"), 1);
-    builder.add(new Term(FIELD_NAME, "text"), 3);
-    builder.add(new Term(FIELD_NAME, "refers"), 4);
-    builder.add(new Term(FIELD_NAME, "kennedy"), 6);
+    builder = new PhraseQuery.Builder(FIELD_NAME);
+    builder.add("piece", 1);
+    builder.add("text", 3);
+    builder.add("refers", 4);
+    builder.add("kennedy", 6);
     phraseQuery = builder.build();
 
     doSearching(phraseQuery);
@@ -451,11 +461,11 @@
     
     numHighlights = 0;
 
-    builder = new PhraseQuery.Builder();
-    builder.add(new Term(FIELD_NAME, "lets"), 0);
-    builder.add(new Term(FIELD_NAME, "lets"), 4);
-    builder.add(new Term(FIELD_NAME, "lets"), 8);
-    builder.add(new Term(FIELD_NAME, "lets"), 12);
+    builder = new PhraseQuery.Builder(FIELD_NAME);
+    builder.add("lets", 0);
+    builder.add("lets", 4);
+    builder.add("lets", 8);
+    builder.add("lets", 12);
     phraseQuery = builder.build();
 
     doSearching(phraseQuery);
@@ -644,7 +654,7 @@
   }
 
   public void testSimpleQueryScorerPhraseHighlighting2() throws Exception {
-    PhraseQuery phraseQuery = new PhraseQuery(5, FIELD_NAME, "text", "piece", "long");
+    PhraseQuery phraseQuery = new PhraseQuery.Builder(FIELD_NAME).setSlop(5).add("text").add("piece").add("long").build();
     doSearching(phraseQuery);
 
     int maxNumFragmentsRequired = 2;
@@ -669,7 +679,7 @@
   }
 
   public void testSimpleQueryScorerPhraseHighlighting3() throws Exception {
-    PhraseQuery phraseQuery = new PhraseQuery(FIELD_NAME, "x", "y", "z");
+    PhraseQuery phraseQuery = new PhraseQuery.Builder(FIELD_NAME).add("x").add("y").add("z").build();
     doSearching(phraseQuery);
 
     int maxNumFragmentsRequired = 2;
@@ -694,11 +704,11 @@
   }
   
   public void testSimpleSpanFragmenter() throws Exception {
-    Builder builder = new PhraseQuery.Builder();
-    builder.add(new Term(FIELD_NAME, "piece"), 0);
-    builder.add(new Term(FIELD_NAME, "text"), 2);
-    builder.add(new Term(FIELD_NAME, "very"), 5);
-    builder.add(new Term(FIELD_NAME, "long"), 6);
+    Builder builder = new PhraseQuery.Builder(FIELD_NAME);
+    builder.add("piece", 0);
+    builder.add("text", 2);
+    builder.add("very", 5);
+    builder.add("long", 6);
     PhraseQuery phraseQuery = builder.build();
     doSearching(phraseQuery);
 
@@ -721,7 +731,7 @@
 
     }
 
-    phraseQuery = new PhraseQuery(FIELD_NAME, "been", "shot");
+    phraseQuery = new PhraseQuery.Builder(FIELD_NAME).add("been").add("shot").build();
 
     doSearching(query);
 
@@ -748,7 +758,7 @@
     BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder();
     booleanQuery.add(new TermQuery(new Term(FIELD_NAME, "y")), Occur.SHOULD);
 
-    PhraseQuery phraseQuery = new PhraseQuery(FIELD_NAME, "x", "y", "z");
+    PhraseQuery phraseQuery = new PhraseQuery.Builder(FIELD_NAME).add("x").add("y").add("z").build();
     booleanQuery.add(phraseQuery, Occur.SHOULD);
 
     doSearching(booleanQuery.build());
@@ -1106,7 +1116,7 @@
       @Override
       public void run() throws Exception {
         numHighlights = 0;
-        PhraseQuery phraseQuery = new PhraseQuery(FIELD_NAME, "john", "kennedy");
+        PhraseQuery phraseQuery = new PhraseQuery.Builder(FIELD_NAME).add("john").add("kennedy").build();
         doSearching(phraseQuery);
         doStandardHighlights(analyzer, searcher, hits, query, HighlighterTest.this);
         // Currently highlights "John" and "Kennedy" separately
@@ -1187,7 +1197,7 @@
       @Override
       public void run() throws Exception {
         numHighlights = 0;
-        PhraseQuery pq = new PhraseQuery("contents", "john", "kennedy");
+        PhraseQuery pq = new PhraseQuery.Builder("contents").add("john").add("kennedy").build();
         BooleanQuery.Builder bq = new BooleanQuery.Builder();
         bq.add(pq, Occur.MUST);
         bq.add(TermRangeQuery.newStringRange("contents", "john", "john", true, true), Occur.FILTER);
Index: lucene/highlighter/src/test/org/apache/lucene/search/highlight/MissesTest.java
===================================================================
--- lucene/highlighter/src/test/org/apache/lucene/search/highlight/MissesTest.java	(revision 1686523)
+++ lucene/highlighter/src/test/org/apache/lucene/search/highlight/MissesTest.java	(working copy)
@@ -58,7 +58,7 @@
 
   public void testPhraseQuery() throws IOException, InvalidTokenOffsetsException {
     try (Analyzer analyzer = new MockAnalyzer(random(), MockTokenizer.WHITESPACE, false)) {
-      final PhraseQuery query = new PhraseQuery("test", "foo", "bar");
+      final PhraseQuery query = new PhraseQuery.Builder("test").add("foo").add("bar").build();
       final Highlighter highlighter = new Highlighter(new SimpleHTMLFormatter(), new QueryScorer(query));
       assertEquals("this is a <B>foo</B> <B>bar</B> example",
           highlighter.getBestFragment(analyzer, "test", "this is a foo bar example"));
Index: lucene/highlighter/src/test/org/apache/lucene/search/postingshighlight/TestPostingsHighlighter.java
===================================================================
--- lucene/highlighter/src/test/org/apache/lucene/search/postingshighlight/TestPostingsHighlighter.java	(revision 1686523)
+++ lucene/highlighter/src/test/org/apache/lucene/search/postingshighlight/TestPostingsHighlighter.java	(working copy)
@@ -447,7 +447,7 @@
     IndexReader ir = iw.getReader();
     iw.close();
     IndexSearcher searcher = newSearcher(ir);
-    PhraseQuery query = new PhraseQuery("body", "buddhist", "origins");
+    PhraseQuery query = new PhraseQuery.Builder("body").add("buddhist").add("origins").build();
     TopDocs topDocs = searcher.search(query, 10);
     assertEquals(1, topDocs.totalHits);
     PostingsHighlighter highlighter = new PostingsHighlighter();
@@ -475,7 +475,7 @@
     IndexReader ir = iw.getReader();
     iw.close();
     IndexSearcher searcher = newSearcher(ir);
-    PhraseQuery query = new PhraseQuery("body", "curious", "george");
+    PhraseQuery query = new PhraseQuery.Builder("body").add("curious").add("george").build();
     TopDocs topDocs = searcher.search(query, 10);
     assertEquals(1, topDocs.totalHits);
     PostingsHighlighter highlighter = new PostingsHighlighter();
Index: lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/AbstractTestCase.java
===================================================================
--- lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/AbstractTestCase.java	(revision 1686523)
+++ lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/AbstractTestCase.java	(working copy)
@@ -138,7 +138,12 @@
   }
   
   protected Query pq( float boost, int slop, String field, String... texts ){
-    PhraseQuery query = new PhraseQuery(slop, field, texts);
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(field);
+    for (String term : texts){
+      builder.add(term);
+    }
+    builder.setSlop(slop);
+    PhraseQuery query = builder.build();
     query.setBoost( boost );
     return query;
   }
@@ -184,7 +189,11 @@
   }
 
   protected PhraseQuery toPhraseQuery(List<BytesRef> bytesRefs, String field) {
-    return new PhraseQuery(field, bytesRefs.toArray(new BytesRef[0]));
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(field);
+    for (BytesRef term : bytesRefs){
+      builder.add(term);
+    }
+    return builder.build();
   }
 
   static final class BigramAnalyzer extends Analyzer {
Index: lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/FastVectorHighlighterTest.java
===================================================================
--- lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/FastVectorHighlighterTest.java	(revision 1686523)
+++ lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/FastVectorHighlighterTest.java	(working copy)
@@ -148,7 +148,7 @@
     }
     
     {
-      PhraseQuery query = new PhraseQuery(field, "internet", "explorer");
+      PhraseQuery query = new PhraseQuery.Builder(field).add("internet").add("explorer").build();
       FieldQuery fieldQuery = highlighter.getFieldQuery(query, reader);
       String[] bestFragments = highlighter.getBestFragments(fieldQuery, reader,
           docId, field, 128, 1);
@@ -195,7 +195,7 @@
     }
     {
       BooleanQuery.Builder query = new BooleanQuery.Builder();
-      PhraseQuery pq = new PhraseQuery(5, field, "test", "foo", "highlighed");
+      PhraseQuery pq = new PhraseQuery.Builder(field).setSlop(5).add("test").add("foo").add("highlighed").build();
       query.add(new TermQuery(new Term(field, "foo")), Occur.MUST);
       query.add(pq, Occur.MUST);
       query.add(new TermQuery(new Term(field, "highlighed")), Occur.MUST);
@@ -212,7 +212,7 @@
       
     }
     {
-      PhraseQuery query = new PhraseQuery(3, field, "test", "foo", "highlighed");
+      PhraseQuery query = new PhraseQuery.Builder(field).setSlop(3).add("test").add("foo").add("highlighed").build();
       FieldQuery fieldQuery = highlighter.getFieldQuery(query, reader);
       String[] bestFragments = highlighter.getBestFragments(fieldQuery, reader,
           docId, field, 18, 1);
@@ -226,7 +226,7 @@
       
     }
     {
-      PhraseQuery query = new PhraseQuery(30, field, "test", "foo", "highlighed");
+      PhraseQuery query = new PhraseQuery.Builder(field).setSlop(30).add("test").add("foo").add("highlighed").build();
       FieldQuery fieldQuery = highlighter.getFieldQuery(query, reader);
       String[] bestFragments = highlighter.getBestFragments(fieldQuery, reader,
           docId, field, 18, 1);
@@ -234,7 +234,7 @@
     }
     {
       BooleanQuery.Builder query = new BooleanQuery.Builder();
-      PhraseQuery pq = new PhraseQuery(5, field, "test", "foo", "highlighed");
+      PhraseQuery pq = new PhraseQuery.Builder(field).setSlop(5).add("test").add("foo").add("highlighed").build();
       BooleanQuery.Builder inner = new BooleanQuery.Builder();
       inner.add(pq, Occur.MUST);
       inner.add(new TermQuery(new Term(field, "foo")), Occur.MUST);
@@ -550,13 +550,13 @@
     int docId = 0;
     
     // query1: match
-    PhraseQuery pq = new PhraseQuery("field", "test", "http", "www", "facebook", "com");
+    PhraseQuery pq = new PhraseQuery.Builder("field").add("test").add("http").add("www").add("facebook").add("com").build();
     FieldQuery fieldQuery  = highlighter.getFieldQuery(pq, reader);
     String[] bestFragments = highlighter.getBestFragments(fieldQuery, reader, docId, "field", 54, 1);
     assertEquals("<b>Test: http://www.facebook.com</b>", bestFragments[0]);
     
     // query2: match
-    PhraseQuery pq2 = new PhraseQuery("field", "test", "httpwwwfacebookcom", "www", "facebook", "com");
+    PhraseQuery pq2 = new PhraseQuery.Builder("field").add("test").add("httpwwwfacebookcom").add("www").add("facebook").add("com").build();
     fieldQuery  = highlighter.getFieldQuery(pq2, reader);
     bestFragments = highlighter.getBestFragments(fieldQuery, reader, docId, "field", 54, 1);
     assertEquals("<b>Test: http://www.facebook.com</b>", bestFragments[0]);
@@ -665,7 +665,11 @@
     if ( terms.length == 1 ) {
       q = new TermQuery( new Term( field, terms[ 0 ] ) );
     } else {
-      q = new PhraseQuery(field, terms);
+      PhraseQuery.Builder builder = new PhraseQuery.Builder(field);
+      for (String term : terms){
+        builder.add(term);
+      }
+      q = builder.build();
     }
     q.setBoost( boost );
     return q;
Index: lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/SimpleFragListBuilderTest.java
===================================================================
--- lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/SimpleFragListBuilderTest.java	(revision 1686523)
+++ lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/SimpleFragListBuilderTest.java	(working copy)
@@ -48,7 +48,7 @@
   public void testSmallerFragSizeThanPhraseQuery() throws Exception {
     SimpleFragListBuilder sflb = new SimpleFragListBuilder();
 
-    PhraseQuery phraseQuery = new PhraseQuery(F, "abcdefgh", "jklmnopqrs");
+    PhraseQuery phraseQuery = new PhraseQuery.Builder(F).add("abcdefgh").add("jklmnopqrs").build();
 
     FieldFragList ffl = sflb.createFieldFragList( fpl(phraseQuery, "abcdefgh   jklmnopqrs" ), sflb.minFragCharSize );
     assertEquals( 1, ffl.getFragInfos().size() );
@@ -118,7 +118,7 @@
   public void testPhraseQuery() throws Exception {
     SimpleFragListBuilder sflb = new SimpleFragListBuilder();
 
-    PhraseQuery phraseQuery = new PhraseQuery(F, "a", "b");
+    PhraseQuery phraseQuery = new PhraseQuery.Builder(F).add("a").add("b").build();
 
     FieldFragList ffl = sflb.createFieldFragList( fpl(phraseQuery, "c d e" ), 20 );
     assertEquals( 0, ffl.getFragInfos().size() );
@@ -134,7 +134,7 @@
   public void testPhraseQuerySlop() throws Exception {
     SimpleFragListBuilder sflb = new SimpleFragListBuilder();
 
-    PhraseQuery phraseQuery = new PhraseQuery(1, F, "a", "b");
+    PhraseQuery phraseQuery = new PhraseQuery.Builder(F).setSlop(1).add("a").add("b").build();
 
     FieldFragList ffl = sflb.createFieldFragList( fpl(phraseQuery, "a c b" ), 20 );
     assertEquals( 1, ffl.getFragInfos().size() );
Index: lucene/memory/src/test/org/apache/lucene/index/memory/TestMemoryIndexAgainstRAMDir.java
===================================================================
--- lucene/memory/src/test/org/apache/lucene/index/memory/TestMemoryIndexAgainstRAMDir.java	(revision 1686523)
+++ lucene/memory/src/test/org/apache/lucene/index/memory/TestMemoryIndexAgainstRAMDir.java	(working copy)
@@ -410,14 +410,14 @@
     LeafReader reader = (LeafReader) mindex.createSearcher().getIndexReader();
     TestUtil.checkReader(reader);
     assertEquals(7, reader.terms("field").getSumTotalTermFreq());
-    PhraseQuery query = new PhraseQuery("field", "fox", "jumps");
+    PhraseQuery query = new PhraseQuery.Builder("field").add("fox").add("jumps").build();
     assertTrue(mindex.search(query) > 0.1);
     mindex.reset();
     mockAnalyzer.setPositionIncrementGap(1 + random().nextInt(10));
     mindex.addField("field", "the quick brown fox", mockAnalyzer);
     mindex.addField("field", "jumps over the", mockAnalyzer);
     assertEquals(0, mindex.search(query), 0.00001f);
-    query = new PhraseQuery(10, "field", "fox", "jumps");
+    query = new PhraseQuery.Builder("field").setSlop(10).add("fox").add("jumps").build();
     assertTrue("posGap" + mockAnalyzer.getPositionIncrementGap("field") , mindex.search(query) > 0.0001);
     TestUtil.checkReader(mindex.createSearcher().getIndexReader());
   }
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/classic/MultiFieldQueryParser.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/classic/MultiFieldQueryParser.java	(revision 1686523)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/classic/MultiFieldQueryParser.java	(working copy)
@@ -124,13 +124,13 @@
 
   private Query applySlop(Query q, int slop) {
     if (q instanceof PhraseQuery) {
-      PhraseQuery.Builder builder = new PhraseQuery.Builder();
+      PhraseQuery pq = (PhraseQuery) q;
+      PhraseQuery.Builder builder = new PhraseQuery.Builder(pq.getField());
       builder.setSlop(slop);
-      PhraseQuery pq = (PhraseQuery) q;
       org.apache.lucene.index.Term[] terms = pq.getTerms();
       int[] positions = pq.getPositions();
       for (int i = 0; i < terms.length; ++i) {
-        builder.add(terms[i], positions[i]);
+        builder.add(terms[i].bytes(), positions[i]);
       }
       q = builder.build();
       q.setBoost(pq.getBoost());
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/classic/QueryParserBase.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/classic/QueryParserBase.java	(revision 1686523)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/classic/QueryParserBase.java	(working copy)
@@ -494,13 +494,13 @@
     Query query = getFieldQuery(field, queryText, true);
 
     if (query instanceof PhraseQuery) {
-      PhraseQuery.Builder builder = new PhraseQuery.Builder();
+      PhraseQuery pq = (PhraseQuery) query;
+      PhraseQuery.Builder builder = new PhraseQuery.Builder(pq.getField());
       builder.setSlop(slop);
-      PhraseQuery pq = (PhraseQuery) query;
       org.apache.lucene.index.Term[] terms = pq.getTerms();
       int[] positions = pq.getPositions();
       for (int i = 0; i < terms.length; ++i) {
-        builder.add(terms[i], positions[i]);
+        builder.add(terms[i].bytes(), positions[i]);
       }
       query = builder.build();
       query.setBoost(pq.getBoost());
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/PhraseQueryNodeBuilder.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/PhraseQueryNodeBuilder.java	(revision 1686523)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/PhraseQueryNodeBuilder.java	(working copy)
@@ -42,7 +42,7 @@
   public Query build(QueryNode queryNode) throws QueryNodeException {
     TokenizedPhraseQueryNode phraseNode = (TokenizedPhraseQueryNode) queryNode;
 
-    PhraseQuery.Builder builder = new PhraseQuery.Builder();
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(phraseNode.getField().toString());
 
     List<QueryNode> children = phraseNode.getChildren();
 
@@ -53,7 +53,7 @@
             .getTag(QueryTreeBuilder.QUERY_TREE_BUILDER_TAGID);
         FieldQueryNode termNode = (FieldQueryNode) child;
 
-        builder.add(termQuery.getTerm(), termNode.getPositionIncrement());
+        builder.add(termQuery.getTerm().bytes(), termNode.getPositionIncrement());
       }
 
     }
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/SlopQueryNodeBuilder.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/SlopQueryNodeBuilder.java	(revision 1686523)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/SlopQueryNodeBuilder.java	(working copy)
@@ -45,17 +45,16 @@
         QueryTreeBuilder.QUERY_TREE_BUILDER_TAGID);
 
     if (query instanceof PhraseQuery) {
-      PhraseQuery.Builder builder = new PhraseQuery.Builder();
+      PhraseQuery pq = (PhraseQuery) query;
+      PhraseQuery.Builder builder = new PhraseQuery.Builder(pq.getField());
       builder.setSlop(phraseSlopNode.getValue());
-      PhraseQuery pq = (PhraseQuery) query;
       org.apache.lucene.index.Term[] terms = pq.getTerms();
       int[] positions = pq.getPositions();
       for (int i = 0; i < terms.length; ++i) {
-        builder.add(terms[i], positions[i]);
+        builder.add(terms[i].bytes(), positions[i]);
       }
       query = builder.build();
       query.setBoost(pq.getBoost());
-
     } else {
       ((MultiPhraseQuery) query).setSlop(phraseSlopNode.getValue());
     }
Index: lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestQPHelper.java
===================================================================
--- lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestQPHelper.java	(revision 1686523)
+++ lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestQPHelper.java	(working copy)
@@ -408,7 +408,7 @@
     // individual CJK chars as terms
     SimpleCJKAnalyzer analyzer = new SimpleCJKAnalyzer();
     
-    PhraseQuery expected = new PhraseQuery("field", "中", "国");
+    PhraseQuery expected = new PhraseQuery.Builder("field").add("中").add("国").build();
     
     assertEquals(expected, getQuery("\"中国\"", analyzer));
   }
@@ -417,7 +417,7 @@
     // individual CJK chars as terms
     SimpleCJKAnalyzer analyzer = new SimpleCJKAnalyzer();
     
-    PhraseQuery expected = new PhraseQuery("field", "中", "国");
+    PhraseQuery expected = new PhraseQuery.Builder("field").add("中").add("国").build();
     expected.setBoost(0.5f);
     
     assertEquals(expected, getQuery("\"中国\"^0.5", analyzer));
@@ -427,7 +427,7 @@
     // individual CJK chars as terms
     SimpleCJKAnalyzer analyzer = new SimpleCJKAnalyzer(); 
     
-    PhraseQuery expected = new PhraseQuery(3, "field", "中", "国");
+    PhraseQuery expected = new PhraseQuery.Builder("field").add("中").add("国").setSlop(3).build();
     
     assertEquals(expected, getQuery("\"中国\"~3", analyzer));
   }
Index: lucene/queryparser/src/test/org/apache/lucene/queryparser/simple/TestSimpleQueryParser.java
===================================================================
--- lucene/queryparser/src/test/org/apache/lucene/queryparser/simple/TestSimpleQueryParser.java	(revision 1686523)
+++ lucene/queryparser/src/test/org/apache/lucene/queryparser/simple/TestSimpleQueryParser.java	(working copy)
@@ -103,29 +103,29 @@
 
   /** test a simple phrase */
   public void testPhrase() throws Exception {
-    PhraseQuery expected = new PhraseQuery("field", "foo", "bar");
+    PhraseQuery expected = createPhraseQuery("field", "foo", "bar");
 
     assertEquals(expected, parse("\"foo bar\""));
   }
 
   /** test a simple phrase with various slop settings */
   public void testPhraseWithSlop() throws Exception {
-    PhraseQuery expectedWithSlop = new PhraseQuery(2, "field", "foo", "bar");
+    PhraseQuery expectedWithSlop = createPhraseQuery(2, "field", "foo", "bar");
 
     assertEquals(expectedWithSlop, parse("\"foo bar\"~2"));
 
-    PhraseQuery expectedWithMultiDigitSlop = new PhraseQuery(10, "field", "foo", "bar");
+    PhraseQuery expectedWithMultiDigitSlop = createPhraseQuery(10, "field", "foo", "bar");
 
     assertEquals(expectedWithMultiDigitSlop, parse("\"foo bar\"~10"));
 
-    PhraseQuery expectedNoSlop = new PhraseQuery("field", "foo", "bar");
+    PhraseQuery expectedNoSlop = createPhraseQuery("field", "foo", "bar");
 
     assertEquals("Ignore trailing tilde with no slop", expectedNoSlop, parse("\"foo bar\"~"));
     assertEquals("Ignore non-numeric trailing slop", expectedNoSlop, parse("\"foo bar\"~a"));
     assertEquals("Ignore non-numeric trailing slop", expectedNoSlop, parse("\"foo bar\"~1a"));
     assertEquals("Ignore negative trailing slop", expectedNoSlop, parse("\"foo bar\"~-1"));
 
-    PhraseQuery pq = new PhraseQuery(12, "field", "foo", "bar");
+    PhraseQuery pq = createPhraseQuery(12, "field", "foo", "bar");
 
     BooleanQuery.Builder expectedBoolean = new BooleanQuery.Builder();
     expectedBoolean.add(pq, Occur.MUST);
@@ -152,8 +152,8 @@
 
   /** test some AND'd phrases using '+' operator */
   public void testANDPhrase() throws Exception {
-    PhraseQuery phrase1 = new PhraseQuery("field", "foo", "bar");
-    PhraseQuery phrase2 = new PhraseQuery("field", "star", "wars");
+    PhraseQuery phrase1 = createPhraseQuery("field", "foo", "bar");
+    PhraseQuery phrase2 = createPhraseQuery("field", "star", "wars");
     BooleanQuery.Builder expected = new BooleanQuery.Builder();
     expected.add(phrase1, Occur.MUST);
     expected.add(phrase2, Occur.MUST);
@@ -192,8 +192,8 @@
 
   /** test some OR'd phrases using '|' operator */
   public void testORPhrase() throws Exception {
-    PhraseQuery phrase1 = new PhraseQuery("field", "foo", "bar");
-    PhraseQuery phrase2 = new PhraseQuery("field", "star", "wars");
+    PhraseQuery phrase1 = createPhraseQuery("field", "foo", "bar");
+    PhraseQuery phrase2 = createPhraseQuery("field", "star", "wars");
     BooleanQuery.Builder expected = new BooleanQuery.Builder();
     expected.add(phrase1, Occur.SHOULD);
     expected.add(phrase2, Occur.SHOULD);
@@ -303,7 +303,7 @@
   }
 
   public void testGarbagePhrase() throws Exception {
-    PhraseQuery expected = new PhraseQuery("field", "star", "wars");
+    PhraseQuery expected = createPhraseQuery("field", "star", "wars");
 
     assertEquals(expected, parse("\"star wars\""));
     assertEquals(expected, parse("\"star wars\\ \""));
@@ -597,7 +597,7 @@
   }
 
   public void testDisableSlop() {
-    PhraseQuery expectedPhrase = new PhraseQuery("field", "foo", "bar");
+    PhraseQuery expectedPhrase = createPhraseQuery("field", "foo", "bar");
 
     BooleanQuery.Builder expected = new BooleanQuery.Builder();
     expected.add(expectedPhrase, Occur.MUST);
@@ -627,4 +627,22 @@
       parseKeyword(sb.toString(), TestUtil.nextInt(random(), 0, 1024)); // no exception
     }
   }
+
+
+  private PhraseQuery createPhraseQuery(int slop, String field, String... terms) {
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(field)
+        .setSlop(slop);
+    for (String term : terms){
+      builder.add(term);
+    }
+    return builder.build();
+  }
+
+  private PhraseQuery createPhraseQuery(String field, String... terms) {
+    PhraseQuery.Builder builder = new PhraseQuery.Builder(field);
+    for (String term : terms) {
+      builder.add(term);
+    }
+    return builder.build();
+  }
 }
Index: lucene/queryparser/src/test/org/apache/lucene/queryparser/util/QueryParserTestBase.java
===================================================================
--- lucene/queryparser/src/test/org/apache/lucene/queryparser/util/QueryParserTestBase.java	(revision 1686523)
+++ lucene/queryparser/src/test/org/apache/lucene/queryparser/util/QueryParserTestBase.java	(working copy)
@@ -299,7 +299,7 @@
     // individual CJK chars as terms
     SimpleCJKAnalyzer analyzer = new SimpleCJKAnalyzer();
     
-    PhraseQuery expected = new PhraseQuery("field", "中", "国");
+    PhraseQuery expected = new PhraseQuery.Builder("field").add("中").add("国").build();
     
     assertEquals(expected, getQuery("\"中国\"", analyzer));
   }
@@ -308,7 +308,7 @@
     // individual CJK chars as terms
     SimpleCJKAnalyzer analyzer = new SimpleCJKAnalyzer();
     
-    PhraseQuery expected = new PhraseQuery("field", "中", "国");
+    PhraseQuery expected = new PhraseQuery.Builder("field").add("中").add("国").build();
     expected.setBoost(0.5f);
     
     assertEquals(expected, getQuery("\"中国\"^0.5", analyzer));
@@ -318,7 +318,7 @@
     // individual CJK chars as terms
     SimpleCJKAnalyzer analyzer = new SimpleCJKAnalyzer();
     
-    PhraseQuery expected = new PhraseQuery(3, "field", "中", "国");
+    PhraseQuery expected = new PhraseQuery.Builder("field").add("中").add("国").setSlop(3).build();
     
     assertEquals(expected, getQuery("\"中国\"~3", analyzer));
   }
@@ -327,7 +327,7 @@
     // individual CJK chars as terms
     SimpleCJKAnalyzer analyzer = new SimpleCJKAnalyzer(); 
   
-    PhraseQuery expected = new PhraseQuery("field", "中", "国");
+    PhraseQuery expected = new PhraseQuery.Builder("field").add("中").add("国").build();
     CommonQueryParserConfiguration qp = getParserConfig(analyzer);
     setAutoGeneratePhraseQueries(qp, true);
     assertEquals(expected, getQuery("中国",qp));
@@ -1255,9 +1255,9 @@
                          new MockAnalyzer(random(), MockTokenizer.WHITESPACE, false, stopStopList));
     qp.setEnablePositionIncrements(true);
 
-    PhraseQuery.Builder phraseQuery = new PhraseQuery.Builder();
-    phraseQuery.add(new Term("field", "1"));
-    phraseQuery.add(new Term("field", "2"), 2);
+    PhraseQuery.Builder phraseQuery = new PhraseQuery.Builder("field");
+    phraseQuery.add("1");
+    phraseQuery.add("2", 2);
     assertEquals(phraseQuery.build(), getQuery("\"1 stop 2\"",qp));
   }
 
Index: lucene/test-framework/src/java/org/apache/lucene/index/ThreadedIndexingAndSearchingTestCase.java
===================================================================
--- lucene/test-framework/src/java/org/apache/lucene/index/ThreadedIndexingAndSearchingTestCase.java	(revision 1686523)
+++ lucene/test-framework/src/java/org/apache/lucene/index/ThreadedIndexingAndSearchingTestCase.java	(working copy)
@@ -673,7 +673,10 @@
   protected void smokeTestSearcher(IndexSearcher s) throws Exception {
     runQuery(s, new TermQuery(new Term("body", "united")));
     runQuery(s, new TermQuery(new Term("titleTokenized", "states")));
-    PhraseQuery pq = new PhraseQuery("body", "united", "states");
+    PhraseQuery.Builder builder = new PhraseQuery.Builder("body");
+    builder.add("united");
+    builder.add("states");
+    PhraseQuery pq = builder.build();
     runQuery(s, pq);
   }
 }
Index: lucene/test-framework/src/java/org/apache/lucene/search/SearchEquivalenceTestBase.java
===================================================================
--- lucene/test-framework/src/java/org/apache/lucene/search/SearchEquivalenceTestBase.java	(revision 1686523)
+++ lucene/test-framework/src/java/org/apache/lucene/search/SearchEquivalenceTestBase.java	(working copy)
@@ -151,8 +151,11 @@
       query = TermRangeQuery.newStringRange("field", "a", "" + randomChar(), true, true);
     } else {
       // use a query with a two-phase approximation
-      PhraseQuery phrase = new PhraseQuery(100, "field", "" + randomChar(), "" + randomChar());
-      query = phrase;
+      PhraseQuery.Builder builder = new PhraseQuery.Builder("field");
+      builder.setSlop(100);
+      builder.add("" + randomChar());
+      builder.add("" + randomChar());
+      query = builder.build();
     }
     
     // now wrap the query as a filter. QWF has its own codepath
Index: solr/core/src/java/org/apache/solr/parser/SolrQueryParserBase.java
===================================================================
--- solr/core/src/java/org/apache/solr/parser/SolrQueryParserBase.java	(revision 1686523)
+++ solr/core/src/java/org/apache/solr/parser/SolrQueryParserBase.java	(working copy)
@@ -388,13 +388,13 @@
 
       if (query instanceof PhraseQuery) {
         PhraseQuery pq = (PhraseQuery) query;
+        PhraseQuery.Builder builder = new PhraseQuery.Builder(pq.getField());
+        builder.setSlop(slop);
         Term[] terms = pq.getTerms();
         int[] positions = pq.getPositions();
-        PhraseQuery.Builder builder = new PhraseQuery.Builder();
         for (int i = 0; i < terms.length; ++i) {
-          builder.add(terms[i], positions[i]);
+          builder.add(terms[i].bytes(), positions[i]);
         }
-        builder.setSlop(slop);
         query = builder.build();
         query.setBoost(pq.getBoost());
       }
Index: solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java
===================================================================
--- solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java	(revision 1686523)
+++ solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java	(working copy)
@@ -1244,14 +1244,15 @@
             if (query instanceof PhraseQuery) {
               PhraseQuery pq = (PhraseQuery)query;
               if (minClauseSize > 1 && pq.getTerms().length < minClauseSize) return null;
-              PhraseQuery.Builder builder = new PhraseQuery.Builder();
+              PhraseQuery.Builder builder = new PhraseQuery.Builder(pq.getField());
+              builder.setSlop(slop);
               Term[] terms = pq.getTerms();
               int[] positions = pq.getPositions();
               for (int i = 0; i < terms.length; ++i) {
-                builder.add(terms[i], positions[i]);
+                builder.add(terms[i].bytes(), positions[i]);
               }
-              builder.setSlop(slop);
               query = builder.build();
+              query.setBoost(pq.getBoost());
             } else if (query instanceof MultiPhraseQuery) {
               MultiPhraseQuery pq = (MultiPhraseQuery)query;
               if (minClauseSize > 1 && pq.getTermArrays().size() < minClauseSize) return null;
