/* * Copyright (c) 2013 QNX Software Systems 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 */ package org.eclipse.cdt.internal.qt.ui.assist; import org.eclipse.cdt.core.dom.ast.IASTCompletionNode; import org.eclipse.cdt.internal.corext.template.c.CContext; import org.eclipse.cdt.ui.text.contentassist.ICEditorContentAssistInvocationContext; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.Position; import org.eclipse.jface.text.templates.Template; import org.eclipse.jface.text.templates.TemplateContextType; import org.eclipse.swt.graphics.Point; @SuppressWarnings("restriction") public class QtProposalContext extends CContext { private final String contextId; public QtProposalContext(ICEditorContentAssistInvocationContext context, TemplateContextType ctxType) { super(ctxType, context.getDocument(), getCompletionPosition(context), context.getTranslationUnit()); this.contextId = ctxType.getId(); } private static Position getCompletionPosition(ICEditorContentAssistInvocationContext context) { // The normal CDT behaviour is to not offer template proposals when text is selected. I // don't know why they avoid it, so I've opted to replace the selection instead. int adjustment = 0; IASTCompletionNode node = context.getCompletionNode(); if (node != null) { String prefix = node.getPrefix(); if (prefix != null) adjustment -= prefix.length(); } int length = -adjustment; ITextViewer viewer = context.getViewer(); if (viewer != null) { Point selection = viewer.getSelectedRange(); if (selection != null && selection.y > 0) length += selection.y; } int offset = context.getInvocationOffset() + adjustment; return new Position(offset, length); } @Override public boolean canEvaluate(Template template) { // The base implementation uses a length of 0 to create an empty string for the key // and then refuses to apply the template. This override offers all templates that // have the right ID. This is ok, because only the templates that apply were proposed. return contextId.equals(template.getContextTypeId()); } @Override public int getStart() { // The base implementation creates a different offset when the replacement length // is not 0. We need to use the same start of the replacement region regardless of // whether or not characters are selected. try { IDocument document= getDocument(); int start= getCompletionOffset(); int end= getCompletionOffset() + getCompletionLength(); while (start != 0 && isUnicodeIdentifierPartOrPoundSign(document.getChar(start - 1))) start--; while (start != end && Character.isWhitespace(document.getChar(start))) start++; if (start == end) start= getCompletionOffset(); return start; } catch (BadLocationException e) { return super.getStart(); } } private boolean isUnicodeIdentifierPartOrPoundSign(char c) { return Character.isUnicodeIdentifierPart(c) || c == '#'; } }