Only allow ranges over holes when line number optimization is on

Bug: b/287210793
Change-Id: I38e643acdc7b53a330e82f5e52b17781bfdd2767
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 6ef1691..7841a75 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -141,7 +141,15 @@
 
   public enum LineNumberOptimization {
     OFF,
-    ON
+    ON;
+
+    public boolean isOff() {
+      return this == OFF;
+    }
+
+    public boolean isOn() {
+      return this == ON;
+    }
   }
 
   public enum DesugarState {
@@ -2547,7 +2555,7 @@
   }
 
   public boolean canUseDexPc2PcAsDebugInformation() {
-    return isGeneratingDex() && lineNumberOptimization == LineNumberOptimization.ON;
+    return isGeneratingDex() && lineNumberOptimization.isOn();
   }
 
   // Debug entries may be dropped only if the source file content allows being omitted from
diff --git a/src/main/java/com/android/tools/r8/utils/positions/DexPositionToNoPcMappedRangeMapper.java b/src/main/java/com/android/tools/r8/utils/positions/DexPositionToNoPcMappedRangeMapper.java
index a6a2a06..e80a0a7 100644
--- a/src/main/java/com/android/tools/r8/utils/positions/DexPositionToNoPcMappedRangeMapper.java
+++ b/src/main/java/com/android/tools/r8/utils/positions/DexPositionToNoPcMappedRangeMapper.java
@@ -26,7 +26,6 @@
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.code.Position;
 import com.android.tools.r8.ir.code.Position.SourcePosition;
-import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -176,7 +175,7 @@
 
   public DexPositionToNoPcMappedRangeMapper(AppView<?> appView) {
     this.appView = appView;
-    isIdentityMapping = appView.options().lineNumberOptimization == LineNumberOptimization.OFF;
+    isIdentityMapping = appView.options().lineNumberOptimization.isOff();
   }
 
   public List<MappedPosition> optimizeDexCodePositions(
diff --git a/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java b/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java
index 7fe3d32..0ab3695 100644
--- a/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java
+++ b/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java
@@ -1,4 +1,3 @@
-// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
@@ -45,7 +44,6 @@
 import com.android.tools.r8.synthesis.SyntheticItems;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.IntBox;
-import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
 import com.android.tools.r8.utils.ListUtils;
 import com.android.tools.r8.utils.OneShotCollectionConsumer;
 import com.android.tools.r8.utils.OriginalSourceFiles;
@@ -56,6 +54,7 @@
 import it.unimi.dsi.fastutil.ints.Int2IntSortedMap;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Comparator;
 import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Map;
@@ -79,7 +78,7 @@
       PositionRangeAllocator.createCardinalPositionRangeAllocator();
   private final NonCardinalPositionRangeAllocator nonCardinalRangeCache =
       PositionRangeAllocator.createNonCardinalPositionRangeAllocator();
-  private final int maxGap = 1000;
+  private final int maxGap;
 
   private MappedPositionToClassNameMapperBuilder(
       AppView<?> appView, OriginalSourceFiles originalSourceFiles) {
@@ -88,6 +87,7 @@
     classNameMapperBuilder = ClassNameMapper.builder();
     classNameMapperBuilder.setCurrentMapVersion(
         appView.options().getMapFileVersion().toMapVersionMappingInformation());
+    maxGap = appView.options().lineNumberOptimization.isOn() ? 1000 : 1;
   }
 
   public static String getPrunedInlinedClassObfuscatedPrefix() {
@@ -246,7 +246,7 @@
           residualMethod,
           originalMethod,
           originalType)) {
-        assert appView.options().lineNumberOptimization == LineNumberOptimization.OFF
+        assert appView.options().lineNumberOptimization.isOff()
             || hasAtMostOnePosition(appView, definition)
             || appView.isCfByteCodePassThrough(definition);
         return this;
@@ -290,6 +290,8 @@
         methodSpecificMappingInformation.add(OutlineMappingInformation.builder().build());
       }
 
+      mappedPositions.sort(Comparator.comparing(MappedPosition::getObfuscatedLine));
+
       // Update memberNaming with the collected positions, merging multiple positions into a
       // single region whenever possible.
       for (int i = 0; i < mappedPositions.size(); /* updated in body */ ) {
@@ -317,14 +319,7 @@
               || firstMappedPosition.getPosition().getOutlineCallee() != null) {
             break;
           }
-          // The mapped positions are not guaranteed to be in order, so maintain first and last
-          // position.
-          if (firstMappedPosition.getObfuscatedLine() > currentMappedPosition.getObfuscatedLine()) {
-            firstMappedPosition = currentMappedPosition;
-          }
-          if (lastMappedPosition.getObfuscatedLine() < currentMappedPosition.getObfuscatedLine()) {
-            lastMappedPosition = currentMappedPosition;
-          }
+          lastMappedPosition = currentMappedPosition;
         }
         Range obfuscatedRange =
             nonCardinalRangeCache.get(
@@ -385,9 +380,7 @@
         }
         i = j;
       }
-      // TODO(b/287210793): Enable assertion again.
-      assert true
-          || mappedPositions.size() <= 1
+      assert mappedPositions.size() <= 1
           || getBuilder().hasNoOverlappingRangesForSignature(residualSignature);
       return this;
     }
diff --git a/src/main/java/com/android/tools/r8/utils/positions/PositionRemapper.java b/src/main/java/com/android/tools/r8/utils/positions/PositionRemapper.java
index 3f0288f..861c9dc 100644
--- a/src/main/java/com/android/tools/r8/utils/positions/PositionRemapper.java
+++ b/src/main/java/com/android/tools/r8/utils/positions/PositionRemapper.java
@@ -20,7 +20,6 @@
 import com.android.tools.r8.utils.CfLineToMethodMapper;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
 import com.android.tools.r8.utils.Pair;
 import java.util.IdentityHashMap;
 import java.util.Map;
@@ -34,8 +33,7 @@
 
   static PositionRemapper getPositionRemapper(
       AppView<?> appView, CfLineToMethodMapper cfLineToMethodMapper) {
-    boolean identityMapping =
-        appView.options().lineNumberOptimization == LineNumberOptimization.OFF;
+    boolean identityMapping = appView.options().lineNumberOptimization.isOff();
     PositionRemapper positionRemapper =
         identityMapping
             ? new IdentityPositionRemapper()