import com.intellij.psi.d.c.d.b.i; import com.intellij.psi.d.c.d.b.b; import com.intellij.psi.d.c.d.b.c; import com.intellij.psi.d.c.d.b.d; import com.intellij.psi.d.c.d.m; import com.intellij.psi.*; import com.intellij.psi.scope.*; import com.intellij.psi.jsp.JspDirective; import com.intellij.psi.jsp.JspAttribute; import com.intellij.psi.jsp.JspImplicitVariable; import com.intellij.openapi.project.Project; import java.util.*; privileged aspect JSP20 { pointcut si() : staticinitialization(i); /** * This adds the additional tag file directive definitions that we need in order to get rid of the squigglies and * populate the autocompletion feature. */ after() : si() { d directives = (d) i.a; addDirectives(directives); } /** * When IntelliJ sets the directives it wants to scan in the file, it lazily does it in the getPageDirectives() method. We * intercept the setting of the variable in this method and tack our additional directives on the end for tag file * directives. */ pointcut setdirectives(m jspfile, JspDirective[] directives) : set(private JspDirective[] m.v) && args(directives) && this(jspfile); void around(m jspfile, JspDirective[] directives) : setdirectives(jspfile, directives) && withincode(public JspDirective[] m.getPageDirectives()) { List list = new ArrayList(); List directiveList = Arrays.asList(directives); list.addAll(directiveList); jspfile.a(list, (PsiElement) jspfile, "tag"); jspfile.a(list, (PsiElement) jspfile, "attribute"); jspfile.a(list, (PsiElement) jspfile, "variable"); directives = (JspDirective[]) list.toArray(new JspDirective[list.size()]); proceed(jspfile, directives); } /** * Tag files have additional implicit variables that are set in directives. We need to find those implicit variables * and put them in the page so IntelliJ can help us out. */ pointcut setvars(m jspfile, JspImplicitVariable[] vars) : set(private JspImplicitVariable[] m.r) && args(vars) && this(jspfile); void around(m jspfile, JspImplicitVariable[] vars) : setvars(jspfile, vars) && withincode(public JspImplicitVariable[] m.x()) { if (!isTagFile(jspfile)) { proceed(jspfile, vars); return; } List list = new ArrayList(); List varsList = Arrays.asList(vars); list.addAll(varsList); list.add(com.intellij.psi.d.c.d.o.a(jspfile.i.getProject()).a(new com.intellij.psi.d.c.d.c(jspfile, "jspContext", "javax.servlet.jsp.JspContext", null))); addAliasesAndAttributes(jspfile, list, jspfile.i.getProject()); vars = (JspImplicitVariable[]) list.toArray(new JspImplicitVariable[list.size()]); proceed(jspfile, vars); } /** * This is the biggest hack. This bascially affects a single string compare when looking for imports in a file. The tag directive is basically the same as the page directive * when it comes to imports. */ pointcut comparemethod() : within(com.intellij.psi.d.c.f.b.b) && withincode(private static com.intellij.psi.d.c.a.c a(com.intellij.psi.PsiManager, java.lang.String, com.intellij.psi.d.c.f.d)); pointcut comparethem(String left, String right) : comparemethod() && (call(public boolean String.equals(Object)) && target(left) && args(right)); boolean around(String left, String right) : comparethem(left, right) { if (right.equals("page") && left.equals("tag")) return true; return proceed(left, right); } /** * In order to include-prelude/coda we need to get the list of patterns, match them to the jspfile. * We would have to add web.xml parsing in order to get the new stuff. I tried a bunch of different things * but the cruxt of the matter is that JSP 1.2 doesn't depend on the web.xml very much. * We might be able to use the same thing that taglibs do to find them, see: com.intellij.j2ee.module.b.f */ private void addDirectives(d directives) { c tag = new c("tag", 1); directives.a(tag); tag.a(new b("import", false, null)); tag.a(new b("display-name", false, null)); String[] bodyContent = new String[] {"scriptless", "tagdependent", "empty"}; tag.a(new b("body-content", false, bodyContent)); tag.a(new b("dynamic-attributes", false, null)); tag.a(new b("small-icon", false, null)); tag.a(new b("large-icon", false, null)); tag.a(new b("description", false, null)); tag.a(new b("example", false, null)); tag.a(new b("pageEncoding", false, null)); tag.a(new b("language", false, null)); String[] trueFalse = new String[] { "true", "false" }; tag.a(new b("isELIgnored", false, trueFalse)); c attribute = new c("attribute", 1); directives.a(attribute); attribute.a(new b("name", true, null)); attribute.a(new b("required", false, trueFalse)); attribute.a(new b("fragment", false, trueFalse)); attribute.a(new b("rtexprvalue", false, trueFalse)); attribute.a(new b("type", false, null)); attribute.a(new b("description", false, null)); c variable = new c("variable", 1); directives.a(variable); variable.a(new b("name-given", false, null)); variable.a(new b("name-from-attribute", false, null)); variable.a(new b("alias", false, null)); variable.a(new b("variable-class", false, null)); variable.a(new b("declare", false, trueFalse)); String[] scope = new String[] { "AT_BEGIN", "AT_END", "NESTED" }; variable.a(new b("scope", false, scope)); variable.a(new b("description", false, null)); } private static boolean isTagFile(m jspfile) { JspDirective ajspdirective[] = (JspDirective[])jspfile.getPageDirectives(); for(int j = 0; j < ajspdirective.length; j++) { JspDirective jspdirective = ajspdirective[j]; if (jspdirective.getName().equals("tag")) return true; } return false; } private void addAliasesAndAttributes(m jspfile, List list, Project project) { JspDirective ajspdirective[] = (JspDirective[])jspfile.getPageDirectives(); for(int j = 0; j < ajspdirective.length; j++) { JspDirective jspdirective = ajspdirective[j]; if (jspdirective.getName().equals("attribute")) { String varName = null; String varType = "java.lang.Object"; PsiElement apsielement[] = (PsiElement[])jspdirective.getChildren(); for(int k = 0; k < apsielement.length; k++) { PsiElement psielement = apsielement[k]; if(!(psielement instanceof JspAttribute)) continue; JspAttribute jspattribute = (JspAttribute)psielement; if(jspattribute.getName().equals("name")) { PsiElement psielement1 = jspattribute.getValueElement(); varName = psielement1.getText(); } if(jspattribute.getName().equals("type")) { PsiElement psielement1 = jspattribute.getValueElement(); varType = psielement1.getText(); } } list.add(com.intellij.psi.d.c.d.o.a(project).a(new com.intellij.psi.d.c.d.c(jspfile, varName, varType, null))); } if (jspdirective.getName().equals("variable")) { String varName = null; String varType = "java.lang.Object"; PsiElement apsielement[] = (PsiElement[])jspdirective.getChildren(); for(int k = 0; k < apsielement.length; k++) { PsiElement psielement = apsielement[k]; if(!(psielement instanceof JspAttribute)) continue; JspAttribute jspattribute = (JspAttribute)psielement; if(jspattribute.getName().equals("name-given") || jspattribute.getName().equals("alias")) { PsiElement psielement1 = jspattribute.getValueElement(); varName = psielement1.getText(); } if(jspattribute.getName().equals("variable-class")) { PsiElement psielement1 = jspattribute.getValueElement(); varType = psielement1.getText(); } } list.add(com.intellij.psi.d.c.d.o.a(project).a(new com.intellij.psi.d.c.d.c(jspfile, varName, varType, null))); } } } }