下面列出了org.eclipse.jdt.core.dom.SuperMethodReference#org.eclipse.jface.text.link.LinkedPositionGroup 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Sets up a simple linked mode at {@link #getCursorPosition()} and an exit policy that will
* exit the mode when <code>closingCharacter</code> is typed and an exit position at
* <code>getCursorPosition() + 1</code>.
*
* @param document the document
*/
protected void setUpLinkedMode(IDocument document) {
try {
LinkedPositionGroup group= new LinkedPositionGroup();
group.addPosition(new LinkedPosition(document, getSelectionStart(), getSelectionLength(), LinkedPositionGroup.NO_STOP));
LinkedModeModel model= new LinkedModeModel();
model.addGroup(group);
model.forceInstall();
LinkedModeUI ui= new LinkedModeUI(model, viewer);
// ui.setSimpleMode(true);
ui.setExitPolicy(new ExitPolicy(exitChars));
ui.setExitPosition(viewer, getCursorPosition() + getReplacementOffset(), 0, Integer.MAX_VALUE);
ui.setCyclingMode(LinkedModeUI.CYCLE_NEVER);
ui.enter();
} catch (BadLocationException e) {
log.info(e.getMessage(), e);
}
}
@Override
public ExitFlags doExit(LinkedModeModel model, VerifyEvent event, int offset, int length) {
showPreview = (event.stateMask & SWT.CTRL) != 0 && (event.character == SWT.CR || event.character == SWT.LF);
if (length == 0 && (event.character == SWT.BS || event.character == SWT.DEL)) {
LinkedPosition position = model.findPosition(new LinkedPosition(document, offset, 0,
LinkedPositionGroup.NO_STOP));
if (position != null) {
if (event.character == SWT.BS) {
if (offset - 1 < position.getOffset()) {
// skip backspace at beginning of linked position
event.doit = false;
}
} else /* event.character == SWT.DEL */{
if (offset + 1 > position.getOffset() + position.getLength()) {
// skip delete at end of linked position
event.doit = false;
}
}
}
}
return null; // don't change behavior
}
@Override
public ExitFlags doExit(LinkedModeModel model, VerifyEvent event, int offset, int length) {
if (length == 0 && (event.character == SWT.BS || event.character == SWT.DEL)) {
LinkedPosition position= model.findPosition(new LinkedPosition(fDocument, offset, 0, LinkedPositionGroup.NO_STOP));
if (position != null) {
if (event.character == SWT.BS) {
if (offset - 1 < position.getOffset()) {
//skip backspace at beginning of linked position
event.doit= false;
}
} else /* event.character == SWT.DEL */ {
if (offset + 1 > position.getOffset() + position.getLength()) {
//skip delete at end of linked position
event.doit= false;
}
}
}
}
return null; // don't change behavior
}
/**
* Sets up a simple linked mode at {@link #getCursorPosition()} and an exit policy that will
* exit the mode when <code>closingCharacter</code> is typed and an exit position at
* <code>getCursorPosition() + 1</code>.
*
* @param document the document
* @param closingCharacter the exit character
*/
protected void setUpLinkedMode(IDocument document, char closingCharacter) {
if (getTextViewer() != null && autocloseBrackets()) {
int offset= getReplacementOffset() + getCursorPosition();
int exit= getReplacementOffset() + getReplacementString().length();
try {
LinkedPositionGroup group= new LinkedPositionGroup();
group.addPosition(new LinkedPosition(document, offset, 0, LinkedPositionGroup.NO_STOP));
LinkedModeModel model= new LinkedModeModel();
model.addGroup(group);
model.forceInstall();
LinkedModeUI ui= new EditorLinkedModeUI(model, getTextViewer());
ui.setSimpleMode(true);
ui.setExitPolicy(new ExitPolicy(closingCharacter, document));
ui.setExitPosition(getTextViewer(), exit, 0, Integer.MAX_VALUE);
ui.setCyclingMode(LinkedModeUI.CYCLE_NEVER);
ui.enter();
} catch (BadLocationException x) {
JavaPlugin.log(x);
}
}
}
/**
* Generates the Assignment in an iterator based for, used in the first statement of an iterator
* based <code>for</code> loop body, to retrieve the next element of the {@link Iterable}
* instance.
*
* @param rewrite the current instance of {@link ASTRewrite}
* @param loopOverType the {@link ITypeBinding} of the loop variable
* @param loopVariableName the name of the loop variable
* @return an {@link Assignment}, which retrieves the next element of the {@link Iterable} using
* the active {@link Iterator}
*/
private Assignment getIteratorBasedForBodyAssignment(ASTRewrite rewrite, ITypeBinding loopOverType, SimpleName loopVariableName) {
AST ast= rewrite.getAST();
Assignment assignResolvedVariable= ast.newAssignment();
// left hand side
SimpleName resolvedVariableName= resolveLinkedVariableNameWithProposals(rewrite, loopOverType.getName(), loopVariableName.getIdentifier(), false);
VariableDeclarationFragment resolvedVariableDeclarationFragment= ast.newVariableDeclarationFragment();
resolvedVariableDeclarationFragment.setName(resolvedVariableName);
VariableDeclarationExpression resolvedVariableDeclaration= ast.newVariableDeclarationExpression(resolvedVariableDeclarationFragment);
resolvedVariableDeclaration.setType(getImportRewrite().addImport(loopOverType, ast, new ContextSensitiveImportRewriteContext(fCurrentNode, getImportRewrite())));
assignResolvedVariable.setLeftHandSide(resolvedVariableDeclaration);
// right hand side
MethodInvocation invokeIteratorNextExpression= ast.newMethodInvocation();
invokeIteratorNextExpression.setName(ast.newSimpleName("next")); //$NON-NLS-1$
SimpleName currentElementName= ast.newSimpleName(loopVariableName.getIdentifier());
addLinkedPosition(rewrite.track(currentElementName), LinkedPositionGroup.NO_STOP, currentElementName.getIdentifier());
invokeIteratorNextExpression.setExpression(currentElementName);
assignResolvedVariable.setRightHandSide(invokeIteratorNextExpression);
assignResolvedVariable.setOperator(Assignment.Operator.ASSIGN);
return assignResolvedVariable;
}
public ExitFlags doExit(LinkedModeModel model, VerifyEvent event, int offset, int length) {
if (length == 0 && (event.character == SWT.BS || event.character == SWT.DEL)) {
LinkedPosition position= model.findPosition(new LinkedPosition(fDocument, offset, 0, LinkedPositionGroup.NO_STOP));
if (position != null) {
if (event.character == SWT.BS) {
if (offset - 1 < position.getOffset()) {
//skip backspace at beginning of linked position
event.doit= false;
}
} else /* event.character == SWT.DEL */ {
if (offset + 1 > position.getOffset() + position.getLength()) {
//skip delete at end of linked position
event.doit= false;
}
}
}
}
return null; // don't change behavior
}
@Override
public ExitFlags doExit(LinkedModeModel model, VerifyEvent event, int offset, int length) {
if (length == 0 && (event.character == SWT.BS || event.character == SWT.DEL)) {
LinkedPosition position= model.findPosition(new LinkedPosition(fDocument, offset, 0, LinkedPositionGroup.NO_STOP));
if (position != null) {
if (event.character == SWT.BS) {
if (offset - 1 < position.getOffset()) {
//skip backspace at beginning of linked position
event.doit= false;
}
} else /* event.character == SWT.DEL */ {
if (offset + 1 > position.getOffset() + position.getLength()) {
//skip delete at end of linked position
event.doit= false;
}
}
}
}
return null; // don't change behavior
}
private void startLinkedEdit(List<IRegion> selections, ITextViewer viewer, Point originalSelection)
throws BadLocationException {
final LinkedPositionGroup linkedPositionGroup = new LinkedPositionGroup();
for (IRegion selection : selections) {
linkedPositionGroup.addPosition(new LinkedPosition(viewer.getDocument(), selection.getOffset(), selection
.getLength()));
}
LinkedModeModel model = new LinkedModeModel();
model.addGroup(linkedPositionGroup);
model.forceInstall();
//FIXME can add a listener here to listen for the end of linked mode
//model.addLinkingListener(null);
LinkedModeUI ui = new EditorLinkedModeUI(model, viewer);
ui.setExitPolicy(new DeleteBlockingExitPolicy(viewer.getDocument()));
ui.enter();
// by default the text being edited is selected so restore original selection
viewer.setSelectedRange(originalSelection.x, originalSelection.y);
}
protected LinkedModeModel getLinkedModeModel(ITextViewer viewer) throws BadLocationException {
Indexable<SourceRange> sourceSubElements = proposal.getSourceSubElements();
if(sourceSubElements == null || sourceSubElements.isEmpty()) {
return null;
}
LinkedModeModel model = new LinkedModeModel();
IDocument document = viewer.getDocument();
int replaceOffset = getReplaceOffset();
firstLinkedModeGroupPosition = -1;
for (SourceRange sr : sourceSubElements) {
LinkedPositionGroup group = new LinkedPositionGroup();
int posOffset = replaceOffset + sr.getOffset();
group.addPosition(new LinkedPosition(document, posOffset, sr.getLength()));
if(firstLinkedModeGroupPosition == -1) {
firstLinkedModeGroupPosition = posOffset;
}
model.addGroup(group);
}
return model;
}
@Test public void testCorrectTextEditsDeclarationInFile() throws Exception {
String initialModel1 = "A { B ref A } C { D ref A }";
createFile(pathToFile1, initialModel1);
String initialModel2 = "E { ref A } F { ref E ref A}";
IFile file1 = createFile(pathToFile1, initialModel1);
createFile(pathToFile2, initialModel2);
waitForBuild();
XtextEditor editor = openEditor(file1);
EObject a = editor.getDocument().readOnly(new IUnitOfWork<EObject, XtextResource>() {
@Override
public EObject exec(XtextResource state) throws Exception {
return state.getContents().get(0).eContents().get(0);
}
});
URI uri = EcoreUtil.getURI(a);
selectElementInEditor(a, uri, editor, (XtextResource) a.eResource());
IRenameElementContext renameElementContext = new IRenameElementContext.Impl(uri, a.eClass(), editor, editor
.getSelectionProvider().getSelection(), uriToFile1);
LinkedPositionGroup linkedPositionGroup = linkedModelCalculator.getLinkedPositionGroup(renameElementContext,
new NullProgressMonitor()).get();
LinkedPosition[] positions = linkedPositionGroup.getPositions();
assertEquals(3, positions.length);
int[] offsets = { 0, 10, 24 };
for (int i = 0; i < positions.length; i++) {
assertEquals(offsets[i], positions[i].getOffset());
}
}
@Test public void testCorrectTextEditsDeclarationNotInFile() throws Exception {
String initialModel1 = "A { B ref A } C { D ref A }";
createFile(pathToFile1, initialModel1);
String initialModel2 = "E { ref A } F { ref E ref A}";
IFile file2 = createFile(pathToFile2, initialModel2);
waitForBuild();
XtextEditor editor = openEditor(file2);
EObject a = editor.getDocument().readOnly(new IUnitOfWork<EObject, XtextResource>() {
@Override
public EObject exec(XtextResource state) throws Exception {
return ((Element) state.getContents().get(0).eContents().get(0)).getReferenced().get(0);
}
});
URI uri = EcoreUtil.getURI(a);
selectElementInEditor(a, uri, editor, (XtextResource) a.eResource());
IRenameElementContext renameElementContext = new IRenameElementContext.Impl(uri, a.eClass(), editor, editor
.getSelectionProvider().getSelection(), uriToFile2);
LinkedPositionGroup linkedPositionGroup = linkedModelCalculator.getLinkedPositionGroup(renameElementContext,
new NullProgressMonitor()).get();
LinkedPosition[] positions = linkedPositionGroup.getPositions();
assertEquals(2, positions.length);
int[] offsets = { 8, 26 };
for (int i = 0; i < positions.length; i++) {
assertEquals(offsets[i], positions[i].getOffset());
}
}
protected LinkedPositionGroup createLinkedGroupFromReplaceEdits(List<ReplaceEdit> edits, XtextEditor xtextEditor, String originalName,
SubMonitor progress) {
if (edits == null) {
return null;
}
IXtextDocument document = xtextEditor.getDocument();
LinkedPositionGroup group = new LinkedPositionGroup();
List<LinkedPosition> linkedPositions = new ArrayList<>();
edits.forEach(replaceEdit -> {
try {
String textToReplace = document.get(replaceEdit.getOffset(), replaceEdit.getLength());
int indexOf = textToReplace.indexOf(originalName);
if (indexOf != -1) {
int calculatedOffset = replaceEdit.getOffset() + indexOf;
linkedPositions.add(new LinkedPosition(document, calculatedOffset, originalName.length()));
}
} catch (BadLocationException exc) {
LOG.error("Skipping invalid text edit " + replaceEdit, exc);
}
});
progress.worked(10);
int invocationOffset = xtextEditor.getInternalSourceViewer().getSelectedRange().x;
int i = 0;
for (LinkedPosition position : sortPositions(linkedPositions, invocationOffset)) {
try {
position.setSequenceNumber(i);
i++;
group.addPosition(position);
} catch (BadLocationException e) {
LOG.error(e.getMessage(), e);
return null;
}
}
return group;
}
public boolean start(IRenameElementContext renameElementContext, Provider<LinkedPositionGroup> provider, IProgressMonitor monitor) {
if (renameElementContext == null)
throw new IllegalArgumentException("RenameElementContext is null");
this.linkedPositionGroup = provider.get();
if (linkedPositionGroup == null || linkedPositionGroup.isEmpty())
return false;
this.editor = (XtextEditor) renameElementContext.getTriggeringEditor();
this.focusEditingSupport = new FocusEditingSupport();
ISourceViewer viewer = editor.getInternalSourceViewer();
IDocument document = viewer.getDocument();
originalSelection = viewer.getSelectedRange();
currentPosition = linkedPositionGroup.getPositions()[0];
originalName = getCurrentName();
try {
linkedModeModel = new LinkedModeModel();
linkedModeModel.addGroup(linkedPositionGroup);
linkedModeModel.forceInstall();
linkedModeModel.addLinkingListener(new EditorSynchronizer());
LinkedModeUI ui = new EditorLinkedModeUI(linkedModeModel, viewer);
ui.setExitPolicy(new ExitPolicy(document));
if (currentPosition.includes(originalSelection.x))
ui.setExitPosition(viewer, originalSelection.x, 0, Integer.MAX_VALUE);
ui.enter();
if (currentPosition.includes(originalSelection.x)
&& currentPosition.includes(originalSelection.x + originalSelection.y))
viewer.setSelectedRange(originalSelection.x, originalSelection.y);
if (viewer instanceof IEditingSupportRegistry) {
IEditingSupportRegistry registry = (IEditingSupportRegistry) viewer;
registry.register(focusEditingSupport);
}
openPopup();
return true;
} catch (BadLocationException e) {
throw new WrappedException(e);
}
}
protected LinkedPositionGroup createLinkedGroupFromReplaceEdits(List<ReplaceEdit> edits, XtextEditor xtextEditor,
final String originalName, SubMonitor progress) {
if (edits == null)
return null;
final IXtextDocument document = xtextEditor.getDocument();
LinkedPositionGroup group = new LinkedPositionGroup();
Iterable<LinkedPosition> linkedPositions = filter(
Iterables.transform(edits, new Function<ReplaceEdit, LinkedPosition>() {
@Override
public LinkedPosition apply(ReplaceEdit edit) {
try {
String textToReplace = document.get(edit.getOffset(), edit.getLength());
int indexOf = textToReplace.indexOf(originalName);
if (indexOf != -1) {
int calculatedOffset = edit.getOffset() + indexOf;
return new LinkedPosition(document, calculatedOffset, originalName.length());
}
} catch (BadLocationException exc) {
LOG.error("Skipping invalid text edit " + notNull(edit), exc);
}
return null;
}
}), Predicates.notNull());
progress.worked(10);
final int invocationOffset = xtextEditor.getInternalSourceViewer().getSelectedRange().x;
int i = 0;
for (LinkedPosition position : sortPositions(linkedPositions, invocationOffset)) {
try {
position.setSequenceNumber(i);
i++;
group.addPosition(position);
} catch (BadLocationException e) {
LOG.error(e.getMessage(), e);
return null;
}
}
return group;
}
public void apply(IDocument document) {
try {
if (fentry.arguments > 0) {
StringBuffer displayKey = new StringBuffer(fentry.key);
for (int j=0; j < fentry.arguments; j++)
displayKey.append("{}");
document.replace(fReplacementOffset, fReplacementLength, displayKey.toString());
if (TexlipsePlugin.getDefault().getPreferenceStore()
.getBoolean(TexlipseProperties.SMART_PARENS)){
LinkedModeModel model= new LinkedModeModel();
for (int j=0; j < fentry.arguments; j++){
int newOffset = fReplacementOffset + fentry.key.length() + j*2 + 1;
LinkedPositionGroup group = new LinkedPositionGroup();
group.addPosition(new LinkedPosition(document, newOffset, 0, LinkedPositionGroup.NO_STOP));
model.addGroup(group);
}
model.forceInstall();
LinkedModeUI ui = new EditorLinkedModeUI(model, fviewer);
ui.setSimpleMode(false);
ui.setExitPolicy(new ExitPolicy('}', fviewer));
ui.setExitPosition(fviewer, fReplacementOffset + displayKey.length(),
0, Integer.MAX_VALUE);
ui.setCyclingMode(LinkedModeUI.CYCLE_NEVER);
ui.enter();
}
} else {
document.replace(fReplacementOffset, fReplacementLength, fentry.key);
}
} catch (BadLocationException x) {
}
}
/**
* Special code added to allow tabstop positions so we can easily tab past the quotes for Events/Attributes.
*/
@Override
public void apply(ITextViewer viewer, char trigger, int stateMask, int offset)
{
super.apply(viewer, trigger, stateMask, offset);
// See if there are any positions that should be linked. Last is always exit, first is cursor position
if (_positions != null && _positions.length > 0)
{
IDocument document = viewer.getDocument();
boolean validPrefix = isValidPrefix(getPrefix(document, offset), getDisplayString());
int shift = (validPrefix) ? offset - this._replacementOffset : 0;
try
{
LinkedModeModel.closeAllModels(document); // Exit out of any existing linked mode
LinkedModeModel model = new LinkedModeModel();
int i = 0;
for (int pos : _positions)
{
LinkedPositionGroup group = new LinkedPositionGroup();
group.addPosition(new LinkedPosition(document, (offset - shift) + pos, 0, i++));
model.addGroup(group);
}
model.forceInstall();
LinkedModeUI ui = new LinkedModeUI(model, viewer);
ui.setCyclingMode(LinkedModeUI.CYCLE_ALWAYS);
ui.setExitPosition(viewer, (offset - shift) + _positions[_positions.length - 1], 0, Integer.MAX_VALUE);
ui.enter();
}
catch (BadLocationException e)
{
IdeLog.logError(XMLPlugin.getDefault(), e);
}
}
}
/**
* Special code added to allow tabstop positions so we can easily tab past the quotes for Events/Attributes.
*/
@Override
public void apply(ITextViewer viewer, char trigger, int stateMask, int offset)
{
super.apply(viewer, trigger, stateMask, offset);
// See if there are any positions that should be linked. Last is always exit, first is cursor position
if (_positions != null && _positions.length > 0)
{
IDocument document = viewer.getDocument();
boolean validPrefix = isValidPrefix(getPrefix(document, offset), getDisplayString());
int shift = (validPrefix) ? offset - this._replacementOffset : 0;
try
{
LinkedModeModel.closeAllModels(document); // Exit out of any existing linked mode
LinkedModeModel model = new LinkedModeModel();
int i = 0;
for (int pos : _positions)
{
LinkedPositionGroup group = new LinkedPositionGroup();
group.addPosition(new LinkedPosition(document, (offset - shift) + pos, 0, i++));
model.addGroup(group);
}
model.forceInstall();
LinkedModeUI ui = new LinkedModeUI(model, viewer);
ui.setCyclingMode(LinkedModeUI.CYCLE_ALWAYS);
ui.setExitPosition(viewer, (offset - shift) + _positions[_positions.length - 1], 0, Integer.MAX_VALUE);
ui.enter();
}
catch (BadLocationException e)
{
IdeLog.logError(HTMLPlugin.getDefault(), e);
}
}
}
/**
* Helper to generate an iterator based <code>for</code> loop to iterate over an
* {@link Iterable}.
*
* @param ast the {@link AST} instance to rewrite the loop to
* @return the complete {@link ASTRewrite} object
*/
private ASTRewrite generateIteratorBasedForRewrite(AST ast) {
ASTRewrite rewrite= ASTRewrite.create(ast);
ForStatement loopStatement= ast.newForStatement();
ITypeBinding loopOverType= extractElementType(ast);
SimpleName loopVariableName= resolveLinkedVariableNameWithProposals(rewrite, "iterator", null, true); //$NON-NLS-1$
loopStatement.initializers().add(getIteratorBasedForInitializer(rewrite, loopVariableName));
MethodInvocation loopExpression= ast.newMethodInvocation();
loopExpression.setName(ast.newSimpleName("hasNext")); //$NON-NLS-1$
SimpleName expressionName= ast.newSimpleName(loopVariableName.getIdentifier());
addLinkedPosition(rewrite.track(expressionName), LinkedPositionGroup.NO_STOP, expressionName.getIdentifier());
loopExpression.setExpression(expressionName);
loopStatement.setExpression(loopExpression);
Block forLoopBody= ast.newBlock();
Assignment assignResolvedVariable= getIteratorBasedForBodyAssignment(rewrite, loopOverType, loopVariableName);
forLoopBody.statements().add(ast.newExpressionStatement(assignResolvedVariable));
forLoopBody.statements().add(createBlankLineStatementWithCursorPosition(rewrite));
loopStatement.setBody(forLoopBody);
rewrite.replace(fCurrentNode, loopStatement, null);
return rewrite;
}
/**
* Creates an {@link Assignment} as first expression appearing in a <code>for</code> loop's
* body. This Assignment declares a local variable and initializes it using the array's current
* element identified by the loop index.
*
* @param rewrite the current {@link ASTRewrite} instance
* @param loopVariableName the name of the index variable in String representation
* @return a completed {@link Assignment} containing the mentioned declaration and
* initialization
*/
private Assignment getForBodyAssignment(ASTRewrite rewrite, SimpleName loopVariableName) {
AST ast= rewrite.getAST();
ITypeBinding loopOverType= extractElementType(ast);
Assignment assignResolvedVariable= ast.newAssignment();
// left hand side
SimpleName resolvedVariableName= resolveLinkedVariableNameWithProposals(rewrite, loopOverType.getName(), loopVariableName.getIdentifier(), false);
VariableDeclarationFragment resolvedVariableDeclarationFragment= ast.newVariableDeclarationFragment();
resolvedVariableDeclarationFragment.setName(resolvedVariableName);
VariableDeclarationExpression resolvedVariableDeclaration= ast.newVariableDeclarationExpression(resolvedVariableDeclarationFragment);
resolvedVariableDeclaration.setType(getImportRewrite().addImport(loopOverType, ast, new ContextSensitiveImportRewriteContext(fCurrentNode, getImportRewrite())));
assignResolvedVariable.setLeftHandSide(resolvedVariableDeclaration);
// right hand side
ArrayAccess access= ast.newArrayAccess();
access.setArray((Expression) rewrite.createCopyTarget(fCurrentExpression));
SimpleName indexName= ast.newSimpleName(loopVariableName.getIdentifier());
addLinkedPosition(rewrite.track(indexName), LinkedPositionGroup.NO_STOP, indexName.getIdentifier());
access.setIndex(indexName);
assignResolvedVariable.setRightHandSide(access);
assignResolvedVariable.setOperator(Assignment.Operator.ASSIGN);
return assignResolvedVariable;
}
/**
* Creates an {@link InfixExpression} which is linked to the group of the variableToIncrement.
*
* @param rewrite the current {@link ASTRewrite} instance
* @param variableToIncrement the name of the variable to generate the {@link InfixExpression}
* for
* @param rightHandSide the right hand side expression which shall be included in the
* {@link InfixExpression}
* @param operator the {@link org.eclipse.jdt.core.dom.InfixExpression.Operator} to use in the
* {@link InfixExpression} to create
* @return a filled, new {@link InfixExpression} instance
*/
private InfixExpression getLinkedInfixExpression(ASTRewrite rewrite, String variableToIncrement, Expression rightHandSide, InfixExpression.Operator operator) {
AST ast= rewrite.getAST();
InfixExpression loopExpression= ast.newInfixExpression();
SimpleName name= ast.newSimpleName(variableToIncrement);
addLinkedPosition(rewrite.track(name), LinkedPositionGroup.NO_STOP, name.getIdentifier());
loopExpression.setLeftOperand(name);
loopExpression.setOperator(operator);
loopExpression.setRightOperand(rightHandSide);
return loopExpression;
}
/**
* Creates a {@link PostfixExpression} used to increment the loop variable of a <code>for</code>
* loop to iterate over an array.
*
* @param rewrite the current {@link ASTRewrite} instance
* @param variableToIncrement the name of the variable to increment
* @return a filled {@link PostfixExpression} realizing an incrementation of the specified
* variable
*/
private Expression getLinkedIncrementExpression(ASTRewrite rewrite, String variableToIncrement) {
AST ast= rewrite.getAST();
PostfixExpression incrementLoopVariable= ast.newPostfixExpression();
SimpleName name= ast.newSimpleName(variableToIncrement);
addLinkedPosition(rewrite.track(name), LinkedPositionGroup.NO_STOP, name.getIdentifier());
incrementLoopVariable.setOperand(name);
incrementLoopVariable.setOperator(PostfixExpression.Operator.INCREMENT);
return incrementLoopVariable;
}
/**
* Creates an {@link Assignment} as first expression appearing in an index based
* <code>for</code> loop's body. This Assignment declares a local variable and initializes it
* using the {@link List}'s current element identified by the loop index.
*
* @param rewrite the current {@link ASTRewrite} instance
* @param loopVariableName the name of the index variable in String representation
* @return a completed {@link Assignment} containing the mentioned declaration and
* initialization
*/
private Expression getIndexBasedForBodyAssignment(ASTRewrite rewrite, SimpleName loopVariableName) {
AST ast= rewrite.getAST();
ITypeBinding loopOverType= extractElementType(ast);
Assignment assignResolvedVariable= ast.newAssignment();
// left hand side
SimpleName resolvedVariableName= resolveLinkedVariableNameWithProposals(rewrite, loopOverType.getName(), loopVariableName.getIdentifier(), false);
VariableDeclarationFragment resolvedVariableDeclarationFragment= ast.newVariableDeclarationFragment();
resolvedVariableDeclarationFragment.setName(resolvedVariableName);
VariableDeclarationExpression resolvedVariableDeclaration= ast.newVariableDeclarationExpression(resolvedVariableDeclarationFragment);
resolvedVariableDeclaration.setType(getImportRewrite().addImport(loopOverType, ast, new ContextSensitiveImportRewriteContext(fCurrentNode, getImportRewrite())));
assignResolvedVariable.setLeftHandSide(resolvedVariableDeclaration);
// right hand side
MethodInvocation invokeGetExpression= ast.newMethodInvocation();
invokeGetExpression.setName(ast.newSimpleName("get")); //$NON-NLS-1$
SimpleName indexVariableName= ast.newSimpleName(loopVariableName.getIdentifier());
addLinkedPosition(rewrite.track(indexVariableName), LinkedPositionGroup.NO_STOP, indexVariableName.getIdentifier());
invokeGetExpression.arguments().add(indexVariableName);
invokeGetExpression.setExpression((Expression) rewrite.createCopyTarget(fCurrentExpression));
assignResolvedVariable.setRightHandSide(invokeGetExpression);
assignResolvedVariable.setOperator(Assignment.Operator.ASSIGN);
return assignResolvedVariable;
}
/**
* Really do apply the proposal. Assumed to be run within the prevent flickering mode.
*/
private int doApply(QualifiedName qualifiedName, String alias, IDocument document,
ConfigurableCompletionProposal proposal) throws BadLocationException {
String shortSemanticReplacementString = alias != null ? alias : lastSegmentOrDefaultHost(qualifiedName);
String shortSyntacticReplacementString = valueConverter.toString(shortSemanticReplacementString);
String longReplacementString = shortSyntacticReplacementString
+ ConfigurableCompletionProposalExtensions.getReplacementSuffix(proposal);
ImportRewriter importRewriter = importRewriterFactory.create(document, context);
ReplaceEdit replaceEdit = new ReplaceEdit(
proposal.getReplacementOffset(),
proposal.getReplacementLength(),
longReplacementString);
MultiTextEdit compound = new MultiTextEdit();
AliasLocation aliasLocation = null;
if (alias != null) {
aliasLocation = importRewriter.addSingleImport(qualifiedName, alias, compound);
} else {
importRewriter.addSingleImport(qualifiedName, compound);
}
compound.addChild(replaceEdit);
Position caret = new Position(proposal.getReplacementOffset(), 0);
document.addPosition(caret);
compound.apply(document);
document.removePosition(caret);
int cursorPosition = caret.getOffset();
proposal.setReplacementOffset(cursorPosition - longReplacementString.length());
proposal.setReplacementLength(shortSyntacticReplacementString.length()); // do not include suffix!
proposal.setCursorPosition(
cursorPosition - proposal.getReplacementOffset()); // cursorPosition is relative to replacementOffset!
if (aliasLocation != null) {
final int aliasOffset = aliasLocation.getBaseOffset() + aliasLocation.getRelativeOffset();
final int aliasLength = shortSyntacticReplacementString.length();
N4JSCompletionProposal castedProposal = (N4JSCompletionProposal) proposal;
castedProposal.setLinkedModeBuilder((appliedProposal, currentDocument) -> {
if (viewer.getTextWidget() == null || viewer.getTextWidget().isDisposed()) {
return; // do not attempt to set up linked mode in a disposed UI
}
try {
LinkedPositionGroup group = new LinkedPositionGroup();
group.addPosition(new LinkedPosition(
currentDocument,
aliasOffset,
aliasLength,
LinkedPositionGroup.NO_STOP));
group.addPosition(new LinkedPosition(
currentDocument,
proposal.getReplacementOffset(),
proposal.getReplacementLength(),
LinkedPositionGroup.NO_STOP));
proposal.setSelectionStart(proposal.getReplacementOffset());
proposal.setSelectionLength(proposal.getReplacementLength());
LinkedModeModel model = new LinkedModeModel();
model.addGroup(group);
model.forceInstall();
LinkedModeUI ui = new LinkedModeUI(model, viewer);
ui.setExitPolicy(new IdentifierExitPolicy('\n'));
ui.setExitPosition(
viewer,
proposal.getReplacementOffset()
+ proposal.getCursorPosition()
+ ConfigurableCompletionProposalExtensions.getCursorOffset(proposal),
0,
Integer.MAX_VALUE);
ui.setCyclingMode(LinkedModeUI.CYCLE_NEVER);
ui.enter();
} catch (BadLocationException e) {
logger.error(e.getMessage(), e);
}
});
} else {
adjustCursorPositionIfRequested(proposal);
}
return cursorPosition;
}
@Override
public Provider<LinkedPositionGroup> getLinkedPositionGroup(IRenameElementContext renameElementContext, IProgressMonitor monitor) {
SubMonitor progress = SubMonitor.convert(monitor, 100);
XtextEditor editor = (XtextEditor) renameElementContext.getTriggeringEditor();
IProject project = projectUtil.getProject(renameElementContext.getContextResourceURI());
if (project == null) {
throw new IllegalStateException(
"Could not determine the project for context resource " + renameElementContext.getContextResourceURI());
}
CachingResourceSetProvider cachingResourceSetProvider = new CachingResourceSetProvider(resourceSetProvider);
ResourceSet resourceSet = cachingResourceSetProvider.get(project);
EObject targetElement = resourceSet.getEObject(renameElementContext.getTargetElementURI(), true);
if (targetElement == null) {
throw new IllegalStateException("Target element could not be loaded");
}
if (monitor.isCanceled()) {
throw new OperationCanceledException();
}
IRenameStrategy2 renameStrategy = globalServiceProvider.findService(targetElement, IRenameStrategy2.class);
if (renameStrategy == null) {
throw new IllegalArgumentException("Cannot find a rename strategy for " + renameElementContext.getTargetElementURI());
}
String oldName = simpleNameProvider.getSimpleName(targetElement);
String newName = getNewDummyName(oldName);
IResourceServiceProvider resourceServiceProvider = resourceServiceProviderRegistry
.getResourceServiceProvider(renameElementContext.getTargetElementURI());
LtkIssueAcceptor issues = resourceServiceProvider.get(LtkIssueAcceptor.class);
IChangeSerializer changeSerializer = resourceServiceProvider.get(IChangeSerializer.class);
changeSerializer.setUpdateRelatedFiles(false);
RenameChange change = new RenameChange(newName, renameElementContext.getTargetElementURI());
RenameContext renameContext = new RenameContext(Lists.newArrayList(change), resourceSet, changeSerializer, issues);
renameStrategy.applyRename(renameContext);
List<ReplaceEdit> replaceEdits = new ArrayList<>();
changeSerializer.applyModifications(c -> {
if (c instanceof ITextDocumentChange) {
ITextDocumentChange textDocumentChange = (ITextDocumentChange) c;
textDocumentChange.getReplacements().forEach(replacement -> {
replaceEdits.add(new ReplaceEdit(replacement.getOffset(), replacement.getLength(), replacement.getReplacementText()));
});
}
});
if (monitor.isCanceled()) {
throw new OperationCanceledException();
}
return () -> {
return createLinkedGroupFromReplaceEdits(replaceEdits, editor, oldName, progress.newChild(10));
};
}
Provider<LinkedPositionGroup> getLinkedPositionGroup(IRenameElementContext renameElementContext,
IProgressMonitor monitor);
@Override
public Provider<LinkedPositionGroup> getLinkedPositionGroup(
IRenameElementContext renameElementContext,
IProgressMonitor monitor) {
final SubMonitor progress = SubMonitor.convert(monitor, 100);
final XtextEditor editor = (XtextEditor) renameElementContext.getTriggeringEditor();
IProject project = projectUtil.getProject(renameElementContext.getContextResourceURI());
if (project == null)
throw new IllegalStateException("Could not determine project for context resource "
+ renameElementContext.getContextResourceURI());
RefactoringResourceSetProvider resourceSetProvider = new CachingResourceSetProvider(DefaultLinkedPositionGroupCalculator.this.resourceSetProvider);
ResourceSet resourceSet = resourceSetProvider.get(project);
EObject targetElement = resourceSet.getEObject(renameElementContext.getTargetElementURI(), true);
if (targetElement == null)
throw new IllegalStateException("Target element could not be loaded");
if (monitor.isCanceled()) {
throw new OperationCanceledException();
}
IRenameStrategy.Provider strategyProvider = globalServiceProvider.findService(targetElement,
IRenameStrategy.Provider.class);
IRenameStrategy renameStrategy = null;
try {
renameStrategy = strategyProvider.get(targetElement, renameElementContext);
} catch(NoSuchStrategyException exc) {
// handle in next line
}
if(renameStrategy == null)
throw new IllegalArgumentException("Cannot find a rename strategy for "
+ notNull(renameElementContext.getTargetElementURI()));
String newName = renameStrategy.getOriginalName();
IResourceServiceProvider resourceServiceProvider = resourceServiceProviderRegistry.getResourceServiceProvider(renameElementContext.getTargetElementURI());
IDependentElementsCalculator dependentElementsCalculator = resourceServiceProvider.get(IDependentElementsCalculator.class);
Iterable<URI> dependentElementURIs = dependentElementsCalculator.getDependentElementURIs(targetElement,
progress.newChild(10));
if (monitor.isCanceled()) {
throw new OperationCanceledException();
}
LocalResourceRefactoringUpdateAcceptor updateAcceptor = updateAcceptorProvider.get();
updateAcceptor.setLocalResourceURI(renameElementContext.getContextResourceURI());
renameStrategy.createDeclarationUpdates(newName, resourceSet, updateAcceptor);
if (monitor.isCanceled()) {
throw new OperationCanceledException();
}
Map<URI, URI> original2newEObjectURI = renamedElementTracker.renameAndTrack(
concat(Collections.singleton(renameElementContext.getTargetElementURI()), dependentElementURIs),
newName, resourceSet, renameStrategy, progress.newChild(10));
if (monitor.isCanceled()) {
throw new OperationCanceledException();
}
ElementRenameArguments elementRenameArguments = new ElementRenameArguments(
renameElementContext.getTargetElementURI(), newName, renameStrategy, original2newEObjectURI, resourceSetProvider);
final List<IReferenceDescription> referenceDescriptions = newArrayList();
IReferenceFinder.Acceptor referenceAcceptor = new IReferenceFinder.Acceptor() {
@Override
public void accept(IReferenceDescription referenceDescription) {
referenceDescriptions.add(referenceDescription);
}
@Override
public void accept(EObject source, URI sourceURI, EReference eReference, int index, EObject targetOrProxy,
URI targetURI) {
referenceDescriptions.add(new DefaultReferenceDescription(EcoreUtil2.getFragmentPathURI(source), targetURI, eReference, index, null));
}
};
if (monitor.isCanceled()) {
throw new OperationCanceledException();
}
referenceFinder.findReferences(
targetURIConverter.fromIterable(elementRenameArguments.getRenamedElementURIs()),
resourceSet.getResource(renameElementContext.getContextResourceURI(), true),
referenceAcceptor, progress.newChild(10));
if (monitor.isCanceled()) {
throw new OperationCanceledException();
}
referenceUpdater.createReferenceUpdates(elementRenameArguments, referenceDescriptions, updateAcceptor,
progress.newChild(60));
final List<ReplaceEdit> textEdits = updateAcceptor.getTextEdits();
if (monitor.isCanceled()) {
throw new OperationCanceledException();
}
final IRenameStrategy renameStrategy2 = renameStrategy;
return new Provider<LinkedPositionGroup>() {
@Override
public LinkedPositionGroup get() {
LinkedPositionGroup linkedGroup = createLinkedGroupFromReplaceEdits(textEdits, editor,
renameStrategy2.getOriginalName(), progress.newChild(10));
return linkedGroup;
}
};
}
public void start() {
if (getActiveLinkedMode() != null) {
// for safety; should already be handled in RenameJavaElementAction
fgActiveLinkedMode.startFullDialog();
return;
}
ISourceViewer viewer = fEditor.getViewer();
IDocument document = viewer.getDocument();
ITypeScriptFile tsFile = fEditor.getTypeScriptFile();
tsFile.setDisableChanged(true);
fOriginalSelection = viewer.getSelectedRange();
int offset = fOriginalSelection.x;
try {
fLinkedPositionGroup = new LinkedPositionGroup();
if (viewer instanceof ITextViewerExtension6) {
IUndoManager undoManager = ((ITextViewerExtension6) viewer).getUndoManager();
if (undoManager instanceof IUndoManagerExtension) {
IUndoManagerExtension undoManagerExtension = (IUndoManagerExtension) undoManager;
IUndoContext undoContext = undoManagerExtension.getUndoContext();
IOperationHistory operationHistory = OperationHistoryFactory.getOperationHistory();
fStartingUndoOperation = operationHistory.getUndoOperation(undoContext);
}
}
// Find occurrences
List<OccurrencesResponseItem> occurrences = tsFile.occurrences(offset).get(1000, TimeUnit.MILLISECONDS);
// Create Eclipse linked position from the occurrences list.
int start, length;
for (int i = 0; i < occurrences.size(); i++) {
OccurrencesResponseItem item = occurrences.get(i);
start = tsFile.getPosition(item.getStart());
length = tsFile.getPosition(item.getEnd()) - start;
LinkedPosition linkedPosition = new LinkedPosition(document, start, length, i);
if (i == 0) {
fOriginalName = document.get(start, length);
fNamePosition = linkedPosition;
}
fLinkedPositionGroup.addPosition(linkedPosition);
}
fLinkedModeModel = new LinkedModeModel();
fLinkedModeModel.addGroup(fLinkedPositionGroup);
fLinkedModeModel.forceInstall();
fLinkedModeModel.addLinkingListener(new EditorHighlightingSynchronizer(fEditor));
fLinkedModeModel.addLinkingListener(new EditorSynchronizer());
LinkedModeUI ui = new EditorLinkedModeUI(fLinkedModeModel, viewer);
ui.setExitPosition(viewer, offset, 0, Integer.MAX_VALUE);
ui.setExitPolicy(new ExitPolicy(document));
ui.enter();
viewer.setSelectedRange(fOriginalSelection.x, fOriginalSelection.y); // by
// default,
// full
// word
// is
// selected;
// restore
// original
// selection
if (viewer instanceof IEditingSupportRegistry) {
IEditingSupportRegistry registry = (IEditingSupportRegistry) viewer;
registry.register(fFocusEditingSupport);
}
openSecondaryPopup();
// startAnimation();
fgActiveLinkedMode = this;
} catch (Exception e) {
JSDTTypeScriptUIPlugin.log(e);
}
}
/**
* Enters the linked mode for editing the namespace prefix we generated.
*/
private void enterLinkedModeForPrefix(IDocument document,
ITextViewer viewer, IDOMElement rootElement, String prefix)
throws BadLocationException {
int linkedPosSequence = 0;
// The prefix is the first thing entered at the start position
LinkedPosition pos1 = new LinkedPosition(document, startPosition,
prefix.length(), linkedPosSequence++);
// The prefix is also at the cursor position + 2 (those two following
// characters are '<' and '/')
LinkedPosition pos2 = new LinkedPosition(document, cursorPosition + 2,
prefix.length(), linkedPosSequence++);
IDOMElement rootDomElement = (IDOMElement) rootElement;
// TODO: use UiBinderConstants.XMLNS_PREFIX, but that has been modified in
// a parallel CL. Will switch to using that constant in the latter of this
// and that other CL.
final String xmlnsPrefix = "xmlns:";
String fullPrefixName = xmlnsPrefix + prefix;
IDOMAttr domAttribute = (IDOMAttr) rootDomElement.getAttributeNode(fullPrefixName);
LinkedPosition pos3 = new LinkedPosition(document,
domAttribute.getStartOffset() + xmlnsPrefix.length(),
prefix.length(), linkedPosSequence++);
LinkedPositionGroup group = new LinkedPositionGroup();
group.addPosition(pos1);
group.addPosition(pos2);
group.addPosition(pos3);
// Boilerplate stuff below
LinkedModeModel model = new LinkedModeModel();
model.addGroup(group);
model.forceInstall();
LinkedModeUI ui = new LinkedModeUI(model, viewer);
ui.enter();
wasLinkedModeEntered = true;
}
public void start() {
if (getActiveLinkedMode() != null) {
// for safety; should already be handled in RenameJavaElementAction
fgActiveLinkedMode.startFullDialog();
return;
}
ISourceViewer viewer= fEditor.getViewer();
IDocument document= viewer.getDocument();
fOriginalSelection= viewer.getSelectedRange();
int offset= fOriginalSelection.x;
try {
CompilationUnit root= SharedASTProvider.getAST(getCompilationUnit(), SharedASTProvider.WAIT_YES, null);
fLinkedPositionGroup= new LinkedPositionGroup();
ASTNode selectedNode= NodeFinder.perform(root, fOriginalSelection.x, fOriginalSelection.y);
if (! (selectedNode instanceof SimpleName)) {
return; // TODO: show dialog
}
SimpleName nameNode= (SimpleName) selectedNode;
if (viewer instanceof ITextViewerExtension6) {
IUndoManager undoManager= ((ITextViewerExtension6)viewer).getUndoManager();
if (undoManager instanceof IUndoManagerExtension) {
IUndoManagerExtension undoManagerExtension= (IUndoManagerExtension)undoManager;
IUndoContext undoContext= undoManagerExtension.getUndoContext();
IOperationHistory operationHistory= OperationHistoryFactory.getOperationHistory();
fStartingUndoOperation= operationHistory.getUndoOperation(undoContext);
}
}
fOriginalName= nameNode.getIdentifier();
final int pos= nameNode.getStartPosition();
ASTNode[] sameNodes= LinkedNodeFinder.findByNode(root, nameNode);
//TODO: copied from LinkedNamesAssistProposal#apply(..):
// sort for iteration order, starting with the node @ offset
Arrays.sort(sameNodes, new Comparator<ASTNode>() {
public int compare(ASTNode o1, ASTNode o2) {
return rank(o1) - rank(o2);
}
/**
* Returns the absolute rank of an <code>ASTNode</code>. Nodes
* preceding <code>pos</code> are ranked last.
*
* @param node the node to compute the rank for
* @return the rank of the node with respect to the invocation offset
*/
private int rank(ASTNode node) {
int relativeRank= node.getStartPosition() + node.getLength() - pos;
if (relativeRank < 0)
return Integer.MAX_VALUE + relativeRank;
else
return relativeRank;
}
});
for (int i= 0; i < sameNodes.length; i++) {
ASTNode elem= sameNodes[i];
LinkedPosition linkedPosition= new LinkedPosition(document, elem.getStartPosition(), elem.getLength(), i);
if (i == 0)
fNamePosition= linkedPosition;
fLinkedPositionGroup.addPosition(linkedPosition);
}
fLinkedModeModel= new LinkedModeModel();
fLinkedModeModel.addGroup(fLinkedPositionGroup);
fLinkedModeModel.forceInstall();
fLinkedModeModel.addLinkingListener(new EditorHighlightingSynchronizer(fEditor));
fLinkedModeModel.addLinkingListener(new EditorSynchronizer());
LinkedModeUI ui= new EditorLinkedModeUI(fLinkedModeModel, viewer);
ui.setExitPosition(viewer, offset, 0, Integer.MAX_VALUE);
ui.setExitPolicy(new ExitPolicy(document));
ui.enter();
viewer.setSelectedRange(fOriginalSelection.x, fOriginalSelection.y); // by default, full word is selected; restore original selection
if (viewer instanceof IEditingSupportRegistry) {
IEditingSupportRegistry registry= (IEditingSupportRegistry) viewer;
registry.register(fFocusEditingSupport);
}
openSecondaryPopup();
// startAnimation();
fgActiveLinkedMode= this;
} catch (BadLocationException e) {
JavaPlugin.log(e);
}
}
public VariablePosition(IDocument document, int offset, int length, MultiVariableGuess guess, MultiVariable variable) {
this(document, offset, length, LinkedPositionGroup.NO_STOP, guess, variable);
}