| /******************************************************************************* |
| * Copyright (c) 2016, 2017 xored software, Inc. and others. |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * xored software, Inc. - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.dltk.core.model.binary; |
| |
| import java.io.InputStream; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.dltk.core.CompletionRequestor; |
| import org.eclipse.dltk.core.DLTKCore; |
| import org.eclipse.dltk.core.DLTKLanguageManager; |
| import org.eclipse.dltk.core.IField; |
| import org.eclipse.dltk.core.IMethod; |
| import org.eclipse.dltk.core.IModelElement; |
| import org.eclipse.dltk.core.IParent; |
| import org.eclipse.dltk.core.IScriptFolder; |
| import org.eclipse.dltk.core.IScriptProject; |
| import org.eclipse.dltk.core.ISourceModule; |
| import org.eclipse.dltk.core.IType; |
| import org.eclipse.dltk.core.ITypeHierarchy; |
| import org.eclipse.dltk.core.ModelException; |
| import org.eclipse.dltk.core.WorkingCopyOwner; |
| import org.eclipse.dltk.core.search.IDLTKSearchScope; |
| import org.eclipse.dltk.core.search.SearchEngine; |
| import org.eclipse.dltk.internal.core.CreateTypeHierarchyOperation; |
| import org.eclipse.dltk.internal.core.DefaultWorkingCopyOwner; |
| import org.eclipse.dltk.internal.core.ModelElement; |
| import org.eclipse.dltk.internal.core.ModelManager; |
| import org.eclipse.dltk.internal.core.hierarchy.TypeHierarchy; |
| import org.eclipse.dltk.internal.core.hierarchy.TypeHierarchyBuilders; |
| import org.eclipse.dltk.internal.core.util.Messages; |
| import org.eclipse.dltk.utils.CorePrinter; |
| |
| /** |
| * @since 2.0 |
| */ |
| public class BinaryType extends BinaryMember implements IType, IParent { |
| private static final IField[] NO_FIELDS = new IField[0]; |
| private static final IMethod[] NO_METHODS = new IMethod[0]; |
| private static final IType[] NO_TYPES = new IType[0]; |
| |
| public BinaryType(ModelElement parent, String name) { |
| super(parent, name); |
| } |
| |
| @Override |
| public void codeComplete(char[] snippet, int insertion, int position, |
| char[][] localVariableTypeNames, char[][] localVariableNames, |
| int[] localVariableModifiers, boolean isStatic, |
| CompletionRequestor requestor) throws ModelException { |
| } |
| |
| @Override |
| public void codeComplete(char[] snippet, int insertion, int position, |
| char[][] localVariableTypeNames, char[][] localVariableNames, |
| int[] localVariableModifiers, boolean isStatic, |
| CompletionRequestor requestor, WorkingCopyOwner owner) |
| throws ModelException { |
| } |
| |
| private IDLTKSearchScope createReferencingProjectsScope() { |
| |
| IScriptProject scriptProject = getScriptProject(); |
| IProject project = scriptProject.getProject(); |
| IProject[] referencingProjects = project.getReferencingProjects(); |
| |
| List<IScriptProject> scriptProjects = new ArrayList<>( |
| referencingProjects.length + 1); |
| scriptProjects.add(scriptProject); |
| |
| for (int i = 0; i < referencingProjects.length; ++i) { |
| IProject p = referencingProjects[i]; |
| if (p.isAccessible()) { |
| scriptProjects.add(DLTKCore.create(p)); |
| } |
| } |
| return SearchEngine.createSearchScope( |
| scriptProjects |
| .toArray(new IModelElement[scriptProjects.size()]), |
| false, DLTKLanguageManager.getLanguageToolkit(this)); |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (!(o instanceof BinaryType)) { |
| return false; |
| } |
| return super.equals(o); |
| } |
| |
| /* |
| * @see IType |
| */ |
| @Override |
| public IMethod[] findMethods(IMethod method) { |
| try { |
| return findMethods(method, getMethods()); |
| } catch (ModelException e) { |
| // if type doesn't exist, no matching method can exist |
| return null; |
| } |
| } |
| |
| @Override |
| public int getElementType() { |
| return TYPE; |
| } |
| |
| @Override |
| public IField getField(String name) { |
| return new BinaryField(this, name); |
| } |
| |
| @Override |
| public IField[] getFields() throws ModelException { |
| List<IModelElement> list = getChildrenOfType(FIELD); |
| int size; |
| if ((size = list.size()) == 0) { |
| return NO_FIELDS; |
| } else { |
| IField[] array = new IField[size]; |
| list.toArray(array); |
| return array; |
| } |
| } |
| |
| @Override |
| public String getFullyQualifiedName() { |
| return getFullyQualifiedName("$"); //$NON-NLS-1$ |
| } |
| |
| @Override |
| public String getFullyQualifiedName(String enclosingTypeSeparator) { |
| try { |
| /* |
| * don't show parameters |
| */ |
| return getFullyQualifiedName(enclosingTypeSeparator, false); |
| } catch (ModelException e) { |
| // exception thrown only when showing parameters |
| return null; |
| } |
| } |
| |
| @Override |
| public IMethod getMethod(String name) { |
| return new BinaryMethod(this, name); |
| } |
| |
| @Override |
| public IMethod[] getMethods() throws ModelException { |
| List<IModelElement> list = getChildrenOfType(METHOD); |
| int size; |
| if ((size = list.size()) == 0) { |
| return NO_METHODS; |
| } else { |
| IMethod[] array = new IMethod[size]; |
| list.toArray(array); |
| return array; |
| } |
| } |
| |
| @Override |
| public IScriptFolder getScriptFolder() { |
| return (IScriptFolder) getAncestor(IModelElement.SCRIPT_FOLDER); |
| } |
| |
| @Override |
| public String[] getSuperClasses() throws ModelException { |
| return ((BinaryTypeElementInfo) getElementInfo()).getSuperclassNames(); |
| } |
| |
| @Override |
| public IType getType(String name) { |
| try { |
| IType[] types = getTypes(); |
| for (IType type : types) { |
| if (type.getElementName().equals(name)) { |
| return type; |
| } |
| } |
| } catch (ModelException e) { |
| if (DLTKCore.DEBUG) { |
| e.printStackTrace(); |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public String getTypeQualifiedName() { |
| return this.getTypeQualifiedName("$"); |
| } |
| |
| @Override |
| public String getTypeQualifiedName(String enclosingTypeSeparator) { |
| try { |
| /* |
| * don't show parameters |
| */ |
| return getTypeQualifiedName(enclosingTypeSeparator, false); |
| } catch (ModelException e) { |
| // exception thrown only when showing parameters |
| return null; |
| } |
| } |
| |
| @Override |
| public IType[] getTypes() throws ModelException { |
| List<IModelElement> list = getChildrenOfType(TYPE); |
| int size; |
| if ((size = list.size()) == 0) { |
| return NO_TYPES; |
| } else { |
| IType[] array = new IType[size]; |
| list.toArray(array); |
| return array; |
| } |
| } |
| |
| /* |
| * Type hierarchies section |
| */ |
| |
| /** |
| * @see IType |
| */ |
| @Override |
| public ITypeHierarchy loadTypeHierachy(InputStream input, |
| IProgressMonitor monitor) throws ModelException { |
| return loadTypeHierachy(input, DefaultWorkingCopyOwner.PRIMARY, |
| monitor); |
| } |
| |
| /** |
| * NOTE: This method is not part of the API has it is not clear clients |
| * would easily use it: they would need to first make sure all working |
| * copies for the given owner exist before calling it. This is especially |
| * har at startup time. In case clients want this API, here is how it should |
| * be specified: |
| * <p> |
| * Loads a previously saved ITypeHierarchy from an input stream. A type |
| * hierarchy can be stored using ITypeHierachy#store(OutputStream). A |
| * compilation unit of a loaded type has the given owner if such a working |
| * copy exists, otherwise the type's compilation unit is a primary |
| * compilation unit. |
| * |
| * Only hierarchies originally created by the following methods can be |
| * loaded: |
| * <ul> |
| * <li>IType#newSupertypeHierarchy(IProgressMonitor)</li> |
| * <li>IType#newSupertypeHierarchy(WorkingCopyOwner, IProgressMonitor)</li> |
| * <li>IType#newTypeHierarchy(IJavaProject, IProgressMonitor)</li> |
| * <li>IType#newTypeHierarchy(IJavaProject, WorkingCopyOwner, |
| * IProgressMonitor)</li> |
| * <li>IType#newTypeHierarchy(IProgressMonitor)</li> |
| * <li>IType#newTypeHierarchy(WorkingCopyOwner, IProgressMonitor)</li> </u> |
| * |
| * @param input |
| * stream where hierarchy will be read |
| * @param monitor |
| * the given progress monitor |
| * @return the stored hierarchy |
| * @exception JavaModelException |
| * if the hierarchy could not be restored, reasons include: - |
| * type is not the focus of the hierarchy or - unable to read |
| * the input stream (wrong format, IOException during |
| * reading, ...) |
| * @see ITypeHierarchy#store(java.io.OutputStream, IProgressMonitor) |
| * @since 3.0 |
| */ |
| public ITypeHierarchy loadTypeHierachy(InputStream input, |
| WorkingCopyOwner owner, IProgressMonitor monitor) |
| throws ModelException { |
| // TODO monitor should be passed to TypeHierarchy.load(...) |
| return TypeHierarchy.load(this, input, owner); |
| } |
| |
| /** |
| * @see IType |
| */ |
| @Override |
| public ITypeHierarchy newSupertypeHierarchy(IProgressMonitor monitor) |
| throws ModelException { |
| return this.newSupertypeHierarchy(DefaultWorkingCopyOwner.PRIMARY, |
| monitor); |
| } |
| |
| /* |
| * @see IType#newSupertypeHierarchy(ICompilationUnit[], IProgressMonitor) |
| */ |
| @Override |
| public ITypeHierarchy newSupertypeHierarchy(ISourceModule[] workingCopies, |
| IProgressMonitor monitor) throws ModelException { |
| |
| CreateTypeHierarchyOperation op; |
| IScriptProject scriptProject = getScriptProject(); |
| IDLTKSearchScope scope = SearchEngine.createSearchScope(scriptProject); |
| op = new CreateTypeHierarchyOperation(this, workingCopies, scope, |
| false); |
| op.runOperation(monitor); |
| return op.getResult(); |
| } |
| |
| /** |
| * @see IType#newSupertypeHierarchy(WorkingCopyOwner, IProgressMonitor) |
| */ |
| @Override |
| public ITypeHierarchy newSupertypeHierarchy(WorkingCopyOwner owner, |
| IProgressMonitor monitor) throws ModelException { |
| |
| ISourceModule[] workingCopies = ModelManager.getModelManager() |
| .getWorkingCopies(owner, true/* add primary working copies */); |
| CreateTypeHierarchyOperation op; |
| IScriptProject scriptProject = getScriptProject(); |
| IDLTKSearchScope scope = SearchEngine.createSearchScope(scriptProject); |
| op = new CreateTypeHierarchyOperation(this, workingCopies, scope, |
| false); |
| op.runOperation(monitor); |
| return op.getResult(); |
| } |
| |
| /** |
| * @see IType |
| */ |
| @Override |
| public ITypeHierarchy newTypeHierarchy(IProgressMonitor monitor) |
| throws ModelException { |
| final ITypeHierarchy hierarchy = TypeHierarchyBuilders |
| .getTypeHierarchy(this, ITypeHierarchy.Mode.HIERARCHY, monitor); |
| if (hierarchy != null) { |
| return hierarchy; |
| } |
| CreateTypeHierarchyOperation op; |
| op = new CreateTypeHierarchyOperation(this, null, |
| createReferencingProjectsScope(), true); |
| op.runOperation(monitor); |
| return op.getResult(); |
| } |
| |
| /** |
| * @see IType |
| */ |
| @Override |
| public ITypeHierarchy newTypeHierarchy(IScriptProject project, |
| IProgressMonitor monitor) throws ModelException { |
| return newTypeHierarchy(project, DefaultWorkingCopyOwner.PRIMARY, |
| monitor); |
| } |
| |
| /** |
| * @see IType#newTypeHierarchy(IJavaProject, WorkingCopyOwner, |
| * IProgressMonitor) |
| */ |
| @Override |
| public ITypeHierarchy newTypeHierarchy(IScriptProject project, |
| WorkingCopyOwner owner, IProgressMonitor monitor) |
| throws ModelException { |
| if (project == null) { |
| throw new IllegalArgumentException(Messages.hierarchy_nullProject); |
| } |
| ISourceModule[] workingCopies = ModelManager.getModelManager() |
| .getWorkingCopies(owner, true/* add primary working copies */); |
| ISourceModule[] projectWCs = null; |
| if (workingCopies != null) { |
| int length = workingCopies.length; |
| projectWCs = new ISourceModule[length]; |
| int index = 0; |
| for (int i = 0; i < length; i++) { |
| ISourceModule wc = workingCopies[i]; |
| if (project.equals(wc.getScriptProject())) { |
| projectWCs[index++] = wc; |
| } |
| } |
| if (index != length) { |
| System.arraycopy(projectWCs, 0, |
| projectWCs = new ISourceModule[index], 0, index); |
| } |
| } |
| CreateTypeHierarchyOperation op = new CreateTypeHierarchyOperation(this, |
| projectWCs, project, true); |
| op.runOperation(monitor); |
| return op.getResult(); |
| } |
| |
| /* |
| * @see IType#newTypeHierarchy(ICompilationUnit[], IProgressMonitor) |
| */ |
| @Override |
| public ITypeHierarchy newTypeHierarchy(ISourceModule[] workingCopies, |
| IProgressMonitor monitor) throws ModelException { |
| |
| CreateTypeHierarchyOperation op; |
| op = new CreateTypeHierarchyOperation(this, workingCopies, |
| createReferencingProjectsScope(), true); |
| op.runOperation(monitor); |
| return op.getResult(); |
| } |
| |
| /** |
| * @see IType#newTypeHierarchy(WorkingCopyOwner, IProgressMonitor) |
| */ |
| @Override |
| public ITypeHierarchy newTypeHierarchy(WorkingCopyOwner owner, |
| IProgressMonitor monitor) throws ModelException { |
| |
| ISourceModule[] workingCopies = ModelManager.getModelManager() |
| .getWorkingCopies(owner, true/* add primary working copies */); |
| CreateTypeHierarchyOperation op; |
| op = new CreateTypeHierarchyOperation(this, workingCopies, |
| createReferencingProjectsScope(), true); |
| op.runOperation(monitor); |
| return op.getResult(); |
| } |
| |
| @Override |
| public void printNode(CorePrinter output) { |
| output.formatPrint("DLTK Binary Type:" + getElementName()); //$NON-NLS-1$ |
| output.indent(); |
| try { |
| IModelElement modelElements[] = this.getChildren(); |
| for (int i = 0; i < modelElements.length; ++i) { |
| IModelElement element = modelElements[i]; |
| if (element instanceof ModelElement) { |
| ((ModelElement) element).printNode(output); |
| } else { |
| output.print("Unknown element:" + element); //$NON-NLS-1$ |
| } |
| } |
| } catch (ModelException ex) { |
| output.formatPrint(ex.getLocalizedMessage()); |
| } |
| output.dedent(); |
| } |
| } |