blob: 2746efb800be3e766b1610619919375df7e28974 [file] [log] [blame]
/**
* 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());
}
}