package com.aptana.editor.php.internal.contentAssist;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.part.FileEditorInput;
import org2.eclipse.php.internal.core.compiler.ast.nodes.PHPDocBlock;
import com.aptana.editor.php.indexer.IElementEntry;
import com.aptana.editor.php.indexer.IElementsIndex;
import com.aptana.editor.php.internal.builder.LocalModule;
import com.aptana.editor.php.internal.core.builder.IModule;
import com.aptana.editor.php.internal.indexer.ClassPHPEntryValue;
import com.aptana.editor.php.internal.indexer.FunctionPHPEntryValue;
import com.aptana.editor.php.internal.indexer.PHPDocUtils;
import com.aptana.editor.php.internal.indexer.PHPTypeProcessor;
import com.aptana.editor.php.internal.indexer.VariablePHPEntryValue;
import com.aptana.editor.php.internal.parser.phpdoc.FunctionDocumentation;
import com.aptana.ui.util.UIUtils;
class EntryDocumentationResolver implements IDocumentationResolver
{
private static final String EMPTY_STRING = ""; //$NON-NLS-1$
private final String proposalContent;
private final IElementsIndex index;
private final Object val;
private final IElementEntry entry;
protected EntryDocumentationResolver(String proposalContent, IElementsIndex index, Object val, IElementEntry entry)
{
this.proposalContent = proposalContent;
this.index = index;
this.val = val;
this.entry = entry;
}
public String resolveDocumentation()
{
IDocument document = resolveDocument();
if (val instanceof FunctionPHPEntryValue)
{
FunctionPHPEntryValue pl = (FunctionPHPEntryValue) val;
PHPDocBlock findFunctionPHPDocComment = PHPDocUtils.findFunctionPHPDocComment(entry, document,
pl.getStartOffset());
StringBuffer bf = new StringBuffer();
bf.append(proposalContent);
bf.append('(');
if (!pl.getParameters().isEmpty())
{
for (String s : pl.getParameters().keySet())
{
bf.append('$');
bf.append(s);
bf.append(',');
}
bf.deleteCharAt(bf.length() - 1);
}
bf.append(')');
String sig = bf.toString();
FunctionDocumentation parseFunctionPHPDoc = (findFunctionPHPDocComment != null) ? PHPDocUtils
.getFunctionDocumentation(findFunctionPHPDocComment) : null;
String docString = PHPDocUtils.computeDocumentation(parseFunctionPHPDoc, document, sig);
String typesString = computeEntryTypesDisplayString(entry, index);
if (typesString != null && typesString.length() > 0)
{
String resolvedStr = Messages.EntryDocumentationResolver_resolvedReturnTypes;
docString += "<br><b>" + resolvedStr + "</b> " + typesString; //$NON-NLS-1$ //$NON-NLS-2$
}
return docString;
}
else if (val instanceof ClassPHPEntryValue)
{
ClassPHPEntryValue pl = (ClassPHPEntryValue) val;
PHPDocBlock findFunctionPHPDocComment = PHPDocUtils.findFunctionPHPDocComment(entry, document,
pl.getStartOffset());
StringBuffer bf = new StringBuffer();
bf.append(proposalContent);
String sig = bf.toString();
FunctionDocumentation parseFunctionPHPDoc = (findFunctionPHPDocComment != null) ? PHPDocUtils
.getFunctionDocumentation(findFunctionPHPDocComment) : null;
String docString = PHPDocUtils.computeDocumentation(parseFunctionPHPDoc, document, sig);
/*
* String typesString = computeEntryTypesDisplayString(entry, index); if (typesString != null &&
* typesString.length() > 0) { docString += "<br>Types: " + typesString; }
*/
return docString;
}
else if (val instanceof VariablePHPEntryValue)
{
VariablePHPEntryValue pl = (VariablePHPEntryValue) val;
int startOffset = pl.getStartOffset();
PHPDocBlock findFunctionPHPDocComment = PHPDocUtils.findFunctionPHPDocComment(entry, document, startOffset);
StringBuffer bf = new StringBuffer();
bf.append(proposalContent);
String sig = bf.toString();
FunctionDocumentation parseFunctionPHPDoc = (findFunctionPHPDocComment != null) ? PHPDocUtils
.getFunctionDocumentation(findFunctionPHPDocComment) : null;
if (pl.isParameter())
{
parseFunctionPHPDoc = null;
}
String docString = PHPDocUtils.computeDocumentation(parseFunctionPHPDoc, document, sig);
String typesString = computeEntryTypesDisplayString(entry, index);
if (typesString != null && typesString.length() > 0)
{
String resolvedStr = Messages.EntryDocumentationResolver_resolvedTypes;
docString += "<br><b>" + resolvedStr + "</b> " + typesString; //$NON-NLS-1$ //$NON-NLS-2$
}
return docString;
}
return null;
}
/**
* Resolves the right document to be used when computing the documentation out of an IDocument (happens when the
* docs are in an opened editor).<br>
* The method retrieves the entry's {@link IModule}, and in case it's a local module, tries to locate an open editor
* that match the input on that module.
*
* @return An {@link IDocument} or <code>null</code>
*/
protected IDocument resolveDocument()
{
IDocument document = null;
if (entry != null)
{
IModule module = entry.getModule();
if (!(module instanceof LocalModule))
{
return null;
}
IWorkbenchPage activePage = UIUtils.getActivePage();
if (activePage != null)
{
IFile moduleFile = ((LocalModule) module).getFile();
// locate an open editor.
IEditorPart editor = activePage.findEditor(new FileEditorInput(moduleFile));
if (editor != null)
{
ISourceViewer sourceViewer = (ISourceViewer) editor.getAdapter(ISourceViewer.class);
if (sourceViewer != null)
{
document = sourceViewer.getDocument();
}
}
}
}
return document;
}
/**
* Computes display string for the entry types (performs types eveluation if needed).
*
* @param entry
* - entry.
* @return display string
*/
private static String computeEntryTypesDisplayString(IElementEntry entry, IElementsIndex indexer)
{
Object entryValue = entry.getValue();
if (entryValue instanceof ClassPHPEntryValue)
{
return EMPTY_STRING;
}
else if (entryValue instanceof FunctionPHPEntryValue)
{
Set<Object> returnTypes = ((FunctionPHPEntryValue) entryValue).getReturnTypes();
if (returnTypes == null || returnTypes.size() == 0)
{
return EMPTY_STRING;
}
Set<String> resolvedTypes = PHPTypeProcessor.processTypes(returnTypes, indexer);
if (resolvedTypes.size() == 0)
{
return EMPTY_STRING;
}
List<String> typesList = new ArrayList<String>(resolvedTypes.size());
typesList.addAll(resolvedTypes);
return getTypesDisplayString(typesList, entry);
}
else if (entryValue instanceof VariablePHPEntryValue)
{
Set<Object> variableTypes = ((VariablePHPEntryValue) entryValue).getTypes();
if (variableTypes == null || variableTypes.size() == 0)
{
return EMPTY_STRING;
}
Set<String> resolvedTypes = PHPTypeProcessor.processTypes(variableTypes, indexer);
if (resolvedTypes.size() == 0)
{
return EMPTY_STRING;
}
List<String> typesList = new ArrayList<String>(resolvedTypes.size());
typesList.addAll(resolvedTypes);
return getTypesDisplayString(typesList, entry);
}
else
{
return EMPTY_STRING;
}
}
/**
* Gets display string for the list of types.
*
* @param types
* - types.
* @return display string
*/
private static String getTypesDisplayString(List<String> types, IElementEntry entry)
{
List<String> sortedTypes = new ArrayList<String>(types.size());
sortedTypes.addAll(types);
Collections.sort(sortedTypes);
StringBuilder result = new StringBuilder();
for (int i = 0; i < sortedTypes.size() - 1; i++)
{
String type = sortedTypes.get(i);
result.append(type);
result.append(", "); //$NON-NLS-1$
}
result.append(sortedTypes.get(sortedTypes.size() - 1));
return ContentAssistUtils.truncateLineIfNeeded(result.toString());
}
/*
* (non-Javadoc)
* @see com.aptana.editor.php.internal.contentAssist.IDocumentationResolver#getProposalContent()
*/
public String getProposalContent()
{
return this.proposalContent;
}
}