class InstantRunDex extends Transform {

    @Override
    public void transform(@NonNull TransformInvocation invocation)
            throws IOException, TransformException, InterruptedException {

        File outputFolder = InstantRunBuildType.RELOAD.getOutputFolder(variantScope);

        boolean changesAreCompatible =
                variantScope.getInstantRunBuildContext().hasPassedVerification();
        boolean restartDexRequested =
                variantScope.getGlobalScope().isActive(OptionalCompilationStep.RESTART_ONLY);

        if (!changesAreCompatible || restartDexRequested) {
            FileUtils.cleanOutputDir(outputFolder);
            return;
        }

        // create a tmp jar file.
        File classesJar = new File(outputFolder, "classes.jar");
        if (classesJar.exists()) {
            FileUtils.delete(classesJar);
        }
        Files.createParentDirs(classesJar);
        final JarClassesBuilder jarClassesBuilder = getJarClassBuilder(classesJar);

        try {
            for (TransformInput input : invocation.getReferencedInputs()) {
                for (DirectoryInput directoryInput : input.getDirectoryInputs()) {
                    Set<QualifiedContent.ContentType> types = directoryInput.getContentTypes();
                    // we want to process only CLASSES_ENHANCED
                    if (types.size() != 1
                            || !types.contains(ExtendedContentType.CLASSES_ENHANCED)) {
                        continue;
                    }
                    final File folder = directoryInput.getFile();
                    if (invocation.isIncremental()) {
                        for (Map.Entry<File, Status> entry :
                                directoryInput.getChangedFiles().entrySet()) {
                            if (entry.getValue() != Status.REMOVED) {
                                File file = entry.getKey();
                                if (file.isFile()) {
                                    jarClassesBuilder.add(folder, file);
                                }
                            }
                        }
                    } else {
                        Iterable<File> files = FileUtils.getAllFiles(folder);
                        for (File inputFile : files) {
                            jarClassesBuilder.add(folder, inputFile);
                        }
                    }
                }
            }
        } finally {
            jarClassesBuilder.close();
        }

        // if no files were added, clean up and return.
        if (jarClassesBuilder.isEmpty()) {
            FileUtils.cleanOutputDir(outputFolder);
            return;
        }

        try {
            variantScope
                    .getInstantRunBuildContext()
                    .startRecording(InstantRunBuildContext.TaskType.INSTANT_RUN_DEX);
            List<Path> classpath = getClasspath(invocation);
            convertByteCode(classesJar, classpath, outputFolder);
            variantScope
                    .getInstantRunBuildContext()
                    .addChangedFile(FileType.RELOAD_DEX, new File(outputFolder, "classes.dex"));
        } finally {
            variantScope
                    .getInstantRunBuildContext()
                    .stopRecording(InstantRunBuildContext.TaskType.INSTANT_RUN_DEX);
        }
    }

    public  InstantRunDex(
            @NonNull InstantRunVariantScope transformVariantScope,
            int minSdkForDx,
            boolean enableDesugaring,
            @NonNull FileCollection bootClasspath,
            @NonNull MessageReceiver messageReceiver);

}