blob: c98f2ec6b84eac3bc3c9189c3590063c64fd5d0c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
* $Id: TypeConverter.java 23404 2010-02-03 14:10:22Z stephan $
*
* Contributors:
* IBM Corporation - initial API and implementation
*
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.parser;
import java.util.ArrayList;
import java.util.Arrays;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
import org.eclipse.jdt.internal.compiler.ast.NameReference;
import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.Reference;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.objectteams.otdt.core.ICallinMapping;
import org.eclipse.objectteams.otdt.core.ICalloutMapping;
import org.eclipse.objectteams.otdt.core.ICalloutToFieldMapping;
import org.eclipse.objectteams.otdt.core.IFieldAccessSpec;
import org.eclipse.objectteams.otdt.core.IMethodMapping;
import org.eclipse.objectteams.otdt.core.IMethodSpec;
import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
import org.eclipse.objectteams.otdt.internal.core.CallinMapping;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.AbstractMethodMappingDeclaration;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CallinMappingDeclaration;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CalloutMappingDeclaration;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.FieldAccessSpec;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.MethodSpec;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.QualifiedBaseReference;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.TypeAnchorReference;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.TypeValueParameter;
public abstract class TypeConverter {
int namePos;
protected ProblemReporter problemReporter;
protected boolean has1_5Compliance;
private char memberTypeSeparator;
protected TypeConverter(ProblemReporter problemReporter, char memberTypeSeparator) {
this.problemReporter = problemReporter;
this.has1_5Compliance = problemReporter.options.originalComplianceLevel >= ClassFileConstants.JDK1_5;
this.memberTypeSeparator = memberTypeSeparator;
}
private void addIdentifiers(String typeSignature, int start, int endExclusive, int identCount, ArrayList fragments) {
if (identCount == 1) {
char[] identifier;
typeSignature.getChars(start, endExclusive, identifier = new char[endExclusive-start], 0);
fragments.add(identifier);
} else
fragments.add(extractIdentifiers(typeSignature, start, endExclusive-1, identCount));
}
/*
* Build an import reference from an import name, e.g. java.lang.*
*/
protected ImportReference createImportReference(
String[] importName,
int start,
int end,
boolean onDemand,
int modifiers) {
int length = importName.length;
long[] positions = new long[length];
long position = ((long) start << 32) + end;
char[][] qImportName = new char[length][];
for (int i = 0; i < length; i++) {
qImportName[i] = importName[i].toCharArray();
positions[i] = position; // dummy positions
}
return new ImportReference(
qImportName,
positions,
onDemand,
modifiers);
}
//{ObjectTeams: argument baseBounds added:
/* orig:
protected TypeParameter createTypeParameter(char[] typeParameterName, char[][] typeParameterBounds, int start, int end) {
:giro */
protected TypeParameter createTypeParameter(char[] typeParameterName, char[][] typeParameterBounds, boolean hasBaseBound, int start, int end) {
// SH}
TypeParameter parameter = new TypeParameter();
parameter.name = typeParameterName;
parameter.sourceStart = start;
parameter.sourceEnd = end;
if (typeParameterBounds != null) {
int length = typeParameterBounds.length;
if (length > 0) {
parameter.type = createTypeReference(typeParameterBounds[0], start, end);
//{ObjectTeams: base bound (only first bound)?
if (hasBaseBound)
parameter.type.bits |= ASTNode.IsRoleType;
// SH}
if (length > 1) {
parameter.bounds = new TypeReference[length-1];
for (int i = 1; i < length; i++) {
TypeReference bound = createTypeReference(typeParameterBounds[i], start, end);
bound.bits |= ASTNode.IsSuperType;
parameter.bounds[i-1] = bound;
}
}
}
}
return parameter;
}
//{ObjectTeams: value parameters:
protected TypeParameter createValueParameter(char[] parameterName, char[] parameterType, int start, int end)
{
TypeParameter parameter = new TypeValueParameter(parameterName, 0L); // set pos below
parameter.sourceStart = start;
parameter.sourceEnd = end;
parameter.declarationSourceStart = start;
parameter.declarationSourceEnd = end;
parameter.declarationEnd = end;
parameter.type = createTypeReference(parameterType, start, end);
return parameter;
}
// SH}
/*
* Build a type reference from a readable name, e.g. java.lang.Object[][]
*/
protected TypeReference createTypeReference(
char[] typeName,
int start,
int end,
boolean includeGenericsAnyway) {
int length = typeName.length;
this.namePos = 0;
return decodeType(typeName, length, start, end, true);
}
/*
* Build a type reference from a readable name, e.g. java.lang.Object[][]
*/
protected TypeReference createTypeReference(
char[] typeName,
int start,
int end) {
int length = typeName.length;
this.namePos = 0;
return decodeType(typeName, length, start, end, false);
}
/*
* Build a type reference from a type signature, e.g. Ljava.lang.Object;
*/
protected TypeReference createTypeReference(
String typeSignature,
int start,
int end) {
int length = typeSignature.length();
this.namePos = 0;
return decodeType(typeSignature, length, start, end);
}
private TypeReference decodeType(String typeSignature, int length, int start, int end) {
int identCount = 1;
int dim = 0;
int nameFragmentStart = this.namePos, nameFragmentEnd = -1;
boolean nameStarted = false;
ArrayList fragments = null;
//{ObjectTeams: consider @anchor:
boolean isAnchor = false;
// SH}
typeLoop: while (this.namePos < length) {
char currentChar = typeSignature.charAt(this.namePos);
switch (currentChar) {
case Signature.C_BOOLEAN :
if (!nameStarted) {
this.namePos++;
if (dim == 0)
return new SingleTypeReference(TypeBinding.BOOLEAN.simpleName, ((long) start << 32) + end);
else
return new ArrayTypeReference(TypeBinding.BOOLEAN.simpleName, dim, ((long) start << 32) + end);
}
break;
case Signature.C_BYTE :
if (!nameStarted) {
this.namePos++;
if (dim == 0)
return new SingleTypeReference(TypeBinding.BYTE.simpleName, ((long) start << 32) + end);
else
return new ArrayTypeReference(TypeBinding.BYTE.simpleName, dim, ((long) start << 32) + end);
}
break;
case Signature.C_CHAR :
if (!nameStarted) {
this.namePos++;
if (dim == 0)
return new SingleTypeReference(TypeBinding.CHAR.simpleName, ((long) start << 32) + end);
else
return new ArrayTypeReference(TypeBinding.CHAR.simpleName, dim, ((long) start << 32) + end);
}
break;
case Signature.C_DOUBLE :
if (!nameStarted) {
this.namePos++;
if (dim == 0)
return new SingleTypeReference(TypeBinding.DOUBLE.simpleName, ((long) start << 32) + end);
else
return new ArrayTypeReference(TypeBinding.DOUBLE.simpleName, dim, ((long) start << 32) + end);
}
break;
case Signature.C_FLOAT :
if (!nameStarted) {
this.namePos++;
if (dim == 0)
return new SingleTypeReference(TypeBinding.FLOAT.simpleName, ((long) start << 32) + end);
else
return new ArrayTypeReference(TypeBinding.FLOAT.simpleName, dim, ((long) start << 32) + end);
}
break;
case Signature.C_INT :
if (!nameStarted) {
this.namePos++;
if (dim == 0)
return new SingleTypeReference(TypeBinding.INT.simpleName, ((long) start << 32) + end);
else
return new ArrayTypeReference(TypeBinding.INT.simpleName, dim, ((long) start << 32) + end);
}
break;
case Signature.C_LONG :
if (!nameStarted) {
this.namePos++;
if (dim == 0)
return new SingleTypeReference(TypeBinding.LONG.simpleName, ((long) start << 32) + end);
else
return new ArrayTypeReference(TypeBinding.LONG.simpleName, dim, ((long) start << 32) + end);
}
break;
case Signature.C_SHORT :
if (!nameStarted) {
this.namePos++;
if (dim == 0)
return new SingleTypeReference(TypeBinding.SHORT.simpleName, ((long) start << 32) + end);
else
return new ArrayTypeReference(TypeBinding.SHORT.simpleName, dim, ((long) start << 32) + end);
}
break;
case Signature.C_VOID :
if (!nameStarted) {
this.namePos++;
return new SingleTypeReference(TypeBinding.VOID.simpleName, ((long) start << 32) + end);
}
break;
case Signature.C_RESOLVED :
case Signature.C_UNRESOLVED :
case Signature.C_TYPE_VARIABLE :
if (!nameStarted) {
nameFragmentStart = this.namePos+1;
nameStarted = true;
}
break;
case Signature.C_STAR:
this.namePos++;
Wildcard result = new Wildcard(Wildcard.UNBOUND);
result.sourceStart = start;
result.sourceEnd = end;
return result;
case Signature.C_EXTENDS:
this.namePos++;
result = new Wildcard(Wildcard.EXTENDS);
result.bound = decodeType(typeSignature, length, start, end);
result.sourceStart = start;
result.sourceEnd = end;
return result;
case Signature.C_SUPER:
this.namePos++;
result = new Wildcard(Wildcard.SUPER);
result.bound = decodeType(typeSignature, length, start, end);
result.sourceStart = start;
result.sourceEnd = end;
return result;
case Signature.C_ARRAY :
dim++;
break;
case Signature.C_GENERIC_END :
case Signature.C_SEMICOLON :
nameFragmentEnd = this.namePos-1;
//{ObjectTeams: don't consume stop char of anchor:
if (!isAnchor)
// SH}
this.namePos++;
break typeLoop;
case Signature.C_DOLLAR:
//{ObjectTeams: recover _OT$ prefix (revert separator-ness of '$'):
if ( nameStarted
&& this.namePos >= 3
&& typeSignature.substring(this.namePos-3, this.namePos+1)
.equals(IOTConstants.OT_DOLLAR))
{
nameFragmentStart = this.namePos-3;
break;
}
// SH}
if (this.memberTypeSeparator != Signature.C_DOLLAR)
break;
// $FALL-THROUGH$
case Signature.C_DOT :
if (!nameStarted) {
nameFragmentStart = this.namePos+1;
nameStarted = true;
} else if (this.namePos > nameFragmentStart) // handle name starting with a $ (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=91709)
identCount ++;
break;
case Signature.C_GENERIC_START :
nameFragmentEnd = this.namePos-1;
// convert 1.5 specific constructs only if compliance is 1.5 or above
if (!this.has1_5Compliance)
break typeLoop;
if (fragments == null) fragments = new ArrayList(2);
addIdentifiers(typeSignature, nameFragmentStart, nameFragmentEnd + 1, identCount, fragments);
this.namePos++; // skip '<'
TypeReference[] arguments = decodeTypeArguments(typeSignature, length, start, end); // positionned on '>' at end
fragments.add(arguments);
identCount = 1;
nameStarted = false;
// next increment will skip '>'
break;
//{ObjectTeams: detecting the @anchor
case '@':
isAnchor = true;
nameFragmentStart++;
break;
// SH}
}
this.namePos++;
}
if (fragments == null) { // non parameterized
/* rebuild identifiers and dimensions */
if (identCount == 1) { // simple type reference
if (dim == 0) {
char[] nameFragment = new char[nameFragmentEnd - nameFragmentStart + 1];
typeSignature.getChars(nameFragmentStart, nameFragmentEnd +1, nameFragment, 0);
//{ObjectTeams: anchor reference detected?
if (isAnchor) {
// _OT$base may have been beautified to base, recover original:
if (CharOperation.equals(nameFragment, IOTConstants.BASE))
nameFragment = IOTConstants._OT_BASE;
NameReference name = new SingleNameReference(nameFragment, ((long) start << 32) + end);
return new TypeAnchorReference(name, start);
}
// SH}
return new SingleTypeReference(nameFragment, ((long) start << 32) + end);
} else {
char[] nameFragment = new char[nameFragmentEnd - nameFragmentStart + 1];
typeSignature.getChars(nameFragmentStart, nameFragmentEnd +1, nameFragment, 0);
return new ArrayTypeReference(nameFragment, dim, ((long) start << 32) + end);
}
} else { // qualified type reference
long[] positions = new long[identCount];
long pos = ((long) start << 32) + end;
for (int i = 0; i < identCount; i++) {
positions[i] = pos;
}
char[][] identifiers = extractIdentifiers(typeSignature, nameFragmentStart, nameFragmentEnd, identCount);
if (dim == 0) {
//{ObjectTeams: anchor reference detected?
if (isAnchor) {
Reference anchor;
// anchors including a 'base' token are encoded differently:
if (CharOperation.equals(identifiers[identCount-1], IOTConstants.BASE)) {
TypeReference qualification;
if (identCount == 2) {
qualification = new SingleTypeReference(identifiers[0], positions[0]);
} else {
System.arraycopy(positions, 0, positions=new long[positions.length-1], 0, positions.length-1);
qualification = new QualifiedTypeReference(CharOperation.subarray(identifiers, 0, identCount-1), positions);
}
anchor = new QualifiedBaseReference(qualification, end-3, end);
} else {
anchor = new QualifiedNameReference(identifiers, positions, start, end);
}
return new TypeAnchorReference(anchor, start);
}
// SH}
return new QualifiedTypeReference(identifiers, positions);
} else {
return new ArrayQualifiedTypeReference(identifiers, dim, positions);
}
}
} else { // parameterized
// rebuild type reference from available fragments: char[][], arguments, char[][], arguments...
// check trailing qualified name
if (nameStarted) {
addIdentifiers(typeSignature, nameFragmentStart, nameFragmentEnd + 1, identCount, fragments);
}
int fragmentLength = fragments.size();
if (fragmentLength == 2) {
Object firstFragment = fragments.get(0);
if (firstFragment instanceof char[]) {
// parameterized single type
return new ParameterizedSingleTypeReference((char[]) firstFragment, (TypeReference[]) fragments.get(1), dim, ((long) start << 32) + end);
}
}
// parameterized qualified type
identCount = 0;
for (int i = 0; i < fragmentLength; i ++) {
Object element = fragments.get(i);
if (element instanceof char[][]) {
identCount += ((char[][])element).length;
} else if (element instanceof char[])
identCount++;
}
char[][] tokens = new char[identCount][];
TypeReference[][] arguments = new TypeReference[identCount][];
int index = 0;
for (int i = 0; i < fragmentLength; i ++) {
Object element = fragments.get(i);
if (element instanceof char[][]) {
char[][] fragmentTokens = (char[][]) element;
int fragmentTokenLength = fragmentTokens.length;
System.arraycopy(fragmentTokens, 0, tokens, index, fragmentTokenLength);
index += fragmentTokenLength;
} else if (element instanceof char[]) {
tokens[index++] = (char[]) element;
} else {
arguments[index-1] = (TypeReference[]) element;
}
}
long[] positions = new long[identCount];
long pos = ((long) start << 32) + end;
for (int i = 0; i < identCount; i++) {
positions[i] = pos;
}
return new ParameterizedQualifiedTypeReference(tokens, arguments, dim, positions);
}
}
private TypeReference decodeType(char[] typeName, int length, int start, int end, boolean includeGenericsAnyway) {
int identCount = 1;
int dim = 0;
int nameFragmentStart = this.namePos, nameFragmentEnd = -1;
ArrayList fragments = null;
//{ObjectTeams: consider @anchor:
boolean isAnchor = false;
// SH}
typeLoop: while (this.namePos < length) {
char currentChar = typeName[this.namePos];
switch (currentChar) {
case '?' :
this.namePos++; // skip '?'
while (typeName[this.namePos] == ' ') this.namePos++;
switch(typeName[this.namePos]) {
case 's' :
checkSuper: {
int max = TypeConstants.WILDCARD_SUPER.length-1;
for (int ahead = 1; ahead < max; ahead++) {
if (typeName[this.namePos+ahead] != TypeConstants.WILDCARD_SUPER[ahead+1]) {
break checkSuper;
}
}
this.namePos += max;
Wildcard result = new Wildcard(Wildcard.SUPER);
result.bound = decodeType(typeName, length, start, end, includeGenericsAnyway);
result.sourceStart = start;
result.sourceEnd = end;
return result;
}
break;
case 'e' :
checkExtends: {
int max = TypeConstants.WILDCARD_EXTENDS.length-1;
for (int ahead = 1; ahead < max; ahead++) {
if (typeName[this.namePos+ahead] != TypeConstants.WILDCARD_EXTENDS[ahead+1]) {
break checkExtends;
}
}
this.namePos += max;
Wildcard result = new Wildcard(Wildcard.EXTENDS);
result.bound = decodeType(typeName, length, start, end, includeGenericsAnyway);
result.sourceStart = start;
result.sourceEnd = end;
return result;
}
break;
}
Wildcard result = new Wildcard(Wildcard.UNBOUND);
result.sourceStart = start;
result.sourceEnd = end;
return result;
case '[' :
if (dim == 0 && nameFragmentEnd < 0) nameFragmentEnd = this.namePos-1;
dim++;
break;
case ']' :
break;
case '>' :
case ',' :
break typeLoop;
case '.' :
if (nameFragmentStart < 0) nameFragmentStart = this.namePos+1; // member type name
identCount ++;
break;
case '<' :
/* We need to convert and preserve 1.5 specific constructs either if compliance is 1.5 or above,
or the caller has explicitly requested generics to be included. The parameter includeGenericsAnyway
should be used by the caller to signal that in the calling context generics information must be
internalized even when the requesting project is 1.4. But in all cases, we must skip over them to
see if there are any applicable type fragments after the type parameters: i.e we just aren't done
having seen a '<' in 1.4 mode.
Because of the way type signatures are encoded, TypeConverter.decodeType(String, int, int, int) is immune
to this problem. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=325633
*/
if (this.has1_5Compliance || includeGenericsAnyway) {
if (fragments == null) fragments = new ArrayList(2);
}
nameFragmentEnd = this.namePos-1;
if (this.has1_5Compliance || includeGenericsAnyway) {
char[][] identifiers = CharOperation.splitOn('.', typeName, nameFragmentStart, this.namePos);
fragments.add(identifiers);
}
this.namePos++; // skip '<'
TypeReference[] arguments = decodeTypeArguments(typeName, length, start, end, includeGenericsAnyway); // positionned on '>' at end
if (this.has1_5Compliance || includeGenericsAnyway) {
fragments.add(arguments);
identCount = 0;
nameFragmentStart = -1;
nameFragmentEnd = -1;
}
// next increment will skip '>'
break;
//{ObjectTeams: detecting the @anchor
case '@':
isAnchor = true;
nameFragmentStart++;
break;
// SH}
}
this.namePos++;
}
if (nameFragmentEnd < 0) nameFragmentEnd = this.namePos-1;
if (fragments == null) { // non parameterized
/* rebuild identifiers and dimensions */
if (identCount == 1) { // simple type reference
if (dim == 0) {
char[] nameFragment;
if (nameFragmentStart != 0 || nameFragmentEnd >= 0) {
int nameFragmentLength = nameFragmentEnd - nameFragmentStart + 1;
System.arraycopy(typeName, nameFragmentStart, nameFragment = new char[nameFragmentLength], 0, nameFragmentLength);
} else {
nameFragment = typeName;
}
//{ObjectTeams: anchor reference detected?
if (isAnchor) {
// _OT$base may have been beautified to base, recover original:
if (CharOperation.equals(nameFragment, IOTConstants.BASE))
nameFragment = IOTConstants._OT_BASE;
NameReference name = new SingleNameReference(nameFragment, ((long) start << 32) + end);
return new TypeAnchorReference(name, start);
}
// SH}
return new SingleTypeReference(nameFragment, ((long) start << 32) + end);
} else {
int nameFragmentLength = nameFragmentEnd - nameFragmentStart + 1;
char[] nameFragment = new char[nameFragmentLength];
System.arraycopy(typeName, nameFragmentStart, nameFragment, 0, nameFragmentLength);
return new ArrayTypeReference(nameFragment, dim, ((long) start << 32) + end);
}
} else { // qualified type reference
long[] positions = new long[identCount];
long pos = ((long) start << 32) + end;
for (int i = 0; i < identCount; i++) {
positions[i] = pos;
}
char[][] identifiers = CharOperation.splitOn('.', typeName, nameFragmentStart, nameFragmentEnd+1);
if (dim == 0) {
//{ObjectTeams: anchor reference detected?
if (isAnchor) {
Reference anchor;
// anchors including a 'base' token are encoded differently:
if (CharOperation.equals(identifiers[identCount-1], IOTConstants.BASE)) {
TypeReference qualification;
if (identCount == 2) { // Single.base
qualification = new SingleTypeReference(identifiers[0], positions[0]);
} else {
System.arraycopy(positions, 0, positions=new long[positions.length-1], 0, positions.length-1);
qualification = new QualifiedTypeReference(CharOperation.subarray(identifiers, 0, identCount-1), positions);
}
anchor = new QualifiedBaseReference(qualification, end-3, end);
} else {
anchor = new QualifiedNameReference(identifiers, positions, start, end);
}
return new TypeAnchorReference(anchor, start);
}
// SH}
return new QualifiedTypeReference(identifiers, positions);
} else {
return new ArrayQualifiedTypeReference(identifiers, dim, positions);
}
}
} else { // parameterized
// rebuild type reference from available fragments: char[][], arguments, char[][], arguments...
// check trailing qualified name
if (nameFragmentStart > 0 && nameFragmentStart < length) {
char[][] identifiers = CharOperation.splitOn('.', typeName, nameFragmentStart, nameFragmentEnd+1);
fragments.add(identifiers);
}
int fragmentLength = fragments.size();
if (fragmentLength == 2) {
char[][] firstFragment = (char[][]) fragments.get(0);
if (firstFragment.length == 1) {
// parameterized single type
return new ParameterizedSingleTypeReference(firstFragment[0], (TypeReference[]) fragments.get(1), dim, ((long) start << 32) + end);
}
}
// parameterized qualified type
identCount = 0;
for (int i = 0; i < fragmentLength; i ++) {
Object element = fragments.get(i);
if (element instanceof char[][]) {
identCount += ((char[][])element).length;
}
}
char[][] tokens = new char[identCount][];
TypeReference[][] arguments = new TypeReference[identCount][];
int index = 0;
for (int i = 0; i < fragmentLength; i ++) {
Object element = fragments.get(i);
if (element instanceof char[][]) {
char[][] fragmentTokens = (char[][]) element;
int fragmentTokenLength = fragmentTokens.length;
System.arraycopy(fragmentTokens, 0, tokens, index, fragmentTokenLength);
index += fragmentTokenLength;
} else {
arguments[index-1] = (TypeReference[]) element;
}
}
long[] positions = new long[identCount];
long pos = ((long) start << 32) + end;
for (int i = 0; i < identCount; i++) {
positions[i] = pos;
}
return new ParameterizedQualifiedTypeReference(tokens, arguments, dim, positions);
}
}
private TypeReference[] decodeTypeArguments(char[] typeName, int length, int start, int end, boolean includeGenericsAnyway) {
ArrayList argumentList = new ArrayList(1);
int count = 0;
argumentsLoop: while (this.namePos < length) {
TypeReference argument = decodeType(typeName, length, start, end, includeGenericsAnyway);
count++;
argumentList.add(argument);
if (this.namePos >= length) break argumentsLoop;
if (typeName[this.namePos] == '>') {
break argumentsLoop;
}
this.namePos++; // skip ','
}
TypeReference[] typeArguments = new TypeReference[count];
argumentList.toArray(typeArguments);
return typeArguments;
}
private TypeReference[] decodeTypeArguments(String typeSignature, int length, int start, int end) {
ArrayList argumentList = new ArrayList(1);
int count = 0;
argumentsLoop: while (this.namePos < length) {
TypeReference argument = decodeType(typeSignature, length, start, end);
count++;
argumentList.add(argument);
if (this.namePos >= length) break argumentsLoop;
if (typeSignature.charAt(this.namePos) == Signature.C_GENERIC_END) {
break argumentsLoop;
}
}
TypeReference[] typeArguments = new TypeReference[count];
argumentList.toArray(typeArguments);
return typeArguments;
}
private char[][] extractIdentifiers(String typeSignature, int start, int endInclusive, int identCount) {
char[][] result = new char[identCount][];
int charIndex = start;
int i = 0;
while (charIndex < endInclusive) {
char currentChar;
if ((currentChar = typeSignature.charAt(charIndex)) == this.memberTypeSeparator || currentChar == Signature.C_DOT) {
typeSignature.getChars(start, charIndex, result[i++] = new char[charIndex - start], 0);
start = ++charIndex;
} else
charIndex++;
}
typeSignature.getChars(start, charIndex + 1, result[i++] = new char[charIndex - start + 1], 0);
return result;
}
//{ObjectTeams: OT Elements are handled uniformely in source/binary types:
/**
* @param methodMapping
* @param compilationResult
* @return
*/
protected AbstractMethodMappingDeclaration convertCallout(
IMethodMapping methodMapping, CompilationResult compilationResult)
{
if (methodMapping instanceof ICalloutToFieldMapping)
{
return convertCalloutToField(methodMapping, compilationResult);
}
else
{
ICalloutMapping callout = (ICalloutMapping)methodMapping;
boolean hasSignature = callout.hasSignature();
CalloutMappingDeclaration result =
new CalloutMappingDeclaration(compilationResult);
result.declarationSourceStart = callout.getDeclarationSourceStart();
result.sourceStart = callout.getSourceStart();
result.sourceEnd = callout.getSourceEnd();
result.declarationSourceEnd = callout.getDeclarationSourceEnd();
result.declaredModifiers = callout.getDeclaredModifiers();
result.hasSignature = hasSignature;
result.setCalloutKind(callout.isOverride());
result.compilationResult = compilationResult;
result.roleMethodSpec = convert(callout.getRoleMethodHandle(), hasSignature);
IMethodSpec baseHandle = callout.getBaseMethodHandle();
if (baseHandle != null)
result.baseMethodSpec = convert(baseHandle, hasSignature);
return result;
}
}
protected AbstractMethodMappingDeclaration convertCalloutToField(
IMethodMapping methodMapping,
CompilationResult compilationResult)
{
ICalloutToFieldMapping callout = (ICalloutToFieldMapping)methodMapping;
boolean hasSignature = callout.hasSignature();
CalloutMappingDeclaration result =
new CalloutMappingDeclaration(compilationResult);
result.declarationSourceStart = callout.getDeclarationSourceStart();
result.sourceStart = callout.getSourceStart();
result.sourceEnd = callout.getSourceEnd();
result.declarationSourceEnd = callout.getDeclarationSourceEnd();
result.hasSignature = hasSignature;
result.setCalloutKind(callout.isOverride());
result.compilationResult = compilationResult;
result.roleMethodSpec = convert(callout.getRoleMethodHandle(), hasSignature);
IFieldAccessSpec baseFieldHandle = callout.getBaseFieldHandle();
result.baseMethodSpec = convert(baseFieldHandle, hasSignature);
return result;
}
/**
* @param methodMapping
* @param compilationResult
*/
protected CallinMappingDeclaration convertCallin(
IMethodMapping methodMapping, CompilationResult compilationResult)
{
ICallinMapping callinMapping = (ICallinMapping)methodMapping;
boolean hasSignature = callinMapping.hasSignature();
CallinMappingDeclaration result =
new CallinMappingDeclaration(compilationResult);
result.name = callinMapping.getName().toCharArray();
result.declarationSourceStart = callinMapping.getDeclarationSourceStart();
result.sourceStart = callinMapping.getSourceStart();
result.sourceEnd = callinMapping.getSourceEnd();
result.declarationSourceEnd = callinMapping.getDeclarationSourceEnd();
result.hasSignature = hasSignature;
result.callinModifier = CallinMapping.convertModelToTerminalToken(callinMapping.getCallinKind());
result.compilationResult = compilationResult;
result.roleMethodSpec = convert(callinMapping.getRoleMethodHandle(), hasSignature);
IMethodSpec[] baseHandles = callinMapping.getBaseMethodHandles();
int baseCount = baseHandles.length;
result.baseMethodSpecs = new MethodSpec[baseCount];
for(int idx = 0; idx < baseCount; idx++)
{
result.baseMethodSpecs[idx] =
convert(baseHandles[idx], hasSignature);
}
return result;
}
protected MethodSpec convert(IMethodSpec handle, boolean hasSignature)
{
//FIXME (haebor) : sourcepositions are not set!! try to find them elsewhere
//initialize a dummy and then fill the values,
//since there's no constructor that fits the needs of this initialization
MethodSpec result = new MethodSpec(handle.getSelector().toCharArray(), 0);
int start = result.sourceStart = handle.getSourceStart();
int end = result.sourceEnd = handle.getSourceEnd();
result.hasSignature = hasSignature;
result.isDeclaration = handle.isDeclaration();
result.covariantReturn= handle.hasCovariantReturn();
if(hasSignature)
{
String[] argTypes = handle.getArgumentTypes();
String[] argNames = handle.getArgumentNames();
result.arguments = new Argument[argTypes.length];
for(int idx = 0; idx < argTypes.length; idx++)
{
//TODO (haebor) : again no sourceposition
//(put them to the methodspec pos like convert(ISourceMethod,..))
//don't care about access modifiers (see conversion of methods)
result.arguments[idx] = new Argument(
((argNames.length > idx) ? argNames[idx].toCharArray() : ("arg"+idx).toCharArray()), //$NON-NLS-1$
0,
createTypeReference(argTypes[idx]),
ClassFileConstants.AccDefault);
}
if (result.arguments != null) {
result.argNeedsTranslation = new boolean[result.arguments.length];
Arrays.fill(result.argNeedsTranslation, false);
}
String returnType = handle.getReturnType();
if (returnType != null && returnType.length() > 0) // empty string caused IllegalArgumentException below
result.returnType = createTypeReference(returnType);
/* convert type parameters (see convert(SourceMethod,..)) */
char[][] typeParameterNames = handle.getTypeParameterNames();
if (typeParameterNames != null) {
int parameterCount = typeParameterNames.length;
if (parameterCount > 0) { // method's type parameters must be null if no type parameter
char[][][] typeParameterBounds = handle.getTypeParameterBounds();
TypeParameter[] typeParams = new TypeParameter[parameterCount];
for (int i = 0; i < parameterCount; i++) {
typeParams[i] = createTypeParameter(typeParameterNames[i], typeParameterBounds[i], false/*baseBound*/, start, end);
}
result.typeParameters= typeParams;
}
}
}
return result;
}
protected MethodSpec convert(IFieldAccessSpec handle, boolean hasSignature)
{
//FIXME(gbr) source positions are not set!
TypeReference fieldType = hasSignature ? createTypeReference(handle.getFieldType()) : null;
MethodSpec result = new FieldAccessSpec(handle.getSelector().toCharArray(), fieldType, 0, handle.isSetter());
result.sourceStart = 0;
result.sourceEnd = 0;
result.hasSignature = hasSignature;
return result;
}
protected TypeReference createTypeReference(String typeSignature) {
return createTypeReference(typeSignature, 0, 0);
}
// SH,haebor,gbr}
}