package org.eclipse.dltk.tcl.internal.ui;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.dltk.ast.declarations.ModuleDeclaration;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.DLTKLanguageManager;
import org.eclipse.dltk.core.IDLTKLanguageToolkit;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.core.SourceParserUtil;
import org.eclipse.dltk.internal.ui.editor.EditorUtility;
import org.eclipse.dltk.internal.ui.text.hover.AbstractScriptEditorTextHover;
import org.eclipse.dltk.tcl.ast.TclModule;
import org.eclipse.dltk.tcl.ast.TclModuleDeclaration;
import org.eclipse.dltk.tcl.core.TclNature;
import org.eclipse.dltk.tcl.core.TclPackagesManager;
import org.eclipse.dltk.tcl.core.packages.TclModuleInfo;
import org.eclipse.dltk.tcl.core.packages.TclSourceEntry;
import org.eclipse.dltk.tcl.core.packages.UserCorrection;
import org.eclipse.dltk.tcl.indexing.PackageSourceCollector;
import org.eclipse.dltk.tcl.parser.TclParser;
import org.eclipse.dltk.tcl.parser.definitions.DefinitionManager;
import org.eclipse.emf.common.util.EList;
import org.eclipse.jface.text.AbstractReusableInformationControlCreator;
import org.eclipse.jface.text.DefaultInformationControl;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IInformationControlCreator;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.swt.widgets.Shell;
public class PackagesSourcesHover extends AbstractScriptEditorTextHover {
@Override
public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
final IModelElement inputModelElement = EditorUtility
.getEditorInputModelElement(this.getEditor(), false);
if (inputModelElement == null) {
return null;
}
final IDLTKLanguageToolkit toolkit = DLTKLanguageManager
.getLanguageToolkit(inputModelElement);
if (toolkit == null) {
return null;
}
if (!TclNature.NATURE_ID.equals(toolkit.getNatureId())) {
return null;
}
// This is correct tcl module, so lets locate package at specified
// location.
final ISourceModule sourceModule = (ISourceModule) inputModelElement
.getAncestor(IModelElement.SOURCE_MODULE);
final TclModuleInfo info = extractPackageSourceInfo(sourceModule);
if (info == null) {
return null;
}
final TclModuleInfo moduleInfo = loadModuleInfo(sourceModule);
if (moduleInfo == null) {
return null;
}
for (TclSourceEntry entry : info.getSourced()) {
if (entry.getStart() <= hoverRegion.getOffset()
&& hoverRegion.getOffset() <= entry.getEnd()) {
final String hover = describe(entry,
moduleInfo.getSourceCorrections(),
"Source information:");
if (hover != null) {
return hover;
}
}
}
for (TclSourceEntry entry : info.getRequired()) {
if (entry.getStart() <= hoverRegion.getOffset()
&& hoverRegion.getOffset() <= entry.getEnd()) {
final String hover = describe(entry,
moduleInfo.getPackageCorrections(),
"Require information:");
if (hover != null) {
return null;
}
}
}
return null;
}
private String describe(TclSourceEntry entry,
EList<UserCorrection> corrections, String caption) {
StringBuilder buffer = new StringBuilder(256);
buffer.append(caption);
boolean added = false;
for (UserCorrection userCorrection : corrections) {
if (userCorrection.getOriginalValue().equals(entry.getValue())) {
List<String> userValue = new ArrayList<>(
userCorrection.getUserValue());
Collections.sort(userValue);
buffer.append("<ul>"); //$NON-NLS-1$
for (String value : userValue) {
buffer.append("<li>").append(value).append("</li>"); //$NON-NLS-1$ //$NON-NLS-2$
added = true;
}
buffer.append("</ul>"); //$NON-NLS-1$
}
}
if (added) {
return buffer.toString();
}
return null;
}
private TclModuleInfo extractPackageSourceInfo(ISourceModule sourceModule) {
final TclModule module = parse(sourceModule);
if (module != null) {
final PackageSourceCollector collector = new PackageSourceCollector();
collector.process(module.getStatements(), sourceModule);
return collector.getCurrentModuleInfo();
}
return null;
}
private TclModule parse(final ISourceModule sourceModule) {
final ModuleDeclaration declaration = SourceParserUtil
.getModuleDeclaration(sourceModule);
if (declaration instanceof TclModuleDeclaration) {
return ((TclModuleDeclaration) declaration).getTclModule();
} else {
TclParser parser = new TclParser();
try {
return parser.parseModule(sourceModule.getSource(), null,
DefinitionManager.getInstance().createProcessor());
} catch (ModelException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
return null;
}
}
}
private TclModuleInfo loadModuleInfo(ISourceModule sourceModule) {
final List<TclModuleInfo> projectModules = TclPackagesManager
.getProjectModules(
sourceModule.getScriptProject().getElementName());
final String handle = sourceModule.getHandleIdentifier();
for (TclModuleInfo tclModuleInfo : projectModules) {
if (tclModuleInfo.getHandle().equals(handle)) {
return tclModuleInfo;
}
}
return null;
}
@Override
public IInformationControlCreator getHoverControlCreator() {
return new AbstractReusableInformationControlCreator() {
@Override
protected IInformationControl doCreateInformationControl(
Shell parent) {
DefaultInformationControl ctrl = new DefaultInformationControl(
parent, false);
return ctrl;
}
};
}
}