org.eclipse.jface.text.codemining.ICodeMining#org.eclipse.jdt.core.ITypeRoot源码实例Demo

下面列出了org.eclipse.jface.text.codemining.ICodeMining#org.eclipse.jdt.core.ITypeRoot 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。

@Override
public CompletableFuture<List<? extends ICodeMining>> provideCodeMinings(ITextViewer viewer,
		IProgressMonitor monitor) {
	return CompletableFuture.supplyAsync(() -> {
		monitor.isCanceled();
		ITextEditor textEditor = super.getAdapter(ITextEditor.class);
		ITypeRoot unit = EditorUtility.getEditorInputJavaElement(textEditor, true);
		if (unit == null) {
			return Collections.emptyList();
		}
		try {
			IJavaElement[] elements = unit.getChildren();
			List<ICodeMining> minings = new ArrayList<>(elements.length);
			collectMinings(unit, textEditor, unit.getChildren(), minings, viewer, monitor);
			monitor.isCanceled();
			return minings;
		} catch (JavaModelException e) {
			// Should never occur
		}
		return Collections.emptyList();
	});
}
 
源代码2 项目: jdt-codemining   文件: JUnitCodeMiningProvider.java
@Override
public CompletableFuture<List<? extends ICodeMining>> provideCodeMinings(ITextViewer viewer,
		IProgressMonitor monitor) {
	this.viewer = viewer;
	return CompletableFuture.supplyAsync(() -> {
		monitor.isCanceled();
		ITextEditor textEditor = super.getAdapter(ITextEditor.class);
		ITypeRoot unit = EditorUtility.getEditorInputJavaElement(textEditor, true);
		if (unit == null) {
			return null;
		}
		try {
			IJavaElement[] elements = unit.getChildren();
			List<ICodeMining> minings = new ArrayList<>(elements.length);
			collectCodeMinings(unit, elements, minings, viewer, monitor);
			monitor.isCanceled();
			return minings;
		} catch (JavaModelException e) {
			// TODO: what should we done when there are some errors?
		}
		return null;
	});
}
 
private synchronized void initRevisionSupport(ITextViewer viewer, ITypeRoot unit) {
	if (fRevisionInfoSupport != null) {
		return;
	}
	IResource resource = unit.getResource();
	if (resource == null) {
		return;
	}
	if (fRevisionInfoSupport == null) {
		RevisionInformation info = RevisionInformationProviderManager.getInstance().getRevisionInformation(resource,
				viewer, super.getAdapter(ITextEditor.class));
		if (info != null) {
			fRevisionInfoSupport = new RevisionInformationSupport();
			fRevisionInfoSupport.install((ISourceViewer) viewer, info);
		}
	}
}
 
private static String getExpressionBaseName(Expression expr) {
	IBinding argBinding= Bindings.resolveExpressionBinding(expr, true);
	if (argBinding instanceof IVariableBinding) {
		IJavaProject project= null;
		ASTNode root= expr.getRoot();
		if (root instanceof CompilationUnit) {
			ITypeRoot typeRoot= ((CompilationUnit) root).getTypeRoot();
			if (typeRoot != null)
				project= typeRoot.getJavaProject();
		}
		return StubUtility.getBaseName((IVariableBinding)argBinding, project);
	}
	if (expr instanceof SimpleName)
		return ((SimpleName) expr).getIdentifier();
	return null;
}
 
private Object getPackageFragmentObjectToOpen(IPackageFragment packageFragment) throws JavaModelException {
	ITypeRoot typeRoot= null;
	IPackageFragmentRoot root= (IPackageFragmentRoot) packageFragment.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
	if (root.getKind() == IPackageFragmentRoot.K_BINARY)
		typeRoot= (packageFragment).getClassFile(JavaModelUtil.PACKAGE_INFO_CLASS);
	else
		typeRoot= (packageFragment).getCompilationUnit(JavaModelUtil.PACKAGE_INFO_JAVA);
	if (typeRoot.exists())
		return typeRoot;
	
	Object[] nonJavaResources= (packageFragment).getNonJavaResources();
	for (Object nonJavaResource : nonJavaResources) {
		if (nonJavaResource instanceof IFile) {
			IFile file= (IFile) nonJavaResource;
			if (file.exists() && JavaModelUtil.PACKAGE_HTML.equals(file.getName())) {
				return file;
			}
		}
	}
	return packageFragment;
}
 
protected final IStatus calculateASTandInform(ITypeRoot input, ITextSelection selection, IProgressMonitor monitor) {
	if (monitor.isCanceled()) {
		return Status.CANCEL_STATUS;
	}
	// create AST
	try {
		CompilationUnit astRoot= SharedASTProvider.getAST(input, SharedASTProvider.WAIT_ACTIVE_ONLY, monitor);

		if (astRoot != null && !monitor.isCanceled()) {
			Object[] listeners;
			synchronized (PartListenerGroup.this) {
				listeners= fAstListeners.getListeners();
			}
			for (int i= 0; i < listeners.length; i++) {
				((ISelectionListenerWithAST) listeners[i]).selectionChanged(fPart, selection, astRoot);
				if (monitor.isCanceled()) {
					return Status.CANCEL_STATUS;
				}
			}
			return Status.OK_STATUS;
		}
	} catch (OperationCanceledException e) {
		// thrown when canceling the AST creation
	}
	return Status.CANCEL_STATUS;
}
 
public InternalExtendedCompletionContext(
		InternalCompletionContext completionContext,
		ITypeRoot typeRoot,
		CompilationUnitDeclaration compilationUnitDeclaration,
		LookupEnvironment lookupEnvironment,
		Scope assistScope,
		ASTNode assistNode,
		ASTNode assistNodeParent,
		WorkingCopyOwner owner,
		CompletionParser parser) {
	this.completionContext = completionContext;
	this.typeRoot = typeRoot;
	this.compilationUnitDeclaration = compilationUnitDeclaration;
	this.lookupEnvironment = lookupEnvironment;
	this.assistScope = assistScope;
	this.assistNode = assistNode;
	this.assistNodeParent = assistNodeParent;
	this.owner = owner;
	this.parser = parser;
}
 
/**
 * Update internal structures after reconcile.
 * 
 * @param ast the compilation unit AST or <code>null</code> if the working copy was consistent
 *            or reconciliation has been cancelled
 * @param javaElement the Java element for which the AST was built
 * @param progressMonitor the progress monitor
 * @see org.eclipse.jdt.internal.ui.text.java.IJavaReconcilingListener#reconciled(CompilationUnit,
 *      boolean, IProgressMonitor)
 */
void reconciled(CompilationUnit ast, ITypeRoot javaElement, IProgressMonitor progressMonitor) {
	if (DEBUG)
		System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "reconciled: " + toString(javaElement) + ", AST: " + toString(ast)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

	synchronized (fReconcileLock) {
		fIsReconciling= false;
		if (javaElement == null || !javaElement.equals(fReconcilingJavaElement)) {

			if (DEBUG)
				System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "  ignoring AST of out-dated editor"); //$NON-NLS-1$ //$NON-NLS-2$

			// Signal - threads might wait for wrong element
			synchronized (fWaitLock) {
				fWaitLock.notifyAll();
			}

			return;
		}
		cache(ast, javaElement);
	}
}
 
源代码9 项目: eclipse.jdt.ls   文件: JavadocContentAccess.java
/**
 * Gets a reader for an package fragment's Javadoc comment content from the source attachment.
 * The content does contain only the text from the comment without the Javadoc leading star characters.
 * Returns <code>null</code> if the package fragment does not contain a Javadoc comment or if no source is available.
 * @param fragment The package fragment to get the Javadoc of.
 * @return Returns a reader for the Javadoc comment content or <code>null</code> if the member
 * does not contain a Javadoc comment or if no source is available
 * @throws JavaModelException is thrown when the package fragment's javadoc can not be accessed
 * @since 3.4
 */
private static Reader internalGetContentReader(IPackageFragment fragment) throws JavaModelException {
	IPackageFragmentRoot root= (IPackageFragmentRoot) fragment.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);

	//1==> Handle the case when the documentation is present in package-info.java or package-info.class file
	boolean isBinary= root.getKind() == IPackageFragmentRoot.K_BINARY;
	ITypeRoot packageInfo;
	if (isBinary) {
		packageInfo= fragment.getClassFile(PACKAGE_INFO_CLASS);
	} else {
		packageInfo= fragment.getCompilationUnit(PACKAGE_INFO_JAVA);
	}
	if (packageInfo != null && packageInfo.exists()) {
		String source = packageInfo.getSource();
		//the source can be null for some of the class files
		if (source != null) {
			Javadoc javadocNode = getPackageJavadocNode(fragment, source);
			if (javadocNode != null) {
				int start = javadocNode.getStartPosition();
				int length = javadocNode.getLength();
				return new JavaDocCommentReader(source, start, start + length - 1);
			}
		}
	}
	return null;
}
 
public boolean equals(Object o) {
	if (this == o)
		return true;
	/* I see cases where equal lambdas are dismissed as unequal on account of working copy owner.
	   This results in spurious failures. See JavaSearchBugs8Tests.testBug400905_0021()
	   For now exclude the working copy owner and compare
	*/
	if (o instanceof LambdaExpression) {
		LambdaExpression that = (LambdaExpression) o;
		if (this.sourceStart != that.sourceStart)
			return false;
		ITypeRoot thisTR = this.getTypeRoot();
		ITypeRoot thatTR = that.getTypeRoot();
		return thisTR.getElementName().equals(thatTR.getElementName()) && thisTR.getParent().equals(thatTR.getParent());
	}
	return false;
}
 
private static String getInfoText(IJavaElement element, ITypeRoot editorInputElement, IRegion hoverRegion, boolean allowImage) {
		long flags= getHeaderFlags(element);
		StringBuffer label= new StringBuffer(JavaElementLinks.getElementLabel(element, flags));
		
		if (element.getElementType() == IJavaElement.FIELD) {
			String constantValue= getConstantValue((IField) element, editorInputElement, hoverRegion);
			if (constantValue != null) {
				constantValue= HTMLPrinter.convertToHTMLContentWithWhitespace(constantValue);
				IJavaProject javaProject= element.getJavaProject();
				label.append(getFormattedAssignmentOperator(javaProject));
				label.append(constantValue);
			}
		}

//		if (element.getElementType() == IJavaElement.METHOD) {
//			IMethod method= (IMethod)element;
//			//TODO: add default value for annotation type members, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=249016
//		}

		return getImageAndLabel(element, allowImage, label.toString());
	}
 
protected void installOccurrencesFinder(boolean forceUpdate) {
	fMarkOccurrenceAnnotations= true;

	fPostSelectionListenerWithAST= new ISelectionListenerWithAST() {
		public void selectionChanged(IEditorPart part, ITextSelection selection, CompilationUnit astRoot) {
			updateOccurrenceAnnotations(selection, astRoot);
		}
	};
	SelectionListenerWithASTManager.getDefault().addListener(this, fPostSelectionListenerWithAST);
	if (forceUpdate && getSelectionProvider() != null) {
		fForcedMarkOccurrencesSelection= getSelectionProvider().getSelection();
		ITypeRoot inputJavaElement= getInputJavaElement();
		if (inputJavaElement != null)
			updateOccurrenceAnnotations((ITextSelection)fForcedMarkOccurrencesSelection, SharedASTProvider.getAST(inputJavaElement, SharedASTProvider.WAIT_NO, getProgressMonitor()));
	}

	if (fOccurrencesFinderJobCanceler == null) {
		fOccurrencesFinderJobCanceler= new OccurrencesFinderJobCanceler();
		fOccurrencesFinderJobCanceler.install();
	}
}
 
源代码13 项目: eclipse.jdt.ls   文件: DocumentHighlightHandler.java
private DocumentHighlight convertToHighlight(ITypeRoot unit, OccurrenceLocation occurrence)
		throws JavaModelException {
	DocumentHighlight h = new DocumentHighlight();
	if ((occurrence.getFlags() | IOccurrencesFinder.F_WRITE_OCCURRENCE) == IOccurrencesFinder.F_WRITE_OCCURRENCE) {
		h.setKind(DocumentHighlightKind.Write);
	} else if ((occurrence.getFlags()
			| IOccurrencesFinder.F_READ_OCCURRENCE) == IOccurrencesFinder.F_READ_OCCURRENCE) {
		h.setKind(DocumentHighlightKind.Read);
	}
	int[] loc = JsonRpcHelpers.toLine(unit.getBuffer(), occurrence.getOffset());
	int[] endLoc = JsonRpcHelpers.toLine(unit.getBuffer(), occurrence.getOffset() + occurrence.getLength());

	h.setRange(new Range(
			new Position(loc[0], loc[1]),
			new Position(endLoc[0],endLoc[1])
			));
	return h;
}
 
@Override
public IRegion getHoverRegion(ITextViewer textViewer, int offset) {
	if (!(getEditor() instanceof JavaEditor))
		return null;

	ITypeRoot je= getEditorInputJavaElement();
	if (je == null)
		return null;

	// Never wait for an AST in UI thread.
	CompilationUnit ast= SharedASTProvider.getAST(je, SharedASTProvider.WAIT_NO, null);
	if (ast == null)
		return null;

	ASTNode node= NodeFinder.perform(ast, offset, 1);
	if (node instanceof StringLiteral) {
		StringLiteral stringLiteral= (StringLiteral)node;
		return new Region(stringLiteral.getStartPosition(), stringLiteral.getLength());
	} else if (node instanceof SimpleName) {
		SimpleName simpleName= (SimpleName)node;
		return new Region(simpleName.getStartPosition(), simpleName.getLength());
	}

	return null;
}
 
/**
 * Returns the constant value for the given field.
 *
 * @param field the field
 * @param editorInputElement the editor input element
 * @param hoverRegion the hover region in the editor
 * @return the constant value for the given field or <code>null</code> if none
 * @since 3.4
 */
private static String getConstantValue(IField field, ITypeRoot editorInputElement, IRegion hoverRegion) {
	if (!isStaticFinal(field))
		return null;

	ASTNode node= getHoveredASTNode(editorInputElement, hoverRegion);
	if (node == null)
		return null;

	Object constantValue= getVariableBindingConstValue(node, field);
	if (constantValue == null)
		return null;

	if (constantValue instanceof String) {
		return ASTNodes.getEscapedStringLiteral((String) constantValue);
	} else {
		return getHexConstantValue(constantValue);
	}
}
 
@Override
public void run(ITextSelection selection) {
	if (!ActionUtil.isEditable(fEditor))
		return;

	ITypeRoot typeRoot= SelectionConverter.getInput(fEditor);
	if (typeRoot == null)
		return;

	CompilationUnit node= RefactoringASTParser.parseWithASTProvider(typeRoot, true, null);

	if (typeRoot instanceof ICompilationUnit) {
		ICompilationUnit cu= (ICompilationUnit) typeRoot;
		if (fInlineTemp.isEnabled() && fInlineTemp.tryInlineTemp(cu, node, selection, getShell()))
			return;

		if (fInlineConstant.isEnabled() && fInlineConstant.tryInlineConstant(cu, node, selection, getShell()))
			return;
	}
	//InlineMethod is last (also tries enclosing element):
	if (fInlineMethod.isEnabled() && fInlineMethod.tryInlineMethod(typeRoot, node, selection, getShell()))
		return;

	MessageDialog.openInformation(getShell(), RefactoringMessages.InlineAction_dialog_title, RefactoringMessages.InlineAction_select);
}
 
protected void setExtendedData(
		ITypeRoot typeRoot,
		CompilationUnitDeclaration compilationUnitDeclaration,
		LookupEnvironment lookupEnvironment,
		Scope scope,
		ASTNode astNode,
		ASTNode astNodeParent,
		WorkingCopyOwner owner,
		CompletionParser parser) {
	this.isExtended = true;
	this.extendedContext =
		new InternalExtendedCompletionContext(
				this,
				typeRoot,
				compilationUnitDeclaration,
				lookupEnvironment,
				scope,
				astNode,
				astNodeParent,
				owner,
				parser);
}
 
源代码18 项目: jdt-codemining   文件: JavaASTCodeMiningProvider.java
private void collectCodeMinings(ITypeRoot unit, ITextEditor textEditor, ITextViewer viewer,
		List<ICodeMining> minings) {
	CompilationUnit cu = SharedASTProvider.getAST(unit, SharedASTProvider.WAIT_YES, null);
	JavaCodeMiningASTVisitor visitor = new JavaCodeMiningASTVisitor(cu, textEditor, viewer, minings, this);
	visitor.setShowParameterName(showParameterName);
	visitor.setShowParameterType(showParameterType);
	visitor.setShowParameterOnlyForLiteral(showParameterOnlyForLiteral);
	visitor.setShowParameterByUsingFilters(showParameterByUsingFilters);
	visitor.setShowEndStatement(showEndStatement);
	visitor.setEndStatementMinLineNumber(endStatementMinLineNumber);
	visitor.setShowJava10VarType(showJava10VarType);
	cu.accept(visitor);
}
 
/**
 * Informs that reconciling for the given element is about to be started.
 *
 * @param javaElement the Java element
 * @see org.eclipse.jdt.internal.ui.text.java.IJavaReconcilingListener#aboutToBeReconciled()
 */
void aboutToBeReconciled(ITypeRoot javaElement) {

	if (javaElement == null)
		return;

	if (DEBUG)
		System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "about to reconcile: " + toString(javaElement)); //$NON-NLS-1$ //$NON-NLS-2$

	synchronized (fReconcileLock) {
		fReconcilingJavaElement= javaElement;
		fIsReconciling= true;
	}
	cache(null, javaElement);
}
 
@Override
public boolean select(Viewer viewer, Object parent, Object element) {
	if (element instanceof ITypeRoot)
		return false;

	if (element instanceof IPackageFragment)
		try {
			return ((IPackageFragment)element).getNonJavaResources().length > 0;
		} catch (JavaModelException ex) {
			return true;
		}
	return true;
}
 
源代码21 项目: JDeodorant   文件: ASTNodeMatcher.java
public ASTNodeMatcher(ITypeRoot root1, ITypeRoot root2) {
	this.differences = new ArrayList<ASTNodeDifference>();
	this.typeRoot1 = root1;
	this.typeRoot2 = root2;
	this.additionallyMatchedFragments1 = new ArrayList<AbstractMethodFragment>();
	this.additionallyMatchedFragments2 = new ArrayList<AbstractMethodFragment>();
}
 
@Override
public final  void run() {
	IJavaElement inputElement= EditorUtility.getEditorInputJavaElement(fEditor, false);
	if (!(inputElement instanceof ITypeRoot && inputElement.exists()))
		return;

	ITypeRoot typeRoot= (ITypeRoot) inputElement;
	ISourceRange sourceRange;
	try {
		sourceRange= typeRoot.getSourceRange();
		if (sourceRange == null || sourceRange.getLength() == 0) {
			MessageDialog.openInformation(fEditor.getEditorSite().getShell(),
				SelectionActionMessages.StructureSelect_error_title,
				SelectionActionMessages.StructureSelect_error_message);
			return;
		}
	} catch (JavaModelException e) {
	}
	ITextSelection selection= getTextSelection();
	ISourceRange newRange= getNewSelectionRange(createSourceRange(selection), typeRoot);
	// Check if new selection differs from current selection
	if (selection.getOffset() == newRange.getOffset() && selection.getLength() == newRange.getLength())
		return;
	fSelectionHistory.remember(new SourceRange(selection.getOffset(), selection.getLength()));
	try {
		fSelectionHistory.ignoreSelectionChanges();
		fEditor.selectAndReveal(newRange.getOffset(), newRange.getLength());
	} finally {
		fSelectionHistory.listenToSelectionChanges();
	}
}
 
源代码23 项目: xtext-eclipse   文件: TraceForTypeRootProvider.java
@Override
public IEclipseTrace getTraceToSource(final ITypeRoot derivedJavaType) {
	if (lruCache != null && lruCache.getFirst().equals(derivedJavaType))
		return lruCache.getSecond();
	IEclipseTrace trace = createTraceToSource(derivedJavaType);
	if (derivedJavaType.isReadOnly()) {
		lruCache = Tuples.<ITypeRoot, IEclipseTrace> create(derivedJavaType, trace);
	}
	return trace;
}
 
源代码24 项目: xtext-eclipse   文件: TraceForTypeRootProvider.java
private IEclipseTrace createTraceToSource(final ITypeRoot derivedJavaType) {
	if (derivedJavaType instanceof IClassFile)
		return getTraceToSource((IClassFile) derivedJavaType);
	if (derivedJavaType instanceof ICompilationUnit)
		return getTraceToSource((ICompilationUnit) derivedJavaType);
	throw new IllegalStateException("Unknown type " + derivedJavaType);
}
 
源代码25 项目: eclipse.jdt.ls   文件: ProjectCommand.java
/**
 * public visibility only for test purpose
 */
public static IJavaProject getJavaProjectFromUri(String uri) throws CoreException, URISyntaxException {
	ITypeRoot typeRoot = JDTUtils.resolveTypeRoot(uri);
	if (typeRoot != null) {
		IJavaProject javaProject = typeRoot.getJavaProject();
		if (javaProject == null) {
			throw new CoreException(new Status(IStatus.ERROR, IConstants.PLUGIN_ID, "Given URI does not belong to an existing Java project."));
		}
		return javaProject;
	}

	// check for project root uri
	IContainer[] containers = ResourcesPlugin.getWorkspace().getRoot().findContainersForLocationURI(new URI(uri));
	if (containers == null || containers.length == 0) {
		throw new CoreException(new Status(IStatus.ERROR, IConstants.PLUGIN_ID, "Given URI does not belong to any Java project."));
	}

	// For multi-module scenario
	Arrays.sort(containers, (Comparator<IContainer>) (IContainer a, IContainer b) -> {
		return a.getFullPath().toPortableString().length() - b.getFullPath().toPortableString().length();
	});

	IJavaElement targetElement = null;
	for (IContainer container : containers) {
		targetElement = JavaCore.create(container);
		if (targetElement != null) {
			break;
		}
	}

	if (targetElement == null || targetElement.getJavaProject() == null) {
		throw new CoreException(new Status(IStatus.ERROR, IConstants.PLUGIN_ID, "Given URI does not belong to any Java project."));
	}

	return targetElement.getJavaProject();
}
 
@Override
public void run(ITextSelection selection) {
	if (!ActionUtil.isProcessable(fEditor))
		return;
	ITypeRoot editorInput= SelectionConverter.getInput(fEditor);
	if (!ActionUtil.isEditable(getShell(), editorInput))
		return;
	if (editorInput instanceof ICompilationUnit)
		run(selection.getOffset(), selection.getLength(), (ICompilationUnit) editorInput);
	else if (editorInput instanceof IClassFile)
		run(selection.getOffset(), selection.getLength(), (IClassFile) editorInput);
}
 
源代码27 项目: eclipse.jdt.ls   文件: JDTUtils.java
public static String toUri(ITypeRoot typeRoot) {
	if (typeRoot instanceof ICompilationUnit) {
		return toURI((ICompilationUnit) typeRoot);
	}
	if (typeRoot instanceof IClassFile) {
		return toUri((IClassFile) typeRoot);
	}
	return null;
}
 
static CompilationUnit getCompilationUnitNode(IMember member, boolean resolveBindings) {
	ITypeRoot typeRoot= member.getTypeRoot();
    try {
 	if (typeRoot.exists() && typeRoot.getBuffer() != null) {
ASTParser parser= ASTParser.newParser(ASTProvider.SHARED_AST_LEVEL);
parser.setSource(typeRoot);
parser.setResolveBindings(resolveBindings);
return (CompilationUnit) parser.createAST(null);
 	}
    } catch (JavaModelException e) {
        JavaPlugin.log(e);
    }
    return null;
}
 
public Object[] getElements(Object parent) {
	if (fTopLevelTypeOnly) {
		if (parent instanceof ITypeRoot) {
			try {
				IType type= ((ITypeRoot) parent).findPrimaryType();
				return type != null ? type.getChildren() : NO_CLASS;
			} catch (JavaModelException e) {
				JavaPlugin.log(e);
			}
		}
	}
	return getChildren(parent);
}
 
public static IJavaElement getElementAtOffset(ITypeRoot input, ITextSelection selection) throws JavaModelException {
	if (input instanceof ICompilationUnit) {
		JavaModelUtil.reconcile((ICompilationUnit) input);
	}
	IJavaElement ref= input.getElementAt(selection.getOffset());
	if (ref == null)
		return input;
	return ref;
}