/*
 * Copyright 2010-2021 The jdependency developers.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.vafer.jdependency.asm;

import java.util.HashSet;
import java.util.Set;
import java.io.File;

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.TypePath;
import org.objectweb.asm.commons.ClassRemapper;
import org.objectweb.asm.commons.Remapper;

/**
 * interal - do not use
 */

public final class DependenciesClassAdapter extends ClassRemapper {

    private static final EmptyVisitor ev = new EmptyVisitor();

    public DependenciesClassAdapter() {
        super(ev, new CollectingRemapper());
    }

    public Set<String> getDependencies() {
        return ((CollectingRemapper) super.remapper).classes;
    }

    private static class CollectingRemapper extends Remapper {

        final Set<String> classes = new HashSet<String>();

        public String map(String pClassName) {
            classes.add(pClassName.replace('/', '.'));
            return pClassName;
        }
    }

    static class EmptyVisitor extends ClassVisitor {

        private static final AnnotationVisitor av = new AnnotationVisitor(Opcodes.ASM7) {
            @Override
            public AnnotationVisitor visitAnnotation(String name, String desc) {
                return this;
            }

            @Override
            public AnnotationVisitor visitArray(String name) {
                return this;
            }
        };

        private static final MethodVisitor mv = new MethodVisitor( Opcodes.ASM6) {
            @Override
            public AnnotationVisitor visitAnnotationDefault() {
                return av;
            }

            @Override
            public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
                return av;
            }

            @Override
            public AnnotationVisitor visitParameterAnnotation(
                int parameter, String desc, boolean visible) {
                return av;
            }

            @Override
            public AnnotationVisitor visitInsnAnnotation( int typeRef, TypePath typePath, String descriptor,
                                                          boolean visible ) {
                return av;
            }

            @Override
            public AnnotationVisitor visitLocalVariableAnnotation( int typeRef, TypePath typePath, Label[] start,
                                                                   Label[] end, int[] index, String descriptor,
                                                                   boolean visible ) {
                return av;
            }

            @Override
            public AnnotationVisitor visitTryCatchAnnotation( int typeRef, TypePath typePath, String descriptor,
                                                              boolean visible ) {
                return av;
            }

            @Override
            public AnnotationVisitor visitTypeAnnotation( int typeRef, TypePath typePath, String descriptor,
                                                          boolean visible ) {
                return av;
            }
        };

        private static final FieldVisitor fieldVisitor = new FieldVisitor( Opcodes.ASM7 ) {
            @Override
            public AnnotationVisitor visitAnnotation( String desc, boolean visible ) {
                return av;
            }
            @Override
            public AnnotationVisitor visitTypeAnnotation( int typeRef, TypePath typePath, String descriptor,
                                                          boolean visible ) {
                return av;
            }
        };

        public EmptyVisitor() {
            super(Opcodes.ASM7);
        }

        @Override
        public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
            return av;
        }

        @Override
        public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
            return fieldVisitor;
        }

        @Override
        public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
            return mv;
        }

        @Override
        public AnnotationVisitor visitTypeAnnotation( int typeRef, TypePath typePath, String descriptor,
                                                      boolean visible ) {
            return av;
        }
    }
}

@@ -697,29 +697,8 @@
 Set;
-%0Aimport java.io.File;
 %0A%0Aim
@@ -914,23 +914,112 @@
 web.asm.
-Opcodes
+ModuleVisitor;%0Aimport org.objectweb.asm.Opcodes;%0Aimport org.objectweb.asm.RecordComponentVisitor
 ;%0Aimport
@@ -1151,16 +1151,17 @@
  * inter
+n
 al - do 
@@ -1238,24 +1238,78 @@
 Remapper %7B%0A%0A
+    private static final int OPCODES = Opcodes.ASM9;%0A%0A
     private 
@@ -1967,27 +1967,22 @@
 isitor(O
-pcodes.ASM7
+PCODES
 ) %7B%0A    
@@ -2334,21 +2334,15 @@
 tor(
- Opcodes.ASM6
+OPCODES
 ) %7B%0A
@@ -4035,22 +4035,15 @@
 tor(
- Opcodes.ASM7 
+OPCODES
 ) %7B%0A
@@ -4467,27 +4467,203 @@
    p
-ublic Empty
+rivate static final ModuleVisitor moduleVisitor = new ModuleVisitor(OPCODES) %7B%0A        %7D;%0A%0A        private static final RecordComponentVisitor recordComponentVisitor = new RecordComponent
 Visitor(
 ) %7B%0A
@@ -4658,16 +4658,23 @@
 Visitor(
+OPCODES
 ) %7B%0A    
@@ -4685,26 +4685,410 @@
     
-super(Opcodes.ASM7
+@Override%0A            public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) %7B%0A                return av;%0A            %7D%0A%0A            @Override%0A            public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) %7B%0A                return av;%0A            %7D%0A        %7D;%0A%0A        public EmptyVisitor() %7B%0A            super(OPCODES
 );%0A 
@@ -5800,21 +5800,351 @@
 v;%0A        %7D
+%0A%0A        @Override%0A        public ModuleVisitor visitModule(String name, int access, String version) %7B%0A            return moduleVisitor;%0A        %7D%0A%0A        @Override%0A        public RecordComponentVisitor visitRecordComponent(String name, String descriptor, String signature) %7B%0A            return recordComponentVisitor;%0A        %7D
 %0A    %7D%0A%7D%0A

Use ASM9 Opcodes, add missing non-void overrides