Author: akazakov
Date: 2008-02-12 13:08:02 -0500 (Tue, 12 Feb 2008)
New Revision: 6280
Added:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/el/ElVarSearcher.java
Modified:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/el/SeamELCompletionEngine.java
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/el/SeamELTokenizer.java
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/el/SeamPromptingProvider.java
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamCoreValidator.java
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamELValidator.java
trunk/seam/plugins/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/text/java/SeamELProposalProcessor.java
Log:
Added:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/el/ElVarSearcher.java
===================================================================
---
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/el/ElVarSearcher.java
(rev 0)
+++
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/el/ElVarSearcher.java 2008-02-12
18:08:02 UTC (rev 6280)
@@ -0,0 +1,128 @@
+ /*******************************************************************************
+ * Copyright (c) 2007 Red Hat, Inc.
+ * Distributed under license by Red Hat, Inc. All rights reserved.
+ * This program is made available under the terms of the
+ * Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at
http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ ******************************************************************************/
+package org.jboss.tools.seam.internal.core.el;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * This class helps to find var/value attributes in DOM tree.
+ * @author Alexey Kazakov
+ */
+public class ElVarSearcher {
+
+ private final static String VAR_ATTRIBUTE_NAME = "var";
+ private final static String VALUE_ATTRIBUTE_NAME = "value";
+
+ /**
+ * @param node
+ * @return All var/value that can be used in node and null if can't find anyone.
+ */
+ public static List<Var> findAllVars(Node node) {
+ ArrayList<Var> vars = null;
+ Node parentNode = node.getParentNode();
+ while(parentNode!=null) {
+ Var var = findVar(parentNode);
+ if(var!=null) {
+ if(vars == null) {
+ vars = new ArrayList<Var>();
+ }
+ vars.add(var);
+ }
+ parentNode = parentNode.getParentNode();
+ }
+ return vars;
+ }
+
+ /**
+ * Finds var/value attribute in node
+ * @param node
+ * @param vars
+ * @return found var/value or null
+ */
+ public static Var findVar(Node node) {
+ if(node!=null && Node.ELEMENT_NODE == node.getNodeType()) {
+ Element element = (Element)node;
+ String var = element.getAttribute(VAR_ATTRIBUTE_NAME);
+ if(var!=null) {
+ var = var.trim();
+ if(!"".equals(var)) {
+ String value = element.getAttribute(VALUE_ATTRIBUTE_NAME);
+ if(value!=null) {
+ value = value.trim();
+ Var newVar = new Var(var, value);
+ if(newVar.getElToken()!=null) {
+ return newVar;
+ }
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Represents "var"/"value" attributes.
+ * @author Alexey Kazakov
+ */
+ public static class Var {
+ private String name;
+ private String value;
+ private ELToken elToken;
+
+ /**
+ * Constructor
+ * @param name - value of "var" attribute.
+ * @param value - value of "value" attribute.
+ */
+ public Var(String name, String value) {
+ super();
+ this.name = name;
+ this.value = value;
+ if(value.length()>3 && value.startsWith("#{") &&
value.endsWith("}")) {
+ String elBody = value.substring(0, value.length()-1).substring(2);
+ SeamELTokenizer elTokenizer = new SeamELTokenizer(elBody);
+ List<ELToken> tokens = elTokenizer.getTokens();
+ for (ELToken token : tokens) {
+ if(token.getType()==ELToken.EL_VARIABLE_TOKEN) {
+ elToken = token;
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * @return parsed EL from "value" attribute. Returns null if EL is not
valid.
+ */
+ public ELToken getElToken() {
+ return elToken;
+ }
+
+ /**
+ * @return name of variable.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @return value of variable. It's EL.
+ */
+ public String getValue() {
+ return value;
+ }
+ }
+}
\ No newline at end of file
Modified:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/el/SeamELCompletionEngine.java
===================================================================
---
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/el/SeamELCompletionEngine.java 2008-02-12
18:03:38 UTC (rev 6279)
+++
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/el/SeamELCompletionEngine.java 2008-02-12
18:08:02 UTC (rev 6280)
@@ -30,6 +30,7 @@
import org.jboss.tools.seam.core.ISeamContextVariable;
import org.jboss.tools.seam.core.ISeamProject;
import org.jboss.tools.seam.core.ScopeType;
+import org.jboss.tools.seam.internal.core.el.ElVarSearcher.Var;
/**
* Utility class used to find Seam Project content assist proposals
@@ -37,12 +38,11 @@
* @author Jeremy
*/
public final class SeamELCompletionEngine {
-
+
/**
* Constructs SeamELCompletionEngine object
*/
public SeamELCompletionEngine() {
-
}
/**
@@ -52,52 +52,29 @@
* @param file File
* @param document
* @param prefix the prefix to search for
- * @param position Offset of the prefix
+ * @param position Offset of the prefix
+ * @param vars - 'var' attributes which can be used in this EL
* @return the list of all possible suggestions
* @throws BadLocationException if accessing the current document fails
*/
public List<String> getCompletions(ISeamProject project, IFile file, IDocument
document, CharSequence prefix,
- int position) throws BadLocationException, StringIndexOutOfBoundsException {
+ int position, List<Var> vars) throws BadLocationException,
StringIndexOutOfBoundsException {
String documentContent = null;
if(document!=null) {
documentContent = document.get();
}
- return getCompletions(project, file, documentContent, prefix, position);
+ return getCompletions(project, file, documentContent, prefix, position, false, vars);
}
/**
* Create the array of suggestions.
- *
* @param project Seam project
* @param file File
- * @param documentContent
+ * @param documentContent
* @param prefix the prefix to search for
* @param position Offset of the prefix
- * @return the list of all possible suggestions
- * @throws BadLocationException if accessing the current document fails
- */
- public List<String> getCompletions(ISeamProject project, IFile file, String
documentContent, CharSequence prefix,
- int position) throws BadLocationException, StringIndexOutOfBoundsException {
- List<String> completions = new ArrayList<String>();
- SeamELOperandResolveStatus status = resolveSeamELOperand(project, file,
documentContent, prefix, position, false);
- if (status.isOK()) {
- completions.addAll(status.getProposals());
- }
- return completions;
-
-// return getCompletions(project, file, documentContent, prefix, position, false, null,
null);
- }
- /**
- * Create the array of suggestions.
- * @param project Seam project
- * @param file File
- * @param document
- * @param prefix the prefix to search for
- * @param position Offset of the prefix
- * @return the list of all possible suggestions
- * @param usedVariables - Set of variables which are used in this Expression. It's
useful in incremental validation.
- * @param unpairedGettersOrSetters - map of unpaired getters or setters of property
which is used in last segment of Expression. 'key' is property name.
- * @param returnCompletedVariablesOnly - if 'true' then returns only variables
that equals prefix. It's useful for validation.
+ * @param vars - 'var' attributes which can be used in this EL. Can be null.
+ * @param returnEqualedVariablesOnly 'false' if we get proposals for mask
* for example:
* we have 'variableName.variableProperty',
'variableName.variableProperty1', 'variableName.variableProperty2'
* prefix is 'variableName.variableProperty'
@@ -107,204 +84,44 @@
* we have 'variableName.variableProperty',
'variableName.variableProperty1', 'variableName.variableProperty2'
* prefix is 'variableName.variableProperty'
* Result is {'1','2'}
+ * @return the list of all possible suggestions
+ * @throws BadLocationException if accessing the current document fails
+ * @throws StringIndexOutOfBoundsException
*/
public List<String> getCompletions(ISeamProject project, IFile file, String
documentContent, CharSequence prefix,
- int position, boolean returnEqualedVariablesOnly, Set<ISeamContextVariable>
usedVariables, Map<String, TypeInfoCollector.MethodInfo> unpairedGettersOrSetters)
throws BadLocationException, StringIndexOutOfBoundsException {
-
- List<String> res= new ArrayList<String>();
- SeamELOperandTokenizer tokenizer = new SeamELOperandTokenizer(documentContent, position
+ prefix.length());
- List<ELOperandToken> tokens = tokenizer.getTokens();
-
- List<ELOperandToken> resolvedExpressionPart = new
ArrayList<ELOperandToken>();
- List<ISeamContextVariable> resolvedVariables = new
ArrayList<ISeamContextVariable>();
- ScopeType scope = getScope(project, file);
- List<List<ELOperandToken>> variations = getPossibleVarsFromPrefix(tokens);
-
- if (variations.isEmpty()) {
- resolvedVariables = resolveVariables(project, scope, tokens, tokens,
returnEqualedVariablesOnly);
- } else {
- for (List<ELOperandToken> variation : variations) {
- List<ISeamContextVariable>resolvedVars = new
ArrayList<ISeamContextVariable>();
- resolvedVars = resolveVariables(project, scope, variation, tokens,
returnEqualedVariablesOnly);
- if (resolvedVars != null && !resolvedVars.isEmpty()) {
- resolvedVariables = resolvedVars;
- resolvedExpressionPart = variation;
- break;
- }
- }
+ int position, boolean returnEqualedVariablesOnly, List<Var> vars) throws
BadLocationException, StringIndexOutOfBoundsException {
+ List<String> completions = new ArrayList<String>();
+ SeamELOperandResolveStatus status = resolveSeamELOperand(project, file,
documentContent, prefix, position, returnEqualedVariablesOnly, vars);
+ if (status.isOK()) {
+ completions.addAll(status.getProposals());
}
-
- // Save all resolved variables. It's useful for incremental validation.
- if(resolvedVariables!=null && resolvedVariables.size()>0 &&
usedVariables!=null) {
- usedVariables.addAll(resolvedVariables);
- }
-
- if (resolvedExpressionPart.isEmpty() &&
- !returnEqualedVariablesOnly &&
- tokens.size() > 0 &&
- tokens.get(tokens.size() - 1).getType() == ELOperandToken.EL_SEPARATOR_TOKEN) {
- // no vars are resolved
- // the tokens are the part of var name ended with a separator (.)
- resolvedVariables = resolveVariables(project, scope, tokens, tokens,
returnEqualedVariablesOnly);
- String prefixString = prefix.toString();
- for (ISeamContextVariable var : resolvedVariables) {
- String varName = var.getName();
- if(varName.startsWith(prefixString)) {
- res.add(varName.substring(prefixString.length()));
- }
- }
- return res;
- }
-
-
- // Here we have a list of vars for some part of expression
- // OK. we'll proceed with members of these vars
- if (areEqualExpressions(resolvedExpressionPart, tokens)) {
- // First segment is the last one
- for (ISeamContextVariable var : resolvedVariables) {
- String varName = var.getName();
- String prefixString = prefix.toString();
- if(prefixString.length()<=varName.length()) {
- res.add(varName.substring(prefixString.length()));
- } else if(returnEqualedVariablesOnly) {
- res.add(varName);
- }
- }
- return res;
- }
-
- // First segment is found - proceed with next tokens
- int startTokenIndex = (resolvedExpressionPart == null ? 0 :
resolvedExpressionPart.size());
- List<TypeInfoCollector.MemberInfo> members = new
ArrayList<TypeInfoCollector.MemberInfo>();
- for (ISeamContextVariable var : resolvedVariables) {
- TypeInfoCollector.MemberInfo member =
SeamExpressionResolver.getMemberInfoByVariable(var, returnEqualedVariablesOnly);
- if (member != null && !members.contains(member))
- members.add(member);
- }
- for (int i = startTokenIndex;
- tokens != null && i < tokens.size() &&
- members != null && members.size() > 0;
- i++) {
- ELOperandToken token = tokens.get(i);
-
- if (i < tokens.size() - 1) { // inside expression
- if (token.getType() == ELOperandToken.EL_SEPARATOR_TOKEN)
- // proceed with next token
- continue;
-
- if (token.isNameToken()) {
- // Find properties for the token
- String name = token.getText();
- List<TypeInfoCollector.MemberInfo> newMembers = new
ArrayList<TypeInfoCollector.MemberInfo>();
- for (TypeInfoCollector.MemberInfo mbr : members) {
- TypeInfoCollector infos =
SeamExpressionResolver.collectTypeInfo(mbr.getMemberType());
- List<TypeInfoCollector.MemberInfo> properties = infos.getProperties();
- for (TypeInfoCollector.MemberInfo property : properties) {
- StringBuffer propertyName = new StringBuffer(property.getName());
- if (property instanceof TypeInfoCollector.MethodInfo) { // Setter or getter
- propertyName.delete(0, (propertyName.charAt(0) == 'i' ? 2 : 3));
- propertyName.setCharAt(0, Character.toLowerCase(propertyName.charAt(0)));
- }
- if (name.equals(propertyName.toString())) {
- newMembers.add(property);
- }
- }
- }
- members = newMembers;
- }
- if (token.getType() == ELOperandToken.EL_METHOD_TOKEN) {
- // Find methods for the token
- String name = token.getText();
- if (name.indexOf('(') != -1) {
- name = name.substring(0, name.indexOf('('));
- }
- List<TypeInfoCollector.MemberInfo> newMembers = new
ArrayList<TypeInfoCollector.MemberInfo>();
- for (TypeInfoCollector.MemberInfo mbr : members) {
- TypeInfoCollector infos =
SeamExpressionResolver.collectTypeInfo(mbr.getMemberType());
- List<TypeInfoCollector.MemberInfo> methods = infos.getMethods();
- for (TypeInfoCollector.MemberInfo method : methods) {
- if (name.equals(method.getName())) {
- newMembers.add(method);
- }
- }
- }
- members = newMembers;
- }
- } else { // Last segment
- Set<String> proposals = new
TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
- if (token.getType() == ELOperandToken.EL_SEPARATOR_TOKEN) {
- // return all the methods + properties
- for (TypeInfoCollector.MemberInfo mbr : members) {
- TypeInfoCollector infos =
SeamExpressionResolver.collectTypeInfo(mbr.getMemberType());
- proposals.addAll(infos.getMethodPresentations());
- proposals.addAll(infos.getPropertyPresentations(unpairedGettersOrSetters));
- }
- } else if (token.getType() == ELOperandToken.EL_VARIABLE_NAME_TOKEN ||
- token.getType() == ELOperandToken.EL_PROPERTY_NAME_TOKEN ||
- token.getType() == ELOperandToken.EL_METHOD_TOKEN) {
- // return filtered methods + properties
- Set<String> proposalsToFilter = new
TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
- for (TypeInfoCollector.MemberInfo mbr : members) {
- TypeInfoCollector infos =
SeamExpressionResolver.collectTypeInfo(mbr.getMemberType());
- proposalsToFilter.addAll(infos.getMethodPresentations());
- proposalsToFilter.addAll(infos.getPropertyPresentations(unpairedGettersOrSetters));
- }
- for (String proposal : proposalsToFilter) {
- // We do expect nothing but name for method tokens (No round brackets)
- String filter = token.getText();
- if(returnEqualedVariablesOnly) {
- // This is used for validation.
- if (proposal.equals(filter)) {
- proposals.add(proposal);
- if(unpairedGettersOrSetters!=null) {
- TypeInfoCollector.MethodInfo unpirMethod =
unpairedGettersOrSetters.get(filter);
- unpairedGettersOrSetters.clear();
- if(unpirMethod!=null) {
- unpairedGettersOrSetters.put(filter, unpirMethod);
- }
- }
- break;
- }
- } else {
- // This is used for CA.
- if (proposal.startsWith(filter)) {
- proposals.add(proposal.substring(filter.length()));
- }
- }
- }
- }
- res.addAll(proposals);
- }
- }
-
- if(res.isEmpty() && unpairedGettersOrSetters!=null) {
- unpairedGettersOrSetters.clear();
- }
- return res;
+ return completions;
}
-
+
+ /**
+ * Status of EL resolving.
+ * @author Jeremy
+ */
public static class SeamELOperandResolveStatus {
private List<ELOperandToken> tokens;
public List<ISeamContextVariable> usedVariables;
Map<String, TypeInfoCollector.MethodInfo> unpairedGettersOrSetters;
Set<String> proposals;
private ELOperandToken lastResolvedToken;
- private boolean isMapOrBundleAmoungTheTokens;
+ private boolean isMapOrBundleAmoungTheTokens = false;
public SeamELOperandResolveStatus(List<ELOperandToken> tokens) {
this.tokens = tokens;
- this.lastResolvedToken = null;
- this.isMapOrBundleAmoungTheTokens = false;
}
-
+
public boolean isMapOrBundleAmoungTheTokens() {
return this.isMapOrBundleAmoungTheTokens;
}
-
+
public void setMapOrBundleAmoungTheTokens() {
this.isMapOrBundleAmoungTheTokens = true;
}
-
+
public boolean isOK() {
return !getProposals().isEmpty() || isMapOrBundleAmoungTheTokens();
}
@@ -312,7 +129,7 @@
public boolean isError() {
return !isOK();
}
-
+
public List<ELOperandToken> getResolvedTokens() {
List<ELOperandToken> resolvedTokens = new ArrayList<ELOperandToken>();
int index = tokens.indexOf(lastResolvedToken); // index == -1 means that no tokens are
resolved
@@ -373,20 +190,100 @@
public void clearUnpairedGettersOrSetters() {
getUnpairedGettersOrSetters().clear();
}
-
}
-
+
public SeamELOperandResolveStatus resolveSeamELOperand(ISeamProject project, IFile file,
String documentContent, CharSequence prefix,
+ int position, boolean returnEqualedVariablesOnly, List<Var> vars) throws
BadLocationException, StringIndexOutOfBoundsException {
+ String oldEl = prefix.toString();
+ Var var = findVarForEl(oldEl, vars);
+ String newEl = replacePrefixByVar(oldEl, var);
+ String newDocumentContent = documentContent;
+ boolean prefixWasChanged = newEl!=oldEl;
+ if(prefixWasChanged) {
+ newDocumentContent = documentContent.substring(0, position) + newEl;
+ }
+
+ SeamELOperandResolveStatus status = resolveSeamELOperand(project, file,
newDocumentContent, newEl, position, returnEqualedVariablesOnly);
+
+ if(prefixWasChanged) {
+ // Replace new EL by original one in result status.
+ ELOperandToken newLastResolvedToken = status.getLastResolvedToken();
+ SeamELOperandTokenizer tokenizer = new SeamELOperandTokenizer(documentContent,
position + prefix.length());
+ List<ELOperandToken> oldTokens = tokenizer.getTokens();
+ status.setTokens(oldTokens);
+ if(newLastResolvedToken != null) {
+ if(newLastResolvedToken.getStart() < var.getElToken().getLength()) {
+ // Last resolved token is token from "var". Set first token of original EL
as last resolved one.
+ status.setLastResolvedToken(oldTokens.get(0));
+ } else {
+ // Last resolved token is token outside "var" prefix. Correct last
resolved token.
+ int oldLastResolvedTokenStart = newLastResolvedToken.getStart() -
var.getElToken().getText().length() + var.getName().length();
+ for (ELOperandToken oldToken : oldTokens) {
+ if(oldToken.getStart() == oldLastResolvedTokenStart) {
+ status.setLastResolvedToken(oldToken);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return status;
+ }
+
+ private Var findVarForEl(String el, List<Var> vars) {
+ if(vars!=null) {
+ for (Var var : vars) {
+ ELToken token = var.getElToken();
+ if(token!=null && !token.getText().endsWith(".")) {
+ String varName = var.getName();
+ if(el.equals(varName) || el.startsWith(varName + ".")) {
+ return var;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Replace all el variables by variables from found "var" attributes.
+ * @param el
+ * @param vars
+ * @return
+ */
+ private String replacePrefixByVar(String el, Var var) {
+ if(var!=null) {
+ ELToken token = var.getElToken();
+ if(token!=null) {
+ return token.getText() + el.substring(var.getName().length());
+ }
+ }
+ return el;
+ }
+
+ /**
+ * Resolves Seam EL
+ * @param project
+ * @param file
+ * @param documentContent
+ * @param prefix
+ * @param position
+ * @param returnEqualedVariablesOnly
+ * @return
+ * @throws BadLocationException
+ * @throws StringIndexOutOfBoundsException
+ */
+ public SeamELOperandResolveStatus resolveSeamELOperand(ISeamProject project, IFile file,
String documentContent, String prefix,
int position, boolean returnEqualedVariablesOnly) throws BadLocationException,
StringIndexOutOfBoundsException {
-
SeamELOperandTokenizer tokenizer = new SeamELOperandTokenizer(documentContent, position
+ prefix.length());
- SeamELOperandResolveStatus status= new
SeamELOperandResolveStatus(tokenizer.getTokens());
+ SeamELOperandResolveStatus status = new
SeamELOperandResolveStatus(tokenizer.getTokens());
List<ISeamContextVariable> resolvedVariables = new
ArrayList<ISeamContextVariable>();
ScopeType scope = getScope(project, file);
List<List<ELOperandToken>> variations =
getPossibleVarsFromPrefix(status.getTokens());
-
+
if (variations.isEmpty()) {
resolvedVariables = resolveVariables(project, scope,
status.getTokens(), status.getTokens(),
@@ -409,7 +306,7 @@
if(resolvedVariables!=null && resolvedVariables.size()>0) {
status.setUsedVariables(resolvedVariables);
}
-
+
if (status.getResolvedTokens().isEmpty() &&
!returnEqualedVariablesOnly &&
status.getTokens().size() > 0 &&
@@ -417,18 +314,16 @@
// no vars are resolved
// the tokens are the part of var name ended with a separator (.)
resolvedVariables = resolveVariables(project, scope, status.getTokens(),
status.getTokens(), returnEqualedVariablesOnly);
- String prefixString = prefix.toString();
Set<String> proposals = new
TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
for (ISeamContextVariable var : resolvedVariables) {
String varName = var.getName();
- if(varName.startsWith(prefixString)) {
- proposals.add(varName.substring(prefixString.length()));
+ if(varName.startsWith(prefix)) {
+ proposals.add(varName.substring(prefix.length()));
}
}
status.setProposals(proposals);
return status;
}
-
// Here we have a list of vars for some part of expression
// OK. we'll proceed with members of these vars
@@ -437,9 +332,8 @@
Set<String> proposals = new
TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
for (ISeamContextVariable var : resolvedVariables) {
String varName = var.getName();
- String prefixString = prefix.toString();
- if(prefixString.length()<=varName.length()) {
- proposals.add(varName.substring(prefixString.length()));
+ if(prefix.length()<=varName.length()) {
+ proposals.add(varName.substring(prefix.length()));
} else if(returnEqualedVariablesOnly) {
proposals.add(varName);
}
@@ -580,9 +474,8 @@
status.clearUnpairedGettersOrSetters();
}
return status;
-
}
-
+
private String computeVariableName(List<ELOperandToken> tokens){
if (tokens == null)
tokens = new ArrayList<ELOperandToken>();
@@ -597,7 +490,7 @@
}
return sb.toString();
}
-
+
/*
* Compares to tokenized expressions.
*
@@ -608,17 +501,17 @@
private boolean areEqualExpressions(List<ELOperandToken>first,
List<ELOperandToken>second) {
if (first == null || second == null)
return (first == second);
-
+
if (first.size() != second.size())
return false;
-
+
for (int i = 0; i < first.size(); i++) {
if (!first.get(i).equals(second.get(i)))
return false;
}
return true;
}
-
+
/* Returns scope for the resource
*
* @param project
@@ -673,7 +566,7 @@
}
return new ArrayList<ISeamContextVariable>();
}
-
+
/*
* Creates and returns list of possible variable name combinations from expression
starting from the longest name
*
@@ -695,7 +588,7 @@
}
return result;
}
-
+
/**
* Removes duplicates of completion strings
*
@@ -708,7 +601,7 @@
if (suggestions == null)
return unique;
-
+
for (String item : suggestions) {
if (!present.contains(item)) {
present.add(item);
@@ -765,13 +658,13 @@
if (tokens == null || tokens.size() == 0)
return null;
-
+
List<List<ELOperandToken>> vars = getPossibleVarsFromPrefix(tokens);
if (vars == null)
return null;
-
+
String prefixPart = documentContent.substring(tokens.get(0).start, offset);
-
+
// Search from the shortest variation to the longest one
for (int i = vars.size() - 1; i >= 0; i--) {
List<ELOperandToken>var = vars.get(i);
@@ -782,7 +675,7 @@
}
return null;
}
-
+
/**
* Create the array of suggestions.
* @param project Seam project
@@ -791,20 +684,19 @@
* @param prefix the prefix to search for
* @param position Offset of the prefix
*/
-
public List<IJavaElement> getJavaElementsForExpression(ISeamProject project, IFile
file, String expression) throws BadLocationException, StringIndexOutOfBoundsException {
List<IJavaElement> res= new ArrayList<IJavaElement>();
SeamELOperandTokenizer tokenizer = new SeamELOperandTokenizer(expression,
expression.length());
List<ELOperandToken> tokens = tokenizer.getTokens();
-
+
if (tokens == null || tokens.size() == 0 || tokens.get(tokens.size() - 1).getType() ==
ELOperandToken.EL_SEPARATOR_TOKEN)
return res;
-
+
List<ELOperandToken> resolvedExpressionPart = new
ArrayList<ELOperandToken>();
List<ISeamContextVariable> resolvedVariables = new
ArrayList<ISeamContextVariable>();
ScopeType scope = getScope(project, file);
List<List<ELOperandToken>> variations = getPossibleVarsFromPrefix(tokens);
-
+
if (variations.isEmpty()) {
resolvedVariables = resolveVariables(project, scope, tokens, tokens, true);
} else {
@@ -824,12 +716,6 @@
if (areEqualExpressions(resolvedExpressionPart, tokens)) {
// First segment is the last one
for (ISeamContextVariable var : resolvedVariables) {
-// String varName = var.getName();
-// if(expression.length()<varName.length()) {
-// res.add(varName.substring(prefixString.length()));
-// } else if(returnEqualedVariablesOnly) {
-// res.add(varName);
-// }
IMember member = SeamExpressionResolver.getMemberByVariable(var, true);
if (member instanceof IJavaElement){
res.add((IJavaElement)member);
@@ -851,7 +737,7 @@
members != null && members.size() > 0;
i++) {
ELOperandToken token = tokens.get(i);
-
+
if (i < tokens.size() - 1) { // inside expression
if (token.getType() == ELOperandToken.EL_SEPARATOR_TOKEN)
// proceed with next token
@@ -908,7 +794,7 @@
javaElementInfosToFilter.addAll(infos.getMethods());
javaElementInfosToFilter.addAll(infos.getProperties());
}
-
+
for (TypeInfoCollector.MemberInfo info : javaElementInfosToFilter) {
// We do expect nothing but name for method tokens (No round brackets)
String filter = token.getText();
Modified:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/el/SeamELTokenizer.java
===================================================================
---
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/el/SeamELTokenizer.java 2008-02-12
18:03:38 UTC (rev 6279)
+++
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/el/SeamELTokenizer.java 2008-02-12
18:08:02 UTC (rev 6280)
@@ -44,7 +44,7 @@
/**
* Constructs SeamELTokenizer object.
* Parse an expression.
- * For example: expression is '#{var1.pr != var2.pr}'
+ * For example: expression is "var1.pr != var2.pr"
* then tokens are ["var1.pr"," ", "!=",
" ", "var2.pr"]
* @param expression
*/
Modified:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/el/SeamPromptingProvider.java
===================================================================
---
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/el/SeamPromptingProvider.java 2008-02-12
18:03:38 UTC (rev 6279)
+++
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/el/SeamPromptingProvider.java 2008-02-12
18:08:02 UTC (rev 6280)
@@ -8,7 +8,6 @@
* Contributors:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
-
package org.jboss.tools.seam.internal.core.el;
import java.util.ArrayList;
@@ -29,9 +28,9 @@
static String IS_SEAM_PROJECT = "seam.is_seam_project"; //$NON-NLS-1$
public static String VARIABLES = "seam.variables"; //$NON-NLS-1$
public static String MEMBERS = "seam.members"; //$NON-NLS-1$
-
+
SeamELCompletionEngine engine= new SeamELCompletionEngine();
-
+
public SeamPromptingProvider() {}
public List getList(XModel model, String id, String prefix,
@@ -59,12 +58,11 @@
} else if(MEMBERS.equals(id)) {
try {
String prefix2 = SeamELCompletionEngine.getPrefix(prefix, prefix.length());
- List<String> suggestions = engine.getCompletions(p, f, prefix, prefix2, 2,
true, null, null);
+ List<String> suggestions = engine.getCompletions(p, f, prefix, prefix2, 2,
true, null);
return suggestions;
} catch (BadLocationException e) {
return EMPTY_LIST;
}
-
}
return null;
}
@@ -72,5 +70,4 @@
public boolean isSupporting(String id) {
return id != null && id.startsWith("seam."); //$NON-NLS-1$
}
-
-}
+}
\ No newline at end of file
Modified:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamCoreValidator.java
===================================================================
---
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamCoreValidator.java 2008-02-12
18:03:38 UTC (rev 6279)
+++
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamCoreValidator.java 2008-02-12
18:08:02 UTC (rev 6280)
@@ -254,16 +254,9 @@
// return type is void
String factoryName = factory.getName();
if(factoryName==null) {
- String methodName = method.getElementName();
- if(methodName.startsWith("get") && methodName.length()>3) {
//$NON-NLS-1$
- // This is getter
- factoryName = methodName.substring(3);
- } else {
- // Unknown factory name
- SeamCorePlugin.getDefault().logError(NLS.bind(SeamCoreMessages.SEAM_CORE_VALIDATOR_FACTORY_METHOD_MUST_HAVE_NAME,factory.getResource()));
- //factoryName = methodName;
- return;
- }
+ // Unknown factory name
+ SeamCorePlugin.getDefault().logError(NLS.bind(SeamCoreMessages.SEAM_CORE_VALIDATOR_FACTORY_METHOD_MUST_HAVE_NAME,factory.getResource()));
+ return;
}
validateFactoryName(factory, factoryName, markedDuplicateFactoryNames, true);
}
Modified:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamELValidator.java
===================================================================
---
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamELValidator.java 2008-02-12
18:03:38 UTC (rev 6279)
+++
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamELValidator.java 2008-02-12
18:08:02 UTC (rev 6280)
@@ -11,6 +11,7 @@
package org.jboss.tools.seam.internal.core.validation;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -30,13 +31,14 @@
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
-import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
import org.eclipse.wst.validation.internal.core.ValidationException;
import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
import org.jboss.tools.common.util.FileUtil;
import org.jboss.tools.seam.core.ISeamContextVariable;
@@ -47,10 +49,14 @@
import org.jboss.tools.seam.internal.core.el.ELOperandToken;
import org.jboss.tools.seam.internal.core.el.ELStringToken;
import org.jboss.tools.seam.internal.core.el.ELToken;
+import org.jboss.tools.seam.internal.core.el.ElVarSearcher;
import org.jboss.tools.seam.internal.core.el.SeamELCompletionEngine;
import org.jboss.tools.seam.internal.core.el.SeamELStringTokenizer;
import org.jboss.tools.seam.internal.core.el.SeamELTokenizer;
import org.jboss.tools.seam.internal.core.el.TypeInfoCollector;
+import org.jboss.tools.seam.internal.core.el.ElVarSearcher.Var;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
/**
* EL Validator
@@ -64,7 +70,8 @@
protected static final String VALIDATING_EL_FILE_MESSAGE_ID =
"VALIDATING_EL_FILE";
- private SeamELCompletionEngine engine= new SeamELCompletionEngine();
+ private SeamELCompletionEngine engine = new SeamELCompletionEngine();
+ private List<Var> varListForCurentValidatedNode = new ArrayList<Var>();
public SeamELValidator(SeamValidatorManager validatorManager,
SeamValidationHelper coreHelper, IReporter reporter,
@@ -166,6 +173,7 @@
}
private void validateDom(IFile file, String content) {
+ varListForCurentValidatedNode.clear();
IModelManager manager = StructuredModelManager.getModelManager();
if(manager == null) {
// this can happen if plugin org.eclipse.wst.sse.core
@@ -178,17 +186,8 @@
model = manager.getModelForRead(file);
if (model instanceof IDOMModel) {
IDOMModel domModel = (IDOMModel) model;
- IStructuredDocument structuredDoc = domModel.getStructuredDocument();
- IStructuredDocumentRegion curNode =
structuredDoc.getFirstStructuredDocumentRegion();
- while (curNode !=null && !reporter.isCancelled()) {
- if (curNode.getFirstRegion().getType() == DOMRegionContext.XML_TAG_OPEN) {
- validateNodeContent(file, curNode, DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE);
- }
- if (curNode.getFirstRegion().getType() == DOMRegionContext.XML_CONTENT) {
- validateNodeContent(file, curNode, DOMRegionContext.XML_CONTENT);
- }
- curNode = curNode.getNext();
- }
+ IDOMDocument document = domModel.getDocument();
+ validateChildNodes(file, document);
}
} catch (CoreException e) {
SeamCorePlugin.getDefault().logError(SeamCoreMessages.SEAM_EL_VALIDATOR_ERROR_VALIDATING_SEAM_EL,
e);
@@ -199,10 +198,29 @@
model.releaseFromRead();
}
}
-
return;
}
+ private void validateChildNodes(IFile file, Node parent) {
+ Var var = ElVarSearcher.findVar(parent);
+ if(var!=null) {
+ varListForCurentValidatedNode.add(var);
+ }
+ NodeList children = parent.getChildNodes();
+ for(int i=0; i<children.getLength() && !reporter.isCancelled(); i++) {
+ Node curentValidatedNode = children.item(i);
+ if(Node.ELEMENT_NODE == curentValidatedNode.getNodeType()) {
+ validateNodeContent(file,
((IDOMNode)curentValidatedNode).getFirstStructuredDocumentRegion(),
DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE);
+ } else if(Node.TEXT_NODE == curentValidatedNode.getNodeType()) {
+ validateNodeContent(file,
((IDOMNode)curentValidatedNode).getFirstStructuredDocumentRegion(),
DOMRegionContext.XML_CONTENT);
+ }
+ validateChildNodes(file, curentValidatedNode);
+ }
+ if(var!=null) {
+ varListForCurentValidatedNode.remove(var);
+ }
+ }
+
private void validateNodeContent(IFile file, IStructuredDocumentRegion node, String
regionType) {
ITextRegionList regions = node.getRegions();
for(int i=0; i<regions.size(); i++) {
@@ -264,7 +282,7 @@
}
SeamELCompletionEngine.SeamELOperandResolveStatus status =
- engine.resolveSeamELOperand(project, file, operand, prefix, position, true);
+ engine.resolveSeamELOperand(project, file, operand, prefix, position, true,
varListForCurentValidatedNode);
if(status.getUsedVariables().size()==0 && status.isError()) {
// Save resources with unknown variables names
Modified:
trunk/seam/plugins/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/text/java/SeamELProposalProcessor.java
===================================================================
---
trunk/seam/plugins/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/text/java/SeamELProposalProcessor.java 2008-02-12
18:03:38 UTC (rev 6279)
+++
trunk/seam/plugins/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/text/java/SeamELProposalProcessor.java 2008-02-12
18:08:02 UTC (rev 6280)
@@ -284,7 +284,7 @@
}
}
- List<String> suggestions = fEngine.getCompletions(seamProject, file,
documentContent, prefix, offset + proposalPrefix.length() - prefix.length());
+ List<String> suggestions = fEngine.getCompletions(seamProject, file,
documentContent, prefix, offset + proposalPrefix.length() - prefix.length(), false,
null);
List<String> uniqueSuggestions = fEngine.makeUnique(suggestions);
List<ICompletionProposal> result= new ArrayList<ICompletionProposal>();