/******************************************************************************* * Copyright (c) 2008, 2017 Johan Compagner 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 * * Contributors: * initial API and Implementation (Johan Compagner) *******************************************************************************/ package org.eclipse.dltk.debug.ui.display; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.SortedMap; import java.util.TreeMap; import org.eclipse.dltk.console.ui.IScriptConsoleViewer; import org.eclipse.dltk.dbgp.IDbgpProperty; import org.eclipse.dltk.dbgp.exceptions.DbgpException; import org.eclipse.dltk.debug.core.model.IScriptStackFrame; import org.eclipse.dltk.debug.core.model.IScriptThread; import org.eclipse.dltk.internal.debug.ui.ScriptEvaluationContextManager; import org.eclipse.dltk.utils.TextUtils; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.contentassist.CompletionProposal; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.jface.text.contentassist.IContentAssistProcessor; import org.eclipse.jface.text.contentassist.IContextInformation; import org.eclipse.jface.text.contentassist.IContextInformationValidator; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; class DebugConsoleContentAssistProcessor implements IContentAssistProcessor { @Override public String getErrorMessage() { return null; } @Override public IContextInformationValidator getContextInformationValidator() { return null; } @Override public char[] getContextInformationAutoActivationCharacters() { return null; } @Override public char[] getCompletionProposalAutoActivationCharacters() { return null; } @Override public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) { return null; } @Override public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) { if (!(viewer instanceof IScriptConsoleViewer)) { return null; } IScriptThread thread = getScriptThread(); if (thread == null) return null; // TODO should we try to cache this tree? SortedMap tree; try { IDbgpProperty[] contextProperties = thread.getDbgpSession() .getCoreCommands().getContextProperties(0); tree = getTree(contextProperties); } catch (DbgpException ex) { return null; } SortedMap hit = null; String text = ((IScriptConsoleViewer) viewer).getCommandLine(); if (text.endsWith(".")) //$NON-NLS-1$ text += " "; //$NON-NLS-1$ String[] segments = TextUtils.split(text, '.'); int beginOffset = 0; if (text.equals("") || segments.length == 0) { //$NON-NLS-1$ hit = tree; } else { SortedMap map = tree; String fullName = ""; //$NON-NLS-1$ int lastSegment = 0; while (lastSegment != segments.length - 1) { for (; lastSegment < segments.length - 1; lastSegment++) { fullName += segments[lastSegment]; SortedMap segmentMap = (SortedMap) map .get(segments[lastSegment]); if (segmentMap == null) { break; } fullName += "."; //$NON-NLS-1$ map = segmentMap; } if (lastSegment < segments.length - 1) { try { IDbgpProperty property = thread.getDbgpSession() .getCoreCommands().getProperty(fullName); if (property != null) { String name = property.getName(); int index = name.lastIndexOf("."); if (index != -1) { name = name.substring(index + 1); } map.put(name, getTree(property.getAvailableChildren())); SortedMap segmentMap = (SortedMap) map .get(segments[lastSegment]); if (segmentMap == null) { break; } fullName += "."; //$NON-NLS-1$ map = segmentMap; lastSegment++; } else { return null; } } catch (DbgpException ex) { return null; } } } String lastSegmentString = segments[lastSegment]; if (lastSegmentString.equals(" ")) { //$NON-NLS-1$ hit = map; } else { hit = (SortedMap) map.get(lastSegmentString); } if (hit == null) { hit = new TreeMap(); beginOffset = lastSegmentString.length(); Iterator iterator = map.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry entry = (Entry) iterator.next(); if (((String) entry.getKey()) .startsWith(lastSegmentString)) { hit.put(entry.getKey(), entry.getKey()); } } } } ICompletionProposal[] proposals = new ICompletionProposal[hit.size()]; Iterator iterator = hit.keySet().iterator(); int i = 0; while (iterator.hasNext()) { String proposal = (String) iterator.next(); proposals[i++] = new CompletionProposal( proposal.substring(beginOffset), offset, 0, proposal.length(), null, proposal, null, null); } return proposals; } private SortedMap getTree(IDbgpProperty[] properties) { SortedMap map = new TreeMap(); for (int i = 0; i < properties.length; i++) { IDbgpProperty property = properties[i]; map.put(property.getName(), getTree(property.getAvailableChildren())); } return map.size() == 0 ? null : map; } private IScriptThread getScriptThread() { final IWorkbenchWindow site = PlatformUI.getWorkbench() .getActiveWorkbenchWindow(); if (site == null) { return null; } final IWorkbenchPage page = site.getActivePage(); if (page == null) { return null; } final IWorkbenchPart part = page.getActivePart(); if (part == null) { return null; } final IScriptStackFrame frame = ScriptEvaluationContextManager .getEvaluationContext(part); if (frame != null) { final IScriptThread thread = frame.getScriptThread(); if (thread != null) { return thread; } } return null; } }