|
What this is
Other links
The source code/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is NetBeans. The Initial Developer of the Original
* Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
* Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.modules.web.core.syntax;
import java.io.File;
import java.util.*;
import java.io.IOException;
import java.net.URL;
import javax.swing.text.BadLocationException;
import javax.swing.text.EditorKit;
import javax.swing.JEditorPane;
import javax.swing.text.JTextComponent;
import javax.servlet.jsp.tagext.*;
import org.openide.filesystems.FileObject;
import org.openide.ErrorManager;
import org.openide.loaders.DataObject;
import org.netbeans.modules.web.jsps.parserapi.JspParserAPI;
import org.netbeans.modules.web.jsps.parserapi.PageInfo;
import org.netbeans.editor.*;
import org.netbeans.editor.ext.ExtSyntaxSupport;
import org.netbeans.editor.ext.html.HTMLTokenContext;
import org.netbeans.editor.ext.java.JavaSyntaxSupport;
import org.netbeans.editor.ext.java.JavaTokenContext;
import org.netbeans.modules.editor.NbEditorUtilities;
import java.util.*;
import org.openide.filesystems.FileUtil;
import org.openide.modules.InstalledFileLocator;
/**
*
* @author Petr Jiricka, Petr Nejedly
*/
public class JspSyntaxSupport extends ExtSyntaxSupport {
/** ErrorManager shared by whole module (package) for logging */
static final ErrorManager err =
ErrorManager.getDefault().getInstance("org.netbeans.modules.web.jspsyntax"); // NOI18N
/* Constants for various contexts in the text from the point of
view of JSP completion.*/
/** Completion context for JSP tags (standard or custom) */
public static final int TAG_COMPLETION_CONTEXT = 1;
/** Completion context for JSP end tags (standard or custom) */
public static final int ENDTAG_COMPLETION_CONTEXT = 2;
/** Completion context for JSP directives */
public static final int DIRECTIVE_COMPLETION_CONTEXT = 3;
/** Completion context for JSP comments */
public static final int COMMENT_COMPLETION_CONTEXT = 4;
/** Completion context for other JSP text - such as body of custom tags
* with TAG_DEPENDENT body content. */
public static final int TEXT_COMPLETION_CONTEXT = 5;
/** Completion context for the content language */
public static final int CONTENTL_COMPLETION_CONTEXT = 6;
/** Completion context for the scripting language */
public static final int SCRIPTINGL_COMPLETION_CONTEXT = 7;
/** Completion context for error */
public static final int ERROR_COMPLETION_CONTEXT = 8;
private static final String STANDARD_JSP_PREFIX = "jsp"; // NOI18N
/** Data for completion: TreeMap for standard JSP tags
* (tag name, array of attributes). */
private static TagInfo[] standardJspTagDatas;
private static TagInfo[] standardTagTagDatas;
/** Data for completion, when the jsp page is in XML syntax
**/
private static TagInfo[] xmlJspTagDatas;
/** Data for completion, when the tag file is in XML syntax
**/
private static TagInfo[] xmlTagFileTagDatas;
/** Data for completion: TreeMap for JSP directives
* (directive name, array of attributes). */
private static TagInfo[] directiveJspData;
private static TagInfo[] directiveTagFileData;
/** Mapping the URI of tag library -> URL where the help files are.
*/
private static HashMap helpMap = null;
private static final TokenID[] JSP_BRACKET_SKIP_TOKENS = new TokenID[] {
JavaTokenContext.LINE_COMMENT,
JavaTokenContext.BLOCK_COMMENT,
JavaTokenContext.CHAR_LITERAL,
JavaTokenContext.STRING_LITERAL,
JspTagTokenContext.ATTR_VALUE,
JspTagTokenContext.COMMENT
};
protected FileObject fobj;
/** Content language SyntaxSupport cached for getContentLanguageSyntaxSupport */
private ExtSyntaxSupport contentLanguageSyntaxSupport = null;
/** Special bracket finder is used when caret is in JSP context */
private boolean useCustomBracketFinder = true;
private boolean isXmlSyntax = false;
/** Creates new HTMLSyntaxSupport */
public JspSyntaxSupport(BaseDocument doc, boolean isXml) {
super(doc);
fobj = null;
if (doc != null){
DataObject dobj = NbEditorUtilities.getDataObject(doc);
fobj = (dobj != null) ? NbEditorUtilities.getDataObject(doc).getPrimaryFile(): null;
}
isXmlSyntax = isXml;
}
public JspSyntaxSupport(BaseDocument doc) {
this(doc, false);
}
public boolean isXmlSyntax(){
return isXmlSyntax;
}
protected JspParserAPI.ParseResult getParseResult() {
JspParserAPI.ParseResult result = JspUtils.getCachedParseResult(getDocument(), fobj, true, false);
if (result == null) {
result = JspUtils.getCachedParseResult(getDocument(), fobj, false, false);
}
return result;
}
/** Returns a map of prefix -> URI that maps tag libraries on prefixes.
* For the XML syntax this mapping may only be approximate.
*/
private Map getPrefixMapper() {
// PENDING - must also take xmlPrefixMapper into account
JspParserAPI.ParseResult result = getParseResult();
Map prefixMapper = null;
if (result != null && result.getPageInfo() != null) {
//if (result.isParsingSuccess()) {
// PENDING - can we somehow get incomplete parsed information ?
if (result.getPageInfo().getXMLPrefixMapper().size() > 0) {
prefixMapper = result.getPageInfo().getApproxXmlPrefixMapper();
if (prefixMapper.size() == 0){
prefixMapper = result.getPageInfo().getXMLPrefixMapper();
}
prefixMapper.putAll(result.getPageInfo().getJspPrefixMapper());
}
else {
prefixMapper = result.getPageInfo().getJspPrefixMapper();
}
//}
}
return prefixMapper;
}
private Map getTagLibraries() {
JspParserAPI.ParseResult result = getParseResult();
if (result != null) {
return result.getPageInfo().getTagLibraries();
}
return null;
}
private TagLibraryInfo getTagLibrary(String prefix) {
Map mapper = getPrefixMapper();
if (mapper != null) {
Object uri = mapper.get(prefix);
if (uri != null) {
Map taglibs = getTagLibraries();
if (taglibs != null) {
return (TagLibraryInfo)taglibs.get(uri);
}
}
}
return null;
}
protected SyntaxSupport createSyntaxSupport(Class syntaxSupportClass) {
if (syntaxSupportClass.isAssignableFrom (JspJavaSyntaxSupport.class)) {
return new JspJavaSyntaxSupport(getDocument(), this);
}
SyntaxSupport support = super.createSyntaxSupport(syntaxSupportClass);
if (support != null)
return support;
//System.out.println("JspSyntaxSupport- createSyntaxSupport - " + NbEditorUtilities.getMimeType(getDocument()) );
EditorKit kit;
// try the content language support
kit = JEditorPane.createEditorKitForContentType(JspUtils.getContentLanguage());
if (kit instanceof BaseKit) {
support = ((BaseKit)kit).createSyntaxSupport(getDocument());
if (support != null)
return support;
}
// try the scripting language support
kit = JEditorPane.createEditorKitForContentType(JspUtils.getScriptingLanguage());
if (kit instanceof BaseKit) {
support = ((BaseKit)kit).createSyntaxSupport(getDocument());
if (support != null)
return support;
}
return null;
}
/** Returns SyntaxSupport corresponding to content type of JSP data object.
* HTMLSyntaxSupport is used when we can't find it. */
protected ExtSyntaxSupport getContentLanguageSyntaxSupport() {
if (contentLanguageSyntaxSupport != null) {
return contentLanguageSyntaxSupport;
}
EditorKit kit =
JEditorPane.createEditorKitForContentType(JspUtils.getContentLanguage());
if (kit instanceof BaseKit) {
SyntaxSupport support = ((BaseKit)kit).createSyntaxSupport(getDocument());
if (support != null && support instanceof ExtSyntaxSupport) {
contentLanguageSyntaxSupport = (ExtSyntaxSupport) support;
return contentLanguageSyntaxSupport;
}
}
return (ExtSyntaxSupport)get( org.netbeans.editor.ext.html.HTMLSyntaxSupport.class );
}
/** This method decides what kind of completion (html, java, jsp-tag, ...) should be opened
* or whether the completion window should be closed if it is opened.
*/
public int checkCompletion(JTextComponent target, String typedText, boolean visible ) {
char first = typedText.charAt(0); //get typed char
TokenItem item = null; //get token on the cursor
try{
item = getItemAtOrBefore(target.getCaret().getDot());
}catch(BadLocationException e) {
return COMPLETION_HIDE;
}
if (item == null) return COMPLETION_HIDE;
TokenContextPath tcp = item.getTokenContextPath();
//System.out.println("typed '" + first + "' ;token = " + item);
if(tcp.contains(HTMLTokenContext.contextPath)) {
//we are in content language
if (err.isLoggable(ErrorManager.INFORMATIONAL)) err.log("CONTENTL_COMPLETION_CONTEXT"); // NOI18N
ExtSyntaxSupport support = getContentLanguageSyntaxSupport();
if (support != null) {
return support.checkCompletion( target, typedText, visible );
}
}
if(tcp.contains(JavaTokenContext.contextPath)) {
//we are in scripting language
if (err.isLoggable(ErrorManager.INFORMATIONAL)) err.log("SCRIPTINGL_COMPLETION_CONTEXT" ); // NOI18N
if (JspUtils.getScriptingLanguage().equals("text/x-java")) { // NOI18N
return ((ExtSyntaxSupport)get( org.netbeans.editor.ext.java.JavaSyntaxSupport.class )).checkCompletion( target, typedText, visible );
}
}
//JSP tag or directive
if(tcp.contains(JspTagTokenContext.contextPath)) {
//need to distinguish tag/end_tag/directive - search back throught the token chain for <%@ , which is recognized as a JspTagToken, but before that there are java tokens
if(image.equals("%>")) return COMPLETION_HIDE;
if(tracking.getImage().startsWith("<%")) {
//we are in a directive
if (err.isLoggable(ErrorManager.INFORMATIONAL)) err.log("DIRECTIVE_COMPLETION_CONTEXT"); // NOI18N
//open completion also in such a case: <%=|
if( !visible && first == '=' && tracking.getImage().equals("<%")) return COMPLETION_POPUP;
if( !visible && first == '%' || first == '@' || first == ' ' ) return COMPLETION_POPUP;
if( visible && first == '=' || first == '>' ) return COMPLETION_HIDE;
return visible ? COMPLETION_POST_REFRESH : COMPLETION_CANCEL;
}
if(tracking.getImage().equals("<")) {
//we are in a tag
if (err.isLoggable(ErrorManager.INFORMATIONAL)) err.log("TAG_COMPLETION_CONTEXT"); // NOI18N
if( !visible && first == ' ' || first == ':' ) return COMPLETION_POPUP;
if( visible && first == '>' ) return COMPLETION_HIDE;
return visible ? COMPLETION_POST_REFRESH : COMPLETION_CANCEL;
}
if(tracking.getImage().equals("' ) return COMPLETION_HIDE;
return visible ? COMPLETION_POST_REFRESH : COMPLETION_CANCEL;
}
//test whether we are still in the tag context
if(!tracking.getTokenContextPath().contains(JspTagTokenContext.contextPath)) {
ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, new IllegalStateException("we are out of jsp tag without finding any tag start token!"));
break;
}
//search previous token
tracking = tracking.getPrevious();
} while(maxBacktrace-- > 0);
}//eof JSP tag
if(tcp.contains(ELTokenContext.contextPath)) {
//we are in expression language - we do not provide any code completion so far
if (visible) return COMPLETION_HIDE;
}
return COMPLETION_HIDE;
}
/** Returns offset where the next offset after this offset starts. */
private final int getTokenEnd( TokenItem item ) {
if (item == null)
return 0; //getDocument().getLength();
return item.getOffset() + item.getImage().length();
}
/** Filters list of strings so only strings starting
* with a given prefix are returned in the new List. */
public final List filterList(List toFilter, String prefix) {
List newList = new ArrayList();
Object item;
for (int i = 0; i < toFilter.size(); i++) {
item = toFilter.get(i);
String txt;
if (item instanceof TagInfo)
txt = ((TagInfo)item).getTagName ();
else if (item instanceof TagAttributeInfo)
txt = ((TagAttributeInfo)item).getName ();
else
txt = (String)item;
if (txt != null && txt.startsWith(prefix)) {
newList.add(item);
}
}
return newList;
}
/** Gets all 'jsp prefixes' whose 'string prefix' matches complPrefix as a list of Strings. */
protected final List getTagPrefixes(String complPrefix) {
return filterList(getAllTagPrefixes(), complPrefix);
}
/** Gets all tags whose 'string prefix' matches complPrefix as a list of Strings.
* Assumes that complPrefix also includes the 'jsp prefix'.
*/
protected final List getTags(String complPrefix) {
int colonIndex = complPrefix.indexOf(":"); // NOI18N
if (colonIndex == -1)
throw new IllegalArgumentException();
return getTags(complPrefix.substring(0, colonIndex),
complPrefix.substring(colonIndex + 1));
}
/** Gets all tags whose 'string prefix' matches complPrefix and whose 'jsp prefix'
* is tagPrefix as a list of Strings.
* Assumes that complPrefix does not include the 'jsp prefix'.
*/
protected final List getTags(String tagPrefix, String complPrefix) {
return filterList(getAllTags(tagPrefix), complPrefix);
}
/** Gets attributes for tag whose prefix + name
* is tagPrefixName as a list of Strings.
* The attribute's 'string prefix' must match complPrefix.
*/
protected final List getTagAttributes(String tagPrefixName, String complPrefix) {
int colonIndex = tagPrefixName.indexOf(":"); // NOI18N
if (colonIndex == -1)
throw new IllegalArgumentException();
return getTagAttributes(tagPrefixName.substring(0, colonIndex),
tagPrefixName.substring(colonIndex + 1), complPrefix);
}
/** Gets attributes for tag whose 'jsp prefix'
* is tagPrefix and whose tag name is tagName as a list of Strings.
* The attribute's 'string prefix' must match complPrefix.
*/
protected final List getTagAttributes(String tagPrefix, String tagName, String complPrefix) {
return filterList(getAllTagAttributes(tagPrefix, tagName), complPrefix);
}
/** Gets all directives whose 'string prefix' matches complPrefix as a list of Strings. */
protected final List getDirectives(String complPrefix) {
return filterList(getAllDirectives(), complPrefix);
}
/** Gets attributes for directive
|
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.