Merge "Repackage sparse conditional constant propagation."
diff --git a/build.gradle b/build.gradle
index a9c4e7a..db938f0 100644
--- a/build.gradle
+++ b/build.gradle
@@ -4,6 +4,7 @@
 import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
 import net.ltgt.gradle.errorprone.ErrorProneToolChain
 import org.gradle.internal.os.OperatingSystem
+import tasks.GetJarsFromConfiguration
 import utils.Utils
 
 apply plugin: 'java'
@@ -470,7 +471,6 @@
     baseName 'sources'
 }
 
-
 task R8(type: ShadowJar) {
     from consolidatedLicense.outputs.files
     from repackageSources.outputs.files
@@ -780,7 +780,7 @@
     }
     task extractExamplesRuntime(type: Sync) {
         dependsOn configurations.examplesRuntime
-        from configurations.examplesRuntime.collect { zipTree(it) }
+        from { configurations.examplesRuntime.collect { zipTree(it) } }
         include "**/*.class"
         includeEmptyDirs false
         into "$buildDir/runtime/examples/"
@@ -1185,53 +1185,8 @@
     args inFile
 }
 
-task supportLibDir() {
-    doLast {
-        File dir = file("build/supportlibraries")
-        dir.mkdir()
-    }
-}
-
-configurations.supportLibs.files.each { file ->
-    if (file.getName().endsWith(".aar")) {
-        def name = "extract_"+file.getName()
-        task "${name}"(type: Copy) {
-            dependsOn supportLibDir
-            from zipTree(file)
-            into "build/supportlibraries"
-            eachFile { FileCopyDetails fcp ->
-                if (fcp.relativePath.pathString.equals("classes.jar")) {
-                    // remap the file to the root with correct name
-                    fcp.relativePath = new RelativePath(true, file.getName().replace(".aar", ".jar"))
-                } else {
-                    fcp.exclude()
-                }
-            }
-        }
-    }
-}
-
-task supportLibList() {
-    configurations.supportLibs.files.each {
-        if (it.getName().endsWith(".aar")) {
-            dependsOn "extract_"+it.getName()
-        }
-    }
-    doLast {
-        file("build/generated").mkdir()
-        def file = file("build/generated/supportlibraries.txt")
-        file.createNewFile()
-        file.text = ""
-        configurations.supportLibs.files.each {
-            if (it.getName().endsWith(".aar")) {
-                def outName =  it.getName().replace(".aar", ".jar")
-                file.text += ("build/supportlibraries/"
-                  + outName + "\n")
-            } else {
-                file.text += (it.getPath() + "\n")
-            }
-        }
-    }
+task getJarsFromSupportLibs(type: GetJarsFromConfiguration) {
+    setConfiguration(configurations.supportLibs)
 }
 
 task AospJarTest(type: Exec) {
@@ -1243,7 +1198,7 @@
 }
 
 test {
-    dependsOn supportLibList
+    dependsOn getJarsFromSupportLibs
     testLogging.exceptionFormat = 'full'
     if (project.hasProperty('print_test_stdout')) {
         testLogging.showStandardStreams = true
diff --git a/buildSrc/src/main/java/tasks/GetJarsFromConfiguration.java b/buildSrc/src/main/java/tasks/GetJarsFromConfiguration.java
new file mode 100644
index 0000000..d638e0d
--- /dev/null
+++ b/buildSrc/src/main/java/tasks/GetJarsFromConfiguration.java
@@ -0,0 +1,87 @@
+// Copyright (c) 2016, 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.
+package tasks;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import org.gradle.api.DefaultTask;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.file.FileTree;
+import org.gradle.api.tasks.InputFiles;
+import org.gradle.api.tasks.OutputDirectory;
+import org.gradle.api.tasks.OutputFile;
+import org.gradle.api.tasks.TaskAction;
+
+/**
+ * Extract all jars from the configuration. If an aar is in the configuration, classes.jar is
+ * extracted. Locations of the jars are written to a generated file.
+ */
+public class GetJarsFromConfiguration extends DefaultTask {
+
+  private Configuration configuration;
+
+  @InputFiles
+  public Configuration getInputFiles() {
+    return configuration;
+  }
+
+  public void setConfiguration(Configuration configuration) {
+    this.configuration = configuration;
+  }
+
+  @OutputDirectory
+  public File getOutputDir() {
+    return new File(getProject().getBuildDir(), "supportlibraries");
+  }
+
+  @OutputFile
+  public File getGeneratedFile() {
+    return new File(getProject().getBuildDir(), "generated/supportlibraries.txt");
+  }
+
+  @TaskAction
+  public void extract() throws IOException {
+    Files.createDirectories(getOutputDir().toPath());
+
+    Set<File> configurationFiles = configuration.getFiles();
+    List<String> jarPaths = new ArrayList<>(configurationFiles.size());
+    for (File file : configurationFiles) {
+      jarPaths.add(getSingleJar(file));
+    }
+
+    Path generatedPath = getGeneratedFile().toPath();
+    Files.deleteIfExists(generatedPath);
+    Files.createDirectories(generatedPath.getParent());
+    Files.write(generatedPath, jarPaths);
+  }
+
+  private String getSingleJar(File jarOrAar) throws IOException {
+    if (jarOrAar.getName().endsWith(".aar")) {
+      FileTree aarEntries = getProject().zipTree(jarOrAar);
+
+      for (File aarEntry : aarEntries) {
+        if (aarEntry.getName().equals("classes.jar")) {
+          try (InputStream is = new FileInputStream(aarEntry)) {
+            String jarName = jarOrAar.getName().replaceAll("\\.aar$", ".jar");
+            Path extractedPath = getOutputDir().toPath().resolve(jarName);
+            Files.deleteIfExists(extractedPath);
+            Files.copy(is, extractedPath);
+
+            return extractedPath.toString();
+          }
+        }
+      }
+      throw new RuntimeException("Aar does not contain classes.jar: " + jarOrAar.toString());
+    } else {
+      return jarOrAar.toString();
+    }
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/BaseCommand.java b/src/main/java/com/android/tools/r8/BaseCommand.java
index 8a0e247..4059ab8 100644
--- a/src/main/java/com/android/tools/r8/BaseCommand.java
+++ b/src/main/java/com/android/tools/r8/BaseCommand.java
@@ -110,17 +110,6 @@
       return app;
     }
 
-    /**
-     * This is not part of the public API of a command, but allows subclasses to add vdex
-     * files as allowed input.
-     *
-     * Default is that vdex is not allowed.
-     */
-    B setVdexAllowed() {
-      guard(() -> getAppBuilder().setVdexAllowed());
-      return self();
-    }
-
     /** Add program file resources. */
     public B addProgramFiles(Path... files) {
       addProgramFiles(Arrays.asList(files));
diff --git a/src/main/java/com/android/tools/r8/DexSegments.java b/src/main/java/com/android/tools/r8/DexSegments.java
index be50c0e..59a3c86 100644
--- a/src/main/java/com/android/tools/r8/DexSegments.java
+++ b/src/main/java/com/android/tools/r8/DexSegments.java
@@ -44,8 +44,7 @@
         "  --help                  # Print this message."));
 
     public static Command.Builder builder() {
-      // Allow vdex files for the dex segments tool.
-      return new Command.Builder().setVdexAllowed();
+      return new Command.Builder();
     }
 
     public static Command.Builder parse(String[] args) {
diff --git a/src/main/java/com/android/tools/r8/Diagnostic.java b/src/main/java/com/android/tools/r8/Diagnostic.java
index b0868cc..7896251 100644
--- a/src/main/java/com/android/tools/r8/Diagnostic.java
+++ b/src/main/java/com/android/tools/r8/Diagnostic.java
@@ -4,12 +4,27 @@
 package com.android.tools.r8;
 
 import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.position.Position;
 
 /**
  * Interface for all diagnostic message produced by D8 and R8.
  */
 public interface Diagnostic {
+
+  /**
+   * Origin of the resource causing the problem.
+   * @return Origin.unknown() when origin is not available.
+   */
   Origin getOrigin();
 
+  /**
+   * Position of the problem in the origin.
+   * @return {@link Position#UNKNOWN} when position is not available.
+   */
+  Position getPosition();
+
+  /**
+   * User friendly description of the problem.
+   */
   String getDiagnosticMessage();
 }
diff --git a/src/main/java/com/android/tools/r8/ExtractMarker.java b/src/main/java/com/android/tools/r8/ExtractMarker.java
index 6534361..b3c9a6d 100644
--- a/src/main/java/com/android/tools/r8/ExtractMarker.java
+++ b/src/main/java/com/android/tools/r8/ExtractMarker.java
@@ -5,11 +5,16 @@
 
 import com.android.tools.r8.dex.ApplicationReader;
 import com.android.tools.r8.dex.Marker;
+import com.android.tools.r8.dex.VDexFile;
+import com.android.tools.r8.dex.VDexFileReader;
 import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.graph.DexApplication;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.origin.PathOrigin;
 import com.android.tools.r8.shaking.FilteredClassPath;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.FileUtils;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.Timing;
 import com.google.common.io.ByteStreams;
@@ -19,18 +24,30 @@
 import java.util.concurrent.ExecutionException;
 
 public class ExtractMarker {
+  public static class VdexOrigin extends Origin {
+
+    private final int index;
+
+    public VdexOrigin(Origin vdexOrigin, int index) {
+      super(vdexOrigin);
+      this.index = index;
+    }
+
+    @Override
+    public String part() {
+      return Integer.toString(index);
+    }
+  }
 
   public static Marker extractMarkerFromDexFile(Path file) throws IOException, ExecutionException {
     AndroidApp.Builder appBuilder = AndroidApp.builder();
-    appBuilder.setVdexAllowed();
-    appBuilder.addProgramFiles(FilteredClassPath.unfiltered(file));
+    addDexResources(appBuilder, file);
     return extractMarker(appBuilder.build());
   }
 
   public static int extractDexSize(Path file) throws IOException, ExecutionException {
     AndroidApp.Builder appBuilder = AndroidApp.builder();
-    appBuilder.setVdexAllowed();
-    appBuilder.addProgramFiles(FilteredClassPath.unfiltered(file));
+    addDexResources(appBuilder, file);
     int size = 0;
     for (Resource resource : appBuilder.build().getDexProgramResources()) {
       try (InputStream input = resource.getStream()) {
@@ -46,6 +63,20 @@
     return extractMarker(app);
   }
 
+  private static void addDexResources(AndroidApp.Builder appBuilder, Path file) throws IOException {
+    if (FileUtils.isVDexFile(file)) {
+      PathOrigin vdexOrigin = new PathOrigin(file);
+      VDexFileReader reader = new VDexFileReader(new VDexFile(Resource.fromFile(file)));
+      int index = 0;
+      for (byte[] bytes : reader.getDexFiles()) {
+        appBuilder.addDexProgramData(bytes, new VdexOrigin(vdexOrigin, index));
+        index++;
+      }
+    } else {
+      appBuilder.addProgramFiles(FilteredClassPath.unfiltered(file));
+    }
+  }
+
   private static Marker extractMarker(AndroidApp app) throws IOException, ExecutionException {
     InternalOptions options = new InternalOptions();
     options.skipReadingDexCode = true;
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index 50e1e6e..57eed20 100644
--- a/src/main/java/com/android/tools/r8/Version.java
+++ b/src/main/java/com/android/tools/r8/Version.java
@@ -10,7 +10,7 @@
 
   // This field is accessed from release scripts using simple pattern matching.
   // Therefore, changing this field could break our release scripts.
-  public static final String LABEL = "v0.2.1-dev";
+  public static final String LABEL = "v0.2.2-dev";
 
   private Version() {
   }
diff --git a/src/main/java/com/android/tools/r8/errors/CompilationError.java b/src/main/java/com/android/tools/r8/errors/CompilationError.java
index 5c3220d..1104b29 100644
--- a/src/main/java/com/android/tools/r8/errors/CompilationError.java
+++ b/src/main/java/com/android/tools/r8/errors/CompilationError.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.Diagnostic;
 import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.position.Position;
 
 /**
  * Exception to signal an compilation error.
@@ -15,6 +16,7 @@
 public class CompilationError extends RuntimeException implements Diagnostic {
 
   private final Origin origin;
+  private final Position position;
   public CompilationError(String message) {
     this(message, Origin.unknown());
   }
@@ -27,9 +29,14 @@
     this(message, null, origin);
   }
 
-  public CompilationError(String message, Throwable cause, Origin location) {
+  public CompilationError(String message, Throwable cause, Origin origin) {
+    this(message, cause, origin, Position.UNKNOWN);
+  }
+
+  public CompilationError(String message, Throwable cause, Origin origin, Position position) {
     super(message, cause);
-    this.origin = location;
+    this.origin = origin;
+    this.position = position;
   }
 
   @Override
@@ -38,6 +45,11 @@
   }
 
   @Override
+  public Position getPosition() {
+    return position;
+  }
+
+  @Override
   public String getDiagnosticMessage() {
     return getMessage();
   }
diff --git a/src/main/java/com/android/tools/r8/graph/ClassAccessFlags.java b/src/main/java/com/android/tools/r8/graph/ClassAccessFlags.java
index a72c1bc..f587642 100644
--- a/src/main/java/com/android/tools/r8/graph/ClassAccessFlags.java
+++ b/src/main/java/com/android/tools/r8/graph/ClassAccessFlags.java
@@ -74,7 +74,13 @@
 
   @Override
   public int getAsDexAccessFlags() {
-    return flags & ~Constants.ACC_SUPER;
+    // We unset the super flag here, as it is meaningless in DEX. Furthermore, we add missing
+    // abstract to interfaces to work around a javac bug when generating package-info classes.
+    if (isInterface()) {
+      return (flags & ~Constants.ACC_SUPER) | Constants.ACC_ABSTRACT;
+    } else {
+      return flags & ~Constants.ACC_SUPER;
+    }
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/origin/TextRangeOrigin.java b/src/main/java/com/android/tools/r8/origin/TextRangeOrigin.java
deleted file mode 100644
index 4df5540..0000000
--- a/src/main/java/com/android/tools/r8/origin/TextRangeOrigin.java
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright (c) 2017, 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.
-
-package com.android.tools.r8.origin;
-
-/**
- * An {@link Origin} with a position in a text file.
- */
-public class TextRangeOrigin extends Origin {
-
-  /**
-   * A position in a text file determined by line and column.
-   * Line and column numbers start at 1.
-   */
-  public static class TextPosition {
-    private final int line;
-    private final int column;
-
-    public TextPosition(int line, int column) {
-      this.line = line;
-      this.column = column;
-    }
-
-    /**
-     * Return the line of this position.
-     */
-    public int getLine() {
-      return line;
-    }
-
-    /**
-     * Return the column of this position.
-     * @return May return {@link #UNKNOWN_COLUMN} if column information is not available.
-     */
-    public int getColumn() {
-      return column;
-    }
-
-    @Override
-    public String toString() {
-      return "Line: " + line + ", column: " + column;
-    }
-
-    @Override
-    public final int hashCode() {
-      return line ^ (column << 16);
-    }
-
-    @Override
-    public final boolean equals(Object o) {
-      if (o == this) {
-        return true;
-      }
-      if (o instanceof TextPosition) {
-        TextPosition other = (TextPosition) o;
-        return line == other.line && column == other.column;
-      }
-      return false;
-    }
-  }
-
-  /**
-   * Line or column is unknown.
-   */
-  public static final int UNKNOWN_COLUMN = -1;
-
-  private final TextPosition start;
-  private final TextPosition end;
-
-  public static Origin get(Origin fileOrigin, int startLine, int startColumn) {
-    return get(fileOrigin, startLine, startColumn, startLine, startColumn);
-  }
-
-  public static Origin get(Origin fileOrigin, int startLine, int startColumn, int endLine,
-      int endColumn) {
-    if (fileOrigin == Origin.unknown()) {
-      return Origin.unknown();
-    } else {
-      assert startLine > 0
-          && endLine >= startLine
-          && ((startColumn == UNKNOWN_COLUMN && endColumn == UNKNOWN_COLUMN)
-            || (startColumn > 0 && endColumn > 0));
-      TextPosition start = new TextPosition(startLine, startColumn);
-      TextPosition end;
-      if (startLine == endLine && startColumn == endColumn) {
-        end = start;
-      } else {
-        end = new TextPosition(endLine, endColumn);
-      }
-      return new TextRangeOrigin(fileOrigin, start, end);
-    }
-  }
-
-  private TextRangeOrigin(Origin fileOrigin, TextPosition start, TextPosition end) {
-    super(fileOrigin);
-    this.start = start;
-    this.end = end;
-  }
-
-  /**
-   * Return the start position of this text range.
-   */
-  public TextPosition getStart() {
-    return start;
-  }
-
-  /**
-   * Return the end position of this text range.
-   */
-  public TextPosition getEnd() {
-    return end;
-  }
-
-  @Override
-  public String part() {
-    return " line " + getStart().getLine();
-  }
-}
diff --git a/src/main/java/com/android/tools/r8/position/BinaryPosition.java b/src/main/java/com/android/tools/r8/position/BinaryPosition.java
new file mode 100644
index 0000000..5eb2da2
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/position/BinaryPosition.java
@@ -0,0 +1,49 @@
+// Copyright (c) 2017, 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.
+
+package com.android.tools.r8.position;
+
+public class BinaryPosition implements Position {
+
+  /**
+   * Byte offset from start of the resource.
+   */
+  private final long offset;
+
+  public BinaryPosition(long offset) {
+    assert offset >= 0;
+    this.offset = offset;
+  }
+
+  public long getOffset() {
+    return offset;
+  }
+
+  @Override
+  public String toString() {
+    return "Index : " + offset;
+  }
+
+  @Override
+  public int hashCode() {
+    return Long.hashCode(offset);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (o == this) {
+      return true;
+    }
+    if (o != null  && o.getClass().equals(BinaryPosition.class)) {
+      BinaryPosition other = (BinaryPosition) o;
+      return offset == other.offset;
+    }
+    return false;
+  }
+
+  @Override
+  public String getDescription() {
+    return "Offset " + offset;
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/position/Position.java b/src/main/java/com/android/tools/r8/position/Position.java
new file mode 100644
index 0000000..902fad5
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/position/Position.java
@@ -0,0 +1,28 @@
+// Copyright (c) 2017, 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.
+
+package com.android.tools.r8.position;
+
+/**
+ * Represent a position in a resource, it can for example be line in a text file of the byte offset
+ * in a binary stream.
+ */
+public interface Position {
+
+  /**
+   * Position is unknown.
+   */
+  Position UNKNOWN = new Position() {
+    @Override
+    public String getDescription() {
+      return "Unknown";
+    }
+  };
+
+  /**
+   * A user friendly text representation of this position.
+   */
+  String getDescription();
+
+}
diff --git a/src/main/java/com/android/tools/r8/position/TextPosition.java b/src/main/java/com/android/tools/r8/position/TextPosition.java
new file mode 100644
index 0000000..17de30d
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/position/TextPosition.java
@@ -0,0 +1,79 @@
+// Copyright (c) 2017, 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.
+
+package com.android.tools.r8.position;
+
+/**
+ * A position in a text file determined by line and column.
+ * Line and column numbers start at 1.
+ */
+public class TextPosition implements Position {
+
+  /**
+   * Column is unknown.
+   */
+  public static final int UNKNOWN_COLUMN = -1;
+
+  /**
+   * Char offset from the start of the text resource.
+   */
+  private final long offset;
+  private final int line;
+  private final int column;
+
+  public TextPosition(long offset, int line, int column) {
+    assert (offset >= 1)
+        && (line >= 1)
+        && (column >= 1 || column == UNKNOWN_COLUMN);
+    this.offset = offset;
+    this.line = line;
+    this.column = column;
+  }
+
+  /**
+   * Return the line of this position.
+   */
+  public int getLine() {
+    return line;
+  }
+
+  /**
+   * Return the column of this position.
+   * @return May return {@link #UNKNOWN_COLUMN} if column information is not available.
+   */
+  public int getColumn() {
+    return column;
+  }
+
+  public long getOffset() {
+    return offset;
+  }
+
+  @Override
+  public String toString() {
+    return "Offset: " + offset + ", Line: " + line + ", column: " + column;
+  }
+
+  @Override
+  public String getDescription() {
+    return "Line: " + line + (column != UNKNOWN_COLUMN ? ", column: " + column: "");
+  }
+
+  @Override
+  public int hashCode() {
+    return Long.hashCode(offset) ^ line ^ (column << 16);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (o == this) {
+      return true;
+    }
+    if (o != null  && o.getClass().equals(TextPosition.class)) {
+      TextPosition other = (TextPosition) o;
+      return offset == other.offset && line == other.line && column == other.column;
+    }
+    return false;
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/position/TextRange.java b/src/main/java/com/android/tools/r8/position/TextRange.java
new file mode 100644
index 0000000..d7c0f43
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/position/TextRange.java
@@ -0,0 +1,51 @@
+// Copyright (c) 2017, 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.
+
+package com.android.tools.r8.position;
+
+public class TextRange implements Position {
+  private final TextPosition start;
+  private final TextPosition end;
+
+  public TextRange(TextPosition start, TextPosition end) {
+    this.start = start;
+    this.end = end;
+  }
+
+  /**
+   * Return the start position of this range.
+   */
+  public TextPosition getStart() {
+    return start;
+  }
+
+  /**
+   * Return the end position of this range.
+   */
+  public TextPosition getEnd() {
+    return end;
+  }
+
+  @Override
+  public int hashCode() {
+    return start.hashCode() ^ end.hashCode();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (o == this) {
+      return true;
+    }
+    if (o != null  && o.getClass().equals(getClass())) {
+      TextRange other = (TextRange) o;
+      return start.equals(other.getStart()) && end.equals(other.getEnd());
+    }
+    return false;
+  }
+
+  @Override
+  public String getDescription() {
+    return start.getDescription();
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
index 631fbc0..8fe9355 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.naming.DictionaryReader;
 import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.position.Position;
 import com.android.tools.r8.utils.InternalOptions.PackageObfuscationMode;
 import com.android.tools.r8.utils.Reporter;
 import com.google.common.collect.ImmutableList;
@@ -46,6 +47,7 @@
     private boolean useUniqueClassMemberNames;
     private boolean keepParameterNames;
     private Origin keepParameterNamesOptionOrigin;
+    private Position keepParameterNamesOptionPosition;
     private ProguardClassFilter.Builder adaptClassStrings = ProguardClassFilter.builder();
     private boolean forceProguardCompatibility = false;
     private boolean overloadAggressively;
@@ -169,10 +171,12 @@
       return useUniqueClassMemberNames;
     }
 
-    public void setKeepParameterNames(boolean keepParameterNames, Origin optionOrigin) {
+    public void setKeepParameterNames(boolean keepParameterNames, Origin optionOrigin,
+        Position optionPosition) {
       assert optionOrigin != null || !keepParameterNames;
       this.keepParameterNames = keepParameterNames;
       this.keepParameterNamesOptionOrigin = optionOrigin;
+      this.keepParameterNamesOptionPosition = optionPosition;
     }
 
     boolean isKeepParameterNames() {
@@ -183,6 +187,10 @@
       return keepParameterNamesOptionOrigin;
     }
 
+    Position getKeepParameterNamesOptionPosition() {
+      return keepParameterNamesOptionPosition;
+    }
+
     public void addAdaptClassStringsPattern(ProguardClassNameList pattern) {
       adaptClassStrings.addPattern(pattern);
     }
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
index 9c5fc27..4f5447d 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.shaking;
 
-import com.android.tools.r8.origin.TextRangeOrigin;
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexItemFactory;
@@ -11,6 +10,9 @@
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.logging.Log;
 import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.position.Position;
+import com.android.tools.r8.position.TextPosition;
+import com.android.tools.r8.position.TextRange;
 import com.android.tools.r8.shaking.ProguardConfiguration.Builder;
 import com.android.tools.r8.shaking.ProguardTypeMatcher.ClassOrType;
 import com.android.tools.r8.shaking.ProguardTypeMatcher.MatchSpecificType;
@@ -90,7 +92,8 @@
       // are not.
       reporter.fatalError(new StringDiagnostic(
           "-keepparameternames is not supported",
-          configurationBuilder.getKeepParameterNamesOptionOrigin()));
+          configurationBuilder.getKeepParameterNamesOptionOrigin(),
+          configurationBuilder.getKeepParameterNamesOptionPosition()));
     }
   }
 
@@ -164,8 +167,7 @@
       if (acceptArobaseInclude()) {
         return true;
       }
-      int optionLine = line;
-      int optionColumn = getColumn();
+      TextPosition optionStart = getPosition();
       expectChar('-');
       String option;
       if (Iterables.any(IGNORED_SINGLE_ARG_OPTIONS, this::skipOptionWithSingleArg)
@@ -179,12 +181,13 @@
           (option = Iterables.find(WARNED_SINGLE_ARG_OPTIONS,
               this::skipOptionWithSingleArg, null)) != null
               || (option = Iterables.find(WARNED_FLAG_OPTIONS, this::skipFlag, null)) != null) {
-        warnIgnoringOptions(option, optionLine, optionColumn);
+        warnIgnoringOptions(option, optionStart);
       } else if (
           (option = Iterables.find(UNSUPPORTED_FLAG_OPTIONS, this::skipFlag, null)) != null) {
         reporter.error(new StringDiagnostic(
             "Unsupported option: -" + option,
-            getOrigin(optionLine, optionColumn)));
+            origin,
+            getPostion(optionStart)));
       } else if (acceptString("renamesourcefileattribute")) {
         skipWhitespace();
         if (isOptionalArgumentGiven()) {
@@ -199,7 +202,7 @@
         configurationBuilder.addRule(rule);
       } else if (acceptString("keepparameternames")) {
         configurationBuilder.setKeepParameterNames(true,
-            getOrigin(optionLine, optionColumn));
+            origin, getPostion(optionStart));
       } else if (acceptString("checkdiscard")) {
         ProguardCheckDiscardRule rule = parseCheckDiscardRule();
         configurationBuilder.addRule(rule);
@@ -217,9 +220,10 @@
         if (expectedOptimizationPasses == null) {
           throw reporter.fatalError(new StringDiagnostic(
               "Missing n of \"-optimizationpasses n\"",
-              getOrigin(optionLine, optionColumn)));
+              origin,
+              getPostion(optionStart)));
         }
-        warnIgnoringOptions("optimizationpasses", optionLine, optionColumn);
+        warnIgnoringOptions("optimizationpasses", optionStart);
       } else if (acceptString("dontobfuscate")) {
         configurationBuilder.setObfuscating(false);
       } else if (acceptString("dontshrink")) {
@@ -245,7 +249,7 @@
       } else if (acceptString("repackageclasses")) {
         if (configurationBuilder.getPackageObfuscationMode() == PackageObfuscationMode.FLATTEN) {
           warnOverridingOptions("repackageclasses", "flattenpackagehierarchy",
-              optionLine, optionColumn);
+              optionStart);
         }
         skipWhitespace();
         if (acceptChar('\'')) {
@@ -257,7 +261,7 @@
       } else if (acceptString("flattenpackagehierarchy")) {
         if (configurationBuilder.getPackageObfuscationMode() == PackageObfuscationMode.REPACKAGE) {
           warnOverridingOptions("repackageclasses", "flattenpackagehierarchy",
-              optionLine, optionColumn);
+              optionStart);
           skipWhitespace();
           if (isOptionalArgumentGiven()) {
             skipSingleArgument();
@@ -329,25 +333,24 @@
       } else {
         String unknownOption = acceptString();
         reporter.error(new StringDiagnostic("Unknown option \"-" + unknownOption + "\"",
-            getOrigin(optionLine, optionColumn)));
+            origin, getPostion(optionStart)));
       }
       return true;
     }
 
 
     private void parseInclude() throws ProguardRuleParserException {
-      int startLine = line;
-      int startColumn = getColumn();
+      TextPosition start = getPosition();
       Path included = parseFileName();
       try {
         new ProguardConfigurationSourceParser(new ProguardConfigurationSourceFile(included))
             .parse();
       } catch (FileNotFoundException | NoSuchFileException e) {
         throw parseError("Included file '" + included.toString() + "' not found",
-            startLine, startColumn, e);
+            start, e);
       } catch (IOException e) {
         throw parseError("Failed to read included file '" + included.toString() + "'",
-            startLine, startColumn, e);
+            start, e);
       }
     }
 
@@ -534,13 +537,13 @@
         } else {
           // The only path to here is through "-keep" followed by "class".
           unacceptString("-keepclass");
-          int startLine = line;
-          int startColumn = getColumn();
+          TextPosition start = getPosition();
           acceptString("-");
           String unknownOption = acceptString();
           throw reporter.fatalError(new StringDiagnostic(
               "Unknown option \"-" + unknownOption + "\"",
-              getOrigin(startLine, startColumn)));
+              origin,
+              start));
         }
       } else {
         builder.setType(ProguardKeepRuleType.KEEP);
@@ -618,8 +621,7 @@
 
     private ProguardClassType parseClassType() throws ProguardRuleParserException {
       skipWhitespace();
-      int startLine = line;
-      int startColumn = getColumn();
+      TextPosition start = getPosition();
       if (acceptString("interface")) {
         return ProguardClassType.INTERFACE;
       } else if (acceptString("@interface")) {
@@ -630,7 +632,7 @@
         return ProguardClassType.ENUM;
       } else {
         throw reporter.fatalError(new StringDiagnostic("Expected interface|class|enum",
-            getOrigin(startLine, startColumn)));
+            origin, getPostion(start)));
       }
     }
 
@@ -780,8 +782,7 @@
                   } else if (acceptString("false")) {
                     ruleBuilder.setReturnValue(new ProguardMemberRuleReturnValue(false));
                   } else {
-                    int fieldStartLine = line;
-                    int fieldStartColumn = getColumn();
+                    TextPosition fieldStart = getPosition();
                     String qualifiedFieldName = acceptFieldName();
                     if (qualifiedFieldName != null) {
                       if (ruleBuilder.getTypeMatcher() instanceof MatchSpecificType) {
@@ -798,12 +799,10 @@
                             .createField(fieldClass, fieldType, fieldName);
                         ruleBuilder.setReturnValue(new ProguardMemberRuleReturnValue(field));
                       } else {
-                        throw parseError("Expected specific type", fieldStartLine,
-                            fieldStartColumn);
+                        throw parseError("Expected specific type", fieldStart);
                       }
                     } else {
-                      int valueStartLine = line;
-                      int valueStartColumn = getColumn();
+                      TextPosition valueStart = getPosition();
                       Integer min = acceptInteger();
                       Integer max = min;
                       if (min == null) {
@@ -817,8 +816,7 @@
                         }
                       }
                       if (!allowValueSpecification) {
-                        throw parseError("Unexpected value specification", valueStartLine,
-                            valueStartColumn);
+                        throw parseError("Unexpected value specification", valueStart);
                       }
                       ruleBuilder.setReturnValue(
                           new ProguardMemberRuleReturnValue(new LongInterval(min, max)));
@@ -864,15 +862,14 @@
     }
 
     private Path parseFileName() throws ProguardRuleParserException {
-      int startLine = this.line;
-      int startColumn = getColumn();
+      TextPosition start = getPosition();
       skipWhitespace();
       String fileName = acceptString(character ->
           character != File.pathSeparatorChar
               && !Character.isWhitespace(character)
               && character != '(');
       if (fileName == null) {
-        throw parseError("File name expected", startLine, startColumn);
+        throw parseError("File name expected", start);
       }
       return baseDirectory.resolve(fileName);
     }
@@ -912,14 +909,13 @@
     }
 
     private String parseFileFilter() throws ProguardRuleParserException {
-      int startLine = line;
-      int startColumn = getColumn();
+      TextPosition start = getPosition();
       skipWhitespace();
       String fileFilter = acceptString(character ->
           character != ',' && character != ';' && character != ')'
               && !Character.isWhitespace(character));
       if (fileFilter == null) {
-        throw parseError("file filter expected", startLine, startColumn);
+        throw parseError("file filter expected", start);
       }
       return fileFilter;
     }
@@ -1067,12 +1063,11 @@
       while (pattern != null) {
         patterns.add(pattern);
         skipWhitespace();
-        int startLine = line;
-        int startColumn = getColumn();
+        TextPosition start = getPosition();
         if (acceptChar(',')) {
           pattern = acceptPattern();
           if (pattern == null) {
-            throw parseError("Expected list element", startLine, startColumn);
+            throw parseError("Expected list element", start);
           }
         } else {
           pattern = null;
@@ -1157,53 +1152,58 @@
       }
       return name;
     }
-    private String snippetForPosition(int lineNumber, int columnNumber) {
+    private String snippetForPosition(TextPosition start) {
       // TODO(ager): really should deal with \r as well to get column right.
       String[] lines = contents.split("\n", -1);  // -1 to get trailing empty lines represented.
-      String line = lines[lineNumber-1];
-      String arrow = CharBuffer.allocate(columnNumber - 1).toString().replace('\0', ' ') + '^';
-      return name + ":" + (lineNumber + 1) + ":" + columnNumber + "\n" + line
+      String line = lines[start.getLine() - 1];
+      String arrow = CharBuffer.allocate(start.getColumn() - 1).toString().replace('\0', ' ') + '^';
+      return name + ":" + (start.getLine() + 1) + ":" + start.getColumn() + "\n" + line
           + '\n' + arrow;
     }
 
     private ProguardRuleParserException parseError(String message) {
-      return new ProguardRuleParserException(message, snippetForPosition(), getOrigin());
+      return new ProguardRuleParserException(message, snippetForPosition(), origin, getPosition());
     }
 
     private ProguardRuleParserException parseError(String message, Throwable cause) {
-      return new ProguardRuleParserException(message, snippetForPosition(), getOrigin(), cause);
+      return new ProguardRuleParserException(message, snippetForPosition(), origin, getPosition(),
+          cause);
     }
 
-    private ProguardRuleParserException parseError(String message, int startLine, int startColumn,
+    private ProguardRuleParserException parseError(String message, TextPosition start,
         Throwable cause) {
-      return new ProguardRuleParserException(message, snippetForPosition(startLine, startColumn),
-          getOrigin(startLine, startColumn), cause);
+      return new ProguardRuleParserException(message, snippetForPosition(start),
+          origin, getPostion(start), cause);
     }
 
-    private ProguardRuleParserException parseError(String message, int startLine, int startColumn) {
-      return new ProguardRuleParserException(message, snippetForPosition(startLine, startColumn),
-          getOrigin(startLine, startColumn));
+    private ProguardRuleParserException parseError(String message, TextPosition start) {
+      return new ProguardRuleParserException(message, snippetForPosition(start),
+          origin, getPostion(start));
     }
 
-    private void warnIgnoringOptions(String optionName, int startLine, int startColumn) {
+    private void warnIgnoringOptions(String optionName, TextPosition start) {
       reporter.warning(new StringDiagnostic(
           "Ignoring option: -" + optionName,
-          getOrigin(startLine, startColumn)));
+          origin,
+          getPostion(start)));
     }
 
-    private void warnOverridingOptions(String optionName, String victim, int optionLine,
-        int optionColumn) {
+    private void warnOverridingOptions(String optionName, String victim, TextPosition start) {
       reporter.warning(
           new StringDiagnostic("Option -" + optionName + " overrides -" + victim,
-              getOrigin(optionLine, optionColumn)));
+              origin, getPostion(start)));
     }
 
-    private Origin getOrigin(int startLine, int startColumn) {
-      return TextRangeOrigin.get(origin, startLine, startColumn, line, getColumn());
+    private Position getPostion(TextPosition start) {
+      if (start.getOffset() == position) {
+        return start;
+      } else {
+        return new TextRange(start, getPosition());
+      }
     }
 
-    private Origin getOrigin() {
-      return TextRangeOrigin.get(origin, line, getColumn());
+    private TextPosition getPosition() {
+      return new TextPosition(position, line, getColumn());
     }
 
     private int getColumn() {
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardRuleParserException.java b/src/main/java/com/android/tools/r8/shaking/ProguardRuleParserException.java
index 4b9308c..603c56a 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardRuleParserException.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardRuleParserException.java
@@ -5,22 +5,26 @@
 
 import com.android.tools.r8.Diagnostic;
 import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.position.Position;
 
 public class ProguardRuleParserException extends Exception implements Diagnostic {
 
   private final String message;
   private final String snippet;
   private final Origin origin;
+  private final Position position;
 
-  public ProguardRuleParserException(String message, String snippet, Origin origin) {
+  public ProguardRuleParserException(String message, String snippet, Origin origin,
+      Position position) {
     this.message = message;
     this.snippet = snippet;
     this.origin = origin;
+    this.position = position;
   }
 
   public ProguardRuleParserException(String message, String snippet, Origin origin,
-      Throwable cause) {
-    this(message, snippet,origin);
+      Position position, Throwable cause) {
+    this(message, snippet,origin, position);
     initCause(cause);
   }
 
@@ -30,6 +34,11 @@
   }
 
   @Override
+  public Position getPosition() {
+    return position;
+  }
+
+  @Override
   public String getDiagnosticMessage() {
     return message + " at " + snippet;
   }
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApp.java b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
index 4b7b6d4..d6dcdb8 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApp.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
@@ -6,13 +6,10 @@
 import static com.android.tools.r8.utils.FileUtils.isArchive;
 import static com.android.tools.r8.utils.FileUtils.isClassFile;
 import static com.android.tools.r8.utils.FileUtils.isDexFile;
-import static com.android.tools.r8.utils.FileUtils.isVDexFile;
 
 import com.android.tools.r8.ArchiveClassFileProvider;
 import com.android.tools.r8.ClassFileResourceProvider;
 import com.android.tools.r8.Resource;
-import com.android.tools.r8.dex.VDexFile;
-import com.android.tools.r8.dex.VDexFileReader;
 import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.origin.Origin;
@@ -162,12 +159,6 @@
   /** Get input streams for all dex program resources. */
   public List<Resource> getDexProgramResources() throws IOException {
     List<Resource> dexResources = filter(programResources, Kind.DEX);
-    for (Resource resource : filter(programResources, Kind.VDEX)) {
-      VDexFileReader reader = new VDexFileReader(new VDexFile(resource));
-      dexResources.addAll(reader.getDexFiles().stream()
-          .map(bytes -> Resource.fromBytes(resource.origin, bytes))
-          .collect(Collectors.toList()));
-    }
     for (ProgramFileArchiveReader reader : programFileArchiveReaders) {
       dexResources.addAll(reader.getDexProgramResources());
     }
@@ -712,15 +703,6 @@
       return this;
     }
 
-    public Builder setVdexAllowed() {
-      vdexAllowed = true;
-      return this;
-    }
-
-    public boolean isVdexAllowed() {
-      return vdexAllowed;
-    }
-
     /**
      * Build final AndroidApp.
      */
@@ -746,8 +728,6 @@
       }
       if (isDexFile(file)) {
         addProgramResources(Kind.DEX, Resource.fromFile(file));
-      } else if (isVDexFile(file) && isVdexAllowed()) {
-        addProgramResources(Kind.VDEX, Resource.fromFile(file));
       } else if (isClassFile(file)) {
         addProgramResources(Kind.CLASS, Resource.fromFile(file));
       } else if (isArchive(file)) {
diff --git a/src/main/java/com/android/tools/r8/utils/IOExceptionDiagnostic.java b/src/main/java/com/android/tools/r8/utils/IOExceptionDiagnostic.java
index 8856f26..3ebb621 100644
--- a/src/main/java/com/android/tools/r8/utils/IOExceptionDiagnostic.java
+++ b/src/main/java/com/android/tools/r8/utils/IOExceptionDiagnostic.java
@@ -6,6 +6,7 @@
 
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.origin.PathOrigin;
+import com.android.tools.r8.position.Position;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.nio.file.FileAlreadyExistsException;
@@ -60,6 +61,11 @@
   }
 
   @Override
+  public Position getPosition() {
+    return Position.UNKNOWN;
+  }
+
+  @Override
   public String getDiagnosticMessage() {
     return message;
   }
diff --git a/src/main/java/com/android/tools/r8/utils/ProgramResource.java b/src/main/java/com/android/tools/r8/utils/ProgramResource.java
index 0cbf11e..034fb6a 100644
--- a/src/main/java/com/android/tools/r8/utils/ProgramResource.java
+++ b/src/main/java/com/android/tools/r8/utils/ProgramResource.java
@@ -12,7 +12,6 @@
   public enum Kind {
     DEX,
     CLASS,
-    VDEX
   }
 
   public final Kind kind;
diff --git a/src/main/java/com/android/tools/r8/utils/StringDiagnostic.java b/src/main/java/com/android/tools/r8/utils/StringDiagnostic.java
index cd5bbcd..b7cd855 100644
--- a/src/main/java/com/android/tools/r8/utils/StringDiagnostic.java
+++ b/src/main/java/com/android/tools/r8/utils/StringDiagnostic.java
@@ -5,10 +5,12 @@
 
 import com.android.tools.r8.Diagnostic;
 import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.position.Position;
 
 public class StringDiagnostic implements Diagnostic {
 
   private final Origin origin;
+  private final Position position;
   private final String message;
 
   public StringDiagnostic(String message) {
@@ -16,7 +18,12 @@
   }
 
   public StringDiagnostic(String message, Origin origin) {
+    this(message, origin, Position.UNKNOWN);
+  }
+
+  public StringDiagnostic(String message, Origin origin, Position position) {
     this.origin = origin;
+    this.position = position;
     this.message = message;
   }
 
@@ -26,6 +33,11 @@
   }
 
   @Override
+  public Position getPosition() {
+    return position;
+  }
+
+  @Override
   public String getDiagnosticMessage() {
     return message;
   }
diff --git a/src/test/apiUsageSample/com/android/tools/apiusagesample/D8DiagnosticsHandler.java b/src/test/apiUsageSample/com/android/tools/apiusagesample/D8DiagnosticsHandler.java
index 3dca445..d9f11b0 100644
--- a/src/test/apiUsageSample/com/android/tools/apiusagesample/D8DiagnosticsHandler.java
+++ b/src/test/apiUsageSample/com/android/tools/apiusagesample/D8DiagnosticsHandler.java
@@ -9,7 +9,9 @@
 import com.android.tools.r8.origin.ArchiveEntryOrigin;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.origin.PathOrigin;
-import com.android.tools.r8.origin.TextRangeOrigin;
+import com.android.tools.r8.position.Position;
+import com.android.tools.r8.position.TextPosition;
+import com.android.tools.r8.position.TextRange;
 import java.nio.file.Files;
 import java.nio.file.Path;
 
@@ -45,14 +47,21 @@
     String textMessage = diagnostic.getDiagnosticMessage();
 
     Origin origin = diagnostic.getOrigin();
+    Position positionInOrigin = diagnostic.getPosition();
     String position;
-    if (origin instanceof TextRangeOrigin && origin.parent() instanceof PathOrigin) {
-      TextRangeOrigin textRange = (TextRangeOrigin) origin;
-      position = ((PathOrigin) origin.parent()).getPath().toFile() + ": "
-          + textRange.getStart().getLine() + "," + textRange.getStart().getColumn()
-          + " - " + textRange.getEnd().getLine() + "," + textRange.getEnd().getColumn();
-    } else if (origin.parent() instanceof PathOrigin) {
-      position = ((PathOrigin) origin.parent()).getPath().toFile().toString();
+    if (origin instanceof PathOrigin) {
+      if (positionInOrigin instanceof TextRange) {
+        TextRange textRange = (TextRange) positionInOrigin;
+        position = ((PathOrigin) origin.parent()).getPath().toFile() + ": "
+            + textRange.getStart().getLine() + "," + textRange.getStart().getColumn()
+            + " - " + textRange.getEnd().getLine() + "," + textRange.getEnd().getColumn();
+      } else if (positionInOrigin instanceof TextPosition) {
+        TextPosition textPosition = (TextPosition) positionInOrigin;
+        position = ((PathOrigin) origin.parent()).getPath().toFile() + ": "
+            + textPosition.getLine() + "," + textPosition.getColumn();
+      } else {
+        position = ((PathOrigin) origin.parent()).getPath().toFile().toString();
+      }
     } else {
       position = "UNKNOWN";
       if (origin != Origin.unknown()) {
diff --git a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
index 7f39d8e..65d1009 100644
--- a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
@@ -14,13 +14,14 @@
 import com.android.tools.r8.Diagnostic;
 import com.android.tools.r8.DiagnosticsHandler;
 import com.android.tools.r8.TestBase;
-import com.android.tools.r8.origin.TextRangeOrigin;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.graph.ClassAccessFlags;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.FieldAccessFlags;
 import com.android.tools.r8.graph.MethodAccessFlags;
 import com.android.tools.r8.origin.PathOrigin;
+import com.android.tools.r8.position.TextPosition;
+import com.android.tools.r8.position.TextRange;
 import com.android.tools.r8.utils.AbortException;
 import com.android.tools.r8.utils.FileUtils;
 import com.android.tools.r8.utils.InternalOptions.PackageObfuscationMode;
@@ -980,9 +981,15 @@
       int columnStart, String... messageParts) {
     assertEquals(1, diagnostics.size());
     Diagnostic diagnostic = diagnostics.get(0);
-    assertEquals(path, ((PathOrigin) diagnostic.getOrigin().parent()).getPath());
-    assertEquals(new TextRangeOrigin.TextPosition(lineStart, columnStart),
-        ((TextRangeOrigin) diagnostic.getOrigin()).getStart());
+    assertEquals(path, ((PathOrigin) diagnostic.getOrigin()).getPath());
+    TextPosition position;
+    if (diagnostic.getPosition() instanceof TextRange) {
+      position = ((TextRange) diagnostic.getPosition()).getStart();
+    } else {
+      position = ((TextPosition) diagnostic.getPosition());
+    }
+    assertEquals(lineStart, position.getLine());
+    assertEquals(columnStart, position.getColumn());
     for (String part:messageParts) {
       assertTrue(diagnostic.getDiagnosticMessage()+ "doesn't contain \"" + part + "\"",
           diagnostic.getDiagnosticMessage().contains(part));
diff --git a/tests/api_usage_sample.jar b/tests/api_usage_sample.jar
index 69af652..59eb757 100644
--- a/tests/api_usage_sample.jar
+++ b/tests/api_usage_sample.jar
Binary files differ