| /**
|
| * Copyright (c) 2013-2015 Angelo ZERR.
|
| * All rights reserved. This program and the accompanying materials
|
| * are made available under the terms of the Eclipse Public License 2.0
|
| * which accompanies this distribution, and is available at
|
| * https://www.eclipse.org/legal/epl-2.0/
|
| *
|
| * SPDX-License-Identifier: EPL-2.0
|
| *
|
| * Contributors:
|
| * Angelo Zerr <angelo.zerr@gmail.com> - initial API and implementation
|
| */ |
| package org.eclipse.wst.json.ui.contentassist;
|
|
|
| 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.text.contentassist.IContextInformation;
|
| import org.eclipse.jface.text.link.LinkedModeModel;
|
| import org.eclipse.jface.text.link.LinkedModeUI;
|
| import org.eclipse.jface.text.link.LinkedPosition;
|
| import org.eclipse.jface.text.link.LinkedPositionGroup;
|
| import org.eclipse.swt.graphics.Image;
|
| import org.eclipse.swt.graphics.Point;
|
| import org.eclipse.ui.texteditor.link.EditorLinkedModeUI;
|
| import org.eclipse.wst.json.ui.internal.Logger;
|
| import org.eclipse.wst.sse.ui.internal.contentassist.CustomCompletionProposal;
|
|
|
| public class JSONKeyCompletionProposal extends CustomCompletionProposal {
|
|
|
| private IRegion fSelectedRegion = null;
|
|
|
| public JSONKeyCompletionProposal(String replacementString,
|
| int replacementOffset, int replacementLength, int cursorPosition,
|
| Image image, String displayString,
|
| IContextInformation contextInformation,
|
| String additionalProposalInfo, int relevance) {
|
| super(replacementString, replacementOffset, replacementLength,
|
| cursorPosition, image, displayString, contextInformation,
|
| additionalProposalInfo, relevance);
|
| }
|
|
|
| public void apply(ITextViewer viewer, char trigger, int stateMask,
|
| int offset) {
|
| super.apply(viewer, trigger, stateMask, offset);
|
| getLinkedPositions(viewer);
|
| }
|
|
|
| /**
|
| * Sets up linked positions and installs them on the viewer.
|
| *
|
| */
|
| protected void getLinkedPositions(ITextViewer viewer) {
|
| final String replacement = getReplacementString();
|
| final IDocument document = viewer.getDocument();
|
| final int length = replacement.length();
|
| boolean inAttribute = false, hasGroup = false;
|
| int offset = 0;
|
| char attType = 0;
|
| int exitPosition = -1;
|
| LinkedModeModel model = new LinkedModeModel();
|
|
|
| try {
|
| for (int i = 0; i < length; i++) {
|
| final char c = replacement.charAt(i);
|
| switch (c) {
|
| case '=':
|
| break;
|
| case '\'':
|
| case '\"':
|
| if (!inAttribute) {
|
| offset = i;
|
| attType = c;
|
| inAttribute = true;
|
| } else {
|
| // Found matching quotes establishing an attribute value
|
| // region
|
| if (attType == c && replacement.charAt(i - 1) != '\\') {
|
| inAttribute = false; // Record position length
|
| addPosition(model, document, getReplacementOffset()
|
| + offset + 1, i - offset - 1);
|
| hasGroup = true;
|
| }
|
| }
|
| break;
|
| case '>':
|
| if (!inAttribute && exitPosition == -1) {
|
| exitPosition = getReplacementOffset() + i + 1;
|
| }
|
| break;
|
| }
|
| }
|
| if (hasGroup) {
|
| model.forceInstall();
|
| final LinkedModeUI ui = new EditorLinkedModeUI(model, viewer);
|
| ui.setExitPosition(viewer,
|
| exitPosition < 0 ? getReplacementOffset()
|
| + getReplacementLength() + replacement.length()
|
| - 1 : exitPosition, 0, Integer.MAX_VALUE);
|
| ui.setCyclingMode(LinkedModeUI.CYCLE_WHEN_NO_PARENT);
|
| ui.setDoContextInfo(true);
|
| ui.enter();
|
| fSelectedRegion = ui.getSelectedRegion();
|
| }
|
| } catch (BadLocationException e) {
|
| Logger.logException(e);
|
| }
|
| }
|
|
|
| /**
|
| * Adds a {@link LinkedPosition} to its own position group. This group is
|
| * then added to the model
|
| *
|
| * @param model
|
| * the linked model for this proposal
|
| * @param document
|
| * the document the content assist is operating upon
|
| * @param offset
|
| * the offset to establish the {@link LinkedPosition}
|
| * @param length
|
| * the length of the {@link LinkedPosition}
|
| * @throws BadLocationException
|
| */
|
| private void addPosition(LinkedModeModel model, IDocument document,
|
| int offset, int length) throws BadLocationException {
|
| final LinkedPositionGroup group = new LinkedPositionGroup();
|
| group.addPosition(new LinkedPosition(document, offset, length,
|
| LinkedPositionGroup.NO_STOP));
|
| model.addGroup(group);
|
| }
|
|
|
| public Point getSelection(IDocument document) {
|
| // Attempt to return the selection based on the selected region from the
|
| // LinkedModeUI
|
| if (fSelectedRegion == null)
|
| return super.getSelection(document);
|
| return new Point(fSelectedRegion.getOffset(),
|
| fSelectedRegion.getLength());
|
| }
|
|
|
| }
|