djUnitをJava15、eclipse2021-03で使用する

#概要
@umed0025さんの[eclipse4.5(mars)以降でdjunitプラグインを使う方法](https://qiita.com/umed0025/items/85709ca887593548a75c "eclipse4.5(mars)以降でdjunitプラグインを使う方法")と似た内容ですがこちらはJava15、Eclipse2021-03でdjUnitを使う方法です。

#動作環境
・Ubuntu 20.04.1 LTS
・Eclipse IDE 2021-03 R Packages for Enterprise Java and Web Developers Linux x86_64（日本語化せず）
・Java15（Eclipse 2021-03に内蔵）
・djunit 0.8.6

#手順
1. Create a ProjectでPlug-in Projectを選び枠組みを作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132879/5d46928c-e843-2cdd-a835-ce52a453490e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132879/5b43f870-09f8-9879-fe17-24b11bad3c7f.png)
2. djUnitのサイトからjp.co.dgic.eclipse.jdt.djunit_3.5.x_0.8.6.zipをダウンロードし、解凍して図で選択されているファイルを自分のプロジェクトにコピーします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132879/b9f9c823-f75a-8b51-77e8-81753a6926f9.png)
3. zipに含まれているdjunit-src.zipからcomとjpフォルダを自分のプロジェクトのsrcフォルダにコピーします。そして以下のファイル以外削除します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132879/c584ee19-bfc8-cefb-7335-b89bc25381d3.png)
4. Java15で動作させるのに必要なasm-9.1.jarファイルを[ここ](https://repo1.maven.org/maven2/org/ow2/asm/asm/9.1/asm-9.1.jar)からダウンロードし、libフォルダに格納します。
5. META-INF/MANIFEST.MFを開きOverviewタブの以下の値を書き換えます。

|設定箇所|値|
|:--|:--|
|ID|jp.co.dgic.eclipse.jdt.djunit|
|Version|0.8.6|
|Name|%pluginName|
|Activator|jp.co.dgic.eclipse.jdt.internal.junit.ui.DJUnitPlugin|
|Activate this plug-in when one of its classes is loaded|オン|
|This plug-in is a singleton|オン|
見た目は以下のとおりです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132879/9e1ba780-0d0b-052e-a9e7-d6ae2bf50eab.png)

6. プロパティファイルの配置を変更します。
・プロジェクト直下にOSGI-INF/l10nフォルダを作成
・plugin.propertiesとplugin_ja.propertiesを上記のフォルダに移動
・MANIFEST.MFに「Bundle-Localization: OSGI-INF/l10n/plugin」を追記
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132879/56763e4d-39e3-65ac-7786-167754ac6d91.png)

7. Dependenciesタブを設定します。
・plugin.xmlの\<requires>~\</requires>に記述されている依存プラグインを追加します。※検索しても出てこないものは無視してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132879/b93bd250-2748-ced3-9b3c-3d6e1df951ba.png)
8. Runtimeタブを設定します。
Classpathにlib/jcoverage-djunit-1.0.5.jar、lib/jakarta-oro-2.0.7.jar、lib/asm-9.1.jar、djunit.jarを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132879/d1f4c1a6-2b7a-71d7-7e03-b6eedb262ea0.png)

9. Buildタブを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132879/5310951f-da04-0259-d85f-092013c3402b.png)
10. 古いasmにあってasm-9.1.jarに存在しないクラスを自前で追加します。
パケージ：org.objectweb.asm
クラス：ClassAdapter、MethodAdapter

```java:ClassAdapter.java
/***
 * ASM: a very small and fast Java bytecode manipulation framework
 * Copyright (c) 2000-2007 INRIA, France Telecom
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the copyright holders nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.objectweb.asm;

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;

/**
 * An empty {@link ClassVisitor} that delegates to another {@link ClassVisitor}.
 * This class can be used as a super class to quickly implement usefull class
 * adapter classes, just by overriding the necessary methods.
 * 
 * @author Eric Bruneton
 */
public class ClassAdapter extends ClassVisitor {

    /**
     * Constructs a new {@link ClassAdapter} object.
     * 
     * @param cv the class visitor to which this adapter must delegate calls.
     */
    public ClassAdapter(final int api, final ClassVisitor cv) {
    	super(api, cv);
    }

    public void visit(
        final int version,
        final int access,
        final String name,
        final String signature,
        final String superName,
        final String[] interfaces)
    {
        cv.visit(version, access, name, signature, superName, interfaces);
    }

    public void visitSource(final String source, final String debug) {
        cv.visitSource(source, debug);
    }

    public void visitOuterClass(
        final String owner,
        final String name,
        final String desc)
    {
        cv.visitOuterClass(owner, name, desc);
    }

    public AnnotationVisitor visitAnnotation(
        final String desc,
        final boolean visible)
    {
        return cv.visitAnnotation(desc, visible);
    }

    public void visitAttribute(final Attribute attr) {
        cv.visitAttribute(attr);
    }

    public void visitInnerClass(
        final String name,
        final String outerName,
        final String innerName,
        final int access)
    {
        cv.visitInnerClass(name, outerName, innerName, access);
    }

    public FieldVisitor visitField(
        final int access,
        final String name,
        final String desc,
        final String signature,
        final Object value)
    {
        return cv.visitField(access, name, desc, signature, value);
    }

    public MethodVisitor visitMethod(
        final int access,
        final String name,
        final String desc,
        final String signature,
        final String[] exceptions)
    {
        return cv.visitMethod(access, name, desc, signature, exceptions);
    }

    public void visitEnd() {
        cv.visitEnd();
    }
}
```

```java:MethodAdapter.java
/***
 * ASM: a very small and fast Java bytecode manipulation framework
 * Copyright (c) 2000-2007 INRIA, France Telecom
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the copyright holders nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.objectweb.asm;

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;

/**
 * An empty {@link MethodVisitor} that delegates to another
 * {@link MethodVisitor}. This class can be used as a super class to quickly
 * implement usefull method adapter classes, just by overriding the necessary
 * methods.
 * 
 * @author Eric Bruneton
 */
public class MethodAdapter extends MethodVisitor {

	/**
	 * Constructs a new {@link MethodAdapter} object.
	 * 
	 * @param mv the code visitor to which this adapter must delegate calls.
	 */
	public MethodAdapter(final int api, final MethodVisitor mv) {
		super(api, mv);
	}

	public AnnotationVisitor visitAnnotationDefault() {
		return mv.visitAnnotationDefault();
	}

	public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
		return mv.visitAnnotation(desc, visible);
	}

	public AnnotationVisitor visitParameterAnnotation(final int parameter, final String desc, final boolean visible) {
		return mv.visitParameterAnnotation(parameter, desc, visible);
	}

	public void visitAttribute(final Attribute attr) {
		mv.visitAttribute(attr);
	}

	public void visitCode() {
		mv.visitCode();
	}

	public void visitFrame(final int type, final int nLocal, final Object[] local, final int nStack,
			final Object[] stack) {
		mv.visitFrame(type, nLocal, local, nStack, stack);
	}

	public void visitInsn(final int opcode) {
		mv.visitInsn(opcode);
	}

	public void visitIntInsn(final int opcode, final int operand) {
		mv.visitIntInsn(opcode, operand);
	}

	public void visitVarInsn(final int opcode, final int var) {
		mv.visitVarInsn(opcode, var);
	}

	public void visitTypeInsn(final int opcode, final String type) {
		mv.visitTypeInsn(opcode, type);
	}

	public void visitFieldInsn(final int opcode, final String owner, final String name, final String desc) {
		mv.visitFieldInsn(opcode, owner, name, desc);
	}

	public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) {
		mv.visitMethodInsn(opcode, owner, name, desc);
	}

	public void visitJumpInsn(final int opcode, final Label label) {
		mv.visitJumpInsn(opcode, label);
	}

	public void visitLabel(final Label label) {
		mv.visitLabel(label);
	}

	public void visitLdcInsn(final Object cst) {
		mv.visitLdcInsn(cst);
	}

	public void visitIincInsn(final int var, final int increment) {
		mv.visitIincInsn(var, increment);
	}

	public void visitTableSwitchInsn(final int min, final int max, final Label dflt, final Label[] labels) {
		mv.visitTableSwitchInsn(min, max, dflt, labels);
	}

	public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) {
		mv.visitLookupSwitchInsn(dflt, keys, labels);
	}

	public void visitMultiANewArrayInsn(final String desc, final int dims) {
		mv.visitMultiANewArrayInsn(desc, dims);
	}

	public void visitTryCatchBlock(final Label start, final Label end, final Label handler, final String type) {
		mv.visitTryCatchBlock(start, end, handler, type);
	}

	public void visitLocalVariable(final String name, final String desc, final String signature, final Label start,
			final Label end, final int index) {
		mv.visitLocalVariable(name, desc, signature, start, end, index);
	}

	public void visitLineNumber(final int line, final Label start) {
		mv.visitLineNumber(line, start);
	}

	public void visitMaxs(final int maxStack, final int maxLocals) {
		mv.visitMaxs(maxStack, maxLocals);
	}

	public void visitEnd() {
		mv.visitEnd();
	}
}
```

11. 新しいasm用に必要となるクラスを追加します。
パケージ：jp.co.dgic.testing.common.virtualmock.asm
クラス：AsmEmptyClassVisitor、AsmEmptyMethodVisitor

```java:AsmEmptyClassVisitor.java
package jp.co.dgic.testing.common.virtualmock.asm;

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.ModuleVisitor;
import org.objectweb.asm.RecordComponentVisitor;
import org.objectweb.asm.TypePath;

public class AsmEmptyClassVisitor extends ClassVisitor {

	public AsmEmptyClassVisitor(int api) {
		super(api);
	}

	@Override
	public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
	}

	@Override
	public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
		return null;
	}

	@Override
	public void visitAttribute(Attribute attribute) {
	}

	@Override
	public void visitEnd() {
	}

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

	@Override
	public void visitInnerClass(String name, String outerName, String innerName, int access) {
	}

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

	@Override
	public ModuleVisitor visitModule(String name, int access, String version) {
		return null;
	}

	@Override
	public void visitNestHost(String nestHost) {
	}

	@Override
	public void visitNestMember(String nestMember) {
	}

	@Override
	public void visitOuterClass(String owner, String name, String descriptor) {
	}

	@Override
	public void visitPermittedSubclass(String permittedSubclass) {
	}

	@Override
	public RecordComponentVisitor visitRecordComponent(String name, String descriptor, String signature) {
		return null;
	}

	@Override
	public void visitSource(String source, String debug) {
	}

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

```java:AsmEmptyMethodVisitor.java
package jp.co.dgic.testing.common.virtualmock.asm;

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;

public class AsmEmptyMethodVisitor extends MethodAdapter {
	public AsmEmptyMethodVisitor(int api) {
		this(api, null);
	}

	public AsmEmptyMethodVisitor(int api, MethodVisitor mv) {
		super(api, mv);
	}

	@Override
	public AnnotationVisitor visitAnnotationDefault() {
		return null;
	}

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

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

	@Override
	public void visitAttribute(Attribute attr) {
	}

	@Override
	public void visitCode() {
	}

	@Override
	public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
	}

	@Override
	public void visitInsn(int opcode) {
	}

	@Override
	public void visitIntInsn(int opcode, int operand) {
	}

	@Override
	public void visitVarInsn(int opcode, int var) {
	}

	@Override
	public void visitTypeInsn(int opcode, String type) {
	}

	@Override
	public void visitFieldInsn(int opcode, String owner, String name, String desc) {
	}

	@Override
	public void visitMethodInsn(int opcode, String owner, String name, String desc) {
	}

	@Override
	public void visitJumpInsn(int opcode, Label label) {
	}

	@Override
	public void visitLabel(Label label) {
	}

	@Override
	public void visitLdcInsn(Object cst) {
	}

	@Override
	public void visitIincInsn(int var, int increment) {
	}

	@Override
	public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) {
	}

	@Override
	public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
	}

	@Override
	public void visitMultiANewArrayInsn(String desc, int dims) {
	}

	@Override
	public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
	}

	@Override
	public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
	}

	@Override
	public void visitLineNumber(int line, Label start) {
	}

	@Override
	public void visitMaxs(int maxStack, int maxLocals) {
	}

	@Override
	public void visitEnd() {
	}
}
```

パケージ：jp.co.dgic.testing.common.asm9x
クラス：AsmClassReader9x、AsmClassWriter9x

```java:AsmClassReader9x.java
package jp.co.dgic.testing.common.asm9x;

import java.io.IOException;
import jp.co.dgic.testing.common.asm.AsmClassReader;
import org.objectweb.asm.ClassVisitor;

public class AsmClassReader9x extends AsmClassReader {

	private static final int SKIP_FRAMES = 4;

	public AsmClassReader9x(String name) throws IOException {
		super(name);
	}

	public AsmClassReader9x(byte[] bytecodes) {
		super(bytecodes);
	}

	public void accept(ClassVisitor cv) {
		super.accept(cv, SKIP_FRAMES);
	}
}
```

```java:AsmClassWriter9x.java
package jp.co.dgic.testing.common.asm9x;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;

public class AsmClassWriter9x extends ClassVisitor {
	protected ClassWriter cw;

	public AsmClassWriter9x() {
		super(Opcodes.ASM9);
		this.cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
	}
	
	public ClassWriter getClassWriter() {
		return this.cw;
	}
}
```

パケージ：jp.co.dgic.testing.common.virtualmock.asm9x
クラス：AsmClassVisitor9x

```java:AsmClassVisitor9x.java
/**
 * Copyright (C)2004 dGIC Corporation.
 *
 * This file is part of djUnit plugin.
 *
 * djUnit plugin is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published
 * by the Free Software Foundation; either version 2 of the License,
 * or (at your option) any later version.
 *
 * djUnit plugin is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with djUnit plugin; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 *
 */
package jp.co.dgic.testing.common.virtualmock.asm9x;

import jp.co.dgic.testing.common.asm9x.AsmClassWriter9x;
import jp.co.dgic.testing.common.virtualmock.InternalMockObjectManager;
import jp.co.dgic.testing.common.virtualmock.asm.AsmClassChecker;
import jp.co.dgic.testing.common.virtualmock.asm.AsmConstractorVisitor;
import jp.co.dgic.testing.common.virtualmock.asm.AsmMethodVisitor;

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.ModuleVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.RecordComponentVisitor;
import org.objectweb.asm.TypePath;

public class AsmClassVisitor9x extends AsmClassWriter9x {

	protected AsmClassChecker acc;
	protected String className;

	public AsmClassVisitor9x(AsmClassChecker acc) {
		this.acc = acc;
	}

	public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
		InternalMockObjectManager.printConsole("[modify class] " + name + " " + signature);
		InternalMockObjectManager.printConsole("[class version] " + version);
		this.className = name.replace('/', '.');
		cw.visit(version, access, name, signature, superName, interfaces);
	}

	public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {

		boolean isStatic = false;
		if ((access & Opcodes.ACC_STATIC) > 0) {
			isStatic = true;
		}

		InternalMockObjectManager.printConsole("#################################################################");
		InternalMockObjectManager.printConsole("#################################################################");
		InternalMockObjectManager.printConsole("### " + access + (isStatic ? " static " : " ") + name + " " + signature);
		InternalMockObjectManager.printConsole("#################################################################");
		InternalMockObjectManager.printConsole("#################################################################");

		MethodVisitor mv = cw.visitMethod(access, name, desc, signature, exceptions);

		// is abstract or native
		if ((access & Opcodes.ACC_ABSTRACT) > 0) return mv;
		if ((access & Opcodes.ACC_NATIVE) > 0) return mv;
		if ((access & Opcodes.ACC_BRIDGE) > 0) return mv;

		int maxLocals = acc.getMaxLocals(name, desc);

		return createMethodVisitor(mv, name, desc, signature, isStatic, exceptions, maxLocals);
	}

	protected MethodVisitor createMethodVisitor(MethodVisitor mv, String name, String desc, String signature, boolean isStatic, String[] exceptions, int maxLocals) {
		if ("<init>".equalsIgnoreCase(name)) return new AsmConstractorVisitor(mv, this.className, name, desc, signature, exceptions, maxLocals, acc.getSuperClassNames());
		return new AsmMethodVisitor(mv, this.className, name, desc, signature, isStatic, exceptions, maxLocals, acc.getSuperClassNames());
	}

	public ClassWriter getClassWriter() {
		return this.cw;
	}
	
	@Override
	public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
		return cw.visitAnnotation(descriptor, visible);
	}

	@Override
	public void visitAttribute(Attribute attribute) {
		cw.visitAttribute(attribute);
	}

	@Override
	public void visitEnd() {
		cw.visitEnd();
	}

	@Override
	public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
		return cw.visitField(access, name, descriptor, signature, value);
	}

	@Override
	public void visitInnerClass(String name, String outerName, String innerName, int access) {
		cw.visitInnerClass(name, outerName, innerName, access);
	}

	@Override
	public ModuleVisitor visitModule(String name, int access, String version) {
		return cw.visitModule(name, access, version);
	}

	@Override
	public void visitNestHost(String nestHost) {
		cw.visitNestHost(nestHost);
	}

	@Override
	public void visitNestMember(String nestMember) {
		cw.visitNestMember(nestMember);
	}

	@Override
	public void visitOuterClass(String owner, String name, String descriptor) {
		cw.visitOuterClass(owner, name, descriptor);
	}

	@Override
	public void visitPermittedSubclass(String permittedSubclass) {
		cw.visitPermittedSubclass(permittedSubclass);
	}

	@Override
	public RecordComponentVisitor visitRecordComponent(String name, String descriptor, String signature) {
		return cw.visitRecordComponent(name, descriptor, signature);
	}

	@Override
	public void visitSource(String source, String debug) {
		cw.visitSource(source, debug);
	}

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

}
```


12. ソースを修正します。

```java:AsmClassCoverageTargetLineCollector.java(8行目変更)
//import jp.co.dgic.testing.common.virtualmock.asm.AsmEmptyVisitor;
import jp.co.dgic.testing.common.virtualmock.asm.AsmEmptyClassVisitor;
```

```java:AsmClassCoverageTargetLineCollector.java(21~23行目変更)
	public AsmClassCoverageTargetLineCollector() {
		super(Opcodes.ASM9, new AsmEmptyClassVisitor(Opcodes.ASM9));
	}
```


```java:AsmClassInstrumenter.java(62~63行目変更)
	public AsmClassInstrumenter(ClassVisitor cv) {
		super(Opcodes.ASM9, cv);
```

```java:AsmMethodCoverageTargetLineCollector.java(3~6行目変更)
//import jp.co.dgic.testing.common.virtualmock.asm.AsmEmptyVisitor;
import jp.co.dgic.testing.common.virtualmock.asm.AsmEmptyMethodVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.Opcodes;
```

```java:AsmMethodCoverageTargetLineCollector.java(12~15行目変更)
	public AsmMethodCoverageTargetLineCollector(AsmClassCoverageTargetLineCollector classLineCollector) {
		super(Opcodes.ASM9, new AsmEmptyMethodVisitor(Opcodes.ASM9));
		this.classLineCollector = classLineCollector;
	}
```

```java:AsmMethodInstrumenter.java(47~49行目変更)
	public AsmMethodInstrumenter(MethodVisitor mv, String className, String name, String desc,
								InstrumentData instrumentData) {
		super(Opcodes.ASM9, mv);
```

```java:AsmCoverageInstrumenter.java(27行目追加)
import jp.co.dgic.testing.common.asm9x.AsmClassWriter9x;
```

```java:AsmCoverageInstrumenter.java(54行目変更)
//		ClassWriter cw = AsmClassReader.createClassWriter();
		ClassWriter cw = ((AsmClassWriter9x)AsmClassReader.createClassWriter()).getClassWriter();
```

```java:DJUnitLaunchConfiguration.java(171,211行目のエラーを修正)
			abort(
					"Invalid project specified."/*JUnitMessages.JUnitLaunchConfigurationDelegate_error_invalidproject*/,
					null,
					IJavaLaunchConfigurationConstants.ERR_NOT_A_JAVA_PROJECT); //$NON-NLS-1$
```

```java:DJUnitLaunchConfiguration.java(186行目変更)
		if (DJUnitUtil.BYTECODE_LIBRARY_ASM3.equals(asmType)) {
			asmLibURL = new URL(djunitURL, LIB_DIR + "asm-3.1.jar");
		} else if (DJUnitUtil.BYTECODE_LIBRARY_ASM2.equals(asmType)) {
			asmLibURL = new URL(djunitURL, LIB_DIR + "asm-2.2.1.jar");
		} else if (DJUnitUtil.BYTECODE_LIBRARY_ASM15.equals(asmType)) {
			asmLibURL = new URL(djunitURL, LIB_DIR + "asm-1.5.3.jar");
		} else {
			asmLibURL = new URL(djunitURL, LIB_DIR + "asm-9.1.jar");
		}
```

```java:DJUnitPlugin.java(33行目コメント化)
//import org.eclipse.core.runtime.IPluginDescriptor;	// 削除されたためコメント化
```

```java:DJUnitPlugin.java(88行目変更)
	public DJUnitPlugin(/*IPluginDescriptor desc*/) {	// IPluginDescriptorは削除されたのでコメント化
		super(/*desc*/);
```

```java:DJUnitProjectPropertyPage.java(95行目追加)
	private static final String BYTECODE_LIBRARY_TEXT_ASM90 = "ASM9.x";
```

```java:DJUnitProjectPropertyPage.java(108行目追加)
	private Button useAsm3;
```

```java:DJUnitProjectPropertyPage.java(257行目変更)
		useAsm = new Button(libGroup, SWT.RADIO);
		useAsm.setText(BYTECODE_LIBRARY_TEXT_ASM90);
		useAsm3 = new Button(libGroup, SWT.RADIO);
		useAsm3.setText(BYTECODE_LIBRARY_TEXT_ASM30);
		useAsm2 = new Button(libGroup, SWT.RADIO);
		useAsm2.setText(BYTECODE_LIBRARY_TEXT_ASM20);
		useAsm15 = new Button(libGroup, SWT.RADIO);
		useAsm15.setText(BYTECODE_LIBRARY_TEXT_ASM15);
```

```java:DJUnitProjectPropertyPage.java(269行目変更)
		if (DJUnitUtil.BYTECODE_LIBRARY_ASM3.equals(library)) {
			useAsm3.setSelection(true);
		} else if (DJUnitUtil.BYTECODE_LIBRARY_ASM2.equals(library)) {
			useAsm2.setSelection(true);
		} else if (DJUnitUtil.BYTECODE_LIBRARY_ASM15.equals(library)) {
			useAsm15.setSelection(true);
		} else {
			useAsm.setSelection(true);
		}
```

```java:DJUnitProjectPropertyPage.java(312行目変更)
			String library = DJUnitUtil.BYTECODE_LIBRARY_ASM;
			if (useAsm3.getSelection()) {
				library = DJUnitUtil.BYTECODE_LIBRARY_ASM3;
			} else if (useAsm2.getSelection()) {
				library = DJUnitUtil.BYTECODE_LIBRARY_ASM2;
			} else if (useAsm15.getSelection()) {
				library = DJUnitUtil.BYTECODE_LIBRARY_ASM15;
			}
```

```java:AsmClassReader.java(7行目追加)
import jp.co.dgic.testing.common.asm9x.AsmClassReader9x;
import jp.co.dgic.testing.common.asm9x.AsmClassWriter9x;
import jp.co.dgic.testing.common.virtualmock.asm9x.AsmClassVisitor9x;
```

```java:AsmClassReader.java(24行目変更)
//		return new AsmClassReader3x(name);
		if (DJUnitUtil.BYTECODE_LIBRARY_ASM3.equals(getAsmType())) {
			return new AsmClassReader3x(name);
		}
		return new AsmClassReader9x(name);
```

```java:AsmClassReader.java(31行目変更)
//		return new AsmClassReader3x(bytecodes);
		if (DJUnitUtil.BYTECODE_LIBRARY_ASM3.equals(getAsmType())) {
			return new AsmClassReader3x(bytecodes);
		}
		return new AsmClassReader9x(bytecodes);
```

```java:AsmClassReader.java(34~38行目変更)
	public static ClassVisitor createClassWriter() {
		if (DJUnitUtil.BYTECODE_LIBRARY_ASM2.equals(getAsmType())) {
			return new AsmClassWriter2x();
		}
//		return new AsmClassWriter3x();
		if (DJUnitUtil.BYTECODE_LIBRARY_ASM3.equals(getAsmType())) {
			return new AsmClassWriter3x();
		}
		return new AsmClassWriter9x();
```

```java:AsmClassReader.java(41~45行目変更)
	public static ClassVisitor createClassVisitor(AsmClassChecker acc) {
		if (DJUnitUtil.BYTECODE_LIBRARY_ASM2.equals(getAsmType())) {
			return new AsmClassVisitor2x(acc);
		}
//		return new AsmClassVisitor3x(acc);
		if (DJUnitUtil.BYTECODE_LIBRARY_ASM3.equals(getAsmType())) {
			return new AsmClassVisitor3x(acc);
		}
		return new AsmClassVisitor9x(acc);
```

```java:DJUnitUtil.java(42行目追加)
	public static final String BYTECODE_LIBRARY_ASM3 = "ASM3";
```

```java:AbstractAsmMethodVisitor.java(63行目変更)
//		super(methodVisitor);
		super(Opcodes.ASM9, methodVisitor);
```

```java:AbstractAsmMethodVisitor.java(462~463行目変更)
		for (int i = 0; i < argTypes.length; i++) {
			mv.visitInsn(DUP);	// add
			mv.visitVarInsn(ALOAD, _maxLocals);
```

```java:AsmAdviceImplementer.java(29行目追加)
import jp.co.dgic.testing.common.virtualmock.asm9x.AsmClassVisitor9x;
import org.objectweb.asm.ClassVisitor;
```

```java:AsmAdviceImplementer.java(48~50行目追加)
//		ClassWriter asv = AsmClassReader.createClassVisitor(acc);
		ClassVisitor asv = AsmClassReader.createClassVisitor(acc);
		cr.accept(asv);
//		return asv.toByteArray();
		return ((AsmClassVisitor9x)asv).getClassWriter().toByteArray();
```

```java:AsmClassChecker.java(62~64行目変更)
	private AsmClassChecker() {
		super(Opcodes.ASM9, new AsmEmptyClassVisitor(Opcodes.ASM9));
	}
```

```java:AsmMethodChecker.java(26行目追加)
import org.objectweb.asm.Opcodes;
```

```java:AsmMethodChecker.java(35~36行目変更)
	public AsmMethodChecker(AsmClassChecker acc, String name, String desc) {
		super(Opcodes.ASM9, new AsmEmptyMethodVisitor(Opcodes.ASM9));
```

```java:DJUnitClassLoader.java(23~25行目変更)
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.stream.Stream;
```

```java:DJUnitClassLoader.java(44行目変更)
	public DJUnitClassLoader(ClassLoader parent) {
//		super(((URLClassLoader) parent).getURLs(), parent.getParent());
		// java9以上ではjava.lang.ClassCastException: class jdk.internal.loader.ClassLoaders$AppClassLoader cannot be cast to class java.net.URLClassLoader (jdk.internal.loader.ClassLoaders$AppClassLoader and java.net.URLClassLoader are in module java.base of loader 'bootstrap')が発生するので書き換える
		super(Stream.of(System.getProperty("java.class.path",".").split(System.getProperty("path.separator"))).map(p -> {
			try {
				return new File(p).toURI().toURL();
			} catch (MalformedURLException e) {
				e.printStackTrace();
				return null;
			}
		}).toArray(URL[]::new), parent.getParent());

```

13. plugin作成
以上の作業が終わったらOverviewタブのExport Wizardを押下し、DesticationにDirectoryなど指定してjarを生成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132879/1d9c48d4-9743-cfb7-73f1-6bc7c477c634.png)

14. pluginインストール
生成したjarをEclipseのpluginsフォルダにコピーし、Eclipseを再起動します。
プロジェクトのPropertiesで図のようにdjUnitが表示されていればインストール成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132879/189835f2-62c6-8f0a-ac60-576a552869d9.png)


15. テスト実行
[AntでdjUnitタスクを実行する方法](https://qiita.com/tm777/items/7b1f94b99df312814af4 "AntでdjUnitタスクを実行する方法")に書いたテストを実行してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132879/0b14ee40-255b-294d-c608-908fd48ba4c5.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132879/66fefe90-7d6c-a3c0-e639-9512820b0f05.png)
うまくいったようです。
ソースはこちらhttps://github.com/tm000/mydjUnit