Index: /trunk/src/org/openstreetmap/josm/data/validation/tests/CrossingWays.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/validation/tests/CrossingWays.java	(revision 18960)
+++ /trunk/src/org/openstreetmap/josm/data/validation/tests/CrossingWays.java	(revision 18961)
@@ -317,20 +317,29 @@
             DataSet ds = OsmDataManager.getInstance().getActiveDataSet();
             if (ds != null) {
-                for (Way w: waysToTest) {
-                    selection.addAll(ds.searchWays(w.getBBox()));
+                for (Way wt : waysToTest) {
+                    selection.addAll(ds.searchWays(wt.getBBox()).stream()
+                            .filter(w -> !w.isDeleted() && isPrimitiveUsable(w)).collect(Collectors.toList()));
+                    if (this instanceof CrossingWays.Boundaries) {
+                        List<Relation> relations = ds.searchRelations(wt.getBBox()).stream()
+                                .filter(p -> isPrimitiveUsable(p)).collect(Collectors.toList());
+                        for (Relation r: relations) {
+                            for (Way w : r.getMemberPrimitives(Way.class)) {
+                                if (!w.isIncomplete())
+                                    selection.add(w);
+                            }
+                        }
+                    }
                 }
             }
         }
         for (Way w : selection) {
-            if (!w.isDeleted() && isPrimitiveUsable(w)) {
-                testWay(w);
-            }
+            testWay(w);
         }
         // free storage
         cellSegments.clear();
         seenWays.clear();
-        waysToTest.clear();
         if (partialSelection)
             removeIrrelevantErrors(waysToTest);
+        waysToTest.clear();
         super.endTest();
     }
Index: /trunk/test/unit/org/openstreetmap/josm/data/validation/tests/CrossingWaysTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/data/validation/tests/CrossingWaysTest.java	(revision 18960)
+++ /trunk/test/unit/org/openstreetmap/josm/data/validation/tests/CrossingWaysTest.java	(revision 18961)
@@ -10,4 +10,5 @@
 import java.util.HashMap;
 import java.util.List;
+import java.util.stream.Collectors;
 
 import org.junit.jupiter.api.Test;
@@ -17,4 +18,5 @@
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.data.osm.WaySegment;
@@ -23,4 +25,6 @@
 import org.openstreetmap.josm.data.validation.tests.CrossingWays.SelfCrossing;
 import org.openstreetmap.josm.data.validation.tests.CrossingWays.Ways;
+import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.io.OsmReader;
 import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
@@ -200,4 +204,5 @@
         crossingWays.endTest();
 
+        assertEquals(109, crossingWays.getErrors().size());
         for (TestError e : crossingWays.getErrors()) {
             // we don't report self crossing ways in this test
@@ -220,3 +225,38 @@
     }
 
+    /**
+     * Check if partial selection find crossings with unselected objects.
+     * @throws Exception if an error occurs
+     */
+    @Test
+    void testPartial() throws Exception {
+
+        DataSet ds = OsmReader.parseDataSet(
+                Files.newInputStream(Paths.get(TestUtils.getTestDataRoot(), "crossingWays.osm")), null);
+        MainApplication.getLayerManager().addLayer(new OsmDataLayer(ds, null, null));
+
+        CrossingWays crossingWays = new CrossingWays.Ways();
+        List<OsmPrimitive> partialSelection = ds.getWays().stream().filter(w -> w.hasTag("testsel", "horizontal"))
+                .collect(Collectors.toList());
+
+        crossingWays.setPartialSelection(true);
+        crossingWays.startTest(null);
+        crossingWays.visit(partialSelection);
+        crossingWays.endTest();
+
+        assertEquals(109, crossingWays.getErrors().size());
+        for (TestError e : crossingWays.getErrors()) {
+            // we don't report self crossing ways in this test
+            assertEquals(2, e.getPrimitives().size(), e.getPrimitives().toString());
+            // see #20121: crossing water areas should not be reported
+            assertFalse(e.getPrimitives().stream().filter(Way.class::isInstance).allMatch(CrossingWays::isWaterArea));
+        }
+
+        CrossingWays crossingBoundaries = new CrossingWays.Boundaries();
+        crossingBoundaries.setPartialSelection(true);
+        crossingBoundaries.startTest(null);
+        crossingBoundaries.visit(ds.allPrimitives());
+        crossingBoundaries.endTest();
+        assertEquals(2, crossingBoundaries.getErrors().size());
+    }
 }
Index: /trunk/test/unit/org/openstreetmap/josm/data/validation/tests/DuplicateWayTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/data/validation/tests/DuplicateWayTest.java	(revision 18960)
+++ /trunk/test/unit/org/openstreetmap/josm/data/validation/tests/DuplicateWayTest.java	(revision 18961)
@@ -35,9 +35,24 @@
     private static void doTest(int code, String tags1, String tags2, boolean fixable) {
         performTest(code, buildDataSet(tags1, tags2), fixable);
+        performPartialTest(code, buildDataSet(tags1, tags2), fixable);
     }
 
     private static void performTest(int code, DataSet ds, boolean fixable) {
+        TEST.setPartialSelection(false);
         TEST.startTest(NullProgressMonitor.INSTANCE);
         TEST.visit(ds.allPrimitives());
+        TEST.endTest();
+
+        assertEquals(1, TEST.getErrors().size());
+        TestError error = TEST.getErrors().iterator().next();
+        assertEquals(code, error.getCode());
+        assertEquals(fixable, error.isFixable());
+    }
+
+    private static void performPartialTest(int code, DataSet ds, boolean fixable) {
+        ds.setSelected(ds.getWays().iterator().next());
+        TEST.setPartialSelection(true);
+        TEST.startTest(NullProgressMonitor.INSTANCE);
+        TEST.visit(ds.getSelectedWays().iterator().next());
         TEST.endTest();
 
