| /********************************************************************** |
| * This file is part of "Object Teams Development Tooling"-Software |
| * |
| * Copyright 2004, 2006 Fraunhofer Gesellschaft, Munich, Germany, |
| * for its Fraunhofer Institute for Computer Architecture and Software |
| * Technology (FIRST), Berlin, Germany and Technical University Berlin, |
| * Germany. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * $Id: CallinPrecedenceAttribute.java 23416 2010-02-03 19:59:31Z stephan $ |
| * |
| * Please visit http://www.eclipse.org/objectteams for updates and contact. |
| * |
| * Contributors: |
| * Fraunhofer FIRST - Initial API and implementation |
| * Technical University Berlin - Initial API and implementation |
| **********************************************************************/ |
| package org.eclipse.objectteams.otdt.internal.core.compiler.bytecode; |
| |
| import org.eclipse.jdt.core.compiler.CharOperation; |
| import org.eclipse.jdt.internal.compiler.classfmt.ClassFileStruct; |
| import org.eclipse.jdt.internal.compiler.lookup.Binding; |
| import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; |
| import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment; |
| import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; |
| import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; |
| import org.eclipse.objectteams.otdt.core.compiler.IOTConstants; |
| import org.eclipse.objectteams.otdt.core.exceptions.InternalCompilerError; |
| import org.eclipse.objectteams.otdt.internal.core.compiler.control.ITranslationStates; |
| import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.CallinCalloutBinding; |
| import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.PrecedenceBinding; |
| |
| /** |
| * TODO Description of this attribute |
| * |
| * @author stephan |
| * @version $Id: CallinPrecedenceAttribute.java 23416 2010-02-03 19:59:31Z stephan $ |
| */ |
| public class CallinPrecedenceAttribute extends ListValueAttribute { |
| |
| private char[][] callinNames; |
| |
| public CallinPrecedenceAttribute(ReferenceBinding site, CallinCalloutBinding[] callins) |
| { |
| super(IOTConstants.CALLIN_PRECEDENCE, callins.length, 2); // each element is a name reference |
| int count = 0; |
| for (int i = 0; i < callins.length; i++) { |
| Binding callinBinding= callins[i]; |
| if (callinBinding != null && callinBinding.isValidBinding()) |
| count++; |
| } |
| this.callinNames = new char[count][]; |
| this._count = count; |
| count = 0; |
| for (int i = 0; i < callins.length; i++) { |
| CallinCalloutBinding callinBinding = callins[i]; |
| if (callinBinding != null && callinBinding.isValidBinding()) |
| this.callinNames[count++] = getQualifiedName(site, callinBinding); |
| } |
| } |
| |
| /** |
| * Prepend type path to callin when looking from site. |
| * @param site |
| * @param callinBinding |
| * @return a '.' separated path |
| */ |
| private char[] getQualifiedName(ReferenceBinding site, CallinCalloutBinding callinBinding) { |
| String name = new String(callinBinding.name); |
| ReferenceBinding current = callinBinding.introducingRoleClass(); |
| while (current != null && TypeBinding.notEquals(current, site)) { |
| name = new String(current.sourceName())+'.'+name; |
| current = current.enclosingType(); |
| } |
| return name.toCharArray(); |
| } |
| |
| /** |
| * Create an attribute from byte code. |
| * |
| * (Invoked from AbstractAttribute.readAttribute(char[],MethodInfo,int,int,int[])) |
| */ |
| public CallinPrecedenceAttribute(ClassFileStruct reader, int readOffset, int[] constantPoolOffsets) |
| { |
| super(IOTConstants.CALLIN_PRECEDENCE, 0, 2); |
| readList(reader, readOffset, 0 /* no structOffset */, constantPoolOffsets); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.ListValueAttribute#writeElementValue(int) |
| */ |
| @Override |
| void writeElementValue(int i) { |
| writeName(this.callinNames[i]); |
| } |
| |
| @Override |
| void read(int i) |
| { |
| if (i==0) |
| this.callinNames = new char[this._count][]; |
| this.callinNames[i] = consumeName(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.AbstractAttribute#evaluate(org.eclipse.jdt.internal.compiler.lookup.Binding, org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment) |
| */ |
| @Override |
| public void evaluate(Binding binding, LookupEnvironment environment, char[][][] missingTypeNames) { |
| checkBindingMismatch(binding, ExtraCompilerModifiers.AccTeam); |
| if (((ReferenceBinding)binding).isTeam()) |
| ((ReferenceBinding)binding).getTeamModel().addAttribute(this); |
| } |
| // Evaluate Precedence late, because we need our methods and mappings to be in place. |
| @Override |
| public void evaluateLateAttribute(ReferenceBinding enclosingType, int state) |
| { |
| if (state != ITranslationStates.STATE_LATE_ATTRIBUTES_EVALUATED) |
| return; |
| CallinCalloutBinding[] mappings = new CallinCalloutBinding[this.callinNames.length]; |
| for (int i = 0; i < this.callinNames.length; i++) { |
| char[][] parts = CharOperation.splitOn('.', this.callinNames[i]); |
| int j = 0; |
| ReferenceBinding currentType = enclosingType; |
| while (j<parts.length-1) { |
| currentType = currentType.getMemberType( |
| CharOperation.concat(IOTConstants.OT_DELIM_NAME,parts[j++])); |
| } |
| if (currentType == null) // found in Dehla's error log. |
| throw new InternalCompilerError("Can't resolve type for precedence declaration "+new String(this.callinNames[i])); //$NON-NLS-1$ |
| CallinCalloutBinding[] callinCallouts = currentType.callinCallouts; |
| if (callinCallouts != null) { |
| for (int k = 0; k < callinCallouts.length; k++) { |
| if ( callinCallouts[k].type == CallinCalloutBinding.CALLIN |
| && CharOperation.equals(callinCallouts[k].name, parts[j])) |
| { |
| mappings[i] = callinCallouts[k]; |
| break; |
| } |
| } |
| } |
| if (mappings[i] == null) |
| throw new InternalCompilerError("Precedence attribute has unresolved method mapping"); //$NON-NLS-1$ |
| } |
| int len = enclosingType.precedences.length; |
| if (len == 0) |
| enclosingType.precedences = new PrecedenceBinding[1]; |
| else |
| System.arraycopy(enclosingType.precedences, 0, |
| enclosingType.precedences = new PrecedenceBinding[len+1], 0, |
| len); |
| enclosingType.precedences[len] = new PrecedenceBinding(enclosingType, mappings); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.ListValueAttribute#toString(int) |
| */ |
| @Override |
| String toString(int i) { |
| return new String(this.callinNames[i]); |
| } |
| |
| } |