blob: 4f7ae49165d8147a3da7a35447e52c3434e2f38c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009 University of Illinois at Urbana-Champaign 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:
* UIUC - Initial API and implementation
*******************************************************************************/
package org.eclipse.photran.internal.ui.editor_vpg.contentassist;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.TreeMap;
import java.util.TreeSet;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.templates.DocumentTemplateContext;
import org.eclipse.jface.text.templates.Template;
import org.eclipse.jface.text.templates.TemplateProposal;
import org.eclipse.photran.internal.core.analysis.binding.Definition;
import org.eclipse.photran.internal.core.analysis.binding.Definition.Classification;
import org.eclipse.photran.internal.core.intrinsics.IntrinsicProcDescription;
import org.eclipse.photran.internal.core.intrinsics.Intrinsics;
import org.eclipse.photran.internal.core.model.FortranElement;
import org.eclipse.photran.internal.core.vpg.PhotranVPG;
import org.eclipse.photran.internal.ui.FortranTemplateManager;
import org.eclipse.photran.internal.ui.editor.CompletionComputer;
import org.eclipse.photran.internal.ui.editor.FortranTemplateContext;
import org.eclipse.swt.graphics.Image;
/**
* Computes the list of items be shown in the content assist list.
*
* @author Jeff Overbey
*
* @see FortranCompletionProcessor#computeCompletionProposals(org.eclipse.jface.text.ITextViewer, int)
*/
class FortranCompletionProposalComputer extends CompletionComputer
{
private HashMap<String, TreeSet<Definition>> defs;
private String scope;
FortranCompletionProposalComputer(HashMap<String, TreeSet<Definition>> defs, String scope, IDocument document, int offset) throws BadLocationException
{
super(document, offset);
this.defs = defs;
this.scope = scope;
}
public List<ICompletionProposal> proposalsFromDefs() throws BadLocationException
{
TreeSet<FortranCompletionProposal> proposals = new TreeSet<FortranCompletionProposal>();
for (;;)
{
addProposals(defs.get(scope), proposals);
int colon = scope.indexOf(':');
if (colon < 0)
break;
else
scope = scope.substring(colon+1);
}
return toProposalArray(proposals);
}
private List<ICompletionProposal> toProposalArray(TreeSet<FortranCompletionProposal> proposals)
{
List<ICompletionProposal> result = new ArrayList<ICompletionProposal>(proposals.size());
for (FortranCompletionProposal p : proposals)
result.add(p.wrappedProposal);
return result;
}
private void addProposals(Iterable<Definition> proposalsToConsider,
TreeSet<FortranCompletionProposal> proposals)
throws BadLocationException
{
if (proposalsToConsider != null)
{
for (Definition def : proposalsToConsider)
{
if (def.getClassification().equals(Classification.MAIN_PROGRAM))
continue;
String identifier = def.getDeclaredName();
String canonicalizedId = def.getCanonicalizedName();
if (canonicalizedId.startsWith(prefix) && canonicalizedId.endsWith(suffix))
proposals.add(createProposal(identifier,
def.describeClassification(),
getImage(def.getClassification())));
}
}
}
public List<ICompletionProposal> proposalsFromIntrinsics() throws BadLocationException
{
TreeSet<FortranCompletionProposal> proposals = new TreeSet<FortranCompletionProposal>();
for (IntrinsicProcDescription proc : Intrinsics.getAllIntrinsicProcedures())
{
String canonicalizedId = PhotranVPG.canonicalizeIdentifier(proc.genericName);
if (canonicalizedId.startsWith(prefix) && canonicalizedId.endsWith(suffix))
{
//proposals.add(createProposal(proc.genericName.toLowerCase(), proc.description));
for (String proposal : proc.getAllForms())
{
proposals.add(createProposal(proposal.toLowerCase(), proc.description));
}
}
}
return toProposalArray(proposals);
}
private HashMap<Classification, Image> imageCache = new HashMap<Classification, Image>();
private Image getImage(Classification classification)
{
if (!imageCache.containsKey(classification))
imageCache.put(classification, getImageDescriptor(classification).createImage());
return imageCache.get(classification);
}
private ImageDescriptor getImageDescriptor(Classification classification)
{
switch (classification)
{
case VARIABLE_DECLARATION:
case IMPLICIT_LOCAL_VARIABLE:
case DERIVED_TYPE_COMPONENT:
return FortranElement.Variable.imageDescriptor();
case BLOCK_DATA:
return FortranElement.BlockData.imageDescriptor();
case DERIVED_TYPE:
return FortranElement.DerivedType.imageDescriptor();
case FUNCTION:
return FortranElement.Function.imageDescriptor();
case INTERFACE:
return FortranElement.Interface.imageDescriptor();
case MAIN_PROGRAM:
return FortranElement.MainProgram.imageDescriptor();
case MODULE:
return FortranElement.Module.imageDescriptor();
case SUBROUTINE:
return FortranElement.Subroutine.imageDescriptor();
default:
return FortranElement.unknownImageDescriptor();
}
}
// private FortranCompletionProposal createProposal(String identifier)
// {
// return createProposal(identifier, null, null);
// }
private FortranCompletionProposal createProposal(String identifier, String description)
{
return createProposal(identifier, description, null);
}
private FortranCompletionProposal createProposal(String identifier, String description, Image image)
{
// return new FortranCompletionProposal(
// identifier,
// new CompletionProposal(identifier,
// replOffset,
// replLen,
// identifier.length(),
// image,
// displayString(identifier, description),
// null,
// null));
return new FortranCompletionProposal(
identifier,
new TemplateProposal(new Template(
identifier,
description == null ? "" : description, //$NON-NLS-1$
FortranTemplateContext.ID,
replaceArgumentsWithTemplateVariables(identifier),
true),
new DocumentTemplateContext(
FortranTemplateManager.getInstance().getContextTypeRegistry().getContextType(FortranTemplateContext.ID),
document,
replOffset,
replLen),
new Region(replOffset, replLen),
image,
100));
}
/**
* Converts "len(string, kind)" into "len(${string}, ${kind})", for example
*/
private String replaceArgumentsWithTemplateVariables(String string)
{
if (string.contains("(") && string.contains(")") && string.endsWith(")")) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
{
int lparen = string.indexOf('(');
int rparen = string.lastIndexOf(')'); // == string.length()-1
String name = string.substring(0, lparen);
String[] args = string.substring(lparen+1, rparen).split(","); //$NON-NLS-1$
StringBuilder sb = new StringBuilder(string.length() + 16);
sb.append(name);
sb.append('(');
for (int i = 0; i < args.length; i++)
{
if (i > 0) sb.append(", "); //$NON-NLS-1$
sb.append("${"); //$NON-NLS-1$
sb.append(args[i].trim().replace(' ', '_'));
sb.append('}');
}
sb.append(')');
return sb.toString();
}
else return string;
}
// private String displayString(String identifier, String description)
// {
// if (description == null)
// return identifier;
// else
// return identifier + " - " + description; //$NON-NLS-1$
// }
/**
* A single proposal which will appear in the content assist list.
* <p>
* This class implements {@link Comparable} so that instances can be stored in a
* {@link TreeMap}. This ensures that the resulting list will be sorted alphabetically.
*
* @author Jeff Overbey
*/
private static class FortranCompletionProposal implements Comparable<FortranCompletionProposal>
{
public final String canonicalizedId;
public final ICompletionProposal wrappedProposal;
public FortranCompletionProposal(String identifier, ICompletionProposal proposal)
{
this.canonicalizedId = PhotranVPG.canonicalizeIdentifier(identifier);
this.wrappedProposal = proposal;
}
public int compareTo(FortranCompletionProposal o)
{
return canonicalizedId.compareTo(o.canonicalizedId);
}
@Override public boolean equals(Object obj)
{
return obj != null
&& obj.getClass().equals(this.getClass())
&& ((FortranCompletionProposal)obj).canonicalizedId.equals(this.canonicalizedId);
}
@Override public int hashCode()
{
return canonicalizedId.hashCode();
}
}
}