/*******************************************************************************
* Copyright (c) 2010 Martin Schnabel <mb0@mb0.org>.
* 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
******************************************************************************/
package org.axdt.as3.ui.contentassist;
import java.util.Collections;
import java.util.List;
import org.axdt.as3.model.As3ImportList;
import org.axdt.as3.model.As3Package;
import org.axdt.as3.model.As3Program;
import org.axdt.as3.model.IDirective;
import org.axdt.as3.scoping.As3ImportScopeProvider;
import org.axdt.avm.model.AvmDefinitionContainer;
import org.axdt.avm.naming.AvmQualifiedNameConverter;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.swt.graphics.Image;
import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.eclipse.xtext.scoping.impl.ImportNormalizer;
import org.eclipse.xtext.ui.editor.contentassist.ConfigurableCompletionProposal;
/**
* @author mb0
*/
public class As3QualifiedCompletionProposal extends
ConfigurableCompletionProposal {
protected String quali;
protected final EObject currentModel;
private As3ImportScopeProvider importScopeProvider;
public As3QualifiedCompletionProposal(String proposal, As3ImportScopeProvider importScopeProvider,
EObject currentModel, int replacementOffset, int replacementLength,
int length, Image image, StyledString displayString) {
super(proposal, replacementOffset, replacementLength, length, image,
displayString, null, null);
this.importScopeProvider = importScopeProvider;
this.currentModel = currentModel;
}
@Override
public void selected(ITextViewer viewer, boolean smartToggle) {
super.selected(viewer, smartToggle);
}
public void checkImports() {
AvmQualifiedNameConverter converter = new AvmQualifiedNameConverter();
String replacementString = getReplacementString();
QualifiedName qname = converter.toQualifiedName(replacementString);
for (ImportNormalizer norm:getImportNormalizers(currentModel)) {
QualifiedName name = norm.deresolve(qname);
if (name != null && name.getSegmentCount() == 1) {
setReplacementString(name.toString());
return;
}
}
quali = qname.skipLast(1).toString();
String newReplacement = qname.getLastSegment();
setReplacementString(newReplacement);
setCursorPosition(getCursorPosition()-quali.length()-1);
}
protected List<ImportNormalizer> getImportNormalizers(EObject context) {
if (importScopeProvider != null) {
EObject current = context;
while (current != null) {
if (importScopeProvider.hasImports(current)) break;
current = current.eContainer();
}
return importScopeProvider.getImportResolvers(context, false);
}
return Collections.emptyList();
}
@Override
public void apply(IDocument document) {
checkImports();
if (quali != null) {
try {
int importOffset = getImportOffset(currentModel);
if (importOffset != -1) {
IRegion line = document
.getLineInformationOfOffset(importOffset);
String indentation = document.get(line.getOffset(),
importOffset - line.getOffset());
if (indentation.trim().length() != 0)
indentation = "";
String importString = "import " + quali + "."
+ getReplacementString() + ";\n" + indentation;
int otherOffset = getReplacementOffset();
if (importOffset < otherOffset)
setReplacementOffset(otherOffset + importString.length());
document.replace(importOffset, 0, importString);
}
} catch (BadLocationException x) {
// ignore
}
}
super.apply(document);
}
protected int getImportOffset(EObject currentModel) {
AvmDefinitionContainer container = getDefinitionContainer(currentModel);
if (container != null) {
for (EObject child : container.eContents()) {
if (child instanceof As3ImportList) {
// TODO find better import position
return NodeModelUtils.getNode(child).getOffset();
}
}
return getDefaultOffset(container);
}
return -1;
}
protected int getDefaultOffset(AvmDefinitionContainer container) {
EList<IDirective> directives = null;
if (container instanceof As3Package)
directives = ((As3Package) container).getDirectives();
else if (container instanceof As3Program)
directives = ((As3Program) container).getDirectives();
if (directives != null && !directives.isEmpty())
return NodeModelUtils.getNode(directives.get(0)).getOffset();
return -1;
}
protected AvmDefinitionContainer getDefinitionContainer(EObject current) {
for (; current != null; current = current.eContainer())
if (current instanceof AvmDefinitionContainer)
return (AvmDefinitionContainer) current;
return null;
}
}