1e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov/*******************************************************************************
234cd880f4e52a32b9f88ed4ea687b8f3f892395bEvgeny Mandrikov * Copyright (c) 2009, 2017 Mountainminds GmbH & Co. KG and Contributors
3e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * All rights reserved. This program and the accompanying materials
4e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * are made available under the terms of the Eclipse Public License v1.0
5e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * which accompanies this distribution, and is available at
6e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * http://www.eclipse.org/legal/epl-v10.html
7e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov *
8e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * Contributors:
9e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov *    Marc R. Hoffmann - initial API and implementation
10e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov *
11e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov *******************************************************************************/
12e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovpackage org.jacoco.report;
13e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov
14e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovimport org.objectweb.asm.Type;
15e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov
16e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov/**
17e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * Names for the Java language.
18e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov */
19e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovpublic class JavaNames implements ILanguageNames {
20e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov
21e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov	public String getPackageName(final String vmname) {
22e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		if (vmname.length() == 0) {
23e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov			return "default";
24e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		}
25e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		return vmname.replace('/', '.');
26e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov	}
27e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov
28e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov	private String getClassName(final String vmname) {
29e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		final int pos = vmname.lastIndexOf('/');
30e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		final String name = pos == -1 ? vmname : vmname.substring(pos + 1);
31e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		return name.replace('$', '.');
32e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov	}
33e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov
34e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov	private boolean isAnonymous(final String vmname) {
35e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		final int dollarPosition = vmname.lastIndexOf('$');
36e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		if (dollarPosition == -1) {
37e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov			return false;
38e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		}
39e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		final int internalPosition = dollarPosition + 1;
40e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		if (internalPosition == vmname.length()) {
41e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov			// shouldn't happen for classes compiled from Java source
42e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov			return false;
43e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		}
44e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		// assume non-identifier start character for anonymous classes
45e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		final char start = vmname.charAt(internalPosition);
46e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		return !Character.isJavaIdentifierStart(start);
47e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov	}
48e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov
49e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov	public String getClassName(final String vmname, final String vmsignature,
50e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov			final String vmsuperclass, final String[] vminterfaces) {
51e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		if (isAnonymous(vmname)) {
52e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov			final String vmsupertype;
53e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov			if (vminterfaces != null && vminterfaces.length > 0) {
54e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov				vmsupertype = vminterfaces[0];
55e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov			} else if (vmsuperclass != null) {
56e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov				vmsupertype = vmsuperclass;
57e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov			} else {
58e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov				vmsupertype = null;
59e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov			}
60e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov			// append Eclipse style label, e.g. "Foo.new Bar() {...}"
61e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov			if (vmsupertype != null) {
62e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov				final StringBuilder builder = new StringBuilder();
63e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov				final String vmenclosing = vmname.substring(0,
64e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov						vmname.lastIndexOf('$'));
65e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov				builder.append(getClassName(vmenclosing)).append(".new ")
66e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov						.append(getClassName(vmsupertype)).append("() {...}");
67e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov				return builder.toString();
68e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov			}
69e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		}
70e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		return getClassName(vmname);
71e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov	}
72e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov
73e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov	public String getQualifiedClassName(final String vmname) {
74e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		return vmname.replace('/', '.').replace('$', '.');
75e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov	}
76e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov
77e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov	public String getMethodName(final String vmclassname,
78e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov			final String vmmethodname, final String vmdesc,
79e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov			final String vmsignature) {
8055fae171b754e20062fae7cdb2d5feae8ee54017Marc R. Hoffmann		return getMethodName(vmclassname, vmmethodname, vmdesc, false);
8155fae171b754e20062fae7cdb2d5feae8ee54017Marc R. Hoffmann	}
8255fae171b754e20062fae7cdb2d5feae8ee54017Marc R. Hoffmann
8355fae171b754e20062fae7cdb2d5feae8ee54017Marc R. Hoffmann	public String getQualifiedMethodName(final String vmclassname,
8455fae171b754e20062fae7cdb2d5feae8ee54017Marc R. Hoffmann			final String vmmethodname, final String vmdesc,
8555fae171b754e20062fae7cdb2d5feae8ee54017Marc R. Hoffmann			final String vmsignature) {
8655fae171b754e20062fae7cdb2d5feae8ee54017Marc R. Hoffmann		return getQualifiedClassName(vmclassname) + "."
8755fae171b754e20062fae7cdb2d5feae8ee54017Marc R. Hoffmann				+ getMethodName(vmclassname, vmmethodname, vmdesc, true);
8855fae171b754e20062fae7cdb2d5feae8ee54017Marc R. Hoffmann	}
8955fae171b754e20062fae7cdb2d5feae8ee54017Marc R. Hoffmann
9055fae171b754e20062fae7cdb2d5feae8ee54017Marc R. Hoffmann	private String getMethodName(final String vmclassname,
9155fae171b754e20062fae7cdb2d5feae8ee54017Marc R. Hoffmann			final String vmmethodname, final String vmdesc,
9255fae171b754e20062fae7cdb2d5feae8ee54017Marc R. Hoffmann			final boolean qualifiedParams) {
93e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		if ("<clinit>".equals(vmmethodname)) {
94e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov			return "static {...}";
95e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		}
96e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		final StringBuilder result = new StringBuilder();
97e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		if ("<init>".equals(vmmethodname)) {
98e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov			if (isAnonymous(vmclassname)) {
99e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov				return "{...}";
100e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov			} else {
101e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov				result.append(getClassName(vmclassname));
102e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov			}
103e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		} else {
104e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov			result.append(vmmethodname);
105e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		}
106e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		result.append('(');
107e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		final Type[] arguments = Type.getArgumentTypes(vmdesc);
108e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		boolean comma = false;
109e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		for (final Type arg : arguments) {
110e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov			if (comma) {
111e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov				result.append(", ");
112e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov			} else {
113e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov				comma = true;
114e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov			}
11555fae171b754e20062fae7cdb2d5feae8ee54017Marc R. Hoffmann			if (qualifiedParams) {
11655fae171b754e20062fae7cdb2d5feae8ee54017Marc R. Hoffmann				result.append(getQualifiedClassName(arg.getClassName()));
11755fae171b754e20062fae7cdb2d5feae8ee54017Marc R. Hoffmann			} else {
11855fae171b754e20062fae7cdb2d5feae8ee54017Marc R. Hoffmann				result.append(getShortTypeName(arg));
11955fae171b754e20062fae7cdb2d5feae8ee54017Marc R. Hoffmann			}
120e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		}
121e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		result.append(')');
122e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		return result.toString();
123e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov	}
124e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov
125e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov	private String getShortTypeName(final Type type) {
126e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		final String name = type.getClassName();
127e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		final int pos = name.lastIndexOf('.');
128e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		final String shortName = pos == -1 ? name : name.substring(pos + 1);
129e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov		return shortName.replace('$', '.');
130e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov	}
131e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov
132e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov}
133