/*
* #%~
* org.overture.ide.ui
* %%
* Copyright (C) 2008 - 2014 Overture
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #~%
*/
package org.overture.ide.ui.templates;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.CompletionProposal;
import org.eclipse.jface.text.contentassist.ContextInformation;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.templates.TemplateContext;
import org.overture.ast.analysis.AnalysisException;
import org.overture.ast.analysis.DepthFirstAnalysisAdaptor;
import org.overture.ast.definitions.ATypeDefinition;
import org.overture.ast.definitions.PDefinition;
import org.overture.ast.definitions.SClassDefinition;
import org.overture.ast.expressions.AQuoteLiteralExp;
import org.overture.ast.expressions.PExp;
import org.overture.ast.modules.AModuleModules;
import org.overture.ast.node.INode;
import org.overture.ast.statements.PStm;
import org.overture.ast.types.AFieldField;
import org.overture.ast.types.AProductType;
import org.overture.ast.types.AQuoteType;
import org.overture.ast.types.ARecordInvariantType;
import org.overture.ast.types.PType;
import org.overture.ide.ui.VdmUIPlugin;
import org.overture.ide.ui.editor.core.VdmDocument;
import org.overture.ide.ui.internal.viewsupport.VdmElementImageProvider;
import org.overture.ide.ui.utility.ast.AstLocationSearcher2;
import org.overture.ide.ui.utility.ast.AstLocationSearcher2.TextReference;
import org.overture.ide.ui.utility.ast.AstNameUtil;
public class VdmCompleteProcessor
{
private VdmElementImageProvider imgProvider = new VdmElementImageProvider();
private VdmCompletionHelper VdmHelper = new VdmCompletionHelper();
private ArrayList<String> MkDynamicTemplateProposals = new ArrayList<String>();
public void computeCompletionProposals(VdmCompletionContext info,
VdmDocument document, List<ICompletionProposal> proposals,
int offset, ITextViewer viewer,TemplateContext context)
{
List<ICompletionProposal> calculatedProposals = new Vector<ICompletionProposal>();
VdmCompletionExtractor vdmCompletionExtractor = new VdmCompletionExtractor();
VdmNewCompletionExtractor vdmNewCompletionExtractor = new VdmNewCompletionExtractor();
switch (info.getType())
{
case CallParam:
break;
case Dot:
break;
case Mk:
completeMK(info, document, calculatedProposals, offset, context, viewer);
break;
case New:
vdmNewCompletionExtractor.generateNewCompletionProposals(info, document, calculatedProposals, offset, getAst(document), context, viewer);
break;
case Quote:
completeQuotes(info, document, calculatedProposals, offset);
break;
case Types:
completeTypes(info, document, calculatedProposals, offset);
vdmCompletionExtractor.generateCompleteProposals(info, document, calculatedProposals, offset, getAst(document), context,viewer);
break;
default:
break;
}
List<String> replacementDisplayString = new Vector<String>();
for (ICompletionProposal proposal : calculatedProposals)
{
if (proposal instanceof CompletionProposal)
{
CompletionProposal cp = (CompletionProposal) proposal;
if (replacementDisplayString.contains(cp.getDisplayString()))
{
continue;
}
replacementDisplayString.add(cp.getDisplayString());
}
proposals.add(proposal);
}
}
private void completeMK(VdmCompletionContext info, VdmDocument document,
List<ICompletionProposal> calculatedProposals, int offset, final TemplateContext context,final ITextViewer viewer) {
for(INode def : getAst(document))
{
completeRecords(offset, calculatedProposals, info, def, context, viewer);
completeMk_tokens(offset,calculatedProposals,info, def);
completetuples(offset, calculatedProposals, info,def);
}
}
private void completeQuotes(final VdmCompletionContext info,
VdmDocument document, final List<ICompletionProposal> proposals,
int offset)
{
for (INode def : getAst(document))
{
completeQuotes(offset, proposals, info, def);
}
}
private void completeRecords(final int offset,
final List<ICompletionProposal> calculatedProposals,
VdmCompletionContext info, final INode def, final TemplateContext context,final ITextViewer viewer) {
try {
def.apply(new DepthFirstAnalysisAdaptor() {
@Override
public void caseARecordInvariantType(ARecordInvariantType arg0)
throws AnalysisException {
String name = arg0.getName().getName();
String[] functionName = {name, (name + "(")};
String displayString = functionName[1];
String sep = "";
List<String> parameterNameList = new ArrayList<String>();
for (Iterator<AFieldField> iterator = arg0.getFields().iterator(); iterator.hasNext();)
{
AFieldField field = iterator.next();
parameterNameList.add(field.getTagname().getName());
displayString += sep + field.toString();
sep = ", ";
}
String extractedName[] = VdmHelper.templatePatternGenerator(parameterNameList,functionName);
extractedName[0] = displayString + ")";
if(VdmHelper.nullOrEmptyCheck(extractedName[1]) && !VdmHelper.checkForDuplicates(extractedName[1],MkDynamicTemplateProposals)){
VdmHelper.dynamicTemplateCreator(extractedName,"MK Record",offset,context,calculatedProposals,info,viewer,arg0.getLocation().getEndOffset());
MkDynamicTemplateProposals.add(extractedName[1]);
}
}
});
} catch (AnalysisException e) {
VdmUIPlugin.log("Completion error in " + getClass().getSimpleName()
+ "faild during record search", e);
}
}
private void completetuples(final int offset,
final List<ICompletionProposal> calculatedProposals,
final VdmCompletionContext info, final INode def) {
try
{
def.apply(new DepthFirstAnalysisAdaptor() {
@Override
public void caseAProductType(AProductType arg0)
throws AnalysisException {
String name = arg0.toString();
IContextInformation info = new ContextInformation(name, name);
String replacementString = "(";
//String display = replacementString;
String sep = "";
for(Iterator<PDefinition> iterator = arg0.getDefinitions().iterator(); iterator.hasNext();)
{
PDefinition type = iterator.next();
replacementString += sep + type.getType();
//display += sep + type.toString();
sep = ", ";
}
replacementString += ")";
//display += ")";
calculatedProposals.add(new CompletionProposal(replacementString , offset, 0, replacementString.length(), imgProvider.getImageLabel(def, 0), replacementString, info, replacementString));
}
});
}
catch(AnalysisException e)
{
VdmUIPlugin.log("Completion error in " + getClass().getSimpleName()
+ "faild during tuple search", e);
}
//
}
private void completeMk_tokens(final int offset,
final List<ICompletionProposal> calculatedProposals,
final VdmCompletionContext info, INode def) {
String name = "token()";
String display = "mk_token() Token Representation, can take an arbitary expression";
IContextInformation ctxtInfo = new ContextInformation(name, name); //$NON-NLS-1$
calculatedProposals.add(new CompletionProposal(name, offset, 0, name.length() - 1, imgProvider.getImageLabel(def, 0), name, ctxtInfo, display));
}
public void completeTypes(VdmCompletionContext info, VdmDocument document,
List<ICompletionProposal> proposals, int offset)
{
for (INode element : getAst(document))
{
if (info.getType() == SearchType.Types)
{
String name = AstNameUtil.getName(element);
String prefix = info.getProposalPrefix();
if (VdmHelper.findInString(prefix, name) || name.length() == 0)
{
IContextInformation ctxtInfo = new ContextInformation(name, name); //$NON-NLS-1$
int newOffset = offset - prefix.length();
int prefixLength = prefix.length();
proposals.add(new CompletionProposal(name, newOffset, prefixLength, name.length(), imgProvider.getImageLabel(element, 0), name, ctxtInfo, name));
}
}
//addContainerTypes(element, offset, proposals, info);
}
}
private void addContainerTypes(INode def, final int offset,
final List<ICompletionProposal> proposals,
final VdmCompletionContext info)
{
if (def instanceof SClassDefinition)
{
SClassDefinition cd = (SClassDefinition) def;
for (PDefinition element : cd.getDefinitions())
{
if (element instanceof ATypeDefinition)
{
String name = cd.getName() + "`" + element.getName();
IContextInformation contextInfo = new ContextInformation(name, name); //$NON-NLS-1$
if (VdmHelper.findInString(info.getProposalPrefix(), name) || name.length() == 0)
{
proposals.add(new CompletionProposal(name, offset, 0, name.length(), imgProvider.getImageLabel(element, 0), name, contextInfo, name));
}
}
}
completeQuotes(offset, proposals, info, def);
} else if (def instanceof AModuleModules)
{
AModuleModules m = (AModuleModules) def;
for (PDefinition element : m.getDefs())
{
String prefix = "";
if (element.getAncestor(AModuleModules.class) != def)
{
prefix = m.getName() + "`";
}
if (element instanceof ATypeDefinition)
{
String name = prefix + element.getName();
IContextInformation contextInfo = new ContextInformation(name, name); //$NON-NLS-1$
if (name.toLowerCase().startsWith(info.getProposalPrefix().toLowerCase()))
{
proposals.add(new CompletionProposal(name, offset
- info.getProposalPrefix().length(), info.getProposalPrefix().length(), name.length(), imgProvider.getImageLabel(element, 0), name, contextInfo, element.toString()));
}
}
}
completeQuotes(offset, proposals, info, m);
}
}
private void completeQuotes(final int offset,
final List<ICompletionProposal> proposals,
final VdmCompletionContext info2, INode m)
{
try
{
m.apply(new DepthFirstAnalysisAdaptor()
{
@Override
public void caseAQuoteLiteralExp(AQuoteLiteralExp node)
throws AnalysisException
{
populateQuotes(node, node.getValue().getValue(), node.toString());
}
@Override
public void caseAQuoteType(AQuoteType node)
throws AnalysisException
{
populateQuotes(node, node.getValue().getValue(), node.toString());
}
void populateQuotes(INode node, String baseValue, String name)
{
IContextInformation info = new ContextInformation(name, name); //$NON-NLS-1$
int curOffset = offset + info2.getReplacementOffset();// - info2.proposalPrefix.length();
int length = name.length();
int replacementLength = info2.getProposalPrefix().length();
if (info2.getProposalPrefix().equals("<" + baseValue + ">"))
{
curOffset = offset;
replacementLength = 0;
}
if (("<" + baseValue).toLowerCase().startsWith(info2.getProposalPrefix().toLowerCase()))
{
proposals.add(new CompletionProposal(name, curOffset, replacementLength, length, imgProvider.getImageLabel(node, 0), name, info, name));
}
}
});
} catch (AnalysisException e)
{
VdmUIPlugin.log("Completion error in " + getClass().getSimpleName()
+ "faild during quote search", e);
}
}
public void completeFields(VdmCompletionContext info, VdmDocument document,
List<ICompletionProposal> proposals, int offset)
{
try
{
INode found = new AstLocationSearcher2().getNode(new TextReference(document.getSourceUnit().getSystemFile(), offset), getLocalFileAst(document));
if (found != null)
{
PType type = null;
if (found instanceof PExp)
{
type = ((PExp) found).getType();
} else if (found instanceof PStm)
{
type = ((PStm) found).getType();
}
if (type instanceof ARecordInvariantType)
{
ARecordInvariantType rt = (ARecordInvariantType) type;
for (AFieldField field : rt.getFields())
{
if (field.getTag().toLowerCase().startsWith(info.getProposalPrefix().toLowerCase()))
{
proposals.add(createProposal(field, offset, info));
}
}
}
}
} catch (Exception e)
{
VdmUIPlugin.log("Completion error in " + getClass().getSimpleName(), e);
}
}
private ICompletionProposal createProposal(INode node, int offset,
VdmCompletionContext info)
{
String name = AstNameUtil.getName(node);
if (node instanceof ATypeDefinition)
{
name = ((ATypeDefinition) node).getLocation().getModule() + "`"
+ name;
}
IContextInformation info2 = new ContextInformation(name, name); //$NON-NLS-1$
return new CompletionProposal(name, offset
- info.getProposalPrefix().length(), info.getProposalPrefix().length(), name.length(), imgProvider.getImageLabel(node, 0), name, info2, node.toString());
}
private List<INode> getAst(VdmDocument document)
{
List<INode> ast = new Vector<INode>();
ast.addAll(document.getProject().getModel().getRootElementList());
ast.addAll(document.getSourceUnit().getParseList());// maybe add broken parse tree
return ast;
}
private List<INode> getLocalFileAst(VdmDocument document)
{
List<INode> ast = new Vector<INode>();
ast.addAll(document.getSourceUnit().getParseList());
return ast;
}
}