org.netbeans.modules.csl.api.DeclarationFinder Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.csl.api;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.text.Document;
import org.netbeans.api.annotations.common.CheckForNull;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.modules.csl.spi.ParserResult;
import org.openide.filesystems.FileObject;
/**
*
* @author Tor Norbye
*/
public interface DeclarationFinder {
/**
* Find the declaration for the program element that is under the caretOffset
* Return a Set of regions that should be renamed if the element under the caret offset is
* renamed.
*
* Return {@link DeclarationLocation#NONE} if the declaration can not be found, otherwise return
* a valid DeclarationLocation.
*/
@NonNull
DeclarationLocation findDeclaration(@NonNull ParserResult info, int caretOffset);
/**
* Check the caret offset in the document and determine if it is over a span
* of text that should be hyperlinkable ("Go To Declaration" - in other words,
* locate the reference and return it. When the user drags the mouse with a modifier
* key held this will be hyperlinked, and so on.
*
* Remember that when looking up tokens in the token hierarchy, you will get the token
* to the right of the caret offset, so check for these conditions
* {@code (sequence.move(offset); sequence.offset() == offset)} and check both
* sides such that placing the caret between two tokens will match either side.
*
* @return {@link OffsetRange#NONE} if the caret is not over a valid reference span,
* otherwise return the character range for the given hyperlink tokens
*/
@NonNull
public OffsetRange getReferenceSpan(@NonNull Document doc, int caretOffset);
/**
* Holder object for return values from the DeclarationFinder#findDeclaration method.
* The constant {@link #NONE} object should be returned when finding a declaration failed.
*/
public final class DeclarationLocation {
/** DeclarationLocation representing no match or failure to find declaration */
public static final DeclarationLocation NONE = new DeclarationLocation(null, -1);
private final FileObject fileObject;
private final int offset;
private final URL url;
private List alternatives;
/** Associated element, if any */
private ElementHandle element;
private String invalidMessage;
public DeclarationLocation(@NonNull final FileObject fileObject, final int offset) {
this.fileObject = fileObject;
this.offset = offset;
this.url = null;
}
public DeclarationLocation(@NonNull final FileObject fileObject, final int offset, @NonNull ElementHandle element) {
this(fileObject, offset);
this.element = element;
}
public DeclarationLocation(@NonNull final URL url) {
this.url = url;
this.fileObject = null;
this.offset = -1;
}
/** Mark this declaration location as an "invalid" location (for example,
* in Ruby or JavaScript, a builtin function that has no corresponding source.
* @param invalidMessage A message which will be displayed to the user on attempts to
* go to this declaration location.
*/
public void setInvalidMessage(String invalidMessage) {
this.invalidMessage = invalidMessage;
}
public void addAlternative(@NonNull AlternativeLocation location) {
if (alternatives == null) {
alternatives = new ArrayList();
}
alternatives.add(location);
}
@NonNull
public List getAlternativeLocations() {
if (alternatives != null) {
return alternatives;
} else {
return Collections.emptyList();
}
}
@CheckForNull
public URL getUrl() {
return url;
}
@CheckForNull
public FileObject getFileObject() {
return fileObject;
}
public int getOffset() {
return offset;
}
@CheckForNull
public ElementHandle getElement() {
return element;
}
@CheckForNull
public String getInvalidMessage() {
return invalidMessage;
}
@Override
public String toString() {
if (this == NONE) {
return "NONE";
}
if (url != null) {
return url.toExternalForm();
}
return fileObject.getNameExt() + ":" + offset;
}
}
public interface AlternativeLocation extends Comparable {
ElementHandle getElement();
String getDisplayHtml(HtmlFormatter formatter);
DeclarationLocation getLocation();
}
}