Index: /trunk/src/org/openstreetmap/josm/actions/search/SearchCompiler.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/search/SearchCompiler.java	(revision 8898)
+++ /trunk/src/org/openstreetmap/josm/actions/search/SearchCompiler.java	(revision 8899)
@@ -106,5 +106,5 @@
 
     public class CoreSimpleMatchFactory implements SimpleMatchFactory {
-        private Collection<String> keywords = Arrays.asList("id", "version",
+        private Collection<String> keywords = Arrays.asList("id", "version", "type", "user", "role",
                 "changeset", "nodes", "ways", "tags", "areasize", "waylength", "modified", "selected",
                 "incomplete", "untagged", "closed", "new", "indownloadedarea",
@@ -141,4 +141,10 @@
                     case "version":
                         return new Version(tokenizer);
+                    case "type":
+                        return new ExactType(tokenizer.readTextOrNumber());
+                    case "user":
+                        return new UserMatch(tokenizer.readTextOrNumber());
+                    case "role":
+                        return new RoleMatch(tokenizer.readTextOrNumber());
                     case "changeset":
                         return new ChangesetId(tokenizer);
@@ -1583,5 +1589,6 @@
 
                 // key:value form where value is a string (may be OSM key search)
-                return parseKV(key, tokenizer.readTextOrNumber());
+                final String value = tokenizer.readTextOrNumber();
+                return new KeyValue(key, value != null ? value : "", regexSearch, caseSensitive);
             } else if (tokenizer.readIfEqual(Token.QUESTION_MARK))
                 return new BooleanMatch(key, false);
@@ -1610,20 +1617,4 @@
     }
 
-    private Match parseKV(String key, String value) throws ParseError {
-        if (value == null) {
-            value = "";
-        }
-        switch(key) {
-        case "type":
-            return new ExactType(value);
-        case "user":
-            return new UserMatch(value);
-        case "role":
-            return new RoleMatch(value);
-        default:
-            return new KeyValue(key, value, regexSearch, caseSensitive);
-        }
-    }
-
     private static int regexFlags(boolean caseSensitive) {
         int searchFlags = 0;
Index: /trunk/test/unit/org/openstreetmap/josm/actions/search/SearchCompilerTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/actions/search/SearchCompilerTest.java	(revision 8898)
+++ /trunk/test/unit/org/openstreetmap/josm/actions/search/SearchCompilerTest.java	(revision 8899)
@@ -16,7 +16,9 @@
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.RelationData;
 import org.openstreetmap.josm.data.osm.RelationMember;
+import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.data.osm.WayData;
@@ -325,3 +327,55 @@
         }
     }
+
+    /**
+     * Search for node objects.
+     * @throws ParseError if an error has been encountered while compiling
+     */
+    @Test
+    public void testTypeNode() throws ParseError {
+        final SearchContext sc = new SearchContext("type:node");
+        for (OsmPrimitive p : new OsmPrimitive[]{sc.n1, sc.n2, sc.w1, sc.w2, sc.r1, sc.r2}) {
+            sc.match(p, OsmPrimitiveType.NODE.equals(p.getType()));
+        }
+    }
+
+    /**
+     * Search for way objects.
+     * @throws ParseError if an error has been encountered while compiling
+     */
+    @Test
+    public void testTypeWay() throws ParseError {
+        final SearchContext sc = new SearchContext("type:way");
+        for (OsmPrimitive p : new OsmPrimitive[]{sc.n1, sc.n2, sc.w1, sc.w2, sc.r1, sc.r2}) {
+            sc.match(p, OsmPrimitiveType.WAY.equals(p.getType()));
+        }
+    }
+
+    /**
+     * Search for relation objects.
+     * @throws ParseError if an error has been encountered while compiling
+     */
+    @Test
+    public void testTypeRelation() throws ParseError {
+        final SearchContext sc = new SearchContext("type:relation");
+        for (OsmPrimitive p : new OsmPrimitive[]{sc.n1, sc.n2, sc.w1, sc.w2, sc.r1, sc.r2}) {
+            sc.match(p, OsmPrimitiveType.RELATION.equals(p.getType()));
+        }
+    }
+
+    /**
+     * Search for users.
+     * @throws ParseError if an error has been encountered while compiling
+     */
+    @Test
+    public void testUser() throws ParseError {
+        final SearchContext foobar = new SearchContext("user:foobar");
+        foobar.n1.setUser(User.createLocalUser("foobar"));
+        foobar.match(foobar.n1, true);
+        foobar.match(foobar.n2, false);
+        final SearchContext anonymous = new SearchContext("user:anonymous");
+        anonymous.n1.setUser(User.createLocalUser("foobar"));
+        anonymous.match(anonymous.n1, false);
+        anonymous.match(anonymous.n2, true);
+    }
 }
