blob: 32dc0b38f4e6718d62c8b70affc58dbf4339cb2e [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2009, 2020 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.ltk.core;
import java.util.List;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.statet.jcommons.text.core.TextRegion;
import org.eclipse.statet.ltk.model.core.elements.IModelElement;
import org.eclipse.statet.ltk.model.core.elements.ISourceElement;
import org.eclipse.statet.ltk.model.core.elements.ISourceStructElement;
import org.eclipse.statet.ltk.model.core.elements.ISourceUnit;
public class LTKUtils {
public static IModelElement getModelElement(final Object element) {
if (element instanceof IModelElement) {
return (IModelElement) element;
}
if (element instanceof IAdaptable) {
return ((IAdaptable) element).getAdapter(IModelElement.class);
}
return null;
}
public static ISourceUnit getSourceUnit(final IModelElement element) {
if (element instanceof ISourceUnit) {
return (ISourceUnit) element;
}
if (element instanceof ISourceElement) {
return ((ISourceElement) element).getSourceUnit();
}
return null;
}
public static ISourceStructElement getCoveringSourceElement(final ISourceStructElement root, final TextRegion region) {
return getCoveringSourceElement(root, region.getStartOffset(), region.getEndOffset());
}
public static ISourceStructElement getCoveringSourceElement(final ISourceStructElement root,
final int startOffset, final int endOffset) {
ISourceStructElement ok= root;
CHECK: while (ok != null) {
final List<? extends ISourceStructElement> children= ok.getSourceChildren(null);
for (final ISourceStructElement child : children) {
final TextRegion sourceRange= child.getSourceRange();
final TextRegion docRange= child.getDocumentationRange();
final int childOffset= (docRange != null) ?
Math.min(sourceRange.getStartOffset(), docRange.getStartOffset()) :
sourceRange.getStartOffset();
if (startOffset >= childOffset) {
final int childEnd= (docRange != null) ?
Math.max(sourceRange.getEndOffset(), docRange.getEndOffset()) :
sourceRange.getEndOffset();
if ((startOffset < endOffset) ?
(endOffset <= childEnd) : (endOffset < childEnd)) {
ok= child;
continue CHECK;
}
}
else {
break CHECK;
}
}
break CHECK;
}
return ok;
}
public static int searchCoveringSourceElement(final List<? extends ISourceStructElement> elements,
final int offset) {
// binary search
int low= 0;
int high= elements.size() - 1;
while (low <= high) {
final int mid= (low + high) >> 1;
final TextRegion region= elements.get(mid).getSourceRange();
if (region.getEndOffset() < offset) {
low= mid + 1;
}
else if (region.getStartOffset() > offset) {
high= mid - 1;
}
else {
return mid;
}
}
return -(low + 1);
}
public static <T extends ISourceStructElement> T getCoveringSourceElement(final List<T> elements,
final int offset) {
final int idx= searchCoveringSourceElement(elements, offset);
if (idx >= 0) {
return elements.get(idx);
}
return null;
}
}