diff --git a/CFML/.idea/runConfigurations/CFML_Tests.xml b/CFML/.idea/runConfigurations/CFML_Tests.xml
index 5e76a0539a3..d7d09c662a9 100644
--- a/CFML/.idea/runConfigurations/CFML_Tests.xml
+++ b/CFML/.idea/runConfigurations/CFML_Tests.xml
@@ -1,24 +1,17 @@
-
-
-
+
-
-
-
-
+
-
-
@@ -27,6 +20,8 @@
-
+
+
+
\ No newline at end of file
diff --git a/CFML/CFML-plugin.iml b/CFML/CFML-plugin.iml
index 00d76084934..15df663f097 100644
--- a/CFML/CFML-plugin.iml
+++ b/CFML/CFML-plugin.iml
@@ -1,16 +1,16 @@
-
+
+
-
-
+
\ No newline at end of file
diff --git a/CFML/resources/META-INF/plugin.xml b/CFML/resources/META-INF/plugin.xml
index bd2287157b6..a42f6000543 100644
--- a/CFML/resources/META-INF/plugin.xml
+++ b/CFML/resources/META-INF/plugin.xml
@@ -1,6 +1,7 @@
CFML Support
CFML
+ 2019.3.0-BETA
Settings / Preferences dialog and se
com.intellij.modules.java
com.intellij.modules.ultimate
com.intellij.modules.idea.ultimate
+
+
+
Settings / Preferences dialog and se
+
+
diff --git a/CFML/src/com/intellij/coldFusion/UI/CfmlLookUpItemUtil.java b/CFML/src/com/intellij/coldFusion/UI/CfmlLookUpItemUtil.java
index 85272c185d6..a034a2d7f93 100755
--- a/CFML/src/com/intellij/coldFusion/UI/CfmlLookUpItemUtil.java
+++ b/CFML/src/com/intellij/coldFusion/UI/CfmlLookUpItemUtil.java
@@ -11,6 +11,7 @@
import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
import com.intellij.coldFusion.UI.editorActions.completionProviders.CfmlMethodInsertHandler;
import com.intellij.coldFusion.model.info.CfmlFunctionDescription;
+import com.intellij.coldFusion.model.info.CfmlPropertyDescription;
import com.intellij.coldFusion.model.psi.*;
import com.intellij.coldFusion.model.psi.impl.CfmlNamedAttributeImpl;
import com.intellij.openapi.util.text.StringUtil;
@@ -132,10 +133,23 @@ public static CfmlFunctionDescription getFunctionDescription(CfmlFunction functi
PsiType returnType = function.getReturnType();
CfmlFunctionDescription functionInfo = new CfmlFunctionDescription(function.getName(),
returnType != null ? returnType.getCanonicalText() : null);
+
+ functionInfo.setDescription(function.getDescription());
CfmlParameter[] params = function.getParameters();
for (CfmlParameter param : params) {
- functionInfo.addParameter(new CfmlFunctionDescription.CfmlParameterDescription(param.getName(), param.getType(), param.isRequired()));
+ CfmlFunctionDescription.CfmlParameterDescription description =
+ new CfmlFunctionDescription.CfmlParameterDescription(param.getName(), param.getType(), param.getDefault(), param.isRequired());
+ description.setDescription(param.getDescription());
+ functionInfo.addParameter(description);
}
return functionInfo;
}
+
+ public static CfmlPropertyDescription getPropertyDescription(CfmlProperty property) {
+ PsiType type = property.getPsiType();
+ CfmlPropertyDescription propertyInfo = new CfmlPropertyDescription(property.getName(),
+ type != null ? type.getCanonicalText() : null);
+ propertyInfo.setDescription(property.getDescription());
+ return propertyInfo;
+ }
}
diff --git a/CFML/src/com/intellij/coldFusion/UI/editorActions/CfmlDocumentProvider.java b/CFML/src/com/intellij/coldFusion/UI/editorActions/CfmlDocumentProvider.java
index 7c866600d4e..e29ed856e93 100644
--- a/CFML/src/com/intellij/coldFusion/UI/editorActions/CfmlDocumentProvider.java
+++ b/CFML/src/com/intellij/coldFusion/UI/editorActions/CfmlDocumentProvider.java
@@ -2,6 +2,9 @@
package com.intellij.coldFusion.UI.editorActions;
import com.intellij.coldFusion.model.CfmlUtil;
+import com.intellij.coldFusion.model.psi.CfmlComponent;
+import com.intellij.coldFusion.model.psi.CfmlFunction;
+import com.intellij.coldFusion.model.psi.CfmlProperty;
import com.intellij.coldFusion.model.psi.CfmlTag;
import com.intellij.coldFusion.model.psi.impl.CfmlAttributeImpl;
import com.intellij.coldFusion.model.psi.impl.CfmlAttributeNameImpl;
@@ -21,7 +24,16 @@ public class CfmlDocumentProvider extends DocumentationProviderEx {
@Override
public String generateDoc(PsiElement element, PsiElement originalElement) {
- if (element instanceof CfmlAttributeImpl && element.getParent() instanceof CfmlTag) {
+ if (element instanceof CfmlComponent) {
+ return CfmlUtil.getComponentDescription((CfmlComponent)element, element.getProject());
+ }
+ else if (element instanceof CfmlFunction) {
+ return CfmlUtil.getFunctionDescription((CfmlFunction)element, element.getProject());
+ }
+ else if (element instanceof CfmlProperty) {
+ return CfmlUtil.getPropertyDescription((CfmlProperty)element, element.getProject());
+ }
+ else if (element instanceof CfmlAttributeImpl && element.getParent() instanceof CfmlTag) {
String tagName = StringUtil.toLowerCase(((CfmlTag)element.getParent()).getTagName());
String attributeName = (element instanceof CfmlAttributeNameImpl) ?
"name" :
diff --git a/CFML/src/com/intellij/coldFusion/UI/editorActions/CfmlParameterInfoHandler.java b/CFML/src/com/intellij/coldFusion/UI/editorActions/CfmlParameterInfoHandler.java
index 3f5912dec83..848dd31f440 100755
--- a/CFML/src/com/intellij/coldFusion/UI/editorActions/CfmlParameterInfoHandler.java
+++ b/CFML/src/com/intellij/coldFusion/UI/editorActions/CfmlParameterInfoHandler.java
@@ -114,9 +114,11 @@ else if (element1 instanceof PsiMethod) {
new CfmlFunctionDescription(function.getName(), function.getReturnType().getPresentableText());
final PsiParameter[] psiParameters = function.getParameterList().getParameters();
for (PsiParameter psiParameter : psiParameters) {
+ PsiExpression initializerElement = psiParameter.getInitializer();
+ String initializerValue = initializerElement == null ? null : initializerElement.getText();
javaMethodDescr.addParameter(new CfmlFunctionDescription.CfmlParameterDescription(psiParameter.getName(),
psiParameter.getType()
- .getPresentableText(), true));
+ .getPresentableText(), initializerValue, true));
}
return javaMethodDescr;
}
diff --git a/CFML/src/com/intellij/coldFusion/UI/editorActions/CfmllFindUsagesProvider.java b/CFML/src/com/intellij/coldFusion/UI/editorActions/CfmllFindUsagesProvider.java
index b5386ae5b94..c569be3c845 100644
--- a/CFML/src/com/intellij/coldFusion/UI/editorActions/CfmllFindUsagesProvider.java
+++ b/CFML/src/com/intellij/coldFusion/UI/editorActions/CfmllFindUsagesProvider.java
@@ -19,6 +19,7 @@ public class CfmllFindUsagesProvider implements FindUsagesProvider {
public boolean canFindUsagesFor(@NotNull final PsiElement psiElement) {
return psiElement instanceof CfmlReferenceExpression || (psiElement instanceof CfmlTagFunctionImpl) ||
(psiElement instanceof CfmlTag && ((CfmlTag)psiElement).getTagName().equalsIgnoreCase("cfargument")) ||
+ (psiElement instanceof CfmlTag && ((CfmlTag)psiElement).getTagName().equalsIgnoreCase("cfparam")) ||
psiElement instanceof CfmlFunctionImpl || psiElement instanceof CfmlFunctionParameterImpl;
}
diff --git a/CFML/src/com/intellij/coldFusion/UI/editorActions/completionProviders/CfmlAttributeValuesCompletionProvider.java b/CFML/src/com/intellij/coldFusion/UI/editorActions/completionProviders/CfmlAttributeValuesCompletionProvider.java
index 852c113ae54..e19fad4aa63 100644
--- a/CFML/src/com/intellij/coldFusion/UI/editorActions/completionProviders/CfmlAttributeValuesCompletionProvider.java
+++ b/CFML/src/com/intellij/coldFusion/UI/editorActions/completionProviders/CfmlAttributeValuesCompletionProvider.java
@@ -40,6 +40,7 @@ public void addCompletions(@NotNull final CompletionParameters parameters,
String[] attributeValue = CfmlUtil.getAttributeValues(tagName, attributeName, parameters.getPosition().getProject());
if ("type".equalsIgnoreCase(attributeName) && "cfargument".equalsIgnoreCase(tagName) ||
+ "type".equalsIgnoreCase(attributeName) && "cfproperty".equalsIgnoreCase(tagName) ||
"returntype".equalsIgnoreCase(attributeName) && "cffunction".equalsIgnoreCase(tagName)
) {
Object[] objects =
diff --git a/CFML/src/com/intellij/coldFusion/injection/CfqueryEscaper.kt b/CFML/src/com/intellij/coldFusion/injection/CfqueryEscaper.kt
index baa3db85221..90af2d03dd8 100644
--- a/CFML/src/com/intellij/coldFusion/injection/CfqueryEscaper.kt
+++ b/CFML/src/com/intellij/coldFusion/injection/CfqueryEscaper.kt
@@ -18,10 +18,14 @@ class CfqueryEscaper(tag: CfmlTagImpl) : LiteralTextEscaper(tag) {
//exclude cfquery tags from TextRange
override fun getRelevantTextRange(): TextRange {
- val startOffset = Regex("]*>").find(myHost.text)!!.range.endInclusive + 1
- val closeTagOffset = Regex("]*>").find(myHost.text) ?: return TextRange(startOffset, startOffset)
- val endOffset = closeTagOffset.range.start
- return TextRange(startOffset, endOffset)
+ try {
+ val startOffset = Regex("]*>").find(myHost.text)!!.range.endInclusive + 1
+ val closeTagOffset = Regex("]*>").find(myHost.text) ?: return TextRange(startOffset, startOffset)
+ val endOffset = closeTagOffset.range.start
+ return TextRange(startOffset, endOffset)
+ } catch (e: KotlinNullPointerException) {
+ return TextRange(0, 0)
+ }
}
}
\ No newline at end of file
diff --git a/CFML/src/com/intellij/coldFusion/model/CfmlDocUtil.kt b/CFML/src/com/intellij/coldFusion/model/CfmlDocUtil.kt
index f52a6eb0525..ab1959820f3 100644
--- a/CFML/src/com/intellij/coldFusion/model/CfmlDocUtil.kt
+++ b/CFML/src/com/intellij/coldFusion/model/CfmlDocUtil.kt
@@ -7,9 +7,13 @@ import com.intellij.coldFusion.model.info.CfmlAttributeDescription
import com.intellij.coldFusion.model.info.CfmlLangInfo
import com.intellij.coldFusion.model.info.CfmlTagDescription
import com.intellij.coldFusion.model.info.CfmlTypesInfo
+import com.intellij.coldFusion.model.psi.CfmlComponent
+import com.intellij.coldFusion.model.psi.CfmlFunction
+import com.intellij.coldFusion.model.psi.CfmlProperty
import com.intellij.openapi.project.Project
import com.intellij.util.containers.isNullOrEmpty
import com.intellij.xml.util.XmlStringUtil
+import java.util.*
object CfmlDocUtil {
@@ -117,4 +121,58 @@ object CfmlDocUtil {
return "$this"
}
+ private fun String.faint(): String {
+ return "$this"
+ }
+
+ @JvmStatic
+ fun componentDescription(component: CfmlComponent, project: Project): String {
+ var description = p { (component.name ?: "Unknown component name").bold() }
+
+ val hintDescription = component.description
+ if (hintDescription != null) {
+ description += p { hintDescription }
+ }
+
+ val init = Arrays.stream(component.getFunctionsWithSupers(false)).filter { f: CfmlFunction -> f.name == "init" }
+ .findFirst()
+ if (init.isPresent) {
+ description += "" + functionDescription(init.get(), project)
+ }
+ return description
+ }
+
+ @JvmStatic
+ fun functionDescription(function: CfmlFunction, project: Project): String {
+ val info = function.functionInfo
+ var paramsLabel = "Params: ".faint()
+ return p {
+ info.name.trim().bold() + if (info.parameters.isEmpty()) "()" else "(...)" + " : " + (info.returnType ?: "any")
+ } + p {
+ info.description?.trim() ?: ""
+ } + table {
+ info.parameters.map {
+ tr {
+ td {
+ paramsLabel
+ } + td {
+ paramsLabel = ""
+ it.presetableText.bold() + " "
+ } + td {
+ it.description?.trim() ?: ""
+ }
+ }
+ }.joinToString("")
+ }
+ }
+
+ @JvmStatic
+ fun propertyDescription(property: CfmlProperty, project: Project): String {
+ val info = property.propertyInfo
+ return p {
+ info.name.trim().bold() + " : " + (info.type ?: "any")
+ } + p {
+ info.description?.trim() ?: ""
+ }
+ }
}
\ No newline at end of file
diff --git a/CFML/src/com/intellij/coldFusion/model/CfmlUtil.java b/CFML/src/com/intellij/coldFusion/model/CfmlUtil.java
index 8db2e7a6fef..2744c7521cf 100644
--- a/CFML/src/com/intellij/coldFusion/model/CfmlUtil.java
+++ b/CFML/src/com/intellij/coldFusion/model/CfmlUtil.java
@@ -2,14 +2,14 @@
package com.intellij.coldFusion.model;
import com.intellij.codeInsight.AutoPopupController;
+import com.intellij.coldFusion.model.files.CfmlFile;
import com.intellij.coldFusion.model.info.CfmlAttributeDescription;
import com.intellij.coldFusion.model.info.CfmlLangInfo;
import com.intellij.coldFusion.model.info.CfmlTagDescription;
import com.intellij.coldFusion.model.lexer.CfmlTokenTypes;
import com.intellij.coldFusion.model.lexer.CfscriptTokenTypes;
import com.intellij.coldFusion.model.parsers.CfmlKeywords;
-import com.intellij.coldFusion.model.psi.CfmlImport;
-import com.intellij.coldFusion.model.psi.CfmlReferenceExpression;
+import com.intellij.coldFusion.model.psi.*;
import com.intellij.coldFusion.model.psi.impl.CfmlTagImpl;
import com.intellij.lang.Language;
import com.intellij.lang.PsiBuilder;
@@ -25,6 +25,7 @@
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiType;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
@@ -167,6 +168,18 @@ public static boolean isEndTagRequired(String tagName, Project project) {
return getCfmlLangInfo(project).getTagAttributes().get(tagName).isEndTagRequired();
}
+ public static String getComponentDescription(CfmlComponent component, Project project) {
+ return CfmlDocUtil.componentDescription(component, project);
+ }
+
+ public static String getFunctionDescription(CfmlFunction function, Project project) {
+ return CfmlDocUtil.functionDescription(function, project);
+ }
+
+ public static String getPropertyDescription(CfmlProperty property, Project project) {
+ return CfmlDocUtil.propertyDescription(property, project);
+ }
+
public static String getTagDescription(String tagName, Project project) {
return CfmlDocUtil.tagDescription(tagName, project);
}
@@ -294,4 +307,24 @@ public static Couple getPrefixAndName(String name) {
}
return Couple.of(name.substring(0, index), name.substring(index + 1));
}
+
+ @Nullable
+ public static PsiType getTypeFromName(CfmlFile file, String typeName, Project project) {
+ if (file == null || typeName == null) return null;
+
+ final boolean isArray = typeName.endsWith("[]");
+ final String qualifiedTypeString;
+ if (isArray) {
+ qualifiedTypeString = file.getComponentQualifiedName(typeName.substring(0, typeName.length() - 2));
+ }
+ else {
+ qualifiedTypeString = file.getComponentQualifiedName(typeName);
+ }
+ if (qualifiedTypeString == null) return null;
+ PsiType type = new CfmlComponentType(qualifiedTypeString, file, project);
+ if (isArray) {
+ type = type.createArrayType();
+ }
+ return type;
+ }
}
diff --git a/CFML/src/com/intellij/coldFusion/model/files/CfmlFile.java b/CFML/src/com/intellij/coldFusion/model/files/CfmlFile.java
index e602d660c85..994d7b5391f 100644
--- a/CFML/src/com/intellij/coldFusion/model/files/CfmlFile.java
+++ b/CFML/src/com/intellij/coldFusion/model/files/CfmlFile.java
@@ -178,7 +178,7 @@ public String getComponentQualifiedName(@NotNull String componentName) {
CfmlImport[] childrenByClass = findChildrenByClass(CfmlImport.class);
for (CfmlImport importStatement : childrenByClass) {
if (importStatement.isImported(componentName)) {
- String importString = importStatement.getImportString();
+ String importString = importStatement.getComponentQualifiedName(componentName);
return importString != null ? importString : "";
}
}
@@ -189,10 +189,8 @@ public Collection getImportStrings() {
Set result = new HashSet<>();
CfmlImport[] childrenByClass = findChildrenByClass(CfmlImport.class);
for (CfmlImport importStatement : childrenByClass) {
- String importString = importStatement.getImportString();
- if (importString != null) {
- result.add(importString);
- }
+ Set importStrings = importStatement.getAllComponentQualifiedNames();
+ result.addAll(importStrings);
}
return result;
}
diff --git a/CFML/src/com/intellij/coldFusion/model/info/CfmlFunctionDescription.java b/CFML/src/com/intellij/coldFusion/model/info/CfmlFunctionDescription.java
index 6b1d9b313c4..14e88180cdb 100755
--- a/CFML/src/com/intellij/coldFusion/model/info/CfmlFunctionDescription.java
+++ b/CFML/src/com/intellij/coldFusion/model/info/CfmlFunctionDescription.java
@@ -59,12 +59,14 @@ public void setDescription(String description) {
public static class CfmlParameterDescription {
private final String myName;
private final String myType;
+ private final String myDefault;
private final boolean myIsRequired;
private String myDescription;
- public CfmlParameterDescription(String name, String type, boolean isRequired) {
+ public CfmlParameterDescription(String name, String type, String defaultValue, boolean isRequired) {
myName = name;
myType = type;
+ myDefault = defaultValue;
myIsRequired = isRequired;
}
@@ -75,6 +77,10 @@ public String getName() {
public String getType() {
return myType;
}
+
+ public String getDefault() {
+ return myDefault;
+ }
public boolean isRequired() {
return myIsRequired;
@@ -95,6 +101,10 @@ public String getPresetableText() {
if (type != null) {
paramDescription = paramDescription + " : " + type;
}
+ final String defaultValue = getDefault();
+ if (defaultValue != null) {
+ paramDescription = paramDescription + " = \"" + defaultValue + "\"";
+ }
if (!isRequired()) {
sb.append("[");
sb.append(paramDescription);
diff --git a/CFML/src/com/intellij/coldFusion/model/info/CfmlPropertyDescription.java b/CFML/src/com/intellij/coldFusion/model/info/CfmlPropertyDescription.java
new file mode 100644
index 00000000000..d4455b7e89c
--- /dev/null
+++ b/CFML/src/com/intellij/coldFusion/model/info/CfmlPropertyDescription.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2000-2020 JetBrains s.r.o.
+ *
+ * Licensed 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 com.intellij.coldFusion.model.info;
+
+public class CfmlPropertyDescription {
+
+ private final String myName;
+ private final String myType;
+ private String myDescription;
+
+ public CfmlPropertyDescription(String name, String Type) {
+ myName = name;
+ myType = Type;
+ }
+
+ public String getName() {
+ return myName;
+ }
+
+ public String getType() {
+ return myType;
+ }
+
+ public String getDescription() {
+ return myDescription;
+ }
+
+ public void setDescription(String description) {
+ myDescription = description;
+ }
+
+ public String getPresentableText() {
+ StringBuilder buffer = new StringBuilder();
+ buffer.append(getName());
+ final String type = getType();
+ if (type != null) {
+ buffer.append(" : ");
+ buffer.append(type);
+ }
+ return buffer.toString();
+ }
+}
diff --git a/CFML/src/com/intellij/coldFusion/model/info/CfmlTagsDescriptionsParser.java b/CFML/src/com/intellij/coldFusion/model/info/CfmlTagsDescriptionsParser.java
index 993c319baab..9970378e2c3 100644
--- a/CFML/src/com/intellij/coldFusion/model/info/CfmlTagsDescriptionsParser.java
+++ b/CFML/src/com/intellij/coldFusion/model/info/CfmlTagsDescriptionsParser.java
@@ -135,9 +135,10 @@ else if (myState == FUNCTION_STATE) {
else if (localName.equals("parameter") && myCurrentFunction != null) {
String aName = attr.getValue("name");
String aType = attr.getValue("type");
+ String aDefault = attr.getValue("default");
boolean aRequired = Boolean.valueOf(attr.getValue("required"));
- myCurrentFunction.addParameter(new CfmlFunctionDescription.CfmlParameterDescription(aName, aType, aRequired));
+ myCurrentFunction.addParameter(new CfmlFunctionDescription.CfmlParameterDescription(aName, aType, aDefault, aRequired));
}
else if (localName.equals("help")) {
myIsFunctionHelpSection = true;
diff --git a/CFML/src/com/intellij/coldFusion/model/parsers/CfmlElementTypes.java b/CFML/src/com/intellij/coldFusion/model/parsers/CfmlElementTypes.java
index edd6517f450..49a7592d5e2 100644
--- a/CFML/src/com/intellij/coldFusion/model/parsers/CfmlElementTypes.java
+++ b/CFML/src/com/intellij/coldFusion/model/parsers/CfmlElementTypes.java
@@ -127,6 +127,12 @@ public PsiElement createPsiElement(final ASTNode node) {
return new CfmlReferenceExpression(node);
}
};
+ IElementType ARRAY_ACCESS_EXPRESSION = new CfmlCompositeElementType("ArrayAccessExpression") {
+ @Override
+ public PsiElement createPsiElement(final ASTNode node) {
+ return new CfmlArrayAccessExpression(node);
+ }
+ };
CfmlCompositeElementType FUNCTION_CALL_EXPRESSION = new CfmlCompositeElementType("FunctionCallExpression") {
@Override
public PsiElement createPsiElement(final ASTNode node) {
@@ -181,6 +187,12 @@ public PsiElement createPsiElement(final ASTNode node) {
return new CfmlTagFunctionParameterImpl(node);
}
};
+ CfmlCompositeElementType PARAM_TAG = new CfmlCompositeElementType("Tag") {
+ @Override
+ public PsiElement createPsiElement(final ASTNode node) {
+ return new CfmlTagParamImpl(node);
+ }
+ };
CfmlCompositeElementType SCRIPT_TAG = new CfmlCompositeElementType("Tag") {
@Override
public PsiElement createPsiElement(final ASTNode node) {
diff --git a/CFML/src/com/intellij/coldFusion/model/parsers/CfmlExpressionParser.java b/CFML/src/com/intellij/coldFusion/model/parsers/CfmlExpressionParser.java
index 27a5189f69d..0ebb0e15ae3 100644
--- a/CFML/src/com/intellij/coldFusion/model/parsers/CfmlExpressionParser.java
+++ b/CFML/src/com/intellij/coldFusion/model/parsers/CfmlExpressionParser.java
@@ -18,6 +18,7 @@
import com.intellij.coldFusion.CfmlBundle;
import com.intellij.coldFusion.model.lexer.CfmlTokenTypes;
import com.intellij.coldFusion.model.lexer.CfscriptTokenTypes;
+import com.intellij.coldFusion.model.psi.CfmlElementType;
import com.intellij.lang.PsiBuilder;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.Nullable;
@@ -100,7 +101,8 @@ public boolean parseExpression() {
return true;
}
expr.done(CfmlElementTypes.TERNARY_EXPRESSION);
- } else if (myBuilder.getTokenType() == ELVIS) {
+ }
+ else if (myBuilder.getTokenType() == ELVIS) {
advance();
if (!parseExpression()) {
myBuilder.error(CfmlBundle.message("cfml.parsing.expression.expected"));
@@ -445,6 +447,9 @@ public void parseComponentReference() {
}
myBuilder.advanceLexer();
}
+ if (myBuilder.getTokenType() == MUL) {
+ myBuilder.advanceLexer();
+ }
componentReferenceMarker.done(CfmlElementTypes.COMPONENT_REFERENCE);
}
@@ -495,8 +500,7 @@ else if (parseNewExpression()) {
isReference = true;
referenceExpression = referenceExpression.precede();
parseArrayAccess();
- // referenceExpression.done(CfmlElementTypes.ARRAY_ACCESS);
- referenceExpression.done(CfmlElementTypes.NONE);
+ referenceExpression.done(CfmlElementTypes.ARRAY_ACCESS_EXPRESSION);
arrayAccessNumber++;
}
if (arrayAccessNumber != 1) {
@@ -619,7 +623,7 @@ else if (parseRValue()) {
*/
private void parseAssignsList() {
- while(true) {
+ while (true) {
parseAssignmentExpression(true);
if (getTokenType() != COMMA) break;
advance();
@@ -634,6 +638,7 @@ public boolean parseNewExpression() {
return false;
}
PsiBuilder.Marker newExpression = mark();
+ PsiBuilder.Marker outerExpression = newExpression;
advance();
PsiBuilder.Marker constructorCall = mark();
if (getTokenType() == CfmlTokenTypes.DOUBLE_QUOTE) {
@@ -643,11 +648,35 @@ else if (getTokenType() == CfscriptTokenTypes.IDENTIFIER) {
parseComponentReference();
}
else {
- myBuilder.error(CfmlBundle.message("cfml.parsing.identifier.expected"));
+ newExpression.rollbackTo();
+ return false;
}
parseArgumentsList();
constructorCall.done(CfmlElementTypes.COMPONENT_CONSTRUCTOR_CALL);
newExpression.done(CfmlElementTypes.NEW_EXPRESSION);
+ while (getTokenType() == POINT) {
+ PsiBuilder.Marker beforePoint = mark();
+ outerExpression = outerExpression.precede();
+ advance();
+ if (getTokenType() == IDENTIFIER) {
+ advance();
+ beforePoint.drop();
+ outerExpression.done(CfmlElementTypes.REFERENCE_EXPRESSION);
+ beforePoint = mark();
+ if (getTokenType() == L_BRACKET) {
+ outerExpression = outerExpression.precede();
+ if (!parseArgumentsList()) {
+ beforePoint.rollbackTo();
+ break;
+ }
+ outerExpression.done(CfmlElementTypes.FUNCTION_CALL_EXPRESSION);
+ }
+ beforePoint.drop();
+ continue;
+ }
+ beforePoint.rollbackTo();
+ break;
+ }
return true;
}
diff --git a/CFML/src/com/intellij/coldFusion/model/parsers/CfmlParser.java b/CFML/src/com/intellij/coldFusion/model/parsers/CfmlParser.java
index aeddc4c9be0..dc1376f5e7d 100644
--- a/CFML/src/com/intellij/coldFusion/model/parsers/CfmlParser.java
+++ b/CFML/src/com/intellij/coldFusion/model/parsers/CfmlParser.java
@@ -47,6 +47,9 @@ else if ("cfinvoke".equals(StringUtil.toLowerCase(tagName))) {
else if ("cfargument".equals(StringUtil.toLowerCase(tagName))) {
return CfmlElementTypes.ARGUMENT_TAG;
}
+ else if ("cfparam".equals(StringUtil.toLowerCase(tagName))) {
+ return CfmlElementTypes.PARAM_TAG;
+ }
else if ("cfscript".equals(StringUtil.toLowerCase(tagName))) {
return CfmlElementTypes.SCRIPT_TAG;
}
@@ -185,6 +188,7 @@ private static boolean doNeedNamedAttribute(String tagName) {
return false;
}
return !(StringUtil.toLowerCase(tagName).equals("cffunction") ||
+ StringUtil.toLowerCase(tagName).equals("cfparam") ||
StringUtil.toLowerCase(tagName).equals("cfargument"));
}
@@ -218,7 +222,6 @@ else if (tagName.equals("cfif") || tagName.equals("cfelseif") || tagName.equals(
*/
if (builder.getTokenType() != ASSIGN) {
attrMarker.done(CfmlElementTypes.ATTRIBUTE);
- builder.error(CfmlBundle.message("cfml.parsing.no.value"));
continue;
}
builder.advanceLexer();
diff --git a/CFML/src/com/intellij/coldFusion/model/parsers/CfscriptParser.java b/CFML/src/com/intellij/coldFusion/model/parsers/CfscriptParser.java
index 11a4e6d5f33..c541a00323f 100644
--- a/CFML/src/com/intellij/coldFusion/model/parsers/CfscriptParser.java
+++ b/CFML/src/com/intellij/coldFusion/model/parsers/CfscriptParser.java
@@ -24,6 +24,7 @@
import java.util.Objects;
+import static com.intellij.coldFusion.model.lexer.CfmlTokenTypes.*;
import static com.intellij.coldFusion.model.lexer.CfscriptTokenTypes.*;
import static com.intellij.coldFusion.model.parsers.CfmlKeywordsKt.isKeyword;
import static com.intellij.coldFusion.model.parsers.CfmlKeywordsKt.parseKeyword;
@@ -444,14 +445,14 @@ private void parseParametersList(PsiBuilder myBuilder) {
}
// try to parse type
final PsiBuilder.Marker marker = myBuilder.mark();
- if (!parseType(myBuilder) || myBuilder.getTokenType() != IDENTIFIER) {
+ if (!parseType(myBuilder) || (myBuilder.getTokenType() != IDENTIFIER && !KEYWORDS.contains(myBuilder.getTokenType()))) {
marker.rollbackTo();
}
else {
marker.drop();
}
// parse parameter name
- if (myBuilder.getTokenType() == IDENTIFIER) {
+ if (myBuilder.getTokenType() == IDENTIFIER || KEYWORDS.contains(myBuilder.getTokenType())) {
myBuilder.advanceLexer();
if (myBuilder.getTokenType() == CfmlTokenTypes.ASSIGN) { // parse default value
@@ -635,6 +636,26 @@ private static boolean parseType(PsiBuilder myBuilder) {
typeMarker.done(CfmlElementTypes.TYPE);
}
else {
+ if (STRING_ELEMENTS.contains(myBuilder.getTokenType())) {
+ final PsiBuilder.Marker stringMarker = myBuilder.mark();
+ myBuilder.advanceLexer();
+ if (myBuilder.getTokenType() != STRING_TEXT) {
+ stringMarker.rollbackTo();
+ myBuilder.error(CfmlBundle.message("cfml.parsing.string.expected"));
+ return false;
+ }
+ final PsiBuilder.Marker typeMarker = myBuilder.mark();
+ myBuilder.advanceLexer();
+ typeMarker.done(CfmlElementTypes.TYPE);
+ if (!STRING_ELEMENTS.contains(myBuilder.getTokenType())) {
+ stringMarker.rollbackTo();
+ myBuilder.error(CfmlBundle.message("cfml.parsing.string.expected"));
+ return false;
+ }
+ myBuilder.advanceLexer();
+ stringMarker.done(CfmlElementTypes.STRING_LITERAL);
+ return true;
+ }
if (myBuilder.getTokenType() != IDENTIFIER) {
myBuilder.error(CfmlBundle.message("cfml.parsing.type.expected"));
return false;
diff --git a/CFML/src/com/intellij/coldFusion/model/psi/CfmlArrayAccessExpression.java b/CFML/src/com/intellij/coldFusion/model/psi/CfmlArrayAccessExpression.java
new file mode 100644
index 00000000000..6fa46ed6ca6
--- /dev/null
+++ b/CFML/src/com/intellij/coldFusion/model/psi/CfmlArrayAccessExpression.java
@@ -0,0 +1,45 @@
+package com.intellij.coldFusion.model.psi;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.psi.PsiArrayType;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class CfmlArrayAccessExpression extends CfmlCompositeElement implements CfmlExpression, CfmlTypedElement {
+ public CfmlArrayAccessExpression(@NotNull ASTNode node) {
+ super(node);
+ }
+
+ @Nullable
+ public CfmlReference getReferenceExpression() {
+ return findChildByClass(CfmlReferenceExpression.class);
+ }
+
+ @Nullable
+ public PsiType getExternalType() {
+ final CfmlReference referenceExpression = getReferenceExpression();
+ if (referenceExpression != null) {
+ final PsiElement resolve = referenceExpression.resolve();
+ return resolve instanceof CfmlVariable ? ((CfmlVariable)resolve).getPsiType() : null;
+ }
+ return null;
+ }
+
+ @Override
+ @Nullable
+ public PsiType getPsiType() {
+ PsiType type = getExternalType();
+
+ if (type == null) {
+ CfmlReference referenceExpression = getReferenceExpression();
+ type = referenceExpression != null ? referenceExpression.getPsiType() : null;
+ }
+
+ if (type instanceof PsiArrayType) {
+ return ((PsiArrayType)type).getComponentType();
+ }
+ return null;
+ }
+}
diff --git a/CFML/src/com/intellij/coldFusion/model/psi/CfmlComponent.java b/CFML/src/com/intellij/coldFusion/model/psi/CfmlComponent.java
index a6cc2bc150b..384459148af 100755
--- a/CFML/src/com/intellij/coldFusion/model/psi/CfmlComponent.java
+++ b/CFML/src/com/intellij/coldFusion/model/psi/CfmlComponent.java
@@ -24,6 +24,9 @@
public interface CfmlComponent extends CfmlPsiElement, CfmlNamedElement {
CfmlComponent[] EMPTY_ARRAY = new CfmlComponent[0];
+ @Nullable
+ String getDescription();
+
@NotNull
CfmlFunction[] getFunctions();
diff --git a/CFML/src/com/intellij/coldFusion/model/psi/CfmlComponentReference.java b/CFML/src/com/intellij/coldFusion/model/psi/CfmlComponentReference.java
index d3d72f02d15..0250f90c65f 100755
--- a/CFML/src/com/intellij/coldFusion/model/psi/CfmlComponentReference.java
+++ b/CFML/src/com/intellij/coldFusion/model/psi/CfmlComponentReference.java
@@ -122,8 +122,8 @@ public static Collection resolveFromQualifiedName(String componen
// PsiFile containingFile = getContainingFile();
// containingFile = containingFile == null ? null : containingFile.getOriginalFile();
{
- CfmlFile cfmlConteiningFile = originalFile;
- PsiDirectory directory = cfmlConteiningFile.getParent();
+ CfmlFile cfmlContainingFile = originalFile;
+ PsiDirectory directory = cfmlContainingFile.getParent();
if (directory != null) {
GlobalSearchScope searchScope = GlobalSearchScopesCore.directoryScope(directory, false);
@@ -166,6 +166,15 @@ public static Collection resolveFromQualifiedName(String componen
components.addAll(CfmlIndex.getInstance(project).getInterfacesByName(
componentName));
+ if (componentName.equals("*")) {
+ for (String name : CfmlIndex.getInstance(project).getAllComponentsNames()) {
+ components.addAll(CfmlIndex.getInstance(project).getComponentsByName(name));
+ }
+ for (String name : CfmlIndex.getInstance(project).getAllInterfaceNames()) {
+ components.addAll(CfmlIndex.getInstance(project).getInterfacesByName(name));
+ }
+ }
+
for (CfmlComponent component : components) {
PsiDirectory parent = component.getContainingFile().getParent();
if (parent == null) {
@@ -333,7 +342,7 @@ public Object[] getVariants() {
public static Object[] buildVariants(String text, PsiFile containingFile, final Project project,
@Nullable CfmlComponentReference reference,
final boolean forceQualify
- ) {
+ ) {
Collection