blob: 7c95b2cc6d98d2d8e5bbee4609a812800b2791ab [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016, 2017 xored software, Inc. 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
*
* 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();
}
}