/*******************************************************************************
* Copyright © 2000, 2013 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*
*******************************************************************************/
package org.eclipse.edt.ide.ui.internal.contentassist.proposalhandlers;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.edt.compiler.core.IEGLConstants;
import org.eclipse.edt.compiler.core.ast.File;
import org.eclipse.edt.ide.core.internal.model.BinaryPart;
import org.eclipse.edt.ide.core.internal.model.SourcePart;
import org.eclipse.edt.ide.core.internal.search.PartDeclarationInfo;
import org.eclipse.edt.ide.core.internal.search.PartInfoRequestor;
import org.eclipse.edt.ide.core.model.EGLModelException;
import org.eclipse.edt.ide.core.model.IIndexConstants;
import org.eclipse.edt.ide.core.model.IPart;
import org.eclipse.edt.ide.core.model.Signature;
import org.eclipse.edt.ide.core.model.document.IEGLDocument;
import org.eclipse.edt.ide.core.search.IEGLSearchConstants;
import org.eclipse.edt.ide.core.search.IEGLSearchScope;
import org.eclipse.edt.ide.core.search.SearchEngine;
import org.eclipse.edt.ide.ui.internal.EGLLogger;
import org.eclipse.edt.ide.ui.internal.contentassist.EGLCompletionProposal;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.ui.IEditorPart;
public class EGLPartSearchProposalHandler extends EGLAbstractProposalHandler {
private String excludeName;
private String[] subTypes;
public EGLPartSearchProposalHandler(ITextViewer viewer, int documentOffset, String prefix, IEditorPart editor) {
super(viewer, documentOffset, prefix, editor);
}
/*
* get proposals with nothing to exclude, all subTypes
*/
public List getProposals(int types) {
return getProposals(types, "", new String[0]); //$NON-NLS-1$
}
/*
* Get the proposals based on all subTypes.
* Exclude any proposals that match excludeName.
* This is to prevent cases such as adding a structure item with a type
* the same as the record it is in (recursive)
*/
public List getProposals(int types, String excludeName) {
return getProposals(types, excludeName, new String[0]);
}
/*
* Get the proposals based on the allowable type.
* restrict proposals to specific subtype
* Exclude any proposals that match excludeName.
* This is to prevent cases such as adding a structure item with a type
* the same as the record it is in (recursive)
*/
public List getProposals(int types, String excludeName, String subType) {
return getProposals(types, excludeName, new String[] {subType});
}
/*
* Get the proposals based on the allowable types.
* restrict proposals to specific subtypes
* Exclude any proposals that match excludeName.
* This is to prevent cases such as adding a structure item with a type
* the same as the record it is in (recursive)
*/
public List getProposals(int types, String excludeName, String[] subTypes) {
this.excludeName = excludeName;
this.subTypes = subTypes;
return createProposals(searchIndex(types), false);
}
/*
* Get the proposals based on the allowable types.
* restrict proposals to specific subtypes
* Exclude any proposals that match excludeName.
* This is to prevent cases such as adding a structure item with a type
* the same as the record it is in (recursive)
*/
public List getProposals(int types, String excludeName, String[] subTypes, boolean quoted) {
this.excludeName = excludeName;
this.subTypes = subTypes;
return createProposals(searchIndex(types), quoted);
}
/*
* loop through the parts returned from the index search to create each of the proposals
*/
protected List createProposals(List parts, boolean quoted) {
List proposals = new ArrayList();
String currentFilePackageName;
File eglFile = ((IEGLDocument) getViewer().getDocument()).getNewModelEGLFile();
currentFilePackageName = eglFile.hasPackageDeclaration() ?
eglFile.getPackageDeclaration().getName().getCanonicalName() :
""; //$NON-NLS-1$
for (Iterator iter = parts.iterator(); iter.hasNext();) {
PartDeclarationInfo partDeclarationInfo = (PartDeclarationInfo) iter.next();
if (partDeclarationInfo.getPartName().equalsIgnoreCase(excludeName))
//do not add a proposal for this part
continue;
if (!validSubtype(partDeclarationInfo))
continue;
String partDeclarationPackageName = partDeclarationInfo.getPackageName();
if (!shouldInclude(partDeclarationInfo)) {
continue;
}
//If source is not in the default package, we don't want proposals for parts in the default package
if(currentFilePackageName.length() == 0 || partDeclarationPackageName.length() != 0) {
//Ignore private parts if not in the same package
if (!currentFilePackageName.equalsIgnoreCase(partDeclarationPackageName)) {
if (isPublic(partDeclarationInfo)) {
EGLCompletionProposal proposal = createPartProposal(partDeclarationInfo, getPartType(partDeclarationInfo), quoted);
if (proposal != null) proposals.add(proposal);
}
}
else {
EGLCompletionProposal proposal = createPartProposal(partDeclarationInfo, getPartType(partDeclarationInfo), quoted);
if (proposal != null) proposals.add(proposal);
}
}
}
return proposals;
}
protected boolean validSubtype(PartDeclarationInfo partDeclarationInfo) {
if (subTypes != null && subTypes.length > 0) {
try {
IPart part = partDeclarationInfo.resolvePart(createScope());
if (part != null && (part instanceof SourcePart || part instanceof BinaryPart)) {
IPart sourcePart = (IPart) part;
String subTypeSignature = sourcePart.getSubTypeSignature();
if (subTypeSignature != null) {
String subtypeName = Signature.toString(subTypeSignature);
if (subtypeName == null || !validSubtype(subtypeName)) {
//do not add a proposal. Only looking for specific subtypes
return false;
}
}
else
return false;
}
} catch (EGLModelException e) {
EGLLogger.log(this, e);
return false;
}
}
return true;
}
/**
* @param subtypeName
* @return
*/
private boolean validSubtype(String subtypeName) {
for (int i = 0; i < subTypes.length; i++) {
if (subTypes[i].equalsIgnoreCase(subtypeName))
return true;
}
return false;
}
/*
* get the type of the part for the additional information
*/
protected String getPartType(PartDeclarationInfo part) {
String partTypeName;
switch (part.getPartType()) {
case IEGLSearchConstants.PROGRAM :
partTypeName = IEGLConstants.KEYWORD_PROGRAM;
break;
case IEGLSearchConstants.RECORD :
partTypeName = IEGLConstants.KEYWORD_RECORD;
break;
case IEGLSearchConstants.FUNCTION :
partTypeName = IEGLConstants.KEYWORD_FUNCTION;
break;
case IEGLSearchConstants.LIBRARY :
partTypeName = IEGLConstants.KEYWORD_LIBRARY;
break;
case IEGLSearchConstants.HANDLER :
partTypeName = IEGLConstants.KEYWORD_HANDLER;
break;
case IEGLSearchConstants.SERVICE :
partTypeName = IEGLConstants.KEYWORD_SERVICE;
break;
case IEGLSearchConstants.INTERFACE :
partTypeName = IEGLConstants.KEYWORD_INTERFACE;
break;
case IEGLSearchConstants.DELEGATE :
partTypeName = IEGLConstants.KEYWORD_DELEGATE;
break;
case IEGLSearchConstants.EXTERNALTYPE :
partTypeName = IEGLConstants.KEYWORD_EXTERNALTYPE;
break;
case IEGLSearchConstants.ENUMERATION :
partTypeName = IEGLConstants.KEYWORD_ENUMERATION;
break;
case IEGLSearchConstants.CLASS :
partTypeName = IEGLConstants.KEYWORD_CLASS;
break;
default :
partTypeName = ""; //$NON-NLS-1$
break;
}
return partTypeName;
}
/*
* search the index to find appropriate matches
*/
private List searchIndex(int types) {
List parts = new ArrayList();
try {
new SearchEngine().searchAllPartNames(
ResourcesPlugin.getWorkspace(),
null,
getPrefix().toCharArray(),
IIndexConstants.PREFIX_MATCH,
IEGLSearchConstants.CASE_INSENSITIVE,
types,
createScope(),
new PartInfoRequestor(parts),
IEGLSearchConstants.WAIT_UNTIL_READY_TO_SEARCH,
null);
} catch (EGLModelException e) {
EGLLogger.log(this, e);
}
return parts;
}
/*
* create the search scope
*/
protected IEGLSearchScope createScope() {
return createProjectSearchScope();
}
/*
* place the cursor based on the text being pasted into the document
*/
protected int getCursorPosition(PartDeclarationInfo part) {
return part.getPartName().length();
}
protected boolean isPublic(PartDeclarationInfo partInfo) {
try {
IPart type = (IPart) partInfo.resolvePart(createScope());
if (type != null) return type.isPublic();
} catch (EGLModelException e) {
EGLLogger.log(this, e);
} catch (NullPointerException e) {
return false;
}
return false;
}
protected boolean shouldInclude(PartDeclarationInfo partDeclarationInfo) {
return true;
}
}