/******************************************************************************* * Copyright (c) 2016 Pivotal, Inc. * 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 * * Contributors: * Pivotal, Inc. - initial API and implementation *******************************************************************************/ package org.springframework.ide.eclipse.editor.support.yaml.completions; import org.eclipse.jface.text.IDocument; import org.springframework.ide.eclipse.editor.support.completions.CompletionFactory; import org.springframework.ide.eclipse.editor.support.hover.HoverInfo; import org.springframework.ide.eclipse.editor.support.util.DocumentRegion; import org.springframework.ide.eclipse.editor.support.util.DocumentUtil; import org.springframework.ide.eclipse.editor.support.util.PrefixFinder; import org.springframework.ide.eclipse.editor.support.yaml.YamlDocument; import org.springframework.ide.eclipse.editor.support.yaml.path.YamlPath; import org.springframework.ide.eclipse.editor.support.yaml.structure.YamlStructureParser.SDocNode; import org.springframework.ide.eclipse.editor.support.yaml.structure.YamlStructureParser.SKeyNode; import org.springframework.ide.eclipse.editor.support.yaml.structure.YamlStructureParser.SNode; import org.springframework.ide.eclipse.editor.support.yaml.structure.YamlStructureParser.SNodeType; import org.springframework.ide.eclipse.editor.support.yaml.structure.YamlStructureParser.SRootNode; /** * @author Kris De Volder */ public abstract class AbstractYamlAssistContext implements YamlAssistContext { /** * Delete a content assist query from the document, and also the line of * text in the document that contains it, if that line of text contains just the * query surrounded by whitespace. */ public static void deleteQueryAndLine(YamlDocument doc, String query, int queryOffset, YamlPathEdits edits) throws Exception { edits.delete(queryOffset, query); String wholeLine = doc.getLineTextAtOffset(queryOffset); if (wholeLine.trim().equals(query.trim())) { edits.deleteLineBackwardAtOffset(queryOffset); } } public final int documentSelector; public final YamlPath contextPath; private static PrefixFinder prefixfinder = new PrefixFinder() { protected boolean isPrefixChar(char c) { return !Character.isWhitespace(c); } }; protected final String getPrefix(YamlDocument doc, SNode node, int offset) { //For value completions... in general we would like to determine the whole text // corresponding to the value, so a simplistic backwards scan isn't good enough. // instead we should use offset in current node / structure to determine the // the start of the current value. if (node.getNodeType()==SNodeType.KEY) { SKeyNode keyNode = (SKeyNode) node; if (keyNode.isInValue(offset)) { int valueStart = keyNode.getColonOffset()+1; while (valueStart<=offset && Character.isWhitespace(doc.getChar(valueStart))) { valueStart++; } if (offset>=valueStart) { return doc.textBetween(valueStart, offset); } else { //only whitespace, or nothing found upto the cursor return ""; } } // } else if (node.getNodeType()==SNodeType.RAW) { // TODO: Handle this as we could be in a value that's on the next line instead of right behind the node } //If not one of the special cases where we try to be more precise... // we use simplistic backward scan to determine 'CA query'. return prefixfinder.getPrefix(doc.getDocument(), offset); } public AbstractYamlAssistContext(int documentSelector, YamlPath contextPath) { this.documentSelector = documentSelector; this.contextPath = contextPath; } protected SNode getContextNode(YamlDocument file) throws Exception { return contextPath.traverse((SNode)getContextRoot(file)); } protected SDocNode getContextRoot(YamlDocument file) throws Exception { SRootNode root = file.getStructure(); return (SDocNode) root.getChildren().get(documentSelector); } protected CompletionFactory completionFactory() { return CompletionFactory.DEFAULT; } @Override public HoverInfo getHoverInfo() { return null; } @Override public HoverInfo getValueHoverInfo(YamlDocument doc, DocumentRegion documentRegion) { //By default we don't provide value-specific hover, so just show the same hover // as the assistContext the value is in. This is likely more interesting than showing nothing at all. return getHoverInfo(); } }