diff --git a/.consulo/runConfigurations/consulo_run_desktop_awt.xml b/.consulo/runConfigurations/consulo_run_desktop_awt.xml new file mode 100644 index 00000000..45d7fbfd --- /dev/null +++ b/.consulo/runConfigurations/consulo_run_desktop_awt.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 00000000..8dae953b --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,24 @@ +name: jdk21 + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] +env: + BUILD_NUMBER: 999999 + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 21 + uses: actions/setup-java@v1 + with: + distribution: 'temurin' + java-version: 21 + - name: Build with Maven + run: mvn -U -T 1C -Dmaven.javadoc.skip=true -B -V clean package diff --git a/.gitignore b/.gitignore index d26fae78..d7c94e2a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ /.consulo !/.consulo/codeStyleSettings.xml +!/.consulo/runConfigurations /out /target -target/ \ No newline at end of file +target/ +plugin/sandbox/ \ No newline at end of file diff --git a/README.md b/README.md index 075c9a79..496ebd2e 100644 --- a/README.md +++ b/README.md @@ -1 +1,5 @@ -[![Build Status](https://ci.consulo.io/job/consulo-javascript/badge/icon)](https://ci.consulo.io/job/consulo-javascript) \ No newline at end of file +[![Build Status](https://ci.consulo.io/job/consulo-javascript/badge/icon)](https://ci.consulo.io/job/consulo-javascript) + + +# Browser Debugging + * For `Chrome Like` browsers visit [https://github.com/consulo/chrome-consulo-debugger-extension](link) diff --git a/base-api/pom.xml b/base-api/pom.xml index 24095d66..b7bc90b0 100644 --- a/base-api/pom.xml +++ b/base-api/pom.xml @@ -32,7 +32,7 @@ consulo - https://maven.consulo.io/repository/snapshots/ + https://maven.consulo.dev/repository/snapshots/ true interval:60 diff --git a/base-api/src/main/java/com/intellij/lang/javascript/formatter/JSCodeStyleSettings.java b/base-api/src/main/java/com/intellij/lang/javascript/formatter/JSCodeStyleSettings.java index bc71236b..b33c1586 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/formatter/JSCodeStyleSettings.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/formatter/JSCodeStyleSettings.java @@ -21,21 +21,18 @@ /** * @author Maxim.Mossienko - * Date: Mar 12, 2008 - * Time: 10:25:17 PM + * @since 2008-03-12 */ -public class JSCodeStyleSettings extends CustomCodeStyleSettings -{ - public int INDENT_PACKAGE_CHILDREN = DO_NOT_INDENT; - public boolean USE_SEMICOLON_AFTER_STATEMENT = true; - public String FIELD_PREFIX = "_"; - public String PROPERTY_PREFIX = ""; +public class JSCodeStyleSettings extends CustomCodeStyleSettings { + public int INDENT_PACKAGE_CHILDREN = DO_NOT_INDENT; + public boolean USE_SEMICOLON_AFTER_STATEMENT = true; + public String FIELD_PREFIX = "_"; + public String PROPERTY_PREFIX = ""; - public static final int DO_NOT_INDENT = 0; - public static final int INDENT = 1; + public static final int DO_NOT_INDENT = 0; + public static final int INDENT = 1; - public JSCodeStyleSettings(CodeStyleSettings container) - { - super("JSCodeStyleSettings", container); - } + public JSCodeStyleSettings(CodeStyleSettings container) { + super("JSCodeStyleSettings", container); + } } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSArgumentList.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSArgumentList.java index ebca9251..1257b8b0 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSArgumentList.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSArgumentList.java @@ -17,13 +17,9 @@ package com.intellij.lang.javascript.psi; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 7:44:58 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSArgumentList extends JSElement -{ - JSExpression[] getArguments(); +public interface JSArgumentList extends JSElement { + JSExpression[] getArguments(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSArrayLiteralExpression.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSArrayLiteralExpression.java index 94b251b8..f2cd42bc 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSArrayLiteralExpression.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSArrayLiteralExpression.java @@ -16,18 +16,17 @@ package com.intellij.lang.javascript.psi; +import consulo.annotation.access.RequiredReadAction; + /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 7:30:55 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSArrayLiteralExpression extends JSExpression -{ - /** - * @return nulls stand in the returned array for skipped values. This for [,1,] array of 3 elements to be returned with first and last - * elements nulled - */ - JSExpression[] getExpressions(); +public interface JSArrayLiteralExpression extends JSExpression { + /** + * @return nulls stand in the returned array for skipped values. This for [,1,] array of 3 elements to be returned with first and last + * elements nulled + */ + @RequiredReadAction + JSExpression[] getExpressions(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSAssignmentExpression.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSAssignmentExpression.java index 604c8590..147515af 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSAssignmentExpression.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSAssignmentExpression.java @@ -17,12 +17,8 @@ package com.intellij.lang.javascript.psi; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 7:40:31 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSAssignmentExpression extends JSBinaryExpression -{ +public interface JSAssignmentExpression extends JSBinaryExpression { } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSAttribute.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSAttribute.java index 9d3baef7..697dfcf5 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSAttribute.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSAttribute.java @@ -16,34 +16,32 @@ package com.intellij.lang.javascript.psi; -import javax.annotation.Nonnull; - import com.intellij.lang.javascript.psi.stubs.JSAttributeStub; +import consulo.annotation.access.RequiredReadAction; import consulo.language.psi.PsiNamedElement; import consulo.language.psi.StubBasedPsiElement; import consulo.util.collection.ArrayFactory; +import jakarta.annotation.Nonnull; /** - * @author Maxim.Mossienko + * @author Maxim.Mossienko */ -public interface JSAttribute extends JSElement, PsiNamedElement, StubBasedPsiElement -{ - public static final JSAttribute[] EMPTY_ARRAY = new JSAttribute[0]; +public interface JSAttribute extends JSElement, PsiNamedElement, StubBasedPsiElement { + JSAttribute[] EMPTY_ARRAY = new JSAttribute[0]; - public static ArrayFactory ARRAY_FACTORY = new ArrayFactory() - { - @Nonnull - @Override - public JSAttribute[] create(int count) - { - return count == 0 ? EMPTY_ARRAY : new JSAttribute[count]; - } - }; + ArrayFactory ARRAY_FACTORY = new ArrayFactory<>() { + @Nonnull + @Override + public JSAttribute[] create(int count) { + return count == 0 ? EMPTY_ARRAY : new JSAttribute[count]; + } + }; - @Override - String getName(); + @Override + @RequiredReadAction + String getName(); - JSAttributeNameValuePair[] getValues(); + JSAttributeNameValuePair[] getValues(); - JSAttributeNameValuePair getValueByName(String name); + JSAttributeNameValuePair getValueByName(String name); } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSAttributeList.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSAttributeList.java index acfcd11e..a2aae4cf 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSAttributeList.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSAttributeList.java @@ -16,43 +16,55 @@ package com.intellij.lang.javascript.psi; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import consulo.annotation.access.RequiredReadAction; +import jakarta.annotation.Nullable; import com.intellij.lang.javascript.psi.stubs.JSAttributeListStub; import consulo.language.psi.PsiElement; import consulo.language.psi.StubBasedPsiElement; +import jakarta.annotation.Nonnull; /** * @author Maxim.Mossienko */ -public interface JSAttributeList extends JSElement, StubBasedPsiElement -{ - @Nullable - String getNamespace(); +public interface JSAttributeList extends JSElement, StubBasedPsiElement { + @Nullable + @RequiredReadAction + String getNamespace(); - @Nullable - JSReferenceExpression getNamespaceElement(); + @Nullable + @RequiredReadAction + JSReferenceExpression getNamespaceElement(); - JSAttribute[] getAttributes(); + JSAttribute[] getAttributes(); - @Nonnull - JSAttribute[] getAttributesByName(@Nonnull String name); + @Nonnull + @RequiredReadAction + JSAttribute[] getAttributesByName(@Nonnull String name); - enum AccessType - { - PACKAGE_LOCAL, PUBLIC, PRIVATE, PROTECTED; - } + enum AccessType { + PACKAGE_LOCAL, + PUBLIC, + PRIVATE, + PROTECTED + } - AccessType getAccessType(); + @RequiredReadAction + AccessType getAccessType(); - @Nullable - PsiElement findAccessTypeElement(); + @Nullable + @RequiredReadAction + PsiElement findAccessTypeElement(); - enum ModifierType - { - DYNAMIC, NATIVE, OVERRIDE, STATIC, FINAL, VIRTUAL - } + enum ModifierType { + DYNAMIC, + NATIVE, + OVERRIDE, + STATIC, + FINAL, + VIRTUAL + } - boolean hasModifier(ModifierType modifier); + @RequiredReadAction + boolean hasModifier(ModifierType modifier); } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSAttributeListOwner.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSAttributeListOwner.java index f20c33d5..cf325a78 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSAttributeListOwner.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSAttributeListOwner.java @@ -18,13 +18,12 @@ import consulo.language.psi.PsiElement; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; /** - * @by Maxim.Mossienko + * @author Maxim.Mossienko */ -public interface JSAttributeListOwner extends PsiElement -{ - @Nullable - JSAttributeList getAttributeList(); +public interface JSAttributeListOwner extends PsiElement { + @Nullable + JSAttributeList getAttributeList(); } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSAttributeNameValuePair.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSAttributeNameValuePair.java index 426f6c43..b2147f49 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSAttributeNameValuePair.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSAttributeNameValuePair.java @@ -16,20 +16,22 @@ package com.intellij.lang.javascript.psi; -import javax.annotation.Nullable; +import consulo.annotation.access.RequiredReadAction; +import jakarta.annotation.Nullable; import com.intellij.lang.javascript.psi.stubs.JSAttributeNameValuePairStub; import consulo.language.psi.PsiNamedElement; import consulo.language.psi.StubBasedPsiElement; /** - * @by Maxim.Mossienko + * @author Maxim.Mossienko */ -public interface JSAttributeNameValuePair extends JSElement, PsiNamedElement, StubBasedPsiElement -{ - JSAttributeNameValuePair[] EMPTY_ARRAY = new JSAttributeNameValuePair[0]; +public interface JSAttributeNameValuePair extends JSElement, PsiNamedElement, StubBasedPsiElement { + JSAttributeNameValuePair[] EMPTY_ARRAY = new JSAttributeNameValuePair[0]; - JSExpression getValue(); + @RequiredReadAction + JSExpression getValue(); - @Nullable - String getSimpleValue(); + @Nullable + @RequiredReadAction + String getSimpleValue(); } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSBinaryExpression.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSBinaryExpression.java index b88ac07b..a13a2643 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSBinaryExpression.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSBinaryExpression.java @@ -19,31 +19,27 @@ import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.IElementType; import consulo.language.psi.PsiElement; - -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 6:49:21 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSBinaryExpression extends JSExpression -{ - JSExpression getLOperand(); +public interface JSBinaryExpression extends JSExpression { + @RequiredReadAction + JSExpression getLOperand(); - JSExpression getROperand(); + @RequiredReadAction + JSExpression getROperand(); - @Nullable - @RequiredReadAction - default IElementType getOperationSign() - { - PsiElement element = getOperationElement(); - return element != null ? element.getNode().getElementType() : null; - } + @Nullable + @RequiredReadAction + default IElementType getOperationSign() { + PsiElement element = getOperationElement(); + return element != null ? element.getNode().getElementType() : null; + } - @Nullable - @RequiredReadAction - PsiElement getOperationElement(); + @Nullable + @RequiredReadAction + PsiElement getOperationElement(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSBlockStatement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSBlockStatement.java index 13075ffb..f7a142f5 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSBlockStatement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSBlockStatement.java @@ -17,13 +17,9 @@ package com.intellij.lang.javascript.psi; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 6:51:45 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSBlockStatement extends JSStatement -{ - JSStatement[] getStatements(); +public interface JSBlockStatement extends JSStatement { + JSStatement[] getStatements(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSBreakStatement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSBreakStatement.java index a02fb1da..23c3ab44 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSBreakStatement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSBreakStatement.java @@ -16,16 +16,16 @@ package com.intellij.lang.javascript.psi; +import consulo.annotation.access.RequiredReadAction; + /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 6:58:10 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSBreakStatement extends JSStatement -{ - String getLabel(); +public interface JSBreakStatement extends JSStatement { + @RequiredReadAction + String getLabel(); - JSStatement getStatementToBreak(); + @RequiredReadAction + JSStatement getStatementToBreak(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSCallExpression.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSCallExpression.java index 8d55ea46..7c7c4311 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSCallExpression.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSCallExpression.java @@ -16,16 +16,15 @@ package com.intellij.lang.javascript.psi; +import consulo.annotation.access.RequiredReadAction; + /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 7:46:07 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSCallExpression extends JSExpression -{ - JSExpression getMethodExpression(); +public interface JSCallExpression extends JSExpression { + JSExpression getMethodExpression(); - JSArgumentList getArgumentList(); + @RequiredReadAction + JSArgumentList getArgumentList(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSCaseClause.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSCaseClause.java index 317ac8bb..00dde4dc 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSCaseClause.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSCaseClause.java @@ -16,18 +16,18 @@ package com.intellij.lang.javascript.psi; +import consulo.annotation.access.RequiredReadAction; + /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 7:16:36 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSCaseClause extends JSElement -{ - boolean isDefault(); +public interface JSCaseClause extends JSElement { + @RequiredReadAction + boolean isDefault(); - JSExpression getCaseExpression(); + @RequiredReadAction + JSExpression getCaseExpression(); - JSStatement[] getStatements(); + JSStatement[] getStatements(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSCatchBlock.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSCatchBlock.java index a740a994..be01f5c8 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSCatchBlock.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSCatchBlock.java @@ -16,18 +16,17 @@ package com.intellij.lang.javascript.psi; +import consulo.annotation.access.RequiredReadAction; + /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 7:04:04 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSCatchBlock extends JSElement -{ - JSCatchBlock[] EMPTY_ARRAY = new JSCatchBlock[0]; +public interface JSCatchBlock extends JSElement { + JSCatchBlock[] EMPTY_ARRAY = new JSCatchBlock[0]; - JSParameter getParameter(); + @RequiredReadAction + JSParameter getParameter(); - JSStatement getStatement(); + JSStatement getStatement(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSClass.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSClass.java index 65524958..3d98321f 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSClass.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSClass.java @@ -16,41 +16,40 @@ package com.intellij.lang.javascript.psi; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import com.intellij.lang.javascript.psi.stubs.JSClassStub; import consulo.language.psi.StubBasedPsiElement; import consulo.navigation.Navigatable; /** - * @by Maxim.Mossienko + * @author Maxim.Mossienko */ -public interface JSClass extends JSQualifiedNamedElement, JSSourceElement, JSAttributeListOwner, Navigatable, StubBasedPsiElement -{ - JSClass[] EMPTY_ARRAY = new JSClass[0]; +public interface JSClass extends JSQualifiedNamedElement, JSSourceElement, JSAttributeListOwner, Navigatable, StubBasedPsiElement { + JSClass[] EMPTY_ARRAY = new JSClass[0]; - @Nullable - JSReferenceList getExtendsList(); + @Nullable + JSReferenceList getExtendsList(); - @Nullable - JSReferenceList getImplementsList(); + @Nullable + JSReferenceList getImplementsList(); - boolean isInterface(); + boolean isInterface(); - JSClass[] getSuperClasses(); + JSClass[] getSuperClasses(); - JSFunction[] getFunctions(); + JSFunction[] getFunctions(); - JSVariable[] getFields(); + JSVariable[] getFields(); - JSFunction findFunctionByName(final String name); + JSFunction findFunctionByName(String name); - JSFunction findFunctionByNameAndKind(final String name, JSFunction.FunctionKind kind); + JSFunction findFunctionByNameAndKind(String name, JSFunction.FunctionKind kind); - JSVariable findFieldByName(final String name); + JSVariable findFieldByName(String name); - JSClass[] getSupers(); + JSClass[] getSupers(); - JSClass[] getImplementedInterfaces(); + JSClass[] getImplementedInterfaces(); - boolean isDeprecated(); + boolean isDeprecated(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSClassExpression.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSClassExpression.java index edde7c95..7b971391 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSClassExpression.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSClassExpression.java @@ -2,15 +2,14 @@ import consulo.annotation.access.RequiredReadAction; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL - * @since 11/12/2021 + * @since 2021-12-11 */ -public interface JSClassExpression extends JSExpression -{ - @Nonnull - @RequiredReadAction - JSClass getClassElement(); +public interface JSClassExpression extends JSExpression { + @Nonnull + @RequiredReadAction + JSClass getClassElement(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSCommaExpression.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSCommaExpression.java index c22fc23d..c1bcfd29 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSCommaExpression.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSCommaExpression.java @@ -17,12 +17,8 @@ package com.intellij.lang.javascript.psi; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 7:42:26 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSCommaExpression extends JSBinaryExpression -{ +public interface JSCommaExpression extends JSBinaryExpression { } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSConditionalExpression.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSConditionalExpression.java index 44c01c43..ee9f3b7c 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSConditionalExpression.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSConditionalExpression.java @@ -16,18 +16,19 @@ package com.intellij.lang.javascript.psi; +import consulo.annotation.access.RequiredReadAction; + /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 7:40:54 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSConditionalExpression extends JSExpression -{ - JSExpression getCondition(); +public interface JSConditionalExpression extends JSExpression { + @RequiredReadAction + JSExpression getCondition(); - JSExpression getThen(); + @RequiredReadAction + JSExpression getThen(); - JSExpression getElse(); + @RequiredReadAction + JSExpression getElse(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSContinueStatement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSContinueStatement.java index 12033b67..48b6a567 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSContinueStatement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSContinueStatement.java @@ -16,16 +16,15 @@ package com.intellij.lang.javascript.psi; +import consulo.annotation.access.RequiredReadAction; + /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 6:58:10 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSContinueStatement extends JSStatement -{ - String getLabel(); +public interface JSContinueStatement extends JSStatement { + String getLabel(); - JSStatement getStatementToContinue(); + @RequiredReadAction + JSStatement getStatementToContinue(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDefinitionExpression.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDefinitionExpression.java index 25740607..ebbe5147 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDefinitionExpression.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDefinitionExpression.java @@ -17,13 +17,9 @@ package com.intellij.lang.javascript.psi; /** - * Created by IntelliJ IDEA. - * User: maxim.mossienko - * Date: Dec 14, 2005 - * Time: 6:37:59 PM - * To change this template use File | Settings | File Templates. + * @author maxim.mossienko + * @since 2005-12-14 */ -public interface JSDefinitionExpression extends JSExpression, JSNamedElement -{ - JSExpression getExpression(); +public interface JSDefinitionExpression extends JSExpression, JSNamedElement { + JSExpression getExpression(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDestructuringElement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDestructuringElement.java index 21d7556e..e672c092 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDestructuringElement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDestructuringElement.java @@ -1,25 +1,23 @@ package com.intellij.lang.javascript.psi; import consulo.annotation.access.RequiredReadAction; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; /** * @author VISTALL * @since 2019-12-14 */ -public interface JSDestructuringElement extends JSElement -{ - @Nonnull - @RequiredReadAction - default JSVariable[] getVariables() - { - JSDestructuringObject object = getDestructuringObject(); - return object == null ? JSVariable.EMPTY_ARRAY : object.getVariables(); - } +public interface JSDestructuringElement extends JSElement { + @Nonnull + @RequiredReadAction + default JSVariable[] getVariables() { + JSDestructuringObject object = getDestructuringObject(); + return object == null ? JSVariable.EMPTY_ARRAY : object.getVariables(); + } - @Nullable - @RequiredReadAction - JSDestructuringObject getDestructuringObject(); + @Nullable + @RequiredReadAction + JSDestructuringObject getDestructuringObject(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDestructuringObject.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDestructuringObject.java index de354952..56b3e92a 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDestructuringObject.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDestructuringObject.java @@ -2,17 +2,16 @@ import consulo.annotation.access.RequiredReadAction; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 2019-12-14 */ -public interface JSDestructuringObject extends JSElement -{ - @Nonnull - @RequiredReadAction - JSVariable[] getVariables(); +public interface JSDestructuringObject extends JSElement { + @Nonnull + @RequiredReadAction + JSVariable[] getVariables(); - JSDestructuringShorthandedProperty[] getProperties(); + JSDestructuringShorthandedProperty[] getProperties(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDestructuringParameter.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDestructuringParameter.java index 078d98d0..d2618005 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDestructuringParameter.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDestructuringParameter.java @@ -1,16 +1,14 @@ package com.intellij.lang.javascript.psi; import consulo.annotation.access.RequiredReadAction; - -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; /** * @author VISTALL * @since 2019-12-17 */ -public interface JSDestructuringParameter extends JSParameter -{ - @RequiredReadAction - @Nullable - JSDestructuringObject getDestructuringObject(); +public interface JSDestructuringParameter extends JSParameter { + @Nullable + @RequiredReadAction + JSDestructuringObject getDestructuringObject(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDestructuringShorthandedProperty.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDestructuringShorthandedProperty.java index 4af569e5..1b48d22e 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDestructuringShorthandedProperty.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDestructuringShorthandedProperty.java @@ -1,16 +1,14 @@ package com.intellij.lang.javascript.psi; import consulo.annotation.access.RequiredReadAction; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 2019-12-14 */ -public interface JSDestructuringShorthandedProperty extends JSElement -{ - @RequiredReadAction - @Nonnull - JSVariable getVarialbe(); +public interface JSDestructuringShorthandedProperty extends JSElement { + @Nonnull + @RequiredReadAction + JSVariable getVariable(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDoWhileStatement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDoWhileStatement.java index 00f82e16..c5bc10ae 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDoWhileStatement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDoWhileStatement.java @@ -17,13 +17,9 @@ package com.intellij.lang.javascript.psi; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 7:25:34 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSDoWhileStatement extends JSLoopStatement -{ - JSExpression getCondition(); +public interface JSDoWhileStatement extends JSLoopStatement { + JSExpression getCondition(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDocComment.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDocComment.java index 7647a5ad..5062a699 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDocComment.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDocComment.java @@ -16,9 +16,10 @@ package com.intellij.lang.javascript.psi; +import consulo.annotation.access.RequiredReadAction; import consulo.language.psi.PsiComment; -public interface JSDocComment extends PsiComment, JSElement -{ - JSDocTag[] getTags(); +public interface JSDocComment extends PsiComment, JSElement { + @RequiredReadAction + JSDocTag[] getTags(); } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDocTag.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDocTag.java index 49983e35..858b322f 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDocTag.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDocTag.java @@ -16,13 +16,12 @@ package com.intellij.lang.javascript.psi; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import consulo.language.psi.PsiNamedElement; -public interface JSDocTag extends PsiNamedElement, JSElement -{ - JSDocTag[] EMPTY_ARRAY = new JSDocTag[0]; +public interface JSDocTag extends PsiNamedElement, JSElement { + JSDocTag[] EMPTY_ARRAY = new JSDocTag[0]; - @Nullable - JSDocTagValue getValue(); + @Nullable + JSDocTagValue getValue(); } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDocTagValue.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDocTagValue.java index 7aa3a68f..a2d2df3c 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDocTagValue.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSDocTagValue.java @@ -16,7 +16,5 @@ package com.intellij.lang.javascript.psi; -public interface JSDocTagValue extends JSElement -{ - +public interface JSDocTagValue extends JSElement { } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSElement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSElement.java index 0057fb5a..89c2da37 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSElement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSElement.java @@ -20,8 +20,7 @@ /** * @author max - * @since 2:30:26 PM Feb 3, 2005 + * @since 2005-02-03 */ -public interface JSElement extends NavigatablePsiElement -{ +public interface JSElement extends NavigatablePsiElement { } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSElementVisitor.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSElementVisitor.java index 431c5a53..0c781bee 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSElementVisitor.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSElementVisitor.java @@ -19,342 +19,273 @@ import consulo.javascript.psi.JSSimpleLiteralExpression; import consulo.javascript.psi.JavaScriptLambdaExpression; import consulo.language.psi.PsiElementVisitor; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Feb 3, 2005 - * Time: 2:25:12 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-02-03 */ -public class JSElementVisitor extends PsiElementVisitor -{ - public void visitJSCallExpression(final JSCallExpression node) - { - visitJSExpression(node); - } - - public void visitJSIndexedPropertyAccessExpression(final JSIndexedPropertyAccessExpression node) - { - visitJSExpression(node); - } - - public void visitJSNewExpression(final JSNewExpression node) - { - visitJSCallExpression(node); - } - - public void visitJSFunctionExpression(final JSFunctionExpression node) - { - visitJSExpression(node); - } - - public void visitJSPrefixExpression(final JSPrefixExpression expression) - { - visitJSExpression(expression); - } - - public void visitJSPostfixExpression(final JSPostfixExpression node) - { - visitJSExpression(node); - } - - public void visitJSConditionalExpression(final JSConditionalExpression node) - { - visitJSExpression(node); - } - - public void visitJSCommaExpression(final JSCommaExpression node) - { - visitJSBinaryExpression(node); - } - - public void visitJSAssignmentExpression(final JSAssignmentExpression node) - { - visitJSBinaryExpression(node); - } - - public void visitJSBinaryExpression(final JSBinaryExpression node) - { - visitJSExpression(node); - } - - public void visitJSProperty(final JSProperty node) - { - visitJSElement(node); - } - - public void visitJSObjectLiteralExpression(final JSObjectLiteralExpression node) - { - visitJSExpression(node); - } - - public void visitJSArrayLiteralExpression(final JSArrayLiteralExpression node) - { - visitJSExpression(node); - } - - public void visitJSParenthesizedExpression(final JSParenthesizedExpression node) - { - visitJSExpression(node); - } - - public void visitJSReferenceExpression(final JSReferenceExpression node) - { - visitJSExpression(node); - } - - public void visitJSDefinitionExpression(final JSDefinitionExpression node) - { - visitJSExpression(node); - } - - public void visitJSLiteralExpression(final JSSimpleLiteralExpression node) - { - visitJSExpression(node); - } - - public void visitJSThisExpression(final JSThisExpression node) - { - visitJSExpression(node); - } - - public void visitJSForInStatement(final JSForInStatement node) - { - visitJSStatement(node); - } - - public void visitJSForStatement(final JSForStatement node) - { - visitJSStatement(node); - } - - public void visitJSDoWhileStatement(final JSDoWhileStatement node) - { - visitJSStatement(node); - } - - public void visitJSWhileStatement(final JSWhileStatement node) - { - visitJSStatement(node); - } - - public void visitJSCaseClause(final JSCaseClause node) - { - visitJSElement(node); - } - - public void visitJSSwitchStatement(final JSSwitchStatement node) - { - visitJSStatement(node); - } - - public void visitJSCatchBlock(final JSCatchBlock node) - { - visitJSElement(node); - } - - public void visitJSTryStatement(final JSTryStatement node) - { - visitJSStatement(node); - } - - public void visitJSThrowStatement(final JSThrowStatement node) - { - visitJSStatement(node); - } - - public void visitJSReturnStatement(final JSReturnStatement node) - { - visitJSStatement(node); - } - - public void visitJSWithStatement(final JSWithStatement node) - { - visitJSStatement(node); - } - - public void visitJSBreakStatement(final JSBreakStatement node) - { - visitJSStatement(node); - } - - public void visitJSContinueStatement(final JSContinueStatement node) - { - visitJSStatement(node); - } - - public void visitJSIfStatement(final JSIfStatement node) - { - visitJSStatement(node); - } - - public void visitJSEmptyStatement(final JSEmptyStatement node) - { - visitJSStatement(node); - } - - public void visitJSVarStatement(final JSVarStatement node) - { - visitJSStatement(node); - } - - public void visitJSExpressionStatement(final JSExpressionStatement node) - { - visitJSStatement(node); - } - - public void visitJSLabeledStatement(final JSLabeledStatement node) - { - visitJSStatement(node); - } - - public void visitJSBlock(final JSBlockStatement node) - { - visitJSStatement(node); - } - - public void visitJSArgumentList(final JSArgumentList node) - { - visitJSElement(node); - } - - public void visitJSParameter(final JSParameter parameter) - { - visitJSVariable(parameter); - } - - public void visitJSVariable(final JSVariable node) - { - visitJSElement(node); - } - - public void visitJSParameterList(final JSParameterList node) - { - visitJSElement(node); - } - - public void visitJSElement(final JSElement node) - { - visitElement(node); - } - - public void visitJSSourceElement(final JSElement node) - { - visitJSElement(node); - } - - public void visitJSFunctionDeclaration(final JSFunction node) - { - visitJSSourceElement(node); - } - - public void visitJSStatement(final JSStatement node) - { - visitJSSourceElement(node); - } - - public void visitJSExpression(final JSExpression node) - { - visitJSElement(node); - } - - public void visitJSAttributeList(final JSAttributeList attributeList) - { - visitJSElement(attributeList); - } - - public void visitJSPackageStatement(final JSPackageStatement packageStatement) - { - visitJSStatement(packageStatement); - } - - public void visitJSImportStatement(final JSImportStatement importStatement) - { - visitJSStatement(importStatement); - } - - public void visitJSUseNamespaceDirective(final JSUseNamespaceDirective useNamespaceDirective) - { - visitJSStatement(useNamespaceDirective); - } - - public void visitJSNamespaceDeclaration(final JSNamespaceDeclaration namespaceDeclaration) - { - visitJSStatement(namespaceDeclaration); - } - - public void visitJSClass(final JSClass aClass) - { - visitJSElement(aClass); - } - - public void visitJSClassExpression(final JSClassExpression expression) - { - visitJSExpression(expression); - } - - public void visitJSReferenceList(final JSReferenceList referenceList) - { - visitJSElement(referenceList); - } - - public void visitJSSuperExpression(final JSSuperExpression superExpression) - { - visitJSExpression(superExpression); - } - - public void visitJSIncludeDirective(final JSIncludeDirective includeDirective) - { - visitJSStatement(includeDirective); - } - - public void visitJSAttribute(final JSAttribute jsAttribute) - { - visitJSElement(jsAttribute); - } - - public void visitJSAttributeNameValuePair(final JSAttributeNameValuePair attributeNameValuePair) - { - } - - public void visitJSYieldStatement(final JSYieldStatement statement) - { - visitJSStatement(statement); - } - - public void visitJSLetStatement(final JSLetStatement statement) - { - visitJSStatement(statement); - } - - public void visitJSLetExpression(final JSLetExpression expression) - { - visitJSExpression(expression); - } - - public void visitJSGenericSignature(final JSGenericSignature signature) - { - visitJSElement(signature); - } - - public void visitJSDocTagValue(final JSDocTagValue tagValue) - { - visitJSElement(tagValue); - } - - public void visitJSDocTag(final JSDocTag docTag) - { - visitJSElement(docTag); - } - - public void visitJSDocComment(final JSDocComment docComment) - { - visitComment(docComment); - } - - public void visitLambdaExpression(JavaScriptLambdaExpression expression) - { - visitJSExpression(expression); - } +public class JSElementVisitor extends PsiElementVisitor { + public void visitJSCallExpression(@Nonnull JSCallExpression node) { + visitJSExpression(node); + } + + public void visitJSIndexedPropertyAccessExpression(@Nonnull JSIndexedPropertyAccessExpression node) { + visitJSExpression(node); + } + + public void visitJSNewExpression(@Nonnull JSNewExpression node) { + visitJSCallExpression(node); + } + + public void visitJSFunctionExpression(@Nonnull JSFunctionExpression node) { + visitJSExpression(node); + } + + public void visitJSPrefixExpression(@Nonnull JSPrefixExpression expression) { + visitJSExpression(expression); + } + + public void visitJSPostfixExpression(@Nonnull JSPostfixExpression node) { + visitJSExpression(node); + } + + public void visitJSConditionalExpression(@Nonnull JSConditionalExpression node) { + visitJSExpression(node); + } + + public void visitJSCommaExpression(@Nonnull JSCommaExpression node) { + visitJSBinaryExpression(node); + } + + public void visitJSAssignmentExpression(@Nonnull JSAssignmentExpression node) { + visitJSBinaryExpression(node); + } + + public void visitJSBinaryExpression(@Nonnull JSBinaryExpression node) { + visitJSExpression(node); + } + + public void visitJSProperty(@Nonnull JSProperty node) { + visitJSElement(node); + } + + public void visitJSObjectLiteralExpression(@Nonnull JSObjectLiteralExpression node) { + visitJSExpression(node); + } + + public void visitJSArrayLiteralExpression(@Nonnull JSArrayLiteralExpression node) { + visitJSExpression(node); + } + + public void visitJSParenthesizedExpression(@Nonnull JSParenthesizedExpression node) { + visitJSExpression(node); + } + + public void visitJSReferenceExpression(@Nonnull JSReferenceExpression node) { + visitJSExpression(node); + } + + public void visitJSDefinitionExpression(@Nonnull JSDefinitionExpression node) { + visitJSExpression(node); + } + + public void visitJSLiteralExpression(@Nonnull JSSimpleLiteralExpression node) { + visitJSExpression(node); + } + + public void visitJSThisExpression(@Nonnull JSThisExpression node) { + visitJSExpression(node); + } + + public void visitJSForInStatement(@Nonnull JSForInStatement node) { + visitJSStatement(node); + } + + public void visitJSForStatement(@Nonnull JSForStatement node) { + visitJSStatement(node); + } + + public void visitJSDoWhileStatement(@Nonnull JSDoWhileStatement node) { + visitJSStatement(node); + } + + public void visitJSWhileStatement(@Nonnull JSWhileStatement node) { + visitJSStatement(node); + } + + public void visitJSCaseClause(@Nonnull JSCaseClause node) { + visitJSElement(node); + } + + public void visitJSSwitchStatement(@Nonnull JSSwitchStatement node) { + visitJSStatement(node); + } + + public void visitJSCatchBlock(@Nonnull JSCatchBlock node) { + visitJSElement(node); + } + + public void visitJSTryStatement(@Nonnull JSTryStatement node) { + visitJSStatement(node); + } + + public void visitJSThrowStatement(@Nonnull JSThrowStatement node) { + visitJSStatement(node); + } + + public void visitJSReturnStatement(@Nonnull JSReturnStatement node) { + visitJSStatement(node); + } + + public void visitJSWithStatement(@Nonnull JSWithStatement node) { + visitJSStatement(node); + } + + public void visitJSBreakStatement(@Nonnull JSBreakStatement node) { + visitJSStatement(node); + } + + public void visitJSContinueStatement(@Nonnull JSContinueStatement node) { + visitJSStatement(node); + } + + public void visitJSIfStatement(@Nonnull JSIfStatement node) { + visitJSStatement(node); + } + + public void visitJSEmptyStatement(@Nonnull JSEmptyStatement node) { + visitJSStatement(node); + } + + public void visitJSVarStatement(@Nonnull JSVarStatement node) { + visitJSStatement(node); + } + + public void visitJSExpressionStatement(@Nonnull JSExpressionStatement node) { + visitJSStatement(node); + } + + public void visitJSLabeledStatement(@Nonnull JSLabeledStatement node) { + visitJSStatement(node); + } + + public void visitJSBlock(@Nonnull JSBlockStatement node) { + visitJSStatement(node); + } + + public void visitJSArgumentList(@Nonnull JSArgumentList node) { + visitJSElement(node); + } + + public void visitJSParameter(@Nonnull JSParameter parameter) { + visitJSVariable(parameter); + } + + public void visitJSVariable(@Nonnull JSVariable node) { + visitJSElement(node); + } + + public void visitJSParameterList(@Nonnull JSParameterList node) { + visitJSElement(node); + } + + public void visitJSElement(@Nonnull JSElement node) { + visitElement(node); + } + + public void visitJSSourceElement(@Nonnull JSElement node) { + visitJSElement(node); + } + + public void visitJSFunctionDeclaration(@Nonnull JSFunction node) { + visitJSSourceElement(node); + } + + public void visitJSStatement(@Nonnull JSStatement node) { + visitJSSourceElement(node); + } + + public void visitJSExpression(@Nonnull JSExpression node) { + visitJSElement(node); + } + + public void visitJSAttributeList(@Nonnull JSAttributeList attributeList) { + visitJSElement(attributeList); + } + + public void visitJSPackageStatement(@Nonnull JSPackageStatement packageStatement) { + visitJSStatement(packageStatement); + } + + public void visitJSImportStatement(@Nonnull JSImportStatement importStatement) { + visitJSStatement(importStatement); + } + + public void visitJSUseNamespaceDirective(@Nonnull JSUseNamespaceDirective useNamespaceDirective) { + visitJSStatement(useNamespaceDirective); + } + + public void visitJSNamespaceDeclaration(@Nonnull JSNamespaceDeclaration namespaceDeclaration) { + visitJSStatement(namespaceDeclaration); + } + + public void visitJSClass(@Nonnull JSClass aClass) { + visitJSElement(aClass); + } + + public void visitJSClassExpression(@Nonnull JSClassExpression expression) { + visitJSExpression(expression); + } + + public void visitJSReferenceList(@Nonnull JSReferenceList referenceList) { + visitJSElement(referenceList); + } + + public void visitJSSuperExpression(@Nonnull JSSuperExpression superExpression) { + visitJSExpression(superExpression); + } + + public void visitJSIncludeDirective(@Nonnull JSIncludeDirective includeDirective) { + visitJSStatement(includeDirective); + } + + public void visitJSAttribute(@Nonnull JSAttribute jsAttribute) { + visitJSElement(jsAttribute); + } + + public void visitJSAttributeNameValuePair(@Nonnull JSAttributeNameValuePair attributeNameValuePair) { + } + + public void visitJSYieldStatement(@Nonnull JSYieldStatement statement) { + visitJSStatement(statement); + } + + public void visitJSLetStatement(@Nonnull JSLetStatement statement) { + visitJSStatement(statement); + } + + public void visitJSLetExpression(@Nonnull JSLetExpression expression) { + visitJSExpression(expression); + } + + public void visitJSGenericSignature(@Nonnull JSGenericSignature signature) { + visitJSElement(signature); + } + + public void visitJSDocTagValue(@Nonnull JSDocTagValue tagValue) { + visitJSElement(tagValue); + } + + public void visitJSDocTag(@Nonnull JSDocTag docTag) { + visitJSElement(docTag); + } + + public void visitJSDocComment(@Nonnull JSDocComment docComment) { + visitComment(docComment); + } + + public void visitLambdaExpression(@Nonnull JavaScriptLambdaExpression expression) { + visitJSExpression(expression); + } } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSEmptyStatement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSEmptyStatement.java index 000e3a3e..0c0a57f9 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSEmptyStatement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSEmptyStatement.java @@ -17,12 +17,8 @@ package com.intellij.lang.javascript.psi; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 6:56:36 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSEmptyStatement extends JSStatement -{ +public interface JSEmptyStatement extends JSStatement { } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSExpression.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSExpression.java index b327d842..717fdbf0 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSExpression.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSExpression.java @@ -20,22 +20,21 @@ import consulo.annotation.access.RequiredReadAction; import consulo.javascript.language.psi.JavaScriptType; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author max - * @since 6:46:19 PM Jan 30, 2005 + * @since 2005-01-30 */ -public interface JSExpression extends JSElement -{ - JSExpression[] EMPTY_ARRAY = new JSExpression[0]; +public interface JSExpression extends JSElement { + JSExpression[] EMPTY_ARRAY = new JSExpression[0]; - ArrayFactory ARRAY_FACTORY = count -> count == 0 ? EMPTY_ARRAY : new JSExpression[count]; + ArrayFactory ARRAY_FACTORY = count -> count == 0 ? EMPTY_ARRAY : new JSExpression[count]; - @Nonnull - JSExpression replace(JSExpression other); + @Nonnull + JSExpression replace(JSExpression other); - @Nonnull - @RequiredReadAction - JavaScriptType getType(); + @Nonnull + @RequiredReadAction + JavaScriptType getType(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSExpressionCodeFragment.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSExpressionCodeFragment.java index 4fdff8fe..2802a77e 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSExpressionCodeFragment.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSExpressionCodeFragment.java @@ -19,6 +19,5 @@ /** * @author nik */ -public interface JSExpressionCodeFragment extends JSFile -{ +public interface JSExpressionCodeFragment extends JSFile { } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSExpressionStatement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSExpressionStatement.java index 742869aa..2fd6b943 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSExpressionStatement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSExpressionStatement.java @@ -17,17 +17,14 @@ package com.intellij.lang.javascript.psi; import consulo.annotation.access.RequiredReadAction; - -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; /** - * User: max - * Date: Jan 30, 2005 - * Time: 9:27:17 PM + * @author max + * @since 2005-01-30 */ -public interface JSExpressionStatement extends JSStatement -{ - @Nullable - @RequiredReadAction - JSExpression getExpression(); +public interface JSExpressionStatement extends JSStatement { + @Nullable + @RequiredReadAction + JSExpression getExpression(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSFile.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSFile.java index 90322d0f..eade95fd 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSFile.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSFile.java @@ -22,9 +22,8 @@ /** * @author nik */ -public interface JSFile extends PsiFile, JSElement -{ - StubBasedPsiElement findStubbedElementAtOffset(final int offset, final Class clazz); +public interface JSFile extends PsiFile, JSElement { + StubBasedPsiElement findStubbedElementAtOffset(int offset, Class clazz); - JSSourceElement[] getStatements(); + JSSourceElement[] getStatements(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSForInStatement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSForInStatement.java index d63cc70d..dc6085fc 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSForInStatement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSForInStatement.java @@ -16,20 +16,20 @@ package com.intellij.lang.javascript.psi; +import consulo.annotation.access.RequiredReadAction; + /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 7:20:55 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSForInStatement extends JSLoopStatement -{ - JSVarStatement getDeclarationStatement(); +public interface JSForInStatement extends JSLoopStatement { + JSVarStatement getDeclarationStatement(); - JSExpression getVariableExpression(); + @RequiredReadAction + JSExpression getVariableExpression(); - JSExpression getCollectionExpression(); + @RequiredReadAction + JSExpression getCollectionExpression(); - boolean isForEach(); + boolean isForEach(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSForStatement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSForStatement.java index 3417572c..65b3ac36 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSForStatement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSForStatement.java @@ -16,20 +16,22 @@ package com.intellij.lang.javascript.psi; +import consulo.annotation.access.RequiredReadAction; + /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 7:21:49 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSForStatement extends JSLoopStatement -{ - JSVarStatement getVarDeclaration(); +public interface JSForStatement extends JSLoopStatement { + @RequiredReadAction + JSVarStatement getVarDeclaration(); - JSExpression getInitialization(); + @RequiredReadAction + JSExpression getInitialization(); - JSExpression getCondition(); + @RequiredReadAction + JSExpression getCondition(); - JSExpression getUpdate(); + @RequiredReadAction + JSExpression getUpdate(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSFunction.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSFunction.java index efc6ae17..a12519e9 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSFunction.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSFunction.java @@ -21,82 +21,73 @@ import consulo.javascript.language.psi.JavaScriptTypeElement; import consulo.util.collection.ArrayFactory; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author max */ -public interface JSFunction extends JSQualifiedNamedElement, JSSourceElement, JSAttributeListOwner -{ - public static final JSFunction[] EMPTY_ARRAY = new JSFunction[0]; - - public static ArrayFactory ARRAY_FACTORY = count -> count == 0 ? EMPTY_ARRAY : new JSFunction[count]; - - @Nullable - @RequiredReadAction - JSParameterList getParameterList(); - - JSSourceElement[] getBody(); - - @RequiredReadAction - default boolean isGetProperty() - { - return false; - } - - @RequiredReadAction - default boolean isSetProperty() - { - return false; - } - - @RequiredReadAction - default boolean isConstructor() - { - return false; - } - - @Nonnull - JavaScriptType getReturnType(); - - String getReturnTypeString(); - - @Nullable - JavaScriptTypeElement getReturnTypeElement(); - - enum FunctionKind - { - GETTER, - SETTER, - CONSTRUCTOR, - SIMPLE - } - - @Nonnull - @RequiredReadAction - default FunctionKind getKind() - { - if(isGetProperty()) - { - return FunctionKind.GETTER; - } - if(isSetProperty()) - { - return FunctionKind.SETTER; - } - if(isConstructor()) - { - return FunctionKind.CONSTRUCTOR; - } - return FunctionKind.SIMPLE; - } - - - boolean isDeprecated(); - - default boolean isReferencesArguments() - { - return false; - } +public interface JSFunction extends JSQualifiedNamedElement, JSSourceElement, JSAttributeListOwner { + JSFunction[] EMPTY_ARRAY = new JSFunction[0]; + + ArrayFactory ARRAY_FACTORY = count -> count == 0 ? EMPTY_ARRAY : new JSFunction[count]; + + @Nullable + @RequiredReadAction + JSParameterList getParameterList(); + + @RequiredReadAction + JSSourceElement[] getBody(); + + @RequiredReadAction + default boolean isGetProperty() { + return false; + } + + @RequiredReadAction + default boolean isSetProperty() { + return false; + } + + @RequiredReadAction + default boolean isConstructor() { + return false; + } + + @Nonnull + JavaScriptType getReturnType(); + + String getReturnTypeString(); + + @Nullable + JavaScriptTypeElement getReturnTypeElement(); + + enum FunctionKind { + GETTER, + SETTER, + CONSTRUCTOR, + SIMPLE + } + + @Nonnull + @RequiredReadAction + default FunctionKind getKind() { + if (isGetProperty()) { + return FunctionKind.GETTER; + } + if (isSetProperty()) { + return FunctionKind.SETTER; + } + if (isConstructor()) { + return FunctionKind.CONSTRUCTOR; + } + return FunctionKind.SIMPLE; + } + + + boolean isDeprecated(); + + default boolean isReferencesArguments() { + return false; + } } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSFunctionExpression.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSFunctionExpression.java index 642cb1e6..8d6bc703 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSFunctionExpression.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSFunctionExpression.java @@ -16,17 +16,15 @@ package com.intellij.lang.javascript.psi; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author max - * @since 7:42:48 PM Jan 30, 2005 + * @since 2005-01-30 */ -public interface JSFunctionExpression extends JSFunction, JSExpression -{ - @Nonnull - default JSFunction getFunction() - { - return this; - } +public interface JSFunctionExpression extends JSFunction, JSExpression { + @Nonnull + default JSFunction getFunction() { + return this; + } } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSFunctionProperty.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSFunctionProperty.java index b5dee996..e58eb63c 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSFunctionProperty.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSFunctionProperty.java @@ -2,8 +2,7 @@ /** * @author VISTALL - * @since 19/12/2021 + * @since 2021-12-19 */ -public interface JSFunctionProperty extends JSProperty, JSFunction -{ +public interface JSFunctionProperty extends JSProperty, JSFunction { } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSGenericSignature.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSGenericSignature.java index 715a57cd..617f0b6e 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSGenericSignature.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSGenericSignature.java @@ -17,8 +17,7 @@ package com.intellij.lang.javascript.psi; /** - * @by Maxim.Mossienko + * @author Maxim.Mossienko */ -public interface JSGenericSignature extends JSElement -{ +public interface JSGenericSignature extends JSElement { } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSIfStatement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSIfStatement.java index c3dd31d1..7f797b5a 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSIfStatement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSIfStatement.java @@ -16,24 +16,23 @@ package com.intellij.lang.javascript.psi; +import consulo.annotation.access.RequiredReadAction; + /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 6:56:53 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSIfStatement extends JSStatement -{ - JSExpression getCondition(); +public interface JSIfStatement extends JSStatement { + JSExpression getCondition(); - JSStatement getThen(); + JSStatement getThen(); - JSStatement getElse(); + @RequiredReadAction + JSStatement getElse(); - void setThen(JSStatement statement); + void setThen(JSStatement statement); - void setElse(JSStatement statement); + void setElse(JSStatement statement); - void setCondition(JSExpression expr); + void setCondition(JSExpression expr); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSImportStatement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSImportStatement.java index c72e83f5..41886a1b 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSImportStatement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSImportStatement.java @@ -18,17 +18,18 @@ import com.intellij.lang.javascript.psi.stubs.JSImportStatementStub; import consulo.annotation.DeprecationInfo; +import consulo.annotation.access.RequiredReadAction; import consulo.javascript.psi.JavaScriptImportStatementBase; import consulo.language.psi.StubBasedPsiElement; /** - * @by Maxim.Mossienko - * * EcmaScript 4 implementation + * + * @author Maxim.Mossienko */ @Deprecated -@DeprecationInfo("We need rename it") -public interface JSImportStatement extends JSStatement, StubBasedPsiElement, JavaScriptImportStatementBase -{ - String getImportText(); +@DeprecationInfo("We need to rename it") +public interface JSImportStatement extends JSStatement, StubBasedPsiElement, JavaScriptImportStatementBase { + @RequiredReadAction + String getImportText(); } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSIncludeDirective.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSIncludeDirective.java index ac89c7b5..a11c9112 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSIncludeDirective.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSIncludeDirective.java @@ -17,15 +17,17 @@ package com.intellij.lang.javascript.psi; import com.intellij.lang.javascript.psi.stubs.JSIncludeDirectiveStub; +import consulo.annotation.access.RequiredReadAction; import consulo.language.psi.PsiFile; import consulo.language.psi.StubBasedPsiElement; /** - * @by Maxim.Mossienko + * @author Maxim.Mossienko */ -public interface JSIncludeDirective extends JSStatement, StubBasedPsiElement -{ - String getIncludeText(); +public interface JSIncludeDirective extends JSStatement, StubBasedPsiElement { + @RequiredReadAction + String getIncludeText(); - PsiFile resolveFile(); + @RequiredReadAction + PsiFile resolveFile(); } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSIndexedPropertyAccessExpression.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSIndexedPropertyAccessExpression.java index 1e347eb4..a560c161 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSIndexedPropertyAccessExpression.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSIndexedPropertyAccessExpression.java @@ -16,16 +16,16 @@ package com.intellij.lang.javascript.psi; +import consulo.annotation.access.RequiredReadAction; + /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 7:45:31 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSIndexedPropertyAccessExpression extends JSExpression -{ - JSExpression getQualifier(); +public interface JSIndexedPropertyAccessExpression extends JSExpression { + @RequiredReadAction + JSExpression getQualifier(); - JSExpression getIndexExpression(); + @RequiredReadAction + JSExpression getIndexExpression(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSLabeledStatement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSLabeledStatement.java index 366347cf..1820b3e8 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSLabeledStatement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSLabeledStatement.java @@ -16,26 +16,25 @@ package com.intellij.lang.javascript.psi; +import consulo.annotation.access.RequiredReadAction; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiNameIdentifierOwner; import consulo.annotation.DeprecationInfo; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 6:52:43 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSLabeledStatement extends JSStatement, PsiNameIdentifierOwner -{ - String getLabel(); +public interface JSLabeledStatement extends JSStatement, PsiNameIdentifierOwner { + @RequiredReadAction + String getLabel(); - @Deprecated - @DeprecationInfo("Use #getNameIdentifier()") - PsiElement getLabelIdentifier(); + @Deprecated + @DeprecationInfo("Use #getNameIdentifier()") + @RequiredReadAction + PsiElement getLabelIdentifier(); - JSStatement getStatement(); + JSStatement getStatement(); - JSStatement unlabel(); + JSStatement unlabel(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSLetExpression.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSLetExpression.java index 0cf12dbe..355fee29 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSLetExpression.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSLetExpression.java @@ -17,13 +17,9 @@ package com.intellij.lang.javascript.psi; /** - * Created by IntelliJ IDEA. - * User: maxim.mossienko - * Date: Dec 14, 2005 - * Time: 6:37:59 PM - * To change this template use File | Settings | File Templates. + * @author maxim.mossienko + * @since 2005-12-14 */ -public interface JSLetExpression extends JSExpression -{ - JSExpression getExpression(); +public interface JSLetExpression extends JSExpression { + JSExpression getExpression(); } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSLetStatement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSLetStatement.java index 4a44a60a..22d73429 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSLetStatement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSLetStatement.java @@ -19,9 +19,8 @@ /** * @author maxim */ -public interface JSLetStatement extends JSStatement -{ - JSExpression[] getExpressions(); +public interface JSLetStatement extends JSStatement { + JSExpression[] getExpressions(); - JSBlockStatement getBody(); + JSBlockStatement getBody(); } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSLiteralExpression.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSLiteralExpression.java index 42e11d5f..d3ecf075 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSLiteralExpression.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSLiteralExpression.java @@ -18,8 +18,7 @@ /** * @author max - * @since 7:29:31 PM Jan 30, 2005 + * @since 2005-01-30 */ -public interface JSLiteralExpression extends JSExpression -{ +public interface JSLiteralExpression extends JSExpression { } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSLoopStatement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSLoopStatement.java index 7906359f..e385e68d 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSLoopStatement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSLoopStatement.java @@ -16,14 +16,13 @@ package com.intellij.lang.javascript.psi; +import consulo.annotation.access.RequiredReadAction; + /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 7:22:13 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSLoopStatement extends JSStatement -{ - JSStatement getBody(); +public interface JSLoopStatement extends JSStatement { + @RequiredReadAction + JSStatement getBody(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSNamedElement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSNamedElement.java index 177b4a7f..52c050d8 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSNamedElement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSNamedElement.java @@ -23,6 +23,5 @@ /** * @author ven */ -public interface JSNamedElement extends PsiNamedElement, JSElement, NavigationItem, PsiNameIdentifierOwner -{ +public interface JSNamedElement extends PsiNamedElement, JSElement, NavigationItem, PsiNameIdentifierOwner { } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSNamespaceDeclaration.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSNamespaceDeclaration.java index febe96ef..f8bd8cda 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSNamespaceDeclaration.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSNamespaceDeclaration.java @@ -16,18 +16,18 @@ package com.intellij.lang.javascript.psi; -import javax.annotation.Nullable; import com.intellij.lang.javascript.psi.stubs.JSNamespaceDeclarationStub; import consulo.language.psi.StubBasedPsiElement; +import jakarta.annotation.Nullable; /** - * @by Maxim.Mossienko + * @author Maxim.Mossienko */ -public interface JSNamespaceDeclaration extends JSStatement, JSQualifiedNamedElement, JSAttributeListOwner, - StubBasedPsiElement -{ - @Nullable - String getInitialValueString(); +public interface JSNamespaceDeclaration + extends JSStatement, JSQualifiedNamedElement, JSAttributeListOwner, StubBasedPsiElement { - boolean isDeprecated(); + @Nullable + String getInitialValueString(); + + boolean isDeprecated(); } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSNewExpression.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSNewExpression.java index 7d466de8..d2426405 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSNewExpression.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSNewExpression.java @@ -17,12 +17,8 @@ package com.intellij.lang.javascript.psi; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 7:44:26 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSNewExpression extends JSCallExpression -{ +public interface JSNewExpression extends JSCallExpression { } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSObjectLiteralExpression.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSObjectLiteralExpression.java index d51939fe..64dc260e 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSObjectLiteralExpression.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSObjectLiteralExpression.java @@ -17,13 +17,9 @@ package com.intellij.lang.javascript.psi; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 7:38:54 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSObjectLiteralExpression extends JSExpression -{ - JSProperty[] getProperties(); +public interface JSObjectLiteralExpression extends JSExpression { + JSProperty[] getProperties(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSPackageStatement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSPackageStatement.java index 67915d20..c1cd7fe9 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSPackageStatement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSPackageStatement.java @@ -17,14 +17,15 @@ package com.intellij.lang.javascript.psi; import com.intellij.lang.javascript.psi.stubs.JSPackageStatementStub; +import consulo.annotation.access.RequiredWriteAction; import consulo.language.psi.StubBasedPsiElement; /** - * @by Maxim.Mossienko + * @author Maxim.Mossienko */ -public interface JSPackageStatement extends JSStatement, JSQualifiedNamedElement, StubBasedPsiElement -{ - JSSourceElement[] getStatements(); +public interface JSPackageStatement extends JSStatement, JSQualifiedNamedElement, StubBasedPsiElement { + JSSourceElement[] getStatements(); - void setQualifiedName(final String expectedPackageNameFromFile); + @RequiredWriteAction + void setQualifiedName(String expectedPackageNameFromFile); } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSParameter.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSParameter.java index 867f248f..e4551b72 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSParameter.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSParameter.java @@ -19,28 +19,25 @@ import consulo.annotation.access.RequiredReadAction; import consulo.language.psi.PsiElement; import consulo.util.collection.ArrayFactory; - -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; /** - * User: max - * Date: Jan 30, 2005 - * Time: 6:43:02 PM + * @author max + * @since 2005-01-30 */ -public interface JSParameter extends JSVariable -{ - JSParameter[] EMPTY_ARRAY = new JSParameter[0]; +public interface JSParameter extends JSVariable { + JSParameter[] EMPTY_ARRAY = new JSParameter[0]; - ArrayFactory ARRAY_FACTORY = count -> count == 0 ? EMPTY_ARRAY : new JSParameter[count]; + ArrayFactory ARRAY_FACTORY = count -> count == 0 ? EMPTY_ARRAY : new JSParameter[count]; - JSFunction getDeclaringFunction(); + JSFunction getDeclaringFunction(); - @RequiredReadAction - boolean isRest(); + @RequiredReadAction + boolean isRest(); - @Nullable - @RequiredReadAction - PsiElement getRestElement(); + @Nullable + @RequiredReadAction + PsiElement getRestElement(); - boolean isOptional(); + boolean isOptional(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSParameterList.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSParameterList.java index 25b316af..d6ffcb89 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSParameterList.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSParameterList.java @@ -21,10 +21,8 @@ /** * @author max - * Date: Jan 30, 2005 - * Time: 6:42:10 PM + * @since 2005-01-30 */ -public interface JSParameterList extends JSElement, StubBasedPsiElement -{ - JSParameter[] getParameters(); +public interface JSParameterList extends JSElement, StubBasedPsiElement { + JSParameter[] getParameters(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSParenthesizedExpression.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSParenthesizedExpression.java index e9fd5342..44fe2b9d 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSParenthesizedExpression.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSParenthesizedExpression.java @@ -17,13 +17,9 @@ package com.intellij.lang.javascript.psi; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 7:30:30 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSParenthesizedExpression extends JSExpression -{ - JSExpression getInnerExpression(); +public interface JSParenthesizedExpression extends JSExpression { + JSExpression getInnerExpression(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSPostfixExpression.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSPostfixExpression.java index 7ca495e2..324e2090 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSPostfixExpression.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSPostfixExpression.java @@ -16,20 +16,18 @@ package com.intellij.lang.javascript.psi; -import javax.annotation.Nullable; +import consulo.annotation.access.RequiredReadAction; +import jakarta.annotation.Nullable; import consulo.language.ast.IElementType; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 7:41:36 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSPostfixExpression extends JSExpression -{ - @Nullable - JSExpression getExpression(); +public interface JSPostfixExpression extends JSExpression { + @Nullable + JSExpression getExpression(); - IElementType getOperationSign(); + @RequiredReadAction + IElementType getOperationSign(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSPrefixExpression.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSPrefixExpression.java index 16449e30..804f4c98 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSPrefixExpression.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSPrefixExpression.java @@ -16,28 +16,24 @@ package com.intellij.lang.javascript.psi; -import javax.annotation.Nullable; import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.IElementType; import consulo.language.psi.PsiElement; +import jakarta.annotation.Nullable; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 7:41:36 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSPrefixExpression extends JSExpression -{ - @Nullable - JSExpression getExpression(); +public interface JSPrefixExpression extends JSExpression { + @Nullable + JSExpression getExpression(); - @Nullable - @RequiredReadAction - IElementType getOperationSign(); + @Nullable + @RequiredReadAction + IElementType getOperationSign(); - @RequiredReadAction - @Nullable - PsiElement getOperatorElement(); + @Nullable + @RequiredReadAction + PsiElement getOperatorElement(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSProperty.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSProperty.java index 0081bfe1..8a2858c4 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSProperty.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSProperty.java @@ -17,33 +17,32 @@ package com.intellij.lang.javascript.psi; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import consulo.annotation.access.RequiredReadAction; import consulo.javascript.language.psi.JavaScriptType; import consulo.javascript.psi.JSComputedName; import consulo.language.psi.PsiElement; +import jakarta.annotation.Nonnull; /** * @author max - * @since 7:39:29 PM Jan 30, 2005 + * @since 2005-01-30 */ -public interface JSProperty extends JSNamedElement -{ - @Nullable - @RequiredReadAction - JSExpression getValue(); +public interface JSProperty extends JSNamedElement { + @Nullable + @RequiredReadAction + JSExpression getValue(); - @Nullable - @RequiredReadAction - PsiElement getColonElement(); + @Nullable + @RequiredReadAction + PsiElement getColonElement(); - @Nullable - @RequiredReadAction - JSComputedName getComputedName(); + @Nullable + @RequiredReadAction + JSComputedName getComputedName(); - @Nonnull - @RequiredReadAction - JavaScriptType getType(); + @Nonnull + @RequiredReadAction + JavaScriptType getType(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSQualifiedNamedElement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSQualifiedNamedElement.java index 79631775..c58a74a5 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSQualifiedNamedElement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSQualifiedNamedElement.java @@ -16,10 +16,12 @@ package com.intellij.lang.javascript.psi; +import consulo.annotation.access.RequiredReadAction; + /** * @author ven */ -public interface JSQualifiedNamedElement extends JSNamedElement -{ - String getQualifiedName(); +public interface JSQualifiedNamedElement extends JSNamedElement { + @RequiredReadAction + String getQualifiedName(); } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSReferenceExpression.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSReferenceExpression.java index 8915e3ba..0c43a695 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSReferenceExpression.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSReferenceExpression.java @@ -19,22 +19,21 @@ import consulo.language.psi.PsiElement; import consulo.language.psi.PsiPolyVariantReference; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; /** * @author max - * @since 7:26:32 PM Jan 30, 2005 + * @since 2005-01-30 */ -public interface JSReferenceExpression extends JSExpression, PsiPolyVariantReference -{ - @Nullable - JSExpression getQualifier(); +public interface JSReferenceExpression extends JSExpression, PsiPolyVariantReference { + @Nullable + JSExpression getQualifier(); - @Nullable - String getReferencedName(); + @Nullable + String getReferencedName(); - @Nullable - PsiElement getReferenceNameElement(); + @Nullable + PsiElement getReferenceNameElement(); - boolean shouldCheckReferences(); + boolean shouldCheckReferences(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSReferenceList.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSReferenceList.java index 9a904362..765577a4 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSReferenceList.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSReferenceList.java @@ -16,7 +16,7 @@ package com.intellij.lang.javascript.psi; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; import consulo.annotation.access.RequiredReadAction; import com.intellij.lang.javascript.psi.stubs.JSReferenceListStub; @@ -25,17 +25,16 @@ /** * @author Maxim.Mossienko */ -public interface JSReferenceList extends JSElement, StubBasedPsiElement -{ - @RequiredReadAction - @Nonnull - JSReferenceExpression[] getExpressions(); +public interface JSReferenceList extends JSElement, StubBasedPsiElement { + @Nonnull + @RequiredReadAction + JSReferenceExpression[] getExpressions(); - @RequiredReadAction - @Nonnull - String[] getReferenceTexts(); + @Nonnull + @RequiredReadAction + String[] getReferenceTexts(); - @RequiredReadAction - @Nonnull - JSClass[] getReferencedClasses(); + @Nonnull + @RequiredReadAction + JSClass[] getReferencedClasses(); } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSReturnStatement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSReturnStatement.java index 394db5fd..13c306f0 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSReturnStatement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSReturnStatement.java @@ -17,13 +17,9 @@ package com.intellij.lang.javascript.psi; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 7:01:41 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSReturnStatement extends JSStatement -{ - JSExpression getExpression(); +public interface JSReturnStatement extends JSStatement { + JSExpression getExpression(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSSourceElement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSSourceElement.java index e732522b..9cb9d947 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSSourceElement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSSourceElement.java @@ -19,7 +19,6 @@ /** * @author ven */ -public interface JSSourceElement extends JSElement -{ - JSSourceElement[] EMPTY_ARRAY = new JSSourceElement[0]; +public interface JSSourceElement extends JSElement { + JSSourceElement[] EMPTY_ARRAY = new JSSourceElement[0]; } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSSpreadExpression.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSSpreadExpression.java index 9645b902..e704de9f 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSSpreadExpression.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSSpreadExpression.java @@ -4,7 +4,6 @@ * @author VISTALL * @since 2020-01-01 */ -public interface JSSpreadExpression extends JSExpression -{ - JSExpression getInnerExpression(); +public interface JSSpreadExpression extends JSExpression { + JSExpression getInnerExpression(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSStatement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSStatement.java index 032ba45c..21355407 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSStatement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSStatement.java @@ -16,22 +16,22 @@ package com.intellij.lang.javascript.psi; +import consulo.annotation.access.RequiredWriteAction; import consulo.language.util.IncorrectOperationException; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 6:48:51 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSStatement extends JSSourceElement -{ - JSStatement[] EMPTY = new JSStatement[0]; +public interface JSStatement extends JSSourceElement { + JSStatement[] EMPTY = new JSStatement[0]; - JSStatement addStatementBefore(JSStatement toAdd) throws IncorrectOperationException; + @RequiredWriteAction + JSStatement addStatementBefore(JSStatement toAdd) throws IncorrectOperationException; - JSStatement addStatementAfter(JSStatement toAdd) throws IncorrectOperationException; + @RequiredWriteAction + JSStatement addStatementAfter(JSStatement toAdd) throws IncorrectOperationException; - JSStatement replace(JSStatement with); + @RequiredWriteAction + JSStatement replace(JSStatement with); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSSuperExpression.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSSuperExpression.java index e53f6fb4..e7f47e5a 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSSuperExpression.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSSuperExpression.java @@ -17,8 +17,7 @@ package com.intellij.lang.javascript.psi; /** - * @by Maxim.Mossienko + * @author Maxim.Mossienko */ -public interface JSSuperExpression extends JSExpression -{ +public interface JSSuperExpression extends JSExpression { } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSSuppressionHolder.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSSuppressionHolder.java index 1ea1c297..d85b6c03 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSSuppressionHolder.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSSuppressionHolder.java @@ -23,6 +23,5 @@ * * @author yole */ -public interface JSSuppressionHolder extends PsiElement -{ +public interface JSSuppressionHolder extends PsiElement { } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSSwitchStatement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSSwitchStatement.java index d2a9b3a0..68aa4d33 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSSwitchStatement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSSwitchStatement.java @@ -17,15 +17,11 @@ package com.intellij.lang.javascript.psi; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 7:06:18 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSSwitchStatement extends JSStatement -{ - JSExpression getSwitchExpression(); +public interface JSSwitchStatement extends JSStatement { + JSExpression getSwitchExpression(); - JSCaseClause[] getCaseClauses(); + JSCaseClause[] getCaseClauses(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSThisExpression.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSThisExpression.java index a6ac795d..7cae6897 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSThisExpression.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSThisExpression.java @@ -17,12 +17,8 @@ package com.intellij.lang.javascript.psi; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 7:28:55 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSThisExpression extends JSExpression -{ +public interface JSThisExpression extends JSExpression { } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSThrowStatement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSThrowStatement.java index 705859ae..d4dbb1c3 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSThrowStatement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSThrowStatement.java @@ -17,13 +17,9 @@ package com.intellij.lang.javascript.psi; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 7:02:11 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSThrowStatement extends JSStatement -{ - JSExpression getExpression(); +public interface JSThrowStatement extends JSStatement { + JSExpression getExpression(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSTryStatement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSTryStatement.java index cfafa152..d30a4597 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSTryStatement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSTryStatement.java @@ -16,27 +16,28 @@ package com.intellij.lang.javascript.psi; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import consulo.annotation.access.RequiredReadAction; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 7:03:06 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSTryStatement extends JSStatement -{ - JSStatement getStatement(); +public interface JSTryStatement extends JSStatement { + @RequiredReadAction + JSStatement getStatement(); - @Nonnull - JSCatchBlock[] getAllCatchBlocks(); + @Nonnull + @RequiredReadAction + JSCatchBlock[] getAllCatchBlocks(); - @Deprecated - @Nullable - JSCatchBlock getCatchBlock(); + @Deprecated + @Nullable + @RequiredReadAction + JSCatchBlock getCatchBlock(); - @Nullable - JSStatement getFinallyStatement(); + @Nullable + @RequiredReadAction + JSStatement getFinallyStatement(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSUseNamespaceDirective.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSUseNamespaceDirective.java index e8b4d3fe..c63bba9b 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSUseNamespaceDirective.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSUseNamespaceDirective.java @@ -17,12 +17,13 @@ package com.intellij.lang.javascript.psi; import com.intellij.lang.javascript.psi.stubs.JSUseNamespaceDirectiveStub; +import consulo.annotation.access.RequiredReadAction; import consulo.language.psi.StubBasedPsiElement; /** - * @by Maxim.Mossienko + * @author Maxim.Mossienko */ -public interface JSUseNamespaceDirective extends JSStatement, StubBasedPsiElement -{ - String getNamespaceToBeUsed(); +public interface JSUseNamespaceDirective extends JSStatement, StubBasedPsiElement { + @RequiredReadAction + String getNamespaceToBeUsed(); } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSVarStatement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSVarStatement.java index 9959741c..5292b603 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSVarStatement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSVarStatement.java @@ -19,23 +19,19 @@ import com.intellij.lang.javascript.psi.stubs.JSVarStatementStub; import consulo.annotation.access.RequiredReadAction; import consulo.language.psi.StubBasedPsiElement; - -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 6:55:04 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSVarStatement extends JSStatement, StubBasedPsiElement -{ - JSVariable[] getVariables(); +public interface JSVarStatement extends JSStatement, StubBasedPsiElement { + @RequiredReadAction + JSVariable[] getVariables(); - @Nullable - @RequiredReadAction - JSDestructuringElement getDestructuringElement(); + @Nullable + @RequiredReadAction + JSDestructuringElement getDestructuringElement(); - void declareVariable(String name, JSExpression initializer); + void declareVariable(String name, JSExpression initializer); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSVariable.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSVariable.java index 6f26c7ec..e183f311 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSVariable.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSVariable.java @@ -20,43 +20,42 @@ import consulo.javascript.language.psi.JavaScriptType; import consulo.javascript.language.psi.JavaScriptTypeElement; import consulo.language.util.IncorrectOperationException; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; /** * @author max - * Date: Jan 30, 2005 - * Time: 6:43:42 PM + * @since 2005-01-30 */ -public interface JSVariable extends JSQualifiedNamedElement, JSAttributeListOwner -{ - JSVariable[] EMPTY_ARRAY = new JSVariable[0]; +public interface JSVariable extends JSQualifiedNamedElement, JSAttributeListOwner { + JSVariable[] EMPTY_ARRAY = new JSVariable[0]; - boolean hasInitializer(); + boolean hasInitializer(); - @RequiredReadAction - @Nullable - JSExpression getInitializer(); + @RequiredReadAction + @Nullable + JSExpression getInitializer(); - String getInitializerText(); + @RequiredReadAction + String getInitializerText(); - void setInitializer(JSExpression expr) throws IncorrectOperationException; + void setInitializer(JSExpression expr) throws IncorrectOperationException; - @Nonnull - JavaScriptType getType(); + @Nonnull + JavaScriptType getType(); - @Nullable - @Deprecated - String getTypeString(); + @Nullable + @Deprecated + String getTypeString(); - @Nullable - @RequiredReadAction - JavaScriptTypeElement getTypeElement(); + @Nullable + @RequiredReadAction + JavaScriptTypeElement getTypeElement(); - boolean isConst(); + boolean isConst(); - boolean isLocal(); + boolean isLocal(); - boolean isDeprecated(); + boolean isDeprecated(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSWhileStatement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSWhileStatement.java index 358af431..986f7e13 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSWhileStatement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSWhileStatement.java @@ -17,13 +17,9 @@ package com.intellij.lang.javascript.psi; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 7:25:13 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSWhileStatement extends JSLoopStatement -{ - JSExpression getCondition(); +public interface JSWhileStatement extends JSLoopStatement { + JSExpression getCondition(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSWithStatement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSWithStatement.java index fedd0246..a9ed2b3b 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSWithStatement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSWithStatement.java @@ -17,15 +17,11 @@ package com.intellij.lang.javascript.psi; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 7:01:01 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public interface JSWithStatement extends JSStatement -{ - JSExpression getExpression(); +public interface JSWithStatement extends JSStatement { + JSExpression getExpression(); - JSStatement getStatement(); + JSStatement getStatement(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSYieldStatement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSYieldStatement.java index b0f6120b..ae7463a0 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/JSYieldStatement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/JSYieldStatement.java @@ -16,15 +16,13 @@ package com.intellij.lang.javascript.psi; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; /** - * User: max - * Date: Jan 30, 2005 - * Time: 9:27:17 PM + * @author Maxim.Mossienko + * @since 2005-01-30 */ -public interface JSYieldStatement extends JSStatement -{ - @Nullable - JSExpression getExpression(); +public interface JSYieldStatement extends JSStatement { + @Nullable + JSExpression getExpression(); } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSAttributeListStub.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSAttributeListStub.java index 4ce4f77c..67edae06 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSAttributeListStub.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSAttributeListStub.java @@ -21,16 +21,14 @@ /** * @author Maxim.Mossienko - * Date: Mar 25, 2008 - * Time: 4:00:16 PM + * @since 2008-03-25 */ -public interface JSAttributeListStub extends StubElement, JSStubElement -{ - JSAttributeList.AccessType getAccessType(); +public interface JSAttributeListStub extends StubElement, JSStubElement { + JSAttributeList.AccessType getAccessType(); - boolean hasModifier(final JSAttributeList.ModifierType modifier); + boolean hasModifier(JSAttributeList.ModifierType modifier); - String getNamespace(); + String getNamespace(); - int getFlags(); + int getFlags(); } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSAttributeNameValuePairStub.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSAttributeNameValuePairStub.java index ac09849b..18b51cfa 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSAttributeNameValuePairStub.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSAttributeNameValuePairStub.java @@ -16,19 +16,17 @@ package com.intellij.lang.javascript.psi.stubs; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import com.intellij.lang.javascript.psi.JSAttributeNameValuePair; import consulo.language.psi.stub.StubElement; /** * @author Maxim.Mossienko - * Date: Jun 6, 2008 - * Time: 7:52:57 PM + * @since 2008-06-06 */ -public interface JSAttributeNameValuePairStub extends JSStubElement, StubElement -{ - @Nullable - String getValue(); +public interface JSAttributeNameValuePairStub extends JSStubElement, StubElement { + @Nullable + String getValue(); - String getName(); + String getName(); } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSAttributeStub.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSAttributeStub.java index 75ec2498..e757e32c 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSAttributeStub.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSAttributeStub.java @@ -21,9 +21,7 @@ /** * @author Maxim.Mossienko - * Date: Mar 25, 2008 - * Time: 4:00:16 PM + * @since 2008-03-25 */ -public interface JSAttributeStub extends JSStubElement, NamedStub -{ +public interface JSAttributeStub extends JSStubElement, NamedStub { } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSClassStub.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSClassStub.java index 3e439ba3..41c8861b 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSClassStub.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSClassStub.java @@ -20,12 +20,10 @@ /** * @author Maxim.Mossienko - * Date: Mar 25, 2008 - * Time: 4:00:16 PM + * @since 2008-03-25 */ -public interface JSClassStub extends JSStubElement, JSQualifiedStub -{ - boolean isInterface(); +public interface JSClassStub extends JSStubElement, JSQualifiedStub { + boolean isInterface(); - boolean isDeprecated(); + boolean isDeprecated(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSFunctionStub.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSFunctionStub.java index 4d657fd5..52e388c2 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSFunctionStub.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSFunctionStub.java @@ -20,20 +20,18 @@ /** * @author Maxim.Mossienko - * Date: Mar 25, 2008 - * Time: 4:00:16 PM + * @since 2008-03-25 */ -public interface JSFunctionStub extends JSStubElement, JSQualifiedStub -{ - String getReturnTypeString(); +public interface JSFunctionStub extends JSStubElement, JSQualifiedStub { + String getReturnTypeString(); - boolean isGetProperty(); + boolean isGetProperty(); - boolean isSetProperty(); + boolean isSetProperty(); - boolean isConstructor(); + boolean isConstructor(); - boolean isDeprecated(); + boolean isDeprecated(); - boolean isReferencesArguments(); + boolean isReferencesArguments(); } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSImportStatementStub.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSImportStatementStub.java index 0d2b74bf..171f941e 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSImportStatementStub.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSImportStatementStub.java @@ -21,10 +21,8 @@ /** * @author Maxim.Mossienko - * Date: Jun 6, 2008 - * Time: 7:52:44 PM + * @since 2008-06-06 */ -public interface JSImportStatementStub extends JSStubElement, StubElement -{ - String getImportText(); +public interface JSImportStatementStub extends JSStubElement, StubElement { + String getImportText(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSIncludeDirectiveStub.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSIncludeDirectiveStub.java index ec6f07e3..6954fef0 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSIncludeDirectiveStub.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSIncludeDirectiveStub.java @@ -21,10 +21,8 @@ /** * @author Maxim.Mossienko - * Date: Jun 6, 2008 - * Time: 7:52:57 PM + * @since 2008-06-06 */ -public interface JSIncludeDirectiveStub extends JSStubElement, StubElement -{ - String getIncludeText(); +public interface JSIncludeDirectiveStub extends JSStubElement, StubElement { + String getIncludeText(); } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSNamespaceDeclarationStub.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSNamespaceDeclarationStub.java index 0c8fa342..762a22a5 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSNamespaceDeclarationStub.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSNamespaceDeclarationStub.java @@ -20,10 +20,8 @@ /** * @author Maxim.Mossienko - * Date: Jun 6, 2008 - * Time: 7:52:57 PM + * @since 2008-06-06 */ -public interface JSNamespaceDeclarationStub extends JSStubElement, JSQualifiedStub -{ - String getInitialValueString(); +public interface JSNamespaceDeclarationStub extends JSStubElement, JSQualifiedStub { + String getInitialValueString(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSPackageStatementStub.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSPackageStatementStub.java index 8021c5e1..79237ac0 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSPackageStatementStub.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSPackageStatementStub.java @@ -20,9 +20,7 @@ /** * @author Maxim.Mossienko - * Date: Jun 6, 2008 - * Time: 7:52:30 PM + * @since 2008-06-06 */ -public interface JSPackageStatementStub extends JSStubElement, JSQualifiedStub -{ +public interface JSPackageStatementStub extends JSStubElement, JSQualifiedStub { } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSParameterListStub.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSParameterListStub.java index 4558cb2c..50fadd94 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSParameterListStub.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSParameterListStub.java @@ -20,9 +20,7 @@ /** * @author Maxim.Mossienko - * Date: Mar 25, 2008 - * Time: 4:00:16 PM + * @since 2008-03-25 */ -public interface JSParameterListStub extends JSStubElement -{ +public interface JSParameterListStub extends JSStubElement { } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSParameterStub.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSParameterStub.java index 69562997..afb9ed81 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSParameterStub.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSParameterStub.java @@ -20,12 +20,10 @@ /** * @author Maxim.Mossienko - * Date: Mar 25, 2008 - * Time: 4:00:16 PM + * @since 2008-03-25 */ -public interface JSParameterStub extends JSVariableStubBase -{ - boolean isRest(); +public interface JSParameterStub extends JSVariableStubBase { + boolean isRest(); - boolean isOptional(); + boolean isOptional(); } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSQualifiedStub.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSQualifiedStub.java index 7dcc5be5..eb018dab 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSQualifiedStub.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSQualifiedStub.java @@ -21,12 +21,10 @@ /** * @author Maxim.Mossienko - * Date: Jul 30, 2008 - * Time: 9:30:52 PM + * @since 2008-07-30 */ -public interface JSQualifiedStub extends NamedStub, JSStubElement -{ - String getQualifiedName(); +public interface JSQualifiedStub extends NamedStub, JSStubElement { + String getQualifiedName(); - int getFlags(); + int getFlags(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSReferenceListStub.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSReferenceListStub.java index a281cc83..83973abd 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSReferenceListStub.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSReferenceListStub.java @@ -21,10 +21,8 @@ /** * @author Maxim.Mossienko - * Date: Jun 6, 2008 - * Time: 7:52:51 PM + * @since 2008-06-06 */ -public interface JSReferenceListStub extends JSStubElement, StubElement -{ - String[] getReferenceTexts(); +public interface JSReferenceListStub extends JSStubElement, StubElement { + String[] getReferenceTexts(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSStubElement.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSStubElement.java index 6ca330de..5b2b9f90 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSStubElement.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSStubElement.java @@ -21,10 +21,7 @@ /** * @author Maxim.Mossienko - * Date: Mar 26, 2008 - * Time: 9:39:31 PM + * @since 2008-03-26 */ -public interface JSStubElement extends StubElement -{ - +public interface JSStubElement extends StubElement { } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSUseNamespaceDirectiveStub.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSUseNamespaceDirectiveStub.java index 99714fcb..25c4327b 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSUseNamespaceDirectiveStub.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSUseNamespaceDirectiveStub.java @@ -21,10 +21,8 @@ /** * @author Maxim.Mossienko - * Date: Jun 6, 2008 - * Time: 7:52:51 PM + * @since 2008-06-06 */ -public interface JSUseNamespaceDirectiveStub extends JSStubElement, StubElement -{ - String getNamespaceToUse(); +public interface JSUseNamespaceDirectiveStub extends JSStubElement, StubElement { + String getNamespaceToUse(); } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSVarStatementStub.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSVarStatementStub.java index d9caa2bf..bc5d729a 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSVarStatementStub.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSVarStatementStub.java @@ -20,9 +20,7 @@ /** * @author Maxim.Mossienko - * Date: Jun 8, 2008 - * Time: 1:51:29 PM + * @since 2008-06-08 */ -public interface JSVarStatementStub extends JSStubElement -{ +public interface JSVarStatementStub extends JSStubElement { } diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSVariableStub.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSVariableStub.java index 1d562726..ff736696 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSVariableStub.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSVariableStub.java @@ -20,9 +20,7 @@ /** * @author Maxim.Mossienko - * Date: Mar 25, 2008 - * Time: 4:00:16 PM + * @since 2008-03-25 */ -public interface JSVariableStub extends JSVariableStubBase -{ +public interface JSVariableStub extends JSVariableStubBase { } \ No newline at end of file diff --git a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSVariableStubBase.java b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSVariableStubBase.java index d23181a3..552c705a 100644 --- a/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSVariableStubBase.java +++ b/base-api/src/main/java/com/intellij/lang/javascript/psi/stubs/JSVariableStubBase.java @@ -20,18 +20,16 @@ /** * @author Maxim.Mossienko - * Date: Mar 25, 2008 - * Time: 4:00:16 PM + * @since 2008-03-25 */ -public interface JSVariableStubBase extends JSQualifiedStub, JSStubElement -{ - String getTypeString(); +public interface JSVariableStubBase extends JSQualifiedStub, JSStubElement { + String getTypeString(); - boolean isDeprecated(); + boolean isDeprecated(); - boolean isConst(); + boolean isConst(); - String getInitializerText(); + String getInitializerText(); - boolean isLocal(); + boolean isLocal(); } \ No newline at end of file diff --git a/base-api/src/main/java/consulo/javascript/ide/completion/JavaScriptKeywordCompletionExtender.java b/base-api/src/main/java/consulo/javascript/ide/completion/JavaScriptKeywordCompletionExtender.java index 550f83a7..8425e016 100644 --- a/base-api/src/main/java/consulo/javascript/ide/completion/JavaScriptKeywordCompletionExtender.java +++ b/base-api/src/main/java/consulo/javascript/ide/completion/JavaScriptKeywordCompletionExtender.java @@ -7,16 +7,15 @@ import consulo.language.editor.completion.CompletionResultSet; import consulo.language.util.ProcessingContext; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 2019-12-17 */ @ExtensionAPI(ComponentScope.APPLICATION) -public interface JavaScriptKeywordCompletionExtender -{ - ExtensionPointName EP_NAME = ExtensionPointName.create(JavaScriptKeywordCompletionExtender.class); +public interface JavaScriptKeywordCompletionExtender { + ExtensionPointName EP_NAME = ExtensionPointName.create(JavaScriptKeywordCompletionExtender.class); - void fillCompletion(@Nonnull CompletionParameters parameters, ProcessingContext context, @Nonnull CompletionResultSet result); + void fillCompletion(@Nonnull CompletionParameters parameters, ProcessingContext context, @Nonnull CompletionResultSet result); } diff --git a/base-api/src/main/java/consulo/javascript/index/JavaScriptIndexer.java b/base-api/src/main/java/consulo/javascript/index/JavaScriptIndexer.java index cd99bccb..cfbae972 100644 --- a/base-api/src/main/java/consulo/javascript/index/JavaScriptIndexer.java +++ b/base-api/src/main/java/consulo/javascript/index/JavaScriptIndexer.java @@ -5,23 +5,20 @@ import consulo.component.extension.ExtensionPointName; import consulo.javascript.psi.stubs.JSFileStub; import consulo.language.psi.stub.IndexSink; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; /** * @author VISTALL - * @since 19.07.2015 + * @since 2015-07-19 */ @ExtensionAPI(ComponentScope.APPLICATION) -public abstract class JavaScriptIndexer -{ - public static final ExtensionPointName EP_NAME = ExtensionPointName.create(JavaScriptIndexer.class); +public abstract class JavaScriptIndexer { + public static final ExtensionPointName EP_NAME = ExtensionPointName.create(JavaScriptIndexer.class); - public void indexFile(@Nonnull JSFileStub fileStub, @Nonnull final IndexSink sink) - { - } + public void indexFile(@Nonnull JSFileStub fileStub, @Nonnull IndexSink sink) { + } - public int getVersion() - { - return 0; - } + public int getVersion() { + return 0; + } } diff --git a/base-api/src/main/java/consulo/javascript/internal/DefaultJavaScriptVersion.java b/base-api/src/main/java/consulo/javascript/internal/DefaultJavaScriptVersion.java new file mode 100644 index 00000000..f970121f --- /dev/null +++ b/base-api/src/main/java/consulo/javascript/internal/DefaultJavaScriptVersion.java @@ -0,0 +1,10 @@ +package consulo.javascript.internal; + +/** + * Marker for default javascript file version if not selected + * + * @author VISTALL + * @since 2023-08-31 + */ +public interface DefaultJavaScriptVersion { +} diff --git a/base-api/src/main/java/consulo/javascript/language/JavaScriptBundle.java b/base-api/src/main/java/consulo/javascript/language/JavaScriptBundle.java deleted file mode 100644 index f2196d68..00000000 --- a/base-api/src/main/java/consulo/javascript/language/JavaScriptBundle.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2000-2005 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 consulo.javascript.language; - -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.PropertyKey; -import consulo.component.util.localize.AbstractBundle; - -public class JavaScriptBundle extends AbstractBundle -{ - @NonNls - public static final String BUNDLE = "messages.JavaScriptBundle"; - - private static final JavaScriptBundle ourInstance = new JavaScriptBundle(); - - private JavaScriptBundle() - { - super(BUNDLE); - } - - public static String message(@PropertyKey(resourceBundle = BUNDLE) String key) - { - return ourInstance.getMessage(key); - } - - public static String message(@PropertyKey(resourceBundle = BUNDLE) String key, Object... params) - { - return ourInstance.getMessage(key, params); - } -} diff --git a/base-api/src/main/java/consulo/javascript/language/JavaScriptConstants.java b/base-api/src/main/java/consulo/javascript/language/JavaScriptConstants.java index 2362dcdb..5df5c68b 100644 --- a/base-api/src/main/java/consulo/javascript/language/JavaScriptConstants.java +++ b/base-api/src/main/java/consulo/javascript/language/JavaScriptConstants.java @@ -2,9 +2,8 @@ /** * @author VISTALL - * @since 15.02.2016 + * @since 2016-02-15 */ -public interface JavaScriptConstants -{ - String USE_STRICT = "use strict"; +public interface JavaScriptConstants { + String USE_STRICT = "use strict"; } diff --git a/base-api/src/main/java/consulo/javascript/language/JavaScriptFeature.java b/base-api/src/main/java/consulo/javascript/language/JavaScriptFeature.java index d731ae7e..439be46b 100644 --- a/base-api/src/main/java/consulo/javascript/language/JavaScriptFeature.java +++ b/base-api/src/main/java/consulo/javascript/language/JavaScriptFeature.java @@ -16,34 +16,31 @@ package consulo.javascript.language; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL - * @since 23.02.2016 + * @since 2016-02-23 */ -public enum JavaScriptFeature -{ - CLASS("Classes"), - OCTAL_LITERAL("Octal literals"), - BINARY_LITERAL("Binary literals"), - PARAMETER_DEFAULT_VALUE("Default parameter values"), - REST_PARAMETER("Rest parameters"), - SPREAD_OPERATOR("Spread operator"), - OPTIONAL_CHAINING_OPERATOR("Optional chaining operator"), - FUNCTION_PROPERTY("Function property"), - EXPONENTIATION_OPERATOR("Exponentiation operator"); +public enum JavaScriptFeature { + CLASS("Classes"), + OCTAL_LITERAL("Octal literals"), + BINARY_LITERAL("Binary literals"), + PARAMETER_DEFAULT_VALUE("Default parameter values"), + REST_PARAMETER("Rest parameters"), + SPREAD_OPERATOR("Spread operator"), + OPTIONAL_CHAINING_OPERATOR("Optional chaining operator"), + FUNCTION_PROPERTY("Function property"), + EXPONENTIATION_OPERATOR("Exponentiation operator"); - private String myName; + private String myName; - JavaScriptFeature(String name) - { - myName = name; - } + JavaScriptFeature(String name) { + myName = name; + } - @Nonnull - public String getName() - { - return myName; - } + @Nonnull + public String getName() { + return myName; + } } diff --git a/base-api/src/main/java/consulo/javascript/language/JavaScriptFileType.java b/base-api/src/main/java/consulo/javascript/language/JavaScriptFileType.java index af2fa996..0f1ca167 100644 --- a/base-api/src/main/java/consulo/javascript/language/JavaScriptFileType.java +++ b/base-api/src/main/java/consulo/javascript/language/JavaScriptFileType.java @@ -28,65 +28,56 @@ import consulo.ui.image.Image; import consulo.virtualFileSystem.VirtualFile; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** - * User: max - * Date: Jan 27, 2005 - * Time: 6:02:59 PM + * @author max + * @since 2005-01-27 */ -public class JavaScriptFileType extends LanguageFileType implements JavaScriptFileTypeWithVersion -{ - public static final JavaScriptFileType INSTANCE = new JavaScriptFileType(); +public class JavaScriptFileType extends LanguageFileType implements JavaScriptFileTypeWithVersion { + public static final JavaScriptFileType INSTANCE = new JavaScriptFileType(); - public JavaScriptFileType() - { - super(JavaScriptLanguage.INSTANCE); - } + public JavaScriptFileType() { + super(JavaScriptLanguage.INSTANCE); + } - @Override - @Nonnull - public String getId() - { - return "JavaScript"; - } + @Override + @Nonnull + public String getId() { + return "JavaScript"; + } - @Override - @Nonnull - public LocalizeValue getDescription() - { - return JavaScriptLocalize.javascriptFiletypeDescription(); - } + @Override + @Nonnull + public LocalizeValue getDescription() { + return JavaScriptLocalize.javascriptFiletypeDescription(); + } - @Override - @Nonnull - public String getDefaultExtension() - { - return "js"; - } + @Override + @Nonnull + public String getDefaultExtension() { + return "js"; + } - @Override - public Image getIcon() - { - return JavaScriptIconGroup.javascript(); - } + @Nonnull + @Override + public Image getIcon() { + return JavaScriptIconGroup.javascript(); + } - @RequiredReadAction - @Nonnull - @Override - public LanguageVersion getLanguageVersion(@Nullable Module module, @Nullable VirtualFile virtualFile) - { - if(module == null) - { - return StandardJavaScriptVersions.getInstance().getDefaultVersion(); - } + @Nonnull + @Override + @RequiredReadAction + public LanguageVersion getLanguageVersion(@Nullable Module module, @Nullable VirtualFile virtualFile) { + if (module == null) { + return StandardJavaScriptVersions.getInstance().getDefaultVersion(); + } - JavaScriptModuleExtension extension = ModuleUtilCore.getExtension(module, JavaScriptModuleExtension.class); - if(extension != null) - { - return extension.getLanguageVersion(); - } - return StandardJavaScriptVersions.getInstance().getDefaultVersion(); - } + JavaScriptModuleExtension extension = ModuleUtilCore.getExtension(module, JavaScriptModuleExtension.class); + if (extension != null) { + return extension.getLanguageVersion(); + } + return StandardJavaScriptVersions.getInstance().getDefaultVersion(); + } } diff --git a/base-api/src/main/java/consulo/javascript/language/JavaScriptFileTypeWithVersion.java b/base-api/src/main/java/consulo/javascript/language/JavaScriptFileTypeWithVersion.java index 69966243..e6a74307 100644 --- a/base-api/src/main/java/consulo/javascript/language/JavaScriptFileTypeWithVersion.java +++ b/base-api/src/main/java/consulo/javascript/language/JavaScriptFileTypeWithVersion.java @@ -21,16 +21,15 @@ import consulo.module.Module; import consulo.virtualFileSystem.VirtualFile; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL - * @since 11.12.2015 + * @since 2015-12-11 */ -public interface JavaScriptFileTypeWithVersion -{ - @Nonnull - @RequiredReadAction - LanguageVersion getLanguageVersion(@Nullable Module module, @Nullable VirtualFile virtualFile); +public interface JavaScriptFileTypeWithVersion { + @Nonnull + @RequiredReadAction + LanguageVersion getLanguageVersion(@Nullable Module module, @Nullable VirtualFile virtualFile); } diff --git a/base-api/src/main/java/consulo/javascript/language/JavaScriptLanguage.java b/base-api/src/main/java/consulo/javascript/language/JavaScriptLanguage.java index 361f758b..bb073bb0 100644 --- a/base-api/src/main/java/consulo/javascript/language/JavaScriptLanguage.java +++ b/base-api/src/main/java/consulo/javascript/language/JavaScriptLanguage.java @@ -16,60 +16,61 @@ package consulo.javascript.language; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.Language; import consulo.language.file.LanguageFileType; import consulo.language.version.LanguageVersion; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.HashMap; import java.util.Map; /** * @author VISTALL - * @since 05.12.2015 + * @since 2015-12-05 */ -public class JavaScriptLanguage extends Language -{ - public static final JavaScriptLanguage INSTANCE = new JavaScriptLanguage(); +public class JavaScriptLanguage extends Language { + public static final JavaScriptLanguage INSTANCE = new JavaScriptLanguage(); - private Map myVersionsById = new HashMap<>(); + private Map myVersionsById = new HashMap<>(); - public JavaScriptLanguage() - { - super("JavaScript", "text/javascript", "application/javascript"); - } + public JavaScriptLanguage() { + super("JavaScript", "text/javascript", "application/javascript"); + } - @Nullable - public LanguageVersion getVersionById(@Nonnull String id) - { - Map oldMap = myVersionsById; - if(oldMap == null) - { - Map newMap = new HashMap<>(); - for(LanguageVersion version : getVersions()) - { - newMap.put(version.getId(), version); - } + @Nullable + public LanguageVersion getVersionById(@Nonnull String id) { + Map oldMap = myVersionsById; + if (oldMap == null) { + Map newMap = new HashMap<>(); + for (LanguageVersion version : getVersions()) { + newMap.put(version.getId(), version); + } - myVersionsById = newMap; + myVersionsById = newMap; - return newMap.get(id); - } + return newMap.get(id); + } - return oldMap.get(id); - } + return oldMap.get(id); + } - @Nullable - @Override - public LanguageFileType getAssociatedFileType() - { - return JavaScriptFileType.INSTANCE; - } + @Nonnull + @Override + public LocalizeValue getDisplayName() { + return JavaScriptLocalize.javascriptName(); + } - @Override - public boolean isCaseSensitive() - { - return true; - } + @Nullable + @Override + public LanguageFileType getAssociatedFileType() { + return JavaScriptFileType.INSTANCE; + } + + @Override + public boolean isCaseSensitive() { + return true; + } } diff --git a/base-api/src/main/java/consulo/javascript/language/JavaScriptLanguageVersion.java b/base-api/src/main/java/consulo/javascript/language/JavaScriptLanguageVersion.java index 2306826a..ac37a2bd 100644 --- a/base-api/src/main/java/consulo/javascript/language/JavaScriptLanguageVersion.java +++ b/base-api/src/main/java/consulo/javascript/language/JavaScriptLanguageVersion.java @@ -1,30 +1,27 @@ package consulo.javascript.language; -import consulo.javascript.language.JavaScriptFeature; import consulo.language.Language; import consulo.language.version.LanguageVersion; import consulo.language.version.LanguageVersionWithParsing; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; + import java.util.Set; /** * @author VISTALL - * @since 23-Dec-17 + * @since 2017-12-23 */ -public abstract class JavaScriptLanguageVersion extends LanguageVersion implements LanguageVersionWithParsing -{ - public JavaScriptLanguageVersion(@Nonnull String id, @Nonnull String name, @Nonnull Language language, String... mimeTypes) - { - super(id, name, language, mimeTypes); - } +public abstract class JavaScriptLanguageVersion extends LanguageVersion implements LanguageVersionWithParsing { + public JavaScriptLanguageVersion(@Nonnull String id, @Nonnull String name, @Nonnull Language language, String... mimeTypes) { + super(id, name, language, mimeTypes); + } - @Nonnull - public abstract Set getFeatures(); + @Nonnull + public abstract Set getFeatures(); - @Nonnull - public String getPresentableName() - { - return getName(); - } + @Nonnull + public String getPresentableName() { + return getName(); + } } diff --git a/base-api/src/main/java/consulo/javascript/language/JavaScriptVersionUtil.java b/base-api/src/main/java/consulo/javascript/language/JavaScriptVersionUtil.java index 737c24a0..bb09748a 100644 --- a/base-api/src/main/java/consulo/javascript/language/JavaScriptVersionUtil.java +++ b/base-api/src/main/java/consulo/javascript/language/JavaScriptVersionUtil.java @@ -16,27 +16,28 @@ package consulo.javascript.language; +import consulo.annotation.access.RequiredReadAction; import consulo.language.psi.PsiElement; import consulo.language.version.LanguageVersion; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; + import java.util.Collections; import java.util.Set; /** * @author VISTALL - * @since 23.02.2016 + * @since 2016-02-23 */ -public class JavaScriptVersionUtil -{ - public static boolean containsFeature(@Nonnull PsiElement element, @Nonnull JavaScriptFeature feature) - { - return getFeatures(element).contains(feature); - } +public class JavaScriptVersionUtil { + @RequiredReadAction + public static boolean containsFeature(@Nonnull PsiElement element, @Nonnull JavaScriptFeature feature) { + return getFeatures(element).contains(feature); + } - public static Set getFeatures(@Nonnull PsiElement element) - { - LanguageVersion languageVersion = element.getLanguageVersion(); - return languageVersion instanceof JavaScriptLanguageVersion ? ((JavaScriptLanguageVersion) languageVersion).getFeatures() : Collections.emptySet(); - } + @RequiredReadAction + public static Set getFeatures(@Nonnull PsiElement element) { + LanguageVersion languageVersion = element.getLanguageVersion(); + return languageVersion instanceof JavaScriptLanguageVersion ? ((JavaScriptLanguageVersion)languageVersion).getFeatures() : Collections.emptySet(); + } } diff --git a/base-api/src/main/java/consulo/javascript/language/StandardJavaScriptVersion.java b/base-api/src/main/java/consulo/javascript/language/StandardJavaScriptVersion.java new file mode 100644 index 00000000..f1ef0473 --- /dev/null +++ b/base-api/src/main/java/consulo/javascript/language/StandardJavaScriptVersion.java @@ -0,0 +1,14 @@ +package consulo.javascript.language; + +/** + * Marker for javascript version which can be selected inside combobox for module + * + * @author VISTALL + * @since 2023-08-31 + */ +public interface StandardJavaScriptVersion { + @Deprecated + default int getWeight() { + return 0; + } +} diff --git a/base-api/src/main/java/consulo/javascript/language/StandardJavaScriptVersions.java b/base-api/src/main/java/consulo/javascript/language/StandardJavaScriptVersions.java index 14efc045..af7a6ede 100644 --- a/base-api/src/main/java/consulo/javascript/language/StandardJavaScriptVersions.java +++ b/base-api/src/main/java/consulo/javascript/language/StandardJavaScriptVersions.java @@ -20,38 +20,29 @@ import consulo.annotation.component.ServiceAPI; import consulo.ide.ServiceManager; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; + import java.util.List; /** * @author VISTALL - * @since 11.12.2015 + * @since 2015-12-11 */ @ServiceAPI(ComponentScope.APPLICATION) -public abstract class StandardJavaScriptVersions -{ - public static interface Marker - { - @Deprecated - default int getWeight() - { - return 0; - } - } - - @Nonnull - public static StandardJavaScriptVersions getInstance() - { - return ServiceManager.getService(StandardJavaScriptVersions.class); - } - - @Nonnull - public abstract JavaScriptLanguageVersion getDefaultVersion(); - - @Nonnull - public abstract List getValidLanguageVersions(); - - @Nonnull - public abstract JavaScriptLanguageVersion findVersionById(@Nullable String id); +public abstract class StandardJavaScriptVersions { + + @Nonnull + public static StandardJavaScriptVersions getInstance() { + return ServiceManager.getService(StandardJavaScriptVersions.class); + } + + @Nonnull + public abstract JavaScriptLanguageVersion getDefaultVersion(); + + @Nonnull + public abstract List getValidLanguageVersions(); + + @Nonnull + public abstract JavaScriptLanguageVersion findVersionById(@Nullable String id); } diff --git a/base-api/src/main/java/consulo/javascript/language/psi/JavaScriptPrimitiveType.java b/base-api/src/main/java/consulo/javascript/language/psi/JavaScriptPrimitiveType.java index 001cf1d8..046180f9 100644 --- a/base-api/src/main/java/consulo/javascript/language/psi/JavaScriptPrimitiveType.java +++ b/base-api/src/main/java/consulo/javascript/language/psi/JavaScriptPrimitiveType.java @@ -18,47 +18,41 @@ import consulo.annotation.access.RequiredReadAction; import consulo.language.psi.PsiElement; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL - * @since 13.12.2015 + * @since 2015-12-13 */ -public class JavaScriptPrimitiveType implements JavaScriptType -{ - public static final JavaScriptPrimitiveType BOOL = new JavaScriptPrimitiveType("Boolean"); - public static final JavaScriptPrimitiveType STRING = new JavaScriptPrimitiveType("String"); - public static final JavaScriptPrimitiveType NUMBER = new JavaScriptPrimitiveType("Number"); - public static final JavaScriptPrimitiveType REGEXP = new JavaScriptPrimitiveType("Regexp"); - public static final JavaScriptPrimitiveType NULL = new JavaScriptPrimitiveType("null"); - - private String myName; - - public JavaScriptPrimitiveType(String name) - { - myName = name; - } - - @RequiredReadAction - @Nonnull - @Override - public String getPresentableText() - { - return myName; - } - - @Nullable - @Override - public PsiElement getTargetElement() - { - return null; - } - - @Override - public String toString() - { - return "JavaScriptPrimitiveType: " + myName; - } +public class JavaScriptPrimitiveType implements JavaScriptType { + public static final JavaScriptPrimitiveType BOOL = new JavaScriptPrimitiveType("Boolean"); + public static final JavaScriptPrimitiveType STRING = new JavaScriptPrimitiveType("String"); + public static final JavaScriptPrimitiveType NUMBER = new JavaScriptPrimitiveType("Number"); + public static final JavaScriptPrimitiveType REGEXP = new JavaScriptPrimitiveType("Regexp"); + public static final JavaScriptPrimitiveType NULL = new JavaScriptPrimitiveType("null"); + + private String myName; + + public JavaScriptPrimitiveType(String name) { + myName = name; + } + + @Nonnull + @Override + @RequiredReadAction + public String getPresentableText() { + return myName; + } + + @Nullable + @Override + public PsiElement getTargetElement() { + return null; + } + + @Override + public String toString() { + return "JavaScriptPrimitiveType: " + myName; + } } diff --git a/base-api/src/main/java/consulo/javascript/language/psi/JavaScriptType.java b/base-api/src/main/java/consulo/javascript/language/psi/JavaScriptType.java index 874d4897..3b1bc07c 100644 --- a/base-api/src/main/java/consulo/javascript/language/psi/JavaScriptType.java +++ b/base-api/src/main/java/consulo/javascript/language/psi/JavaScriptType.java @@ -18,38 +18,33 @@ import consulo.annotation.access.RequiredReadAction; import consulo.language.psi.PsiElement; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL - * @since 13.12.2015 + * @since 2015-12-13 */ -public interface JavaScriptType -{ - JavaScriptType UNKNOWN = new JavaScriptType() - { - @RequiredReadAction - @Nonnull - @Override - public String getPresentableText() - { - return "?"; - } +public interface JavaScriptType { + JavaScriptType UNKNOWN = new JavaScriptType() { + @Nonnull + @Override + @RequiredReadAction + public String getPresentableText() { + return "?"; + } - @Nullable - @Override - public PsiElement getTargetElement() - { - return null; - } - }; + @Nullable + @Override + public PsiElement getTargetElement() { + return null; + } + }; - @Nonnull - @RequiredReadAction - String getPresentableText(); + @Nonnull + @RequiredReadAction + String getPresentableText(); - @Nullable - PsiElement getTargetElement(); + @Nullable + PsiElement getTargetElement(); } diff --git a/base-api/src/main/java/consulo/javascript/language/psi/JavaScriptTypeElement.java b/base-api/src/main/java/consulo/javascript/language/psi/JavaScriptTypeElement.java index 4a14b3e1..dc7da63f 100644 --- a/base-api/src/main/java/consulo/javascript/language/psi/JavaScriptTypeElement.java +++ b/base-api/src/main/java/consulo/javascript/language/psi/JavaScriptTypeElement.java @@ -16,16 +16,14 @@ package consulo.javascript.language.psi; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; import com.intellij.lang.javascript.psi.JSElement; -import consulo.javascript.language.psi.JavaScriptType; /** * @author VISTALL - * @since 29.02.2016 + * @since 2016-02-29 */ -public interface JavaScriptTypeElement extends JSElement -{ - @Nonnull - JavaScriptType getType(); +public interface JavaScriptTypeElement extends JSElement { + @Nonnull + JavaScriptType getType(); } diff --git a/base-api/src/main/java/consulo/javascript/language/psi/stub/JSImplementedInterfacesIndex.java b/base-api/src/main/java/consulo/javascript/language/psi/stub/JSImplementedInterfacesIndex.java index e28eee01..6bafd932 100644 --- a/base-api/src/main/java/consulo/javascript/language/psi/stub/JSImplementedInterfacesIndex.java +++ b/base-api/src/main/java/consulo/javascript/language/psi/stub/JSImplementedInterfacesIndex.java @@ -21,15 +21,13 @@ import consulo.language.psi.stub.StringStubIndexExtension; import consulo.language.psi.stub.StubIndexKey; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; @ExtensionImpl -public class JSImplementedInterfacesIndex extends StringStubIndexExtension -{ - @Nonnull - @Override - public StubIndexKey getKey() - { - return JavaScriptIndexKeys.IMPLEMENTED_INDEX; - } +public class JSImplementedInterfacesIndex extends StringStubIndexExtension { + @Nonnull + @Override + public StubIndexKey getKey() { + return JavaScriptIndexKeys.IMPLEMENTED_INDEX; + } } \ No newline at end of file diff --git a/base-api/src/main/java/consulo/javascript/language/psi/stub/JSNameIndex.java b/base-api/src/main/java/consulo/javascript/language/psi/stub/JSNameIndex.java index bc1fe0b8..4ae07b1c 100644 --- a/base-api/src/main/java/consulo/javascript/language/psi/stub/JSNameIndex.java +++ b/base-api/src/main/java/consulo/javascript/language/psi/stub/JSNameIndex.java @@ -24,15 +24,13 @@ import consulo.language.psi.stub.StringStubIndexExtension; import consulo.language.psi.stub.StubIndexKey; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; @ExtensionImpl -public class JSNameIndex extends StringStubIndexExtension -{ - @Nonnull - @Override - public StubIndexKey getKey() - { - return JavaScriptIndexKeys.ELEMENTS_BY_NAME; - } +public class JSNameIndex extends StringStubIndexExtension { + @Nonnull + @Override + public StubIndexKey getKey() { + return JavaScriptIndexKeys.ELEMENTS_BY_NAME; + } } \ No newline at end of file diff --git a/base-api/src/main/java/consulo/javascript/language/psi/stub/JSQualifiedElementIndex.java b/base-api/src/main/java/consulo/javascript/language/psi/stub/JSQualifiedElementIndex.java index 8e5b39c3..248c122b 100644 --- a/base-api/src/main/java/consulo/javascript/language/psi/stub/JSQualifiedElementIndex.java +++ b/base-api/src/main/java/consulo/javascript/language/psi/stub/JSQualifiedElementIndex.java @@ -23,16 +23,13 @@ import consulo.annotation.component.ExtensionImpl; import consulo.language.psi.stub.StringStubIndexExtension; import consulo.language.psi.stub.StubIndexKey; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; @ExtensionImpl -public class JSQualifiedElementIndex extends StringStubIndexExtension -{ - @Nonnull - @Override - public StubIndexKey getKey() - { - return JavaScriptIndexKeys.ELEMENTS_BY_QNAME; - } +public class JSQualifiedElementIndex extends StringStubIndexExtension { + @Nonnull + @Override + public StubIndexKey getKey() { + return JavaScriptIndexKeys.ELEMENTS_BY_QNAME; + } } \ No newline at end of file diff --git a/base-api/src/main/java/consulo/javascript/language/psi/stub/JSSuperClassIndex.java b/base-api/src/main/java/consulo/javascript/language/psi/stub/JSSuperClassIndex.java index 560068e4..e8840c49 100644 --- a/base-api/src/main/java/consulo/javascript/language/psi/stub/JSSuperClassIndex.java +++ b/base-api/src/main/java/consulo/javascript/language/psi/stub/JSSuperClassIndex.java @@ -20,16 +20,13 @@ import consulo.annotation.component.ExtensionImpl; import consulo.language.psi.stub.StringStubIndexExtension; import consulo.language.psi.stub.StubIndexKey; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; @ExtensionImpl -public class JSSuperClassIndex extends StringStubIndexExtension -{ - @Nonnull - @Override - public StubIndexKey getKey() - { - return JavaScriptIndexKeys.EXTENDS_INDEX; - } +public class JSSuperClassIndex extends StringStubIndexExtension { + @Nonnull + @Override + public StubIndexKey getKey() { + return JavaScriptIndexKeys.EXTENDS_INDEX; + } } \ No newline at end of file diff --git a/base-api/src/main/java/consulo/javascript/language/psi/stub/JavaScriptIndexKeys.java b/base-api/src/main/java/consulo/javascript/language/psi/stub/JavaScriptIndexKeys.java index 6e77c901..635ddb86 100644 --- a/base-api/src/main/java/consulo/javascript/language/psi/stub/JavaScriptIndexKeys.java +++ b/base-api/src/main/java/consulo/javascript/language/psi/stub/JavaScriptIndexKeys.java @@ -23,14 +23,13 @@ /** * @author VISTALL - * @since 05.12.2015 + * @since 2015-12-05 */ -public interface JavaScriptIndexKeys -{ - StubIndexKey CLASSES_BY_NAME = StubIndexKey.createIndexKey("js.class.shortName"); - StubIndexKey ELEMENTS_BY_NAME = StubIndexKey.createIndexKey("js.qualified.shortName"); - StubIndexKey ELEMENTS_BY_QNAME = StubIndexKey.createIndexKey("js.element.qualifiedName"); +public interface JavaScriptIndexKeys { + StubIndexKey CLASSES_BY_NAME = StubIndexKey.createIndexKey("js.class.shortName"); + StubIndexKey ELEMENTS_BY_NAME = StubIndexKey.createIndexKey("js.qualified.shortName"); + StubIndexKey ELEMENTS_BY_QNAME = StubIndexKey.createIndexKey("js.element.qualifiedName"); - StubIndexKey EXTENDS_INDEX = StubIndexKey.createIndexKey("JS.class.super"); - StubIndexKey IMPLEMENTED_INDEX = StubIndexKey.createIndexKey("JS.class.implements"); + StubIndexKey EXTENDS_INDEX = StubIndexKey.createIndexKey("JS.class.super"); + StubIndexKey IMPLEMENTED_INDEX = StubIndexKey.createIndexKey("JS.class.implements"); } diff --git a/base-api/src/main/java/consulo/javascript/module/extension/JavaScriptModuleExtension.java b/base-api/src/main/java/consulo/javascript/module/extension/JavaScriptModuleExtension.java index c4a9e02c..db766505 100644 --- a/base-api/src/main/java/consulo/javascript/module/extension/JavaScriptModuleExtension.java +++ b/base-api/src/main/java/consulo/javascript/module/extension/JavaScriptModuleExtension.java @@ -2,15 +2,13 @@ import consulo.language.version.LanguageVersion; import consulo.module.extension.ModuleExtensionWithSdk; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL - * @since 29.06.14 + * @since 2014-06-29 */ -public interface JavaScriptModuleExtension> extends ModuleExtensionWithSdk -{ - @Nonnull - LanguageVersion getLanguageVersion(); +public interface JavaScriptModuleExtension> extends ModuleExtensionWithSdk { + @Nonnull + LanguageVersion getLanguageVersion(); } diff --git a/base-api/src/main/java/consulo/javascript/module/extension/JavaScriptMutableModuleExtension.java b/base-api/src/main/java/consulo/javascript/module/extension/JavaScriptMutableModuleExtension.java index 1043a134..752ecbff 100644 --- a/base-api/src/main/java/consulo/javascript/module/extension/JavaScriptMutableModuleExtension.java +++ b/base-api/src/main/java/consulo/javascript/module/extension/JavaScriptMutableModuleExtension.java @@ -18,14 +18,12 @@ import consulo.language.version.LanguageVersion; import consulo.module.extension.MutableModuleExtensionWithSdk; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL - * @since 12.12.2015 + * @since 2015-12-12 */ -public interface JavaScriptMutableModuleExtension> extends JavaScriptModuleExtension, MutableModuleExtensionWithSdk -{ - void setLanguageVersion(@Nonnull LanguageVersion languageVersion); +public interface JavaScriptMutableModuleExtension> extends JavaScriptModuleExtension, MutableModuleExtensionWithSdk { + void setLanguageVersion(@Nonnull LanguageVersion languageVersion); } diff --git a/base-api/src/main/java/consulo/javascript/psi/JSComputedName.java b/base-api/src/main/java/consulo/javascript/psi/JSComputedName.java index cce7278f..c70dde79 100644 --- a/base-api/src/main/java/consulo/javascript/psi/JSComputedName.java +++ b/base-api/src/main/java/consulo/javascript/psi/JSComputedName.java @@ -16,17 +16,16 @@ package consulo.javascript.psi; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import com.intellij.lang.javascript.psi.JSElement; import com.intellij.lang.javascript.psi.JSExpression; /** * @author VISTALL - * @since 03.03.2016 + * @since 2016-03-03 */ -public interface JSComputedName extends JSElement -{ - @Nullable - JSExpression getExpression(); +public interface JSComputedName extends JSElement { + @Nullable + JSExpression getExpression(); } diff --git a/base-api/src/main/java/consulo/javascript/psi/JSSimpleLiteralExpression.java b/base-api/src/main/java/consulo/javascript/psi/JSSimpleLiteralExpression.java index 6027465a..ab5d457f 100644 --- a/base-api/src/main/java/consulo/javascript/psi/JSSimpleLiteralExpression.java +++ b/base-api/src/main/java/consulo/javascript/psi/JSSimpleLiteralExpression.java @@ -20,16 +20,14 @@ import com.intellij.lang.javascript.psi.JSLiteralExpression; import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.IElementType; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL - * @since 11.12.2015 + * @since 2015-12-11 */ -public interface JSSimpleLiteralExpression extends JSLiteralExpression -{ - @Nonnull - @RequiredReadAction - IElementType getLiteralElementType(); +public interface JSSimpleLiteralExpression extends JSLiteralExpression { + @Nonnull + @RequiredReadAction + IElementType getLiteralElementType(); } diff --git a/base-api/src/main/java/consulo/javascript/psi/JavaScriptImportStatementBase.java b/base-api/src/main/java/consulo/javascript/psi/JavaScriptImportStatementBase.java index c777a749..77bdf304 100644 --- a/base-api/src/main/java/consulo/javascript/psi/JavaScriptImportStatementBase.java +++ b/base-api/src/main/java/consulo/javascript/psi/JavaScriptImportStatementBase.java @@ -3,11 +3,10 @@ import com.intellij.lang.javascript.psi.JSStatement; /** + * Base interface for all imports in at js implementation. Affects folding. + * * @author VISTALL * @since 2019-12-14 - * - * Base interface for all imports in at js implementation. Affect folding */ -public interface JavaScriptImportStatementBase extends JSStatement -{ +public interface JavaScriptImportStatementBase extends JSStatement { } diff --git a/base-api/src/main/java/consulo/javascript/psi/JavaScriptLambdaExpression.java b/base-api/src/main/java/consulo/javascript/psi/JavaScriptLambdaExpression.java index ba6e1477..58cfbc2d 100644 --- a/base-api/src/main/java/consulo/javascript/psi/JavaScriptLambdaExpression.java +++ b/base-api/src/main/java/consulo/javascript/psi/JavaScriptLambdaExpression.java @@ -20,8 +20,7 @@ /** * @author VISTALL - * @since 03.03.2016 + * @since 2016-03-03 */ -public interface JavaScriptLambdaExpression extends JSFunctionExpression -{ +public interface JavaScriptLambdaExpression extends JSFunctionExpression { } diff --git a/base-api/src/main/java/consulo/javascript/psi/impl/reference/JSPropertyNameReferenceProvider.java b/base-api/src/main/java/consulo/javascript/psi/impl/reference/JSPropertyNameReferenceProvider.java index 2342e6c3..5fdf53db 100644 --- a/base-api/src/main/java/consulo/javascript/psi/impl/reference/JSPropertyNameReferenceProvider.java +++ b/base-api/src/main/java/consulo/javascript/psi/impl/reference/JSPropertyNameReferenceProvider.java @@ -24,19 +24,18 @@ import consulo.component.extension.ExtensionPointName; import consulo.language.psi.PsiReference; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL - * @since 02.12.2015 + * @since 2015-12-02 */ @ExtensionAPI(ComponentScope.APPLICATION) -public interface JSPropertyNameReferenceProvider -{ - ExtensionPointName EP_NAME = ExtensionPointName.create(JSPropertyNameReferenceProvider.class); +public interface JSPropertyNameReferenceProvider { + ExtensionPointName EP_NAME = ExtensionPointName.create(JSPropertyNameReferenceProvider.class); - @Nullable - @RequiredReadAction - PsiReference getReference(@Nonnull JSProperty property); + @Nullable + @RequiredReadAction + PsiReference getReference(@Nonnull JSProperty property); } diff --git a/base-api/src/main/java/consulo/javascript/psi/stubs/JSFileStub.java b/base-api/src/main/java/consulo/javascript/psi/stubs/JSFileStub.java index cb89a010..59d08d1d 100644 --- a/base-api/src/main/java/consulo/javascript/psi/stubs/JSFileStub.java +++ b/base-api/src/main/java/consulo/javascript/psi/stubs/JSFileStub.java @@ -3,14 +3,13 @@ import com.intellij.lang.javascript.psi.JSFile; import consulo.language.psi.stub.PsiFileStub; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL - * @since 19.07.2015 + * @since 2015-07-19 */ -public interface JSFileStub extends PsiFileStub -{ - @Nonnull - String getName(); +public interface JSFileStub extends PsiFileStub { + @Nonnull + String getName(); } diff --git a/base-api/src/main/java/module-info.java b/base-api/src/main/java/module-info.java index 8b6845e9..0a8a9b01 100644 --- a/base-api/src/main/java/module-info.java +++ b/base-api/src/main/java/module-info.java @@ -1,24 +1,28 @@ /** * @author VISTALL - * @since 23-Aug-22 + * @since 2022-08-23 */ open module consulo.javascript.base.api { - requires transitive consulo.ide.api; + requires transitive consulo.ide.api; - exports com.intellij.lang.javascript.formatter; - exports com.intellij.lang.javascript.psi; - exports com.intellij.lang.javascript.psi.stubs; + exports com.intellij.lang.javascript.formatter; + exports com.intellij.lang.javascript.psi; + exports com.intellij.lang.javascript.psi.stubs; - exports consulo.javascript.icon; - exports consulo.javascript.ide.completion; - exports consulo.javascript.index; - exports consulo.javascript.language; - exports consulo.javascript.language.psi; - exports consulo.javascript.localize; - exports consulo.javascript.module.extension; - exports consulo.javascript.psi; - exports consulo.javascript.psi.impl.reference; - exports consulo.javascript.language.psi.stub; - exports consulo.javascript.psi.stubs; + exports consulo.javascript.icon; + exports consulo.javascript.ide.completion; + exports consulo.javascript.index; + exports consulo.javascript.language; + exports consulo.javascript.language.psi; + exports consulo.javascript.language.psi.stub; + exports consulo.javascript.localize; + exports consulo.javascript.module.extension; + exports consulo.javascript.psi; + exports consulo.javascript.psi.impl.reference; + exports consulo.javascript.psi.stubs; + + exports consulo.javascript.internal to + consulo.javascript.base.impl, + consulo.javascript.ecmascript.impl; } \ No newline at end of file diff --git a/base-api/src/main/resources/ICON-LIB/dark/consulo.javascript.JavaScriptIconGroup/as.svg b/base-api/src/main/resources/ICON-LIB/dark/consulo.javascript.JavaScriptIconGroup/as.svg new file mode 100644 index 00000000..54fb344d --- /dev/null +++ b/base-api/src/main/resources/ICON-LIB/dark/consulo.javascript.JavaScriptIconGroup/as.svg @@ -0,0 +1,7 @@ + + + + + diff --git a/base-api/src/main/resources/ICON-LIB/dark/consulo.javascript.JavaScriptIconGroup/javaScript.svg b/base-api/src/main/resources/ICON-LIB/dark/consulo.javascript.JavaScriptIconGroup/javaScript.svg new file mode 100644 index 00000000..86f91868 --- /dev/null +++ b/base-api/src/main/resources/ICON-LIB/dark/consulo.javascript.JavaScriptIconGroup/javaScript.svg @@ -0,0 +1,9 @@ + + + + + + diff --git a/base-api/src/main/resources/ICON-LIB/dark/consulo.javascript.JavaScriptIconGroup/javaScriptModule.svg b/base-api/src/main/resources/ICON-LIB/dark/consulo.javascript.JavaScriptIconGroup/javaScriptModule.svg new file mode 100644 index 00000000..86f91868 --- /dev/null +++ b/base-api/src/main/resources/ICON-LIB/dark/consulo.javascript.JavaScriptIconGroup/javaScriptModule.svg @@ -0,0 +1,9 @@ + + + + + + diff --git a/base-api/src/main/resources/ICON-LIB/dark/consulo.javascript.JavaScriptIconGroup/json.svg b/base-api/src/main/resources/ICON-LIB/dark/consulo.javascript.JavaScriptIconGroup/json.svg index 48be129a..7507cc4e 100644 --- a/base-api/src/main/resources/ICON-LIB/dark/consulo.javascript.JavaScriptIconGroup/json.svg +++ b/base-api/src/main/resources/ICON-LIB/dark/consulo.javascript.JavaScriptIconGroup/json.svg @@ -1,9 +1,7 @@ - - - - - - - - + + + + diff --git a/base-api/src/main/resources/ICON-LIB/dark/consulo.javascript.JavaScriptIconGroup/jsx.svg b/base-api/src/main/resources/ICON-LIB/dark/consulo.javascript.JavaScriptIconGroup/jsx.svg new file mode 100644 index 00000000..37505479 --- /dev/null +++ b/base-api/src/main/resources/ICON-LIB/dark/consulo.javascript.JavaScriptIconGroup/jsx.svg @@ -0,0 +1,8 @@ + + + + + diff --git a/base-api/src/main/resources/ICON-LIB/dark/consulo.javascript.JavaScriptIconGroup/typeScript.svg b/base-api/src/main/resources/ICON-LIB/dark/consulo.javascript.JavaScriptIconGroup/typeScript.svg new file mode 100644 index 00000000..6495f933 --- /dev/null +++ b/base-api/src/main/resources/ICON-LIB/dark/consulo.javascript.JavaScriptIconGroup/typeScript.svg @@ -0,0 +1,8 @@ + + + + + + diff --git a/base-api/src/main/resources/ICON-LIB/light/consulo.javascript.JavaScriptIconGroup/as.svg b/base-api/src/main/resources/ICON-LIB/light/consulo.javascript.JavaScriptIconGroup/as.svg index a4afa938..8bf2482d 100644 --- a/base-api/src/main/resources/ICON-LIB/light/consulo.javascript.JavaScriptIconGroup/as.svg +++ b/base-api/src/main/resources/ICON-LIB/light/consulo.javascript.JavaScriptIconGroup/as.svg @@ -1,10 +1,7 @@ - - - - - - - - - + + + + diff --git a/base-api/src/main/resources/ICON-LIB/light/consulo.javascript.JavaScriptIconGroup/flex.png b/base-api/src/main/resources/ICON-LIB/light/consulo.javascript.JavaScriptIconGroup/flex.png deleted file mode 100644 index cf39e7dd..00000000 Binary files a/base-api/src/main/resources/ICON-LIB/light/consulo.javascript.JavaScriptIconGroup/flex.png and /dev/null differ diff --git a/base-api/src/main/resources/ICON-LIB/light/consulo.javascript.JavaScriptIconGroup/javaScript.svg b/base-api/src/main/resources/ICON-LIB/light/consulo.javascript.JavaScriptIconGroup/javaScript.svg index 0d8fa6fb..cf626328 100644 --- a/base-api/src/main/resources/ICON-LIB/light/consulo.javascript.JavaScriptIconGroup/javaScript.svg +++ b/base-api/src/main/resources/ICON-LIB/light/consulo.javascript.JavaScriptIconGroup/javaScript.svg @@ -1,10 +1,9 @@ - - - - - - - - - + + + + + diff --git a/base-api/src/main/resources/ICON-LIB/light/consulo.javascript.JavaScriptIconGroup/javaScriptModule.svg b/base-api/src/main/resources/ICON-LIB/light/consulo.javascript.JavaScriptIconGroup/javaScriptModule.svg new file mode 100644 index 00000000..cf626328 --- /dev/null +++ b/base-api/src/main/resources/ICON-LIB/light/consulo.javascript.JavaScriptIconGroup/javaScriptModule.svg @@ -0,0 +1,9 @@ + + + + + + diff --git a/base-api/src/main/resources/ICON-LIB/light/consulo.javascript.JavaScriptIconGroup/json.svg b/base-api/src/main/resources/ICON-LIB/light/consulo.javascript.JavaScriptIconGroup/json.svg index 9898855a..d9ca60d9 100644 --- a/base-api/src/main/resources/ICON-LIB/light/consulo.javascript.JavaScriptIconGroup/json.svg +++ b/base-api/src/main/resources/ICON-LIB/light/consulo.javascript.JavaScriptIconGroup/json.svg @@ -1,9 +1,7 @@ - - - - - - - - + + + + diff --git a/base-api/src/main/resources/ICON-LIB/light/consulo.javascript.JavaScriptIconGroup/jsx.svg b/base-api/src/main/resources/ICON-LIB/light/consulo.javascript.JavaScriptIconGroup/jsx.svg index 81e10aad..3fdeb21a 100644 --- a/base-api/src/main/resources/ICON-LIB/light/consulo.javascript.JavaScriptIconGroup/jsx.svg +++ b/base-api/src/main/resources/ICON-LIB/light/consulo.javascript.JavaScriptIconGroup/jsx.svg @@ -1,17 +1,8 @@ - - - - - - - - - - - + + + + diff --git a/base-api/src/main/resources/ICON-LIB/light/consulo.javascript.JavaScriptIconGroup/typeScript.svg b/base-api/src/main/resources/ICON-LIB/light/consulo.javascript.JavaScriptIconGroup/typeScript.svg index 05c1e277..71acf1a7 100644 --- a/base-api/src/main/resources/ICON-LIB/light/consulo.javascript.JavaScriptIconGroup/typeScript.svg +++ b/base-api/src/main/resources/ICON-LIB/light/consulo.javascript.JavaScriptIconGroup/typeScript.svg @@ -1,15 +1,8 @@ - - - - - - - - - - + + + + + diff --git a/base-api/src/main/resources/LOCALIZE-LIB/en_US/consulo.javascript.JavaScriptLocalize.yaml b/base-api/src/main/resources/LOCALIZE-LIB/en_US/consulo.javascript.JavaScriptLocalize.yaml index 5fb96c45..5dc70d92 100644 --- a/base-api/src/main/resources/LOCALIZE-LIB/en_US/consulo.javascript.JavaScriptLocalize.yaml +++ b/base-api/src/main/resources/LOCALIZE-LIB/en_US/consulo.javascript.JavaScriptLocalize.yaml @@ -1,538 +1,544 @@ +action.JavaScript.File.empty.file.kind: + text: Empty File +action.JavaScript.File.text: + text: JavaScript File +action.JavaScript.File.title.text: + text: Create JavaScript File +building.index.message: + text: Building JavaScript indices +choose.class.title: + text: Choose Class +create.class.dialog.title: + text: Create Class +create.interface.dialog.title: + text: Create Interface +flex.import.class: + text: Import Class {0} +flex.import.function: + text: Import Function {0} +generate.constructor.fields.chooser.title: + text: Choose Fields to Initialize by Constructor +generate.getter.fields.bindable.properties: + text: '&Bindable properties' +generate.getter.fields.chooser.title: + text: Select Fields to Generate Getters +generate.getter.setter.chooser.title: + text: Select Fields to Generate Getters and Setters +generate.setter.fields.chooser.title: + text: Select Fields to Generate Setters +generate.to.string.chooser.title: + text: Select Fields to Use in toString function +interface.function.declaration.should.have.no.body: + text: Interface functions declaration should have no body +interface.should.have.no.variable.declarations: + text: Interface should have no variable declarations +invalid.identifier.value: + text: invalid identifier value +javascript.argument.type.mismatch: + text: Argument type {1} is not assignable to parameter type {0} +javascript.assigned.expression.type.mismatch: + text: Assigned expression type {1} is not assignable to type {0} +javascript.badcharacter: + text: Bad character +javascript.binary.operand.type.mismatch: + text: Binary operation argument type {1} is not assignable to type {0} +javascript.blockcomment: + text: Block comment +javascript.braces: + text: Braces +javascript.brackets: + text: Brackets +javascript.comma: + text: Comma +javascript.create.class.intention.name: + text: Create Class {0} +javascript.create.constant.field.intention.name: + text: Create Constant Field {0} +javascript.create.constant.intention.name: + text: Create Constant {0} +javascript.create.event.handler.intention.name: + text: Create Event Handler {0} +javascript.create.function.intention.family: + text: Create JavaScript Function or Method +javascript.create.function.intention.name: + text: Create Function {0} +javascript.create.get.property.intention.name: + text: Create Get Property {0} +javascript.create.interface.intention.name: + text: Create Interface {0} +javascript.create.method.intention.name: + text: Create Method {0} +javascript.create.namespace.intention.name: + text: Create Namespace {0} +javascript.create.property.intention.name: + text: Create Field {0} +javascript.create.set.property.intention.name: + text: Create Set Property {0} +javascript.create.variable.intention.family: + text: Create JavaScript Variable Or Property +javascript.create.variable.intention.name: + text: Create Variable {0} +javascript.declare.variable.intention.name: + text: Insert Var Declaration for {0} +javascript.deprecated.symbol.used.name.message: + text: 'Deprecated symbol used, consult docs for better alternative #loc' +javascript.doccomment: + text: Doc comment +javascript.docmarkup: + text: Documentation markup +javascript.doctag: + text: Documentation tag +javascript.dot: + text: Dot +javascript.extract.method.title: + text: Extract Function javascript.filetype.description: - text: JavaScript files -typescript.filetype.description: - text: TypeScript files -javascript.language.term.function: - text: function + text: JavaScript files +javascript.fix.add.override.modifier: + text: Add override modifier +javascript.fix.create.constructor.invoke.super: + text: Create constructor matching super +javascript.fix.create.invoke.super: + text: Insert super class constructor invokation +javascript.fix.implement.methods: + text: Implement Methods +javascript.fix.optimize.imports: + text: Optimize imports +javascript.fix.package.name: + text: Set package name to ''{0}'' +javascript.fix.remove.access.modifier: + text: Remove access modifier +javascript.fix.remove.circular.dependency: + text: Remove circular dependency +javascript.fix.remove.constructor: + text: Remove constructor +javascript.fix.remove.externally.visible.symbol: + text: Remove externally visible symbol +javascript.fix.remove.initializer: + text: Remove initializer +javascript.fix.remove.namespace.reference: + text: Remove namespace reference +javascript.fix.remove.override.modifier: + text: Remove override modifier +javascript.fix.remove.parameter: + text: Remove parameter +javascript.fix.remove.type.reference: + text: Remove type reference +javascript.formatting.options.panel.title: + text: Formatting options +javascript.global.function: + text: Global function +javascript.global.variable: + text: Global variable +javascript.incorrect.array.type.in.forin: + text: Array key type should be String +javascript.incorrect.variable.type.mismatch: + text: Variable type {1} is not assignable to type {0} +javascript.initializer.type.mismatch: + text: Initializer type {1} is not assignable to variable type {0} +javascript.insert.cast.fix: + text: Insert cast +javascript.instance.member.function: + text: Instance member function +javascript.instance.member.variable: + text: Instance member variable +javascript.interface.can.not.be.instantiated.message: + text: Interface can not be instantiated +javascript.introduce.constant.error.no.expression.selected: + text: |- + Cannot introduce constant. + Selection does not form an expression. +javascript.introduce.constant.error.not.available.in.javascript.code: + text: Introduce Constant is not available in JavaScript code +javascript.introduce.constant.error.not.constant.expression.selected: + text: |- + Cannot introduce constant. + Selection is not constant expression. +javascript.introduce.constant.title: + text: Introduce Constant +javascript.introduce.field.error.no.expression.selected: + text: |- + Cannot introduce field. + Selection does not form an expression. +javascript.introduce.field.error.not.available.in.javascript.code: + text: Introduce Field is not available in JavaScript code +javascript.introduce.field.title: + text: Introduce Field +javascript.introduce.variable.error.no.expression.selected: + text: |- + Cannot introduce variable. + Selection does not form an expression. +javascript.introduce.variable.function.already.exists: + text: Function with name {0} already exists in the scope. +javascript.introduce.variable.invalid.name: + text: Please enter a valid name. +javascript.introduce.variable.name.prompt: + text: '&Name:' +javascript.introduce.variable.replace.all.occurrences: + text: Replace &all occurrences ({0} occurrences found) +javascript.introduce.variable.title: + text: Introduce Variable +javascript.introduce.variable.variable.already.exists: + text: Variable with name {0} already exists in the scope. +javascript.invalid.number.of.parameters: + text: Invalid number of parameters, expected {0} +javascript.invalid.string.escape: + text: Invalid string escape +javascript.keyword: + text: Keyword +javascript.language.term.attribute.value: + text: Attribute value javascript.language.term.class: - text: class + text: class +javascript.language.term.function: + text: function +javascript.language.term.label: + text: label javascript.language.term.namespace: - text: namespace + text: namespace +javascript.language.term.package: + text: package javascript.language.term.parameter: - text: parameter + text: parameter javascript.language.term.property: - text: property -javascript.language.term.variable: - text: variable -javascript.language.term.value: - text: value -javascript.language.term.tag: - text: tag -javascript.language.term.label: - text: label + text: property javascript.language.term.prototype: - text: prototype + text: prototype +javascript.language.term.tag: + text: tag +javascript.language.term.value: + text: value +javascript.language.term.variable: + text: variable +javascript.linecomment: + text: Line comment +javascript.local.variable: + text: Local variable +javascript.metadata: + text: Metadata +javascript.name: + text: JavaScript +javascript.number: + text: Number +javascript.operation: + text: Operation +javascript.parameter: + text: Parameter +javascript.parens: + text: Parenthesis +javascript.parser.message.expected.catch.or.default: + text: catch or default expected +javascript.parser.message.expected.colon: + text: ': expected' +javascript.parser.message.expected.comma: + text: ', expected' +javascript.parser.message.expected.comma.or.rparen: + text: ', or ) expected' +javascript.parser.message.expected.doc.tag.name: + text: Expected doc tag name +javascript.parser.message.expected.doc.tag.value: + text: Expected doc tag value +javascript.parser.message.expected.eof: + text: End of file expected +javascript.parser.message.expected.equal: + text: expected = javascript.parser.message.expected.expression: - text: expression expected -javascript.parser.message.expected.xml.element: - text: xml element expected -javascript.parser.property.expected: - text: property expected + text: expression expected +javascript.parser.message.expected.forloop.in.of.or.semicolon: + text: '''in'', ''of'' or ; expected' +javascript.parser.message.expected.forloop.in.or.semicolon: + text: '''in'' or ; expected' +javascript.parser.message.expected.forloop.left.hand.side.expression.or.variable.declaration: + text: left hand side expression or variable declaration expected before 'in' +javascript.parser.message.expected.formal.parameter.name: + text: formal parameter name expected +javascript.parser.message.expected.function.name: + text: function name expected +javascript.parser.message.expected.function.var.class.interface.namespace: + text: Expected function, variable, class, interface or namespace declaration +javascript.parser.message.expected.identifer.or.value: + text: Identifier or value expected +javascript.parser.message.expected.identifier: + text: Expected identifier +javascript.parser.message.expected.identifier.string.literal.or.numeric.literal: + text: identifier or string literal or numeric literal expected +javascript.parser.message.expected.instanceof: + text: Expected instanceof javascript.parser.message.expected.lbrace: - text: "'{' expected" + text: '''{'' expected' +javascript.parser.message.expected.lbrace.or.lbracket: + text: '''{'' or ''['' expected' +javascript.parser.message.expected.lparen: + text: ( expected +javascript.parser.message.expected.lt: + text: Expected > +javascript.parser.message.expected.name: + text: name expected +javascript.parser.message.expected.name.or.lbrace: + text: Expected package name or '{' +javascript.parser.message.expected.namespace: + text: Namespace keyword expected +javascript.parser.message.expected.parameter.name: + text: parameter name expected javascript.parser.message.expected.rbrace: - text: "'}' expected" -javascript.parser.message.expected.identifier.string.literal.or.numeric.literal: - text: identifier or string literal or numeric literal expected -javascript.parser.message.expected.colon: - text: ': expected' -javascript.parser.message.expected.semicolon: - text: ; expected + text: '''}'' expected' javascript.parser.message.expected.rbracket: - text: '] expected' -javascript.parser.message.expected.lparen: - text: ( expected + text: '] expected' javascript.parser.message.expected.rparen: - text: ) expected -javascript.parser.message.expected.name: - text: name expected -javascript.parser.message.expected.comma.or.rparen: - text: ', or ) expected' -javascript.parser.message.expected.function.name: - text: function name expected -javascript.parser.message.expected.formal.parameter.name: - text: formal parameter name expected + text: ) expected +javascript.parser.message.expected.semicolon: + text: ; expected javascript.parser.message.expected.statement: - text: statement expected -javascript.parser.message.expected.parameter.name: - text: parameter name expected -javascript.parser.message.expected.catch.or.default: - text: catch or default expected -javascript.parser.message.expected.forloop.left.hand.side.expression.or.variable.declaration: - text: left hand side expression or variable declaration expected before 'in' -javascript.parser.message.expected.forloop.in.or.semicolon: - text: '''in'' or ; expected' -javascript.parser.message.expected.forloop.in.of.or.semicolon: - text: '''in'', ''of'' or ; expected' -javascript.parser.message.expected.while.keyword: - text: while expected -javascript.parser.message.expected.comma: - text: ', expected' + text: statement expected +javascript.parser.message.expected.string.literal: + text: String literal expected +javascript.parser.message.expected.typename: + text: '* or type name expected' +javascript.parser.message.expected.value: + text: value expected javascript.parser.message.expected.variable.name: - text: variable name expected + text: variable name expected +javascript.parser.message.expected.while.keyword: + text: while expected +javascript.parser.message.expected.xml: + text: xml context keyword expected +javascript.parser.message.expected.xml.element: + text: xml element expected javascript.parser.message.missing.rbrace: - text: missing } -javascript.parser.message.unexpected.end.of.file: - text: unexpected end of file + text: missing } javascript.parser.message.unclosed.string.literal: - text: Unclosed string literal -javascript.validation.message.duplicate.declaration: - text: Duplicate declaration -javascript.validation.message.assignment.to.const: - text: Attempt to assign to const variable -javascript.validation.message.arguments.out.of.function: - text: Using function arguments object outside function -javascript.validation.message.must.be.lvalue: - text: Must be lvalue -javascript.validation.message.const.variable.without.initializer.: - text: const variable without initializer. It won't be possible to assign meaningful value later. -javascript.validation.message.continue.without.target: - text: Cannot determine target for 'continue' -javascript.validation.message.break.without.target: - text: Cannot determine target for 'break' -javascript.validation.message.return.outside.function.definition: - text: '''return'' outside function definition' -javascript.validation.message.duplicate.label: - text: Duplicate label + text: Unclosed string literal +javascript.parser.message.unexpected.end.of.file: + text: unexpected end of file +javascript.parser.property.expected: + text: property expected +javascript.regexp: + text: Regular expression +javascript.returned.expression.type.mismatch: + text: Returned expression type {1} is not assignable to type {0} +javascript.semicolon: + text: Semicolon +javascript.static.member.function: + text: Static member function +javascript.static.member.variable: + text: Static member variable +javascript.string: + text: String javascript.surround.with.do.while: - text: do / while + text: do / while javascript.surround.with.for: - text: for + text: for +javascript.surround.with.function: + text: function +javascript.surround.with.function.expression: + text: function expression javascript.surround.with.if: - text: if + text: if javascript.surround.with.if.else: - text: if / else + text: if / else javascript.surround.with.parenthesis: - text: (expr) + text: (expr) javascript.surround.with.try.catch: - text: try / catch -javascript.surround.with.try.finally: - text: try / finally + text: try / catch javascript.surround.with.try.catch.finally: - text: try / catch / finally + text: try / catch / finally +javascript.surround.with.try.finally: + text: try / finally javascript.surround.with.while: - text: while + text: while javascript.surround.with.with: - text: with -javascript.surround.with.function: - text: function -javascript.surround.with.function.expression: - text: function expression -javascript.introduce.variable.title: - text: Introduce Variable -javascript.introduce.variable.error.no.expression.selected: - text: |- - Cannot introduce variable. - Selection does not form an expression. -javascript.introduce.variable.name.prompt: - text: '&Name:' -javascript.introduce.variable.replace.all.occurrences: - text: Replace &all occurrences ({0} occurrences found) -javascript.introduce.variable.invalid.name: - text: Please enter a valid name. -javascript.introduce.variable.variable.already.exists: - text: Variable with name {0} already exists in the scope. -javascript.introduce.variable.function.already.exists: - text: Function with name {0} already exists in the scope. -javascript.introduce.field.title: - text: Introduce Field -javascript.introduce.field.error.no.expression.selected: - text: |- - Cannot introduce field. - Selection does not form an expression. -javascript.introduce.constant.title: - text: Introduce Constant -javascript.introduce.constant.error.no.expression.selected: - text: |- - Cannot introduce constant. - Selection does not form an expression. -javascript.introduce.constant.error.not.constant.expression.selected: - text: |- - Cannot introduce constant. - Selection is not constant expression. -javascript.keyword: - text: Keyword -javascript.string: - text: String -javascript.number: - text: Number -javascript.linecomment: - text: Line comment -javascript.doccomment: - text: Doc comment -javascript.blockcomment: - text: Block comment -javascript.regexp: - text: Regular expression -javascript.operation: - text: Operation -javascript.parens: - text: Parenthesis -javascript.brackets: - text: Brackets -javascript.braces: - text: Braces -javascript.semicolon: - text: Semicolon -javascript.badcharacter: - text: Bad character -javascript.docmarkup: - text: Documentation markup -javascript.doctag: - text: Documentation tag -javascript.valid.string.escape: - text: Valid string escape -javascript.invalid.string.escape: - text: Invalid string escape -javascript.comma: - text: Comma -javascript.dot: - text: Dot -building.index.message: - text: Building JavaScript indices -loading.index.message: - text: Loading JavaScript indices + text: with +javascript.template.context.type: + text: Java Sc&ript +javascript.term.does.not.evaluate.to.function: + text: Method expression is not of Function type +javascript.term.does.not.evaluate.to.function2: + text: Property can not be invoked as function +javascript.term.does.not.evaluate.to.function2.fix: + text: Remove argument list +javascript.undeclared.variable.name.message: + text: 'Variable {0} implicitly declared #loc' javascript.unresolved.function.name.message: - text: 'Unresolved function or method {0}() #loc' -javascript.unresolved.variable.name.message: - text: 'Unresolved variable {0} #loc' + text: 'Unresolved function or method {0}() #loc' javascript.unresolved.type.name.message: - text: 'Unresolved type {0} #loc' + text: 'Unresolved type {0} #loc' +javascript.unresolved.variable.name.message: + text: 'Unresolved variable {0} #loc' javascript.unresolved.variable.or.type.name.message: - text: 'Unresolved variable or type {0} #loc' + text: 'Unresolved variable or type {0} #loc' javascript.unresolved.variable.or.type.name.message2: - text: Unresolved variable or type {0} -javascript.undeclared.variable.name.message: - text: 'Variable {0} implicitly declared #loc' -javascript.create.function.intention.name: - text: Create Function {0} -javascript.create.variable.intention.name: - text: Create Variable {0} -javascript.create.constant.intention.name: - text: Create Constant {0} -javascript.declare.variable.intention.name: - text: Insert Var Declaration for {0} -javascript.create.namespace.intention.name: - text: Create Namespace {0} -javascript.create.property.intention.name: - text: Create Field {0} -javascript.create.constant.field.intention.name: - text: Create Constant Field {0} -javascript.create.method.intention.name: - text: Create Method {0} -javascript.create.get.property.intention.name: - text: Create Get Property {0} -javascript.create.set.property.intention.name: - text: Create Set Property {0} -javascript.create.function.intention.family: - text: Create JavaScript Function or Method -javascript.create.variable.intention.family: - text: Create JavaScript Variable Or Property -js.inspection.group.name: - text: JavaScript -js.unresolved.variable.inspection.name: - text: Unresolved JavaScript variable -js.undeclared.variable.inspection.name: - text: Implicitly declared JavaScript variable -js.duplicated.declaration.inspection.name: - text: Duplicated JavaScript declaration -js.unused.local.symbol.inspection.name: - text: Unused JavaScript local symbol -js.unresolved.function.inspection.name: - text: Unresolved JavaScript function -js.deprecated.symbols.inspection.name: - text: Deprecated JavaScript symbol -javascript.parser.message.expected.typename: - text: '* or type name expected' -javascript.parser.message.expected.name.or.lbrace: - text: "Expected package name or '{'" -javascript.parser.message.expected.function.var.class.interface.namespace: - text: Expected function, variable, class, interface or namespace declaration -interface.function.declaration.should.have.no.body: - text: Interface functions declaration should have no body -javascript.parser.message.expected.namespace: - text: Namespace keyword expected -javascript.parser.message.expected.string.literal: - text: String literal expected -javascript.parser.message.expected.xml: - text: xml context keyword expected -javascript.parser.message.expected.equal: - text: expected = -javascript.parser.message.expected.lbrace.or.lbracket: - text: "'{' or '[' expected" -javascript.parser.message.expected.eof: - text: End of file expected -javascript.deprecated.symbol.used.name.message: - text: 'Deprecated symbol used, consult docs for better alternative #loc' -js.classname.macro.description: - text: jsClassName() -js.methodname.macro.description: - text: jsMethodName() -js.unused.parameter: - text: Unused parameter -js.unused.function.declaration: - text: Unused function declaration -js.unused.local.variable: - text: Unused local variable declaration -js.unused.symbol.remove: - text: Remove unused symbol -javascript.parser.message.expected.identifier: - text: Expected identifier -javascript.parser.message.expected.instanceof: - text: Expected instanceof -javascript.parser.message.expected.value: - text: value expected -javascript.parser.message.expected.identifer.or.value: - text: Identifier or value expected -js.show.overriding.markers.inspection.name: - text: Shows function overriding markers in JavaScript -js.untyped.declaration.inspection.name: - text: Declaration with no type -js.untyped.variable.problem: - text: Variable {0} has no type -js.untyped.function.problem: - text: Function {0} has no return type -js.untyped.declaration.problem.addtype.fix: - text: Add Type to Declaration -invalid.identifier.value: - text: invalid identifier value -javascript.validation.message.this.referenced.from.static.context: - text: '''this'' referenced in static context' -javascript.validation.message.super.referenced.without.class.instance.context: - text: '''super'' referenced without class instance context' -javascript.validation.message.super.referenced.from.static.context: - text: '''super'' referenced in static context' -javascript.validation.message.function.override.without.override.modifier: - text: Method overrides method in superclass {0} without override keyword -javascript.language.term.attribute.value: - text: Attribute value -javascript.validation.message.class.should.be.in.file: - text: Class ''{0}'' should be defined in file ''{1}'' -javascript.validation.message.function.should.be.in.file: - text: Function ''{0}'' should be defined in file ''{1}'' -javascript.validation.message.namespace.should.be.in.file: - text: Namespace ''{0}'' should be defined in file ''{1}'' -javascript.validation.message.variable.should.be.in.file: - text: Variable ''{0}'' should be defined in file ''{1}'' -javascript.validation.message.incorrect.package.name: - text: Package name ''{0}'' does not correspond to file path ''{1}'' -javascript.fix.package.name: - text: Set package name to ''{0}'' -javascript.fix.add.override.modifier: - text: Add override modifier -js.code.style.tab.name: - text: JavaScript / ECMAScript / ActionScript -to.indent.package.statement.children: - text: '&Indent package statement children' -javascript.formatting.options.panel.title: - text: Formatting options -preview.panel.title: - text: Preview -javascript.validation.message.interface.members.cannot.have.access.modifiers: - text: Interface members cannot have access modifiers -javascript.template.context.type: - text: Java Sc&ript -flex.import.class: - text: Import Class {0} -flex.import.function: - text: Import Function {0} -interface.should.have.no.variable.declarations: - text: Interface should have no variable declarations -javascript.validation.message.implements.for.interface.not.allowed: - text: Implements list is not allowed for interface -javascript.validation.message.interface.name.expected.here: - text: Interface name expected here -javascript.validation.message.class.name.expected.here: - text: Class name expected here + text: Unresolved variable or type {0} +javascript.valid.string.escape: + text: Valid string escape +javascript.validation.message.access.modifier.allowed.only.for.class.members: + text: Access modifier allowed for class members only +javascript.validation.message.access.modifier.allowed.only.for.package.members: + text: Only public / internal modifiers allowed for package members +javascript.validation.message.arguments.out.of.function: + text: Using function arguments object outside function +javascript.validation.message.arguments.with.rest.parameter: + text: '''arguments'' object is not available when using rest parameter' +javascript.validation.message.assignment.to.const: + text: Attempt to assign to const variable +javascript.validation.message.break.without.target: + text: Cannot determine target for 'break' javascript.validation.message.circular.dependency: - text: Circular dependency -javascript.fix.remove.circular.dependency: - text: Remove circular dependency -javascript.validation.message.more.than.one.externally.visible.symbol: - text: More than one externally visible symbol defined in file -javascript.validation.message.interface.method.not.implemented: - text: Method {0} from interface {1} is not implemented -javascript.fix.remove.externally.visible.symbol: - text: Remove externally visible symbol -javascript.fix.implement.methods: - text: Implement Methods -javascript.parameter: - text: Parameter -javascript.local.variable: - text: Local variable -javascript.global.variable: - text: Global variable -javascript.global.function: - text: Global function -javascript.static.member.function: - text: Static member function -javascript.static.member.variable: - text: Static member variable -javascript.instance.member.variable: - text: Instance member variable -javascript.instance.member.function: - text: Instance member function -javascript.create.class.intention.name: - text: Create Class {0} -javascript.create.interface.intention.name: - text: Create Interface {0} -create.class.dialog.title: - text: Create Class -create.interface.dialog.title: - text: Create Interface -choose.class.title: - text: Choose Class -javascript.fix.remove.override.modifier: - text: Remove override modifier + text: Circular dependency +javascript.validation.message.class.name.expected.here: + text: Class name expected here +javascript.validation.message.class.should.be.in.file: + text: Class ''{0}'' should be defined in file ''{1}'' +javascript.validation.message.const.variable.without.initializer.: + text: const variable without initializer. It won't be possible to assign meaningful value later. +javascript.validation.message.constructor.in.mxml.is.not.allowed: + text: Constructor is not allowed for MXML class +javascript.validation.message.continue.without.target: + text: Cannot determine target for 'continue' +javascript.validation.message.duplicate.declaration: + text: Duplicate declaration +javascript.validation.message.duplicate.label: + text: Duplicate label +javascript.validation.message.duplicated.catch.block: + text: 'Duplicated catch block #loc' +javascript.validation.message.duplicated.catch.block.fix: + text: Remove duplicated catch block +javascript.validation.message.file.should.be.under.source.root: + text: Object is located in file out of source root, certain functionality will not be available javascript.validation.message.function.override.for.object.method: - text: Method inherited from Object does not need override -javascript.validation.message.function.override.without.parent.method: - text: Method does not override method from super class -javascript.parser.message.expected.lt: - text: Expected > -generate.constructor.fields.chooser.title: - text: Choose Fields to Initialize by Constructor -generate.getter.setter.chooser.title: - text: Select Fields to Generate Getters and Setters -generate.to.string.chooser.title: - text: Select Fields to Use in toString function -generate.getter.fields.chooser.title: - text: Select Fields to Generate Getters -generate.setter.fields.chooser.title: - text: Select Fields to Generate Setters -methods.to.implement.chooser.title: - text: Select Methods to Implement -methods.to.override.chooser.title: - text: Select Methods to Override -use.semicolon.to.terminate.statement: - text: Use &semicolon to terminate statements -javascript.validation.unused.import: - text: Unused import -javascript.fix.optimize.imports: - text: Optimize imports -javascript.parser.message.expected.doc.tag.value: - text: Expected doc tag value -javascript.validation.message.incorrect.tag.value: - text: Incorrect Tag Value -javascript.validation.message.incorrect.parameter.name: - text: Incorrect parameter name -javascript.parser.message.expected.doc.tag.name: - text: Expected doc tag name -javascript.invalid.number.of.parameters: - text: Invalid number of parameters, expected {0} -javascript.argument.type.mismatch: - text: Argument type {1} is not assignable to parameter type {0} -javascript.initializer.type.mismatch: - text: Initializer type {1} is not assignable to variable type {0} -javascript.binary.operand.type.mismatch: - text: Binary operation argument type {1} is not assignable to type {0} -javascript.incorrect.variable.type.mismatch: - text: Variable type {1} is not assignable to type {0} -javascript.term.does.not.evaluate.to.function: - text: Method expression is not of Function type -javascript.term.does.not.evaluate.to.function2: - text: Property can not be invoked as function -javascript.term.does.not.evaluate.to.function2.fix: - text: Remove argument list -javascript.assigned.expression.type.mismatch: - text: Assigned expression type {1} is not assignable to type {0} -javascript.returned.expression.type.mismatch: - text: Returned expression type {1} is not assignable to type {0} -javascript.insert.cast.fix: - text: Insert cast -javascript.introduce.constant.error.not.available.in.javascript.code: - text: Introduce Constant is not available in JavaScript code -javascript.introduce.field.error.not.available.in.javascript.code: - text: Introduce Field is not available in JavaScript code -javascript.extract.method.title: - text: Extract Function + text: Method inherited from Object does not need override javascript.validation.message.function.override.incompatible.access.modifier: - text: Incompatible override, should have ''{0}'' access modifier + text: Incompatible override, should have ''{0}'' access modifier javascript.validation.message.function.override.incompatible.signature: - text: Incompatible override, should have signature ''{0}'' + text: Incompatible override, should have signature ''{0}'' javascript.validation.message.function.override.incompatible.signature2: - text: Incompatible override, should have return type ''{0}'' + text: Incompatible override, should have return type ''{0}'' +javascript.validation.message.function.override.without.override.modifier: + text: Method overrides method in superclass {0} without override keyword +javascript.validation.message.function.override.without.parent.method: + text: Method does not override method from super class +javascript.validation.message.function.should.be.in.file: + text: Function ''{0}'' should be defined in file ''{1}'' +javascript.validation.message.get.method.should.be.valid.type: + text: Return type of a getter definition should not be {0} +javascript.validation.message.get.method.should.have.no.parameter: + text: A getter definition must have no parameters +javascript.validation.message.implements.for.interface.not.allowed: + text: Implements list is not allowed for interface +javascript.validation.message.incorrect.package.name: + text: Package name ''{0}'' does not correspond to file path ''{1}'' +javascript.validation.message.incorrect.parameter.name: + text: Incorrect parameter name +javascript.validation.message.incorrect.tag.value: + text: Incorrect Tag Value +javascript.validation.message.interface.members.cannot.have.access.modifiers: + text: Interface members cannot have access modifiers javascript.validation.message.interface.method.invalid.access.modifier: - text: Incompatible implementation, should have 'public' access modifier + text: Incompatible implementation, should have 'public' access modifier javascript.validation.message.interface.method.invalid.signature: - text: Incompatible implementation, should have signature ''{0}'' + text: Incompatible implementation, should have signature ''{0}'' javascript.validation.message.interface.method.invalid.signature2: - text: Incompatible implementation, should have return type ''{0}'' -javascript.validation.message.duplicated.catch.block: - text: 'Duplicated catch block #loc' -javascript.validation.message.duplicated.catch.block.fix: - text: Remove duplicated catch block -javascript.validation.message.return.value.of.type.is.required: - text: Return value of type {0} is required -javascript.validation.message.constructor.in.mxml.is.not.allowed: - text: Constructor is not allowed for MXML class -javascript.fix.remove.constructor: - text: Remove constructor -javascript.validation.message.package.shouldbe.first.statement: - text: Package should be first statement in file -javascript.metadata: - text: Metadata -javascript.validation.message.file.should.be.under.source.root: - text: Object is located in file out of source root, certain functionality will not be available -javascript.validation.message.unneeded.comma: - text: Unneeded comma -javascript.validation.message.remove.unneeded.comma.fix: - text: Remove unneeded comma -javascript.create.event.handler.intention.name: - text: Create Event Handler {0} + text: Incompatible implementation, should have return type ''{0}'' +javascript.validation.message.interface.method.not.implemented: + text: Method {0} from interface {1} is not implemented +javascript.validation.message.interface.name.expected.here: + text: Interface name expected here javascript.validation.message.missed.super.constructor.call: - text: Missed superclass's constructor invokation -javascript.fix.create.constructor.invoke.super: - text: Create constructor matching super -javascript.fix.create.invoke.super: - text: Insert super class constructor invokation -javascript.interface.can.not.be.instantiated.message: - text: Interface can not be instantiated -javascript.validation.message.set.method.should.be.void.or.without.type: - text: Return type of a setter definition must be unspecified or void -javascript.validation.message.set.method.should.have.one.parameter: - text: A setter definition must have exactly one parameter -javascript.validation.message.get.method.should.have.no.parameter: - text: A getter definition must have no parameters -javascript.validation.message.get.method.should.be.valid.type: - text: Return type of a getter definition should not be {0} -javascript.validation.message.access.modifier.allowed.only.for.class.members: - text: Access modifier allowed for class members only + text: Missed superclass's constructor invokation +javascript.validation.message.more.than.one.externally.visible.symbol: + text: More than one externally visible symbol defined in file +javascript.validation.message.must.be.lvalue: + text: Must be lvalue javascript.validation.message.namespace.allowed.only.for.class.members: - text: Namespace allowed for class members only -javascript.validation.message.access.modifier.allowed.only.for.package.members: - text: Only public / internal modifiers allowed for package members -javascript.validation.message.use.namespace.reference.or.access.modifier: - text: Use namespace OR access modifier -javascript.fix.remove.access.modifier: - text: Remove access modifier -javascript.fix.remove.namespace.reference: - text: Remove namespace reference -javascript.incorrect.array.type.in.for.in: - text: Array key type should be String -javascript.validation.message.unexpected.type.for.rest.parameter: - text: Rest parameter should have no type -javascript.fix.remove.type.reference: - text: Remove type reference + text: Namespace allowed for class members only +javascript.validation.message.namespace.should.be.in.file: + text: Namespace ''{0}'' should be defined in file ''{1}'' +javascript.validation.message.nested.classes.are.not.allowed: + text: Nested classes are not allowed +javascript.validation.message.package.shouldbe.first.statement: + text: Package should be first statement in file javascript.validation.message.parameter.is.not.allowed.after.rest.parameter: - text: No parameter is allowed after rest parameter -javascript.fix.remove.parameter: - text: Remove parameter -javascript.fix.remove.initializer: - text: Remove initializer + text: No parameter is allowed after rest parameter javascript.validation.message.parameter.should.be.initialized: - text: Parameter should be initialized + text: Parameter should be initialized +javascript.validation.message.remove.unneeded.comma.fix: + text: Remove unneeded comma javascript.validation.message.rest.parameter.should.not.be.initialized: - text: Rest parameter should not be initialized -javascript.validation.message.nested.classes.are.not.allowed: - text: Nested classes are not allowed -generate.getter.fields.bindable.properties: - text: '&Bindable properties' -javascript.language.term.package: - text: package -javascript.validation.message.arguments.with.rest.parameter: - text: '''arguments'' object is not available when using rest parameter' -action.JavaScript.File.text: - text: JavaScript File + text: Rest parameter should not be initialized +javascript.validation.message.return.outside.function.definition: + text: '''return'' outside function definition' +javascript.validation.message.return.value.of.type.is.required: + text: Return value of type {0} is required +javascript.validation.message.set.method.should.be.void.or.without.type: + text: Return type of a setter definition must be unspecified or void +javascript.validation.message.set.method.should.have.one.parameter: + text: A setter definition must have exactly one parameter +javascript.validation.message.super.referenced.from.static.context: + text: '''super'' referenced in static context' +javascript.validation.message.super.referenced.without.class.instance.context: + text: '''super'' referenced without class instance context' +javascript.validation.message.this.referenced.from.static.context: + text: '''this'' referenced in static context' +javascript.validation.message.unexpected.type.for.rest.parameter: + text: Rest parameter should have no type +javascript.validation.message.unneeded.comma: + text: Unneeded comma +javascript.validation.message.use.namespace.reference.or.access.modifier: + text: Use namespace OR access modifier +javascript.validation.message.variable.should.be.in.file: + text: Variable ''{0}'' should be defined in file ''{1}'' +javascript.validation.unused.import: + text: Unused import +js.classname.macro.description: + text: jsClassName() +js.code.style.tab.name: + text: JavaScript / ECMAScript / ActionScript +js.deprecated.symbols.inspection.name: + text: Deprecated JavaScript symbol +js.duplicated.declaration.inspection.name: + text: Duplicated JavaScript declaration +js.inspection.group.name: + text: JavaScript +js.methodname.macro.description: + text: jsMethodName() +js.show.overriding.markers.inspection.name: + text: Shows function overriding markers in JavaScript +js.undeclared.variable.inspection.name: + text: Implicitly declared JavaScript variable +js.unresolved.function.inspection.name: + text: Unresolved JavaScript function +js.unresolved.variable.inspection.name: + text: Unresolved JavaScript variable +js.untyped.declaration.inspection.name: + text: Declaration with no type +js.untyped.declaration.problem.addtype.fix: + text: Add Type to Declaration +js.untyped.function.problem: + text: Function {0} has no return type +js.untyped.variable.problem: + text: Variable {0} has no type +js.unused.function.declaration: + text: Unused function declaration +js.unused.local.symbol.inspection.name: + text: Unused JavaScript local symbol +js.unused.local.variable: + text: Unused local variable declaration +js.unused.parameter: + text: Unused parameter +js.unused.symbol.remove: + text: Remove unused symbol +loading.index.message: + text: Loading JavaScript indices +methods.to.implement.chooser.title: + text: Select Methods to Implement +methods.to.override.chooser.title: + text: Select Methods to Override +preview.panel.title: + text: Preview this.feature.is.not.supported.by.current.language: - text: '''''{0}'''' is not supported by current language version' + text: '''''{0}'''' is not supported by current language version' +to.indent.package.statement.children: + text: '&Indent package statement children' +typescript.filetype.description: + text: TypeScript files +use.semicolon.to.terminate.statement: + text: Use &semicolon to terminate statements diff --git a/base-api/src/main/resources/messages/JavaScriptBundle.properties b/base-api/src/main/resources/messages/JavaScriptBundle.properties deleted file mode 100644 index 7d5c67d4..00000000 --- a/base-api/src/main/resources/messages/JavaScriptBundle.properties +++ /dev/null @@ -1,284 +0,0 @@ -javascript.filetype.description=JavaScript files -typescript.filetype.description=TypeScript files - -#language terms -javascript.language.term.function=function -javascript.language.term.class=class -javascript.language.term.namespace=namespace -javascript.language.term.parameter=parameter -javascript.language.term.property=property -javascript.language.term.variable=variable -javascript.language.term.value=value -javascript.language.term.tag=tag -javascript.language.term.label=label -javascript.language.term.prototype=prototype - -#parser error messages -javascript.parser.message.expected.expression=expression expected -javascript.parser.message.expected.xml.element=xml element expected -javascript.parser.property.expected=property expected -javascript.parser.message.expected.lbrace={ expected -javascript.parser.message.expected.rbrace=} expected -javascript.parser.message.expected.identifier.string.literal.or.numeric.literal=identifier or string literal or numeric literal expected -javascript.parser.message.expected.colon=: expected -javascript.parser.message.expected.semicolon=; expected -javascript.parser.message.expected.rbracket=] expected -javascript.parser.message.expected.lparen=( expected -javascript.parser.message.expected.rparen=) expected -javascript.parser.message.expected.name=name expected -javascript.parser.message.expected.comma.or.rparen=, or ) expected -javascript.parser.message.expected.function.name=function name expected -javascript.parser.message.expected.formal.parameter.name=formal parameter name expected -javascript.parser.message.expected.statement=statement expected -javascript.parser.message.expected.parameter.name=parameter name expected -javascript.parser.message.expected.catch.or.default=catch or default expected -javascript.parser.message.expected.forloop.left.hand.side.expression.or.variable.declaration=left hand side expression or variable declaration expected before 'in' -javascript.parser.message.expected.forloop.in.or.semicolon='in' or ; expected -javascript.parser.message.expected.forloop.in.of.or.semicolon='in', 'of' or ; expected -javascript.parser.message.expected.while.keyword=while expected -javascript.parser.message.expected.comma=, expected -javascript.parser.message.expected.variable.name=variable name expected -javascript.parser.message.missing.rbrace=missing } -javascript.parser.message.unexpected.end.of.file=unexpected end of file -javascript.parser.message.unclosed.string.literal=Unclosed string literal - -#validation messages -javascript.validation.message.duplicate.declaration=Duplicate declaration -javascript.validation.message.assignment.to.const=Attempt to assign to const variable -javascript.validation.message.arguments.out.of.function=Using function arguments object outside function -javascript.validation.message.must.be.lvalue=Must be lvalue -javascript.validation.message.const.variable.without.initializer.=const variable without initializer. It won't be possible to assign meaningful value later. -javascript.validation.message.continue.without.target=Cannot determine target for 'continue' -javascript.validation.message.break.without.target=Cannot determine target for 'break' -javascript.validation.message.return.outside.function.definition='return' outside function definition -javascript.validation.message.duplicate.label=Duplicate label - -#surround with names -javascript.surround.with.do.while=do / while -javascript.surround.with.for=for -javascript.surround.with.if=if -javascript.surround.with.if.else=if / else -javascript.surround.with.parenthesis=(expr) -javascript.surround.with.try.catch=try / catch -javascript.surround.with.try.finally=try / finally -javascript.surround.with.try.catch.finally=try / catch / finally -javascript.surround.with.while=while -javascript.surround.with.with=with -javascript.surround.with.function=function -javascript.surround.with.function.expression=function expression - -javascript.introduce.variable.title=Introduce Variable -javascript.introduce.variable.error.no.expression.selected=Cannot introduce variable.\nSelection does not form an expression. -javascript.introduce.variable.name.prompt=&Name: -javascript.introduce.variable.replace.all.occurrences=Replace &all occurrences ({0} occurrences found) -javascript.introduce.variable.invalid.name=Please enter a valid name. -javascript.introduce.variable.variable.already.exists=Variable with name {0} already exists in the scope. -javascript.introduce.variable.function.already.exists=Function with name {0} already exists in the scope. - -javascript.introduce.field.title=Introduce Field -javascript.introduce.field.error.no.expression.selected=Cannot introduce field.\nSelection does not form an expression. -javascript.introduce.constant.title=Introduce Constant -javascript.introduce.constant.error.no.expression.selected=Cannot introduce constant.\nSelection does not form an expression. -javascript.introduce.constant.error.not.constant.expression.selected=Cannot introduce constant.\nSelection is not constant expression. - -#Highlighting categories -javascript.keyword=Keyword -javascript.string=String -javascript.number=Number -javascript.linecomment=Line comment -javascript.doccomment=Doc comment -javascript.blockcomment=Block comment -javascript.regexp=Regular expression -javascript.operation=Operation -javascript.parens=Parenthesis -javascript.brackets=Brackets -javascript.braces=Braces -javascript.semicolon=Semicolon -javascript.badcharacter=Bad character -javascript.docmarkup=Documentation markup -javascript.doctag=Documentation tag -javascript.valid.string.escape=Valid string escape -javascript.invalid.string.escape=Invalid string escape -javascript.comma=Comma -javascript.dot=Dot - -building.index.message=Building JavaScript indices -loading.index.message=Loading JavaScript indices - -#errors with intentions -javascript.unresolved.function.name.message=Unresolved function or method {0}() #loc -javascript.unresolved.variable.name.message=Unresolved variable {0} #loc -javascript.unresolved.type.name.message=Unresolved type {0} #loc -javascript.unresolved.variable.or.type.name.message=Unresolved variable or type {0} #loc -javascript.unresolved.variable.or.type.name.message2=Unresolved variable or type {0} -javascript.undeclared.variable.name.message=Variable {0} implicitly declared #loc -javascript.create.function.intention.name=Create Function {0} -javascript.create.variable.intention.name=Create Variable {0} -javascript.create.constant.intention.name=Create Constant {0} -javascript.declare.variable.intention.name=Insert Var Declaration for {0} -javascript.create.namespace.intention.name=Create Namespace {0} -javascript.create.property.intention.name=Create Field {0} -javascript.create.constant.field.intention.name=Create Constant Field {0} -javascript.create.method.intention.name=Create Method {0} -javascript.create.get.property.intention.name=Create Get Property {0} -javascript.create.set.property.intention.name=Create Set Property {0} -javascript.create.function.intention.family=Create JavaScript Function or Method -javascript.create.variable.intention.family=Create JavaScript Variable Or Property -js.inspection.group.name=JavaScript -js.unresolved.variable.inspection.name=Unresolved JavaScript variable -js.undeclared.variable.inspection.name=Implicitly declared JavaScript variable -js.duplicated.declaration.inspection.name=Duplicated JavaScript declaration -js.unused.local.symbol.inspection.name=Unused JavaScript local symbol -js.unresolved.function.inspection.name=Unresolved JavaScript function -js.deprecated.symbols.inspection.name=Deprecated JavaScript symbol -javascript.parser.message.expected.typename=* or type name expected -javascript.parser.message.expected.name.or.lbrace=Expected package name or { -javascript.parser.message.expected.function.var.class.interface.namespace=Expected function, variable, class, interface or namespace declaration -interface.function.declaration.should.have.no.body=Interface functions declaration should have no body -javascript.parser.message.expected.namespace=Namespace keyword expected -javascript.parser.message.expected.string.literal=String literal expected -javascript.parser.message.expected.xml=xml context keyword expected -javascript.parser.message.expected.equal=expected = -javascript.parser.message.expected.lbrace.or.lbracket={ or [ expected -javascript.parser.message.expected.eof=End of file expected -javascript.deprecated.symbol.used.name.message=Deprecated symbol used, consult docs for better alternative #loc -js.classname.macro.description=jsClassName() -js.methodname.macro.description=jsMethodName() -js.unused.parameter=Unused parameter -js.unused.function.declaration=Unused function declaration -js.unused.local.variable=Unused local variable declaration -js.unused.symbol.remove=Remove unused symbol -javascript.parser.message.expected.identifier=Expected identifier -javascript.parser.message.expected.instanceof=Expected instanceof -javascript.parser.message.expected.value=value expected -javascript.parser.message.expected.identifer.or.value=Identifier or value expected -js.show.overriding.markers.inspection.name=Shows function overriding markers in JavaScript -js.untyped.declaration.inspection.name=Declaration with no type -js.untyped.variable.problem=Variable {0} has no type -js.untyped.function.problem=Function {0} has no return type -js.untyped.declaration.problem.addtype.fix=Add Type to Declaration -invalid.identifier.value=invalid identifier value -javascript.validation.message.this.referenced.from.static.context='this' referenced in static context -javascript.validation.message.super.referenced.without.class.instance.context='super' referenced without class instance context -javascript.validation.message.super.referenced.from.static.context='super' referenced in static context -javascript.validation.message.function.override.without.override.modifier=Method overrides method in superclass {0} without override keyword -javascript.language.term.attribute.value=Attribute value -javascript.validation.message.class.should.be.in.file=Class ''{0}'' should be defined in file ''{1}'' -javascript.validation.message.function.should.be.in.file=Function ''{0}'' should be defined in file ''{1}'' -javascript.validation.message.namespace.should.be.in.file=Namespace ''{0}'' should be defined in file ''{1}'' -javascript.validation.message.variable.should.be.in.file=Variable ''{0}'' should be defined in file ''{1}'' -javascript.validation.message.incorrect.package.name=Package name ''{0}'' does not correspond to file path ''{1}'' -javascript.fix.package.name=Set package name to ''{0}'' -javascript.fix.add.override.modifier=Add override modifier -js.code.style.tab.name=JavaScript / ECMAScript / ActionScript -to.indent.package.statement.children=&Indent package statement children -javascript.formatting.options.panel.title=Formatting options -preview.panel.title=Preview - -javascript.validation.message.interface.members.cannot.have.access.modifiers=Interface members cannot have access modifiers -javascript.template.context.type=Java Sc&ript -flex.import.class=Import Class {0} -flex.import.function=Import Function {0} -interface.should.have.no.variable.declarations=Interface should have no variable declarations -javascript.validation.message.implements.for.interface.not.allowed=Implements list is not allowed for interface -javascript.validation.message.interface.name.expected.here=Interface name expected here -javascript.validation.message.class.name.expected.here=Class name expected here -javascript.validation.message.circular.dependency=Circular dependency -javascript.fix.remove.circular.dependency=Remove circular dependency -javascript.validation.message.more.than.one.externally.visible.symbol=More than one externally visible symbol defined in file -javascript.validation.message.interface.method.not.implemented=Method {0} from interface {1} is not implemented -javascript.fix.remove.externally.visible.symbol=Remove externally visible symbol -javascript.fix.implement.methods=Implement Methods -javascript.parameter=Parameter -javascript.local.variable=Local variable -javascript.global.variable=Global variable -javascript.global.function=Global function -javascript.static.member.function=Static member function -javascript.static.member.variable=Static member variable -javascript.instance.member.variable=Instance member variable -javascript.instance.member.function=Instance member function -javascript.create.class.intention.name=Create Class {0} -javascript.create.interface.intention.name=Create Interface {0} -create.class.dialog.title=Create Class -create.interface.dialog.title=Create Interface -choose.class.title=Choose Class -javascript.fix.remove.override.modifier=Remove override modifier -javascript.validation.message.function.override.for.object.method=Method inherited from Object does not need override -javascript.validation.message.function.override.without.parent.method=Method does not override method from super class -javascript.parser.message.expected.lt=Expected > - -generate.constructor.fields.chooser.title=Choose Fields to Initialize by Constructor -generate.getter.setter.chooser.title=Select Fields to Generate Getters and Setters -generate.to.string.chooser.title=Select Fields to Use in toString function -generate.getter.fields.chooser.title=Select Fields to Generate Getters -generate.setter.fields.chooser.title=Select Fields to Generate Setters -methods.to.implement.chooser.title=Select Methods to Implement -methods.to.override.chooser.title=Select Methods to Override -use.semicolon.to.terminate.statement=Use &semicolon to terminate statements -javascript.validation.unused.import=Unused import -javascript.fix.optimize.imports=Optimize imports -javascript.parser.message.expected.doc.tag.value=Expected doc tag value -javascript.validation.message.incorrect.tag.value=Incorrect Tag Value -javascript.validation.message.incorrect.parameter.name=Incorrect parameter name -javascript.parser.message.expected.doc.tag.name=Expected doc tag name -javascript.invalid.number.of.parameters=Invalid number of parameters, expected {0} -javascript.argument.type.mismatch=Argument type {1} is not assignable to parameter type {0} -javascript.initializer.type.mismatch=Initializer type {1} is not assignable to variable type {0} -javascript.binary.operand.type.mismatch=Binary operation argument type {1} is not assignable to type {0} -javascript.incorrect.variable.type.mismatch=Variable type {1} is not assignable to type {0} -javascript.term.does.not.evaluate.to.function=Method expression is not of Function type -javascript.term.does.not.evaluate.to.function2=Property can not be invoked as function -javascript.term.does.not.evaluate.to.function2.fix=Remove argument list -javascript.assigned.expression.type.mismatch=Assigned expression type {1} is not assignable to type {0} -javascript.returned.expression.type.mismatch=Returned expression type {1} is not assignable to type {0} -javascript.insert.cast.fix=Insert cast -javascript.introduce.constant.error.not.available.in.javascript.code=Introduce Constant is not available in JavaScript code -javascript.introduce.field.error.not.available.in.javascript.code=Introduce Field is not available in JavaScript code -javascript.extract.method.title=Extract Function -javascript.validation.message.function.override.incompatible.access.modifier=Incompatible override, should have ''{0}'' access modifier -javascript.validation.message.function.override.incompatible.signature=Incompatible override, should have signature ''{0}'' -javascript.validation.message.function.override.incompatible.signature2=Incompatible override, should have return type ''{0}'' -javascript.validation.message.interface.method.invalid.access.modifier=Incompatible implementation, should have 'public' access modifier -javascript.validation.message.interface.method.invalid.signature=Incompatible implementation, should have signature ''{0}'' -javascript.validation.message.interface.method.invalid.signature2=Incompatible implementation, should have return type ''{0}'' -javascript.validation.message.duplicated.catch.block=Duplicated catch block #loc -javascript.validation.message.duplicated.catch.block.fix=Remove duplicated catch block -javascript.validation.message.return.value.of.type.is.required=Return value of type {0} is required -javascript.validation.message.constructor.in.mxml.is.not.allowed=Constructor is not allowed for MXML class -javascript.fix.remove.constructor=Remove constructor -javascript.validation.message.package.shouldbe.first.statement=Package should be first statement in file -javascript.metadata=Metadata -javascript.validation.message.file.should.be.under.source.root=Object is located in file out of source root, certain functionality will not be available -javascript.validation.message.unneeded.comma=Unneeded comma -javascript.validation.message.remove.unneeded.comma.fix=Remove unneeded comma -javascript.create.event.handler.intention.name=Create Event Handler {0} -javascript.validation.message.missed.super.constructor.call=Missed superclass's constructor invokation -javascript.fix.create.constructor.invoke.super=Create constructor matching super -javascript.fix.create.invoke.super=Insert super class constructor invokation -javascript.interface.can.not.be.instantiated.message=Interface can not be instantiated -javascript.validation.message.set.method.should.be.void.or.without.type=Return type of a setter definition must be unspecified or void -javascript.validation.message.set.method.should.have.one.parameter=A setter definition must have exactly one parameter -javascript.validation.message.get.method.should.have.no.parameter=A getter definition must have no parameters -javascript.validation.message.get.method.should.be.valid.type=Return type of a getter definition should not be {0} -javascript.validation.message.access.modifier.allowed.only.for.class.members=Access modifier allowed for class members only -javascript.validation.message.namespace.allowed.only.for.class.members=Namespace allowed for class members only -javascript.validation.message.access.modifier.allowed.only.for.package.members=Only public / internal modifiers allowed for package members -javascript.validation.message.use.namespace.reference.or.access.modifier=Use namespace OR access modifier -javascript.fix.remove.access.modifier=Remove access modifier -javascript.fix.remove.namespace.reference=Remove namespace reference -javascript.incorrect.array.type.in.for-in=Array key type should be String -javascript.validation.message.unexpected.type.for.rest.parameter=Rest parameter should have no type -javascript.fix.remove.type.reference=Remove type reference -javascript.validation.message.parameter.is.not.allowed.after.rest.parameter=No parameter is allowed after rest parameter -javascript.fix.remove.parameter=Remove parameter -javascript.fix.remove.initializer=Remove initializer -javascript.validation.message.parameter.should.be.initialized=Parameter should be initialized -javascript.validation.message.rest.parameter.should.not.be.initialized=Rest parameter should not be initialized -javascript.validation.message.nested.classes.are.not.allowed=Nested classes are not allowed -generate.getter.fields.bindable.properties=&Bindable properties -javascript.language.term.package=package -javascript.validation.message.arguments.with.rest.parameter='arguments' object is not available when using rest parameter - -action.JavaScript.File.text=JavaScript File - -this.feature.is.not.supported.by.current.language=''{0}'' is not supported by current language version \ No newline at end of file diff --git a/base-impl/pom.xml b/base-impl/pom.xml index 1aad098f..48887e2e 100644 --- a/base-impl/pom.xml +++ b/base-impl/pom.xml @@ -50,7 +50,7 @@ consulo - https://maven.consulo.io/repository/snapshots/ + https://maven.consulo.dev/repository/snapshots/ true always diff --git a/base-impl/src/main/java/com/intellij/javascript/documentation/JSDocumentationBuilder.java b/base-impl/src/main/java/com/intellij/javascript/documentation/JSDocumentationBuilder.java index c20f888c..2091c800 100644 --- a/base-impl/src/main/java/com/intellij/javascript/documentation/JSDocumentationBuilder.java +++ b/base-impl/src/main/java/com/intellij/javascript/documentation/JSDocumentationBuilder.java @@ -24,764 +24,643 @@ import com.intellij.lang.javascript.index.JSSymbolUtil; import com.intellij.lang.javascript.psi.*; -import consulo.language.editor.CodeInsightBundle; +import consulo.annotation.access.RequiredReadAction; +import consulo.language.editor.localize.CodeInsightLocalize; import consulo.language.psi.PsiElement; import consulo.util.io.URLUtil; import consulo.util.lang.StringUtil; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; import org.jetbrains.annotations.NonNls; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.LinkedHashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; -class JSDocumentationBuilder implements JSDocumentationProcessor -{ - private static class SymbolInfo - { - String visibility; - StringBuilder description = new StringBuilder(); - String type; - String access; - boolean deprecated; - String namespace; - } - - private static class MethodInfo extends SymbolInfo - { - String methodType; - Map parameterInfoMap = new LinkedHashMap(); - int parameterCount = -1; - SymbolInfo returnInfo = new SymbolInfo(); - } - - private static class ParameterInfo extends SymbolInfo - { - boolean optional; - String initialValue; - } - - private boolean myOptionalParametersStarted; - private boolean myEventsStarted; - private SymbolInfo generationInfo; - private ParameterInfo currentParameterInfo; - private - @NonNls - StringBuilder result; - - private JSFunction function; - private JSNamedElement namedItem; - private final PsiElement myElement; - private PsiElement contextElement; - - private int myNewLinesPendingCount; - private boolean seenPre; - private boolean seenSeeAlso; - @NonNls - private static final String BR_DELIMITER = "
\n"; - - JSDocumentationBuilder(PsiElement element, PsiElement _contextElement) - { - myElement = element; - contextElement = _contextElement; - final PsiElement parent = element.getParent(); - if(element instanceof JSVariable) - { - JSExpression initializer = ((JSVariable) element).getInitializer(); - if(initializer instanceof JSFunctionExpression) - { - element = initializer; - } - } - - if(element instanceof JSFunction) - { - function = (JSFunction) element; - generationInfo = new MethodInfo(); - - if(parent instanceof JSClass) - { - generationInfo.namespace = ((JSClass) parent).getQualifiedName(); - } - - for(JSParameter parameter : function.getParameterList().getParameters()) - { - final ParameterInfo paramInfo = new ParameterInfo(); - ((MethodInfo) generationInfo).parameterInfoMap.put(parameter.getName(), paramInfo); - paramInfo.type = parameter.getTypeString(); - paramInfo.initialValue = parameter.getInitializerText(); - } - - ((MethodInfo) generationInfo).returnInfo.type = function.getReturnTypeString(); - } - else if(element instanceof JSNamedElement) - { - namedItem = (JSNamedElement) element; - generationInfo = new SymbolInfo(); - - if(namedItem instanceof JSClass) - { - if(parent instanceof JSPackageStatement) - { - generationInfo.namespace = ((JSPackageStatement) parent).getQualifiedName(); - } - } - } - else - { - generationInfo = new SymbolInfo(); - } - - result = generationInfo.description; - } - - private void doAppend(final @NonNls String str) - { - while(myNewLinesPendingCount > 0) - { - result.append(seenPre ? "\n" : BR_DELIMITER); - --myNewLinesPendingCount; - } - - result.append(str); - } - - private static final Pattern ourTagStartPattern = Pattern.compile("<(/)?(\\w+)"); - - @Override - public boolean needsPlainCommentData() - { - return true; - } - - @Override - public boolean onCommentLine(@Nonnull String line) - { - String trimmedLine = line.trim(); - boolean parametersStarted = false; - boolean parametersEnded = false; - - if(generationInfo instanceof MethodInfo) - { - final MethodInfo methodInfo = (MethodInfo) generationInfo; - parametersEnded = methodInfo.parameterCount + 1 == methodInfo.parameterInfoMap.size(); - parametersStarted = methodInfo.parameterCount >= 0; - } - - if(trimmedLine.length() == 0) - { - if(result.length() == 0) - { - return true; - } - - final int maxSubsequentBr = parametersStarted && !parametersEnded ? 0 : 2; - if(myNewLinesPendingCount < maxSubsequentBr) - { - ++myNewLinesPendingCount; - } - - if(parametersEnded && ((MethodInfo) generationInfo).returnInfo.description != result) - { - setResult(generationInfo.description); - myNewLinesPendingCount = 1; - } - - return true; - } - - if(line.indexOf("
") != -1)
-		{
-			seenPre = true;
-		}
-
-		if(!seenPre && line.indexOf('<') != -1)
-		{
-			Matcher matcher = ourTagStartPattern.matcher(line);
-			int offset = 0;
-
-			while(matcher.find())
-			{
-				final boolean isTagEnd = matcher.start(1) != matcher.end(1);
-				final String s = matcher.group(2);
-				// tags that do not need escaping
-				if(tagNameThatDoNotNeedEscaping(s))
-				{
-					continue;
-				}
-				line = line.substring(0, offset + matcher.start(0)) + "<" + (isTagEnd ? "/" : "") + s + line.substring(offset + matcher.end(0));
-				offset += 3;
-			}
-		}
-
-		doAppend(line);
-		myNewLinesPendingCount = parametersStarted && !parametersEnded ? 0 : 1;
-
-		if(line.indexOf("
") != -1) - { - seenPre = false; - } - return true; - } - - private static boolean tagNameThatDoNotNeedEscaping(final @NonNls String s) - { - return s.equalsIgnoreCase("p") || s.equalsIgnoreCase("i") || s.equalsIgnoreCase("code") || s.equalsIgnoreCase("ul") || - s.equalsIgnoreCase("li") || s.equalsIgnoreCase("b"); - } - - private void setResult(final StringBuilder builder) - { - result = builder; - myNewLinesPendingCount = 0; - } - - @Override - public boolean onPatternMatch(@Nonnull MetaDocType metaDocType, @Nullable String matchName, @Nullable String matchValue, - @Nullable String remainingLineContent, @Nonnull final String line, final String patternMatched) - { - if(metaDocType == MetaDocType.DEFAULT) - { - boolean color = remainingLineContent.startsWith("0x") && remainingLineContent.length() == 8; - remainingLineContent = appendCurrentOrDefaultValue(remainingLineContent.substring(color ? 2 : 0), color, true); - } - - if(metaDocType == MetaDocType.SEE) - { - if(!seenSeeAlso) - { - seenSeeAlso = true; - result.append("
See also:
"); - } - else - { - result.append("
"); - } - if(URLUtil.isAbsoluteURL(remainingLineContent)) - { - result.append("").append(remainingLineContent).append(""); - } - else if(StringUtil.containsAnyChar(remainingLineContent, JSDocumentationProvider.SEE_PLAIN_TEXT_CHARS)) - { - result.append(StringUtil.stripQuotesAroundValue(remainingLineContent)); - } - else - { - JSDocumentationUtils.appendHyperLinkToElement(null, getSeeAlsoLink(remainingLineContent), result, remainingLineContent, null); - return true; - } - } - else if(seenSeeAlso) - { - seenSeeAlso = false; - result.append("
"); - } - - if(metaDocType == MetaDocType.EVENT) - { - if(myEventsStarted) - { - result.append("
"); - } - - result.append("\n"); - if(!myEventsStarted) - { - myEventsStarted = true; - result.append("
Events:
"); - } - result.append("Event " + matchName + " -" + remainingLineContent); - return true; - } - else if(myEventsStarted) - { - myEventsStarted = false; - result.append("
"); - } - - if(metaDocType == MetaDocType.NOTE) - { - result.append("\n

Note: " + remainingLineContent); - return true; - } - - if(metaDocType == MetaDocType.OPTIONAL_PARAMETERS) - { - myOptionalParametersStarted = true; - if(currentParameterInfo != null) - { - currentParameterInfo.optional = true; - } - if(remainingLineContent != null) - { - onCommentLine(remainingLineContent); - } - return true; - } - - if(metaDocType == MetaDocType.DEPRECATED) - { - generationInfo.deprecated = true; - if(remainingLineContent != null) - { - onCommentLine(remainingLineContent); - } - return true; - } - - if(metaDocType == MetaDocType.DESCRIPTION) - { - generationInfo.description.append(remainingLineContent); - return true; - } - - if(metaDocType == MetaDocType.PRIVATE || - metaDocType == MetaDocType.PUBLIC || - metaDocType == MetaDocType.PROTECTED || - metaDocType == MetaDocType.STATIC) - { - final String s = metaDocType.name().toLowerCase(); - if(generationInfo.visibility == null) - { - generationInfo.visibility = s; - } - else - { - generationInfo.visibility += ", " + s; - } - return true; - } - else if(metaDocType == MetaDocType.TYPE) - { - generationInfo.type = matchName; - return true; - } - else if(metaDocType == MetaDocType.FINAL) - { - generationInfo.access = "final"; - return true; - } - else if(metaDocType == MetaDocType.REQUIRES) - { - //onCommentLine("Requires:"+matchName); - return true; - } - else if(metaDocType == MetaDocType.NAMESPACE) - { - generationInfo.namespace = matchName; - return true; - } - - if(function != null) - { - final MethodInfo methodGenerationInfo = ((MethodInfo) generationInfo); - - if(metaDocType == MetaDocType.CONSTRUCTOR) - { - methodGenerationInfo.methodType = "contructor"; - } - else if(metaDocType == MetaDocType.METHOD) - { - methodGenerationInfo.methodType = "method"; - } - else if(metaDocType == MetaDocType.PARAMETER) - { - ParameterInfo info = methodGenerationInfo.parameterInfoMap.get(matchName); - - if(info != null) - { - int index = 0; - for(SymbolInfo _info : methodGenerationInfo.parameterInfoMap.values()) - { - if(info == _info) - { - break; - } - ++index; - } - - methodGenerationInfo.parameterCount = index; - } - else if(patternMatched.indexOf('@') != -1) - { - // wrong doc (without parameter name) - methodGenerationInfo.parameterCount++; - int index = 0; - - for(SymbolInfo _info : methodGenerationInfo.parameterInfoMap.values()) - { - if(index == methodGenerationInfo.parameterCount) - { - info = (ParameterInfo) _info; - break; - } - ++index; - } - } - - if(info != null) - { - if(matchValue != null) - { - info.type = matchValue; - } - setResult(info.description); - info.description.append(remainingLineContent); - info.optional = myOptionalParametersStarted; - currentParameterInfo = info; - } - else - { - onCommentLine(line); - } - } - else if(metaDocType == MetaDocType.RETURN) - { - result = methodGenerationInfo.returnInfo.description; - if(matchName != null) - { - methodGenerationInfo.returnInfo.type = matchName; - } - if(matchValue != null) - { - methodGenerationInfo.returnInfo.description.append(matchValue); - } - if(remainingLineContent != null) - { - methodGenerationInfo.returnInfo.description.append(remainingLineContent); - } - } - } - return true; - } - - private String getSeeAlsoLink(String remainingLineContent) - { - if(URLUtil.isAbsoluteURL(remainingLineContent)) - { - return remainingLineContent; - } - - if(!remainingLineContent.contains(".") && !remainingLineContent.startsWith("#")) - { - // first try to find class in the same package, then in default one - JSQualifiedNamedElement qualifiedElement = JSDocumentationProvider.findParentQualifiedElement(myElement); - if(qualifiedElement != null) - { - String qname = qualifiedElement.getQualifiedName(); - String aPackage = qname.contains(".") ? qname.substring(0, qname.lastIndexOf('.') + 1) : ""; - String resolvedLink = JSDocumentationProvider.getSeeAlsoLinkResolved(myElement, aPackage + remainingLineContent); - if(resolvedLink != null) - { - return resolvedLink; - } - } - } - - String resolvedLink = JSDocumentationProvider.getSeeAlsoLinkResolved(myElement, remainingLineContent); - return resolvedLink != null ? resolvedLink : remainingLineContent; - } - - private String appendCurrentOrDefaultValue(String remainingLineContent, boolean color, boolean defaultValue) - { - if(color) - { - remainingLineContent = "   "; - } - else - { - remainingLineContent = "" + remainingLineContent + ""; - } - result.append("
\n").append(defaultValue ? "Default" : "Current").append(" value:").append(remainingLineContent); - return remainingLineContent; - } - - String getDoc() - { - if(seenSeeAlso) - { - seenSeeAlso = false; - result.append("

"); - } - result = new StringBuilder(); - - if(function != null) - { - startFunction(function); - result.append(generationInfo.description.toString()); - - result.append("\n
"); - final MethodInfo methodInfo = ((MethodInfo) generationInfo); - - if(methodInfo.parameterInfoMap.size() > 0) - { - result.append("
"); - result.append(CodeInsightBundle.message("javadoc.parameters")); - result.append("
"); - } - - for(Map.Entry parameterInfo : methodInfo.parameterInfoMap.entrySet()) - { - result.append("
"); - result.append(parameterInfo.getKey()); - result.append(""); - - if(parameterInfo.getValue().description.length() > 0) - { - result.append(" - "); - result.append(parameterInfo.getValue().description.toString()); - } - result.append("
\n"); - } - - if(methodInfo.returnInfo.description.length() > 0) - { - result.append("
"); - result.append(CodeInsightBundle.message("javadoc.returns")); - result.append("
"); - - result.append("
"); - result.append(methodInfo.returnInfo.description.toString()); - result.append("
"); - } - - result.append("
"); - } - else - { - if(namedItem != null) - { - startNamedItem(namedItem.getName()); - endNamedItem(); - } - - result.append(generationInfo.description.toString()); - } - - if(contextElement != null) - { - final String text = contextElement.getText(); - if(text.startsWith("#") && text.length() == 7) - { - appendCurrentOrDefaultValue(text.substring(1), true, false); - } - } - - return result.toString(); - } - - public String getParameterDoc(final String name) - { - if(function != null) - { - final MethodInfo methodInfo = ((MethodInfo) generationInfo); - final ParameterInfo parameterInfo = methodInfo.parameterInfoMap.get(name); - - if(parameterInfo != null && parameterInfo.description.length() > 0) - { - result = new StringBuilder(); - startNamedItem(name, parameterInfo); - endNamedItem(); - result.append(parameterInfo.description.toString()); - return result.toString(); - } - } - - return null; - } - - - private void startFunction(JSFunction function) - { - @NonNls String functionName = function.getName(); - final PsiElement parent = function.getParent(); - - if(parent instanceof JSAssignmentExpression) - { - final String unqualifiedFunctionName = functionName; - JSExpression expression = ((JSDefinitionExpression) ((JSAssignmentExpression) parent).getLOperand()).getExpression(); - functionName = null; - - if(expression instanceof JSReferenceExpression) - { - final JSExpression qualifierExpression = ((JSReferenceExpression) expression).getQualifier(); - if(qualifierExpression instanceof JSReferenceExpression) - { - expression = JSSymbolUtil.findReferenceExpressionUsedForClassExtending((JSReferenceExpression) qualifierExpression); - functionName = expression.getText() + "." + unqualifiedFunctionName; - } - } - - if(functionName == null) - { - functionName = expression.getText(); - } - if(generationInfo.namespace != null && functionName.equals(generationInfo.namespace + "." + unqualifiedFunctionName)) - { - generationInfo.namespace = null; - } - } - - if(functionName == null) - { - functionName = ""; - } - - int indent = startNamedItem(functionName); - - result.append("("); - int resultLength = result.length(); - - for(Map.Entry parameterInfo : ((MethodInfo) generationInfo).parameterInfoMap.entrySet()) - { - - if(result.length() != resultLength) - { - result.append(",\n"); - for(int i = 0; i < indent; ++i) - { - result.append(" "); - } - } - result.append(" "); - - String parameterType = parameterInfo.getValue().type; - if(parameterType != null) - { - boolean optional = parameterInfo.getValue().optional; - - if(parameterType.endsWith("?")) - { - optional = true; - parameterType = parameterType.substring(0, parameterType.length() - 1); - } - - - result.append("[ "); - result.append(parameterType); - if(optional) - { - result.append(", optional"); - } - result.append(" ] "); - } - - result.append(parameterInfo.getKey()); - - final String initialValue = parameterInfo.getValue().initialValue; - if(initialValue != null) - { - result.append(" = ").append(initialValue); - } - } - - result.append(" )\n"); - endNamedItem(); - } - - private void endNamedItem() - { - result.append(""); - } - - private int startNamedItem(final String functionName) - { - return startNamedItem(functionName, generationInfo); - } - - private int startNamedItem(final String functionName, SymbolInfo generationInfo) - { - result.append("
");
-
-		StringBuffer options = new StringBuffer();
-		int offset = result.length();
-
-		if(generationInfo instanceof MethodInfo)
-		{
-			addVisibilityAndAccess(options, generationInfo);
-			String returnType = ((MethodInfo) generationInfo).returnInfo.type;
-			if(returnType != null)
-			{
-				if(options.length() > 0)
-				{
-					options.append(", ");
-				}
-				options.append(returnType);
-			}
-
-			final String type = ((MethodInfo) generationInfo).methodType;
-			if(type != null)
-			{
-				if(options.length() > 0)
-				{
-					options.append(", ");
-				}
-				options.append(type);
-			}
-		}
-		else
-		{
-			if(generationInfo.type != null)
-			{
-				if(options.length() > 0)
-				{
-					options.append(", ");
-				}
-				options.append(generationInfo.type);
-			}
-
-			addVisibilityAndAccess(options, generationInfo);
-		}
-
-		if(options.length() > 0)
-		{
-			result.append("[ ");
-			result.append(options.toString());
-			result.append(" ] ");
-		}
-
-		offset = result.length() - offset + functionName.length() + 1;
-
-		result.append("");
-		if(generationInfo.namespace != null && generationInfo.namespace.length() > 0)
-		{
-			result.append(generationInfo.namespace).append('.');
-		}
-		result.append(functionName);
-		result.append("");
-
-		return offset;
-	}
-
-	private void addVisibilityAndAccess(final StringBuffer options, SymbolInfo generationInfo)
-	{
-		if(generationInfo.visibility != null)
-		{
-			if(options.length() > 0)
-			{
-				options.append(", ");
-			}
-			options.append(generationInfo.visibility);
-		}
-
-		if(generationInfo.access != null)
-		{
-			if(options.length() > 0)
-			{
-				options.append(", ");
-			}
-			options.append(generationInfo.access);
-		}
-
-		if(generationInfo.deprecated)
-		{
-			if(options.length() > 0)
-			{
-				options.append(", ");
-			}
-			options.append("deprecated");
-		}
-	}
+class JSDocumentationBuilder implements JSDocumentationProcessor {
+    private static class SymbolInfo {
+        String visibility;
+        StringBuilder description = new StringBuilder();
+        String type;
+        String access;
+        boolean deprecated;
+        String namespace;
+    }
+
+    private static class MethodInfo extends SymbolInfo {
+        String methodType;
+        Map parameterInfoMap = new LinkedHashMap();
+        int parameterCount = -1;
+        SymbolInfo returnInfo = new SymbolInfo();
+    }
+
+    private static class ParameterInfo extends SymbolInfo {
+        boolean optional;
+        String initialValue;
+    }
+
+    private boolean myOptionalParametersStarted;
+    private boolean myEventsStarted;
+    private SymbolInfo generationInfo;
+    private ParameterInfo currentParameterInfo;
+    private
+    @NonNls
+    StringBuilder result;
+
+    private JSFunction function;
+    private JSNamedElement namedItem;
+    private final PsiElement myElement;
+    private PsiElement contextElement;
+
+    private int myNewLinesPendingCount;
+    private boolean seenPre;
+    private boolean seenSeeAlso;
+    private static final String BR_DELIMITER = "
\n"; + + @RequiredReadAction + JSDocumentationBuilder(PsiElement element, PsiElement _contextElement) { + myElement = element; + contextElement = _contextElement; + PsiElement parent = element.getParent(); + if (element instanceof JSVariable variable + && variable.getInitializer() instanceof JSFunctionExpression functionExpression) { + element = functionExpression; + } + + if (element instanceof JSFunction func) { + function = func; + generationInfo = new MethodInfo(); + + if (parent instanceof JSClass jsClass) { + generationInfo.namespace = jsClass.getQualifiedName(); + } + + for (JSParameter parameter : function.getParameterList().getParameters()) { + ParameterInfo paramInfo = new ParameterInfo(); + ((MethodInfo)generationInfo).parameterInfoMap.put(parameter.getName(), paramInfo); + paramInfo.type = parameter.getTypeString(); + paramInfo.initialValue = parameter.getInitializerText(); + } + + ((MethodInfo)generationInfo).returnInfo.type = function.getReturnTypeString(); + } + else if (element instanceof JSNamedElement namedElement) { + namedItem = namedElement; + generationInfo = new SymbolInfo(); + + if (namedItem instanceof JSClass && parent instanceof JSPackageStatement packageStatement) { + generationInfo.namespace = packageStatement.getQualifiedName(); + } + } + else { + generationInfo = new SymbolInfo(); + } + + result = generationInfo.description; + } + + private void doAppend(String str) { + while (myNewLinesPendingCount > 0) { + result.append(seenPre ? "\n" : BR_DELIMITER); + --myNewLinesPendingCount; + } + + result.append(str); + } + + private static final Pattern ourTagStartPattern = Pattern.compile("<(/)?(\\w+)"); + + @Override + public boolean needsPlainCommentData() { + return true; + } + + @Override + public boolean onCommentLine(@Nonnull String line) { + String trimmedLine = line.trim(); + boolean parametersStarted = false; + boolean parametersEnded = false; + + if (generationInfo instanceof MethodInfo methodInfo) { + parametersEnded = methodInfo.parameterCount + 1 == methodInfo.parameterInfoMap.size(); + parametersStarted = methodInfo.parameterCount >= 0; + } + + if (trimmedLine.length() == 0) { + if (result.length() == 0) { + return true; + } + + int maxSubsequentBr = parametersStarted && !parametersEnded ? 0 : 2; + if (myNewLinesPendingCount < maxSubsequentBr) { + ++myNewLinesPendingCount; + } + + if (parametersEnded && ((MethodInfo)generationInfo).returnInfo.description != result) { + setResult(generationInfo.description); + myNewLinesPendingCount = 1; + } + + return true; + } + + if (line.contains("
")) {
+            seenPre = true;
+        }
+
+        if (!seenPre && line.indexOf('<') != -1) {
+            Matcher matcher = ourTagStartPattern.matcher(line);
+            int offset = 0;
+
+            while (matcher.find()) {
+                boolean isTagEnd = matcher.start(1) != matcher.end(1);
+                String s = matcher.group(2);
+                // tags that do not need escaping
+                if (tagNameThatDoNotNeedEscaping(s)) {
+                    continue;
+                }
+                line = line.substring(0, offset + matcher.start(0)) + "<" + (isTagEnd ? "/" : "") + s +
+                    line.substring(offset + matcher.end(0));
+                offset += 3;
+            }
+        }
+
+        doAppend(line);
+        myNewLinesPendingCount = parametersStarted && !parametersEnded ? 0 : 1;
+
+        if (line.contains("
")) { + seenPre = false; + } + return true; + } + + private static boolean tagNameThatDoNotNeedEscaping(@NonNls String s) { + return s.equalsIgnoreCase("p") || s.equalsIgnoreCase("i") || s.equalsIgnoreCase("code") + || s.equalsIgnoreCase("ul") || s.equalsIgnoreCase("li") || s.equalsIgnoreCase("b"); + } + + private void setResult(StringBuilder builder) { + result = builder; + myNewLinesPendingCount = 0; + } + + @Override + public boolean onPatternMatch( + @Nonnull MetaDocType metaDocType, + @Nullable String matchName, + @Nullable String matchValue, + @Nullable String remainingLineContent, + @Nonnull String line, + String patternMatched + ) { + if (metaDocType == MetaDocType.DEFAULT) { + boolean color = remainingLineContent.startsWith("0x") && remainingLineContent.length() == 8; + remainingLineContent = appendCurrentOrDefaultValue(remainingLineContent.substring(color ? 2 : 0), color, true); + } + + if (metaDocType == MetaDocType.SEE) { + if (!seenSeeAlso) { + seenSeeAlso = true; + result.append("
See also:
"); + } + else { + result.append("
"); + } + if (URLUtil.isAbsoluteURL(remainingLineContent)) { + result.append("").append(remainingLineContent).append(""); + } + else if (StringUtil.containsAnyChar(remainingLineContent, JSDocumentationProvider.SEE_PLAIN_TEXT_CHARS)) { + result.append(StringUtil.stripQuotesAroundValue(remainingLineContent)); + } + else { + JSDocumentationUtils.appendHyperLinkToElement( + null, + getSeeAlsoLink(remainingLineContent), + result, + remainingLineContent, + null + ); + return true; + } + } + else if (seenSeeAlso) { + seenSeeAlso = false; + result.append("
"); + } + + if (metaDocType == MetaDocType.EVENT) { + if (myEventsStarted) { + result.append("
"); + } + + result.append("\n"); + if (!myEventsStarted) { + myEventsStarted = true; + result.append("
Events:
"); + } + result.append("Event ").append(matchName).append(" -").append(remainingLineContent); + return true; + } + else if (myEventsStarted) { + myEventsStarted = false; + result.append("
"); + } + + if (metaDocType == MetaDocType.NOTE) { + result.append("\n

Note: ").append(remainingLineContent); + return true; + } + + if (metaDocType == MetaDocType.OPTIONAL_PARAMETERS) { + myOptionalParametersStarted = true; + if (currentParameterInfo != null) { + currentParameterInfo.optional = true; + } + if (remainingLineContent != null) { + onCommentLine(remainingLineContent); + } + return true; + } + + if (metaDocType == MetaDocType.DEPRECATED) { + generationInfo.deprecated = true; + if (remainingLineContent != null) { + onCommentLine(remainingLineContent); + } + return true; + } + + if (metaDocType == MetaDocType.DESCRIPTION) { + generationInfo.description.append(remainingLineContent); + return true; + } + + if (metaDocType == MetaDocType.PRIVATE || + metaDocType == MetaDocType.PUBLIC || + metaDocType == MetaDocType.PROTECTED || + metaDocType == MetaDocType.STATIC) { + String s = metaDocType.name().toLowerCase(); + if (generationInfo.visibility == null) { + generationInfo.visibility = s; + } + else { + generationInfo.visibility += ", " + s; + } + return true; + } + else if (metaDocType == MetaDocType.TYPE) { + generationInfo.type = matchName; + return true; + } + else if (metaDocType == MetaDocType.FINAL) { + generationInfo.access = "final"; + return true; + } + else if (metaDocType == MetaDocType.REQUIRES) { + //onCommentLine("Requires:"+matchName); + return true; + } + else if (metaDocType == MetaDocType.NAMESPACE) { + generationInfo.namespace = matchName; + return true; + } + + if (function != null) { + MethodInfo methodGenerationInfo = ((MethodInfo)generationInfo); + + if (metaDocType == MetaDocType.CONSTRUCTOR) { + methodGenerationInfo.methodType = "contructor"; + } + else if (metaDocType == MetaDocType.METHOD) { + methodGenerationInfo.methodType = "method"; + } + else if (metaDocType == MetaDocType.PARAMETER) { + ParameterInfo info = methodGenerationInfo.parameterInfoMap.get(matchName); + + if (info != null) { + int index = 0; + for (SymbolInfo _info : methodGenerationInfo.parameterInfoMap.values()) { + if (info == _info) { + break; + } + ++index; + } + + methodGenerationInfo.parameterCount = index; + } + else if (patternMatched.indexOf('@') != -1) { + // wrong doc (without parameter name) + methodGenerationInfo.parameterCount++; + int index = 0; + + for (SymbolInfo _info : methodGenerationInfo.parameterInfoMap.values()) { + if (index == methodGenerationInfo.parameterCount) { + info = (ParameterInfo)_info; + break; + } + ++index; + } + } + + if (info != null) { + if (matchValue != null) { + info.type = matchValue; + } + setResult(info.description); + info.description.append(remainingLineContent); + info.optional = myOptionalParametersStarted; + currentParameterInfo = info; + } + else { + onCommentLine(line); + } + } + else if (metaDocType == MetaDocType.RETURN) { + result = methodGenerationInfo.returnInfo.description; + if (matchName != null) { + methodGenerationInfo.returnInfo.type = matchName; + } + if (matchValue != null) { + methodGenerationInfo.returnInfo.description.append(matchValue); + } + if (remainingLineContent != null) { + methodGenerationInfo.returnInfo.description.append(remainingLineContent); + } + } + } + return true; + } + + @RequiredReadAction + private String getSeeAlsoLink(String remainingLineContent) { + if (URLUtil.isAbsoluteURL(remainingLineContent)) { + return remainingLineContent; + } + + if (!remainingLineContent.contains(".") && !remainingLineContent.startsWith("#")) { + // first try to find class in the same package, then in default one + JSQualifiedNamedElement qualifiedElement = JSDocumentationProvider.findParentQualifiedElement(myElement); + if (qualifiedElement != null) { + String qname = qualifiedElement.getQualifiedName(); + String aPackage = qname.contains(".") ? qname.substring(0, qname.lastIndexOf('.') + 1) : ""; + String resolvedLink = JSDocumentationProvider.getSeeAlsoLinkResolved(myElement, aPackage + remainingLineContent); + if (resolvedLink != null) { + return resolvedLink; + } + } + } + + String resolvedLink = JSDocumentationProvider.getSeeAlsoLinkResolved(myElement, remainingLineContent); + return resolvedLink != null ? resolvedLink : remainingLineContent; + } + + private String appendCurrentOrDefaultValue(String remainingLineContent, boolean color, boolean defaultValue) { + if (color) { + remainingLineContent = "   "; + } + else { + remainingLineContent = "" + remainingLineContent + ""; + } + result.append("
\n").append(defaultValue ? "Default" : "Current").append(" value:").append(remainingLineContent); + return remainingLineContent; + } + + @RequiredReadAction + String getDoc() { + if (seenSeeAlso) { + seenSeeAlso = false; + result.append("

"); + } + result = new StringBuilder(); + + if (function != null) { + startFunction(function); + result.append(generationInfo.description.toString()); + + result.append("\n
"); + MethodInfo methodInfo = ((MethodInfo)generationInfo); + + if (methodInfo.parameterInfoMap.size() > 0) { + result.append("
"); + result.append(CodeInsightLocalize.javadocParameters().get()); + result.append("
"); + } + + for (Map.Entry parameterInfo : methodInfo.parameterInfoMap.entrySet()) { + result.append("
"); + result.append(parameterInfo.getKey()); + result.append(""); + + if (parameterInfo.getValue().description.length() > 0) { + result.append(" - "); + result.append(parameterInfo.getValue().description.toString()); + } + result.append("
\n"); + } + + if (methodInfo.returnInfo.description.length() > 0) { + result.append("
"); + result.append(CodeInsightLocalize.javadocReturns().get()); + result.append("
"); + + result.append("
"); + result.append(methodInfo.returnInfo.description.toString()); + result.append("
"); + } + + result.append("
"); + } + else { + if (namedItem != null) { + startNamedItem(namedItem.getName()); + endNamedItem(); + } + + result.append(generationInfo.description.toString()); + } + + if (contextElement != null) { + String text = contextElement.getText(); + if (text.startsWith("#") && text.length() == 7) { + appendCurrentOrDefaultValue(text.substring(1), true, false); + } + } + + return result.toString(); + } + + public String getParameterDoc(String name) { + if (function != null) { + MethodInfo methodInfo = ((MethodInfo)generationInfo); + ParameterInfo parameterInfo = methodInfo.parameterInfoMap.get(name); + + if (parameterInfo != null && parameterInfo.description.length() > 0) { + result = new StringBuilder(); + startNamedItem(name, parameterInfo); + endNamedItem(); + result.append(parameterInfo.description.toString()); + return result.toString(); + } + } + + return null; + } + + @RequiredReadAction + private void startFunction(JSFunction function) { + String functionName = function.getName(); + PsiElement parent = function.getParent(); + + if (parent instanceof JSAssignmentExpression assignment) { + String unqualifiedFunctionName = functionName; + JSExpression expression = ((JSDefinitionExpression)assignment.getLOperand()).getExpression(); + functionName = null; + + if (expression instanceof JSReferenceExpression refExpr + && refExpr.getQualifier() instanceof JSReferenceExpression qualifierRefExpr) { + expression = JSSymbolUtil.findReferenceExpressionUsedForClassExtending(qualifierRefExpr); + functionName = expression.getText() + "." + unqualifiedFunctionName; + } + + if (functionName == null) { + functionName = expression.getText(); + } + + if (generationInfo.namespace != null && functionName.equals(generationInfo.namespace + "." + unqualifiedFunctionName)) { + generationInfo.namespace = null; + } + } + + if (functionName == null) { + functionName = ""; + } + + int indent = startNamedItem(functionName); + + result.append("("); + int resultLength = result.length(); + + for (Map.Entry parameterInfo : ((MethodInfo)generationInfo).parameterInfoMap.entrySet()) { + if (result.length() != resultLength) { + result.append(",\n"); + for (int i = 0; i < indent; ++i) { + result.append(" "); + } + } + result.append(" "); + + String parameterType = parameterInfo.getValue().type; + if (parameterType != null) { + boolean optional = parameterInfo.getValue().optional; + + if (parameterType.endsWith("?")) { + optional = true; + parameterType = parameterType.substring(0, parameterType.length() - 1); + } + + + result.append("[ "); + result.append(parameterType); + if (optional) { + result.append(", optional"); + } + result.append(" ] "); + } + + result.append(parameterInfo.getKey()); + + String initialValue = parameterInfo.getValue().initialValue; + if (initialValue != null) { + result.append(" = ").append(initialValue); + } + } + + result.append(" )\n"); + endNamedItem(); + } + + private void endNamedItem() { + result.append("
"); + } + + private int startNamedItem(String functionName) { + return startNamedItem(functionName, generationInfo); + } + + private int startNamedItem(String functionName, SymbolInfo generationInfo) { + result.append("
");
+
+        StringBuffer options = new StringBuffer();
+        int offset = result.length();
+
+        if (generationInfo instanceof MethodInfo) {
+            addVisibilityAndAccess(options, generationInfo);
+            String returnType = ((MethodInfo)generationInfo).returnInfo.type;
+            if (returnType != null) {
+                if (options.length() > 0) {
+                    options.append(", ");
+                }
+                options.append(returnType);
+            }
+
+            String type = ((MethodInfo)generationInfo).methodType;
+            if (type != null) {
+                if (options.length() > 0) {
+                    options.append(", ");
+                }
+                options.append(type);
+            }
+        }
+        else {
+            if (generationInfo.type != null) {
+                if (options.length() > 0) {
+                    options.append(", ");
+                }
+                options.append(generationInfo.type);
+            }
+
+            addVisibilityAndAccess(options, generationInfo);
+        }
+
+        if (options.length() > 0) {
+            result.append("[ ");
+            result.append(options.toString());
+            result.append(" ] ");
+        }
+
+        offset = result.length() - offset + functionName.length() + 1;
+
+        result.append("");
+        if (generationInfo.namespace != null && generationInfo.namespace.length() > 0) {
+            result.append(generationInfo.namespace).append('.');
+        }
+        result.append(functionName);
+        result.append("");
+
+        return offset;
+    }
+
+    private void addVisibilityAndAccess(StringBuffer options, SymbolInfo generationInfo) {
+        if (generationInfo.visibility != null) {
+            if (options.length() > 0) {
+                options.append(", ");
+            }
+            options.append(generationInfo.visibility);
+        }
+
+        if (generationInfo.access != null) {
+            if (options.length() > 0) {
+                options.append(", ");
+            }
+            options.append(generationInfo.access);
+        }
+
+        if (generationInfo.deprecated) {
+            if (options.length() > 0) {
+                options.append(", ");
+            }
+            options.append("deprecated");
+        }
+    }
 }
diff --git a/base-impl/src/main/java/com/intellij/javascript/documentation/JSDocumentationProcessor.java b/base-impl/src/main/java/com/intellij/javascript/documentation/JSDocumentationProcessor.java
index 31b81845..c79a645b 100644
--- a/base-impl/src/main/java/com/intellij/javascript/documentation/JSDocumentationProcessor.java
+++ b/base-impl/src/main/java/com/intellij/javascript/documentation/JSDocumentationProcessor.java
@@ -22,21 +22,45 @@
  */
 package com.intellij.javascript.documentation;
 
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
 
-public interface JSDocumentationProcessor
-{
-	enum MetaDocType
-	{
-		RETURN, CONSTRUCTOR, METHOD, PARAMETER, PRIVATE, PUBLIC, PROTECTED, STATIC, DESCRIPTION, FINAL, REQUIRES, TYPE, NAMESPACE,
-		OPTIONAL_PARAMETERS, EVENT, NOTE, DEPRECATED, SEE, DEFAULT, EXTENDS, CLASS, FIELD
-	}
+public interface JSDocumentationProcessor {
+    enum MetaDocType {
+        RETURN,
+        CONSTRUCTOR,
+        METHOD,
+        PARAMETER,
+        PRIVATE,
+        PUBLIC,
+        PROTECTED,
+        STATIC,
+        DESCRIPTION,
+        FINAL,
+        REQUIRES,
+        TYPE,
+        NAMESPACE,
+        OPTIONAL_PARAMETERS,
+        EVENT,
+        NOTE,
+        DEPRECATED,
+        SEE,
+        DEFAULT,
+        EXTENDS,
+        CLASS,
+        FIELD
+    }
 
-	boolean needsPlainCommentData();
+    boolean needsPlainCommentData();
 
-	boolean onCommentLine(@Nonnull String line);
+    boolean onCommentLine(@Nonnull String line);
 
-	boolean onPatternMatch(@Nonnull MetaDocType type, @Nullable String matchName, @Nullable final String matchValue,
-			@Nullable String remainingLineContent, @Nonnull final String line, final String patternMatched);
+    boolean onPatternMatch(
+        @Nonnull MetaDocType type,
+        @Nullable String matchName,
+        @Nullable String matchValue,
+        @Nullable String remainingLineContent,
+        @Nonnull String line,
+        String patternMatched
+    );
 }
\ No newline at end of file
diff --git a/base-impl/src/main/java/com/intellij/javascript/documentation/JSDocumentationProvider.java b/base-impl/src/main/java/com/intellij/javascript/documentation/JSDocumentationProvider.java
index 93502b77..d47e3897 100644
--- a/base-impl/src/main/java/com/intellij/javascript/documentation/JSDocumentationProvider.java
+++ b/base-impl/src/main/java/com/intellij/javascript/documentation/JSDocumentationProvider.java
@@ -39,12 +39,11 @@
 import consulo.project.Project;
 import consulo.util.lang.Pair;
 import consulo.util.lang.StringUtil;
-import consulo.util.lang.ref.Ref;
+import consulo.util.lang.ref.SimpleReference;
 import consulo.xml.psi.xml.XmlToken;
-import org.jetbrains.annotations.NonNls;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
 
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
 import java.io.File;
 import java.lang.reflect.Method;
 import java.util.Collections;
@@ -53,1109 +52,883 @@
 import java.util.Map;
 
 /**
- * User: Maxim.Mossienko
- * Date: Nov 4, 2005
- * Time: 5:04:28 PM
+ * @author Maxim.Mossienko
+ * @since 2005-11-04
  */
 @ExtensionImpl
-public class JSDocumentationProvider implements CodeDocumentationProvider, LanguageDocumentationProvider
-{
-	private DocumentationProvider cssProvider;
-	@NonNls
-	private static final String OBJECT_NAME = "Object";
-	protected static final String SEE_PLAIN_TEXT_CHARS = "\t \"-\\/<>*";
-
-	@NonNls
-	protected static final String PACKAGE = "package";
-	@NonNls
-	protected static final String HTML_EXTENSION = ".html";
-	@NonNls
-	protected static final String PACKAGE_FILE = PACKAGE + HTML_EXTENSION;
-
-	protected static final Map DOCUMENTED_ATTRIBUTES;
-
-	static
-	{
-		DOCUMENTED_ATTRIBUTES = new HashMap();
-		DOCUMENTED_ATTRIBUTES.put("Event", "event:");
-		DOCUMENTED_ATTRIBUTES.put("Style", "style:");
-		DOCUMENTED_ATTRIBUTES.put("Effect", "effect:");
-	}
-
-	private DocumentationProvider getCssProvider(Project project) throws Exception
-	{
-		if(cssProvider == null)
-		{
-			final Class aClass = Class.forName("com.intellij.psi.css.impl.util.CssDocumentationProvider");
-			cssProvider = (DocumentationProvider) aClass.getConstructor(new Class[]{}).newInstance(new Object[]{});
-		}
-
-		return cssProvider;
-	}
-
-	@Nullable
-	public String getQuickNavigateInfo(PsiElement element, PsiElement element2)
-	{
-		if(element instanceof JSFunction)
-		{
-			final JSFunction function = (JSFunction) element;
-			final PsiElement parent = element.getParent();
-
-			if(function.isConstructor())
-			{
-				if(parent instanceof JSClass)
-				{
-					return createQuickNavigateForClazz((JSClass) parent);
-				}
-			}
-			return createQuickNavigateForFunction(function);
-		}
-		else if(element instanceof JSClass)
-		{
-			return createQuickNavigateForClazz((JSClass) element);
-		}
-		else if(element instanceof JSVariable)
-		{
-			return createQuickNavigateForVariable((JSVariable) element);
-		}
-		else if(element instanceof JSAttributeNameValuePair)
-		{
-			return createQuickNavigateForAnnotationDerived(element);
-		}
-		else if(element instanceof XmlToken)
-		{
-			BaseJSSymbolProcessor.TagContextBuilder builder = new BaseJSSymbolProcessor.TagContextBuilder(element, "XmlTag");
-			return StringUtil.stripQuotesAroundValue(element.getText()) + ":" + builder.typeName;
-		}
-		else if(element instanceof JSNamespaceDeclaration)
-		{
-			return createQuickNavigateForNamespace((JSNamespaceDeclaration) element);
-		}
-
-		return null;
-	}
-
-	private static String createQuickNavigateForAnnotationDerived(final PsiElement element)
-	{
-		final JSAttributeNameValuePair valuePair = (JSAttributeNameValuePair) element;
-		final JSAttribute parent = (JSAttribute) valuePair.getParent();
-		final StringBuilder builder = new StringBuilder();
-		final JSClass clazz = PsiTreeUtil.getParentOfType(valuePair, JSClass.class);
-		appendParentInfo(clazz != null ? clazz : parent.getContainingFile(), builder, parent);
-		builder.append(parent.getName()).append(" ").append(valuePair.getSimpleValue());
-		return builder.toString();
-	}
-
-	private static
-	@Nullable
-	String createQuickNavigateForFunction(final JSFunction function)
-	{
-		final PsiElement parent = JSResolveUtil.findParent(function);
-		final StringBuilder result = new StringBuilder();
-
-		appendParentInfo(parent, result, function);
-
-		appendAttrList(function, result);
-		final boolean get = function.isGetProperty();
-		final boolean set = function.isSetProperty();
-
-		result.append(get || set ? "property " : "function ");
-		result.append(function.getName());
-
-		if(!get && !set)
-		{
-			result.append('(');
-			final JSParameterList jsParameterList = function.getParameterList();
-
-			if(jsParameterList != null)
-			{
-				final int start = result.length();
-
-				for(JSParameter p : jsParameterList.getParameters())
-				{
-					if(start != result.length())
-					{
-						result.append(", ");
-					}
-					result.append(p.getName());
-					appendVarType(p, result);
-				}
-			}
-
-			result.append(')');
-		}
-
-		String varType = null;
-
-		if(get || !set)
-		{
-			varType = JSImportHandlingUtil.resolveTypeName(function.getReturnTypeString(), function);
-		}
-		else
-		{
-			final JSParameterList jsParameterList = function.getParameterList();
-
-			if(jsParameterList != null)
-			{
-				final JSParameter[] jsParameters = jsParameterList.getParameters();
-				if(jsParameters != null && jsParameters.length > 0)
-				{
-					varType = JSImportHandlingUtil.resolveTypeName(jsParameters[0].getTypeString(), function);
-				}
-			}
-		}
-
-		if(varType != null)
-		{
-			result.append(':').append(varType);
-		}
-		return result.toString();
-	}
-
-	private static void appendParentInfo(final PsiElement parent, final StringBuilder builder, PsiNamedElement element)
-	{
-		if(parent instanceof JSClass)
-		{
-			builder.append(((JSClass) parent).getQualifiedName()).append("\n");
-		}
-		else if(parent instanceof JSPackageStatement)
-		{
-			builder.append(((JSPackageStatement) parent).getQualifiedName()).append("\n");
-		}
-		else if(parent instanceof JSFile)
-		{
-			if(parent.getContext() != null)
-			{
-				final String mxmlPackage = JSResolveUtil.findPackageForMxml(parent);
-				if(mxmlPackage != null)
-				{
-					builder.append(mxmlPackage).append(mxmlPackage.length() > 0 ? "." : "").append(parent.getContext().getContainingFile().getName()).append("\n");
-				}
-			}
-			else
-			{
-				boolean foundQualified = false;
-
-				if(element instanceof JSNamedElement)
-				{
-					PsiElement node = ((JSNamedElement) element).getNameIdentifier();
-					if(node != null)
-					{
-						final String s = node.getText();
-						int i = s.lastIndexOf('.');
-						if(i != -1)
-						{
-							builder.append(s.substring(0, i)).append("\n");
-							foundQualified = true;
-						}
-					}
-				}
-				if(!foundQualified)
-				{
-					builder.append(parent.getContainingFile().getName()).append("\n");
-				}
-			}
-		}
-	}
-
-	@Nullable
-	@RequiredReadAction
-	private static String createQuickNavigateForVariable(final JSVariable variable)
-	{
-		final PsiElement parent = JSResolveUtil.findParent(variable);
-		final StringBuilder result = new StringBuilder();
-
-		appendParentInfo(parent, result, variable);
-
-		appendAttrList(variable, result);
-		result.append(variable.isConst() ? "const " : "var ");
-		result.append(variable.getName());
-		appendVarType(variable, result);
-
-		JSExpression initializer = variable.getInitializer();
-		if(initializer != null)
-		{
-			result.append(" = ");
-			if(initializer instanceof JSLiteralExpression)
-			{
-				result.append(initializer.getText());
-			}
-			else if(initializer instanceof JSObjectLiteralExpression)
-			{
-				result.append("{...}");
-			}
-			else
-			{
-				result.append("...");
-			}
-		}
-		return result.toString();
-	}
-
-	private static void appendVarType(final JSVariable variable, final StringBuilder builder)
-	{
-		final String varType = variable.getTypeString();
-		if(varType != null)
-		{
-			builder.append(':').append(varType);
-		}
-	}
-
-	private static
-	@Nullable
-	String createQuickNavigateForClazz(final JSClass jsClass)
-	{
-		final String qName = jsClass.getQualifiedName();
-		if(qName == null)
-		{
-			return null;
-		}
-		StringBuilder result = new StringBuilder();
-		String packageName = StringUtil.getPackageName(qName);
-		if(packageName.length() > 0)
-		{
-			result.append(packageName).append("\n");
-		}
-
-		appendAttrList(jsClass, result);
-		if(jsClass.isInterface())
-		{
-			result.append("interface");
-		}
-		else
-		{
-			result.append("class");
-		}
-
-		final String name = jsClass.getName();
-		result.append(" ").append(name);
-
-		String s = generateReferenceTargetList(jsClass.getExtendsList(), packageName);
-		if(s == null && !OBJECT_NAME.equals(name))
-		{
-			s = OBJECT_NAME;
-		}
-		if(s != null)
-		{
-			result.append(" extends ").append(s);
-		}
-
-		s = generateReferenceTargetList(jsClass.getImplementsList(), packageName);
-		if(s != null)
-		{
-			result.append("\nimplements ").append(s);
-		}
-
-		return result.toString();
-	}
-
-	private static
-	@Nullable
-	String createQuickNavigateForNamespace(final JSNamespaceDeclaration ns)
-	{
-		final String qName = ns.getQualifiedName();
-		if(qName == null)
-		{
-			return null;
-		}
-		StringBuilder result = new StringBuilder();
-		String packageName = StringUtil.getPackageName(qName);
-		if(packageName.length() > 0)
-		{
-			result.append(packageName).append("\n");
-		}
-
-		result.append("namespace");
-
-		final String name = ns.getName();
-		result.append(" ").append(name);
-
-		String s = ns.getInitialValueString();
-		if(s != null)
-		{
-			result.append(" = ").append(s);
-		}
-		return result.toString();
-	}
-
-
-	private static void appendAttrList(final JSAttributeListOwner jsClass, final StringBuilder result)
-	{
-		final JSAttributeList attributeList = jsClass.getAttributeList();
-		if(attributeList != null)
-		{
-			if(attributeList.hasModifier(JSAttributeList.ModifierType.OVERRIDE))
-			{
-				result.append("override ");
-			}
-			JSAttributeList.AccessType type = attributeList.getAccessType();
-			String ns = attributeList.getNamespace();
-			if(type != JSAttributeList.AccessType.PACKAGE_LOCAL || ns == null)
-			{
-				result.append(type.toString().toLowerCase());
-			}
-			else
-			{
-				result.append(ns);
-			}
-
-			result.append(" ");
-
-			if(attributeList.hasModifier(JSAttributeList.ModifierType.STATIC))
-			{
-				result.append("static ");
-			}
-			if(attributeList.hasModifier(JSAttributeList.ModifierType.FINAL))
-			{
-				result.append("final ");
-			}
-			if(attributeList.hasModifier(JSAttributeList.ModifierType.DYNAMIC))
-			{
-				result.append("dynamic ");
-			}
-			if(attributeList.hasModifier(JSAttributeList.ModifierType.NATIVE))
-			{
-				result.append("native ");
-			}
-		}
-	}
-
-	private static
-	@Nullable
-	String generateReferenceTargetList(final @Nullable JSReferenceList implementsList, @Nonnull String packageName)
-	{
-		if(implementsList == null)
-		{
-			return null;
-		}
-		StringBuilder result = null;
-
-		final String[] referenceExpressionTexts = implementsList.getReferenceTexts();
-
-		for(String refExprText : referenceExpressionTexts)
-		{
-			refExprText = JSImportHandlingUtil.resolveTypeName(refExprText, implementsList);
-			if(result == null)
-			{
-				result = new StringBuilder();
-			}
-			else
-			{
-				result.append(",");
-			}
-
-			final String referencedPackageName = StringUtil.getPackageName(refExprText);
-			result.append(referencedPackageName.equals(packageName) ? refExprText.substring(refExprText.lastIndexOf('.') + 1) : refExprText);
-		}
-		return result == null ? null : result.toString();
-	}
-
-	@Override
-	public List getUrlFor(PsiElement element, PsiElement originalElement)
-	{
-		String possibleCssName = findPossibleCssName(element);
-
-		if(possibleCssName != null)
-		{
-			try
-			{
-				final DocumentationProvider documentationProvider = getCssProvider(element.getProject());
-				final Method method = documentationProvider.getClass().getMethod("getUrlFor", new Class[]{String.class});
-				final Object o = method.invoke(null, new Object[]{possibleCssName});
-
-				if(o instanceof String)
-				{
-					return Collections.singletonList((String) o);
-				}
-			}
-			catch(Exception e)
-			{
-			}
-		}
-		return null;
-	}
-
-	@Override
-	public String generateDoc(PsiElement _element, PsiElement originalElement)
-	{
-		if(_element instanceof JSReferenceExpression)
-		{
-			StringBuilder buffer = null;
-
-			// ambigious reference
-			final JSReferenceExpression expression = (JSReferenceExpression) _element;
-			for(ResolveResult r : expression.multiResolve(false))
-			{
-				if(buffer == null)
-				{
-					buffer = new StringBuilder();
-				}
-				final PsiElement element = r.getElement();
-				final ItemPresentation presentation = ((NavigationItem) element).getPresentation();
-
-				JSDocumentationUtils.appendHyperLinkToElement(element, expression.getReferencedName(), buffer, presentation.getPresentableText(),
-						presentation.getLocationString());
-				buffer.append("
\n"); - } - return buffer != null ? buffer.toString() : null; - } - - _element = _element.getNavigationElement(); - PsiElement element = findElementForWhichPreviousCommentWillBeSearched(_element); - - final boolean parameterDoc = element instanceof JSParameter; - if(parameterDoc) - { - element = findElementForWhichPreviousCommentWillBeSearched(PsiTreeUtil.getParentOfType(element, JSFunction.class)); - } - - if(element != null) - { - PsiElement docComment = JSDocumentationUtils.findDocComment(element, _element instanceof JSAttributeNameValuePair ? originalElement : null); - - if(docComment != null) - { - docComment = findFirstDocComment(docComment); - element = findTargetElement(_element, element); - final JSDocumentationBuilder builder = new JSDocumentationBuilder(element, originalElement); - JSDocumentationUtils.processDocumentationTextFromComment(docComment.getNode(), builder); - - return parameterDoc ? builder.getParameterDoc(((JSParameter) _element).getName()) : builder.getDoc(); - } - - element = findTargetElement(_element, element); - - if(element instanceof JSFunction) - { - ASTNode initialComment = JSDocumentationUtils.findLeadingCommentInFunctionBody(element); - - if(initialComment != null) - { - final JSDocumentationBuilder builder = new JSDocumentationBuilder(element, originalElement); - JSDocumentationUtils.processDocumentationTextFromComment(initialComment, builder); - return builder.getDoc(); - } - } - } - - String possibleCssName = findPossibleCssName(_element); - if(possibleCssName != null) - { - - try - { - final DocumentationProvider documentationProvider = getCssProvider(_element.getProject()); - final Method declaredMethod = documentationProvider.getClass().getDeclaredMethod("generateDoc", String.class, PsiElement.class); - final Object o = declaredMethod.invoke(null, possibleCssName, null); - - if(o instanceof String) - { - return (String) o; - } - } - catch(Exception e) - { - } - - } - - return null; - } - - private static PsiElement findTargetElement(final PsiElement _element, PsiElement element) - { - if(_element instanceof JSDefinitionExpression) - { - final PsiElement parentElement = _element.getParent(); - - if(parentElement instanceof JSAssignmentExpression) - { - final JSExpression rOperand = ((JSAssignmentExpression) parentElement).getROperand(); - - if(rOperand instanceof JSFunctionExpression) - { - element = rOperand; - } - else - { - element = _element; - } - } - } - else if(_element instanceof JSFunctionExpression) - { - element = _element; - } - else if(_element instanceof JSProperty) - { - final JSExpression expression = ((JSProperty) _element).getValue(); - - if(expression instanceof JSFunction) - { - element = expression; - } - } - else if(_element instanceof JSVariable) - { - if(_element instanceof JSParameter) - { - return PsiTreeUtil.getParentOfType(_element, JSFunction.class); - } - element = _element; - } - else if(_element instanceof JSAttributeNameValuePair) - { - return _element; - } - return element; - } - - private static PsiElement findFirstDocComment(PsiElement docComment) - { - if(docComment.getNode().getElementType() == JSTokenTypes.END_OF_LINE_COMMENT) - { - while(true) - { - PsiElement prev = docComment.getPrevSibling(); - if(prev instanceof PsiWhiteSpace) - { - prev = prev.getPrevSibling(); - } - if(prev == null) - { - break; - } - if(prev.getNode().getElementType() != JSTokenTypes.END_OF_LINE_COMMENT) - { - break; - } - docComment = prev; - } - } - return docComment; - } - - private static String findPossibleCssName(PsiElement _element) - { - if(_element instanceof JSDefinitionExpression) - { - final JSExpression expression = ((JSDefinitionExpression) _element).getExpression(); - - if(expression instanceof JSReferenceExpression) - { - final String text = ((JSReferenceExpression) expression).getReferencedName(); - if(text == null) - { - return null; - } - final StringBuffer buf = new StringBuffer(text.length()); - - for(int i = 0; i < text.length(); ++i) - { - final char ch = text.charAt(i); - - if(Character.isUpperCase(ch)) - { - buf.append('-').append(Character.toLowerCase(ch)); - } - else - { - buf.append(ch); - } - } - - return buf.toString(); - } - } - return null; - } - - @Override - public PsiElement getDocumentationElementForLookupItem(PsiManager psiManager, Object object, PsiElement element) - { - final PsiElement psiElement = findElementForWhichPreviousCommentWillBeSearched(object); - if(psiElement != null && JSDocumentationUtils.findDocComment(psiElement) != null) - { - return psiElement; - } - if(object instanceof PsiElement) - { - return (PsiElement) object; - } - return null; - } - - public static PsiElement findElementForWhichPreviousCommentWillBeSearched(Object object) - { - if(object instanceof JSFunction) - { - PsiElement psiElement = (PsiElement) object; - PsiElement parent = psiElement.getParent(); - if(parent instanceof JSNewExpression) - { - parent = parent.getParent(); - } - if(parent instanceof JSProperty) - { - psiElement = parent; - } - else if(parent instanceof JSAssignmentExpression) - { - psiElement = parent.getParent(); - } - - JSFunction function = (JSFunction) object; - if(function.isSetProperty() || function.isGetProperty()) - { - for(PsiElement el = function.getPrevSibling(); el != null; el = el.getPrevSibling()) - { - if(!(el instanceof PsiWhiteSpace) && !(el instanceof PsiComment)) - { - if(el instanceof JSFunction) - { - JSFunction prevFunction = (JSFunction) el; - String name = prevFunction.getName(); - - if(name != null && - name.equals(function.getName()) && - ((prevFunction.isGetProperty() && function.isSetProperty()) || prevFunction.isSetProperty() && function.isGetProperty())) - { - PsiElement doc = JSDocumentationUtils.findDocComment(prevFunction); - if(doc != null) - { - return prevFunction; - } - } - } - break; - } - } - } - return psiElement; - } - else if(object instanceof JSProperty || object instanceof JSStatement || object instanceof JSClass) - { - return (PsiElement) object; - } - else if(object instanceof PsiElement) - { - final PsiElement parent = ((PsiElement) object).getParent(); - if(parent instanceof JSAssignmentExpression) - { - return parent.getParent(); - } - else if(parent instanceof JSVarStatement) - { - final PsiElement firstChild = parent.getFirstChild(); - if(firstChild instanceof JSAttributeList) - { - if(JSDocumentationUtils.findDocComment((PsiElement) object) != null) - { - return (PsiElement) object; - } - } - return parent; - } - else if(parent instanceof JSAttribute) - { - final PsiElement grandParent = parent.getParent(); - if(grandParent.getFirstChild() == parent) - { - final PsiElement element = grandParent.getParent(); - if(element instanceof JSFile) - { - return grandParent; - } - return element; - } - return parent; - } - else if(parent instanceof JSSuppressionHolder) - { - return parent; - } - else - { - return (PsiElement) object; - } - } - - return null; - } - - @Override - @Nullable - public PsiElement getDocumentationElementForLink(final PsiManager psiManager, String link, final PsiElement context) - { - return getDocumentationElementForLinkStatic(psiManager, link, context); - } - - @Nullable - private static PsiElement getDocumentationElementForLinkStatic(final PsiManager psiManager, String link, @Nonnull PsiElement context) - { - final int delimiterIndex = link.lastIndexOf(':'); - - String attributeType = null; - String attributeName = null; - for(Map.Entry e : DOCUMENTED_ATTRIBUTES.entrySet()) - { - final String pattern = "." + e.getValue(); - if(link.contains(pattern)) - { - attributeType = e.getKey(); - attributeName = link.substring(link.indexOf(pattern) + pattern.length()); - link = link.substring(0, link.indexOf(pattern)); - break; - } - } - if(delimiterIndex != -1 && attributeType == null) - { - final int delimiterIndex2 = link.lastIndexOf(':', delimiterIndex - 1); - String fileName = link.substring(0, delimiterIndex2).replace(File.separatorChar, '/'); - String name = link.substring(delimiterIndex2 + 1, delimiterIndex); - int offset = Integer.parseInt(link.substring(delimiterIndex + 1)); - return JavaScriptIndex.findSymbolByFileAndNameAndOffset(fileName, name, offset); - } - else if(attributeType != null) - { - PsiElement clazz = JSResolveUtil.findClassByQName(link, context.getResolveScope(), psiManager.getProject()); - if(!(clazz instanceof JSClass)) - { - return null; - } - return findNamedAttribute((JSClass) clazz, attributeType, attributeName); - } - else - { - PsiElement clazz = JSResolveUtil.findClassByQName(link, context.getResolveScope(), psiManager.getProject()); - if(clazz == null && link.contains(".")) - { - String qname = link.substring(0, link.lastIndexOf('.')); - clazz = JSResolveUtil.findClassByQName(qname, context.getResolveScope(), psiManager.getProject()); - if(clazz instanceof JSClass) - { - JSClass jsClass = (JSClass) clazz; - String member = link.substring(link.lastIndexOf('.') + 1); - - if(member.endsWith("()")) - { - member = member.substring(0, member.length() - 2); - - PsiElement result = findMethod(jsClass, member); - if(result == null) - { - result = findProperty(jsClass, member); // user might refer to a property - } - return result; - } - else - { - PsiElement result = jsClass.findFieldByName(member); - if(result == null) - { - result = findProperty(jsClass, member); - } - if(result == null) - { - result = findMethod(jsClass, member); // user might forget brackets - } - return result; - } - } - } - - if(clazz instanceof JSVariable) - { - return clazz; - } - - if(link.endsWith("()")) - { - link = link.substring(0, link.length() - 2); - clazz = JSResolveUtil.findClassByQName(link, context.getResolveScope(), psiManager.getProject()); - if(clazz instanceof JSFunction) - { - return clazz; - } - } - return clazz; - } - } - - @Nullable - protected static JSAttributeNameValuePair findNamedAttribute(JSClass clazz, final String type, final String name) - { - final Ref attribute = new Ref(); - JSResolveUtil.processMetaAttributesForClass(clazz, new JSResolveUtil.MetaDataProcessor() - { - @Override - public boolean process(@Nonnull JSAttribute jsAttribute) - { - if(type.equals(jsAttribute.getName())) - { - final JSAttributeNameValuePair jsAttributeNameValuePair = jsAttribute.getValueByName("name"); - if(jsAttributeNameValuePair != null && name.equals(jsAttributeNameValuePair.getSimpleValue())) - { - attribute.set(jsAttributeNameValuePair); - return false; - } - } - return true; - } - - @Override - public boolean handleOtherElement(PsiElement el, PsiElement context, @Nullable Ref continuePassElement) - { - return true; - } - }); - return attribute.get(); - } - - private static PsiElement findProperty(JSClass jsClass, String name) - { - PsiElement result = jsClass.findFunctionByNameAndKind(name, JSFunction.FunctionKind.GETTER); - if(result == null) - { - result = jsClass.findFunctionByNameAndKind(name, JSFunction.FunctionKind.SETTER); - } - return result; - } - - private static PsiElement findMethod(JSClass jsClass, String name) - { - PsiElement result = jsClass.findFunctionByNameAndKind(name, JSFunction.FunctionKind.CONSTRUCTOR); - if(result == null) - { - result = jsClass.findFunctionByNameAndKind(name, JSFunction.FunctionKind.SIMPLE); - } - return result; - } - - @Override - @Nullable - public PsiComment findExistingDocComment(PsiComment contextElement) - { - return contextElement; - } - - @Nullable - @Override - public Pair parseContext(@Nonnull PsiElement element) - { - return null; - } - - @Override - @Nullable - public String generateDocumentationContentStub(PsiComment contextComment) - { - for(PsiElement el = contextComment.getParent(); el != null; el = el.getNextSibling()) - { - if(el instanceof JSProperty) - { - final JSExpression propertyValue = ((JSProperty) el).getValue(); - if(propertyValue instanceof JSFunction) - { - return doGenerateDoc((JSFunction) propertyValue); - } - } - else if(el instanceof JSFunction) - { - final JSFunction function = ((JSFunction) el); - return doGenerateDoc(function); - } - else if(el instanceof JSExpressionStatement) - { - final JSExpression expression = ((JSExpressionStatement) el).getExpression(); - - if(expression instanceof JSAssignmentExpression) - { - final JSExpression rOperand = ((JSAssignmentExpression) expression).getROperand(); - - if(rOperand instanceof JSFunctionExpression) - { - return doGenerateDoc(((JSFunctionExpression) rOperand).getFunction()); - } - } - } - else if(el instanceof JSVarStatement) - { - JSVariable[] variables = ((JSVarStatement) el).getVariables(); - if(variables.length > 0) - { - JSExpression expression = variables[0].getInitializer(); - if(expression instanceof JSFunctionExpression) - { - return doGenerateDoc(((JSFunctionExpression) expression).getFunction()); - } - } - break; - } - } - return null; - } - - private static String doGenerateDoc(final JSFunction function) - { - StringBuilder builder = new StringBuilder(); - final JSParameterList parameterList = function.getParameterList(); - final PsiFile containingFile = function.getContainingFile(); - final boolean ecma = containingFile.getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4; - - if(parameterList != null) - { - for(JSParameter parameter : parameterList.getParameters()) - { - builder.append("* @param ").append(parameter.getName()); - //String s = JSPsiImplUtils.getTypeFromDeclaration(parameter); - //if (s != null) builder.append(" : ").append(s); - builder.append("\n"); - } - } - - if(ecma) - { - String s = JSPsiImplUtils.getTypeFromDeclaration(function); - - if(s != null && !"void".equals(s)) - { - builder.append("* @return "); - - //builder.append(s); - builder.append("\n"); - } - } - - return builder.toString(); - } - - @Nullable - protected static String getSeeAlsoLinkResolved(PsiElement originElement, String link) - { - JSQualifiedNamedElement qualifiedElement = findParentQualifiedElement(originElement); - if(qualifiedElement == null) - { - return null; - } - String linkToResolve = getLinkToResolve(qualifiedElement, link); - final PsiElement resolvedElement = getDocumentationElementForLinkStatic(originElement.getManager(), linkToResolve, originElement); - if(resolvedElement != null) - { - return linkToResolve; - } - return null; - } - - private static String getLinkToResolve(JSQualifiedNamedElement origin, String link) - { - String originQname = origin.getQualifiedName(); - if(link.length() == 0) - { - return originQname; - } - else if(StringUtil.startsWithChar(link, '#')) - { - if(origin instanceof JSClass) - { - return originQname + "." + link.substring(1); - } - else - { - String aPackage = StringUtil.getPackageName(originQname); - return aPackage + "." + link.substring(1); - } - } - else - { - String linkFile = link.contains("#") ? link.substring(0, link.lastIndexOf('#')) : link; - String linkAnchor = link.contains("#") ? link.substring(link.lastIndexOf('#') + 1) : null; - - final String qname; - if(StringUtil.endsWithIgnoreCase(linkFile, HTML_EXTENSION)) - { - String prefix = StringUtil.getPackageName(originQname); - while(linkFile.startsWith("../")) - { - linkFile = linkFile.substring("../".length()); - prefix = StringUtil.getPackageName(prefix); - } - - String linkFilename; - if(linkFile.endsWith(PACKAGE_FILE)) - { - linkFilename = StringUtil.trimEnd(linkFile, PACKAGE_FILE); - linkFilename = StringUtil.trimEnd(linkFilename, "/"); - } - else - { - linkFilename = linkFile.substring(0, linkFile.lastIndexOf(".")); - } - if(linkFilename.length() > 0) - { - qname = (prefix.length() > 0 ? prefix + "." : prefix) + linkFilename.replaceAll("/", "."); - } - else - { - qname = prefix; - } - } - else - { - qname = linkFile; - } - - return linkAnchor != null ? (qname.length() > 0 ? qname + "." : qname) + linkAnchor : qname; - } - } - - @Nullable - protected static JSQualifiedNamedElement findParentQualifiedElement(PsiElement element) - { - if(element instanceof JSClass) - { - return (JSClass) element; - } - if(element instanceof JSFunction || element instanceof JSVariable) - { - final PsiElement parent = JSResolveUtil.findParent(element); - if(parent instanceof JSClass) - { - return (JSClass) parent; - } - else if(parent instanceof JSFile) - { - return (JSQualifiedNamedElement) element; - } - } - - JSAttribute attribute = null; - if(element instanceof JSAttribute) - { - attribute = (JSAttribute) element; - } - else if(element instanceof JSAttributeNameValuePair) - { - attribute = (JSAttribute) element.getParent(); - } - - if(attribute != null && DOCUMENTED_ATTRIBUTES.containsKey(attribute.getName())) - { - final JSClass jsClass = PsiTreeUtil.getParentOfType(element, JSClass.class); - if(jsClass != null) - { - return jsClass; - } - } - - return null; - } - - - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } +public class JSDocumentationProvider implements CodeDocumentationProvider, LanguageDocumentationProvider { + private DocumentationProvider cssProvider; + private static final String OBJECT_NAME = "Object"; + protected static final String SEE_PLAIN_TEXT_CHARS = "\t \"-\\/<>*"; + + protected static final String PACKAGE = "package"; + protected static final String HTML_EXTENSION = ".html"; + protected static String PACKAGE_FILE = PACKAGE + HTML_EXTENSION; + + protected static final Map DOCUMENTED_ATTRIBUTES; + + static { + DOCUMENTED_ATTRIBUTES = new HashMap<>(); + DOCUMENTED_ATTRIBUTES.put("Event", "event:"); + DOCUMENTED_ATTRIBUTES.put("Style", "style:"); + DOCUMENTED_ATTRIBUTES.put("Effect", "effect:"); + } + + private DocumentationProvider getCssProvider(Project project) throws Exception { + if (cssProvider == null) { + Class aClass = Class.forName("com.intellij.psi.css.impl.util.CssDocumentationProvider"); + cssProvider = (DocumentationProvider)aClass.getConstructor(new Class[]{}).newInstance(new Object[]{}); + } + + return cssProvider; + } + + @Override + @Nullable + @RequiredReadAction + public String getQuickNavigateInfo(PsiElement element, PsiElement element2) { + if (element instanceof JSFunction function) { + if (function.isConstructor() && function.getParent() instanceof JSClass jsClass) { + return createQuickNavigateForClazz(jsClass); + } + return createQuickNavigateForFunction(function); + } + else if (element instanceof JSClass jsClass) { + return createQuickNavigateForClazz(jsClass); + } + else if (element instanceof JSVariable variable) { + return createQuickNavigateForVariable(variable); + } + else if (element instanceof JSAttributeNameValuePair attributeNameValuePair) { + return createQuickNavigateForAnnotationDerived(attributeNameValuePair); + } + else if (element instanceof XmlToken xmlToken) { + BaseJSSymbolProcessor.TagContextBuilder builder = new BaseJSSymbolProcessor.TagContextBuilder(xmlToken, "XmlTag"); + return StringUtil.stripQuotesAroundValue(xmlToken.getText()) + ":" + builder.typeName; + } + else if (element instanceof JSNamespaceDeclaration namespaceDeclaration) { + return createQuickNavigateForNamespace(namespaceDeclaration); + } + + return null; + } + + @RequiredReadAction + private static String createQuickNavigateForAnnotationDerived(PsiElement element) { + JSAttributeNameValuePair valuePair = (JSAttributeNameValuePair)element; + JSAttribute parent = (JSAttribute)valuePair.getParent(); + StringBuilder builder = new StringBuilder(); + JSClass clazz = PsiTreeUtil.getParentOfType(valuePair, JSClass.class); + appendParentInfo(clazz != null ? clazz : parent.getContainingFile(), builder, parent); + builder.append(parent.getName()).append(" ").append(valuePair.getSimpleValue()); + return builder.toString(); + } + + @Nullable + @RequiredReadAction + private static String createQuickNavigateForFunction(JSFunction function) { + PsiElement parent = JSResolveUtil.findParent(function); + StringBuilder result = new StringBuilder(); + + appendParentInfo(parent, result, function); + + appendAttrList(function, result); + boolean get = function.isGetProperty(); + boolean set = function.isSetProperty(); + + result.append(get || set ? "property " : "function "); + result.append(function.getName()); + + if (!get && !set) { + result.append('('); + JSParameterList jsParameterList = function.getParameterList(); + + if (jsParameterList != null) { + int start = result.length(); + + for (JSParameter p : jsParameterList.getParameters()) { + if (start != result.length()) { + result.append(", "); + } + result.append(p.getName()); + appendVarType(p, result); + } + } + + result.append(')'); + } + + String varType = null; + + if (get || !set) { + varType = JSImportHandlingUtil.resolveTypeName(function.getReturnTypeString(), function); + } + else { + JSParameterList jsParameterList = function.getParameterList(); + + if (jsParameterList != null) { + JSParameter[] jsParameters = jsParameterList.getParameters(); + if (jsParameters != null && jsParameters.length > 0) { + varType = JSImportHandlingUtil.resolveTypeName(jsParameters[0].getTypeString(), function); + } + } + } + + if (varType != null) { + result.append(':').append(varType); + } + return result.toString(); + } + + @RequiredReadAction + private static void appendParentInfo(PsiElement parent, StringBuilder builder, PsiNamedElement element) { + if (parent instanceof JSClass jsClass) { + builder.append(jsClass.getQualifiedName()).append("\n"); + } + else if (parent instanceof JSPackageStatement packageStatement) { + builder.append(packageStatement.getQualifiedName()).append("\n"); + } + else if (parent instanceof JSFile) { + if (parent.getContext() != null) { + String mxmlPackage = JSResolveUtil.findPackageForMxml(parent); + if (mxmlPackage != null) { + builder.append(mxmlPackage) + .append(mxmlPackage.length() > 0 ? "." : "") + .append(parent.getContext().getContainingFile().getName()) + .append("\n"); + } + } + else { + boolean foundQualified = false; + + if (element instanceof JSNamedElement namedElement) { + PsiElement node = namedElement.getNameIdentifier(); + if (node != null) { + String s = node.getText(); + int i = s.lastIndexOf('.'); + if (i != -1) { + builder.append(s.substring(0, i)).append("\n"); + foundQualified = true; + } + } + } + if (!foundQualified) { + builder.append(parent.getContainingFile().getName()).append("\n"); + } + } + } + } + + @Nullable + @RequiredReadAction + private static String createQuickNavigateForVariable(JSVariable variable) { + PsiElement parent = JSResolveUtil.findParent(variable); + StringBuilder result = new StringBuilder(); + + appendParentInfo(parent, result, variable); + + appendAttrList(variable, result); + result.append(variable.isConst() ? "const " : "var "); + result.append(variable.getName()); + appendVarType(variable, result); + + JSExpression initializer = variable.getInitializer(); + if (initializer != null) { + result.append(" = "); + if (initializer instanceof JSLiteralExpression) { + result.append(initializer.getText()); + } + else if (initializer instanceof JSObjectLiteralExpression) { + result.append("{...}"); + } + else { + result.append("..."); + } + } + return result.toString(); + } + + private static void appendVarType(JSVariable variable, StringBuilder builder) { + String varType = variable.getTypeString(); + if (varType != null) { + builder.append(':').append(varType); + } + } + + @Nullable + @RequiredReadAction + private static String createQuickNavigateForClazz(JSClass jsClass) { + String qName = jsClass.getQualifiedName(); + if (qName == null) { + return null; + } + StringBuilder result = new StringBuilder(); + String packageName = StringUtil.getPackageName(qName); + if (packageName.length() > 0) { + result.append(packageName).append("\n"); + } + + appendAttrList(jsClass, result); + result.append(jsClass.isInterface() ? "interface" : "class"); + + String name = jsClass.getName(); + result.append(" ").append(name); + + String s = generateReferenceTargetList(jsClass.getExtendsList(), packageName); + if (s == null && !OBJECT_NAME.equals(name)) { + s = OBJECT_NAME; + } + if (s != null) { + result.append(" extends ").append(s); + } + + s = generateReferenceTargetList(jsClass.getImplementsList(), packageName); + if (s != null) { + result.append("\nimplements ").append(s); + } + + return result.toString(); + } + + @Nullable + @RequiredReadAction + private static String createQuickNavigateForNamespace(JSNamespaceDeclaration ns) { + String qName = ns.getQualifiedName(); + if (qName == null) { + return null; + } + StringBuilder result = new StringBuilder(); + String packageName = StringUtil.getPackageName(qName); + if (packageName.length() > 0) { + result.append(packageName).append("\n"); + } + + result.append("namespace"); + + result.append(" ").append(ns.getName()); + + String s = ns.getInitialValueString(); + if (s != null) { + result.append(" = ").append(s); + } + return result.toString(); + } + + @RequiredReadAction + private static void appendAttrList(JSAttributeListOwner jsClass, StringBuilder result) { + JSAttributeList attributeList = jsClass.getAttributeList(); + if (attributeList != null) { + if (attributeList.hasModifier(JSAttributeList.ModifierType.OVERRIDE)) { + result.append("override "); + } + JSAttributeList.AccessType type = attributeList.getAccessType(); + String ns = attributeList.getNamespace(); + if (type != JSAttributeList.AccessType.PACKAGE_LOCAL || ns == null) { + result.append(type.toString().toLowerCase()); + } + else { + result.append(ns); + } + + result.append(" "); + + if (attributeList.hasModifier(JSAttributeList.ModifierType.STATIC)) { + result.append("static "); + } + if (attributeList.hasModifier(JSAttributeList.ModifierType.FINAL)) { + result.append("final "); + } + if (attributeList.hasModifier(JSAttributeList.ModifierType.DYNAMIC)) { + result.append("dynamic "); + } + if (attributeList.hasModifier(JSAttributeList.ModifierType.NATIVE)) { + result.append("native "); + } + } + } + + @Nullable + @RequiredReadAction + private static String generateReferenceTargetList(@Nullable JSReferenceList implementsList, @Nonnull String packageName) { + if (implementsList == null) { + return null; + } + StringBuilder result = null; + + String[] referenceExpressionTexts = implementsList.getReferenceTexts(); + + for (String refExprText : referenceExpressionTexts) { + refExprText = JSImportHandlingUtil.resolveTypeName(refExprText, implementsList); + if (result == null) { + result = new StringBuilder(); + } + else { + result.append(","); + } + + String referencedPackageName = StringUtil.getPackageName(refExprText); + result.append(referencedPackageName.equals(packageName) + ? refExprText.substring(refExprText.lastIndexOf('.') + 1) + : refExprText); + } + return result == null ? null : result.toString(); + } + + @Override + public List getUrlFor(PsiElement element, PsiElement originalElement) { + String possibleCssName = findPossibleCssName(element); + + if (possibleCssName != null) { + try { + DocumentationProvider documentationProvider = getCssProvider(element.getProject()); + Method method = documentationProvider.getClass().getMethod("getUrlFor", new Class[]{String.class}); + Object o = method.invoke(null, new Object[]{possibleCssName}); + + if (o instanceof String) { + return Collections.singletonList((String)o); + } + } + catch (Exception ignored) { + } + } + return null; + } + + @Override + @RequiredReadAction + public String generateDoc(PsiElement _element, PsiElement originalElement) { + if (_element instanceof JSReferenceExpression expression) { + StringBuilder buffer = null; + + // ambigious reference + for (ResolveResult r : expression.multiResolve(false)) { + if (buffer == null) { + buffer = new StringBuilder(); + } + PsiElement element = r.getElement(); + ItemPresentation presentation = ((NavigationItem)element).getPresentation(); + + JSDocumentationUtils.appendHyperLinkToElement( + element, + expression.getReferencedName(), + buffer, + presentation.getPresentableText(), + presentation.getLocationString() + ); + buffer.append("
\n"); + } + return buffer != null ? buffer.toString() : null; + } + + _element = _element.getNavigationElement(); + PsiElement element = findElementForWhichPreviousCommentWillBeSearched(_element); + + boolean parameterDoc = element instanceof JSParameter; + if (parameterDoc) { + element = findElementForWhichPreviousCommentWillBeSearched(PsiTreeUtil.getParentOfType(element, JSFunction.class)); + } + + if (element != null) { + PsiElement docComment = + JSDocumentationUtils.findDocComment(element, _element instanceof JSAttributeNameValuePair ? originalElement : null); + + if (docComment != null) { + docComment = findFirstDocComment(docComment); + element = findTargetElement(_element, element); + JSDocumentationBuilder builder = new JSDocumentationBuilder(element, originalElement); + JSDocumentationUtils.processDocumentationTextFromComment(docComment.getNode(), builder); + + return parameterDoc ? builder.getParameterDoc(((JSParameter)_element).getName()) : builder.getDoc(); + } + + element = findTargetElement(_element, element); + + if (element instanceof JSFunction) { + ASTNode initialComment = JSDocumentationUtils.findLeadingCommentInFunctionBody(element); + + if (initialComment != null) { + JSDocumentationBuilder builder = new JSDocumentationBuilder(element, originalElement); + JSDocumentationUtils.processDocumentationTextFromComment(initialComment, builder); + return builder.getDoc(); + } + } + } + + String possibleCssName = findPossibleCssName(_element); + if (possibleCssName != null) { + try { + DocumentationProvider documentationProvider = getCssProvider(_element.getProject()); + Method declaredMethod = + documentationProvider.getClass().getDeclaredMethod("generateDoc", String.class, PsiElement.class); + Object o = declaredMethod.invoke(null, possibleCssName, null); + + if (o instanceof String) { + return (String)o; + } + } + catch (Exception ignored) { + } + } + + return null; + } + + @RequiredReadAction + private static PsiElement findTargetElement(PsiElement _element, PsiElement element) { + if (_element instanceof JSDefinitionExpression definition) { + if (definition.getParent() instanceof JSAssignmentExpression assignment) { + JSExpression rOperand = assignment.getROperand(); + element = rOperand instanceof JSFunctionExpression ? rOperand : definition; + } + } + else if (_element instanceof JSFunctionExpression function) { + element = function; + } + else if (_element instanceof JSProperty property) { + if (property.getValue() instanceof JSFunction function) { + element = function; + } + } + else if (_element instanceof JSVariable variable) { + if (variable instanceof JSParameter parameter) { + return PsiTreeUtil.getParentOfType(parameter, JSFunction.class); + } + element = variable; + } + else if (_element instanceof JSAttributeNameValuePair nameValuePair) { + return nameValuePair; + } + return element; + } + + @RequiredReadAction + private static PsiElement findFirstDocComment(PsiElement docComment) { + if (docComment.getNode().getElementType() == JSTokenTypes.END_OF_LINE_COMMENT) { + while (true) { + PsiElement prev = docComment.getPrevSibling(); + if (prev instanceof PsiWhiteSpace whiteSpace) { + prev = whiteSpace.getPrevSibling(); + } + if (prev == null) { + break; + } + if (prev.getNode().getElementType() != JSTokenTypes.END_OF_LINE_COMMENT) { + break; + } + docComment = prev; + } + } + return docComment; + } + + private static String findPossibleCssName(PsiElement _element) { + if (_element instanceof JSDefinitionExpression definition) { + JSExpression expression = definition.getExpression(); + + if (expression instanceof JSReferenceExpression reference) { + String text = reference.getReferencedName(); + if (text == null) { + return null; + } + StringBuilder sb = new StringBuilder(text.length()); + + for (int i = 0; i < text.length(); ++i) { + char ch = text.charAt(i); + + if (Character.isUpperCase(ch)) { + sb.append('-').append(Character.toLowerCase(ch)); + } + else { + sb.append(ch); + } + } + + return sb.toString(); + } + } + return null; + } + + @Override + public PsiElement getDocumentationElementForLookupItem(PsiManager psiManager, Object object, PsiElement element) { + PsiElement psiElement = findElementForWhichPreviousCommentWillBeSearched(object); + if (psiElement != null && JSDocumentationUtils.findDocComment(psiElement) != null) { + return psiElement; + } + if (object instanceof PsiElement objPsiElement) { + return objPsiElement; + } + return null; + } + + @RequiredReadAction + public static PsiElement findElementForWhichPreviousCommentWillBeSearched(Object object) { + if (object instanceof JSFunction function) { + PsiElement psiElement = function; + PsiElement parent = psiElement.getParent(); + if (parent instanceof JSNewExpression newExpr) { + parent = newExpr.getParent(); + } + if (parent instanceof JSProperty property) { + psiElement = property; + } + else if (parent instanceof JSAssignmentExpression assignment) { + psiElement = assignment.getParent(); + } + + if (function.isSetProperty() || function.isGetProperty()) { + for (PsiElement el = function.getPrevSibling(); el != null; el = el.getPrevSibling()) { + if (!(el instanceof PsiWhiteSpace) && !(el instanceof PsiComment)) { + if (el instanceof JSFunction prevFunction) { + String name = prevFunction.getName(); + + if (name != null && name.equals(function.getName()) && ( + prevFunction.isGetProperty() && function.isSetProperty() + || prevFunction.isSetProperty() && function.isGetProperty() + )) { + PsiElement doc = JSDocumentationUtils.findDocComment(prevFunction); + if (doc != null) { + return prevFunction; + } + } + } + break; + } + } + } + return psiElement; + } + else if (object instanceof JSProperty || object instanceof JSStatement || object instanceof JSClass) { + return (PsiElement)object; + } + else if (object instanceof PsiElement psiElement) { + PsiElement parent = psiElement.getParent(); + if (parent instanceof JSAssignmentExpression assignment) { + return assignment.getParent(); + } + else if (parent instanceof JSVarStatement varStatement) { + if (varStatement.getFirstChild() instanceof JSAttributeList && JSDocumentationUtils.findDocComment(psiElement) != null) { + return psiElement; + } + return varStatement; + } + else if (parent instanceof JSAttribute attribute) { + PsiElement attrParent = attribute.getParent(); + if (attrParent.getFirstChild() == attribute) { + PsiElement attrGrandParent = attrParent.getParent(); + if (attrGrandParent instanceof JSFile) { + return attrParent; + } + return attrGrandParent; + } + return attribute; + } + else if (parent instanceof JSSuppressionHolder suppressionHolder) { + return suppressionHolder; + } + else { + return psiElement; + } + } + + return null; + } + + @Nullable + @Override + public PsiElement getDocumentationElementForLink(PsiManager psiManager, String link, PsiElement context) { + return getDocumentationElementForLinkStatic(psiManager, link, context); + } + + @Nullable + private static PsiElement getDocumentationElementForLinkStatic(PsiManager psiManager, String link, @Nonnull PsiElement context) { + int delimiterIndex = link.lastIndexOf(':'); + + String attributeType = null; + String attributeName = null; + for (Map.Entry e : DOCUMENTED_ATTRIBUTES.entrySet()) { + String pattern = "." + e.getValue(); + if (link.contains(pattern)) { + attributeType = e.getKey(); + attributeName = link.substring(link.indexOf(pattern) + pattern.length()); + link = link.substring(0, link.indexOf(pattern)); + break; + } + } + if (delimiterIndex != -1 && attributeType == null) { + int delimiterIndex2 = link.lastIndexOf(':', delimiterIndex - 1); + String fileName = link.substring(0, delimiterIndex2).replace(File.separatorChar, '/'); + String name = link.substring(delimiterIndex2 + 1, delimiterIndex); + int offset = Integer.parseInt(link.substring(delimiterIndex + 1)); + return JavaScriptIndex.findSymbolByFileAndNameAndOffset(fileName, name, offset); + } + else if (attributeType != null) { + PsiElement clazz = JSResolveUtil.findClassByQName(link, context.getResolveScope(), psiManager.getProject()); + if (!(clazz instanceof JSClass)) { + return null; + } + return findNamedAttribute((JSClass)clazz, attributeType, attributeName); + } + else { + PsiElement clazz = JSResolveUtil.findClassByQName(link, context.getResolveScope(), psiManager.getProject()); + if (clazz == null && link.contains(".")) { + String qname = link.substring(0, link.lastIndexOf('.')); + clazz = JSResolveUtil.findClassByQName(qname, context.getResolveScope(), psiManager.getProject()); + if (clazz instanceof JSClass jsClass) { + String member = link.substring(link.lastIndexOf('.') + 1); + + if (member.endsWith("()")) { + member = member.substring(0, member.length() - 2); + + PsiElement result = findMethod(jsClass, member); + if (result == null) { + result = findProperty(jsClass, member); // user might refer to a property + } + return result; + } + else { + PsiElement result = jsClass.findFieldByName(member); + if (result == null) { + result = findProperty(jsClass, member); + } + if (result == null) { + result = findMethod(jsClass, member); // user might forget brackets + } + return result; + } + } + } + + if (clazz instanceof JSVariable) { + return clazz; + } + + if (link.endsWith("()")) { + link = link.substring(0, link.length() - 2); + clazz = JSResolveUtil.findClassByQName(link, context.getResolveScope(), psiManager.getProject()); + if (clazz instanceof JSFunction) { + return clazz; + } + } + return clazz; + } + } + + @Nullable + @RequiredReadAction + protected static JSAttributeNameValuePair findNamedAttribute(JSClass clazz, String type, String name) { + SimpleReference attribute = new SimpleReference<>(); + JSResolveUtil.processMetaAttributesForClass(clazz, new JSResolveUtil.MetaDataProcessor() { + @Override + @RequiredReadAction + public boolean process(@Nonnull JSAttribute jsAttribute) { + if (type.equals(jsAttribute.getName())) { + JSAttributeNameValuePair jsAttributeNameValuePair = jsAttribute.getValueByName("name"); + if (jsAttributeNameValuePair != null && name.equals(jsAttributeNameValuePair.getSimpleValue())) { + attribute.set(jsAttributeNameValuePair); + return false; + } + } + return true; + } + + @Override + public boolean handleOtherElement(PsiElement el, PsiElement context, @Nullable SimpleReference continuePassElement) { + return true; + } + }); + return attribute.get(); + } + + private static PsiElement findProperty(JSClass jsClass, String name) { + PsiElement result = jsClass.findFunctionByNameAndKind(name, JSFunction.FunctionKind.GETTER); + if (result == null) { + result = jsClass.findFunctionByNameAndKind(name, JSFunction.FunctionKind.SETTER); + } + return result; + } + + private static PsiElement findMethod(JSClass jsClass, String name) { + PsiElement result = jsClass.findFunctionByNameAndKind(name, JSFunction.FunctionKind.CONSTRUCTOR); + if (result == null) { + result = jsClass.findFunctionByNameAndKind(name, JSFunction.FunctionKind.SIMPLE); + } + return result; + } + + @Nullable + @Override + public PsiComment findExistingDocComment(PsiComment contextElement) { + return contextElement; + } + + @Nullable + @Override + public Pair parseContext(@Nonnull PsiElement element) { + return null; + } + + @Nullable + @Override + @RequiredReadAction + public String generateDocumentationContentStub(PsiComment contextComment) { + for (PsiElement el = contextComment.getParent(); el != null; el = el.getNextSibling()) { + if (el instanceof JSProperty property) { + if (property.getValue() instanceof JSFunction function) { + return doGenerateDoc(function); + } + } + else if (el instanceof JSFunction function) { + return doGenerateDoc(function); + } + else if (el instanceof JSExpressionStatement expression) { + if (expression.getExpression() instanceof JSAssignmentExpression assignment + && assignment.getROperand() instanceof JSFunctionExpression functionExpr) { + return doGenerateDoc(functionExpr.getFunction()); + } + } + else if (el instanceof JSVarStatement varStatement) { + JSVariable[] variables = varStatement.getVariables(); + if (variables.length > 0 && variables[0].getInitializer() instanceof JSFunctionExpression functionExpr) { + return doGenerateDoc(functionExpr.getFunction()); + } + break; + } + } + return null; + } + + @RequiredReadAction + private static String doGenerateDoc(JSFunction function) { + StringBuilder builder = new StringBuilder(); + JSParameterList parameterList = function.getParameterList(); + PsiFile containingFile = function.getContainingFile(); + boolean ecma = containingFile.getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4; + + if (parameterList != null) { + for (JSParameter parameter : parameterList.getParameters()) { + builder.append("* @param ").append(parameter.getName()); + //String s = JSPsiImplUtils.getTypeFromDeclaration(parameter); + //if (s != null) builder.append(" : ").append(s); + builder.append("\n"); + } + } + + if (ecma) { + String s = JSPsiImplUtils.getTypeFromDeclaration(function); + + if (s != null && !"void".equals(s)) { + builder.append("* @return "); + + //builder.append(s); + builder.append("\n"); + } + } + + return builder.toString(); + } + + @Nullable + @RequiredReadAction + protected static String getSeeAlsoLinkResolved(PsiElement originElement, String link) { + JSQualifiedNamedElement qualifiedElement = findParentQualifiedElement(originElement); + if (qualifiedElement == null) { + return null; + } + String linkToResolve = getLinkToResolve(qualifiedElement, link); + PsiElement resolvedElement = getDocumentationElementForLinkStatic(originElement.getManager(), linkToResolve, originElement); + if (resolvedElement != null) { + return linkToResolve; + } + return null; + } + + private static String getLinkToResolve(JSQualifiedNamedElement origin, String link) { + String originQname = origin.getQualifiedName(); + if (link.length() == 0) { + return originQname; + } + else if (StringUtil.startsWithChar(link, '#')) { + if (origin instanceof JSClass) { + return originQname + "." + link.substring(1); + } + else { + String aPackage = StringUtil.getPackageName(originQname); + return aPackage + "." + link.substring(1); + } + } + else { + String linkFile = link.contains("#") ? link.substring(0, link.lastIndexOf('#')) : link; + String linkAnchor = link.contains("#") ? link.substring(link.lastIndexOf('#') + 1) : null; + + String qname; + if (StringUtil.endsWithIgnoreCase(linkFile, HTML_EXTENSION)) { + String prefix = StringUtil.getPackageName(originQname); + while (linkFile.startsWith("../")) { + linkFile = linkFile.substring("../".length()); + prefix = StringUtil.getPackageName(prefix); + } + + String linkFilename; + if (linkFile.endsWith(PACKAGE_FILE)) { + linkFilename = StringUtil.trimEnd(linkFile, PACKAGE_FILE); + linkFilename = StringUtil.trimEnd(linkFilename, "/"); + } + else { + linkFilename = linkFile.substring(0, linkFile.lastIndexOf(".")); + } + if (linkFilename.length() > 0) { + qname = (prefix.length() > 0 ? prefix + "." : prefix) + linkFilename.replaceAll("/", "."); + } + else { + qname = prefix; + } + } + else { + qname = linkFile; + } + + return linkAnchor != null ? (qname.length() > 0 ? qname + "." : qname) + linkAnchor : qname; + } + } + + @Nullable + @RequiredReadAction + protected static JSQualifiedNamedElement findParentQualifiedElement(PsiElement element) { + if (element instanceof JSClass jsClass) { + return jsClass; + } + if (element instanceof JSFunction || element instanceof JSVariable) { + PsiElement parent = JSResolveUtil.findParent(element); + if (parent instanceof JSClass jsClass) { + return jsClass; + } + else if (parent instanceof JSFile) { + return (JSQualifiedNamedElement) element; + } + } + + JSAttribute attribute = null; + if (element instanceof JSAttribute jsAttribute) { + attribute = jsAttribute; + } + else if (element instanceof JSAttributeNameValuePair nameValuePair) { + attribute = (JSAttribute)nameValuePair.getParent(); + } + + if (attribute != null && DOCUMENTED_ATTRIBUTES.containsKey(attribute.getName())) { + JSClass jsClass = PsiTreeUtil.getParentOfType(element, JSClass.class); + if (jsClass != null) { + return jsClass; + } + } + + return null; + } + + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } } diff --git a/base-impl/src/main/java/com/intellij/javascript/documentation/JSDocumentationUtils.java b/base-impl/src/main/java/com/intellij/javascript/documentation/JSDocumentationUtils.java index 7501dd11..41c3a360 100644 --- a/base-impl/src/main/java/com/intellij/javascript/documentation/JSDocumentationUtils.java +++ b/base-impl/src/main/java/com/intellij/javascript/documentation/JSDocumentationUtils.java @@ -26,6 +26,7 @@ import com.intellij.lang.javascript.JSTokenTypes; import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; +import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.ASTNode; import consulo.language.ast.IElementType; import consulo.language.ast.TokenSet; @@ -34,11 +35,10 @@ import consulo.language.psi.*; import consulo.language.psi.util.PsiTreeUtil; import consulo.util.lang.StringUtil; -import consulo.util.lang.ref.Ref; -import org.jetbrains.annotations.NonNls; +import consulo.util.lang.ref.SimpleReference; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; @@ -46,933 +46,811 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -public class JSDocumentationUtils -{ - private static final - @NonNls - Pattern ourDojoParametersPattern = Pattern.compile("^\\s*(\\w+):(.*)$"); - private static final - @NonNls - Pattern ourJSDocParametersPattern = Pattern.compile("^\\s*@param\\s*(?:\\{([^\\}]+)\\}\\s*)?(\\w+)?(?:\\s:\\s(\\S+))?(?:\\s*\\[(\\w+)(?:\\.(\\w+))?" + - "(?:=([^\\]]*))?\\])?(.*)$"); - private static final - @NonNls - Pattern ourJSDocEventPattern = Pattern.compile("^\\s*@event\\s*(\\w+)(?:\\s:\\s(\\S+))?(.*)$"); - private static final - @NonNls - Pattern ourJSDocRemarkPattern = Pattern.compile("^\\s*@remarks (.*)$"); - private static final - @NonNls - Pattern ourJSDocMethodPattern = Pattern.compile("^\\s*@method\\s*(\\w+)(.*)$"); - private static final - @NonNls - Pattern ourJSDocClassPattern = Pattern.compile("^\\s*@class\\s*(\\w+(?:\\.\\w+)*)(.*)$"); - private static final - @NonNls - Pattern ourJSDocDeprecatedPattern = Pattern.compile("^\\s*@deprecated\\s*(.*)$"); - - private static final - @NonNls - Pattern ourJSDocConstructorPattern = Pattern.compile("^\\s*@constructor$"); - private static final - @NonNls - Pattern ourJSDocFinalPattern = Pattern.compile("^\\s*@final$"); - private static final - @NonNls - Pattern ourJSDocPrivatePattern = Pattern.compile("^\\s*@private$"); - private static final - @NonNls - Pattern ourJSDocPublicPattern = Pattern.compile("^\\s*@public$"); - private static final - @NonNls - Pattern ourJSDocProtectedPattern = Pattern.compile("^\\s*@protected$"); - - private static final - @NonNls - Pattern ourJSDocOptionalPattern = Pattern.compile("^\\s*@optional(.*)$"); - private static final - @NonNls - Pattern ourJSDocStaticPattern = Pattern.compile("^\\s*@static$"); - private static final - @NonNls - Pattern ourJSDocSeePattern = Pattern.compile("^\\s*@see (.*)$"); - private static final - @NonNls - Pattern ourJSDocDescriptionPattern = Pattern.compile("^\\s*@description\\s*(.+)$"); - private static final - @NonNls - Pattern ourJSDocReturnPattern = Pattern.compile("^\\s*@return(?:s)?\\s*(?:(?:\\{|:)?\\s*([^\\s\\}]+)\\s*\\}?\\s*)?(.*)$"); - private static final - @NonNls - Pattern ourJSDocNamespacePattern = Pattern.compile("^\\s*@namespace\\s*([\\w\\.]+)(.*)$"); - - private static final - @NonNls - Pattern ourJSDocPropertyPattern = Pattern.compile("^\\s*@property\\s*(\\w+)(.*)$"); - private static final - @NonNls - Pattern ourJSDocTypePattern = Pattern.compile("^\\s*@type\\s*\\{?([^\\s\\}]+)\\}?(.*)$"); - private static final - @NonNls - Pattern ourJSDocRequiresPattern = Pattern.compile("^\\s*@requires\\s*(\\S+)(.*)$"); - private static final - @NonNls - Pattern ourJSDocDefaultPattern = Pattern.compile("^\\s*@default\\s*(.*)$"); - private static final - @NonNls - Pattern ourJSDocExtendsPattern = Pattern.compile("^\\s*@extends\\s*(.*)$"); - - private static final - @NonNls - Map patternToHintMap = new HashMap(); - private static final - @NonNls - Map patternToMetaDocTypeMap = new HashMap(); - - static - { - patternToHintMap.put(ourDojoParametersPattern, ":"); - patternToMetaDocTypeMap.put(ourDojoParametersPattern, JSDocumentationProcessor.MetaDocType.PARAMETER); - patternToHintMap.put(ourJSDocParametersPattern, "@pa"); - patternToMetaDocTypeMap.put(ourJSDocParametersPattern, JSDocumentationProcessor.MetaDocType.PARAMETER); - - patternToHintMap.put(ourJSDocMethodPattern, "@m"); - patternToMetaDocTypeMap.put(ourJSDocMethodPattern, JSDocumentationProcessor.MetaDocType.METHOD); - - patternToHintMap.put(ourJSDocOptionalPattern, "@o"); - patternToMetaDocTypeMap.put(ourJSDocOptionalPattern, JSDocumentationProcessor.MetaDocType.OPTIONAL_PARAMETERS); - - patternToHintMap.put(ourJSDocEventPattern, "@ev"); - patternToMetaDocTypeMap.put(ourJSDocEventPattern, JSDocumentationProcessor.MetaDocType.EVENT); - - patternToHintMap.put(ourJSDocExtendsPattern, "@ex"); - patternToMetaDocTypeMap.put(ourJSDocExtendsPattern, JSDocumentationProcessor.MetaDocType.EXTENDS); - - patternToHintMap.put(ourJSDocRemarkPattern, "@rem"); - patternToMetaDocTypeMap.put(ourJSDocRemarkPattern, JSDocumentationProcessor.MetaDocType.NOTE); - - patternToHintMap.put(ourJSDocReturnPattern, "@ret"); - patternToMetaDocTypeMap.put(ourJSDocReturnPattern, JSDocumentationProcessor.MetaDocType.RETURN); - - patternToHintMap.put(ourJSDocPublicPattern, "@pu"); - patternToMetaDocTypeMap.put(ourJSDocPublicPattern, JSDocumentationProcessor.MetaDocType.PUBLIC); - - patternToHintMap.put(ourJSDocProtectedPattern, "@prot"); - patternToMetaDocTypeMap.put(ourJSDocProtectedPattern, JSDocumentationProcessor.MetaDocType.PROTECTED); - - patternToHintMap.put(ourJSDocStaticPattern, "@st"); - patternToMetaDocTypeMap.put(ourJSDocStaticPattern, JSDocumentationProcessor.MetaDocType.STATIC); - - patternToHintMap.put(ourJSDocSeePattern, "@se"); - patternToMetaDocTypeMap.put(ourJSDocSeePattern, JSDocumentationProcessor.MetaDocType.SEE); - - patternToHintMap.put(ourJSDocDescriptionPattern, "@des"); - patternToMetaDocTypeMap.put(ourJSDocDescriptionPattern, JSDocumentationProcessor.MetaDocType.DESCRIPTION); - - patternToHintMap.put(ourJSDocDeprecatedPattern, "@dep"); - patternToMetaDocTypeMap.put(ourJSDocDeprecatedPattern, JSDocumentationProcessor.MetaDocType.DEPRECATED); - - patternToHintMap.put(ourJSDocConstructorPattern, "@co"); - - patternToMetaDocTypeMap.put(ourJSDocConstructorPattern, JSDocumentationProcessor.MetaDocType.CONSTRUCTOR); - - patternToHintMap.put(ourJSDocClassPattern, "@cl"); - patternToMetaDocTypeMap.put(ourJSDocClassPattern, JSDocumentationProcessor.MetaDocType.CLASS); - patternToHintMap.put(ourJSDocPrivatePattern, "@pri"); - patternToMetaDocTypeMap.put(ourJSDocPrivatePattern, JSDocumentationProcessor.MetaDocType.PRIVATE); - - patternToHintMap.put(ourJSDocNamespacePattern, "@n"); - patternToMetaDocTypeMap.put(ourJSDocNamespacePattern, JSDocumentationProcessor.MetaDocType.NAMESPACE); - - patternToHintMap.put(ourJSDocPropertyPattern, "@prop"); - patternToHintMap.put(ourJSDocTypePattern, "@t"); - patternToMetaDocTypeMap.put(ourJSDocTypePattern, JSDocumentationProcessor.MetaDocType.TYPE); - - patternToHintMap.put(ourJSDocFinalPattern, "@f"); - patternToMetaDocTypeMap.put(ourJSDocFinalPattern, JSDocumentationProcessor.MetaDocType.FINAL); - patternToHintMap.put(ourJSDocRequiresPattern, "@req"); - patternToMetaDocTypeMap.put(ourJSDocRequiresPattern, JSDocumentationProcessor.MetaDocType.REQUIRES); - - patternToHintMap.put(ourJSDocDefaultPattern, "@def"); - patternToMetaDocTypeMap.put(ourJSDocDefaultPattern, JSDocumentationProcessor.MetaDocType.DEFAULT); - } - - private static final - @NonNls - Map prefixToPatternToHintMap = new HashMap(); - - static - { - prefixToPatternToHintMap.put(Pattern.compile("^\\s*description:(.*)$"), "descr"); - - prefixToPatternToHintMap.put(Pattern.compile("^ summary(?:\\:)?(.*)$"), "summ"); - - prefixToPatternToHintMap.put(Pattern.compile("^\\s*\\*(?:\\*)?(.*)$"), "*"); - - prefixToPatternToHintMap.put(Pattern.compile("^[/]+(.*)$"), "/"); - - prefixToPatternToHintMap.put(Pattern.compile("^\\s*Parameters:(.*)$"), "Parame"); - } - - public static void processDocumentationTextFromComment(ASTNode _initialComment, JSDocumentationProcessor processor) - { - ASTNode prev = _initialComment.getTreePrev(); - - if(prev != null && prev.getPsi() instanceof OuterLanguageElement) - { - while(prev.getPsi() instanceof OuterLanguageElement) - { - prev = prev.getTreePrev(); - } - } - else - { - prev = null; - } - - if(prev != null && !(prev.getPsi() instanceof PsiComment)) - { - prev = null; - } - - final ASTNode initialComment = prev != null ? prev : _initialComment; - Enumeration commentLineIterator; - - if(initialComment.getElementType() == JSTokenTypes.END_OF_LINE_COMMENT) - { - commentLineIterator = new Enumeration() - { - ASTNode commentNode = initialComment; - - @Override - public boolean hasMoreElements() - { - return commentNode != null; - } - - @Override - public String nextElement() - { - ASTNode resultCommentNode = commentNode; - commentNode = commentNode.getTreeNext(); - - if(commentNode != null && commentNode.getElementType() == TokenType.WHITE_SPACE) - { - commentNode = commentNode.getTreeNext(); - } - - if(commentNode != null && commentNode.getElementType() != JSTokenTypes.END_OF_LINE_COMMENT) - { - commentNode = null; - } - - final String text = resultCommentNode.getText(); - if(text.startsWith("//")) - { - return text.substring(2); - } - return ""; - } - }; - } - else - { - String text = initialComment.getText(); - text = unwrapCommentDelimiters(text); - - commentLineIterator = new StringTokenizer(text, "\r\n"); - } - - final boolean needPlainCharData = processor.needsPlainCommentData(); - - while(commentLineIterator.hasMoreElements()) - { - final String s = (String) commentLineIterator.nextElement(); - if(s.indexOf('@') == -1 && s.indexOf(':') == -1 && !needPlainCharData) - { - continue; - } - - String commentText = s.replace('\t', ' '); - - for(Map.Entry entry : prefixToPatternToHintMap.entrySet()) - { - final Matcher matcher = commentText.indexOf(entry.getValue()) != -1 ? entry.getKey().matcher(commentText) : null; - if(matcher == null) - { - continue; - } - - if(matcher.matches()) - { - commentText = matcher.group(1); - break; - } - } - - boolean matchedSomething = false; - - for(Map.Entry entry : patternToHintMap.entrySet()) - { - final Matcher matcher = commentText.indexOf(entry.getValue()) != -1 ? entry.getKey().matcher(commentText) : null; - if(matcher == null) - { - continue; - } - - if(matcher.matches()) - { - final JSDocumentationProcessor.MetaDocType docType = patternToMetaDocTypeMap.get(entry.getKey()); - if(docType != null) - { - final int groupCount = matcher.groupCount(); - String remainingLineContent = groupCount > 0 ? matcher.group(groupCount) : null; - String matchName = groupCount > 1 ? matcher.group(1) : null; - String matchValue = groupCount > 2 ? matcher.group(2) : null; - - boolean reportAboutOptionalParameter = false; - boolean reportAboutFieldInParameter = false; - boolean reportAboutDefaultValue = false; - - final int groupForInitialValue = 6; - final int groupForFieldName = 5; - String fieldName = null; - - if(groupCount == 7 && entry.getKey() == ourJSDocParametersPattern) - { - String paramNameInBracket = matcher.group(4); - - if(paramNameInBracket != null) - { - String tmp = matchName; - matchName = paramNameInBracket; - matchValue = tmp; - reportAboutFieldInParameter = (fieldName = matcher.group(groupForFieldName)) != null; - reportAboutOptionalParameter = true; - reportAboutDefaultValue = matcher.group(groupForInitialValue) != null; - } - else - { - String typeAfterParamName = matcher.group(3); - if(typeAfterParamName != null) - { - matchName = matchValue; - matchValue = typeAfterParamName; - } - else - { - String tmp = matchValue; - matchValue = matchName; - matchName = tmp; - } - } - } - - String matched = entry.getKey().pattern(); - - if(reportAboutFieldInParameter) - { - if(!processor.onPatternMatch(JSDocumentationProcessor.MetaDocType.FIELD, matchName, null, matcher.group(groupForFieldName), commentText, matched)) - - { - break; - } - } - else - { - if(!processor.onPatternMatch(docType, matchName, matchValue, remainingLineContent, commentText, matched)) - { - break; - } - } - if(reportAboutOptionalParameter) - { - if(!processor.onPatternMatch(JSDocumentationProcessor.MetaDocType.OPTIONAL_PARAMETERS, matchName, fieldName, null, commentText, matched)) - { - break; - } - } - - if(reportAboutDefaultValue) - { - if(!processor.onPatternMatch(JSDocumentationProcessor.MetaDocType.DEFAULT, matchName, fieldName, matcher.group(groupForInitialValue), commentText, matched)) - { - break; - } - } - } - matchedSomething = true; - break; - } - } - - if(!matchedSomething && needPlainCharData) - { - if(!processor.onCommentLine(commentText)) - { - break; - } - } - } - } - - public static String unwrapCommentDelimiters(String text) - { - if(text.startsWith("/**")) - { - text = text.substring(3); - } - else if(text.startsWith("/*") || text.startsWith("//")) - { - text = text.substring(2); - } - - if(text.endsWith("*/")) - { - text = text.substring(0, text.length() - 2); - } - return text; - } - - static - @Nullable - ASTNode findTrailingCommentInFunctionBody(final @Nonnull JSFunction function) - { - final ASTNode block = function.getNode().findChildByType(JSElementTypes.BLOCK_STATEMENT); - if(block == null) - { - return null; - } - - for(ASTNode prev = block.getLastChildNode(); prev != null; prev = prev.getTreePrev()) - { - if(prev.getElementType() == JSElementTypes.RETURN_STATEMENT) - { - return block.findChildByType(JSTokenTypes.COMMENTS, prev); - } - else if(prev.getPsi() instanceof JSStatement) - { - break; - } - } - return null; - } - - static - @Nullable - ASTNode findLeadingCommentInFunctionBody(final @Nonnull PsiElement element) - { - final ASTNode functionNode = element.getNode(); - final ASTNode block = functionNode.findChildByType(JSElementTypes.BLOCK_STATEMENT); - if(block == null) - { - return null; - } - - for(ASTNode node = block.getFirstChildNode().getTreeNext(); node != null; node = node.getTreeNext()) - { - final IElementType nodeType = node.getElementType(); - - if(nodeType != TokenType.WHITE_SPACE) - { - if(JSTokenTypes.COMMENTS.contains(nodeType)) - { - return node; - } - return null; - } - } - - return null; - } - - public static PsiElement findDocComment(PsiElement element) - { - return findDocComment(element, null); - } - - public static PsiElement findDocComment(PsiElement element, PsiElement context) - { - PsiElement docComment = null; - boolean skippedExprStatementOnce = false; - - if(element instanceof JSAttributeListOwner && context == null) - { - final JSAttributeListOwner jsClass = (JSAttributeListOwner) element; - final JSAttributeList attributeList = jsClass.getAttributeList(); - PsiElement anchor = null; - - if(attributeList != null) - { - for(ASTNode currentNode = attributeList.getNode().getLastChildNode(); currentNode != null; currentNode = currentNode.getTreePrev()) - { - final IElementType nodeType = currentNode.getElementType(); - - if(!JSTokenTypes.MODIFIERS.contains(nodeType) && - nodeType != JSTokenTypes.WHITE_SPACE && - nodeType != JSElementTypes.REFERENCE_EXPRESSION // namespace - ) - { - final ASTNode nextNode = currentNode.getTreeNext(); - if(nextNode != null) - { - anchor = nextNode.getPsi(); - } - break; - } - } - } - - if(anchor != null) - { - element = anchor; - } - } - - if(!element.isValid() || element.getContainingFile() == null) - { - return docComment; - } - - boolean shouldSkipPrevExprStatement = false; - String propName = getPropertyNameFromExprStatement(element); - if(propName != null) - { - shouldSkipPrevExprStatement = true; - } - - for(PsiElement prev = element.getPrevSibling(); prev != null; prev = prev.getPrevSibling()) - { - if(prev instanceof PsiWhiteSpace) - { - continue; - } - - if(prev instanceof PsiComment) - { - docComment = prev; - if(((PsiComment) prev).getTokenType() == JSTokenTypes.DOC_COMMENT) - { - break; - } - } - else if(shouldSkipPrevExprStatement && - prev instanceof JSExpressionStatement && - !skippedExprStatementOnce) - { - String propNameFromPrev = getPropertyNameFromExprStatement(prev); - if(!propName.equals(propNameFromPrev)) - { - break; - } - skippedExprStatementOnce = true; // presumably another accessor definition - continue; - } - - break; - } - - if(docComment != null) - { - while(docComment.getPrevSibling() instanceof OuterLanguageElement) - { - PsiElement siblingSibling = docComment.getPrevSibling().getPrevSibling(); - - if(siblingSibling != null && siblingSibling instanceof PsiComment) - { - docComment = siblingSibling; - } - else - { - break; - } - } - } - return docComment; - } - - private static - @Nullable - String getPropertyNameFromExprStatement(@Nonnull PsiElement element) - { - String propName = null; - - if(element instanceof JSExpressionStatement) - { - JSExpression expression = ((JSExpressionStatement) element).getExpression(); - if(expression instanceof JSAssignmentExpression) - { - JSExpression rOperand = ((JSAssignmentExpression) expression).getROperand(); - if(rOperand instanceof JSFunctionExpression) - { - String name = ((JSFunctionExpression) rOperand).getName(); - if(name != null && (StringUtil.startsWith(name, "get") || (StringUtil.startsWith(name, "set")))) - { - propName = name.substring(3); - } - } - } - } - return propName; - } - - private static String findTypeFromParameter(final JSVariable parameter, final PsiElement docComment) - { - if(docComment != null) - { - final String[] detectedType = new String[1]; - - processDocumentationTextFromComment(docComment.getNode(), new JSDocumentationProcessor() - { - final String name = parameter.getName(); - final boolean isparameter = parameter instanceof JSParameter; - - @Override - public boolean needsPlainCommentData() - { - return false; - } - - @Override - public boolean onCommentLine(@Nonnull final String line) - { - return true; - } - - @Override - public boolean onPatternMatch(@Nonnull final MetaDocType type, @Nullable final String matchName, @Nullable final String matchValue, - @Nullable final String remainingLineContent, @Nonnull final String line, final String patternMatched) - { - if(isparameter && type == MetaDocType.PARAMETER && matchName != null && matchName.equals(name)) - { - detectedType[0] = matchValue; - return false; - } - else if(type == MetaDocType.TYPE) - { - detectedType[0] = matchName; - return false; - } - return true; - } - }); - - return detectedType[0]; - } - return null; - } - - public static final TokenSet ourPrimitiveTypeFilter = TokenSet.create(JSTokenTypes.INT_KEYWORD, JSTokenTypes.UINT_KEYWORD, - JSTokenTypes.VOID_KEYWORD, JSTokenTypes.ANY_IDENTIFIER); - public static final TokenSet ourTypeFilter = TokenSet.orSet(TokenSet.create(JSElementTypes.REFERENCE_EXPRESSION), ourPrimitiveTypeFilter); - - private static String findDocForAnchor(final PsiElement _anchor, final JSDocumentationProcessor.MetaDocType... expectedTypes) - { - PsiElement anchor = _anchor; - if(_anchor instanceof JSExpression) - { - anchor = PsiTreeUtil.getParentOfType(_anchor, JSStatement.class, JSProperty.class); - } - - if(anchor != null) - { - final PsiElement docComment = findDocComment(anchor); - - if(docComment != null) - { - final Ref detectedType = new Ref(); - - final PsiElement anchor1 = anchor; - processDocumentationTextFromComment(docComment.getNode(), new JSDocumentationProcessor() - { - @Override - public boolean needsPlainCommentData() - { - return false; - } - - @Override - public boolean onCommentLine(@Nonnull final String line) - { - return true; - } - - @Override - public boolean onPatternMatch(@Nonnull final MetaDocType type, @Nullable final String matchName, @Nullable final String matchValue, - @Nullable final String remainingLineContent, @Nonnull final String line, final String patternMatched) - { - for(MetaDocType expectedType : expectedTypes) - { - if(type == expectedType) - { - if(type == MetaDocType.TYPE && _anchor instanceof JSFunction) - { - final JSParameterList jsParameterList = ((JSFunction) _anchor).getParameterList(); - if(jsParameterList != null && jsParameterList.getParameters().length > 0) - { - return true; - } - if(_anchor.getParent() instanceof JSProperty) - { - return true; - } - } - else if(type == MetaDocType.RETURN) - { - //if (!isOurDocComment()) return true; - } - - detectedType.set(matchName); - return false; - } - } - return true; - } - }); - - return detectedType.get(); - } - } - return null; - } - - public static String findType(final PsiElement def) - { - return findDocForAnchor(def, JSDocumentationProcessor.MetaDocType.TYPE); - } - - public static boolean isDeprecated(PsiElement element) - { - if(element instanceof JSClass) - { - return ((JSClass) element).isDeprecated(); - } - else if(element instanceof JSFunction) - { - return ((JSFunction) element).isDeprecated(); - } - else if(element instanceof JSVariable) - { - return ((JSVariable) element).isDeprecated(); - } - else if(element instanceof JSNamespaceDeclaration) - { - return ((JSNamespaceDeclaration) element).isDeprecated(); - } - - return calculateDeprecated(element); - } - - public static boolean calculateDeprecated(PsiElement element) - { - if(element instanceof JSExpression) - { - element = PsiTreeUtil.getParentOfType(element, JSStatement.class, JSProperty.class); - } - - final PsiElement docComment = element != null ? findDocComment(element) : null; - if(docComment != null) - { - final boolean[] deprecatedStatus = new boolean[1]; - - processDocumentationTextFromComment(docComment.getNode(), new JSDocumentationProcessor() - { - @Override - public boolean needsPlainCommentData() - { - return false; - } - - @Override - public boolean onCommentLine(@Nonnull final String line) - { - return true; - } - - @Override - public boolean onPatternMatch(@Nonnull final MetaDocType type, @Nullable final String matchName, @Nullable final String matchValue, - @Nullable final String remainingLineContent, @Nonnull final String line, final String patternMatched) - { - if(type == MetaDocType.DEPRECATED) - { - deprecatedStatus[0] = true; - return false; - } - return true; - } - }); - - return deprecatedStatus[0]; - } - return false; - } - - public static void appendHyperLinkToElement(@Nullable PsiElement element, String elementName, final StringBuilder buffer, - final String presentableName, final @Nullable String presentableFileName) - { - final PsiFile containingFile = element != null ? element.getContainingFile() : null; - String fileName = containingFile == null ? null : !JSResolveUtil.isPredefinedFile(containingFile) ? containingFile.getVirtualFile() - .getPresentableUrl() : containingFile.getViewProvider().getVirtualFile().getName(); - - DocumentationManagerUtil.createHyperlink(buffer, (fileName != null ? fileName + ":" : "") + elementName + (element != null ? ":" + element - .getTextOffset() : ""), presentableName + (presentableFileName != null ? " in " + presentableFileName : ""), true); - } - - private static String evaluateTypeFromParameter(final JSParameter parameter) - { - String s = evaluateTypeFromVariable(parameter); - - if(s == null) - { - s = findTypeFromParameter(parameter, findFunctionComment(parameter)); - } - - return s; - } - - private static PsiElement findFunctionComment(JSParameter parameter) - { - PsiElement anchor = PsiTreeUtil.getParentOfType(parameter, JSFunction.class); - - if(anchor instanceof JSFunctionExpression) - { - anchor = PsiTreeUtil.getParentOfType(anchor, JSStatement.class, JSProperty.class); - } - - if(anchor != null) - { - return findDocComment(anchor); - } - return null; - } - - private static String evaluateTypeFromFunction(final JSFunction function) - { - final ASTNode lastCommentInFunctionBody = findTrailingCommentInFunctionBody(function); - - String typeString = null; - if(lastCommentInFunctionBody != null) - { - typeString = unwrapCommentDelimiters(lastCommentInFunctionBody.getText()).trim(); - } - - if(typeString == null) - { - typeString = findDocForAnchor(function, JSDocumentationProcessor.MetaDocType.RETURN, JSDocumentationProcessor.MetaDocType.TYPE); - } - return typeString; - } - - private static String evaluateTypeFromVariable(final JSVariable variable) - { - PsiElement prevSibling = variable.getFirstChild(); - if(prevSibling != null && prevSibling.getNode().getElementType() == JSTokenTypes.IDENTIFIER) - { - prevSibling = variable.getPrevSibling(); - } - - if(prevSibling instanceof PsiWhiteSpace) - { - prevSibling = prevSibling.getPrevSibling(); - } - - if(prevSibling instanceof PsiComment && prevSibling.getNode().getElementType() != JSTokenTypes.END_OF_LINE_COMMENT) - { - String parameterCommentText = prevSibling.getText(); - parameterCommentText = unwrapCommentDelimiters(parameterCommentText).trim(); - - if(parameterCommentText.length() > 0 && (Character.isUpperCase(parameterCommentText.charAt(0)) || parameterCommentText.indexOf(' ') == -1)) - { - return parameterCommentText; - } - } - - if(prevSibling != null && prevSibling.getNode() != null && prevSibling.getNode().getElementType() == JSTokenTypes.VAR_KEYWORD) - { - prevSibling = variable.getParent().getPrevSibling(); - - if(prevSibling instanceof PsiWhiteSpace) - { - prevSibling = prevSibling.getPrevSibling(); - } - - if(prevSibling instanceof PsiComment) - { - return findTypeFromParameter(variable, prevSibling); - } - - } - return null; - } - - public static String findTypeFromComments(final JSNamedElement element) - { - if(element instanceof JSParameter) - { - return evaluateTypeFromParameter((JSParameter) element); - } - else if(element instanceof JSVariable) - { - return evaluateTypeFromVariable((JSVariable) element); - } - else if(element instanceof JSFunction) - { - return evaluateTypeFromFunction((JSFunction) element); - } - return null; - } - - public static boolean isSymbolReference(String content) - { - int i = content.indexOf(' '); - if(i == -1) - { - return false; - } - String text = content.substring(0, i); - return text.indexOf('.') != -1 || text.indexOf('#') != -1; - } - - public static boolean findOptionalStatusFromComments(final JSParameter parameter) - { - PsiElement docComment = findFunctionComment(parameter); - if(docComment == null) - { - return false; - } - - final boolean[] detectedType = new boolean[1]; - - processDocumentationTextFromComment(docComment.getNode(), new JSDocumentationProcessor() - { - final String name = parameter.getName(); - - @Override - public boolean needsPlainCommentData() - { - return false; - } - - @Override - public boolean onCommentLine(@Nonnull final String line) - { - return true; - } - - @Override - public boolean onPatternMatch(@Nonnull final MetaDocType type, @Nullable final String matchName, @Nullable final String matchValue, - @Nullable final String remainingLineContent, @Nonnull final String line, final String patternMatched) - { - if(type == MetaDocType.OPTIONAL_PARAMETERS && matchName != null && matchName.equals(name) && matchValue == null) - { - detectedType[0] = true; - return false; - } - - return true; - } - }); - - return detectedType[0]; - } +public class JSDocumentationUtils { + private static final Pattern DOJO_PARAMETERS_PATTERN = Pattern.compile("^\\s*(\\w+):(.*)$"); + private static final Pattern JS_DOC_PARAMETERS_PATTERN = Pattern.compile( + "^\\s*@param\\s*(?:\\{([^}]+)}\\s*)?(\\w+)?(?:\\s:\\s(\\S+))?(?:\\s*\\[(\\w+)(?:\\.(\\w+))?(?:=([^\\]]*))?])?(.*)$" + ); + private static final Pattern JS_DOC_EVENT_PATTERN = Pattern.compile("^\\s*@event\\s*(\\w+)(?:\\s:\\s(\\S+))?(.*)$"); + private static final Pattern JS_DOC_REMARK_PATTERN = Pattern.compile("^\\s*@remarks (.*)$"); + private static final Pattern JS_DOC_METHOD_PATTERN = Pattern.compile("^\\s*@method\\s*(\\w+)(.*)$"); + private static final Pattern JS_DOC_CLASS_PATTERN = Pattern.compile("^\\s*@class\\s*(\\w+(?:\\.\\w+)*)(.*)$"); + private static final Pattern JS_DOC_DEPRECATED_PATTERN = Pattern.compile("^\\s*@deprecated\\s*(.*)$"); + private static final Pattern JS_DOC_CONSTRUCTOR_PATTERN = Pattern.compile("^\\s*@constructor$"); + private static final Pattern JS_DOC_FINAL_PATTERN = Pattern.compile("^\\s*@final$"); + private static final Pattern JS_DOC_PRIVATE_PATTERN = Pattern.compile("^\\s*@private$"); + private static final Pattern JS_DOC_PUBLIC_PATTERN = Pattern.compile("^\\s*@public$"); + private static final Pattern JS_DOC_PROTECTED_PATTERN = Pattern.compile("^\\s*@protected$"); + private static final Pattern JS_DOC_OPTIONAL_PATTERN = Pattern.compile("^\\s*@optional(.*)$"); + private static final Pattern JS_DOC_STATIC_PATTERN = Pattern.compile("^\\s*@static$"); + private static final Pattern JS_DOC_SEE_PATTERN = Pattern.compile("^\\s*@see (.*)$"); + private static final Pattern JS_DOC_DESCRIPTION_PATTERN = Pattern.compile("^\\s*@description\\s*(.+)$"); + private static final Pattern JS_DOC_RETURN_PATTERN = + Pattern.compile("^\\s*@return(?:s)?\\s*(?:(?:\\{|:)?\\s*([^\\s\\}]+)\\s*\\}?\\s*)?(.*)$"); + private static final Pattern JS_DOC_NAMESPACE_PATTERN = Pattern.compile("^\\s*@namespace\\s*([\\w\\.]+)(.*)$"); + private static final Pattern JS_DOC_PROPERTY_PATTERN = Pattern.compile("^\\s*@property\\s*(\\w+)(.*)$"); + private static final Pattern JS_DOC_TYPE_PATTERN = Pattern.compile("^\\s*@type\\s*\\{?([^\\s\\}]+)\\}?(.*)$"); + private static final Pattern JS_DOC_REQUIRES_PATTERN = Pattern.compile("^\\s*@requires\\s*(\\S+)(.*)$"); + private static final Pattern JS_DOC_DEFAULT_PATTERN = Pattern.compile("^\\s*@default\\s*(.*)$"); + private static final Pattern JS_DOC_EXTENDS_PATTERN = Pattern.compile("^\\s*@extends\\s*(.*)$"); + private static final Map PATTERN_TO_HINT_MAP = new HashMap<>(); + private static final Map PATTERN_TO_META_DOC_TYPE_MAP = new HashMap<>(); + + static { + PATTERN_TO_HINT_MAP.put(DOJO_PARAMETERS_PATTERN, ":"); + PATTERN_TO_META_DOC_TYPE_MAP.put(DOJO_PARAMETERS_PATTERN, JSDocumentationProcessor.MetaDocType.PARAMETER); + PATTERN_TO_HINT_MAP.put(JS_DOC_PARAMETERS_PATTERN, "@pa"); + PATTERN_TO_META_DOC_TYPE_MAP.put(JS_DOC_PARAMETERS_PATTERN, JSDocumentationProcessor.MetaDocType.PARAMETER); + + PATTERN_TO_HINT_MAP.put(JS_DOC_METHOD_PATTERN, "@m"); + PATTERN_TO_META_DOC_TYPE_MAP.put(JS_DOC_METHOD_PATTERN, JSDocumentationProcessor.MetaDocType.METHOD); + + PATTERN_TO_HINT_MAP.put(JS_DOC_OPTIONAL_PATTERN, "@o"); + PATTERN_TO_META_DOC_TYPE_MAP.put(JS_DOC_OPTIONAL_PATTERN, JSDocumentationProcessor.MetaDocType.OPTIONAL_PARAMETERS); + + PATTERN_TO_HINT_MAP.put(JS_DOC_EVENT_PATTERN, "@ev"); + PATTERN_TO_META_DOC_TYPE_MAP.put(JS_DOC_EVENT_PATTERN, JSDocumentationProcessor.MetaDocType.EVENT); + + PATTERN_TO_HINT_MAP.put(JS_DOC_EXTENDS_PATTERN, "@ex"); + PATTERN_TO_META_DOC_TYPE_MAP.put(JS_DOC_EXTENDS_PATTERN, JSDocumentationProcessor.MetaDocType.EXTENDS); + + PATTERN_TO_HINT_MAP.put(JS_DOC_REMARK_PATTERN, "@rem"); + PATTERN_TO_META_DOC_TYPE_MAP.put(JS_DOC_REMARK_PATTERN, JSDocumentationProcessor.MetaDocType.NOTE); + + PATTERN_TO_HINT_MAP.put(JS_DOC_RETURN_PATTERN, "@ret"); + PATTERN_TO_META_DOC_TYPE_MAP.put(JS_DOC_RETURN_PATTERN, JSDocumentationProcessor.MetaDocType.RETURN); + + PATTERN_TO_HINT_MAP.put(JS_DOC_PUBLIC_PATTERN, "@pu"); + PATTERN_TO_META_DOC_TYPE_MAP.put(JS_DOC_PUBLIC_PATTERN, JSDocumentationProcessor.MetaDocType.PUBLIC); + + PATTERN_TO_HINT_MAP.put(JS_DOC_PROTECTED_PATTERN, "@prot"); + PATTERN_TO_META_DOC_TYPE_MAP.put(JS_DOC_PROTECTED_PATTERN, JSDocumentationProcessor.MetaDocType.PROTECTED); + + PATTERN_TO_HINT_MAP.put(JS_DOC_STATIC_PATTERN, "@st"); + PATTERN_TO_META_DOC_TYPE_MAP.put(JS_DOC_STATIC_PATTERN, JSDocumentationProcessor.MetaDocType.STATIC); + + PATTERN_TO_HINT_MAP.put(JS_DOC_SEE_PATTERN, "@se"); + PATTERN_TO_META_DOC_TYPE_MAP.put(JS_DOC_SEE_PATTERN, JSDocumentationProcessor.MetaDocType.SEE); + + PATTERN_TO_HINT_MAP.put(JS_DOC_DESCRIPTION_PATTERN, "@des"); + PATTERN_TO_META_DOC_TYPE_MAP.put(JS_DOC_DESCRIPTION_PATTERN, JSDocumentationProcessor.MetaDocType.DESCRIPTION); + + PATTERN_TO_HINT_MAP.put(JS_DOC_DEPRECATED_PATTERN, "@dep"); + PATTERN_TO_META_DOC_TYPE_MAP.put(JS_DOC_DEPRECATED_PATTERN, JSDocumentationProcessor.MetaDocType.DEPRECATED); + + PATTERN_TO_HINT_MAP.put(JS_DOC_CONSTRUCTOR_PATTERN, "@co"); + + PATTERN_TO_META_DOC_TYPE_MAP.put(JS_DOC_CONSTRUCTOR_PATTERN, JSDocumentationProcessor.MetaDocType.CONSTRUCTOR); + + PATTERN_TO_HINT_MAP.put(JS_DOC_CLASS_PATTERN, "@cl"); + PATTERN_TO_META_DOC_TYPE_MAP.put(JS_DOC_CLASS_PATTERN, JSDocumentationProcessor.MetaDocType.CLASS); + PATTERN_TO_HINT_MAP.put(JS_DOC_PRIVATE_PATTERN, "@pri"); + PATTERN_TO_META_DOC_TYPE_MAP.put(JS_DOC_PRIVATE_PATTERN, JSDocumentationProcessor.MetaDocType.PRIVATE); + + PATTERN_TO_HINT_MAP.put(JS_DOC_NAMESPACE_PATTERN, "@n"); + PATTERN_TO_META_DOC_TYPE_MAP.put(JS_DOC_NAMESPACE_PATTERN, JSDocumentationProcessor.MetaDocType.NAMESPACE); + + PATTERN_TO_HINT_MAP.put(JS_DOC_PROPERTY_PATTERN, "@prop"); + PATTERN_TO_HINT_MAP.put(JS_DOC_TYPE_PATTERN, "@t"); + PATTERN_TO_META_DOC_TYPE_MAP.put(JS_DOC_TYPE_PATTERN, JSDocumentationProcessor.MetaDocType.TYPE); + + PATTERN_TO_HINT_MAP.put(JS_DOC_FINAL_PATTERN, "@f"); + PATTERN_TO_META_DOC_TYPE_MAP.put(JS_DOC_FINAL_PATTERN, JSDocumentationProcessor.MetaDocType.FINAL); + PATTERN_TO_HINT_MAP.put(JS_DOC_REQUIRES_PATTERN, "@req"); + PATTERN_TO_META_DOC_TYPE_MAP.put(JS_DOC_REQUIRES_PATTERN, JSDocumentationProcessor.MetaDocType.REQUIRES); + + PATTERN_TO_HINT_MAP.put(JS_DOC_DEFAULT_PATTERN, "@def"); + PATTERN_TO_META_DOC_TYPE_MAP.put(JS_DOC_DEFAULT_PATTERN, JSDocumentationProcessor.MetaDocType.DEFAULT); + } + + private static final Map prefixToPatternToHintMap = new HashMap<>(); + + static { + prefixToPatternToHintMap.put(Pattern.compile("^\\s*description:(.*)$"), "descr"); + + prefixToPatternToHintMap.put(Pattern.compile("^ summary(?::)?(.*)$"), "summ"); + + prefixToPatternToHintMap.put(Pattern.compile("^\\s*\\*(?:\\*)?(.*)$"), "*"); + + prefixToPatternToHintMap.put(Pattern.compile("^[/]+(.*)$"), "/"); + + prefixToPatternToHintMap.put(Pattern.compile("^\\s*Parameters:(.*)$"), "Parame"); + } + + public static void processDocumentationTextFromComment(ASTNode _initialComment, JSDocumentationProcessor processor) { + ASTNode prev = _initialComment.getTreePrev(); + + if (prev != null && prev.getPsi() instanceof OuterLanguageElement) { + while (prev.getPsi() instanceof OuterLanguageElement) { + prev = prev.getTreePrev(); + } + } + else { + prev = null; + } + + if (prev != null && !(prev.getPsi() instanceof PsiComment)) { + prev = null; + } + + final ASTNode initialComment = prev != null ? prev : _initialComment; + Enumeration commentLineIterator; + + if (initialComment.getElementType() == JSTokenTypes.END_OF_LINE_COMMENT) { + commentLineIterator = new Enumeration<>() { + ASTNode commentNode = initialComment; + + @Override + public boolean hasMoreElements() { + return commentNode != null; + } + + @Override + public String nextElement() { + ASTNode resultCommentNode = commentNode; + commentNode = commentNode.getTreeNext(); + + if (commentNode != null && commentNode.getElementType() == TokenType.WHITE_SPACE) { + commentNode = commentNode.getTreeNext(); + } + + if (commentNode != null && commentNode.getElementType() != JSTokenTypes.END_OF_LINE_COMMENT) { + commentNode = null; + } + + String text = resultCommentNode.getText(); + if (text.startsWith("//")) { + return text.substring(2); + } + return ""; + } + }; + } + else { + String text = initialComment.getText(); + text = unwrapCommentDelimiters(text); + + commentLineIterator = new StringTokenizer(text, "\r\n"); + } + + boolean needPlainCharData = processor.needsPlainCommentData(); + + while (commentLineIterator.hasMoreElements()) { + String s = (String)commentLineIterator.nextElement(); + if (s.indexOf('@') == -1 && s.indexOf(':') == -1 && !needPlainCharData) { + continue; + } + + String commentText = s.replace('\t', ' '); + + for (Map.Entry entry : prefixToPatternToHintMap.entrySet()) { + Matcher matcher = commentText.contains(entry.getValue()) ? entry.getKey().matcher(commentText) : null; + if (matcher == null) { + continue; + } + + if (matcher.matches()) { + commentText = matcher.group(1); + break; + } + } + + boolean matchedSomething = false; + + for (Map.Entry entry : PATTERN_TO_HINT_MAP.entrySet()) { + Matcher matcher = commentText.contains(entry.getValue()) ? entry.getKey().matcher(commentText) : null; + if (matcher == null) { + continue; + } + + if (matcher.matches()) { + JSDocumentationProcessor.MetaDocType docType = PATTERN_TO_META_DOC_TYPE_MAP.get(entry.getKey()); + if (docType != null) { + int groupCount = matcher.groupCount(); + String remainingLineContent = groupCount > 0 ? matcher.group(groupCount) : null; + String matchName = groupCount > 1 ? matcher.group(1) : null; + String matchValue = groupCount > 2 ? matcher.group(2) : null; + + boolean reportAboutOptionalParameter = false; + boolean reportAboutFieldInParameter = false; + boolean reportAboutDefaultValue = false; + + int groupForInitialValue = 6; + int groupForFieldName = 5; + String fieldName = null; + + if (groupCount == 7 && entry.getKey() == JS_DOC_PARAMETERS_PATTERN) { + String paramNameInBracket = matcher.group(4); + + if (paramNameInBracket != null) { + String tmp = matchName; + matchName = paramNameInBracket; + matchValue = tmp; + reportAboutFieldInParameter = (fieldName = matcher.group(groupForFieldName)) != null; + reportAboutOptionalParameter = true; + reportAboutDefaultValue = matcher.group(groupForInitialValue) != null; + } + else { + String typeAfterParamName = matcher.group(3); + if (typeAfterParamName != null) { + matchName = matchValue; + matchValue = typeAfterParamName; + } + else { + String tmp = matchValue; + matchValue = matchName; + matchName = tmp; + } + } + } + + String matched = entry.getKey().pattern(); + + if (reportAboutFieldInParameter) { + if (!processor.onPatternMatch( + JSDocumentationProcessor.MetaDocType.FIELD, + matchName, + null, + matcher.group(groupForFieldName), + commentText, + matched + )) { + break; + } + } + else if (!processor.onPatternMatch(docType, matchName, matchValue, remainingLineContent, commentText, matched)) { + break; + } + if (reportAboutOptionalParameter) { + if (!processor.onPatternMatch( + JSDocumentationProcessor.MetaDocType.OPTIONAL_PARAMETERS, + matchName, + fieldName, + null, + commentText, + matched + )) { + break; + } + } + + if (reportAboutDefaultValue) { + if (!processor.onPatternMatch( + JSDocumentationProcessor.MetaDocType.DEFAULT, + matchName, + fieldName, + matcher.group(groupForInitialValue), + commentText, + matched + )) { + break; + } + } + } + matchedSomething = true; + break; + } + } + + if (!matchedSomething && needPlainCharData && !processor.onCommentLine(commentText)) { + break; + } + } + } + + public static String unwrapCommentDelimiters(String text) { + if (text.startsWith("/**")) { + text = text.substring(3); + } + else if (text.startsWith("/*") || text.startsWith("//")) { + text = text.substring(2); + } + + if (text.endsWith("*/")) { + text = text.substring(0, text.length() - 2); + } + return text; + } + + @Nullable + static ASTNode findTrailingCommentInFunctionBody(@Nonnull JSFunction function) { + ASTNode block = function.getNode().findChildByType(JSElementTypes.BLOCK_STATEMENT); + if (block == null) { + return null; + } + + for (ASTNode prev = block.getLastChildNode(); prev != null; prev = prev.getTreePrev()) { + if (prev.getElementType() == JSElementTypes.RETURN_STATEMENT) { + return block.findChildByType(JSTokenTypes.COMMENTS, prev); + } + else if (prev.getPsi() instanceof JSStatement) { + break; + } + } + return null; + } + + @Nullable + static ASTNode findLeadingCommentInFunctionBody(@Nonnull PsiElement element) { + ASTNode functionNode = element.getNode(); + ASTNode block = functionNode.findChildByType(JSElementTypes.BLOCK_STATEMENT); + if (block == null) { + return null; + } + + for (ASTNode node = block.getFirstChildNode().getTreeNext(); node != null; node = node.getTreeNext()) { + IElementType nodeType = node.getElementType(); + + if (nodeType != TokenType.WHITE_SPACE) { + if (JSTokenTypes.COMMENTS.contains(nodeType)) { + return node; + } + return null; + } + } + + return null; + } + + @RequiredReadAction + public static PsiElement findDocComment(PsiElement element) { + return findDocComment(element, null); + } + + @RequiredReadAction + public static PsiElement findDocComment(PsiElement element, PsiElement context) { + PsiElement docComment = null; + boolean skippedExprStatementOnce = false; + + if (element instanceof JSAttributeListOwner jsClass && context == null) { + JSAttributeList attributeList = jsClass.getAttributeList(); + PsiElement anchor = null; + + if (attributeList != null) { + for (ASTNode currentNode = attributeList.getNode().getLastChildNode(); currentNode != null; + currentNode = currentNode.getTreePrev()) { + IElementType nodeType = currentNode.getElementType(); + + if (!JSTokenTypes.MODIFIERS.contains(nodeType) + && nodeType != JSTokenTypes.WHITE_SPACE + && nodeType != JSElementTypes.REFERENCE_EXPRESSION // namespace + ) { + ASTNode nextNode = currentNode.getTreeNext(); + if (nextNode != null) { + anchor = nextNode.getPsi(); + } + break; + } + } + } + + if (anchor != null) { + element = anchor; + } + } + + if (!element.isValid() || element.getContainingFile() == null) { + return docComment; + } + + boolean shouldSkipPrevExprStatement = false; + String propName = getPropertyNameFromExprStatement(element); + if (propName != null) { + shouldSkipPrevExprStatement = true; + } + + for (PsiElement prev = element.getPrevSibling(); prev != null; prev = prev.getPrevSibling()) { + if (prev instanceof PsiWhiteSpace) { + continue; + } + + if (prev instanceof PsiComment) { + docComment = prev; + if (((PsiComment)prev).getTokenType() == JSTokenTypes.DOC_COMMENT) { + break; + } + } + else if (shouldSkipPrevExprStatement && + prev instanceof JSExpressionStatement && + !skippedExprStatementOnce) { + String propNameFromPrev = getPropertyNameFromExprStatement(prev); + if (!propName.equals(propNameFromPrev)) { + break; + } + skippedExprStatementOnce = true; // presumably another accessor definition + continue; + } + + break; + } + + if (docComment != null) { + while (docComment.getPrevSibling() instanceof OuterLanguageElement) { + PsiElement siblingSibling = docComment.getPrevSibling().getPrevSibling(); + + if (siblingSibling != null && siblingSibling instanceof PsiComment) { + docComment = siblingSibling; + } + else { + break; + } + } + } + return docComment; + } + + @Nullable + @RequiredReadAction + private static String getPropertyNameFromExprStatement(@Nonnull PsiElement element) { + String propName = null; + + if (element instanceof JSExpressionStatement expressionStatement + && expressionStatement.getExpression() instanceof JSAssignmentExpression assignment + && assignment.getROperand() instanceof JSFunctionExpression functionExpr) { + String name = functionExpr.getName(); + if (name != null && (StringUtil.startsWith(name, "get") || StringUtil.startsWith(name, "set"))) { + propName = name.substring(3); + } + } + return propName; + } + + private static String findTypeFromParameter(JSVariable parameter, PsiElement docComment) { + if (docComment != null) { + String[] detectedType = new String[1]; + + processDocumentationTextFromComment( + docComment.getNode(), + new JSDocumentationProcessor() { + String name = parameter.getName(); + boolean isparameter = parameter instanceof JSParameter; + + @Override + public boolean needsPlainCommentData() { + return false; + } + + @Override + public boolean onCommentLine(@Nonnull String line) { + return true; + } + + @Override + public boolean onPatternMatch( + @Nonnull MetaDocType type, + @Nullable String matchName, + @Nullable String matchValue, + @Nullable String remainingLineContent, + @Nonnull String line, + String patternMatched + ) { + if (isparameter && type == MetaDocType.PARAMETER && matchName != null && matchName.equals(name)) { + detectedType[0] = matchValue; + return false; + } + else if (type == MetaDocType.TYPE) { + detectedType[0] = matchName; + return false; + } + return true; + } + } + ); + + return detectedType[0]; + } + return null; + } + + public static final TokenSet PRIMITIVE_TYPE_FILTER = TokenSet.create( + JSTokenTypes.INT_KEYWORD, + JSTokenTypes.UINT_KEYWORD, + JSTokenTypes.VOID_KEYWORD, + JSTokenTypes.ANY_IDENTIFIER + ); + public static final TokenSet TYPE_FILTER = + TokenSet.orSet(TokenSet.create(JSElementTypes.REFERENCE_EXPRESSION), PRIMITIVE_TYPE_FILTER); + + @RequiredReadAction + private static String findDocForAnchor(final PsiElement _anchor, final JSDocumentationProcessor.MetaDocType... expectedTypes) { + PsiElement anchor = _anchor; + if (_anchor instanceof JSExpression) { + anchor = PsiTreeUtil.getParentOfType(_anchor, JSStatement.class, JSProperty.class); + } + + if (anchor != null) { + PsiElement docComment = findDocComment(anchor); + + if (docComment != null) { + final SimpleReference detectedType = new SimpleReference<>(); + + processDocumentationTextFromComment( + docComment.getNode(), + new JSDocumentationProcessor() { + @Override + public boolean needsPlainCommentData() { + return false; + } + + @Override + public boolean onCommentLine(@Nonnull String line) { + return true; + } + + @Override + @RequiredReadAction + public boolean onPatternMatch( + @Nonnull MetaDocType type, + @Nullable String matchName, + @Nullable String matchValue, + @Nullable String remainingLineContent, + @Nonnull String line, + String patternMatched + ) { + for (MetaDocType expectedType : expectedTypes) { + if (type == expectedType) { + if (type == MetaDocType.TYPE && _anchor instanceof JSFunction function) { + JSParameterList jsParameterList = function.getParameterList(); + if (jsParameterList != null && jsParameterList.getParameters().length > 0) { + return true; + } + if (_anchor.getParent() instanceof JSProperty) { + return true; + } + } + else if (type == MetaDocType.RETURN) { + //if (!isOurDocComment()) return true; + } + + detectedType.set(matchName); + return false; + } + } + return true; + } + } + ); + + return detectedType.get(); + } + } + return null; + } + + @RequiredReadAction + public static String findType(PsiElement def) { + return findDocForAnchor(def, JSDocumentationProcessor.MetaDocType.TYPE); + } + + @RequiredReadAction + public static boolean isDeprecated(PsiElement element) { + if (element instanceof JSClass jsClass) { + return jsClass.isDeprecated(); + } + else if (element instanceof JSFunction function) { + return function.isDeprecated(); + } + else if (element instanceof JSVariable variable) { + return variable.isDeprecated(); + } + else if (element instanceof JSNamespaceDeclaration namespaceDeclaration) { + return namespaceDeclaration.isDeprecated(); + } + + return calculateDeprecated(element); + } + + @RequiredReadAction + public static boolean calculateDeprecated(PsiElement element) { + if (element instanceof JSExpression) { + element = PsiTreeUtil.getParentOfType(element, JSStatement.class, JSProperty.class); + } + + PsiElement docComment = element != null ? findDocComment(element) : null; + if (docComment != null) { + final boolean[] deprecatedStatus = new boolean[1]; + + processDocumentationTextFromComment( + docComment.getNode(), + new JSDocumentationProcessor() { + @Override + public boolean needsPlainCommentData() { + return false; + } + + @Override + public boolean onCommentLine(@Nonnull String line) { + return true; + } + + @Override + public boolean onPatternMatch( + @Nonnull MetaDocType type, + @Nullable String matchName, + @Nullable String matchValue, + @Nullable String remainingLineContent, + @Nonnull String line, + String patternMatched + ) { + if (type == MetaDocType.DEPRECATED) { + deprecatedStatus[0] = true; + return false; + } + return true; + } + } + ); + + return deprecatedStatus[0]; + } + return false; + } + + public static void appendHyperLinkToElement( + @Nullable PsiElement element, + String elementName, + StringBuilder buffer, + String presentableName, + @Nullable String presentableFileName + ) { + PsiFile containingFile = element != null ? element.getContainingFile() : null; + String fileName = containingFile == null + ? null + : !JSResolveUtil.isPredefinedFile(containingFile) + ? containingFile.getVirtualFile().getPresentableUrl() + : containingFile.getViewProvider().getVirtualFile().getName(); + + DocumentationManagerUtil.createHyperlink( + buffer, + (fileName != null ? fileName + ":" : "") + elementName + (element != null ? ":" + element + .getTextOffset() : ""), + presentableName + (presentableFileName != null ? " in " + presentableFileName : ""), + true + ); + } + + @RequiredReadAction + private static String evaluateTypeFromParameter(JSParameter parameter) { + String s = evaluateTypeFromVariable(parameter); + + if (s == null) { + s = findTypeFromParameter(parameter, findFunctionComment(parameter)); + } + + return s; + } + + @RequiredReadAction + private static PsiElement findFunctionComment(JSParameter parameter) { + PsiElement anchor = PsiTreeUtil.getParentOfType(parameter, JSFunction.class); + + if (anchor instanceof JSFunctionExpression) { + anchor = PsiTreeUtil.getParentOfType(anchor, JSStatement.class, JSProperty.class); + } + + if (anchor != null) { + return findDocComment(anchor); + } + return null; + } + + @RequiredReadAction + private static String evaluateTypeFromFunction(JSFunction function) { + ASTNode lastCommentInFunctionBody = findTrailingCommentInFunctionBody(function); + + String typeString = null; + if (lastCommentInFunctionBody != null) { + typeString = unwrapCommentDelimiters(lastCommentInFunctionBody.getText()).trim(); + } + + if (typeString == null) { + typeString = findDocForAnchor(function, JSDocumentationProcessor.MetaDocType.RETURN, JSDocumentationProcessor.MetaDocType.TYPE); + } + return typeString; + } + + @RequiredReadAction + private static String evaluateTypeFromVariable(JSVariable variable) { + PsiElement prevSibling = variable.getFirstChild(); + if (prevSibling != null && prevSibling.getNode().getElementType() == JSTokenTypes.IDENTIFIER) { + prevSibling = variable.getPrevSibling(); + } + + if (prevSibling instanceof PsiWhiteSpace) { + prevSibling = prevSibling.getPrevSibling(); + } + + if (prevSibling instanceof PsiComment && prevSibling.getNode().getElementType() != JSTokenTypes.END_OF_LINE_COMMENT) { + String parameterCommentText = prevSibling.getText(); + parameterCommentText = unwrapCommentDelimiters(parameterCommentText).trim(); + + if (parameterCommentText.length() > 0 + && (Character.isUpperCase(parameterCommentText.charAt(0)) || parameterCommentText.indexOf(' ') == -1)) { + return parameterCommentText; + } + } + + if (prevSibling != null && prevSibling.getNode() != null && prevSibling.getNode().getElementType() == JSTokenTypes.VAR_KEYWORD) { + prevSibling = variable.getParent().getPrevSibling(); + + if (prevSibling instanceof PsiWhiteSpace) { + prevSibling = prevSibling.getPrevSibling(); + } + + if (prevSibling instanceof PsiComment) { + return findTypeFromParameter(variable, prevSibling); + } + + } + return null; + } + + @RequiredReadAction + public static String findTypeFromComments(JSNamedElement element) { + if (element instanceof JSParameter parameter) { + return evaluateTypeFromParameter(parameter); + } + else if (element instanceof JSVariable variable) { + return evaluateTypeFromVariable(variable); + } + else if (element instanceof JSFunction function) { + return evaluateTypeFromFunction(function); + } + return null; + } + + public static boolean isSymbolReference(String content) { + int i = content.indexOf(' '); + if (i == -1) { + return false; + } + String text = content.substring(0, i); + return text.indexOf('.') != -1 || text.indexOf('#') != -1; + } + + @RequiredReadAction + public static boolean findOptionalStatusFromComments(final JSParameter parameter) { + PsiElement docComment = findFunctionComment(parameter); + if (docComment == null) { + return false; + } + + final boolean[] detectedType = new boolean[1]; + + processDocumentationTextFromComment( + docComment.getNode(), + new JSDocumentationProcessor() { + final String name = parameter.getName(); + + @Override + public boolean needsPlainCommentData() { + return false; + } + + @Override + public boolean onCommentLine(@Nonnull String line) { + return true; + } + + @Override + public boolean onPatternMatch( + @Nonnull MetaDocType type, + @Nullable String matchName, + @Nullable String matchValue, + @Nullable String remainingLineContent, + @Nonnull String line, + String patternMatched + ) { + if (type == MetaDocType.OPTIONAL_PARAMETERS && matchName != null && matchName.equals(name) && matchValue == null) { + detectedType[0] = true; + return false; + } + + return true; + } + } + ); + + return detectedType[0]; + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/DialectOptionHolder.java b/base-impl/src/main/java/com/intellij/lang/javascript/DialectOptionHolder.java index f29bdb57..602fe876 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/DialectOptionHolder.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/DialectOptionHolder.java @@ -20,34 +20,30 @@ * @author Maxim.Mossienko */ @Deprecated -public final class DialectOptionHolder -{ - public static DialectOptionHolder dummy() - { - return new DialectOptionHolder(false, false); - } +public final class DialectOptionHolder { + public static DialectOptionHolder dummy() { + return new DialectOptionHolder(false, false); + } - public final boolean isECMAL4Level; - public final boolean isJavaScript1_6_OrBetter; - public final boolean hasE4X; - public final boolean isJavaScript1_7_OrBetter; - public final boolean isJavaScript1_8_OrBetter; - public final boolean isGwt; + public final boolean isECMAL4Level; + public final boolean isJavaScript1_6_OrBetter; + public final boolean hasE4X; + public final boolean isJavaScript1_7_OrBetter; + public final boolean isJavaScript1_8_OrBetter; + public final boolean isGwt; - public DialectOptionHolder(boolean _ecma, boolean _gwt) - { - this(_ecma, _gwt, true); - } + public DialectOptionHolder(boolean _ecma, boolean _gwt) { + this(_ecma, _gwt, true); + } - public DialectOptionHolder(boolean _ecma, boolean _gwt, final boolean _e4x) - { - isECMAL4Level = _ecma; - isGwt = _gwt; - isJavaScript1_7_OrBetter = _e4x; - isJavaScript1_8_OrBetter = _e4x; - isJavaScript1_6_OrBetter = _e4x; - hasE4X = _e4x; + public DialectOptionHolder(boolean _ecma, boolean _gwt, boolean _e4x) { + isECMAL4Level = _ecma; + isGwt = _gwt; + isJavaScript1_7_OrBetter = _e4x; + isJavaScript1_8_OrBetter = _e4x; + isJavaScript1_6_OrBetter = _e4x; + hasE4X = _e4x; - assert !isGwt || !isECMAL4Level; - } + assert !isGwt || !isECMAL4Level; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/JSDocElementType.java b/base-impl/src/main/java/com/intellij/lang/javascript/JSDocElementType.java index 8015ee6b..246dd974 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/JSDocElementType.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/JSDocElementType.java @@ -16,16 +16,14 @@ package com.intellij.lang.javascript; +import jakarta.annotation.Nonnull; import org.jetbrains.annotations.NonNls; -import javax.annotation.Nonnull; /** * @author yole */ -public class JSDocElementType extends JSElementType -{ - public JSDocElementType(@Nonnull @NonNls String debugName) - { - super(debugName); - } +public class JSDocElementType extends JSElementType { + public JSDocElementType(@Nonnull @NonNls String debugName) { + super(debugName); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/JSDocTokenTypes.java b/base-impl/src/main/java/com/intellij/lang/javascript/JSDocTokenTypes.java index c21ed65c..f4c61de5 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/JSDocTokenTypes.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/JSDocTokenTypes.java @@ -23,27 +23,26 @@ /** * @by maxim.mossienko */ -public interface JSDocTokenTypes -{ - IElementType DOC_COMMENT_START = new JSDocElementType("DOC_COMMENT_START"); - IElementType DOC_COMMENT_END = new JSDocElementType("DOC_COMMENT_END"); - IElementType DOC_SPACE = new JSDocElementType("DOC_SPACE"); - IElementType DOC_REAL_WHITESPACE = TokenType.WHITE_SPACE; - IElementType DOC_COMMENT_DATA = new JSDocElementType("DOC_COMMENT_DATA"); - IElementType DOC_COMMENT_LEADING_ASTERISK = new JSDocElementType("DOC_COMMENT_LEADING_ASTERISK"); - IElementType DOC_TAG_NAME = new JSDocElementType("DOC_TAG_NAME"); - IElementType DOC_BAD_CHARACTER = TokenType.BAD_CHARACTER; - IElementType DOC_TAG_VALUE = new JSDocElementType("DOC_TAG_VALUE"); +public interface JSDocTokenTypes { + IElementType DOC_COMMENT_START = new JSDocElementType("DOC_COMMENT_START"); + IElementType DOC_COMMENT_END = new JSDocElementType("DOC_COMMENT_END"); + IElementType DOC_SPACE = new JSDocElementType("DOC_SPACE"); + IElementType DOC_REAL_WHITESPACE = TokenType.WHITE_SPACE; + IElementType DOC_COMMENT_DATA = new JSDocElementType("DOC_COMMENT_DATA"); + IElementType DOC_COMMENT_LEADING_ASTERISK = new JSDocElementType("DOC_COMMENT_LEADING_ASTERISK"); + IElementType DOC_TAG_NAME = new JSDocElementType("DOC_TAG_NAME"); + IElementType DOC_BAD_CHARACTER = TokenType.BAD_CHARACTER; + IElementType DOC_TAG_VALUE = new JSDocElementType("DOC_TAG_VALUE"); - TokenSet TOKENS_TO_MERGE = TokenSet.create(DOC_SPACE, DOC_REAL_WHITESPACE); - IElementType DOC_TAG = new JSDocElementType("DOC_TAG"); + TokenSet TOKENS_TO_MERGE = TokenSet.create(DOC_SPACE, DOC_REAL_WHITESPACE); + IElementType DOC_TAG = new JSDocElementType("DOC_TAG"); - IElementType DOC_TAG_VALUE_LPAREN = new JSDocElementType("DOC_TAG_VALUE_LPAREN"); - IElementType DOC_TAG_VALUE_RPAREN = new JSDocElementType("DOC_TAG_VALUE_RPAREN"); - IElementType DOC_TAG_VALUE_SHARP = new JSDocElementType("DOC_TAG_VALUE_SHARP"); - IElementType DOC_TAG_VALUE_COMMA = new JSDocElementType("DOC_TAG_VALUE_COMMA"); - IElementType DOC_TAG_VALUE_LT = new JSDocElementType("DOC_TAG_VALUE_LT"); - IElementType DOC_TAG_VALUE_GT = new JSDocElementType("DOC_TAG_VALUE_GT"); - IElementType INLINE_TAG_START = new JSDocElementType("DOC_INLINE_TAG_START"); - IElementType INLINE_TAG_END = new JSDocElementType("DOC_INLINE_TAG_END"); + IElementType DOC_TAG_VALUE_LPAREN = new JSDocElementType("DOC_TAG_VALUE_LPAREN"); + IElementType DOC_TAG_VALUE_RPAREN = new JSDocElementType("DOC_TAG_VALUE_RPAREN"); + IElementType DOC_TAG_VALUE_SHARP = new JSDocElementType("DOC_TAG_VALUE_SHARP"); + IElementType DOC_TAG_VALUE_COMMA = new JSDocElementType("DOC_TAG_VALUE_COMMA"); + IElementType DOC_TAG_VALUE_LT = new JSDocElementType("DOC_TAG_VALUE_LT"); + IElementType DOC_TAG_VALUE_GT = new JSDocElementType("DOC_TAG_VALUE_GT"); + IElementType INLINE_TAG_START = new JSDocElementType("DOC_INLINE_TAG_START"); + IElementType INLINE_TAG_END = new JSDocElementType("DOC_INLINE_TAG_END"); } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/JSElementType.java b/base-impl/src/main/java/com/intellij/lang/javascript/JSElementType.java index ea634c51..8ae120d2 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/JSElementType.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/JSElementType.java @@ -18,20 +18,17 @@ import consulo.javascript.language.JavaScriptLanguage; import consulo.language.ast.IElementType; +import jakarta.annotation.Nonnull; import org.jetbrains.annotations.NonNls; -import javax.annotation.Nonnull; - /** * Created by IntelliJ IDEA. * User: max * Date: Jan 27, 2005 * Time: 6:38:56 PM */ -public class JSElementType extends IElementType -{ - public JSElementType(@NonNls @Nonnull String debugName) - { - super(debugName, JavaScriptLanguage.INSTANCE); - } +public class JSElementType extends IElementType { + public JSElementType(@NonNls @Nonnull String debugName) { + super(debugName, JavaScriptLanguage.INSTANCE); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/JSElementTypes.java b/base-impl/src/main/java/com/intellij/lang/javascript/JSElementTypes.java index 5878b135..0a47c155 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/JSElementTypes.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/JSElementTypes.java @@ -19,170 +19,271 @@ import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.impl.*; import com.intellij.lang.javascript.psi.stubs.*; -import com.intellij.lang.javascript.types.*; +import com.intellij.lang.javascript.types.JSFileElementType; +import com.intellij.lang.javascript.types.JSFunctionElementType; import consulo.annotation.DeprecationInfo; +import consulo.annotation.access.RequiredReadAction; import consulo.javascript.ecmascript4.psi.impl.EcmaScript4ElementTypes; +import consulo.javascript.impl.language.psi.JSComputedNameImpl; import consulo.javascript.impl.language.psi.JSStubElementType; -import consulo.javascript.language.JavaScriptLanguage; +import consulo.javascript.impl.language.psi.JavaScriptLambdaExpressionImpl; +import consulo.javascript.impl.language.psi.JavaScriptSpreadExpressionImpl; import consulo.javascript.lang.parsing.impl.JavaSciptDestructuringElementImpl; import consulo.javascript.lang.parsing.impl.JavaSciptDestructuringObjectImpl; import consulo.javascript.lang.parsing.impl.JavaScriptDestructuringParameterImpl; import consulo.javascript.lang.parsing.impl.JavaScriptDestructuringShorthandedPropertyImpl; import consulo.javascript.lang.psi.impl.JSRegExpLiteralExpressionImpl; -import consulo.javascript.impl.language.psi.JSComputedNameImpl; -import consulo.javascript.impl.language.psi.JavaScriptLambdaExpressionImpl; -import consulo.javascript.impl.language.psi.JavaScriptSpreadExpressionImpl; +import consulo.javascript.language.JavaScriptLanguage; import consulo.javascript.psi.stubs.JSFileStub; import consulo.language.Language; import consulo.language.ast.*; +import consulo.language.parser.ParserDefinition; +import consulo.language.parser.PsiBuilder; +import consulo.language.parser.PsiBuilderFactory; +import consulo.language.parser.PsiParser; import consulo.language.psi.PsiElement; import consulo.language.psi.stub.IStubFileElementType; +import consulo.language.version.LanguageVersion; +import consulo.language.version.LanguageVersionUtil; +import consulo.project.Project; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * User: max * Date: Jan 28, 2005 * Time: 12:27:21 AM */ -public interface JSElementTypes -{ - IStubFileElementType FILE = new JSFileElementType(JavaScriptLanguage.INSTANCE); - - IElementType EMBEDDED_CONTENT = new ILazyParseableElementType("EMBEDDED_CONTENT", JavaScriptLanguage.INSTANCE) - { - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } - }; - IElementType EMBEDDED_EXPRESSION = new ElementTypeAsPsiFactory("EMBEDDED_EXPRESSION", JavaScriptLanguage.INSTANCE, JSEmbeddedContentImpl::new); - - JSStubElementType FUNCTION_DECLARATION = JSStubElementTypes.FUNCTION_DECLARATION; - - JSStubElementType PARAMETER_LIST = JSStubElementTypes.PARAMETER_LIST; - - JSStubElementType FORMAL_PARAMETER = JSStubElementTypes.FORMAL_PARAMETER; - - JSStubElementType VARIABLE = JSStubElementTypes.VARIABLE; - IElementType ARGUMENT_LIST = new ElementTypeAsPsiFactory("ARGUMENT_LIST", JavaScriptLanguage.INSTANCE, JSArgumentListImpl::new); - - JSStubElementType ATTRIBUTE = JSStubElementTypes.ATTRIBUTE; - JSStubElementType ATTRIBUTE_NAME_VALUE_PAIR = JSStubElementTypes.ATTRIBUTE_NAME_VALUE_PAIR; - JSStubElementType ATTRIBUTE_LIST = JSStubElementTypes.ATTRIBUTE_LIST; - JSStubElementType PACKAGE_STATEMENT = JSStubElementTypes.PACKAGE_STATEMENT; - - @Deprecated - JSStubElementType ES4_IMPORT_STATEMENT = EcmaScript4ElementTypes.IMPORT_STATEMENT; - - JSStubElementType CLASS = JSStubElementTypes.CLASS; - JSStubElementType EXTENDS_LIST = JSStubElementTypes.EXTENDS_LIST; - JSStubElementType IMPLEMENTS_LIST = JSStubElementTypes.IMPLEMENTS_LIST; - JSStubElementType USE_NAMESPACE_DIRECTIVE = JSStubElementTypes.USE_NAMESPACE_DIRECTIVE; - JSStubElementType INCLUDE_DIRECTIVE = JSStubElementTypes.INCLUDE_DIRECTIVE; - JSStubElementType NAMESPACE_DECLARATION = JSStubElementTypes.NAMESPACE_DECLARATION; - IElementType SUPER_EXPRESSION = new ElementTypeAsPsiFactory("SUPER_EXPRESSION", JavaScriptLanguage.INSTANCE, JSSuperExpressionImpl::new); - IElementType GENERIC_SIGNATURE = new ElementTypeAsPsiFactory("GENERIC_SIGNATURE", JavaScriptLanguage.INSTANCE, JSGenericSignatureImpl::new); - - // Statements - IElementType BLOCK_STATEMENT = new ElementTypeAsPsiFactory("BLOCK_STATEMENT", JavaScriptLanguage.INSTANCE, JSBlockStatementImpl::new); - IElementType LABELED_STATEMENT = new ElementTypeAsPsiFactory("LABELED_STATEMENT", JavaScriptLanguage.INSTANCE, JSLabeledStatementImpl::new); - IElementType EXPRESSION_STATEMENT = new ElementTypeAsPsiFactory("EXPRESSION_STATEMENT", JavaScriptLanguage.INSTANCE, - JSExpressionStatementImpl::new); - IElementType YIELD_STATEMENT = new ElementTypeAsPsiFactory("YIELD_STATEMENT", JavaScriptLanguage.INSTANCE, JSYieldStatementImpl::new); - IElementType LET_STATEMENT = new ElementTypeAsPsiFactory("LET_STATEMENT", JavaScriptLanguage.INSTANCE, JSLetStatementImpl::new); - JSStubElementType VAR_STATEMENT = JSStubElementTypes.VAR_STATEMENT; - IElementType EMPTY_STATEMENT = new ElementTypeAsPsiFactory("EMPTY_STATEMENT", JavaScriptLanguage.INSTANCE, JSEmptyStatementImpl::new); - IElementType IF_STATEMENT = new ElementTypeAsPsiFactory("IF_STATEMENT", JavaScriptLanguage.INSTANCE, JSIfStatementImpl::new); - IElementType CONTINUE_STATEMENT = new ElementTypeAsPsiFactory("CONTINUE_STATEMENT", JavaScriptLanguage.INSTANCE, JSContinueStatementImpl::new); - IElementType BREAK_STATEMENT = new ElementTypeAsPsiFactory("BREAK_STATEMENT", JavaScriptLanguage.INSTANCE, JSBreakStatementImpl::new); - IElementType DESTRUCTURING_ELEMENT = new ElementTypeAsPsiFactory("DESTRUCTURING_ELEMENT", JavaScriptLanguage.INSTANCE, JavaSciptDestructuringElementImpl::new); - IElementType DESTRUCTURING_PARAMETER = new ElementTypeAsPsiFactory("DESTRUCTURING_PARAMETER", JavaScriptLanguage.INSTANCE, JavaScriptDestructuringParameterImpl::new); - IElementType DESTRUCTURING_OBJECT = new ElementTypeAsPsiFactory("DESTRUCTURING_OBJECT", JavaScriptLanguage.INSTANCE, JavaSciptDestructuringObjectImpl::new); - IElementType DESTRUCTURING_SHORTHANDED_PROPERTY = new ElementTypeAsPsiFactory("DESTRUCTURING_SHORTHANDED_PROPERTY", JavaScriptLanguage.INSTANCE, JavaScriptDestructuringShorthandedPropertyImpl::new); - IElementType WITH_STATEMENT = new ElementTypeAsPsiFactory("WITH_STATEMENT", JavaScriptLanguage.INSTANCE, JSWithStatementImpl::new); - IElementType RETURN_STATEMENT = new ElementTypeAsPsiFactory("RETURN_STATEMENT", JavaScriptLanguage.INSTANCE, JSReturnStatementImpl::new); - IElementType THROW_STATEMENT = new ElementTypeAsPsiFactory("THROW_STATEMENT", JavaScriptLanguage.INSTANCE, JSThrowStatementImpl::new); - IElementType TRY_STATEMENT = new ElementTypeAsPsiFactory("TRY_STATEMENT", JavaScriptLanguage.INSTANCE, JSTryStatementImpl::new); - IElementType CATCH_BLOCK = new ElementTypeAsPsiFactory("CATCH_BLOCK", JavaScriptLanguage.INSTANCE, JSCatchBlockImpl::new); - IElementType CASE_CLAUSE = new ElementTypeAsPsiFactory("CASE_CLAUSE", JavaScriptLanguage.INSTANCE, JSCaseClauseImpl::new); - IElementType SWITCH_STATEMENT = new ElementTypeAsPsiFactory("SWITCH_STATEMENT", JavaScriptLanguage.INSTANCE, JSSwitchStatementImpl::new); - IElementType FOR_STATEMENT = new ElementTypeAsPsiFactory("FOR_STATEMENT", JavaScriptLanguage.INSTANCE, JSForStatementImpl::new); - IElementType FOR_IN_STATEMENT = new ElementTypeAsPsiFactory("FOR_IN_STATEMENT", JavaScriptLanguage.INSTANCE, JSForInStatementImpl::new); - IElementType WHILE_STATEMENT = new ElementTypeAsPsiFactory("WHILE_STATEMENT", JavaScriptLanguage.INSTANCE, JSWhileStatementImpl::new); - IElementType DOWHILE_STATEMENT = new ElementTypeAsPsiFactory("DO_WHILE_STATEMENT", JavaScriptLanguage.INSTANCE, JSDoWhileStatementImpl::new); - - @Deprecated - @DeprecationInfo("Use search by class") - TokenSet STATEMENTS = TokenSet.create(BLOCK_STATEMENT, LABELED_STATEMENT, VAR_STATEMENT, EMPTY_STATEMENT, IF_STATEMENT, CONTINUE_STATEMENT, - BREAK_STATEMENT, WITH_STATEMENT, RETURN_STATEMENT, THROW_STATEMENT, TRY_STATEMENT, SWITCH_STATEMENT, FOR_IN_STATEMENT, FOR_STATEMENT, - WHILE_STATEMENT, DOWHILE_STATEMENT, EXPRESSION_STATEMENT, YIELD_STATEMENT, LET_STATEMENT, ES4_IMPORT_STATEMENT, PACKAGE_STATEMENT, - USE_NAMESPACE_DIRECTIVE); - - TokenSet SOURCE_ELEMENTS = TokenSet.orSet(STATEMENTS, TokenSet.create(FUNCTION_DECLARATION, CLASS, NAMESPACE_DECLARATION, INCLUDE_DIRECTIVE, - USE_NAMESPACE_DIRECTIVE)); - - // Expressions - IElementType THIS_EXPRESSION = new ElementTypeAsPsiFactory("THIS_EXPRESSION", JavaScriptLanguage.INSTANCE, JSThisExpressionImpl::new); - IElementType REFERENCE_EXPRESSION = new ElementTypeAsPsiFactory("REFERENCE_EXPRESSION", JavaScriptLanguage.INSTANCE, - JSReferenceExpressionImpl::new); - IElementType LITERAL_EXPRESSION = new ElementTypeAsPsiFactory("LITERAL_EXPRESSION", JavaScriptLanguage.INSTANCE, JSLiteralExpressionImpl::new); - IElementType REGEXP_LITERAL_EXPRESSION = new ElementTypeAsPsiFactory("REGEXP_LITERAL_EXPRESSION", JavaScriptLanguage.INSTANCE, JSRegExpLiteralExpressionImpl::new); - IElementType XML_LITERAL_EXPRESSION = new ElementTypeAsPsiFactory("XML_LITERAL_EXPRESSION", JavaScriptLanguage.INSTANCE, - JSXmlLiteralExpressionImpl::new); - IElementType PARENTHESIZED_EXPRESSION = new ElementTypeAsPsiFactory("PARENTHESIZED_EXPRESSION", JavaScriptLanguage.INSTANCE, - JSParenthesizedExpressionImpl::new); - IElementType ARRAY_LITERAL_EXPRESSION = new ElementTypeAsPsiFactory("ARRAY_LITERAL_EXPRESSION", JavaScriptLanguage.INSTANCE, - JSArrayLiteralExpressionImpl::new); - IElementType PROPERTY = new ElementTypeAsPsiFactory("PROPERTY", JavaScriptLanguage.INSTANCE, JSPropertyImpl::new); - IElementType FUNCTION_PROPERTY = new ElementTypeAsPsiFactory("FUNCTION_PROPERTY", JavaScriptLanguage.INSTANCE, JSFunctionPropertyImpl::new); - IElementType COMPUTED_NAME = new ElementTypeAsPsiFactory("COMPUTED_NAME", JavaScriptLanguage.INSTANCE, JSComputedNameImpl::new); - IElementType OBJECT_LITERAL_EXPRESSION = new ElementTypeAsPsiFactory("OBJECT_LITERAL_EXPRESSION", JavaScriptLanguage.INSTANCE, - JSObjectLiteralExpressionImpl::new); - IElementType ASSIGNMENT_EXPRESSION = new ElementTypeAsPsiFactory("ASSIGNMENT_EXPRESSION", JavaScriptLanguage.INSTANCE, - JSAssignmentExpressionImpl::new); - IElementType CONDITIONAL_EXPRESSION = new ElementTypeAsPsiFactory("CONDITIONAL_EXPRESSION", JavaScriptLanguage.INSTANCE, - JSConditionalExpressionImpl::new); - IElementType CLASS_EXPRESSION = new ElementTypeAsPsiFactory("CLASS_EXPRESSION", JavaScriptLanguage.INSTANCE, JSClassExpressionImpl::new); - IElementType BINARY_EXPRESSION = new ElementTypeAsPsiFactory("BINARY_EXPRESSION", JavaScriptLanguage.INSTANCE, JSBinaryExpressionImpl::new); - IElementType PREFIX_EXPRESSION = new ElementTypeAsPsiFactory("PREFIX_EXPRESSION", JavaScriptLanguage.INSTANCE, JSPrefixExpressionImpl::new); - IElementType POSTFIX_EXPRESSION = new ElementTypeAsPsiFactory("POSTFIX_EXPRESSION", JavaScriptLanguage.INSTANCE, JSPostfixExpressionImpl::new); - IElementType LAMBDA_EXPRESSION = new ElementTypeAsPsiFactory("LAMBDA_EXPRESSION", JavaScriptLanguage.INSTANCE, JavaScriptLambdaExpressionImpl::new); - IElementType SPREAD_EXPRESSION = new ElementTypeAsPsiFactory("SPREAD_EXPRESSION", JavaScriptLanguage.INSTANCE, JavaScriptSpreadExpressionImpl::new); - IElementType COMMA_EXPRESSION = new ElementTypeAsPsiFactory("COMMA_EXPRESSION", JavaScriptLanguage.INSTANCE, JSCommaExpressionImpl::new); - JSStubElementType FUNCTION_EXPRESSION = new JSFunctionElementType("FUNCTION_EXPRESSION") - { - @Override - public JSFunction createPsi(@Nonnull JSFunctionStub stub) - { - return new JSFunctionExpressionImpl(stub, this); - } - - @Nonnull - @Override - public PsiElement createElement(@Nonnull ASTNode astNode) - { - return new JSFunctionExpressionImpl(astNode); - } - }; - IElementType NEW_EXPRESSION = new ElementTypeAsPsiFactory("NEW_EXPRESSION", JavaScriptLanguage.INSTANCE, JSNewExpressionImpl::new); - - IElementType INDEXED_PROPERTY_ACCESS_EXPRESSION = new ElementTypeAsPsiFactory("INDEXED_PROPERTY_ACCESS_EXPRESSION", JavaScriptLanguage.INSTANCE, - JSIndexedPropertyAccessExpressionImpl::new); - IElementType CALL_EXPRESSION = new ElementTypeAsPsiFactory("CALL_EXPRESSION", JavaScriptLanguage.INSTANCE, JSCallExpressionImpl::new); - IElementType DEFINITION_EXPRESSION = new ElementTypeAsPsiFactory("DEFINITION_EXPRESSION", JavaScriptLanguage.INSTANCE, - JSDefinitionExpressionImpl::new); - IElementType LET_EXPRESSION = new ElementTypeAsPsiFactory("LET_EXPRESSION", JavaScriptLanguage.INSTANCE, JSLetExpressionImpl::new); - - TokenSet PARAMETERS = TokenSet.create(FORMAL_PARAMETER, DESTRUCTURING_PARAMETER); - - @Deprecated - @DeprecationInfo("Use search by class") - TokenSet EXPRESSIONS = TokenSet.create(THIS_EXPRESSION, REFERENCE_EXPRESSION, LITERAL_EXPRESSION, REGEXP_LITERAL_EXPRESSION, PARENTHESIZED_EXPRESSION, - ARRAY_LITERAL_EXPRESSION, OBJECT_LITERAL_EXPRESSION, ASSIGNMENT_EXPRESSION, CONDITIONAL_EXPRESSION, BINARY_EXPRESSION, - PREFIX_EXPRESSION, POSTFIX_EXPRESSION, COMMA_EXPRESSION, FUNCTION_EXPRESSION, NEW_EXPRESSION, INDEXED_PROPERTY_ACCESS_EXPRESSION, - CALL_EXPRESSION, DEFINITION_EXPRESSION, XML_LITERAL_EXPRESSION, SUPER_EXPRESSION, LET_EXPRESSION); +public interface JSElementTypes { + IStubFileElementType FILE = new JSFileElementType(JavaScriptLanguage.INSTANCE); + + IElementType EMBEDDED_CONTENT = new ILazyParseableElementType("EMBEDDED_CONTENT", JavaScriptLanguage.INSTANCE) { + @Override + @RequiredReadAction + protected ASTNode doParseContents(@Nonnull ASTNode chameleon, @Nonnull PsiElement psi) { + LanguageVersion languageVersion = LanguageVersionUtil.findLanguageVersion(getLanguage(), psi); + Project project = psi.getProject(); + Language languageForParser = getLanguageForParser(psi); + PsiBuilder builder = PsiBuilderFactory.getInstance() + .createBuilder(project, chameleon, null, languageForParser, languageVersion, chameleon.getChars()); + PsiParser parser = ParserDefinition.forLanguage(languageForParser).createParser(languageVersion); + return parser.parse(this, builder, languageVersion).getFirstChildNode(); + } + }; + + IElementType EMBEDDED_EXPRESSION = + new ElementTypeAsPsiFactory("EMBEDDED_EXPRESSION", JavaScriptLanguage.INSTANCE, JSEmbeddedContentImpl::new); + + JSStubElementType FUNCTION_DECLARATION = JSStubElementTypes.FUNCTION_DECLARATION; + + JSStubElementType PARAMETER_LIST = JSStubElementTypes.PARAMETER_LIST; + + JSStubElementType FORMAL_PARAMETER = JSStubElementTypes.FORMAL_PARAMETER; + + JSStubElementType VARIABLE = JSStubElementTypes.VARIABLE; + IElementType ARGUMENT_LIST = + new ElementTypeAsPsiFactory("ARGUMENT_LIST", JavaScriptLanguage.INSTANCE, JSArgumentListImpl::new); + + JSStubElementType ATTRIBUTE = JSStubElementTypes.ATTRIBUTE; + JSStubElementType ATTRIBUTE_NAME_VALUE_PAIR = + JSStubElementTypes.ATTRIBUTE_NAME_VALUE_PAIR; + JSStubElementType ATTRIBUTE_LIST = JSStubElementTypes.ATTRIBUTE_LIST; + JSStubElementType PACKAGE_STATEMENT = JSStubElementTypes.PACKAGE_STATEMENT; + + @Deprecated + JSStubElementType ES4_IMPORT_STATEMENT = EcmaScript4ElementTypes.IMPORT_STATEMENT; + + JSStubElementType CLASS = JSStubElementTypes.CLASS; + JSStubElementType EXTENDS_LIST = JSStubElementTypes.EXTENDS_LIST; + JSStubElementType IMPLEMENTS_LIST = JSStubElementTypes.IMPLEMENTS_LIST; + JSStubElementType USE_NAMESPACE_DIRECTIVE = + JSStubElementTypes.USE_NAMESPACE_DIRECTIVE; + JSStubElementType INCLUDE_DIRECTIVE = JSStubElementTypes.INCLUDE_DIRECTIVE; + JSStubElementType NAMESPACE_DECLARATION = JSStubElementTypes.NAMESPACE_DECLARATION; + IElementType SUPER_EXPRESSION = + new ElementTypeAsPsiFactory("SUPER_EXPRESSION", JavaScriptLanguage.INSTANCE, JSSuperExpressionImpl::new); + IElementType GENERIC_SIGNATURE = + new ElementTypeAsPsiFactory("GENERIC_SIGNATURE", JavaScriptLanguage.INSTANCE, JSGenericSignatureImpl::new); + + // Statements + IElementType BLOCK_STATEMENT = + new ElementTypeAsPsiFactory("BLOCK_STATEMENT", JavaScriptLanguage.INSTANCE, JSBlockStatementImpl::new); + IElementType LABELED_STATEMENT = + new ElementTypeAsPsiFactory("LABELED_STATEMENT", JavaScriptLanguage.INSTANCE, JSLabeledStatementImpl::new); + IElementType EXPRESSION_STATEMENT = + new ElementTypeAsPsiFactory("EXPRESSION_STATEMENT", JavaScriptLanguage.INSTANCE, JSExpressionStatementImpl::new); + IElementType YIELD_STATEMENT = + new ElementTypeAsPsiFactory("YIELD_STATEMENT", JavaScriptLanguage.INSTANCE, JSYieldStatementImpl::new); + IElementType LET_STATEMENT = + new ElementTypeAsPsiFactory("LET_STATEMENT", JavaScriptLanguage.INSTANCE, JSLetStatementImpl::new); + JSStubElementType VAR_STATEMENT = JSStubElementTypes.VAR_STATEMENT; + IElementType EMPTY_STATEMENT = + new ElementTypeAsPsiFactory("EMPTY_STATEMENT", JavaScriptLanguage.INSTANCE, JSEmptyStatementImpl::new); + IElementType IF_STATEMENT = new ElementTypeAsPsiFactory("IF_STATEMENT", JavaScriptLanguage.INSTANCE, JSIfStatementImpl::new); + IElementType CONTINUE_STATEMENT = + new ElementTypeAsPsiFactory("CONTINUE_STATEMENT", JavaScriptLanguage.INSTANCE, JSContinueStatementImpl::new); + IElementType BREAK_STATEMENT = + new ElementTypeAsPsiFactory("BREAK_STATEMENT", JavaScriptLanguage.INSTANCE, JSBreakStatementImpl::new); + IElementType DESTRUCTURING_ELEMENT = + new ElementTypeAsPsiFactory("DESTRUCTURING_ELEMENT", JavaScriptLanguage.INSTANCE, JavaSciptDestructuringElementImpl::new); + IElementType DESTRUCTURING_PARAMETER = new ElementTypeAsPsiFactory( + "DESTRUCTURING_PARAMETER", + JavaScriptLanguage.INSTANCE, + JavaScriptDestructuringParameterImpl::new + ); + IElementType DESTRUCTURING_OBJECT = + new ElementTypeAsPsiFactory("DESTRUCTURING_OBJECT", JavaScriptLanguage.INSTANCE, JavaSciptDestructuringObjectImpl::new); + IElementType DESTRUCTURING_SHORTHANDED_PROPERTY = new ElementTypeAsPsiFactory( + "DESTRUCTURING_SHORTHANDED_PROPERTY", + JavaScriptLanguage.INSTANCE, + JavaScriptDestructuringShorthandedPropertyImpl::new + ); + IElementType WITH_STATEMENT = + new ElementTypeAsPsiFactory("WITH_STATEMENT", JavaScriptLanguage.INSTANCE, JSWithStatementImpl::new); + IElementType RETURN_STATEMENT = + new ElementTypeAsPsiFactory("RETURN_STATEMENT", JavaScriptLanguage.INSTANCE, JSReturnStatementImpl::new); + IElementType THROW_STATEMENT = + new ElementTypeAsPsiFactory("THROW_STATEMENT", JavaScriptLanguage.INSTANCE, JSThrowStatementImpl::new); + IElementType TRY_STATEMENT = + new ElementTypeAsPsiFactory("TRY_STATEMENT", JavaScriptLanguage.INSTANCE, JSTryStatementImpl::new); + IElementType CATCH_BLOCK = new ElementTypeAsPsiFactory("CATCH_BLOCK", JavaScriptLanguage.INSTANCE, JSCatchBlockImpl::new); + IElementType CASE_CLAUSE = new ElementTypeAsPsiFactory("CASE_CLAUSE", JavaScriptLanguage.INSTANCE, JSCaseClauseImpl::new); + IElementType SWITCH_STATEMENT = + new ElementTypeAsPsiFactory("SWITCH_STATEMENT", JavaScriptLanguage.INSTANCE, JSSwitchStatementImpl::new); + IElementType FOR_STATEMENT = + new ElementTypeAsPsiFactory("FOR_STATEMENT", JavaScriptLanguage.INSTANCE, JSForStatementImpl::new); + IElementType FOR_IN_STATEMENT = + new ElementTypeAsPsiFactory("FOR_IN_STATEMENT", JavaScriptLanguage.INSTANCE, JSForInStatementImpl::new); + IElementType WHILE_STATEMENT = + new ElementTypeAsPsiFactory("WHILE_STATEMENT", JavaScriptLanguage.INSTANCE, JSWhileStatementImpl::new); + IElementType DOWHILE_STATEMENT = + new ElementTypeAsPsiFactory("DO_WHILE_STATEMENT", JavaScriptLanguage.INSTANCE, JSDoWhileStatementImpl::new); + + @Deprecated + @DeprecationInfo("Use search by class") + TokenSet STATEMENTS = TokenSet.create( + BLOCK_STATEMENT, + LABELED_STATEMENT, + VAR_STATEMENT, + EMPTY_STATEMENT, + IF_STATEMENT, + CONTINUE_STATEMENT, + BREAK_STATEMENT, + WITH_STATEMENT, + RETURN_STATEMENT, + THROW_STATEMENT, + TRY_STATEMENT, + SWITCH_STATEMENT, + FOR_IN_STATEMENT, + FOR_STATEMENT, + WHILE_STATEMENT, + DOWHILE_STATEMENT, + EXPRESSION_STATEMENT, + YIELD_STATEMENT, + LET_STATEMENT, + ES4_IMPORT_STATEMENT, + PACKAGE_STATEMENT, + USE_NAMESPACE_DIRECTIVE + ); + + TokenSet SOURCE_ELEMENTS = TokenSet.orSet( + STATEMENTS, + TokenSet.create(FUNCTION_DECLARATION, CLASS, NAMESPACE_DECLARATION, INCLUDE_DIRECTIVE, USE_NAMESPACE_DIRECTIVE) + ); + + // Expressions + IElementType THIS_EXPRESSION = + new ElementTypeAsPsiFactory("THIS_EXPRESSION", JavaScriptLanguage.INSTANCE, JSThisExpressionImpl::new); + IElementType REFERENCE_EXPRESSION = + new ElementTypeAsPsiFactory("REFERENCE_EXPRESSION", JavaScriptLanguage.INSTANCE, JSReferenceExpressionImpl::new); + IElementType LITERAL_EXPRESSION = + new ElementTypeAsPsiFactory("LITERAL_EXPRESSION", JavaScriptLanguage.INSTANCE, JSLiteralExpressionImpl::new); + IElementType REGEXP_LITERAL_EXPRESSION = + new ElementTypeAsPsiFactory("REGEXP_LITERAL_EXPRESSION", JavaScriptLanguage.INSTANCE, JSRegExpLiteralExpressionImpl::new); + IElementType XML_LITERAL_EXPRESSION = + new ElementTypeAsPsiFactory("XML_LITERAL_EXPRESSION", JavaScriptLanguage.INSTANCE, JSXmlLiteralExpressionImpl::new); + IElementType PARENTHESIZED_EXPRESSION = + new ElementTypeAsPsiFactory("PARENTHESIZED_EXPRESSION", JavaScriptLanguage.INSTANCE, JSParenthesizedExpressionImpl::new); + IElementType ARRAY_LITERAL_EXPRESSION = + new ElementTypeAsPsiFactory("ARRAY_LITERAL_EXPRESSION", JavaScriptLanguage.INSTANCE, JSArrayLiteralExpressionImpl::new); + IElementType PROPERTY = new ElementTypeAsPsiFactory("PROPERTY", JavaScriptLanguage.INSTANCE, JSPropertyImpl::new); + IElementType FUNCTION_PROPERTY = + new ElementTypeAsPsiFactory("FUNCTION_PROPERTY", JavaScriptLanguage.INSTANCE, JSFunctionPropertyImpl::new); + IElementType COMPUTED_NAME = + new ElementTypeAsPsiFactory("COMPUTED_NAME", JavaScriptLanguage.INSTANCE, JSComputedNameImpl::new); + IElementType OBJECT_LITERAL_EXPRESSION = + new ElementTypeAsPsiFactory("OBJECT_LITERAL_EXPRESSION", JavaScriptLanguage.INSTANCE, JSObjectLiteralExpressionImpl::new); + IElementType ASSIGNMENT_EXPRESSION = + new ElementTypeAsPsiFactory("ASSIGNMENT_EXPRESSION", JavaScriptLanguage.INSTANCE, JSAssignmentExpressionImpl::new); + IElementType CONDITIONAL_EXPRESSION = + new ElementTypeAsPsiFactory("CONDITIONAL_EXPRESSION", JavaScriptLanguage.INSTANCE, JSConditionalExpressionImpl::new); + IElementType CLASS_EXPRESSION = + new ElementTypeAsPsiFactory("CLASS_EXPRESSION", JavaScriptLanguage.INSTANCE, JSClassExpressionImpl::new); + IElementType BINARY_EXPRESSION = + new ElementTypeAsPsiFactory("BINARY_EXPRESSION", JavaScriptLanguage.INSTANCE, JSBinaryExpressionImpl::new); + IElementType PREFIX_EXPRESSION = + new ElementTypeAsPsiFactory("PREFIX_EXPRESSION", JavaScriptLanguage.INSTANCE, JSPrefixExpressionImpl::new); + IElementType POSTFIX_EXPRESSION = + new ElementTypeAsPsiFactory("POSTFIX_EXPRESSION", JavaScriptLanguage.INSTANCE, JSPostfixExpressionImpl::new); + IElementType LAMBDA_EXPRESSION = + new ElementTypeAsPsiFactory("LAMBDA_EXPRESSION", JavaScriptLanguage.INSTANCE, JavaScriptLambdaExpressionImpl::new); + IElementType SPREAD_EXPRESSION = + new ElementTypeAsPsiFactory("SPREAD_EXPRESSION", JavaScriptLanguage.INSTANCE, JavaScriptSpreadExpressionImpl::new); + IElementType COMMA_EXPRESSION = + new ElementTypeAsPsiFactory("COMMA_EXPRESSION", JavaScriptLanguage.INSTANCE, JSCommaExpressionImpl::new); + JSStubElementType FUNCTION_EXPRESSION = new JSFunctionElementType("FUNCTION_EXPRESSION") { + @Override + public JSFunction createPsi(@Nonnull JSFunctionStub stub) { + return new JSFunctionExpressionImpl(stub, this); + } + + @Nonnull + @Override + public PsiElement createElement(@Nonnull ASTNode astNode) { + return new JSFunctionExpressionImpl(astNode); + } + }; + IElementType NEW_EXPRESSION = + new ElementTypeAsPsiFactory("NEW_EXPRESSION", JavaScriptLanguage.INSTANCE, JSNewExpressionImpl::new); + + IElementType INDEXED_PROPERTY_ACCESS_EXPRESSION = + new ElementTypeAsPsiFactory( + "INDEXED_PROPERTY_ACCESS_EXPRESSION", + JavaScriptLanguage.INSTANCE, + JSIndexedPropertyAccessExpressionImpl::new + ); + IElementType CALL_EXPRESSION = + new ElementTypeAsPsiFactory("CALL_EXPRESSION", JavaScriptLanguage.INSTANCE, JSCallExpressionImpl::new); + IElementType DEFINITION_EXPRESSION = + new ElementTypeAsPsiFactory("DEFINITION_EXPRESSION", JavaScriptLanguage.INSTANCE, JSDefinitionExpressionImpl::new); + IElementType LET_EXPRESSION = + new ElementTypeAsPsiFactory("LET_EXPRESSION", JavaScriptLanguage.INSTANCE, JSLetExpressionImpl::new); + + TokenSet PARAMETERS = TokenSet.create(FORMAL_PARAMETER, DESTRUCTURING_PARAMETER); + @Deprecated + @DeprecationInfo("Use search by class") + TokenSet EXPRESSIONS = TokenSet.create( + THIS_EXPRESSION, + REFERENCE_EXPRESSION, + LITERAL_EXPRESSION, + REGEXP_LITERAL_EXPRESSION, + PARENTHESIZED_EXPRESSION, + ARRAY_LITERAL_EXPRESSION, + OBJECT_LITERAL_EXPRESSION, + ASSIGNMENT_EXPRESSION, + CONDITIONAL_EXPRESSION, + BINARY_EXPRESSION, + PREFIX_EXPRESSION, + POSTFIX_EXPRESSION, + COMMA_EXPRESSION, + FUNCTION_EXPRESSION, + NEW_EXPRESSION, + INDEXED_PROPERTY_ACCESS_EXPRESSION, + CALL_EXPRESSION, + DEFINITION_EXPRESSION, + XML_LITERAL_EXPRESSION, + SUPER_EXPRESSION, + LET_EXPRESSION + ); } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/JSFlexAdapter.java b/base-impl/src/main/java/com/intellij/lang/javascript/JSFlexAdapter.java index a2db5938..6419949f 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/JSFlexAdapter.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/JSFlexAdapter.java @@ -21,31 +21,26 @@ /** * @author Maxim.Mossienko */ -public class JSFlexAdapter extends FlexAdapter -{ - private static final int BASE_STATE_MASK = 0xF; - private static final int TAG_COUNT_SHIFT = 4; +public class JSFlexAdapter extends FlexAdapter { + private static final int BASE_STATE_MASK = 0xF; + private static final int TAG_COUNT_SHIFT = 4; - public JSFlexAdapter(boolean highlight, DialectOptionHolder optionHolder) - { - super(new _JavaScriptLexer(highlight, optionHolder)); - } + public JSFlexAdapter(boolean highlight, DialectOptionHolder optionHolder) { + super(new _JavaScriptLexer(highlight, optionHolder)); + } - @Override - public void start(final CharSequence buffer, final int startOffset, final int endOffset, final int initialState) - { - super.start(buffer, startOffset, endOffset, initialState & BASE_STATE_MASK); - ((_JavaScriptLexer) getFlex()).setTagCount(initialState >> TAG_COUNT_SHIFT); - } + @Override + public void start(CharSequence buffer, int startOffset, int endOffset, int initialState) { + super.start(buffer, startOffset, endOffset, initialState & BASE_STATE_MASK); + ((_JavaScriptLexer)getFlex()).setTagCount(initialState >> TAG_COUNT_SHIFT); + } - @Override - public int getState() - { - return getStateInternal() + (((_JavaScriptLexer) getFlex()).getTagCount() << TAG_COUNT_SHIFT); - } + @Override + public int getState() { + return getStateInternal() + (((_JavaScriptLexer)getFlex()).getTagCount() << TAG_COUNT_SHIFT); + } - protected int getStateInternal() - { - return super.getState(); - } + protected int getStateInternal() { + return super.getState(); + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/JSLanguageInjector.java b/base-impl/src/main/java/com/intellij/lang/javascript/JSLanguageInjector.java index e5380a33..bac1ba0f 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/JSLanguageInjector.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/JSLanguageInjector.java @@ -35,401 +35,381 @@ import consulo.xml.psi.xml.*; import org.jetbrains.annotations.NonNls; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author Maxim.Mossienko - * Date: Apr 28, 2008 - * Time: 8:40:38 PM + * Date: Apr 28, 2008 + * Time: 8:40:38 PM */ -public abstract class JSLanguageInjector implements MultiHostInjector -{ - @NonNls - private static final String JAVASCRIPT_PREFIX = "javascript:"; - @NonNls - public static final String JSP_URI = "http://java.sun.com/JSP/Page"; - - private static final NamedPointer CSS_LANGUAGE = LanguagePointerUtil.createPointer("CSS"); - - @Override - public void injectLanguages(@Nonnull MultiHostRegistrar registrar, @Nonnull PsiElement host) - { - if(host instanceof XmlAttributeValue) - { - final PsiElement attribute = host.getParent(); - final PsiElement tag = attribute.getParent(); - - if(attribute instanceof XmlAttribute && tag instanceof XmlTag) - { - if(host.getTextLength() == 0) - { - return; - } - @NonNls String attrName = ((XmlAttribute) attribute).getName(); - if(tag instanceof HtmlTag) - { - attrName = attrName.toLowerCase(); - } - - if("href".equals(attrName) && ((XmlAttributeValue) host).getValue().startsWith(JAVASCRIPT_PREFIX)) - { - injectJSIntoAttributeValue(registrar, (XmlAttributeValue) host, true); - } - else if(attrName.startsWith("on")) - { - final String ns = ((XmlTag) tag).getNamespace(); - if(JavaScriptSupportLoader.BINDOWS_URI.equals(ns) || - JavaScriptSupportLoader.isBindowsFile(host) || - isMozillaXulOrXblNs(ns)) - { - TextRange range = new TextRange(1, host.getTextLength() - 1); - registrar.startInjecting(JavaScriptLanguage.INSTANCE).addPlace(null, null, (PsiLanguageInjectionHost) host, - range).doneInjecting(); - } - else - { - checkMxmlInjection(registrar, host, attribute, tag); - } - } - else if("style".equals(attrName) && isMozillaXulOrXblNs(((XmlTag) tag).getNamespace()) && CSS_LANGUAGE.get() != null) - { - registrar.startInjecting(CSS_LANGUAGE.get()).addPlace("inline.style {", "}", (PsiLanguageInjectionHost) host, new TextRange(1, - host.getTextLength() - 1)).doneInjecting(); - } - else if("implements".equals(attrName) && JavaScriptSupportLoader.isFlexMxmFile(tag.getContainingFile())) - { - TextRange range = new TextRange(1, host.getTextLength() - 1); - registrar.startInjecting(JavaScriptSupportLoader.ECMA_SCRIPT_L4).addPlace("class Foo implements ", " {}", (PsiLanguageInjectionHost) host, - range).doneInjecting(); - } - else if(attrName.equalsIgnoreCase("dojoType")) - { - TextRange range = new TextRange(1, host.getTextLength() - 1); - registrar.startInjecting(JavaScriptSupportLoader.ECMA_SCRIPT_L4).addPlace("var a:", null, (PsiLanguageInjectionHost) host, - range).doneInjecting(); - } - else if(attrName.equalsIgnoreCase("djConfig")) - { - TextRange range = new TextRange(1, host.getTextLength() - 1); - registrar.startInjecting(JavaScriptLanguage.INSTANCE).addPlace("a = { ", " }", (PsiLanguageInjectionHost) host, - range).doneInjecting(); - } - else - { - checkMxmlInjection(registrar, host, attribute, tag); - } - } - } - else if(host instanceof XmlText) - { - final PsiElement _tag = host.getParent(); - if(_tag instanceof XmlTag) - { - final XmlTag tag = (XmlTag) _tag; - - final @NonNls String localName = tag.getLocalName(); - - if("attribute".equals(localName) && JSP_URI.equals(tag.getNamespace())) - { - @NonNls final String name = tag.getAttributeValue("name"); - if(name != null && name.startsWith("on")) - { - Language language = JavaScriptLanguage.INSTANCE; - injectToXmlText(registrar, host, language, null, null); - } - } - else if("Style".equals(localName) && JavaScriptSupportLoader.isMxmlNs(tag.getNamespace()) && CSS_LANGUAGE.get() != null) - { - injectToXmlText(registrar, host, CSS_LANGUAGE.get(), null, null); - } - else if((("script".equals(localName) && ((tag.getNamespacePrefix().length() > 0 && doInjectTo(tag)) || isMozillaXulOrXblNs(tag.getNamespace())) - ) || - "Script".equals(localName) || - "Metadata".equals(localName)) && !(tag instanceof HtmlTag)) - { - boolean inject = true; - boolean ecma = JavaScriptSupportLoader.isFlexMxmFile(tag.getContainingFile()); - if(ecma && tag.getAttributeValue("source") != null) - { - inject = false; - } - Language language = ecma ? JavaScriptSupportLoader.ECMA_SCRIPT_L4 : JavaScriptLanguage.INSTANCE; - if(inject) - { - injectToXmlText(registrar, host, language, null, null); - } - } - else if(!(tag instanceof HtmlTag) && JavaScriptSupportLoader.isFlexMxmFile(tag.getContainingFile()) && tag.getSubTags().length == 0) - { - injectInMxmlFile(registrar, host, tag.getDescriptor(), tag); - } - else - { - boolean getter; - boolean setter = false; - boolean field = false; - boolean body = false; - boolean handler = false; - boolean constructor = false; - - if(((getter = "getter".equals(localName)) || - (setter = "setter".equals(localName)) || - (field = "field".equals(localName)) || - (body = "body".equals(localName)) || - (handler = "handler".equals(localName)) || - //(property = ("property".equals(localName) && tag.getSubTags().length == 0)) || - (constructor = "constructor".equals(localName))) && isMozillaXulOrXblNs(tag.getNamespace())) - { - @NonNls String prefix = null; - @NonNls String suffix = null; - - if(getter || setter) - { - final String name = getNameFromTag(tag.getParentTag(), "property"); - prefix = "function " + (getter ? "get " : "set ") + name + "(" + (setter ? "val" : "") + ") {"; - suffix = "}"; - } - else if(body) - { - final XmlTag parentTag = tag.getParentTag(); - String name = getNameFromTag(parentTag, "method"); - String signature = ""; - for(XmlTag ptag : parentTag.findSubTags("parameter")) - { - if(signature.length() > 0) - { - signature += ", "; - } - signature += ptag.getAttributeValue("name"); - } - prefix = "function " + name + "(" + signature + ") {"; - suffix = "}"; - } - else if(field) - { - prefix = "var " + tag.getAttributeValue("name") + " = "; - } - else if(handler) - { - prefix = "function " + tag.getAttributeValue("event") + " {"; - suffix = "}"; - } - else if(constructor) - { - final XmlTag parentTag = tag.getParentTag(); - final XmlTag grandParentTag = parentTag != null ? parentTag.getParentTag() : null; - prefix = "function " + (grandParentTag != null ? grandParentTag.getAttributeValue("id") : null) + "() {"; - suffix = "}"; - } - - injectToXmlText(registrar, host, JavaScriptLanguage.INSTANCE, prefix, suffix); - } - } - } - } - } - - private boolean doInjectTo(final XmlTag tag) - { - final XmlTagValue value = tag.getValue(); - final XmlTagChild[] tagChildren = value.getChildren(); - - return tagChildren.length == 1 && (tagChildren[0].getNode().getElementType() == XmlElementType.XML_CDATA || !tagChildren[0].textContains('<')); - } - - private static void checkMxmlInjection(final MultiHostRegistrar registrar, final PsiElement host, final PsiElement attribute, final PsiElement _tag) - { - final PsiFile containingFile = _tag.getContainingFile(); - if(JavaScriptSupportLoader.isFlexMxmFile(containingFile)) - { - injectInMxmlFile(registrar, host, ((XmlAttribute) attribute).getDescriptor(), (XmlTag) _tag); - } - } - - private static void injectToXmlText(final MultiHostRegistrar registrar, final PsiElement host, final Language language, final String prefix, - final String suffix) - { - TextRange range = new TextRange(0, host.getTextLength()); - registrar.startInjecting(language).addPlace(prefix, suffix, (PsiLanguageInjectionHost) host, range).doneInjecting(); - } - - private static String getNameFromTag(final XmlTag parentTag, final @NonNls String s) - { - return parentTag != null && s.equals(parentTag.getLocalName()) ? parentTag.getAttributeValue("name") : ""; - } - - public static boolean isMozillaXulOrXblNs(final @NonNls String ns) - { - return "http://www.mozilla.org/xbl".equals(ns) || "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul".equals(ns); - } - - public static void injectJSIntoAttributeValue(final MultiHostRegistrar registrar, final XmlAttributeValue host, final boolean startsWithPrefix) - { - final PsiElement[] myChildren = host.getChildren(); - int valueIndex = myChildren.length - 2; - int valueTokenNumber = 1; - if(valueIndex < 0) - { - valueIndex = 0; - valueTokenNumber = 0; - } - - final PsiElement valueChild = myChildren[valueIndex]; - - if(valueChild instanceof XmlToken && ((XmlToken) valueChild).getTokenType() == XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN) - { - boolean injectFromTheBeginning = valueIndex == valueTokenNumber; - if(!injectFromTheBeginning) - { - // check if well formed el holder - boolean wellFormed = true; - boolean badlyFormed = false; - - for(int i = valueTokenNumber; i < valueIndex; ++i) - { - final PsiElement currentElement = myChildren[i]; - - if(currentElement instanceof XmlToken && ((XmlToken) currentElement).getTokenType() == XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN) - { - // ok child - continue; - } - else - { - - if(currentElement instanceof OuterLanguageElement) - { - final String prevText = myChildren[i - 1].getText(); - final String nextText = myChildren[i + 1].getText(); - - if((StringUtil.endsWithChar(prevText, '\"') && StringUtil.startsWithChar(nextText, '\"')) || (StringUtil.endsWithChar(prevText, - '\'') && StringUtil.startsWithChar(nextText, '\''))) - { - // ok child - continue; - } - else if((StringUtil.endsWithChar(prevText, '(') && StringUtil.startsWithChar(nextText, ')')) && currentElement.textContains('<')) - { - badlyFormed = true; - } - else if(currentElement.textContains('$')) - { - final String s = currentElement.getText(); - if(s.startsWith("${") && s.endsWith("}") && s.length() > 2) - { - continue; - } - } - else if(currentElement.textContains('%')) - { - badlyFormed = true; - } - } - - wellFormed = false; - break; - } - } - - if(badlyFormed) - { - return; - } - if(wellFormed) - { - injectFromTheBeginning = wellFormed; - } - } - TextRange range = new TextRange(injectFromTheBeginning ? valueTokenNumber + (startsWithPrefix ? JAVASCRIPT_PREFIX.length() : 0) : valueChild - .getStartOffsetInParent(), host.getTextLength() - valueTokenNumber); - Language language = JavaScriptLanguage.INSTANCE; - registrar.startInjecting(language).addPlace(null, null, (PsiLanguageInjectionHost) host, range).doneInjecting(); - - } - } - - private static void injectInMxmlFile(final MultiHostRegistrar registrar, final PsiElement host, final PsiMetaData descriptor, XmlTag tag) - { - int offset = host instanceof XmlText ? 0 : 1; - - if(descriptor instanceof AnnotationBackedDescriptor && ((XmlElementDescriptorWithCDataContent) descriptor).requiresCdataBracesInContext(tag)) - { - final int length = host.getTextLength(); - if(length < 2 * offset) - { - return; - } - String type = ((AnnotationBackedDescriptor) descriptor).getType(); - if(type == null) - { - type = "*"; - } - final @NonNls String prefix = "(function (event:" + type + ") {"; - final @NonNls String suffix = "})();"; - - if(host instanceof XmlText) - { - injectToXmlText(registrar, host, JavaScriptSupportLoader.ECMA_SCRIPT_L4, prefix, suffix); - } - else - { - TextRange range = new TextRange(offset, length - offset); - - registrar.startInjecting(JavaScriptSupportLoader.ECMA_SCRIPT_L4).addPlace(prefix, (host instanceof XmlAttributeValue ? "\n" : "") + suffix, - (PsiLanguageInjectionHost) host, range).doneInjecting(); - } - } - else - { - final String text = StringUtil.stripQuotesAroundValue(host.getText()); - int openedBraces = 0; - int start = -1; - boolean addedSomething = false; - boolean quoted = false; - - for(int i = 0; i < text.length(); ++i) - { - final char ch = text.charAt(i); - - if(quoted) - { - quoted = false; - continue; - } - if(ch == '\\') - { - quoted = true; - } - else if(ch == '{') - { - if(openedBraces == 0) - { - start = i + 1; - } - openedBraces++; - } - else if(ch == '}') - { - openedBraces--; - if(openedBraces == 0 && start != -1) - { - registrar.startInjecting(JavaScriptSupportLoader.ECMA_SCRIPT_L4).addPlace("(function (){}) (", "\n);", (PsiLanguageInjectionHost) host, new TextRange(offset + start, i + offset)).doneInjecting(); - addedSomething = true; - start = -1; - } - } - } - - if(!addedSomething) - { - final String trimmedText = text.trim(); - start = trimmedText.indexOf("@Embed"); - if(start == 0) - { - offset += text.indexOf(trimmedText); - registrar.startInjecting(JavaScriptSupportLoader.ECMA_SCRIPT_L4).addPlace(null, null, (PsiLanguageInjectionHost) host, new TextRange(offset, trimmedText.length() + offset)).doneInjecting(); - } - } - } - } +public abstract class JSLanguageInjector implements MultiHostInjector { + @NonNls + private static final String JAVASCRIPT_PREFIX = "javascript:"; + @NonNls + public static final String JSP_URI = "http://java.sun.com/JSP/Page"; + + private static final NamedPointer CSS_LANGUAGE = LanguagePointerUtil.createPointer("CSS"); + + @Override + public void injectLanguages(@Nonnull MultiHostRegistrar registrar, @Nonnull PsiElement host) { + if (host instanceof XmlAttributeValue attributeValue) { + PsiElement attribute = attributeValue.getParent(); + PsiElement tag = attribute.getParent(); + + if (attribute instanceof XmlAttribute xmlAttribute && tag instanceof XmlTag xmlTag) { + if (attributeValue.getTextLength() == 0) { + return; + } + @NonNls String attrName = xmlAttribute.getName(); + if (tag instanceof HtmlTag) { + attrName = attrName.toLowerCase(); + } + + if ("href".equals(attrName) && attributeValue.getValue().startsWith(JAVASCRIPT_PREFIX)) { + injectJSIntoAttributeValue(registrar, attributeValue, true); + } + else if (attrName.startsWith("on")) { + String ns = xmlTag.getNamespace(); + if (JavaScriptSupportLoader.BINDOWS_URI.equals(ns) + || JavaScriptSupportLoader.isBindowsFile(attributeValue) + || isMozillaXulOrXblNs(ns)) { + TextRange range = new TextRange(1, attributeValue.getTextLength() - 1); + registrar.startInjecting(JavaScriptLanguage.INSTANCE) + .addPlace(null, null, (PsiLanguageInjectionHost)attributeValue, range) + .doneInjecting(); + } + else { + checkMxmlInjection(registrar, attributeValue, attribute, tag); + } + } + else if ("style".equals(attrName) && isMozillaXulOrXblNs(xmlTag.getNamespace()) && CSS_LANGUAGE.get() != null) { + registrar.startInjecting(CSS_LANGUAGE.get()) + .addPlace( + "inline.style {", + "}", + (PsiLanguageInjectionHost)attributeValue, + new TextRange(1, attributeValue.getTextLength() - 1) + ) + .doneInjecting(); + } + else if ("implements".equals(attrName) && JavaScriptSupportLoader.isFlexMxmFile(tag.getContainingFile())) { + TextRange range = new TextRange(1, attributeValue.getTextLength() - 1); + registrar.startInjecting(JavaScriptSupportLoader.ECMA_SCRIPT_L4) + .addPlace("class Foo implements ", " {}", (PsiLanguageInjectionHost)attributeValue, range) + .doneInjecting(); + } + else if (attrName.equalsIgnoreCase("dojoType")) { + TextRange range = new TextRange(1, attributeValue.getTextLength() - 1); + registrar.startInjecting(JavaScriptSupportLoader.ECMA_SCRIPT_L4) + .addPlace("var a:", null, (PsiLanguageInjectionHost)attributeValue, range) + .doneInjecting(); + } + else if (attrName.equalsIgnoreCase("djConfig")) { + TextRange range = new TextRange(1, attributeValue.getTextLength() - 1); + registrar.startInjecting(JavaScriptLanguage.INSTANCE) + .addPlace("a = { ", " }", (PsiLanguageInjectionHost)attributeValue, range) + .doneInjecting(); + } + else { + checkMxmlInjection(registrar, attributeValue, attribute, tag); + } + } + } + else if (host instanceof XmlText && host.getParent() instanceof XmlTag tag) { + @NonNls String localName = tag.getLocalName(); + + if ("attribute".equals(localName) && JSP_URI.equals(tag.getNamespace())) { + @NonNls String name = tag.getAttributeValue("name"); + if (name != null && name.startsWith("on")) { + Language language = JavaScriptLanguage.INSTANCE; + injectToXmlText(registrar, host, language, null, null); + } + } + else if ("Style".equals(localName) && JavaScriptSupportLoader.isMxmlNs(tag.getNamespace()) && CSS_LANGUAGE.get() != null) { + injectToXmlText(registrar, host, CSS_LANGUAGE.get(), null, null); + } + else if ((("script".equals(localName) && ((tag.getNamespacePrefix().length() > 0 && doInjectTo(tag)) + || isMozillaXulOrXblNs(tag.getNamespace()))) || "Script".equals(localName) || "Metadata".equals(localName)) + && !(tag instanceof HtmlTag)) { + boolean inject = true; + boolean ecma = JavaScriptSupportLoader.isFlexMxmFile(tag.getContainingFile()); + if (ecma && tag.getAttributeValue("source") != null) { + inject = false; + } + Language language = ecma ? JavaScriptSupportLoader.ECMA_SCRIPT_L4 : JavaScriptLanguage.INSTANCE; + if (inject) { + injectToXmlText(registrar, host, language, null, null); + } + } + else if (!(tag instanceof HtmlTag) && JavaScriptSupportLoader.isFlexMxmFile(tag.getContainingFile()) + && tag.getSubTags().length == 0) { + injectInMxmlFile(registrar, host, tag.getDescriptor(), tag); + } + else { + boolean getter; + boolean setter = false; + boolean field = false; + boolean body = false; + boolean handler = false; + boolean constructor = false; + + if (((getter = "getter".equals(localName)) + || (setter = "setter".equals(localName)) + || (field = "field".equals(localName)) + || (body = "body".equals(localName)) + || (handler = "handler".equals(localName)) + //|| (property = ("property".equals(localName) && tag.getSubTags().length == 0)) + || (constructor = "constructor".equals(localName))) + && isMozillaXulOrXblNs(tag.getNamespace())) { + @NonNls String prefix = null; + @NonNls String suffix = null; + + if (getter || setter) { + String name = getNameFromTag(tag.getParentTag(), "property"); + prefix = "function " + (getter ? "get " : "set ") + name + "(" + (setter ? "val" : "") + ") {"; + suffix = "}"; + } + else if (body) { + XmlTag parentTag = tag.getParentTag(); + String name = getNameFromTag(parentTag, "method"); + String signature = ""; + for (XmlTag ptag : parentTag.findSubTags("parameter")) { + if (signature.length() > 0) { + signature += ", "; + } + signature += ptag.getAttributeValue("name"); + } + prefix = "function " + name + "(" + signature + ") {"; + suffix = "}"; + } + else if (field) { + prefix = "var " + tag.getAttributeValue("name") + " = "; + } + else if (handler) { + prefix = "function " + tag.getAttributeValue("event") + " {"; + suffix = "}"; + } + else if (constructor) { + XmlTag parentTag = tag.getParentTag(); + XmlTag grandParentTag = parentTag != null ? parentTag.getParentTag() : null; + prefix = "function " + (grandParentTag != null ? grandParentTag.getAttributeValue("id") : null) + "() {"; + suffix = "}"; + } + + injectToXmlText(registrar, host, JavaScriptLanguage.INSTANCE, prefix, suffix); + } + } + } + } + + private boolean doInjectTo(XmlTag tag) { + XmlTagValue value = tag.getValue(); + XmlTagChild[] tagChildren = value.getChildren(); + + return tagChildren.length == 1 + && (tagChildren[0].getNode().getElementType() == XmlElementType.XML_CDATA || !tagChildren[0].textContains('<')); + } + + private static void checkMxmlInjection( + MultiHostRegistrar registrar, + PsiElement host, + PsiElement attribute, + PsiElement _tag + ) { + PsiFile containingFile = _tag.getContainingFile(); + if (JavaScriptSupportLoader.isFlexMxmFile(containingFile)) { + injectInMxmlFile(registrar, host, ((XmlAttribute)attribute).getDescriptor(), (XmlTag)_tag); + } + } + + private static void injectToXmlText( + MultiHostRegistrar registrar, + PsiElement host, + Language language, + String prefix, + String suffix + ) { + TextRange range = new TextRange(0, host.getTextLength()); + registrar.startInjecting(language).addPlace(prefix, suffix, (PsiLanguageInjectionHost)host, range).doneInjecting(); + } + + private static String getNameFromTag(XmlTag parentTag, @NonNls String s) { + return parentTag != null && s.equals(parentTag.getLocalName()) ? parentTag.getAttributeValue("name") : ""; + } + + public static boolean isMozillaXulOrXblNs(@NonNls String ns) { + return "http://www.mozilla.org/xbl".equals(ns) || "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul".equals(ns); + } + + public static void injectJSIntoAttributeValue( + MultiHostRegistrar registrar, + XmlAttributeValue host, + boolean startsWithPrefix + ) { + PsiElement[] myChildren = host.getChildren(); + int valueIndex = myChildren.length - 2; + int valueTokenNumber = 1; + if (valueIndex < 0) { + valueIndex = 0; + valueTokenNumber = 0; + } + + PsiElement valueChild = myChildren[valueIndex]; + + if (valueChild instanceof XmlToken && ((XmlToken)valueChild).getTokenType() == XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN) { + boolean injectFromTheBeginning = valueIndex == valueTokenNumber; + if (!injectFromTheBeginning) { + // check if well formed el holder + boolean wellFormed = true; + boolean badlyFormed = false; + + for (int i = valueTokenNumber; i < valueIndex; ++i) { + PsiElement currentElement = myChildren[i]; + + if (currentElement instanceof XmlToken && ((XmlToken)currentElement).getTokenType() == XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN) { + // ok child + continue; + } + else { + if (currentElement instanceof OuterLanguageElement) { + String prevText = myChildren[i - 1].getText(); + String nextText = myChildren[i + 1].getText(); + + if ((StringUtil.endsWithChar(prevText, '\"') && StringUtil.startsWithChar(nextText, '\"')) + || (StringUtil.endsWithChar(prevText, '\'') && StringUtil.startsWithChar(nextText, '\''))) { + // ok child + continue; + } + else if ((StringUtil.endsWithChar(prevText, '(') && StringUtil.startsWithChar(nextText, ')')) + && currentElement.textContains('<')) { + badlyFormed = true; + } + else if (currentElement.textContains('$')) { + String s = currentElement.getText(); + if (s.startsWith("${") && s.endsWith("}") && s.length() > 2) { + continue; + } + } + else if (currentElement.textContains('%')) { + badlyFormed = true; + } + } + + wellFormed = false; + break; + } + } + + if (badlyFormed) { + return; + } + if (wellFormed) { + injectFromTheBeginning = wellFormed; + } + } + TextRange range = new TextRange( + injectFromTheBeginning + ? valueTokenNumber + (startsWithPrefix ? JAVASCRIPT_PREFIX.length() : 0) + : valueChild.getStartOffsetInParent(), + host.getTextLength() - valueTokenNumber + ); + Language language = JavaScriptLanguage.INSTANCE; + registrar.startInjecting(language).addPlace(null, null, (PsiLanguageInjectionHost)host, range).doneInjecting(); + } + } + + private static void injectInMxmlFile( + MultiHostRegistrar registrar, + PsiElement host, + PsiMetaData descriptor, + XmlTag tag + ) { + int offset = host instanceof XmlText ? 0 : 1; + + if (descriptor instanceof AnnotationBackedDescriptor annotationBackedDescriptor + && annotationBackedDescriptor.requiresCdataBracesInContext(tag)) { + int length = host.getTextLength(); + if (length < 2 * offset) { + return; + } + String type = ((AnnotationBackedDescriptor)descriptor).getType(); + if (type == null) { + type = "*"; + } + @NonNls String prefix = "(function (event:" + type + ") {"; + @NonNls String suffix = "})();"; + + if (host instanceof XmlText) { + injectToXmlText(registrar, host, JavaScriptSupportLoader.ECMA_SCRIPT_L4, prefix, suffix); + } + else { + TextRange range = new TextRange(offset, length - offset); + + registrar.startInjecting(JavaScriptSupportLoader.ECMA_SCRIPT_L4) + .addPlace( + prefix, + (host instanceof XmlAttributeValue ? "\n" : "") + suffix, + (PsiLanguageInjectionHost)host, + range + ) + .doneInjecting(); + } + } + else { + String text = StringUtil.stripQuotesAroundValue(host.getText()); + int openedBraces = 0; + int start = -1; + boolean addedSomething = false; + boolean quoted = false; + + for (int i = 0; i < text.length(); ++i) { + char ch = text.charAt(i); + + if (quoted) { + quoted = false; + continue; + } + if (ch == '\\') { + quoted = true; + } + else if (ch == '{') { + if (openedBraces == 0) { + start = i + 1; + } + openedBraces++; + } + else if (ch == '}') { + openedBraces--; + if (openedBraces == 0 && start != -1) { + registrar.startInjecting(JavaScriptSupportLoader.ECMA_SCRIPT_L4) + .addPlace( + "(function (){}) (", + "\n);", + (PsiLanguageInjectionHost)host, + new TextRange(offset + start, i + offset) + ) + .doneInjecting(); + addedSomething = true; + start = -1; + } + } + } + + if (!addedSomething) { + String trimmedText = text.trim(); + start = trimmedText.indexOf("@Embed"); + if (start == 0) { + offset += text.indexOf(trimmedText); + registrar.startInjecting(JavaScriptSupportLoader.ECMA_SCRIPT_L4) + .addPlace( + null, + null, + (PsiLanguageInjectionHost)host, + new TextRange(offset, trimmedText.length() + offset) + ) + .doneInjecting(); + } + } + } + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/JSStubElementTypes.java b/base-impl/src/main/java/com/intellij/lang/javascript/JSStubElementTypes.java index f0a5c917..6e71b179 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/JSStubElementTypes.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/JSStubElementTypes.java @@ -8,46 +8,43 @@ import consulo.language.ast.ASTNode; import consulo.language.psi.PsiElement; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 29-Aug-22 */ -public interface JSStubElementTypes -{ - JSStubElementType FUNCTION_DECLARATION = new JSFunctionElementType("FUNCTION_DECLARATION") - { - @Override - public JSFunction createPsi(@Nonnull JSFunctionStub stub) - { - return new JSFunctionImpl(stub, this); - } - - @Nonnull - @Override - public PsiElement createElement(@Nonnull ASTNode astNode) - { - return new JSFunctionImpl(astNode); - } - }; - JSStubElementType PARAMETER_LIST = new JSParameterListElementType(); - - JSStubElementType FORMAL_PARAMETER = new JSParameterElementType(); - - JSStubElementType VARIABLE = new JSVariableElementType(); - - JSStubElementType ATTRIBUTE = new JSAttributeElementType(); - JSStubElementType ATTRIBUTE_NAME_VALUE_PAIR = new JSAttributeNameValuePairType(); - JSStubElementType ATTRIBUTE_LIST = new JSAttributeListElementType(); - JSStubElementType PACKAGE_STATEMENT = new JSPackageStatementElementType(); - - JSStubElementType CLASS = new JSClassElementType(); - JSStubElementType EXTENDS_LIST = new JSReferenceListElementType("EXTENDS_LIST"); - JSStubElementType IMPLEMENTS_LIST = new JSReferenceListElementType("IMPLEMENTS_LIST"); - JSStubElementType USE_NAMESPACE_DIRECTIVE = new JSUseNamespaceDirectiveType(); - JSStubElementType INCLUDE_DIRECTIVE = new JSIncludeDirectiveElementType(); - JSStubElementType NAMESPACE_DECLARATION = new JSNamespaceDeclarationElementType(); - - JSStubElementType VAR_STATEMENT = new JSVarStatementElementType(); +public interface JSStubElementTypes { + JSStubElementType FUNCTION_DECLARATION = new JSFunctionElementType("FUNCTION_DECLARATION") { + @Override + public JSFunction createPsi(@Nonnull JSFunctionStub stub) { + return new JSFunctionImpl(stub, this); + } + + @Nonnull + @Override + public PsiElement createElement(@Nonnull ASTNode astNode) { + return new JSFunctionImpl(astNode); + } + }; + JSStubElementType PARAMETER_LIST = new JSParameterListElementType(); + + JSStubElementType FORMAL_PARAMETER = new JSParameterElementType(); + + JSStubElementType VARIABLE = new JSVariableElementType(); + + JSStubElementType ATTRIBUTE = new JSAttributeElementType(); + JSStubElementType ATTRIBUTE_NAME_VALUE_PAIR = + new JSAttributeNameValuePairType(); + JSStubElementType ATTRIBUTE_LIST = new JSAttributeListElementType(); + JSStubElementType PACKAGE_STATEMENT = new JSPackageStatementElementType(); + + JSStubElementType CLASS = new JSClassElementType(); + JSStubElementType EXTENDS_LIST = new JSReferenceListElementType("EXTENDS_LIST"); + JSStubElementType IMPLEMENTS_LIST = new JSReferenceListElementType("IMPLEMENTS_LIST"); + JSStubElementType USE_NAMESPACE_DIRECTIVE = new JSUseNamespaceDirectiveType(); + JSStubElementType INCLUDE_DIRECTIVE = new JSIncludeDirectiveElementType(); + JSStubElementType NAMESPACE_DECLARATION = new JSNamespaceDeclarationElementType(); + + JSStubElementType VAR_STATEMENT = new JSVarStatementElementType(); } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/JSTokenTypes.java b/base-impl/src/main/java/com/intellij/lang/javascript/JSTokenTypes.java index afe4b19a..c348cd60 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/JSTokenTypes.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/JSTokenTypes.java @@ -21,11 +21,11 @@ import consulo.annotation.DeprecationInfo; import consulo.annotation.access.RequiredReadAction; import consulo.javascript.lang.JavaScriptContextKeywordElementType; -import consulo.javascript.language.JavaScriptLanguage; import consulo.javascript.lang.parsing.JavaScriptParser; import consulo.javascript.lang.parsing.JavaScriptParsingContext; import consulo.javascript.lang.parsing.Parsing; -import consulo.javascript.language.JavaScriptBundle; +import consulo.javascript.language.JavaScriptLanguage; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.Language; import consulo.language.ast.*; import consulo.language.lexer.FlexAdapter; @@ -38,320 +38,433 @@ import consulo.language.version.LanguageVersion; import consulo.project.Project; import consulo.xml.psi.xml.XmlTokenType; +import jakarta.annotation.Nonnull; import org.jetbrains.annotations.NonNls; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; /** * @author max, maxim.mossienko */ -public interface JSTokenTypes -{ - IElementType IDENTIFIER = new JSElementType("IDENTIFIER"); - IElementType ANY_IDENTIFIER = new JSElementType("ANY_IDENTIFIER"); - IElementType ASTERISK = ANY_IDENTIFIER; - - IElementType WHITE_SPACE = TokenType.WHITE_SPACE; - IElementType BAD_CHARACTER = TokenType.BAD_CHARACTER; - - IElementType END_OF_LINE_COMMENT = new JSElementType("END_OF_LINE_COMMENT"); - IElementType C_STYLE_COMMENT = new JSElementType("C_STYLE_COMMENT"); - @Deprecated - @DeprecationInfo("old xml parsing, es4") - IElementType XML_STYLE_COMMENT = new JSElementType("XML_STYLE_COMMENT"); - @Deprecated - @DeprecationInfo("old xml parsing, es4") - IElementType XML_STYLE_COMMENT_START = new JSElementType("XML_STYLE_COMMENT_START"); - - IElementType DOC_COMMENT = new JSChameleonElementType("DOC_COMMENT") - { - @Override - protected void doParse(JavaScriptParsingContext context, PsiBuilder builder) - { - JSDocParsing.parseJSDoc(builder); - - } - - @Override - @Nullable - protected Lexer createLexer() - { - return new MergingLexerAdapter(new FlexAdapter(new _JSDocLexer(false)), JSDocTokenTypes.TOKENS_TO_MERGE); - } - }; - - // Keywords: - IElementType BREAK_KEYWORD = new JSElementType("BREAK_KEYWORD"); - IElementType CASE_KEYWORD = new JSElementType("CASE_KEYWORD"); - IElementType CATCH_KEYWORD = new JSElementType("CATCH_KEYWORD"); - IElementType CONST_KEYWORD = new JSElementType("CONST_KEYWORD"); - IElementType CONTINUE_KEYWORD = new JSElementType("CONTINUE_KEYWORD"); - IElementType DELETE_KEYWORD = new JSElementType("DELETE_KEYWORD"); - IElementType DEFAULT_KEYWORD = new JSElementType("DEFAULT_KEYWORD"); - IElementType DO_KEYWORD = new JSElementType("DO_KEYWORD"); - IElementType ELSE_KEYWORD = new JSElementType("ELSE_KEYWORD"); - IElementType FINALLY_KEYWORD = new JSElementType("FINALLY_KEYWORD"); - IElementType FOR_KEYWORD = new JSElementType("FOR_KEYWORD"); - IElementType FUNCTION_KEYWORD = new JSElementType("FUNCTION_KEYWORD"); - IElementType IF_KEYWORD = new JSElementType("IF_KEYWORD"); - IElementType IN_KEYWORD = new JSElementType("IN_KEYWORD"); - IElementType INSTANCEOF_KEYWORD = new JSElementType("INSTANCEOF_KEYWORD"); - IElementType NEW_KEYWORD = new JSElementType("NEW_KEYWORD"); - IElementType RETURN_KEYWORD = new JSElementType("RETURN_KEYWORD"); - IElementType SWITCH_KEYWORD = new JSElementType("SWITCH_KEYWORD"); - IElementType THIS_KEYWORD = new JSElementType("THIS_KEYWORD"); - IElementType THROW_KEYWORD = new JSElementType("THROW_KEYWORD"); - IElementType TRY_KEYWORD = new JSElementType("TRY_KEYWORD"); - IElementType TYPEOF_KEYWORD = new JSElementType("TYPEOF_KEYWORD"); - IElementType VAR_KEYWORD = new JSElementType("VAR_KEYWORD"); - IElementType VOID_KEYWORD = new JSElementType("VOID_KEYWORD"); - IElementType WHILE_KEYWORD = new JSElementType("WHILE_KEYWORD"); - IElementType WITH_KEYWORD = new JSElementType("WITH_KEYWORD"); - - IElementType PACKAGE_KEYWORD = new JSElementType("PACKAGE_KEYWORD"); // package - IElementType IMPORT_KEYWORD = new JSElementType("IMPORT_KEYWORD"); // import - IElementType CLASS_KEYWORD = new JSElementType("CLASS_KEYWORD"); // class - IElementType INTERFACE_KEYWORD = new JSElementType("INTERFACE_KEYWORD"); // interface - IElementType FROM_KEYWORD = new JavaScriptContextKeywordElementType("FROM_KEYWORD", "from"); - IElementType PUBLIC_KEYWORD = new JSElementType("PUBLIC_KEYWORD"); // public - IElementType STATIC_KEYWORD = new JavaScriptContextKeywordElementType("STATIC_KEYWORD", "static"); // static - IElementType INTERNAL_KEYWORD = new JSElementType("INTERNAL_KEYWORD"); // internal - IElementType FINAL_KEYWORD = new JSElementType("FINAL_KEYWORD"); // final - IElementType DYNAMIC_KEYWORD = new JSElementType("DYNAMIC_KEYWORD"); // dynamic - IElementType NATIVE_KEYWORD = new JSElementType("NATIVE_KEYWORD"); // native - IElementType VIRTUAL_KEYWORD = new JSElementType("VIRTUAL_KEYWORD"); // virtual - - IElementType EXPORT_KEYWORD = new JSElementType("EXPORT_KEYWORD"); // export - IElementType NAMESPACE_KEYWORD = new JSElementType("NAMESPACE_KEYWORD"); // namespace - IElementType EXTENDS_KEYWORD = new JSElementType("EXTENDS_KEYWORD"); // extends - IElementType IMPLEMENTS_KEYWORD = new JSElementType("IMPLEMENTS_KEYWORD"); // implements - IElementType ENUM_KEYWORD = new JSElementType("ENUM_KEYWORD"); // enum - IElementType USE_KEYWORD = new JSElementType("USE_KEYWORD"); // use - - IElementType PRIVATE_KEYWORD = new JSElementType("PRIVATE_KEYWORD"); // private - IElementType PROTECTED_KEYWORD = new JSElementType("PROTECTED_KEYWORD"); // protected - IElementType OVERRIDE_KEYWORD = new JSElementType("OVERRIDE_KEYWORD"); // override - IElementType SUPER_KEYWORD = new JSElementType("SUPER_KEYWORD"); // super - IElementType INCLUDE_KEYWORD = new JSElementType("INCLUDE_KEYWORD"); // include - IElementType IS_KEYWORD = new JSElementType("IS_KEYWORD"); // is - IElementType AS_KEYWORD = new JavaScriptContextKeywordElementType("AS_KEYWORD", "as"); // as - IElementType GET_KEYWORD = new JavaScriptContextKeywordElementType("GET_KEYWORD", "get"); // GET - IElementType SET_KEYWORD = new JavaScriptContextKeywordElementType("SET_KEYWORD", "set"); // SET - IElementType OF_KEYWORD = new JavaScriptContextKeywordElementType("OF_KEYWORD", "of"); // of - IElementType EACH_KEYWORD = new JSElementType("EACH_KEYWORD"); - IElementType INT_KEYWORD = new JSElementType("INT_KEYWORD"); - IElementType UINT_KEYWORD = new JSElementType("UINT_KEYWORD"); - IElementType AT = new JSElementType("AT"); - - IElementType XML_START_TAG_START = XmlTokenType.XML_START_TAG_START; - IElementType XML_START_TAG_LIST = new JSElementType("XML_TAG__LIST_START"); - IElementType XML_END_TAG_LIST = new JSElementType("XML_TAG__LIST_END"); - IElementType XML_END_TAG_START = XmlTokenType.XML_END_TAG_START; - IElementType XML_EMPTY_TAG_END = XmlTokenType.XML_EMPTY_ELEMENT_END; - IElementType XML_NAME = XmlTokenType.XML_NAME; - IElementType XML_TAG_NAME = XmlTokenType.XML_TAG_NAME; - IElementType XML_ATTR_EQUAL = XmlTokenType.XML_EQ; - IElementType XML_TAG_END = XmlTokenType.XML_TAG_END; - IElementType XML_ATTR_VALUE = XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN; - IElementType XML_ATTR_VALUE_START = XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER; - IElementType XML_ATTR_VALUE_END = XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER; - IElementType XML_JS_SCRIPT = new JSChameleonElementType("XML_JS_SCRIPT") - { - @Override - protected void doParse(JavaScriptParsingContext context, PsiBuilder builder) - { - parseScriptExpression(context, builder); - } - - public void parseScriptExpression(JavaScriptParsingContext context, final PsiBuilder builder) - { - PsiBuilder.Marker root = builder.mark(); - Parsing.checkMatches(builder, JSTokenTypes.LBRACE, JavaScriptBundle.message("javascript.parser.message.expected.lbrace")); - if(builder.getTokenType() != JSTokenTypes.RBRACE) - { - context.getExpressionParsing().parseExpression(builder); - } - Parsing.checkMatches(builder, JSTokenTypes.RBRACE, JavaScriptBundle.message("javascript.parser.message.expected.rbrace")); - - while(!builder.eof()) - { - builder.advanceLexer(); - } - - root.done(JSElementTypes.EMBEDDED_EXPRESSION); - } - }; - - IElementType XML_TAG_CONTENT = new JSElementType("XML_TAG_CONTENT"); - IElementType XML_ENTITY_REF = new JSElementType("XML_ENTITY_REF"); - IElementType XML_TAG_WHITE_SPACE = new JSElementType("XML_TAG_WHITESPACE"); - - TokenSet XML_TOKENS = TokenSet.create(XML_START_TAG_START, XML_START_TAG_LIST, XML_END_TAG_LIST, XML_END_TAG_START, XML_EMPTY_TAG_END, XML_NAME, XML_TAG_NAME, XML_ATTR_EQUAL, XML_ATTR_VALUE, - XML_ATTR_VALUE_START, XML_ATTR_VALUE_END, XML_TAG_END, XML_JS_SCRIPT, XML_TAG_CONTENT, XML_STYLE_COMMENT, XML_ENTITY_REF, XML_TAG_WHITE_SPACE); - - @Deprecated - // FIXME [VISTALL] what the heck? maybe old jsp inject support - IElementType JSP_TEXT = new JSElementType("JSP_TEXT"); - IElementType YIELD_KEYWORD = new JSElementType("YIELD_KEYWORD"); - IElementType LET_KEYWORD = new JSElementType("LET_KEYWORD"); - - // Hardcoded literals - IElementType TRUE_KEYWORD = new JSElementType("TRUE_KEYWORD"); - IElementType FALSE_KEYWORD = new JSElementType("FALSE_KEYWORD"); - IElementType NULL_KEYWORD = new JSElementType("NULL_KEYWORD"); - IElementType UNDEFINED_KEYWORD = new JSElementType("UNDEFINED_KEYWORD"); - - TokenSet JS_KEYWORDS = TokenSet.create(BREAK_KEYWORD, CASE_KEYWORD, CATCH_KEYWORD, CONST_KEYWORD, CONTINUE_KEYWORD, DELETE_KEYWORD, DEFAULT_KEYWORD, DO_KEYWORD, ELSE_KEYWORD, FINALLY_KEYWORD, - FOR_KEYWORD, FUNCTION_KEYWORD, IF_KEYWORD, IN_KEYWORD, INSTANCEOF_KEYWORD, NEW_KEYWORD, RETURN_KEYWORD, SWITCH_KEYWORD, THIS_KEYWORD, THROW_KEYWORD, TRY_KEYWORD, TYPEOF_KEYWORD, - VAR_KEYWORD, VOID_KEYWORD, WHILE_KEYWORD, WITH_KEYWORD, TRUE_KEYWORD, FALSE_KEYWORD, NULL_KEYWORD, UNDEFINED_KEYWORD, YIELD_KEYWORD, LET_KEYWORD); - - TokenSet JS2_KEYWORDS = TokenSet.create(INTERNAL_KEYWORD, DYNAMIC_KEYWORD, FINAL_KEYWORD, NATIVE_KEYWORD, VIRTUAL_KEYWORD, - CLASS_KEYWORD, EXTENDS_KEYWORD, IMPORT_KEYWORD, USE_KEYWORD, NAMESPACE_KEYWORD, OVERRIDE_KEYWORD, INCLUDE_KEYWORD, - SUPER_KEYWORD, IS_KEYWORD, AS_KEYWORD, GET_KEYWORD, SET_KEYWORD, EACH_KEYWORD, INT_KEYWORD, UINT_KEYWORD); - - TokenSet ECMASCRIPT6_KEYWORDS = TokenSet.create(EXPORT_KEYWORD, ENUM_KEYWORD, FROM_KEYWORD); - - TokenSet ECMASCRIPT6_STRICT_KEYWORDS = TokenSet.create(PUBLIC_KEYWORD, PRIVATE_KEYWORD, PROTECTED_KEYWORD, PACKAGE_KEYWORD, IMPLEMENTS_KEYWORD, INTERFACE_KEYWORD, STATIC_KEYWORD); - - TokenSet KEYWORDS = TokenSet.orSet(JS_KEYWORDS, JS2_KEYWORDS, ECMASCRIPT6_KEYWORDS); - - // Literals - IElementType NUMERIC_LITERAL = new JSElementType("NUMERIC_LITERAL"); - IElementType STRING_LITERAL = new JSElementType("STRING_LITERAL"); - IElementType SINGLE_QUOTE_STRING_LITERAL = new JSElementType("SINGLE_QUOTE_STRING_LITERAL"); - IElementType INTERPOLATION_STRING_LITERAL = new JSElementType("INTERPOLATION_STRING_LITERAL"); - IElementType REGEXP_LITERAL = new JSElementType("REGEXP_LITERAL"); - - // Punctuators - IElementType LBRACE = new JSElementType("LBRACE");// { - IElementType RBRACE = new JSElementType("RBRACE");// } - IElementType LPAR = new JSElementType("LPAR");// ( - IElementType RPAR = new JSElementType("RPAR");// ) - IElementType LBRACKET = new JSElementType("LBRACKET");// [ - IElementType RBRACKET = new JSElementType("RBRACKET");// ] - IElementType DOT = new JSElementType("DOT");// . - IElementType SEMICOLON = new JSElementType("SEMICOLON");// ; - IElementType COMMA = new JSElementType("COMMA");// , - - IElementType LT = new JSElementType("LT");// < - IElementType GT = new JSElementType("GT");// > - IElementType LE = new JSElementType("LE");// <= - IElementType GE = new JSElementType("GE");// >= - IElementType EQEQ = new JSElementType("EQEQ");// == - IElementType NE = new JSElementType("NE");// != - IElementType EQEQEQ = new JSElementType("EQEQEQ");// === - IElementType NEQEQ = new JSElementType("NEQEQ");// !== - IElementType PLUS = new JSElementType("PLUS");// + - IElementType MINUS = new JSElementType("MINUS");// - - IElementType MULT = new JSElementType("MULT");// * - IElementType MULTMULT = new JSElementType("MULTMULT");// * - IElementType PERC = new JSElementType("PERC");// % - IElementType PLUSPLUS = new JSElementType("PLUSPLUS");// ++ - IElementType MINUSMINUS = new JSElementType("MINUSMINUS");// -- - IElementType LTLT = new JSElementType("LTLT");// << - IElementType GTGT = new JSElementType("GTGT");// >> - IElementType GTGTGT = new JSElementType("GTGTGT");// >>> - IElementType AND = new JSElementType("AND");// & - IElementType OR = new JSElementType("OR");// | - IElementType XOR = new JSElementType("XOR");// ^ - IElementType EXCL = new JSElementType("EXCL");// ! - IElementType TILDE = new JSElementType("TILDE");// ~ - IElementType ANDAND = new JSElementType("ANDAND");// && - IElementType OROR = new JSElementType("OROR");// || - IElementType QUEST = new JSElementType("QUEST");// ? - IElementType QUEST_DOT = new JSElementType("QUEST_DOT");// ? - IElementType COLON = new JSElementType("COLON");// : - IElementType EQ = new JSElementType("EQ");// = - IElementType PLUSEQ = new JSElementType("PLUSEQ");// += - IElementType MINUSEQ = new JSElementType("MINUSEQ");// -= - IElementType MULTEQ = new JSElementType("MULTEQ");// *= - IElementType MULT_MULT_EQ = new JSElementType("MULT_MULT_EQ");// **= - IElementType PERCEQ = new JSElementType("PERCEQ");// %= - IElementType LTLTEQ = new JSElementType("LTLTEQ");// <<= - IElementType GTGTEQ = new JSElementType("GTGTEQ");// >>= - IElementType GTGTGTEQ = new JSElementType("GTGTGTEQ");// >>>= - IElementType ANDEQ = new JSElementType("ANDEQ");// &= - IElementType OREQ = new JSElementType("OREQ");// |= - IElementType XOREQ = new JSElementType("XOREQ");// ^= - IElementType DIV = new JSElementType("DIV"); // / - IElementType DIVEQ = new JSElementType("DIVEQ"); // /= - IElementType OR_OR_EQ = new JSElementType("OR_OR_EQ"); // ||= - IElementType AND_AND_EQ = new JSElementType("AND_AND_EQ"); // &&= - IElementType QUEST_QUEST_EQ = new JSElementType("QUEST_QUEST_EQ"); // ??= - IElementType DARROW = new JSElementType("DARROW"); // => - - IElementType COLON_COLON = new JSElementType("COLON_COLON"); // :: - IElementType GWT_FIELD_OR_METHOD = new JSElementType("GWT_FIELD_OR_METHOD"); // :: - - IElementType DOT_DOT = new JSElementType("DOT_DOT"); // .. - IElementType DOT_DOT_DOT = new JSElementType("DOT_DOT_DOT"); // ... - - IElementType CDATA_START = new JSElementType("CDATA_START"); // - IElementType JSDOC_TAG_DATA = new JSElementType("JSDOC_TAG_DATA"); - - TokenSet OPERATIONS = TokenSet.create(LT, GT, LE, GE, EQEQ, NE, EQEQEQ, NEQEQ, PLUS, MINUS, MULT, PERC, PLUSPLUS, MINUSMINUS, LTLT, GTGT, GTGTGT, AND, OR, XOR, EXCL, TILDE, ANDAND, OROR, QUEST, - COLON, EQ, PLUSEQ, MINUSEQ, MULTEQ, PERCEQ, LTLTEQ, GTGTEQ, GTGTGTEQ, ANDEQ, OREQ, XOREQ, DIV, DIVEQ, MULTMULT, COMMA, IS_KEYWORD, AS_KEYWORD, OR_OR_EQ, AND_AND_EQ, QUEST_QUEST_EQ, - MULT_MULT_EQ); - - TokenSet ASSOC_OPERATIONS = TokenSet.create(PLUS, MULT, AND, OR, XOR, OROR, ANDAND); - - TokenSet ASSIGNMENT_OPERATIONS = TokenSet.create(EQ, PLUSEQ, MINUSEQ, MULTEQ, PERCEQ, LTLTEQ, GTGTEQ, GTGTGTEQ, ANDEQ, OREQ, XOREQ, DIVEQ, OR_OR_EQ, AND_AND_EQ, QUEST_QUEST_EQ, MULT_MULT_EQ); - - TokenSet EQUALITY_OPERATIONS = TokenSet.create(EQEQ, NE, EQEQEQ, NEQEQ); - - TokenSet RELATIONAL_OPERATIONS = TokenSet.create(LT, GT, LE, GE, INSTANCEOF_KEYWORD, IN_KEYWORD); - - TokenSet ADDITIVE_OPERATIONS = TokenSet.create(PLUS, MINUS); - - TokenSet MULTIPLICATIVE_OPERATIONS = TokenSet.create(MULT, DIV, PERC, MULTMULT); - - TokenSet SHIFT_OPERATIONS = TokenSet.create(LTLT, GTGT, GTGTGT); - - TokenSet UNARY_OPERATIONS = TokenSet.create(PLUS, MINUS, PLUSPLUS, MINUSMINUS, TILDE, EXCL, TYPEOF_KEYWORD, VOID_KEYWORD, DELETE_KEYWORD); - - TokenSet COMMENTS = TokenSet.create(END_OF_LINE_COMMENT, DOC_COMMENT, C_STYLE_COMMENT, XML_STYLE_COMMENT, CDATA_START, CDATA_END, XML_STYLE_COMMENT_START, - JavaScriptHighlightingLexer.getTagContentTokenType(), XML_TAG_WHITE_SPACE, JSP_TEXT, JSDOC_TAG_DATA); - - TokenSet MODIFIERS = TokenSet.create(PUBLIC_KEYWORD, STATIC_KEYWORD, OVERRIDE_KEYWORD, PROTECTED_KEYWORD, PRIVATE_KEYWORD, INTERNAL_KEYWORD, DYNAMIC_KEYWORD, FINAL_KEYWORD, NATIVE_KEYWORD, - VIRTUAL_KEYWORD, EXPORT_KEYWORD); - - TokenSet ACCESS_MODIFIERS = TokenSet.create(PUBLIC_KEYWORD, PROTECTED_KEYWORD, PRIVATE_KEYWORD, INTERNAL_KEYWORD); - - TokenSet GET_SET_TOKEN_SET = TokenSet.create(GET_KEYWORD, SET_KEYWORD); - - @Deprecated - TokenSet IDENTIFIER_TOKENS_SET = TokenSet.create(IDENTIFIER); - - abstract class JSChameleonElementType extends ILazyParseableElementType - { - public JSChameleonElementType(@NonNls String name) - { - super(name, JavaScriptLanguage.INSTANCE); - } - - protected abstract void doParse(JavaScriptParsingContext context, PsiBuilder builder); - - @Override - @RequiredReadAction - protected ASTNode doParseContents(@Nonnull ASTNode chameleon, @Nonnull PsiElement psi) - { - final Project project = psi.getProject(); - final Language languageForParser = getLanguageForParser(psi); - final LanguageVersion tempLanguageVersion = chameleon.getUserData(LanguageVersion.KEY); - final LanguageVersion languageVersion = tempLanguageVersion == null ? psi.getLanguageVersion() : tempLanguageVersion; - final PsiBuilder builder = PsiBuilderFactory.getInstance().createBuilder(project, chameleon, createLexer(), languageForParser, languageVersion, chameleon.getChars()); - final JavaScriptParser parser = (JavaScriptParser) ParserDefinition.forLanguage(languageForParser).createParser(languageVersion); - - JavaScriptParsingContext parsingContext = parser.createParsingContext(); - doParse(parsingContext, builder); - return builder.getTreeBuilt(); - } - - protected Lexer createLexer() - { - return null; - } - } +public interface JSTokenTypes { + IElementType IDENTIFIER = new JSElementType("IDENTIFIER"); + IElementType ANY_IDENTIFIER = new JSElementType("ANY_IDENTIFIER"); + IElementType ASTERISK = ANY_IDENTIFIER; + + IElementType WHITE_SPACE = TokenType.WHITE_SPACE; + IElementType BAD_CHARACTER = TokenType.BAD_CHARACTER; + + IElementType END_OF_LINE_COMMENT = new JSElementType("END_OF_LINE_COMMENT"); + IElementType C_STYLE_COMMENT = new JSElementType("C_STYLE_COMMENT"); + @Deprecated + @DeprecationInfo("old xml parsing, es4") + IElementType XML_STYLE_COMMENT = new JSElementType("XML_STYLE_COMMENT"); + @Deprecated + @DeprecationInfo("old xml parsing, es4") + IElementType XML_STYLE_COMMENT_START = new JSElementType("XML_STYLE_COMMENT_START"); + + IElementType DOC_COMMENT = new JSChameleonElementType("DOC_COMMENT") { + @Override + protected void doParse(JavaScriptParsingContext context, PsiBuilder builder) { + JSDocParsing.parseJSDoc(builder); + } + + @Override + @Nullable + protected Lexer createLexer() { + return new MergingLexerAdapter(new FlexAdapter(new _JSDocLexer(false)), JSDocTokenTypes.TOKENS_TO_MERGE); + } + }; + + // Keywords: + IElementType BREAK_KEYWORD = new JSElementType("BREAK_KEYWORD"); + IElementType CASE_KEYWORD = new JSElementType("CASE_KEYWORD"); + IElementType CATCH_KEYWORD = new JSElementType("CATCH_KEYWORD"); + IElementType CONST_KEYWORD = new JSElementType("CONST_KEYWORD"); + IElementType CONTINUE_KEYWORD = new JSElementType("CONTINUE_KEYWORD"); + IElementType DELETE_KEYWORD = new JSElementType("DELETE_KEYWORD"); + IElementType DEFAULT_KEYWORD = new JSElementType("DEFAULT_KEYWORD"); + IElementType DO_KEYWORD = new JSElementType("DO_KEYWORD"); + IElementType ELSE_KEYWORD = new JSElementType("ELSE_KEYWORD"); + IElementType FINALLY_KEYWORD = new JSElementType("FINALLY_KEYWORD"); + IElementType FOR_KEYWORD = new JSElementType("FOR_KEYWORD"); + IElementType FUNCTION_KEYWORD = new JSElementType("FUNCTION_KEYWORD"); + IElementType IF_KEYWORD = new JSElementType("IF_KEYWORD"); + IElementType IN_KEYWORD = new JSElementType("IN_KEYWORD"); + IElementType INSTANCEOF_KEYWORD = new JSElementType("INSTANCEOF_KEYWORD"); + IElementType NEW_KEYWORD = new JSElementType("NEW_KEYWORD"); + IElementType RETURN_KEYWORD = new JSElementType("RETURN_KEYWORD"); + IElementType SWITCH_KEYWORD = new JSElementType("SWITCH_KEYWORD"); + IElementType THIS_KEYWORD = new JSElementType("THIS_KEYWORD"); + IElementType THROW_KEYWORD = new JSElementType("THROW_KEYWORD"); + IElementType TRY_KEYWORD = new JSElementType("TRY_KEYWORD"); + IElementType TYPEOF_KEYWORD = new JSElementType("TYPEOF_KEYWORD"); + IElementType VAR_KEYWORD = new JSElementType("VAR_KEYWORD"); + IElementType VOID_KEYWORD = new JSElementType("VOID_KEYWORD"); + IElementType WHILE_KEYWORD = new JSElementType("WHILE_KEYWORD"); + IElementType WITH_KEYWORD = new JSElementType("WITH_KEYWORD"); + + IElementType PACKAGE_KEYWORD = new JSElementType("PACKAGE_KEYWORD"); // package + IElementType IMPORT_KEYWORD = new JSElementType("IMPORT_KEYWORD"); // import + IElementType CLASS_KEYWORD = new JSElementType("CLASS_KEYWORD"); // class + IElementType INTERFACE_KEYWORD = new JSElementType("INTERFACE_KEYWORD"); // interface + IElementType FROM_KEYWORD = new JavaScriptContextKeywordElementType("FROM_KEYWORD", "from"); + IElementType PUBLIC_KEYWORD = new JSElementType("PUBLIC_KEYWORD"); // public + IElementType STATIC_KEYWORD = new JavaScriptContextKeywordElementType("STATIC_KEYWORD", "static"); // static + IElementType INTERNAL_KEYWORD = new JSElementType("INTERNAL_KEYWORD"); // internal + IElementType FINAL_KEYWORD = new JSElementType("FINAL_KEYWORD"); // final + IElementType DYNAMIC_KEYWORD = new JSElementType("DYNAMIC_KEYWORD"); // dynamic + IElementType NATIVE_KEYWORD = new JSElementType("NATIVE_KEYWORD"); // native + IElementType VIRTUAL_KEYWORD = new JSElementType("VIRTUAL_KEYWORD"); // virtual + + IElementType EXPORT_KEYWORD = new JSElementType("EXPORT_KEYWORD"); // export + IElementType NAMESPACE_KEYWORD = new JSElementType("NAMESPACE_KEYWORD"); // namespace + IElementType EXTENDS_KEYWORD = new JSElementType("EXTENDS_KEYWORD"); // extends + IElementType IMPLEMENTS_KEYWORD = new JSElementType("IMPLEMENTS_KEYWORD"); // implements + IElementType ENUM_KEYWORD = new JSElementType("ENUM_KEYWORD"); // enum + IElementType USE_KEYWORD = new JSElementType("USE_KEYWORD"); // use + + IElementType PRIVATE_KEYWORD = new JSElementType("PRIVATE_KEYWORD"); // private + IElementType PROTECTED_KEYWORD = new JSElementType("PROTECTED_KEYWORD"); // protected + IElementType OVERRIDE_KEYWORD = new JSElementType("OVERRIDE_KEYWORD"); // override + IElementType SUPER_KEYWORD = new JSElementType("SUPER_KEYWORD"); // super + IElementType INCLUDE_KEYWORD = new JSElementType("INCLUDE_KEYWORD"); // include + IElementType IS_KEYWORD = new JSElementType("IS_KEYWORD"); // is + IElementType AS_KEYWORD = new JavaScriptContextKeywordElementType("AS_KEYWORD", "as"); // as + IElementType GET_KEYWORD = new JavaScriptContextKeywordElementType("GET_KEYWORD", "get"); // GET + IElementType SET_KEYWORD = new JavaScriptContextKeywordElementType("SET_KEYWORD", "set"); // SET + IElementType OF_KEYWORD = new JavaScriptContextKeywordElementType("OF_KEYWORD", "of"); // of + IElementType EACH_KEYWORD = new JSElementType("EACH_KEYWORD"); + IElementType INT_KEYWORD = new JSElementType("INT_KEYWORD"); + IElementType UINT_KEYWORD = new JSElementType("UINT_KEYWORD"); + IElementType AT = new JSElementType("AT"); + + IElementType XML_START_TAG_START = XmlTokenType.XML_START_TAG_START; + IElementType XML_START_TAG_LIST = new JSElementType("XML_TAG__LIST_START"); + IElementType XML_END_TAG_LIST = new JSElementType("XML_TAG__LIST_END"); + IElementType XML_END_TAG_START = XmlTokenType.XML_END_TAG_START; + IElementType XML_EMPTY_TAG_END = XmlTokenType.XML_EMPTY_ELEMENT_END; + IElementType XML_NAME = XmlTokenType.XML_NAME; + IElementType XML_TAG_NAME = XmlTokenType.XML_TAG_NAME; + IElementType XML_ATTR_EQUAL = XmlTokenType.XML_EQ; + IElementType XML_TAG_END = XmlTokenType.XML_TAG_END; + IElementType XML_ATTR_VALUE = XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN; + IElementType XML_ATTR_VALUE_START = XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER; + IElementType XML_ATTR_VALUE_END = XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER; + IElementType XML_JS_SCRIPT = new JSChameleonElementType("XML_JS_SCRIPT") { + @Override + protected void doParse(JavaScriptParsingContext context, PsiBuilder builder) { + parseScriptExpression(context, builder); + } + + public void parseScriptExpression(JavaScriptParsingContext context, PsiBuilder builder) { + PsiBuilder.Marker root = builder.mark(); + Parsing.checkMatches(builder, JSTokenTypes.LBRACE, JavaScriptLocalize.javascriptParserMessageExpectedLbrace()); + if (builder.getTokenType() != JSTokenTypes.RBRACE) { + context.getExpressionParsing().parseExpression(builder); + } + Parsing.checkMatches(builder, JSTokenTypes.RBRACE, JavaScriptLocalize.javascriptParserMessageExpectedRbrace()); + + while (!builder.eof()) { + builder.advanceLexer(); + } + + root.done(JSElementTypes.EMBEDDED_EXPRESSION); + } + }; + + IElementType XML_TAG_CONTENT = new JSElementType("XML_TAG_CONTENT"); + IElementType XML_ENTITY_REF = new JSElementType("XML_ENTITY_REF"); + IElementType XML_TAG_WHITE_SPACE = new JSElementType("XML_TAG_WHITESPACE"); + + TokenSet XML_TOKENS = TokenSet.create( + XML_ATTR_EQUAL, + XML_ATTR_VALUE, + XML_ATTR_VALUE_END, + XML_ATTR_VALUE_START, + XML_EMPTY_TAG_END, + XML_END_TAG_LIST, + XML_END_TAG_START, + XML_ENTITY_REF, + XML_JS_SCRIPT, + XML_NAME, + XML_START_TAG_LIST, + XML_START_TAG_START, + XML_STYLE_COMMENT, + XML_TAG_CONTENT, + XML_TAG_END, + XML_TAG_NAME, + XML_TAG_WHITE_SPACE + ); + + @Deprecated + // FIXME [VISTALL] what the heck? maybe old jsp inject support + IElementType JSP_TEXT = new JSElementType("JSP_TEXT"); + IElementType YIELD_KEYWORD = new JSElementType("YIELD_KEYWORD"); + IElementType LET_KEYWORD = new JSElementType("LET_KEYWORD"); + + // Hardcoded literals + IElementType TRUE_KEYWORD = new JSElementType("TRUE_KEYWORD"); + IElementType FALSE_KEYWORD = new JSElementType("FALSE_KEYWORD"); + IElementType NULL_KEYWORD = new JSElementType("NULL_KEYWORD"); + IElementType UNDEFINED_KEYWORD = new JSElementType("UNDEFINED_KEYWORD"); + + TokenSet JS_KEYWORDS = TokenSet.create( + BREAK_KEYWORD, + CASE_KEYWORD, + CATCH_KEYWORD, + CONST_KEYWORD, + CONTINUE_KEYWORD, + DELETE_KEYWORD, + DEFAULT_KEYWORD, + DO_KEYWORD, + ELSE_KEYWORD, + FALSE_KEYWORD, + FINALLY_KEYWORD, + FOR_KEYWORD, + FUNCTION_KEYWORD, + IF_KEYWORD, + IN_KEYWORD, + INSTANCEOF_KEYWORD, + LET_KEYWORD, + NEW_KEYWORD, + NULL_KEYWORD, + RETURN_KEYWORD, + SWITCH_KEYWORD, + THIS_KEYWORD, + THROW_KEYWORD, + TRUE_KEYWORD, + TRY_KEYWORD, + TYPEOF_KEYWORD, + UNDEFINED_KEYWORD, + VAR_KEYWORD, + VOID_KEYWORD, + WHILE_KEYWORD, + WITH_KEYWORD, + YIELD_KEYWORD + ); + + TokenSet JS2_KEYWORDS = TokenSet.create( + AS_KEYWORD, + CLASS_KEYWORD, + DYNAMIC_KEYWORD, + EACH_KEYWORD, + EXTENDS_KEYWORD, + FINAL_KEYWORD, + GET_KEYWORD, + INTERNAL_KEYWORD, + NATIVE_KEYWORD, + IMPORT_KEYWORD, + INT_KEYWORD, + IS_KEYWORD, + USE_KEYWORD, + NAMESPACE_KEYWORD, + OVERRIDE_KEYWORD, + INCLUDE_KEYWORD, + SET_KEYWORD, + SUPER_KEYWORD, + UINT_KEYWORD, + VIRTUAL_KEYWORD + ); + + TokenSet ECMASCRIPT6_KEYWORDS = TokenSet.create(EXPORT_KEYWORD, ENUM_KEYWORD, FROM_KEYWORD); + + TokenSet ECMASCRIPT6_STRICT_KEYWORDS = TokenSet.create( + IMPLEMENTS_KEYWORD, + INTERFACE_KEYWORD, + PACKAGE_KEYWORD, + PRIVATE_KEYWORD, + PROTECTED_KEYWORD, + PUBLIC_KEYWORD, + STATIC_KEYWORD + ); + + TokenSet KEYWORDS = TokenSet.orSet(JS_KEYWORDS, JS2_KEYWORDS, ECMASCRIPT6_KEYWORDS); + + // Literals + IElementType NUMERIC_LITERAL = new JSElementType("NUMERIC_LITERAL"); + IElementType STRING_LITERAL = new JSElementType("STRING_LITERAL"); + IElementType SINGLE_QUOTE_STRING_LITERAL = new JSElementType("SINGLE_QUOTE_STRING_LITERAL"); + IElementType INTERPOLATION_STRING_LITERAL = new JSElementType("INTERPOLATION_STRING_LITERAL"); + IElementType REGEXP_LITERAL = new JSElementType("REGEXP_LITERAL"); + + // Punctuators + IElementType LBRACE = new JSElementType("LBRACE");// { + IElementType RBRACE = new JSElementType("RBRACE");// } + IElementType LPAR = new JSElementType("LPAR");// ( + IElementType RPAR = new JSElementType("RPAR");// ) + IElementType LBRACKET = new JSElementType("LBRACKET");// [ + IElementType RBRACKET = new JSElementType("RBRACKET");// ] + IElementType DOT = new JSElementType("DOT");// . + IElementType SEMICOLON = new JSElementType("SEMICOLON");// ; + IElementType COMMA = new JSElementType("COMMA");// , + + IElementType LT = new JSElementType("LT");// < + IElementType GT = new JSElementType("GT");// > + IElementType LE = new JSElementType("LE");// <= + IElementType GE = new JSElementType("GE");// >= + IElementType EQEQ = new JSElementType("EQEQ");// == + IElementType NE = new JSElementType("NE");// != + IElementType EQEQEQ = new JSElementType("EQEQEQ");// === + IElementType NEQEQ = new JSElementType("NEQEQ");// !== + IElementType PLUS = new JSElementType("PLUS");// + + IElementType MINUS = new JSElementType("MINUS");// - + IElementType MULT = new JSElementType("MULT");// * + IElementType MULTMULT = new JSElementType("MULTMULT");// * + IElementType PERC = new JSElementType("PERC");// % + IElementType PLUSPLUS = new JSElementType("PLUSPLUS");// ++ + IElementType MINUSMINUS = new JSElementType("MINUSMINUS");// -- + IElementType LTLT = new JSElementType("LTLT");// << + IElementType GTGT = new JSElementType("GTGT");// >> + IElementType GTGTGT = new JSElementType("GTGTGT");// >>> + IElementType AND = new JSElementType("AND");// & + IElementType OR = new JSElementType("OR");// | + IElementType XOR = new JSElementType("XOR");// ^ + IElementType EXCL = new JSElementType("EXCL");// ! + IElementType TILDE = new JSElementType("TILDE");// ~ + IElementType ANDAND = new JSElementType("ANDAND");// && + IElementType OROR = new JSElementType("OROR");// || + IElementType QUEST = new JSElementType("QUEST");// ? + IElementType QUEST_DOT = new JSElementType("QUEST_DOT");// ? + IElementType COLON = new JSElementType("COLON");// : + IElementType EQ = new JSElementType("EQ");// = + IElementType PLUSEQ = new JSElementType("PLUSEQ");// += + IElementType MINUSEQ = new JSElementType("MINUSEQ");// -= + IElementType MULTEQ = new JSElementType("MULTEQ");// *= + IElementType MULT_MULT_EQ = new JSElementType("MULT_MULT_EQ");// **= + IElementType PERCEQ = new JSElementType("PERCEQ");// %= + IElementType LTLTEQ = new JSElementType("LTLTEQ");// <<= + IElementType GTGTEQ = new JSElementType("GTGTEQ");// >>= + IElementType GTGTGTEQ = new JSElementType("GTGTGTEQ");// >>>= + IElementType ANDEQ = new JSElementType("ANDEQ");// &= + IElementType OREQ = new JSElementType("OREQ");// |= + IElementType XOREQ = new JSElementType("XOREQ");// ^= + IElementType DIV = new JSElementType("DIV"); // / + IElementType DIVEQ = new JSElementType("DIVEQ"); // /= + IElementType OR_OR_EQ = new JSElementType("OR_OR_EQ"); // ||= + IElementType AND_AND_EQ = new JSElementType("AND_AND_EQ"); // &&= + IElementType QUEST_QUEST_EQ = new JSElementType("QUEST_QUEST_EQ"); // ??= + IElementType DARROW = new JSElementType("DARROW"); // => + + IElementType COLON_COLON = new JSElementType("COLON_COLON"); // :: + IElementType GWT_FIELD_OR_METHOD = new JSElementType("GWT_FIELD_OR_METHOD"); // :: + + IElementType DOT_DOT = new JSElementType("DOT_DOT"); // .. + IElementType DOT_DOT_DOT = new JSElementType("DOT_DOT_DOT"); // ... + + IElementType CDATA_START = new JSElementType("CDATA_START"); // + IElementType JSDOC_TAG_DATA = new JSElementType("JSDOC_TAG_DATA"); + + TokenSet OPERATIONS = TokenSet.create( + LT, GT, LE, GE, + EQEQ, NE, EQEQEQ, NEQEQ, + PLUS, MINUS, MULT, PERC, + PLUSPLUS, MINUSMINUS, LTLT, + GTGT, GTGTGT, AND, OR, XOR, + EXCL, TILDE, ANDAND, OROR, + QUEST, COLON, EQ, PLUSEQ, + MINUSEQ, MULTEQ, PERCEQ, LTLTEQ, + GTGTEQ, GTGTGTEQ, ANDEQ, OREQ, + XOREQ, DIV, DIVEQ, MULTMULT, + COMMA, IS_KEYWORD, AS_KEYWORD, + OR_OR_EQ, AND_AND_EQ, QUEST_QUEST_EQ, MULT_MULT_EQ + ); + + TokenSet ASSOC_OPERATIONS = TokenSet.create(PLUS, MULT, AND, OR, XOR, OROR, ANDAND); + + TokenSet ASSIGNMENT_OPERATIONS = TokenSet.create( + EQ, + PLUSEQ, + MINUSEQ, + MULTEQ, + PERCEQ, + LTLTEQ, + GTGTEQ, + GTGTGTEQ, + ANDEQ, + OREQ, + XOREQ, + DIVEQ, + OR_OR_EQ, + AND_AND_EQ, + QUEST_QUEST_EQ, + MULT_MULT_EQ + ); + + TokenSet EQUALITY_OPERATIONS = TokenSet.create(EQEQ, NE, EQEQEQ, NEQEQ); + + TokenSet RELATIONAL_OPERATIONS = TokenSet.create(LT, GT, LE, GE, INSTANCEOF_KEYWORD, IN_KEYWORD); + + TokenSet ADDITIVE_OPERATIONS = TokenSet.create(PLUS, MINUS); + + TokenSet MULTIPLICATIVE_OPERATIONS = TokenSet.create(MULT, DIV, PERC, MULTMULT); + + TokenSet SHIFT_OPERATIONS = TokenSet.create(LTLT, GTGT, GTGTGT); + + TokenSet UNARY_OPERATIONS = + TokenSet.create(PLUS, MINUS, PLUSPLUS, MINUSMINUS, TILDE, EXCL, TYPEOF_KEYWORD, VOID_KEYWORD, DELETE_KEYWORD); + + TokenSet COMMENTS = TokenSet.create( + C_STYLE_COMMENT, + CDATA_START, + CDATA_END, + DOC_COMMENT, + END_OF_LINE_COMMENT, + JavaScriptHighlightingLexer.getTagContentTokenType(), + JSDOC_TAG_DATA, + JSP_TEXT, + XML_STYLE_COMMENT, + XML_STYLE_COMMENT_START, + XML_TAG_WHITE_SPACE + ); + + TokenSet MODIFIERS = TokenSet.create( + DYNAMIC_KEYWORD, + EXPORT_KEYWORD, + FINAL_KEYWORD, + INTERNAL_KEYWORD, + NATIVE_KEYWORD, + OVERRIDE_KEYWORD, + PROTECTED_KEYWORD, + PRIVATE_KEYWORD, + PUBLIC_KEYWORD, + STATIC_KEYWORD, + VIRTUAL_KEYWORD + ); + + TokenSet ACCESS_MODIFIERS = TokenSet.create(PUBLIC_KEYWORD, PROTECTED_KEYWORD, PRIVATE_KEYWORD, INTERNAL_KEYWORD); + + TokenSet GET_SET_TOKEN_SET = TokenSet.create(GET_KEYWORD, SET_KEYWORD); + + @Deprecated + TokenSet IDENTIFIER_TOKENS_SET = TokenSet.create(IDENTIFIER); + + abstract class JSChameleonElementType extends ILazyParseableElementType { + public JSChameleonElementType(@NonNls String name) { + super(name, JavaScriptLanguage.INSTANCE); + } + + protected abstract void doParse(JavaScriptParsingContext context, PsiBuilder builder); + + @Override + @RequiredReadAction + protected ASTNode doParseContents(@Nonnull ASTNode chameleon, @Nonnull PsiElement psi) { + Project project = psi.getProject(); + Language languageForParser = getLanguageForParser(psi); + LanguageVersion tempLanguageVersion = chameleon.getUserData(LanguageVersion.KEY); + LanguageVersion languageVersion = tempLanguageVersion == null ? psi.getLanguageVersion() : tempLanguageVersion; + PsiBuilder builder = PsiBuilderFactory.getInstance() + .createBuilder(project, chameleon, createLexer(), languageForParser, languageVersion, chameleon.getChars()); + JavaScriptParser parser = (JavaScriptParser)ParserDefinition.forLanguage(languageForParser).createParser(languageVersion); + + JavaScriptParsingContext parsingContext = parser.createParsingContext(); + doParse(parsingContext, builder); + return builder.getTreeBuilt(); + } + + protected Lexer createLexer() { + return null; + } + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/JavaScript.flex b/base-impl/src/main/java/com/intellij/lang/javascript/JavaScript.flex index a2725d27..5c81669b 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/JavaScript.flex +++ b/base-impl/src/main/java/com/intellij/lang/javascript/JavaScript.flex @@ -62,7 +62,7 @@ DOUBLE_QUOTED_LITERAL=\"([^\\\"\r\n]|{ESCAPE_SEQUENCE}|\\{CRLF})*(\"|\\)? ESCAPE_SEQUENCE=\\[^\r\n] GROUP = "[" [^\]]* "]" -REGEXP_LITERAL="/"([^\*\\/\r\n]|{ESCAPE_SEQUENCE}|{GROUP})([^\\/\r\n]|{ESCAPE_SEQUENCE}|{GROUP})*("/"[gimx\u]*)? +REGEXP_LITERAL="/"([^\*\\/\r\n]|{ESCAPE_SEQUENCE}|{GROUP})([^\\/\r\n]|{ESCAPE_SEQUENCE}|{GROUP})*("/"[dgimsuvy]*)? ALPHA=[:letter:] DIGIT=[0-9] XML_NAME=({ALPHA}|"_")({ALPHA}|{DIGIT}|"_"|"."|"-")*(":"({ALPHA}|"_")?({ALPHA}|{DIGIT}|"_"|"."|"-")*)? @@ -412,4 +412,4 @@ FIELD_OR_METHOD={IDENTIFIER} ("(" [^ \\)]* ")"? )? "]]>" { yybegin(YYINITIAL); return JSTokenTypes.CDATA_END; } " -{ - @Nullable - @Override - public String getExternalIdPrefix() - { - return "js."; - } +public class JavaScriptStubElementHolder extends StubElementTypeHolder { + @Nullable + @Override + public String getExternalIdPrefix() { + return "js."; + } - @Nonnull - @Override - public List loadSerializers() - { - return allFromStaticFields(JSStubElementTypes.class, Field::get); - } + @Nonnull + @Override + public List loadSerializers() { + return allFromStaticFields(JSStubElementTypes.class, Field::get); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/JavaScriptSupportLoader.java b/base-impl/src/main/java/com/intellij/lang/javascript/JavaScriptSupportLoader.java index 1a63ce68..9cac359d 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/JavaScriptSupportLoader.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/JavaScriptSupportLoader.java @@ -31,99 +31,78 @@ * @by max, maxim.mossienko */ @Deprecated -public class JavaScriptSupportLoader -{ - @Deprecated - public static final Language ECMA_SCRIPT_L4 = new Language("ECMA4_DEPRECATED") {}; +public class JavaScriptSupportLoader { + @Deprecated + public static final Language ECMA_SCRIPT_L4 = new Language("ECMA4_DEPRECATED") { + }; + @NonNls + public static final String MXML_FILE_EXTENSION_DOT = ".mxml"; + @NonNls + public static final String MXML_FILE_EXTENSION2_DOT = ".mxm"; + @NonNls + public static final String MXML_URI = "http://www.adobe.com/2006/mxml"; + @NonNls + public static final String MXML_URI2 = "http://www.macromedia.com/2003/mxml"; + @NonNls + public static final String MXML_URI3 = "http://ns.adobe.com/mxml/2009"; + @NonNls + public static final String MXML_URI4 = "library://ns.adobe.com/flex/spark"; + @NonNls + public static final String MXML_URI5 = "library://ns.adobe.com/flex/halo"; + @NonNls + public static final String MXML_URI6 = "http://ns.adobe.com/fxg/2008"; + @NonNls + public static final String[] MXML_URIS = { + MXML_URI, + MXML_URI2, + MXML_URI3, + MXML_URI4, + MXML_URI5, + MXML_URI6 + }; + @NonNls + public static final String BINDOWS_URI = "http://www.bindows.net"; + @NonNls + public static final String ACTION_SCRIPT_CLASS_TEMPLATE_NAME = "ActionScript Class"; + @NonNls + public static final String ACTION_SCRIPT_INTERFACE_TEMPLATE_NAME = "ActionScript Interface"; + @NonNls + public static final String MXML_COMPONENT_TEMPLATE_NAME = "Mxml Component"; - public static final - @NonNls - String MXML_FILE_EXTENSION_DOT = ".mxml"; - public static final - @NonNls - String MXML_FILE_EXTENSION2_DOT = ".mxm"; - public static final - @NonNls - String MXML_URI = "http://www.adobe.com/2006/mxml"; - public static final - @NonNls - String MXML_URI2 = "http://www.macromedia.com/2003/mxml"; - public static final - @NonNls - String MXML_URI3 = "http://ns.adobe.com/mxml/2009"; - public static final - @NonNls - String MXML_URI4 = "library://ns.adobe.com/flex/spark"; - public static final - @NonNls - String MXML_URI5 = "library://ns.adobe.com/flex/halo"; - public static final - @NonNls - String MXML_URI6 = "http://ns.adobe.com/fxg/2008"; - public static final - @NonNls - String[] MXML_URIS = { - MXML_URI, - MXML_URI2, - MXML_URI3, - MXML_URI4, - MXML_URI5, - MXML_URI6 - }; - public static final - @NonNls - String BINDOWS_URI = "http://www.bindows.net"; - @NonNls - public static final String ACTION_SCRIPT_CLASS_TEMPLATE_NAME = "ActionScript Class"; - @NonNls - public static final String ACTION_SCRIPT_INTERFACE_TEMPLATE_NAME = "ActionScript Interface"; - @NonNls - public static final String MXML_COMPONENT_TEMPLATE_NAME = "Mxml Component"; + public static boolean isFlexMxmFile(PsiFile file) { + return file.getFileType() == XmlFileType.INSTANCE && nameHasMxmlExtension(file.getName()); + } - public static boolean isFlexMxmFile(final PsiFile file) - { - return file.getFileType() == XmlFileType.INSTANCE && nameHasMxmlExtension(file.getName()); - } + public static boolean isFlexMxmFile(VirtualFile file) { + return file.getFileType() == XmlFileType.INSTANCE && nameHasMxmlExtension(file.getName()); + } - public static boolean isFlexMxmFile(final VirtualFile file) - { - return file.getFileType() == XmlFileType.INSTANCE && nameHasMxmlExtension(file.getName()); - } + private static boolean nameHasMxmlExtension(String s) { + return s.endsWith(MXML_FILE_EXTENSION_DOT) || s.endsWith(MXML_FILE_EXTENSION2_DOT); + } - private static boolean nameHasMxmlExtension(final String s) - { - return s.endsWith(MXML_FILE_EXTENSION_DOT) || s.endsWith(MXML_FILE_EXTENSION2_DOT); - } + public static boolean isFlexMxmFile(String filename) { + return FileTypeManager.getInstance().getFileTypeByFileName(filename) == XmlFileType.INSTANCE && nameHasMxmlExtension(filename); + } - public static boolean isFlexMxmFile(String filename) - { - return FileTypeManager.getInstance().getFileTypeByFileName(filename) == XmlFileType.INSTANCE && nameHasMxmlExtension(filename); - } + public static boolean isBindowsFile(PsiElement element) { + PsiFile containingFile = element.getContainingFile(); + PsiElement tag = element.getParent().getParent(); + if (!(tag instanceof XmlTag)) { + return false; + } + if (BINDOWS_URI.equals(((XmlTag)tag).getNamespace())) { + return true; + } + if (!(containingFile instanceof XmlFile)) { + return false; + } - public static boolean isBindowsFile(final PsiElement element) - { - final PsiFile containingFile = element.getContainingFile(); - final PsiElement tag = element.getParent().getParent(); - if(!(tag instanceof XmlTag)) - { - return false; - } - if(BINDOWS_URI.equals(((XmlTag) tag).getNamespace())) - { - return true; - } - if(!(containingFile instanceof XmlFile)) - { - return false; - } - - return "Application".equals(((XmlFile) containingFile).getDocument().getRootTag().getName()); - } - - public static boolean isMxmlNs(final String ns) - { - return ArrayUtil.contains(ns, MXML_URIS); - } + return "Application".equals(((XmlFile)containingFile).getDocument().getRootTag().getName()); + } + public static boolean isMxmlNs(String ns) { + return ArrayUtil.contains(ns, MXML_URIS); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/XmlAttributeValueJSInjector.java b/base-impl/src/main/java/com/intellij/lang/javascript/XmlAttributeValueJSInjector.java index 5a7d36a2..71e4d4aa 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/XmlAttributeValueJSInjector.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/XmlAttributeValueJSInjector.java @@ -4,19 +4,17 @@ import consulo.language.psi.PsiElement; import consulo.xml.psi.xml.XmlAttributeValue; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 29-Aug-22 */ @ExtensionImpl -public class XmlAttributeValueJSInjector extends JSLanguageInjector -{ - @Nonnull - @Override - public Class getElementClass() - { - return XmlAttributeValue.class; - } +public class XmlAttributeValueJSInjector extends JSLanguageInjector { + @Nonnull + @Override + public Class getElementClass() { + return XmlAttributeValue.class; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/XmlTextJSInjector.java b/base-impl/src/main/java/com/intellij/lang/javascript/XmlTextJSInjector.java index af4f89e7..5de93482 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/XmlTextJSInjector.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/XmlTextJSInjector.java @@ -4,19 +4,17 @@ import consulo.language.psi.PsiElement; import consulo.xml.psi.xml.XmlText; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 29-Aug-22 */ @ExtensionImpl -public class XmlTextJSInjector extends JSLanguageInjector -{ - @Nonnull - @Override - public Class getElementClass() - { - return XmlText.class; - } +public class XmlTextJSInjector extends JSLanguageInjector { + @Nonnull + @Override + public Class getElementClass() { + return XmlText.class; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/flex/AnnotationBackedDescriptor.java b/base-impl/src/main/java/com/intellij/lang/javascript/flex/AnnotationBackedDescriptor.java index 6dd41b8e..42e8ba86 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/flex/AnnotationBackedDescriptor.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/flex/AnnotationBackedDescriptor.java @@ -23,9 +23,8 @@ /** * @author Maxim.Mossienko */ -public interface AnnotationBackedDescriptor extends XmlAttributeDescriptor, XmlElementDescriptor, XmlElementDescriptorWithCDataContent -{ - String getType(); +public interface AnnotationBackedDescriptor extends XmlAttributeDescriptor, XmlElementDescriptor, XmlElementDescriptorWithCDataContent { + String getType(); - String getArrayType(); + String getArrayType(); } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/flex/FlexImportSupport.java b/base-impl/src/main/java/com/intellij/lang/javascript/flex/FlexImportSupport.java index 46c5fb29..8abcc576 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/flex/FlexImportSupport.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/flex/FlexImportSupport.java @@ -20,196 +20,184 @@ import com.intellij.lang.javascript.psi.JSImportStatement; import com.intellij.lang.javascript.psi.resolve.JSImportedElementResolveResult; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; +import consulo.annotation.access.RequiredReadAction; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiNamedElement; import consulo.util.collection.ArrayUtil; -import org.jetbrains.annotations.NonNls; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; + import java.util.HashMap; import java.util.Map; /** * @author Maxim.Mossienko */ -public class FlexImportSupport -{ - // flex2.compiler.mxml.lang.StandardDefs - private static - @NonNls - String[] standardMxmlImports = new String[]{ - "mx.styles.*", - "mx.binding.*", - "mx.core.mx_internal", - "mx.core.IDeferredInstance", - "mx.core.IFactory", - "mx.core.IPropertyChangeNotifier", - "mx.core.ClassFactory", - "mx.core.DeferredInstanceFromClass", - "mx.core.DeferredInstanceFromFunction", - }; - - private static - @NonNls - String[] airOnlyImplicitImports = new String[]{ - "flash.data.*", - "flash.desktop.*", - "flash.filesystem.*", - "flash.html.*", - "flash.html.script.*" - }; - - private static - @NonNls - String[] implicitImports = new String[]{ - "flash.accessibility.*", - "flash.debugger.*", - "flash.display.*", - "flash.errors.*", - "flash.events.*", - "flash.external.*", - "flash.filters.*", - "flash.geom.*", - "flash.media.*", - "flash.net.*", - "flash.printing.*", - "flash.profiler.*", - "flash.system.*", - "flash.text.*", - "flash.ui.*", - "flash.utils.*", - "flash.xml.*" - }; - - private static final Map implicitImportListMap = new HashMap(); - private static final Map mxmlImportListMap = new HashMap(); - - static - { - fillMapFromImportsArray(implicitImports, implicitImportListMap); - fillMapFromImportsArray(standardMxmlImports, mxmlImportListMap); - } - - private static void fillMapFromImportsArray(final String[] strings, final Map map) - { - for(String s : strings) - { - doAppendToMap(map, s); - } - } - - public static void appendToMap(final Map map, final JSImportStatement importStatement) - { - doAppendToMap(map, importStatement); - } - - private static void doAppendToMap(final Map map, final Object stringOrStatement) - { - String s = stringOrStatement instanceof String ? (String) stringOrStatement : ((JSImportStatement) stringOrStatement).getImportText(); - - final int index = s.lastIndexOf('.'); - if(index == -1) - { - return; // nothing to import, global symbol - } - final String key = s.substring(index + 1); - final Object o = map.get(key); - - if(o == null) - { - map.put(key, stringOrStatement); - } - else if(o instanceof Object[]) - { - map.put(key, ArrayUtil.append((Object[]) o, stringOrStatement)); - } - else - { - map.put(key, new Object[]{ - stringOrStatement, - o - }); - } - } - - public static JSImportedElementResolveResult resolveTypeNameUsingImplicitImports(@Nonnull String referenceName, @Nonnull JSFile file) - { - final PsiElement context = file.getContext(); - - if(context != null) - { - JSImportedElementResolveResult expression = tryFindInMap(referenceName, file, implicitImportListMap, null); - if(expression != null) - { - return expression; - } - expression = tryFindInMap(referenceName, file, mxmlImportListMap, null); - if(expression != null) - { - return expression; - } - } - return null; - } - - - public static JSImportedElementResolveResult tryFindInMap(final String referenceName, final PsiNamedElement file, final Map map, - String qName) - { - JSImportedElementResolveResult resolveResult = tryEntry(map.get(referenceName), referenceName, file, qName); - if(resolveResult == null) - { - resolveResult = tryEntry(map.get("*"), referenceName, file, qName); - } - return resolveResult; - } - - public static JSImportedElementResolveResult tryFindInMap(final String referenceName, final PsiNamedElement file, final Map map) - { - return tryFindInMap(referenceName, file, map, null); - } - - private static JSImportedElementResolveResult tryEntry(Object entry, String referenceName, PsiNamedElement file, String qName) - { - if(entry == null) - { - return null; - } - else if(entry instanceof Object[]) - { - for(Object entryItem : (Object[]) entry) - { - JSImportedElementResolveResult expression = tryFindClass(referenceName, file, entryItem, qName); - if(expression != null) - { - return expression; - } - } - return null; - } - else - { - return tryFindClass(referenceName, file, entry, qName); - } - } - - private static JSImportedElementResolveResult tryFindClass(final String referenceName, final PsiNamedElement file, final Object entry, String qName) - { - String importString = entry instanceof String ? (String) entry : ((JSImportStatement) entry).getImportText(); - - String nameToTry = importString.endsWith(".*") ? importString.substring(0, importString.length() - 1) + referenceName : importString; - if(qName != null && !qName.equals(nameToTry)) - { - return null; - } - - PsiElement element = JSResolveUtil.findClassByQName(nameToTry, file); - - if(element != null) - { - return new JSImportedElementResolveResult(nameToTry, element, entry instanceof JSImportStatement ? (JSImportStatement) entry : null); - } - - return null; - } +public class FlexImportSupport { + // flex2.compiler.mxml.lang.StandardDefs + private static final String[] STANDARD_MXML_IMPORTS = new String[]{ + "mx.styles.*", + "mx.binding.*", + "mx.core.mx_internal", + "mx.core.IDeferredInstance", + "mx.core.IFactory", + "mx.core.IPropertyChangeNotifier", + "mx.core.ClassFactory", + "mx.core.DeferredInstanceFromClass", + "mx.core.DeferredInstanceFromFunction", + }; + + private static final String[] AIR_ONLY_IMPLICIT_IMPORTS = new String[]{ + "flash.data.*", + "flash.desktop.*", + "flash.filesystem.*", + "flash.html.*", + "flash.html.script.*" + }; + + private static final String[] IMPLICIT_IMPORTS = new String[]{ + "flash.accessibility.*", + "flash.debugger.*", + "flash.display.*", + "flash.errors.*", + "flash.events.*", + "flash.external.*", + "flash.filters.*", + "flash.geom.*", + "flash.media.*", + "flash.net.*", + "flash.printing.*", + "flash.profiler.*", + "flash.system.*", + "flash.text.*", + "flash.ui.*", + "flash.utils.*", + "flash.xml.*" + }; + + private static final Map IMPLICIT_IMPORT_LIST_MAP = new HashMap<>(); + private static final Map MXML_IMPORT_LIST_MAP = new HashMap<>(); + + static { + fillMapFromImportsArray(IMPLICIT_IMPORTS, IMPLICIT_IMPORT_LIST_MAP); + fillMapFromImportsArray(STANDARD_MXML_IMPORTS, MXML_IMPORT_LIST_MAP); + } + + @RequiredReadAction + private static void fillMapFromImportsArray(String[] strings, Map map) { + for (String s : strings) { + doAppendToMap(map, s); + } + } + + @RequiredReadAction + public static void appendToMap(Map map, JSImportStatement importStatement) { + doAppendToMap(map, importStatement); + } + + @RequiredReadAction + private static void doAppendToMap(Map map, Object stringOrStatement) { + String s = stringOrStatement instanceof String string ? string : ((JSImportStatement)stringOrStatement).getImportText(); + + int index = s.lastIndexOf('.'); + if (index == -1) { + return; // nothing to import, global symbol + } + String key = s.substring(index + 1); + Object o = map.get(key); + + if (o == null) { + map.put(key, stringOrStatement); + } + else if (o instanceof Object[] objects) { + map.put(key, ArrayUtil.append(objects, stringOrStatement)); + } + else { + map.put(key, new Object[]{stringOrStatement, o}); + } + } + + public static JSImportedElementResolveResult resolveTypeNameUsingImplicitImports(@Nonnull String referenceName, @Nonnull JSFile file) { + PsiElement context = file.getContext(); + + if (context != null) { + JSImportedElementResolveResult expression = tryFindInMap(referenceName, file, IMPLICIT_IMPORT_LIST_MAP, null); + if (expression != null) { + return expression; + } + expression = tryFindInMap(referenceName, file, MXML_IMPORT_LIST_MAP, null); + if (expression != null) { + return expression; + } + } + return null; + } + + public static JSImportedElementResolveResult tryFindInMap( + String referenceName, + PsiNamedElement file, + Map map, + String qName + ) { + JSImportedElementResolveResult resolveResult = tryEntry(map.get(referenceName), referenceName, file, qName); + if (resolveResult == null) { + resolveResult = tryEntry(map.get("*"), referenceName, file, qName); + } + return resolveResult; + } + + public static JSImportedElementResolveResult tryFindInMap( + String referenceName, + PsiNamedElement file, + Map map + ) { + return tryFindInMap(referenceName, file, map, null); + } + + private static JSImportedElementResolveResult tryEntry(Object entry, String referenceName, PsiNamedElement file, String qName) { + if (entry == null) { + return null; + } + else if (entry instanceof Object[] entryItems) { + for (Object entryItem : entryItems) { + JSImportedElementResolveResult expression = tryFindClass(referenceName, file, entryItem, qName); + if (expression != null) { + return expression; + } + } + return null; + } + else { + return tryFindClass(referenceName, file, entry, qName); + } + } + + @RequiredReadAction + private static JSImportedElementResolveResult tryFindClass( + String referenceName, + PsiNamedElement file, + Object entry, + String qName + ) { + String importString = entry instanceof String string ? string : ((JSImportStatement)entry).getImportText(); + + String nameToTry = importString.endsWith(".*") + ? importString.substring(0, importString.length() - 1) + referenceName + : importString; + if (qName != null && !qName.equals(nameToTry)) { + return null; + } + + PsiElement element = JSResolveUtil.findClassByQName(nameToTry, file); + + if (element != null) { + return new JSImportedElementResolveResult( + nameToTry, + element, + entry instanceof JSImportStatement importStatement ? importStatement : null + ); + } + + return null; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/flex/JSResolveHelper.java b/base-impl/src/main/java/com/intellij/lang/javascript/flex/JSResolveHelper.java index 359d427e..94ea4f99 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/flex/JSResolveHelper.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/flex/JSResolveHelper.java @@ -28,7 +28,7 @@ import consulo.project.Project; import consulo.virtualFileSystem.VirtualFile; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; /** * @author yole @@ -36,16 +36,20 @@ @Deprecated @DeprecationInfo("We need this?") @ExtensionAPI(ComponentScope.APPLICATION) -public interface JSResolveHelper -{ - ExtensionPointName EP_NAME = ExtensionPointName.create(JSResolveHelper.class); +public interface JSResolveHelper { + ExtensionPointName EP_NAME = ExtensionPointName.create(JSResolveHelper.class); - // TODO: drop module - @Nullable - PsiElement findClassByQName(final String link, final Project project, final String className, GlobalSearchScope scope); + // TODO: drop module + @Nullable + PsiElement findClassByQName(String link, Project project, String className, GlobalSearchScope scope); - void importClass(final PsiScopeProcessor processor, final PsiNamedElement file, final String packageQualifierText); + void importClass(PsiScopeProcessor processor, PsiNamedElement file, String packageQualifierText); - boolean processPackage(final String packageQualifierText, String resolvedName, final Processor processor, - GlobalSearchScope globalSearchScope, Project project); + boolean processPackage( + String packageQualifierText, + String resolvedName, + Processor processor, + GlobalSearchScope globalSearchScope, + Project project + ); } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/flex/XmlBackedJSClassImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/flex/XmlBackedJSClassImpl.java index 7cb917c0..05165794 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/flex/XmlBackedJSClassImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/flex/XmlBackedJSClassImpl.java @@ -26,11 +26,16 @@ import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; import com.intellij.lang.javascript.psi.resolve.ResolveProcessor; import com.intellij.xml.XmlElementDescriptor; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.application.util.*; import consulo.language.ast.ASTNode; import consulo.language.codeStyle.CodeStyleManager; import consulo.language.inject.InjectedLanguageManager; -import consulo.language.psi.*; +import consulo.language.psi.PsiElement; +import consulo.language.psi.PsiFile; +import consulo.language.psi.PsiReference; +import consulo.language.psi.PsiWhiteSpace; import consulo.language.psi.resolve.PsiElementProcessor; import consulo.language.psi.resolve.PsiScopeProcessor; import consulo.language.psi.resolve.ResolveState; @@ -40,726 +45,628 @@ import consulo.virtualFileSystem.VirtualFile; import consulo.xml.psi.XmlRecursiveElementVisitor; import consulo.xml.psi.xml.*; -import org.jetbrains.annotations.NonNls; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.*; /** * @author Maxim.Mossienko */ -public class XmlBackedJSClassImpl extends JSClassBase implements JSClass -{ - @NonNls - public static final String COMPONENT_TAG_NAME = "Component"; - @NonNls - public static final String CLASS_NAME_ATTRIBUTE_NAME = "className"; - - private volatile JSReferenceList myExtendsList; - private volatile JSReferenceList myImplementsList; - - public XmlBackedJSClassImpl(XmlTag tag) - { - super(tag.getNode()); - } - - @Override - @Nullable - public JSReferenceList getExtendsList() - { - JSReferenceList refList = myExtendsList; - if(refList == null) - { - final XmlTag rootTag = getParent(); - refList = createReferenceList(rootTag.getLocalName()); - refList.getParent().putUserData(JSResolveUtil.contextKey, this); - myExtendsList = refList; - } - return refList; - } - - private JSReferenceList createReferenceList(final String s) - { - final JSClass element = (JSClass) JSChangeUtil.createJSTreeFromText(getProject(), "class C extends " + s + " {}").getPsi(); - return element.getExtendsList(); - } - - @Override - public int getTextOffset() - { - return 0; - } - - @Override - @Nullable - public JSReferenceList getImplementsList() - { - JSReferenceList refList = myImplementsList; - - if(refList == null) - { - final XmlTag rootTag = getParent(); - myImplementsList = refList = createReferenceList(rootTag != null ? rootTag.getAttributeValue("implements") : null); - } - return refList; - } - - @Override - public PsiElement getNavigationElement() - { - return getParent(); - } - - @Override - public String getName() - { - XmlTag parent = getParent(); - if(isInlineComponentTag(parent)) - { - String explicitName = getExplicitName(); - if(explicitName != null) - { - return explicitName; - } - } - final PsiFile psi = parent.getContainingFile(); - VirtualFile file = psi.getVirtualFile(); - if(file == null && psi.getOriginalFile() != null) - { - file = psi.getOriginalFile().getVirtualFile(); - } - return file != null ? file.getNameWithoutExtension() : null; - } - - @Nullable - public String getExplicitName() - { - XmlTag parent = getParent(); - return parent.getAttributeValue(CLASS_NAME_ATTRIBUTE_NAME, parent.getNamespace()); - } - - @Override - public String getQualifiedName() - { - final String name = getName(); - if(name == null) - { - return null; - } - final PsiFile containingFile = getNode().getPsi().getContainingFile(); - final String expectedPackageNameFromFile = JSResolveUtil.getExpectedPackageNameFromFile(containingFile.getVirtualFile(), - containingFile.getProject(), true); - if(expectedPackageNameFromFile != null && expectedPackageNameFromFile.length() > 0) - { - return expectedPackageNameFromFile + "." + name; - } - - return name; - } - - @Override - public boolean isInterface() - { - return false; - } - - @Override - public boolean isDeprecated() - { - return false; - } - - @Nullable - @Override - public PsiElement getNameIdentifier() - { - return getParent(); - } - - @Override - public PsiElement setName(@NonNls @Nonnull String name) throws IncorrectOperationException - { - final int i = name.lastIndexOf('.'); - if(i != -1) - { - name = name.substring(0, i); - } - JSPsiImplUtils.updateFileName(this, name, getName()); - return null; - } - - @Override - @Nullable - public JSAttributeList getAttributeList() - { - return null; - } - - @Override - protected boolean processMembers(final PsiScopeProcessor processor, final ResolveState substitutor, final PsiElement lastParent, - final PsiElement place) - { - for(JSFile file : ourCachedScripts.get(CACHED_SCRIPTS_KEY, getParent(), null).getValue()) - { - if(!file.processDeclarations(processor, ResolveState.initial(), null, place)) - { - return false; - } - } - return true; - } - - @Override - public boolean processDeclarations(@Nonnull final PsiScopeProcessor processor, @Nonnull final ResolveState substitutor, - final PsiElement lastParent, @Nonnull final PsiElement place) - { - boolean b = super.processDeclarations(processor, substitutor, lastParent, place); - - if(b && JSResolveUtil.shouldProcessImports(place, processor)) - { - b = JSImportHandlingUtil.tryResolveImports(processor, this, place); - if(!b) - { - return false; - } - b = doImportFromScripts(processor, place); - } - - return b; - } - - public boolean doImportFromScripts(final PsiScopeProcessor processor, final PsiElement place) - { - PsiElement context = place.getContainingFile().getContext(); - if(context instanceof XmlText) - { - context = context.getParent(); - } - - boolean notResolvingTypeViaImport = !(place instanceof JSFile); - - if((context instanceof XmlAttributeValue && (!(place instanceof JSReferenceExpression) || !JSResolveUtil.referenceExpressionShouldBeQualified( - (JSReferenceExpression) place))) || - (context instanceof XmlTag && (!SCRIPT_TAG_NAME.equals(((XmlTag) context).getLocalName()) || notResolvingTypeViaImport)) || - context == null) - { - boolean useImports = JSResolveUtil.shouldProcessImports(place, processor); - boolean adequatePlace = false; - - XmlTag parent = getParent(); - JSFile[] files = ourCachedScripts.get(CACHED_SCRIPTS_KEY, parent, null).getValue(); - for(JSFile file : files) - { - if(JSImportHandlingUtil.isAdequatePlaceForImport(file, place)) - { - if(useImports && JSImportHandlingUtil.importClass(processor, file)) - { - return false; - } - adequatePlace = true; - } - } - - if(adequatePlace && processor instanceof ResolveProcessor) - { - if(!processComponentNames((ResolveProcessor) processor)) - { - return false; - } - } - } - - if(processor instanceof ResolveProcessor && JSResolveUtil.shouldProcessTopLevelGlobalContext(place, processor) && - notResolvingTypeViaImport) - { - if(!JSResolveUtil.processGlobalThings(processor, ResolveState.initial(), place, this)) - { - return false; - } - } - return true; - } - - public boolean processComponentNames(ResolveProcessor processor) - { - String s = processor.getName(); - Map value = myCachedComponentImportsCache.get(OUR_CACHED_SHORT_COMPONENTS_REF_KEY, (XmlFile) getContainingFile(), null).getValue(); - - if(s != null) - { - String qName = value.get(s); - if(qName != null) - { - PsiElement clazz = JSResolveUtil.findClassByQName(qName, this); - if(clazz != null) - { - return processor.execute(clazz, ResolveState.initial()); - } - } - } - else - { - for(String qName : value.values()) - { - PsiElement clazz = JSResolveUtil.findClassByQName(qName, this); - if(clazz != null && !processor.execute(clazz, ResolveState.initial())) - { - return false; - } - } - } - return true; - } - - private static final Key> CACHED_SCRIPTS_KEY = Key.create("cached.scripts"); - private static final Key>> OUR_CACHED_SHORT_COMPONENTS_REF_KEY = Key.create("cached.component.refs"); - - @NonNls - private static final String SCRIPT_TAG_NAME = "Script"; - - private static final UserDataCache, XmlTag, Object> ourCachedScripts = new UserDataCache, XmlTag, - Object>() - { - @Override - protected CachedValue compute(final XmlTag tag, final Object p) - { - return CachedValuesManager.getManager(tag.getProject()).createCachedValue(new CachedValueProvider() - { - @Override - public Result compute() - { - final List injectedFiles = new ArrayList(2); - final List dependencies = new ArrayList(); - dependencies.add(tag); - new InjectedScriptsVisitor(tag, doProcessAllTags(tag), false, false, new InjectedFileVisitor() - { - @Override - public void visit(XmlTag rootTag, JSFile file) - { - injectedFiles.add(file); - dependencies.add(file); - } - }).go(); - return new Result(injectedFiles.toArray(new JSFile[injectedFiles.size()]), dependencies.toArray()); - } - }, false); - } - }; - - private static final UserDataCache>, XmlFile, Object> myCachedComponentImportsCache = new - UserDataCache>, XmlFile, Object>() - { - @Override - protected CachedValue> compute(final XmlFile file, final Object p) - { - return CachedValuesManager.getManager(file.getProject()).createCachedValue(new CachedValueProvider>() - { - @Override - public Result> compute() - { - final Map cachedComponentImports = new HashMap(); - final List dependencies = new ArrayList(); - dependencies.add(file); - - file.acceptChildren(new XmlRecursiveElementVisitor() - { - @Override - public void visitXmlTag(XmlTag tag) - { - XmlElementDescriptor descriptor = tag.getDescriptor(); - if(descriptor != null) - { - PsiElement declaration = descriptor.getDeclaration(); - if(declaration instanceof XmlFile) - { - declaration = XmlBackedJSClassImpl.getXmlBackedClass((XmlFile) declaration); - } - if(declaration instanceof JSClass) - { - JSClass jsClass = (JSClass) declaration; - - cachedComponentImports.put(jsClass.getName(), jsClass.getQualifiedName()); - dependencies.add(declaration.getContainingFile()); - } - } - super.visitXmlTag(tag); - } - }); - return new Result>(cachedComponentImports, dependencies.toArray()); - } - }, false); - } - }; - - - public static boolean doProcessAllTags(final XmlTag rootTag) - { - return JSLanguageInjector.isMozillaXulOrXblNs(rootTag != null ? rootTag.getNamespace() : null); - } - - public static boolean doProcessAllTags(final XmlFile file) - { - return doProcessAllTags(getRootTag(file)); - } - - @Override - public boolean isValid() - { - return getNode().getPsi().isValid(); - } - - private static Key> ourArtificialPsiKey = Key.create("xml.backed.class"); - - @Nullable - public static JSClass getXmlBackedClass(final XmlFile xmlFile) - { - final XmlTag rootTag = getRootTag(xmlFile); - return rootTag != null ? getXmlBackedClass(rootTag) : null; - } - - @Nullable - private static XmlTag getRootTag(XmlFile xmlFile) - { - final XmlDocument document = xmlFile.getDocument(); - return document != null ? document.getRootTag() : null; - } - - public static XmlBackedJSClassImpl getXmlBackedClass(final XmlTag tag) - { - return myCachedClassCache.get(ourArtificialPsiKey, tag, null).getValue(tag); - } - - public static Collection getClasses(XmlFile file) - { - XmlTag rootTag = getRootTag(file); - if(rootTag == null) - { - return Collections.emptyList(); - } - final Collection result = new ArrayList(); - result.add(getXmlBackedClass(rootTag)); - result.addAll(getChildInlineComponents(rootTag, true)); - return result; - } - - public static XmlBackedJSClassImpl getContainingComponent(XmlElement element) - { - if(element instanceof XmlTag && isInlineComponentTag((XmlTag) element)) - { - return getXmlBackedClass((XmlTag) element); - } - XmlTag parentTag = PsiTreeUtil.getParentOfType(element, XmlTag.class); - if(parentTag != null) - { - return getContainingComponent(parentTag); - } - - if(!(element instanceof XmlTag)) - { - return null; - } - return getXmlBackedClass((XmlTag) element); - } - - private static final UserDataCache, XmlTag, - Object> myCachedClassCache = new UserDataCache, XmlTag, Object>() - { - @Override - protected ParameterizedCachedValue compute(final XmlTag tag, final Object p) - { - return CachedValuesManager.getManager(tag.getProject()).createParameterizedCachedValue(new ParameterizedCachedValueProvider() - { - @Override - public CachedValueProvider.Result compute(XmlTag tag) - { - return new CachedValueProvider.Result(new XmlBackedJSClassImpl(tag), tag); - } - }, false); - } - }; - - @Override - public XmlTag getParent() - { - return (XmlTag) getNode().getPsi(); - } - - @Override - public boolean isEquivalentTo(final PsiElement element2) - { - return this == element2 || - element2 == getContainingFile() || - (element2 instanceof XmlBackedJSClassImpl && getContainingFile() == element2.getContainingFile()); - } - - @Override - public PsiElement add(@Nonnull PsiElement element) throws IncorrectOperationException - { - if(element instanceof JSFunction || element instanceof JSVarStatement) - { - final JSFile jsFile = createOrGetFirstScriptTag(); - - if(jsFile != null) - { - final PsiElement child = jsFile.getLastChild(); - - String text; - if(child instanceof PsiWhiteSpace && (text = child.getText()).indexOf("]]>") != -1) - { - int cdataAt = 0; - String marker = "", false)); - return findFirstScriptTag(); - } - return null; - } - - public static String findScriptNs(XmlTag rootTag) - { - String ns = rootTag.getNamespace(); - if(JavaScriptSupportLoader.isFlexMxmFile(rootTag.getContainingFile())) - { - ns = ""; - for(String testNs : JavaScriptSupportLoader.MXML_URIS) - { - if(rootTag.getPrefixByNamespace(testNs) != null) - { - ns = testNs; - break; - } - } - } - return ns; - } - - @Override - public PsiElement addBefore(@Nonnull final PsiElement element, final PsiElement anchor) throws IncorrectOperationException - { - if(anchor == null) - { - return add(element); - } - return anchor.getParent().addBefore(element, anchor); - } - - @Nullable - public JSFile findFirstScriptTag() - { - JSFile[] value = ourCachedScripts.get(CACHED_SCRIPTS_KEY, getParent(), null).getValue(); - if(value.length > 0) - { - return value[0]; - } - return null; - } - - public JSFile createOrGetFirstScriptTag() throws IncorrectOperationException - { - JSFile jsFile = findFirstScriptTag(); - - if(jsFile == null) - { - jsFile = createScriptTag(); - } - - return jsFile; - } - - public static XmlTag[] findMxmlSubTags(XmlTag tag, String scriptTagName) - { - String ns = findScriptNs(tag); - return tag.findSubTags(scriptTagName, ns); - } - - public static void visitInjectedFiles(XmlFile file, final InjectedFileVisitor visitor) - { - new InjectedScriptsVisitor(getRootTag(file), true, true, true, visitor).go(); - } - - public static boolean isInlineComponentTag(XmlTag tag) - { - return COMPONENT_TAG_NAME.equals(tag.getLocalName()) && - JavaScriptSupportLoader.isMxmlNs(tag.getNamespace()) && - !(tag.getParent() instanceof XmlDocument); - } - - public static Collection getChildInlineComponents(XmlTag rootTag, final boolean recursive) - { - final Collection result = new ArrayList(); - rootTag.processElements(new PsiElementProcessor() - { - @Override - public boolean execute(PsiElement element) - { - if(element instanceof XmlTag) - { - XmlTag tag = (XmlTag) element; - if(isInlineComponentTag(tag)) - { - result.add(getXmlBackedClass(tag)); - if(recursive) - { - tag.processElements(this, null); - } - } - else - { - tag.processElements(this, null); - } - } - return true; - } - }, null); - return result; - } - - public interface InjectedFileVisitor - { - void visit(XmlTag rootTag, JSFile file); - } - - public static class InjectedScriptsVisitor implements PsiElementProcessor - { - private final boolean myVisitAllTags; - private final boolean myVisitAttributes; - private final XmlTag myRootTag; - private final boolean myVisitInnerComponents; - private final InjectedFileVisitor myVisitor; - - public InjectedScriptsVisitor(XmlTag rootTag, boolean visitAllTags, boolean visitAttributes, boolean visitInnerComponents, - InjectedFileVisitor visitor) - { - myVisitAllTags = visitAllTags; - myVisitAttributes = visitAttributes; - myRootTag = rootTag; - myVisitInnerComponents = visitInnerComponents; - myVisitor = visitor; - } - - public void go() - { - myRootTag.processElements(this, null); - } - - @Override - public boolean execute(final PsiElement element) - { - if(element instanceof XmlTag) - { - final XmlTag tag = (XmlTag) element; - - if(myVisitAllTags || SCRIPT_TAG_NAME.equals(tag.getLocalName())) - { - final String srcLocation = tag.getAttributeValue("source"); - if(srcLocation != null) - { - PsiReference ref = findFileReference(tag.getAttribute("source").getValueElement()); - if(ref != null) - { - final PsiElement psiElement = ref.resolve(); - if(psiElement instanceof JSFile) - { - psiElement.putUserData(JSResolveUtil.contextKey, tag); - myVisitor.visit(myRootTag, (JSFile) psiElement); - } - } - } - else - { - JSResolveUtil.processInjectedFileForTag(tag, new JSResolveUtil.JSInjectedFilesVisitor() - { - @Override - protected void process(final JSFile file) - { - myVisitor.visit(myRootTag, file); - } - }); - } - } - if(isInlineComponentTag(tag)) - { - if(myVisitInnerComponents) - { - new InjectedScriptsVisitor(tag, myVisitAllTags, myVisitAttributes, true, myVisitor).go(); - } - } - else - { - tag.processElements(this, null); - } - } - if(myVisitAttributes && element instanceof XmlAttribute) - { - XmlAttributeValue value = ((XmlAttribute) element).getValueElement(); - if(value != null) - { - InjectedLanguageManager.getInstance(element.getProject()).enumerate(value, new PsiLanguageInjectionHost.InjectedPsiVisitor() - { - @Override - public void visit(@Nonnull PsiFile injectedPsi, @Nonnull List places) - { - if(places.get(0).getHost() instanceof XmlAttributeValue) - { - myVisitor.visit(myRootTag, (JSFile) injectedPsi); - } - } - }); - } - } - return true; - } - - @Nullable - private static PsiReference findFileReference(XmlAttributeValue valueElement) - { - if(valueElement == null) - { - return null; - } - PsiReference[] references = valueElement.getReferences(); - if(references.length > 0) - { - return references[references.length - 1]; - } - return null; - } - } - +public class XmlBackedJSClassImpl extends JSClassBase implements JSClass { + public static final String COMPONENT_TAG_NAME = "Component"; + public static final String CLASS_NAME_ATTRIBUTE_NAME = "className"; + + private volatile JSReferenceList myExtendsList; + private volatile JSReferenceList myImplementsList; + + public XmlBackedJSClassImpl(XmlTag tag) { + super(tag.getNode()); + } + + @Nullable + @Override + @RequiredReadAction + public JSReferenceList getExtendsList() { + JSReferenceList refList = myExtendsList; + if (refList == null) { + XmlTag rootTag = getParent(); + refList = createReferenceList(rootTag.getLocalName()); + refList.getParent().putUserData(JSResolveUtil.contextKey, this); + myExtendsList = refList; + } + return refList; + } + + @RequiredReadAction + private JSReferenceList createReferenceList(String s) { + JSClass element = (JSClass)JSChangeUtil.createJSTreeFromText(getProject(), "class C extends " + s + " {}").getPsi(); + return element.getExtendsList(); + } + + @Override + @RequiredReadAction + public int getTextOffset() { + return 0; + } + + @Nullable + @Override + @RequiredReadAction + public JSReferenceList getImplementsList() { + JSReferenceList refList = myImplementsList; + + if (refList == null) { + XmlTag rootTag = getParent(); + myImplementsList = refList = createReferenceList(rootTag != null ? rootTag.getAttributeValue("implements") : null); + } + return refList; + } + + @Nonnull + @Override + @RequiredReadAction + public PsiElement getNavigationElement() { + return getParent(); + } + + @Override + @RequiredReadAction + public String getName() { + XmlTag parent = getParent(); + if (isInlineComponentTag(parent)) { + String explicitName = getExplicitName(); + if (explicitName != null) { + return explicitName; + } + } + PsiFile psi = parent.getContainingFile(); + VirtualFile file = psi.getVirtualFile(); + if (file == null && psi.getOriginalFile() != null) { + file = psi.getOriginalFile().getVirtualFile(); + } + return file != null ? file.getNameWithoutExtension() : null; + } + + @Nullable + @RequiredReadAction + public String getExplicitName() { + XmlTag parent = getParent(); + return parent.getAttributeValue(CLASS_NAME_ATTRIBUTE_NAME, parent.getNamespace()); + } + + @Override + @RequiredReadAction + public String getQualifiedName() { + String name = getName(); + if (name == null) { + return null; + } + PsiFile containingFile = getNode().getPsi().getContainingFile(); + String expectedPackageNameFromFile = JSResolveUtil.getExpectedPackageNameFromFile(containingFile.getVirtualFile(), + containingFile.getProject(), true + ); + if (expectedPackageNameFromFile != null && expectedPackageNameFromFile.length() > 0) { + return expectedPackageNameFromFile + "." + name; + } + + return name; + } + + @Override + public boolean isInterface() { + return false; + } + + @Override + public boolean isDeprecated() { + return false; + } + + @Nullable + @Override + @RequiredReadAction + public PsiElement getNameIdentifier() { + return getParent(); + } + + @Override + @RequiredWriteAction + public PsiElement setName(@Nonnull String name) throws IncorrectOperationException { + int i = name.lastIndexOf('.'); + if (i != -1) { + name = name.substring(0, i); + } + JSPsiImplUtils.updateFileName(this, name, getName()); + return null; + } + + @Override + @Nullable + public JSAttributeList getAttributeList() { + return null; + } + + @Override + @RequiredReadAction + protected boolean processMembers( + PsiScopeProcessor processor, + ResolveState substitutor, + PsiElement lastParent, + PsiElement place + ) { + for (JSFile file : CACHED_SCRIPTS.get(CACHED_SCRIPTS_KEY, getParent(), null).getValue()) { + if (!file.processDeclarations(processor, ResolveState.initial(), null, place)) { + return false; + } + } + return true; + } + + @Override + @RequiredReadAction + public boolean processDeclarations( + @Nonnull PsiScopeProcessor processor, + @Nonnull ResolveState substitutor, + PsiElement lastParent, + @Nonnull PsiElement place + ) { + boolean b = super.processDeclarations(processor, substitutor, lastParent, place); + + if (b && JSResolveUtil.shouldProcessImports(place, processor)) { + b = JSImportHandlingUtil.tryResolveImports(processor, this, place); + if (!b) { + return false; + } + b = doImportFromScripts(processor, place); + } + + return b; + } + + @RequiredReadAction + public boolean doImportFromScripts(PsiScopeProcessor processor, PsiElement place) { + PsiElement context = place.getContainingFile().getContext(); + if (context instanceof XmlText xmlText) { + context = xmlText.getParent(); + } + + boolean notResolvingTypeViaImport = !(place instanceof JSFile); + + if ((context instanceof XmlAttributeValue + && !(place instanceof JSReferenceExpression referenceExpression + && JSResolveUtil.referenceExpressionShouldBeQualified(referenceExpression))) + || (context instanceof XmlTag tag && (!SCRIPT_TAG_NAME.equals(tag.getLocalName()) || notResolvingTypeViaImport)) + || context == null + ) { + boolean useImports = JSResolveUtil.shouldProcessImports(place, processor); + boolean adequatePlace = false; + + XmlTag parent = getParent(); + JSFile[] files = CACHED_SCRIPTS.get(CACHED_SCRIPTS_KEY, parent, null).getValue(); + for (JSFile file : files) { + if (JSImportHandlingUtil.isAdequatePlaceForImport(file, place)) { + if (useImports && JSImportHandlingUtil.importClass(processor, file)) { + return false; + } + adequatePlace = true; + } + } + + if (adequatePlace && processor instanceof ResolveProcessor resolveProcessor && !processComponentNames(resolveProcessor)) { + return false; + } + } + + return !(processor instanceof ResolveProcessor) || !JSResolveUtil.shouldProcessTopLevelGlobalContext(place, processor) + || !notResolvingTypeViaImport || JSResolveUtil.processGlobalThings(processor, ResolveState.initial(), place, this); + } + + @RequiredReadAction + public boolean processComponentNames(ResolveProcessor processor) { + String s = processor.getName(); + Map value = + CACHED_COMPONENT_IMPORTS_CACHE.get(CACHED_SHORT_COMPONENTS_REF_KEY, (XmlFile)getContainingFile(), null).getValue(); + + if (s != null) { + String qName = value.get(s); + if (qName != null) { + PsiElement clazz = JSResolveUtil.findClassByQName(qName, this); + if (clazz != null) { + return processor.execute(clazz, ResolveState.initial()); + } + } + } + else { + for (String qName : value.values()) { + PsiElement clazz = JSResolveUtil.findClassByQName(qName, this); + if (clazz != null && !processor.execute(clazz, ResolveState.initial())) { + return false; + } + } + } + return true; + } + + private static final Key> CACHED_SCRIPTS_KEY = Key.create("cached.scripts"); + private static final Key>> CACHED_SHORT_COMPONENTS_REF_KEY = Key.create("cached.component.refs"); + + private static final String SCRIPT_TAG_NAME = "Script"; + + private static final UserDataCache, XmlTag, Object> CACHED_SCRIPTS = new UserDataCache<>() { + @Override + protected CachedValue compute(XmlTag tag, Object p) { + return CachedValuesManager.getManager(tag.getProject()).createCachedValue( + () -> { + List injectedFiles = new ArrayList<>(2); + List dependencies = new ArrayList<>(); + dependencies.add(tag); + new InjectedScriptsVisitor( + tag, + doProcessAllTags(tag), + false, + false, + (rootTag, file) -> { + injectedFiles.add(file); + dependencies.add(file); + } + ).go(); + return new CachedValueProvider.Result<>( + injectedFiles.toArray(new JSFile[injectedFiles.size()]), + dependencies.toArray() + ); + }, + false + ); + } + }; + + private static final UserDataCache>, XmlFile, Object> CACHED_COMPONENT_IMPORTS_CACHE = + new UserDataCache<>() { + @Override + protected CachedValue> compute(final XmlFile file, Object p) { + return CachedValuesManager.getManager(file.getProject()).createCachedValue( + new CachedValueProvider>() { + @Override + public Result> compute() { + Map cachedComponentImports = new HashMap<>(); + List dependencies = new ArrayList<>(); + dependencies.add(file); + + file.acceptChildren(new XmlRecursiveElementVisitor() { + @Override + @RequiredReadAction + public void visitXmlTag(XmlTag tag) { + XmlElementDescriptor descriptor = tag.getDescriptor(); + if (descriptor != null) { + PsiElement declaration = descriptor.getDeclaration(); + if (declaration instanceof XmlFile xmlFile) { + declaration = XmlBackedJSClassImpl.getXmlBackedClass(xmlFile); + } + if (declaration instanceof JSClass jsClass) { + cachedComponentImports.put(jsClass.getName(), jsClass.getQualifiedName()); + dependencies.add(declaration.getContainingFile()); + } + } + super.visitXmlTag(tag); + } + }); + return new Result<>(cachedComponentImports, dependencies.toArray()); + } + }, + false + ); + } + }; + + public static boolean doProcessAllTags(XmlTag rootTag) { + return JSLanguageInjector.isMozillaXulOrXblNs(rootTag != null ? rootTag.getNamespace() : null); + } + + public static boolean doProcessAllTags(XmlFile file) { + return doProcessAllTags(getRootTag(file)); + } + + @Override + @RequiredReadAction + public boolean isValid() { + return getNode().getPsi().isValid(); + } + + private static Key> ourArtificialPsiKey = Key.create("xml.backed.class"); + + @Nullable + public static JSClass getXmlBackedClass(XmlFile xmlFile) { + XmlTag rootTag = getRootTag(xmlFile); + return rootTag != null ? getXmlBackedClass(rootTag) : null; + } + + @Nullable + private static XmlTag getRootTag(XmlFile xmlFile) { + XmlDocument document = xmlFile.getDocument(); + return document != null ? document.getRootTag() : null; + } + + public static XmlBackedJSClassImpl getXmlBackedClass(XmlTag tag) { + return myCachedClassCache.get(ourArtificialPsiKey, tag, null).getValue(tag); + } + + public static Collection getClasses(XmlFile file) { + XmlTag rootTag = getRootTag(file); + if (rootTag == null) { + return Collections.emptyList(); + } + Collection result = new ArrayList<>(); + result.add(getXmlBackedClass(rootTag)); + result.addAll(getChildInlineComponents(rootTag, true)); + return result; + } + + public static XmlBackedJSClassImpl getContainingComponent(XmlElement element) { + if (element instanceof XmlTag && isInlineComponentTag((XmlTag)element)) { + return getXmlBackedClass((XmlTag)element); + } + XmlTag parentTag = PsiTreeUtil.getParentOfType(element, XmlTag.class); + if (parentTag != null) { + return getContainingComponent(parentTag); + } + + if (!(element instanceof XmlTag)) { + return null; + } + return getXmlBackedClass((XmlTag)element); + } + + private static final UserDataCache, XmlTag, Object> myCachedClassCache = + new UserDataCache<>() { + @Override + protected ParameterizedCachedValue compute(XmlTag tag, Object p) { + return CachedValuesManager.getManager(tag.getProject()).createParameterizedCachedValue( + (ParameterizedCachedValueProvider)tag1 -> + new CachedValueProvider.Result<>(new XmlBackedJSClassImpl(tag1), tag1), + false + ); + } + }; + + @Override + @RequiredReadAction + public XmlTag getParent() { + return (XmlTag)getNode().getPsi(); + } + + @Override + public boolean isEquivalentTo(PsiElement element2) { + return this == element2 + || element2 == getContainingFile() + || (element2 instanceof XmlBackedJSClassImpl && getContainingFile() == element2.getContainingFile()); + } + + @Override + @RequiredWriteAction + public PsiElement add(@Nonnull PsiElement element) throws IncorrectOperationException { + if (element instanceof JSFunction || element instanceof JSVarStatement) { + JSFile jsFile = createOrGetFirstScriptTag(); + + if (jsFile != null) { + PsiElement child = jsFile.getLastChild(); + + String text; + if (child instanceof PsiWhiteSpace whiteSpace && (text = whiteSpace.getText()).indexOf("]]>") != -1) { + int cdataAt; + String marker = "", false)); + return findFirstScriptTag(); + } + return null; + } + + public static String findScriptNs(XmlTag rootTag) { + String ns = rootTag.getNamespace(); + if (JavaScriptSupportLoader.isFlexMxmFile(rootTag.getContainingFile())) { + ns = ""; + for (String testNs : JavaScriptSupportLoader.MXML_URIS) { + if (rootTag.getPrefixByNamespace(testNs) != null) { + ns = testNs; + break; + } + } + } + return ns; + } + + @Override + @RequiredWriteAction + public PsiElement addBefore(@Nonnull PsiElement element, PsiElement anchor) throws IncorrectOperationException { + if (anchor == null) { + return add(element); + } + return anchor.getParent().addBefore(element, anchor); + } + + @Nullable + @RequiredReadAction + public JSFile findFirstScriptTag() { + JSFile[] value = CACHED_SCRIPTS.get(CACHED_SCRIPTS_KEY, getParent(), null).getValue(); + if (value.length > 0) { + return value[0]; + } + return null; + } + + @RequiredReadAction + public JSFile createOrGetFirstScriptTag() throws IncorrectOperationException { + JSFile jsFile = findFirstScriptTag(); + + if (jsFile == null) { + jsFile = createScriptTag(); + } + + return jsFile; + } + + public static XmlTag[] findMxmlSubTags(XmlTag tag, String scriptTagName) { + String ns = findScriptNs(tag); + return tag.findSubTags(scriptTagName, ns); + } + + public static void visitInjectedFiles(XmlFile file, InjectedFileVisitor visitor) { + new InjectedScriptsVisitor(getRootTag(file), true, true, true, visitor).go(); + } + + public static boolean isInlineComponentTag(XmlTag tag) { + return COMPONENT_TAG_NAME.equals(tag.getLocalName()) + && JavaScriptSupportLoader.isMxmlNs(tag.getNamespace()) + && !(tag.getParent() instanceof XmlDocument); + } + + public static Collection getChildInlineComponents(XmlTag rootTag, boolean recursive) { + Collection result = new ArrayList<>(); + rootTag.processElements( + new PsiElementProcessor() { + @Override + public boolean execute(@Nonnull PsiElement element) { + if (element instanceof XmlTag tag) { + if (isInlineComponentTag(tag)) { + result.add(getXmlBackedClass(tag)); + if (recursive) { + tag.processElements(this, null); + } + } + else { + tag.processElements(this, null); + } + } + return true; + } + }, + null + ); + return result; + } + + public interface InjectedFileVisitor { + void visit(XmlTag rootTag, JSFile file); + } + + public static class InjectedScriptsVisitor implements PsiElementProcessor { + private final boolean myVisitAllTags; + private final boolean myVisitAttributes; + private final XmlTag myRootTag; + private final boolean myVisitInnerComponents; + private final InjectedFileVisitor myVisitor; + + public InjectedScriptsVisitor( + XmlTag rootTag, + boolean visitAllTags, + boolean visitAttributes, + boolean visitInnerComponents, + InjectedFileVisitor visitor + ) { + myVisitAllTags = visitAllTags; + myVisitAttributes = visitAttributes; + myRootTag = rootTag; + myVisitInnerComponents = visitInnerComponents; + myVisitor = visitor; + } + + public void go() { + myRootTag.processElements(this, null); + } + + @Override + @RequiredReadAction + public boolean execute(@Nonnull PsiElement element) { + if (element instanceof XmlTag tag) { + if (myVisitAllTags || SCRIPT_TAG_NAME.equals(tag.getLocalName())) { + String srcLocation = tag.getAttributeValue("source"); + if (srcLocation != null) { + PsiReference ref = findFileReference(tag.getAttribute("source").getValueElement()); + if (ref != null && ref.resolve() instanceof JSFile jsFile) { + jsFile.putUserData(JSResolveUtil.contextKey, tag); + myVisitor.visit(myRootTag, jsFile); + } + } + else { + JSResolveUtil.processInjectedFileForTag( + tag, + new JSResolveUtil.JSInjectedFilesVisitor() { + @Override + protected void process(JSFile file) { + myVisitor.visit(myRootTag, file); + } + } + ); + } + } + if (isInlineComponentTag(tag)) { + if (myVisitInnerComponents) { + new InjectedScriptsVisitor(tag, myVisitAllTags, myVisitAttributes, true, myVisitor).go(); + } + } + else { + tag.processElements(this, null); + } + } + if (myVisitAttributes && element instanceof XmlAttribute) { + XmlAttributeValue value = ((XmlAttribute)element).getValueElement(); + if (value != null) { + InjectedLanguageManager.getInstance(element.getProject()).enumerate( + value, + (injectedPsi, places) -> { + if (places.get(0).getHost() instanceof XmlAttributeValue) { + myVisitor.visit(myRootTag, (JSFile)injectedPsi); + } + } + ); + } + } + return true; + } + + @Nullable + private static PsiReference findFileReference(XmlAttributeValue valueElement) { + if (valueElement == null) { + return null; + } + PsiReference[] references = valueElement.getReferences(); + if (references.length > 0) { + return references[references.length - 1]; + } + return null; + } + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/highlighting/JSHighlighter.java b/base-impl/src/main/java/com/intellij/lang/javascript/highlighting/JSHighlighter.java index 6e4a3863..c39bef90 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/highlighting/JSHighlighter.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/highlighting/JSHighlighter.java @@ -18,7 +18,6 @@ import com.intellij.lang.javascript.JavaScriptHighlightingLexer; import com.intellij.lang.javascript.*; -import consulo.application.util.function.Processor; import consulo.colorScheme.TextAttributesKey; import consulo.javascript.ide.hightlight.JavaScriptSyntaxHighlightKeys; import consulo.language.ast.IElementType; @@ -26,114 +25,101 @@ import consulo.language.editor.highlight.SyntaxHighlighterBase; import consulo.language.lexer.Lexer; import consulo.xml.editor.XmlHighlighterColors; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; import java.util.HashMap; import java.util.Map; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 27, 2005 - * Time: 11:22:04 PM + * @author max + * @since 2005-01-27 */ @Deprecated -public class JSHighlighter extends SyntaxHighlighterBase implements JavaScriptSyntaxHighlightKeys -{ - private static Map keys1; - private static Map keys2; - private final DialectOptionHolder myDialectOptionsHolder; - - public JSHighlighter(DialectOptionHolder dialectOptionsHolder) - { - myDialectOptionsHolder = dialectOptionsHolder; - } - - @Override - @Nonnull - public Lexer getHighlightingLexer() - { - return new JavaScriptHighlightingLexer(myDialectOptionsHolder); - } - - - static - { - keys1 = new HashMap(); - keys2 = new HashMap(); - - SyntaxHighlighterBase.fillMap(keys1, JSTokenTypes.OPERATIONS, JS_OPERATION_SIGN); // we do need init OPERATIONS before KEYWORDS because has some - // OPERATIONS to be KEYWORDS (is, as) - fillMap(keys1, JSTokenTypes.KEYWORDS, JS_KEYWORD); - - keys1.put(StringEscapesTokenTypes.VALID_STRING_ESCAPE_TOKEN, JS_VALID_STRING_ESCAPE); - keys1.put(StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN, JS_INVALID_STRING_ESCAPE); - keys1.put(StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN, JS_INVALID_STRING_ESCAPE); - - keys1.put(JSTokenTypes.NUMERIC_LITERAL, JS_NUMBER); - keys1.put(JSTokenTypes.STRING_LITERAL, JS_STRING); - keys1.put(JSTokenTypes.SINGLE_QUOTE_STRING_LITERAL, JS_STRING); - keys1.put(JSTokenTypes.REGEXP_LITERAL, JS_REGEXP); - - keys1.put(JSTokenTypes.LPAR, JS_PARENTHS); - keys1.put(JSTokenTypes.RPAR, JS_PARENTHS); - - keys1.put(JSTokenTypes.LBRACE, JS_BRACES); - keys1.put(JSTokenTypes.RBRACE, JS_BRACES); - - keys1.put(JSTokenTypes.LBRACKET, JS_BRACKETS); - keys1.put(JSTokenTypes.RBRACKET, JS_BRACKETS); - - keys1.put(JSTokenTypes.COMMA, JS_COMMA); - keys1.put(JSTokenTypes.DOT, JS_DOT); - keys1.put(JSTokenTypes.SEMICOLON, JS_SEMICOLON); - - keys1.put(JSTokenTypes.C_STYLE_COMMENT, JS_BLOCK_COMMENT); - keys1.put(JSTokenTypes.XML_STYLE_COMMENT, JS_BLOCK_COMMENT); - keys1.put(JSTokenTypes.DOC_COMMENT, JS_DOC_COMMENT); - keys1.put(JSTokenTypes.END_OF_LINE_COMMENT, JS_LINE_COMMENT); - keys1.put(JSTokenTypes.BAD_CHARACTER, JS_BAD_CHARACTER); - - keys1.put(JSDocTokenTypes.DOC_TAG_NAME, JS_DOC_COMMENT); - keys2.put(JSDocTokenTypes.DOC_TAG_NAME, JS_DOC_TAG); - - IElementType[] javadoc = IElementType.enumerate(new Processor() - { - @Override - public boolean process(IElementType type) - { - return type instanceof JSDocElementType; - } - }); - - for(IElementType type : javadoc) - { - keys1.put(type, JS_DOC_COMMENT); - } - - keys1.put(JSTokenTypes.JSDOC_TAG_DATA, JS_DOC_COMMENT); - - for(IElementType type : JSTokenTypes.XML_TOKENS.getTypes()) - { - keys1.put(type, XmlHighlighterColors.XML_TAG); - } - - keys2.put(JSTokenTypes.XML_TAG_NAME, XmlHighlighterColors.XML_TAG_NAME); - keys2.put(JSTokenTypes.XML_NAME, XmlHighlighterColors.XML_ATTRIBUTE_NAME); - keys2.put(JSTokenTypes.XML_ATTR_VALUE, XmlHighlighterColors.XML_ATTRIBUTE_VALUE); - keys2.put(JSTokenTypes.XML_ATTR_VALUE_END, XmlHighlighterColors.XML_ATTRIBUTE_VALUE); - keys2.put(JSTokenTypes.XML_ATTR_VALUE_START, XmlHighlighterColors.XML_ATTRIBUTE_VALUE); - keys2.put(JSTokenTypes.XML_ATTR_EQUAL, XmlHighlighterColors.XML_ATTRIBUTE_VALUE); - keys2.put(JSTokenTypes.XML_ENTITY_REF, XmlHighlighterColors.XML_ENTITY_REFERENCE); - - keys1.put(JSTokenTypes.XML_STYLE_COMMENT, XmlHighlighterColors.XML_COMMENT); - keys1.put(JSTokenTypes.XML_TAG_CONTENT, XmlHighlighterColors.XML_TAG_DATA); - } - - @Override - @Nonnull - public TextAttributesKey[] getTokenHighlights(IElementType tokenType) - { - return pack(keys1.get(tokenType), keys2.get(tokenType)); - } +public class JSHighlighter extends SyntaxHighlighterBase implements JavaScriptSyntaxHighlightKeys { + private static final Map KEYS_1; + private static final Map KEYS_2; + private final DialectOptionHolder myDialectOptionsHolder; + + public JSHighlighter(DialectOptionHolder dialectOptionsHolder) { + myDialectOptionsHolder = dialectOptionsHolder; + } + + @Nonnull + @Override + public Lexer getHighlightingLexer() { + return new JavaScriptHighlightingLexer(myDialectOptionsHolder); + } + + static { + KEYS_1 = new HashMap<>(); + KEYS_2 = new HashMap<>(); + + SyntaxHighlighterBase.fillMap( + KEYS_1, + JSTokenTypes.OPERATIONS, + JS_OPERATION_SIGN + ); // we do need init OPERATIONS before KEYWORDS because has some + // OPERATIONS to be KEYWORDS (is, as) + fillMap(KEYS_1, JSTokenTypes.KEYWORDS, JS_KEYWORD); + + KEYS_1.put(StringEscapesTokenTypes.VALID_STRING_ESCAPE_TOKEN, JS_VALID_STRING_ESCAPE); + KEYS_1.put(StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN, JS_INVALID_STRING_ESCAPE); + KEYS_1.put(StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN, JS_INVALID_STRING_ESCAPE); + + KEYS_1.put(JSTokenTypes.NUMERIC_LITERAL, JS_NUMBER); + KEYS_1.put(JSTokenTypes.STRING_LITERAL, JS_STRING); + KEYS_1.put(JSTokenTypes.SINGLE_QUOTE_STRING_LITERAL, JS_STRING); + KEYS_1.put(JSTokenTypes.REGEXP_LITERAL, JS_REGEXP); + + KEYS_1.put(JSTokenTypes.LPAR, JS_PARENTHS); + KEYS_1.put(JSTokenTypes.RPAR, JS_PARENTHS); + + KEYS_1.put(JSTokenTypes.LBRACE, JS_BRACES); + KEYS_1.put(JSTokenTypes.RBRACE, JS_BRACES); + + KEYS_1.put(JSTokenTypes.LBRACKET, JS_BRACKETS); + KEYS_1.put(JSTokenTypes.RBRACKET, JS_BRACKETS); + + KEYS_1.put(JSTokenTypes.COMMA, JS_COMMA); + KEYS_1.put(JSTokenTypes.DOT, JS_DOT); + KEYS_1.put(JSTokenTypes.SEMICOLON, JS_SEMICOLON); + + KEYS_1.put(JSTokenTypes.C_STYLE_COMMENT, JS_BLOCK_COMMENT); + KEYS_1.put(JSTokenTypes.XML_STYLE_COMMENT, JS_BLOCK_COMMENT); + KEYS_1.put(JSTokenTypes.DOC_COMMENT, JS_DOC_COMMENT); + KEYS_1.put(JSTokenTypes.END_OF_LINE_COMMENT, JS_LINE_COMMENT); + KEYS_1.put(JSTokenTypes.BAD_CHARACTER, JS_BAD_CHARACTER); + + KEYS_1.put(JSDocTokenTypes.DOC_TAG_NAME, JS_DOC_COMMENT); + KEYS_2.put(JSDocTokenTypes.DOC_TAG_NAME, JS_DOC_TAG); + + IElementType[] javadoc = IElementType.enumerate(type -> type instanceof JSDocElementType); + + for (IElementType type : javadoc) { + KEYS_1.put(type, JS_DOC_COMMENT); + } + + KEYS_1.put(JSTokenTypes.JSDOC_TAG_DATA, JS_DOC_COMMENT); + + for (IElementType type : JSTokenTypes.XML_TOKENS.getTypes()) { + KEYS_1.put(type, XmlHighlighterColors.XML_TAG); + } + + KEYS_2.put(JSTokenTypes.XML_TAG_NAME, XmlHighlighterColors.XML_TAG_NAME); + KEYS_2.put(JSTokenTypes.XML_NAME, XmlHighlighterColors.XML_ATTRIBUTE_NAME); + KEYS_2.put(JSTokenTypes.XML_ATTR_VALUE, XmlHighlighterColors.XML_ATTRIBUTE_VALUE); + KEYS_2.put(JSTokenTypes.XML_ATTR_VALUE_END, XmlHighlighterColors.XML_ATTRIBUTE_VALUE); + KEYS_2.put(JSTokenTypes.XML_ATTR_VALUE_START, XmlHighlighterColors.XML_ATTRIBUTE_VALUE); + KEYS_2.put(JSTokenTypes.XML_ATTR_EQUAL, XmlHighlighterColors.XML_ATTRIBUTE_VALUE); + KEYS_2.put(JSTokenTypes.XML_ENTITY_REF, XmlHighlighterColors.XML_ENTITY_REFERENCE); + + KEYS_1.put(JSTokenTypes.XML_STYLE_COMMENT, XmlHighlighterColors.XML_COMMENT); + KEYS_1.put(JSTokenTypes.XML_TAG_CONTENT, XmlHighlighterColors.XML_TAG_DATA); + } + + @Nonnull + @Override + public TextAttributesKey[] getTokenHighlights(@Nonnull IElementType tokenType) { + return pack(KEYS_1.get(tokenType), KEYS_2.get(tokenType)); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/highlighting/JavaScriptHighlightingLexer.java b/base-impl/src/main/java/com/intellij/lang/javascript/highlighting/JavaScriptHighlightingLexer.java index 847b64cc..03207bce 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/highlighting/JavaScriptHighlightingLexer.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/highlighting/JavaScriptHighlightingLexer.java @@ -29,106 +29,103 @@ /** * @author max - * @since 12:13:05 AM Feb 15, 2005 + * @since 2005-02-15 */ -public class JavaScriptHighlightingLexer extends LayeredLexer -{ - public JavaScriptHighlightingLexer(Supplier baseLexerFactory) - { - this(baseLexerFactory, true); - } - - private JavaScriptHighlightingLexer(Supplier baseLexerFactory, boolean withEmbeddments) - { - super(baseLexerFactory.get()); - - if(withEmbeddments) - { - registerSelfStoppingLayer(new StringLiteralLexer('\"', JSTokenTypes.STRING_LITERAL, true, "/"), new IElementType[]{JSTokenTypes.STRING_LITERAL}, - IElementType.EMPTY_ARRAY); - - registerSelfStoppingLayer(new JavaScriptHighlightingLexer(baseLexerFactory, false), new IElementType[]{JSTokenTypes.XML_JS_SCRIPT}, - IElementType.EMPTY_ARRAY); - - registerSelfStoppingLayer(new StringLiteralLexer('\'', JSTokenTypes.SINGLE_QUOTE_STRING_LITERAL, true, "/"), - new IElementType[]{JSTokenTypes.SINGLE_QUOTE_STRING_LITERAL}, IElementType.EMPTY_ARRAY); - - final LayeredLexer docLexer = new LayeredLexer(new FlexAdapter(new _JSDocLexer(true))); - final Lexer lexer = getHtmlHighlightingLexer(); - - // Force html highlighting lexer not to return tag content type since it causes token type collision in javascript embedded to html - docLexer.registerLayer(new LexerBase() - { - final IElementType tagContentType = getTagContentTokenType(); - - - @Override - public void start(final CharSequence buffer, final int startOffset, final int endOffset, final int initialState) - { - lexer.start(buffer, startOffset, endOffset, initialState); - } - - @Override - public int getState() - { - return lexer.getState(); - } - - @Override - public IElementType getTokenType() - { - final IElementType tokenType = lexer.getTokenType(); - if(tokenType == tagContentType) - { - return JSTokenTypes.JSDOC_TAG_DATA; - } - return tokenType; - } - - @Override - public int getTokenStart() - { - return lexer.getTokenStart(); - } - - @Override - public int getTokenEnd() - { - return lexer.getTokenEnd(); - } - - @Override - public void advance() - { - lexer.advance(); - } - - @Override - public CharSequence getBufferSequence() - { - return lexer.getBufferSequence(); - } - - - @Override - public int getBufferEnd() - { - return lexer.getBufferEnd(); - } - }, JSDocTokenTypes.DOC_COMMENT_DATA); - registerSelfStoppingLayer(docLexer, new IElementType[]{JSTokenTypes.DOC_COMMENT}, new IElementType[]{JSDocTokenTypes.DOC_COMMENT_END}); - } - } - - public static IElementType getTagContentTokenType() - { - final Lexer highlightingLexer = getHtmlHighlightingLexer(); - highlightingLexer.start("a", 0, 1, 0); - return highlightingLexer.getTokenType(); - } - - private static Lexer getHtmlHighlightingLexer() - { - return SyntaxHighlighterFactory.getSyntaxHighlighter(HTMLLanguage.INSTANCE, null, null).getHighlightingLexer(); - } +public class JavaScriptHighlightingLexer extends LayeredLexer { + public JavaScriptHighlightingLexer(Supplier baseLexerFactory) { + this(baseLexerFactory, true); + } + + private JavaScriptHighlightingLexer(Supplier baseLexerFactory, boolean withEmbeddments) { + super(baseLexerFactory.get()); + + if (withEmbeddments) { + registerSelfStoppingLayer( + new StringLiteralLexer('\"', JSTokenTypes.STRING_LITERAL, true, "/"), + new IElementType[]{JSTokenTypes.STRING_LITERAL}, + IElementType.EMPTY_ARRAY + ); + + registerSelfStoppingLayer( + new JavaScriptHighlightingLexer(baseLexerFactory, false), + new IElementType[]{JSTokenTypes.XML_JS_SCRIPT}, + IElementType.EMPTY_ARRAY + ); + + registerSelfStoppingLayer(new StringLiteralLexer('\'', JSTokenTypes.SINGLE_QUOTE_STRING_LITERAL, true, "/"), + new IElementType[]{JSTokenTypes.SINGLE_QUOTE_STRING_LITERAL}, IElementType.EMPTY_ARRAY + ); + + LayeredLexer docLexer = new LayeredLexer(new FlexAdapter(new _JSDocLexer(true))); + final Lexer lexer = getHtmlHighlightingLexer(); + + // Force html highlighting lexer not to return tag content type + // since it causes token type collision in javascript embedded to html + docLexer.registerLayer( + new LexerBase() { + final IElementType tagContentType = getTagContentTokenType(); + + @Override + public void start(CharSequence buffer, int startOffset, int endOffset, int initialState) { + lexer.start(buffer, startOffset, endOffset, initialState); + } + + @Override + public int getState() { + return lexer.getState(); + } + + @Override + public IElementType getTokenType() { + IElementType tokenType = lexer.getTokenType(); + if (tokenType == tagContentType) { + return JSTokenTypes.JSDOC_TAG_DATA; + } + return tokenType; + } + + @Override + public int getTokenStart() { + return lexer.getTokenStart(); + } + + @Override + public int getTokenEnd() { + return lexer.getTokenEnd(); + } + + @Override + public void advance() { + lexer.advance(); + } + + @Override + public CharSequence getBufferSequence() { + return lexer.getBufferSequence(); + } + + @Override + public int getBufferEnd() { + return lexer.getBufferEnd(); + } + }, + JSDocTokenTypes.DOC_COMMENT_DATA + ); + registerSelfStoppingLayer( + docLexer, + new IElementType[]{JSTokenTypes.DOC_COMMENT}, + new IElementType[]{JSDocTokenTypes.DOC_COMMENT_END} + ); + } + } + + public static IElementType getTagContentTokenType() { + Lexer highlightingLexer = getHtmlHighlightingLexer(); + highlightingLexer.start("a", 0, 1, 0); + return highlightingLexer.getTokenType(); + } + + private static Lexer getHtmlHighlightingLexer() { + return SyntaxHighlighterFactory.getSyntaxHighlighter(HTMLLanguage.INSTANCE, null, null).getHighlightingLexer(); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/index/JSItemPresentation.java b/base-impl/src/main/java/com/intellij/lang/javascript/index/JSItemPresentation.java index 06530b6a..5d49a008 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/index/JSItemPresentation.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/index/JSItemPresentation.java @@ -21,85 +21,73 @@ import com.intellij.lang.javascript.psi.JSNamedElement; import com.intellij.lang.javascript.psi.JSVariable; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; +import consulo.annotation.access.RequiredReadAction; import consulo.component.util.Iconable; import consulo.language.icon.IconDescriptorUpdaters; -import consulo.language.psi.PsiElement; import consulo.language.psi.PsiFile; import consulo.navigation.ItemPresentation; import consulo.ui.annotation.RequiredUIAccess; import consulo.ui.image.Image; - -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; /** * @author Maxim.Mossienko - * @since 9:55:49 PM Apr 7, 2006 + * @since 2006-04-07 */ -public class JSItemPresentation implements ItemPresentation -{ - private JSNamedElement myElement; - - public JSItemPresentation(final JSNamedElement elementProxy) - { - this.myElement = elementProxy; - } +public class JSItemPresentation implements ItemPresentation { + private JSNamedElement myElement; - @Override - public String getPresentableText() - { - return myElement.getName(); - } + public JSItemPresentation(JSNamedElement elementProxy) { + this.myElement = elementProxy; + } - @Override - @Nullable - public String getLocationString() - { - final PsiFile psiFile = myElement.getContainingFile(); - if(myElement instanceof JSVariable || myElement instanceof JSFunction) - { - PsiElement possibleClazz = JSResolveUtil.findParent(myElement); + @Override + public String getPresentableText() { + return myElement.getName(); + } - if(possibleClazz instanceof JSClass) - { - final StringBuilder presentation = new StringBuilder(); + @Nullable + @Override + @RequiredReadAction + public String getLocationString() { + PsiFile psiFile = myElement.getContainingFile(); + if (myElement instanceof JSVariable || myElement instanceof JSFunction) { + if (JSResolveUtil.findParent(myElement) instanceof JSClass possibleJsClass) { + StringBuilder presentation = new StringBuilder(); - presentation.append(((JSClass) possibleClazz).getQualifiedName()); - presentation.append('(').append(getFileName(psiFile)).append(')'); - return presentation.toString(); - } - } - else if(myElement instanceof JSClass) - { - final String s = ((JSClass) myElement).getQualifiedName(); - final int i = s.lastIndexOf('.'); + presentation.append(possibleJsClass.getQualifiedName()); + presentation.append('(').append(getFileName(psiFile)).append(')'); + return presentation.toString(); + } + } + else if (myElement instanceof JSClass jsClass) { + String s = jsClass.getQualifiedName(); + int i = s.lastIndexOf('.'); - if(i != -1) - { - final StringBuilder presentation = new StringBuilder(); + if (i != -1) { + StringBuilder presentation = new StringBuilder(); - presentation.append(s.substring(0, i)); - presentation.append('(').append(getFileName(psiFile)).append(')'); - return presentation.toString(); - } - } - return getFileName(psiFile); - } + presentation.append(s.substring(0, i)); + presentation.append('(').append(getFileName(psiFile)).append(')'); + return presentation.toString(); + } + } + return getFileName(psiFile); + } - private static String getFileName(final PsiFile psiFile) - { - final String s = psiFile.getName(); - if(JSResolveUtil.isPredefinedFile(psiFile)) - { - return s.substring(s.lastIndexOf('/') + 1); - } - return s; - } + @RequiredReadAction + private static String getFileName(PsiFile psiFile) { + String s = psiFile.getName(); + if (JSResolveUtil.isPredefinedFile(psiFile)) { + return s.substring(s.lastIndexOf('/') + 1); + } + return s; + } - @Override - @Nullable - @RequiredUIAccess - public Image getIcon() - { - return IconDescriptorUpdaters.getIcon(myElement, Iconable.ICON_FLAG_VISIBILITY); - } + @Override + @Nullable + @RequiredUIAccess + public Image getIcon() { + return IconDescriptorUpdaters.getIcon(myElement, Iconable.ICON_FLAG_VISIBILITY); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/index/JSSymbolUtil.java b/base-impl/src/main/java/com/intellij/lang/javascript/index/JSSymbolUtil.java index 3bfdd25c..75991d37 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/index/JSSymbolUtil.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/index/JSSymbolUtil.java @@ -21,428 +21,347 @@ import com.intellij.lang.javascript.psi.resolve.ResolveProcessor; import consulo.language.psi.PsiElement; import consulo.language.psi.util.PsiTreeUtil; -import org.jetbrains.annotations.NonNls; +import jakarta.annotation.Nullable; -import javax.annotation.Nullable; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; /** - * @by maxim.mossienko, yole + * @author maxim.mossienko, yole */ -public class JSSymbolUtil -{ - @NonNls - private static final String PROTOTYPE_FIELD_NAME = "prototype"; - @NonNls - private static final String J_QUERY_VAR_NAME = "jQuery"; - @NonNls - private static final String FN_FUN_NAME = "fn"; - - - private static JSElement findNameComponent(JSElement expr) - { - if(expr instanceof JSReferenceExpression) - { - return expr; - } - JSElement current = expr; - - while(expr != null) - { - if(expr instanceof JSReferenceExpression) - { - return expr; - } - else if(expr instanceof JSAssignmentExpression) - { - final JSExpression _lOperand = ((JSAssignmentExpression) expr).getLOperand(); - if(!(_lOperand instanceof JSDefinitionExpression)) - { - break; - } - final JSExpression lOperand = ((JSDefinitionExpression) _lOperand).getExpression(); - - if(lOperand instanceof JSReferenceExpression) - { - expr = lOperand; - continue; - } - else - { - break; - } - } - else if(expr instanceof JSVariable) - { - return expr; - } - else if(expr instanceof JSCallExpression) - { - final JSExpression method = ((JSCallExpression) expr).getMethodExpression(); - if(method instanceof JSReferenceExpression) - { - return method; - } - } - else - { - current = expr; - } - - if(current != null) - { - final PsiElement parent = current.getParent(); - if(!(parent instanceof JSElement)) - { - break; - } - if(parent instanceof JSStatement) - { - break; - } - expr = (JSElement) parent; - } - } - - return null; - } - - public static String[] buildNameIndexArray(final JSElement _expr) - { - final List nameComponents = new ArrayList(); - - JSElement nameComponent = findNameComponent(_expr); - JSReferenceExpression expr = null; - - if(nameComponent instanceof JSVariable) - { - String varName = nameComponent.getName(); - if(varName != null) - { - nameComponents.add(varName); - } - } - else if(nameComponent instanceof JSReferenceExpression) - { - expr = (JSReferenceExpression) nameComponent; - } - - if(expr != null) - { - final JSReferenceExpression expr1 = expr; - visitReferenceExpressionComponentsInRootFirstOrder(expr, new ReferenceExpressionProcessor() - { - - @Override - public void processExpression(JSReferenceExpression expr) - { - nameComponents.add(expr.getReferencedName()); - } - - @Override - public void processUnresolvedThis() - { - nameComponents.add(""); - } - - @Override - public boolean isTopLevel(final JSReferenceExpression expression) - { - return expr1 == expression; - } - }); - } - - return nameComponents.toArray(new String[nameComponents.size()]); - } - - interface ReferenceExpressionProcessor - { - void processExpression(JSReferenceExpression expr); - - void processUnresolvedThis(); - - boolean isTopLevel(final JSReferenceExpression expression); - } - - - private static void visitReferenceExpressionComponentsInRootFirstOrder(JSReferenceExpression expr, ReferenceExpressionProcessor processor) - { - JSExpression qualifier = expr.getQualifier(); - - if(qualifier instanceof JSCallExpression) - { - qualifier = ((JSCallExpression) qualifier).getMethodExpression(); - } - - if(qualifier instanceof JSIndexedPropertyAccessExpression) - { - qualifier = ((JSIndexedPropertyAccessExpression) qualifier).getQualifier(); - } - - if(qualifier instanceof JSReferenceExpression) - { - visitReferenceExpressionComponentsInRootFirstOrder((JSReferenceExpression) qualifier, processor); - } - - if(qualifier instanceof JSThisExpression) - { - processor.processUnresolvedThis(); - } - - final String refName = expr.getReferencedName(); - - if(refName != null && (!refName.equals(PROTOTYPE_FIELD_NAME) || processor.isTopLevel(expr))) - { - processor.processExpression(expr); - } - } - - private static JSReferenceExpression evaluateInitializedPrototype(final JSExpression initializer) - { - JSReferenceExpression initializedPrototype = null; - - if(initializer instanceof JSReferenceExpression && PROTOTYPE_FIELD_NAME.equals(((JSReferenceExpression) initializer).getReferencedName())) - { - final JSExpression qualifier = ((JSReferenceExpression) initializer).getQualifier(); - if(qualifier instanceof JSReferenceExpression) - { - initializedPrototype = (JSReferenceExpression) qualifier; - } - } - else if(initializer instanceof JSAssignmentExpression) - { - JSExpression initializerlOperand = ((JSAssignmentExpression) initializer).getLOperand(); - if(initializerlOperand instanceof JSDefinitionExpression) - { - JSExpression lOperand = ((JSDefinitionExpression) initializerlOperand).getExpression(); - initializedPrototype = evaluateInitializedPrototype(lOperand); - } - } - return initializedPrototype; - } - - public static JSReferenceExpression findReferenceExpressionUsedForClassExtending(JSReferenceExpression lOperand) - { - return findReferenceExpressionUsedForClassExtending(lOperand, null); - } - - private static JSReferenceExpression findReferenceExpressionUsedForClassExtending(JSReferenceExpression lOperand, @Nullable Set visited) - { - JSReferenceExpression originalExpr = lOperand; - final ResolveProcessor processor = new ResolveProcessor(lOperand.getText(), true); - processor.setLocalResolve(true); - final PsiElement parent = lOperand.getParent(); - JSResolveUtil.treeWalkUp(processor, lOperand, parent, lOperand); - - PsiElement jsElement = processor.getResult(); - if(jsElement == null && parent instanceof JSDefinitionExpression) - { - jsElement = (JSElement) parent; - } - - if(jsElement instanceof JSVariable) - { - final JSExpression initialization = ((JSVariable) jsElement).getInitializer(); - final JSReferenceExpression expression = initialization != null ? evaluateInitializedPrototype(initialization) : null; - - if(expression != null) - { - lOperand = expression; - } - else if(initialization instanceof JSReferenceExpression) - { - lOperand = (JSReferenceExpression) initialization; - } - } - else - { - final PsiElement parentJsElement = jsElement != null ? jsElement.getParent() : null; - - if(jsElement instanceof JSDefinitionExpression && parentJsElement instanceof JSAssignmentExpression) - { // new expression also could mean something extension ! - JSExpression rOperand = ((JSAssignmentExpression) parentJsElement).getROperand(); - - if(rOperand instanceof JSCallExpression && !(rOperand instanceof JSNewExpression)) - { - final JSArgumentList list = ((JSCallExpression) rOperand).getArgumentList(); - - if(list != null) - { - final JSExpression[] jsExpressions = list.getArguments(); - - if(jsExpressions.length >= 2 && - jsExpressions[0] instanceof JSReferenceExpression && - jsExpressions[1] instanceof JSReferenceExpression) - { - lOperand = (JSReferenceExpression) jsExpressions[0]; - } - } - } - else if(rOperand instanceof JSReferenceExpression) - { - final JSReferenceExpression expression = evaluateInitializedPrototype(rOperand); - - if(expression != null) - { - lOperand = expression; - } - else - { - lOperand = (JSReferenceExpression) rOperand; - } - } - } - } - return lOperand != originalExpr ? replaceLocalVars(lOperand, visited) : lOperand; - } - - private static JSReferenceExpression replaceLocalVars(final JSReferenceExpression expression, @Nullable Set visited) - { - JSReferenceExpression expr = expression; - JSExpression qualifier = expr.getQualifier(); - - JSFunction func = PsiTreeUtil.getParentOfType(expression, JSFunction.class); - if(func == null) - { - return expression; - } - - while(qualifier instanceof JSReferenceExpression) - { - expr = (JSReferenceExpression) qualifier; - qualifier = expr.getQualifier(); - } - - if(qualifier == null) - { - final PsiElement ref = JSResolveUtil.getLocalVariableRef(func, expr); - - if(ref instanceof JSVariable && !(ref instanceof JSParameter)) - { - final JSExpression initializer = ((JSVariable) ref).getInitializer(); - - if(initializer instanceof JSReferenceExpression) - { - return replaceExpression(expression, expr, (JSReferenceExpression) initializer); - } - else if(expr != expression) - { - if(visited == null) - { - visited = new HashSet(); - } - final String replaced = expr.getText(); - - if(!visited.contains(replaced)) - { - visited.add(replaced); - return replaceExpression(expression, expr, findReferenceExpressionUsedForClassExtending(expr, visited)); - } - } - else - { - return findReferenceExpressionUsedForClassExtending(expr, visited); - } - } - } - return expression; - } - - private static JSReferenceExpression replaceExpression(final JSReferenceExpression expression, final JSReferenceExpression what, - final JSReferenceExpression by) - { - if(expression == what) - { - return by; - } - int offsetOfExprInExpression = what.getTextOffset() - expression.getTextOffset(); - final JSReferenceExpression copyOfExpr = (JSReferenceExpression) expression.copy(); - final JSReferenceExpression expressionToReplace = PsiTreeUtil.getParentOfType(copyOfExpr.findElementAt(offsetOfExprInExpression), - JSReferenceExpression.class); - expressionToReplace.replace(by); - return copyOfExpr; - } - - public static JSElement findQualifyingExpressionFromArgumentList(final JSArgumentList parent) - { - PsiElement firstParent = parent.getParent(); - final PsiElement grandParent = firstParent.getParent(); - - if(grandParent instanceof JSVariable) - { - return (JSElement) grandParent; - } - - if(grandParent instanceof JSAssignmentExpression) - { - JSExpression jsExpression = ((JSAssignmentExpression) grandParent).getLOperand(); - JSExpression assignedTo = jsExpression instanceof JSDefinitionExpression ? ((JSDefinitionExpression) jsExpression).getExpression() : null; - if(assignedTo instanceof JSReferenceExpression) - { - return assignedTo; - } - } - if(grandParent instanceof JSExpressionStatement && firstParent instanceof JSCallExpression) - { - JSExpression methodExpression = ((JSCallExpression) firstParent).getMethodExpression(); - String methodName = methodExpression instanceof JSReferenceExpression ? ((JSReferenceExpression) methodExpression).getReferencedName() : null; - - if("each".equals(methodName) || "extend".equals(methodName)) - { - JSExpression expression = ((JSReferenceExpression) methodExpression).getQualifier(); - - if(expression instanceof JSReferenceExpression) - { - JSReferenceExpression qualifierExpr = (JSReferenceExpression) expression; - - if(FN_FUN_NAME.equals(qualifierExpr.getReferencedName())) - { - expression = qualifierExpr.getQualifier(); - } - } - if(expression != null && J_QUERY_VAR_NAME.equals(expression.getText())) - { - return expression; - } - } - else if("implement".equals(methodName)) - { - JSExpression qualifier = ((JSReferenceExpression) methodExpression).getQualifier(); - if(qualifier instanceof JSReferenceExpression && parent.getArguments().length == 1) - { - return qualifier; - } - } - } - - JSExpression[] jsExpressions = parent.getArguments(); - for(int i = 0; i < jsExpressions.length; ++i) - { - final JSExpression expr = jsExpressions[i]; - - if(expr instanceof JSReferenceExpression || (expr instanceof JSLiteralExpression && !expr.textContains(' ') && expr.getTextLength() < 100)) - { - return expr; - } - else if(expr instanceof JSCallExpression) - { - final JSArgumentList argumentList = ((JSCallExpression) expr).getArgumentList(); - if(argumentList != null) - { - jsExpressions = argumentList.getArguments(); - i = -1; - } - } - else if(expr instanceof JSArrayLiteralExpression) - { - jsExpressions = ((JSArrayLiteralExpression) expr).getExpressions(); - i = -1; - } - } - return null; - } +public class JSSymbolUtil { + private static final String PROTOTYPE_FIELD_NAME = "prototype"; + private static final String J_QUERY_VAR_NAME = "jQuery"; + private static final String FN_FUN_NAME = "fn"; + + private static JSElement findNameComponent(JSElement expr) { + if (expr instanceof JSReferenceExpression) { + return expr; + } + JSElement current = expr; + + while (expr != null) { + if (expr instanceof JSReferenceExpression) { + return expr; + } + else if (expr instanceof JSAssignmentExpression assignment) { + JSExpression _lOperand = assignment.getLOperand(); + if (!(_lOperand instanceof JSDefinitionExpression)) { + break; + } + JSExpression lOperand = ((JSDefinitionExpression)_lOperand).getExpression(); + + if (lOperand instanceof JSReferenceExpression refExpr) { + expr = refExpr; + continue; + } + else { + break; + } + } + else if (expr instanceof JSVariable variable) { + return variable; + } + else if (expr instanceof JSCallExpression call) { + if (call.getMethodExpression() instanceof JSReferenceExpression methodRefExpr) { + return methodRefExpr; + } + } + else { + current = expr; + } + + if (current != null) { + PsiElement parent = current.getParent(); + if (!(parent instanceof JSElement)) { + break; + } + if (parent instanceof JSStatement) { + break; + } + expr = (JSElement)parent; + } + } + + return null; + } + + public static String[] buildNameIndexArray(JSElement _expr) { + final List nameComponents = new ArrayList<>(); + + JSElement nameComponent = findNameComponent(_expr); + JSReferenceExpression expr = null; + + if (nameComponent instanceof JSVariable variable) { + String varName = variable.getName(); + if (varName != null) { + nameComponents.add(varName); + } + } + else if (nameComponent instanceof JSReferenceExpression nameRefExpr) { + expr = nameRefExpr; + } + + if (expr != null) { + final JSReferenceExpression expr1 = expr; + visitReferenceExpressionComponentsInRootFirstOrder( + expr, + new ReferenceExpressionProcessor() { + @Override + public void processExpression(JSReferenceExpression expr) { + nameComponents.add(expr.getReferencedName()); + } + + @Override + public void processUnresolvedThis() { + nameComponents.add(""); + } + + @Override + public boolean isTopLevel(JSReferenceExpression expression) { + return expr1 == expression; + } + } + ); + } + + return nameComponents.toArray(new String[nameComponents.size()]); + } + + interface ReferenceExpressionProcessor { + void processExpression(JSReferenceExpression expr); + + void processUnresolvedThis(); + + boolean isTopLevel(JSReferenceExpression expression); + } + + private static void visitReferenceExpressionComponentsInRootFirstOrder( + JSReferenceExpression expr, + ReferenceExpressionProcessor processor + ) { + JSExpression qualifier = expr.getQualifier(); + + if (qualifier instanceof JSCallExpression callExpression) { + qualifier = callExpression.getMethodExpression(); + } + + if (qualifier instanceof JSIndexedPropertyAccessExpression indexedPropertyAccessExpression) { + qualifier = indexedPropertyAccessExpression.getQualifier(); + } + + if (qualifier instanceof JSReferenceExpression referenceExpression) { + visitReferenceExpressionComponentsInRootFirstOrder(referenceExpression, processor); + } + + if (qualifier instanceof JSThisExpression) { + processor.processUnresolvedThis(); + } + + String refName = expr.getReferencedName(); + + if (refName != null && (!refName.equals(PROTOTYPE_FIELD_NAME) || processor.isTopLevel(expr))) { + processor.processExpression(expr); + } + } + + private static JSReferenceExpression evaluateInitializedPrototype(JSExpression initializer) { + JSReferenceExpression initializedPrototype = null; + + if (initializer instanceof JSReferenceExpression initializerRefExpr + && PROTOTYPE_FIELD_NAME.equals(initializerRefExpr.getReferencedName()) + && initializerRefExpr.getQualifier() instanceof JSReferenceExpression qualifierRefExpr) { + initializedPrototype = qualifierRefExpr; + } + else if (initializer instanceof JSAssignmentExpression initializerAssignmentExpr + && initializerAssignmentExpr.getLOperand() instanceof JSDefinitionExpression lOperandDefExpr) { + initializedPrototype = evaluateInitializedPrototype(lOperandDefExpr.getExpression()); + } + return initializedPrototype; + } + + public static JSReferenceExpression findReferenceExpressionUsedForClassExtending(JSReferenceExpression lOperand) { + return findReferenceExpressionUsedForClassExtending(lOperand, null); + } + + private static JSReferenceExpression findReferenceExpressionUsedForClassExtending( + JSReferenceExpression lOperand, + @Nullable Set visited + ) { + JSReferenceExpression originalExpr = lOperand; + ResolveProcessor processor = new ResolveProcessor(lOperand.getText(), true); + processor.setLocalResolve(true); + PsiElement parent = lOperand.getParent(); + JSResolveUtil.treeWalkUp(processor, lOperand, parent, lOperand); + + PsiElement jsElement = processor.getResult(); + if (jsElement == null && parent instanceof JSDefinitionExpression parentDefExpr) { + jsElement = parentDefExpr; + } + + if (jsElement instanceof JSVariable variable) { + JSExpression initialization = variable.getInitializer(); + JSReferenceExpression expression = initialization != null ? evaluateInitializedPrototype(initialization) : null; + + if (expression != null) { + lOperand = expression; + } + else if (initialization instanceof JSReferenceExpression initializationRefExpr) { + lOperand = initializationRefExpr; + } + } + else { + PsiElement parentJsElement = jsElement != null ? jsElement.getParent() : null; + + // new expression also could mean something extension ! + if (jsElement instanceof JSDefinitionExpression + && jsElement.getParent() instanceof JSAssignmentExpression parentAssignExpr) { + JSExpression rOperand = parentAssignExpr.getROperand(); + + if (rOperand instanceof JSCallExpression callExpression && !(rOperand instanceof JSNewExpression)) { + JSArgumentList list = callExpression.getArgumentList(); + + if (list != null) { + JSExpression[] jsExpressions = list.getArguments(); + + if (jsExpressions.length >= 2 + && jsExpressions[0] instanceof JSReferenceExpression + && jsExpressions[1] instanceof JSReferenceExpression) { + lOperand = (JSReferenceExpression)jsExpressions[0]; + } + } + } + else if (rOperand instanceof JSReferenceExpression rOperandRefExpr) { + JSReferenceExpression expression = evaluateInitializedPrototype(rOperand); + lOperand = expression != null ? expression : rOperandRefExpr; + } + } + } + return lOperand != originalExpr ? replaceLocalVars(lOperand, visited) : lOperand; + } + + private static JSReferenceExpression replaceLocalVars(JSReferenceExpression expression, @Nullable Set visited) { + JSReferenceExpression expr = expression; + JSExpression qualifier = expr.getQualifier(); + + JSFunction func = PsiTreeUtil.getParentOfType(expression, JSFunction.class); + if (func == null) { + return expression; + } + + while (qualifier instanceof JSReferenceExpression qualifierRefExpr) { + expr = qualifierRefExpr; + qualifier = expr.getQualifier(); + } + + if (qualifier == null) { + PsiElement ref = JSResolveUtil.getLocalVariableRef(func, expr); + + if (ref instanceof JSVariable variable && !(ref instanceof JSParameter)) { + JSExpression initializer = variable.getInitializer(); + + if (initializer instanceof JSReferenceExpression initializerRefExpr) { + return replaceExpression(expression, expr, initializerRefExpr); + } + else if (expr != expression) { + if (visited == null) { + visited = new HashSet<>(); + } + String replaced = expr.getText(); + + if (!visited.contains(replaced)) { + visited.add(replaced); + return replaceExpression(expression, expr, findReferenceExpressionUsedForClassExtending(expr, visited)); + } + } + else { + return findReferenceExpressionUsedForClassExtending(expr, visited); + } + } + } + return expression; + } + + private static JSReferenceExpression replaceExpression( + JSReferenceExpression expression, + JSReferenceExpression what, + JSReferenceExpression by + ) { + if (expression == what) { + return by; + } + int offsetOfExprInExpression = what.getTextOffset() - expression.getTextOffset(); + JSReferenceExpression copyOfExpr = (JSReferenceExpression)expression.copy(); + JSReferenceExpression expressionToReplace = PsiTreeUtil.getParentOfType( + copyOfExpr.findElementAt(offsetOfExprInExpression), + JSReferenceExpression.class + ); + expressionToReplace.replace(by); + return copyOfExpr; + } + + public static JSElement findQualifyingExpressionFromArgumentList(JSArgumentList parent) { + PsiElement firstParent = parent.getParent(); + PsiElement grandParent = firstParent.getParent(); + + if (grandParent instanceof JSVariable variable) { + return variable; + } + + if (grandParent instanceof JSAssignmentExpression assignExpr) { + JSExpression jsExpression = assignExpr.getLOperand(); + JSExpression assignedTo = jsExpression instanceof JSDefinitionExpression defExpr ? defExpr.getExpression() : null; + if (assignedTo instanceof JSReferenceExpression) { + return assignedTo; + } + } + if (grandParent instanceof JSExpressionStatement + && firstParent instanceof JSCallExpression call + && call.getMethodExpression() instanceof JSReferenceExpression methodRefExpr) { + + String methodName = methodRefExpr.getReferencedName(); + + if ("each".equals(methodName) || "extend".equals(methodName)) { + JSExpression expression = methodRefExpr.getQualifier(); + + if (expression instanceof JSReferenceExpression qualifierRefExpr + && FN_FUN_NAME.equals(qualifierRefExpr.getReferencedName())) { + expression = qualifierRefExpr.getQualifier(); + } + + if (expression != null && J_QUERY_VAR_NAME.equals(expression.getText())) { + return expression; + } + } + else if ("implement".equals(methodName)) { + if (methodRefExpr.getQualifier() instanceof JSReferenceExpression qualifierRefExpr && parent.getArguments().length == 1) { + return qualifierRefExpr; + } + } + } + + JSExpression[] jsExpressions = parent.getArguments(); + for (int i = 0; i < jsExpressions.length; ++i) { + JSExpression expr = jsExpressions[i]; + + if (expr instanceof JSReferenceExpression + || (expr instanceof JSLiteralExpression && !expr.textContains(' ') && expr.getTextLength() < 100)) { + return expr; + } + else if (expr instanceof JSCallExpression call) { + JSArgumentList argumentList = call.getArgumentList(); + if (argumentList != null) { + jsExpressions = argumentList.getArguments(); + i = -1; + } + } + else if (expr instanceof JSArrayLiteralExpression arrayLiteral) { + jsExpressions = arrayLiteral.getExpressions(); + i = -1; + } + } + return null; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/index/JSTypeEvaluateManager.java b/base-impl/src/main/java/com/intellij/lang/javascript/index/JSTypeEvaluateManager.java index 37ae97a7..67e72ae7 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/index/JSTypeEvaluateManager.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/index/JSTypeEvaluateManager.java @@ -21,63 +21,48 @@ /** * @author Maxim.Mossienko */ -public class JSTypeEvaluateManager -{ - public static boolean isArrayType(String s) - { - if(s == null) - { - return false; - } - return s.endsWith("[]") || - s.indexOf('[') != -1 || - s.startsWith("Vector") && s.indexOf('<') != -1; - } +public class JSTypeEvaluateManager { + public static boolean isArrayType(String s) { + if (s == null) { + return false; + } + return s.endsWith("[]") || s.indexOf('[') != -1 + || s.startsWith("Vector") && s.indexOf('<') != -1; + } - public static String getComponentType(String s) - { - if(s.endsWith("[]")) - { - return s.substring(0, s.length() - 2); - } - else - { - int i = s.indexOf('['); - if(i != -1) - { - return s.substring(i + 1); - } - else if(s.startsWith("Vector")) - { - i = s.indexOf('<'); - int i2 = s.lastIndexOf('>'); - if(i2 == -1) - { - i2 = s.length(); - } - if(i != -1 && i2 != -1 && i2 > i) - { - return s.substring(i + 1, i2); - } - } - } - return s; - } + public static String getComponentType(String s) { + if (s.endsWith("[]")) { + return s.substring(0, s.length() - 2); + } + else { + int i = s.indexOf('['); + if (i != -1) { + return s.substring(i + 1); + } + else if (s.startsWith("Vector")) { + i = s.indexOf('<'); + int i2 = s.lastIndexOf('>'); + if (i2 == -1) { + i2 = s.length(); + } + if (i != -1 && i2 != -1 && i2 > i) { + return s.substring(i + 1, i2); + } + } + } + return s; + } - public static String getInstanceNameByType(String className) - { - if("Document".equals(className)) - { - return "HTMLDocument"; - } - if("Element".equals(className)) - { - return BaseJSSymbolProcessor.HTML_ELEMENT_TYPE_NAME; - } - if("DOMNode".equalsIgnoreCase(className)) - { - return BaseJSSymbolProcessor.HTML_ELEMENT_TYPE_NAME; - } - return className; - } + public static String getInstanceNameByType(String className) { + if ("Document".equals(className)) { + return "HTMLDocument"; + } + if ("Element".equals(className)) { + return BaseJSSymbolProcessor.HTML_ELEMENT_TYPE_NAME; + } + if ("DOMNode".equalsIgnoreCase(className)) { + return BaseJSSymbolProcessor.HTML_ELEMENT_TYPE_NAME; + } + return className; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/index/JavaScriptIndex.java b/base-impl/src/main/java/com/intellij/lang/javascript/index/JavaScriptIndex.java index 7f76b24b..6b66c27a 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/index/JavaScriptIndex.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/index/JavaScriptIndex.java @@ -23,22 +23,18 @@ * @author maxim, yole */ @Deprecated -public final class JavaScriptIndex -{ - public static final String ECMASCRIPT_JS2 = "ECMAScript.js2"; +public final class JavaScriptIndex { + public static final String ECMASCRIPT_JS2 = "ECMAScript.js2"; - public static boolean isFromPredefinedFile(final PsiFile containingFile) - { - return false; - } + public static boolean isFromPredefinedFile(PsiFile containingFile) { + return false; + } - public static PsiElement findSymbolByFileAndNameAndOffset(final String fileName, final String name, final int offset) - { - return null; - } + public static PsiElement findSymbolByFileAndNameAndOffset(String fileName, String name, int offset) { + return null; + } - public static PsiElement findSymbolWithNameAndOffsetInEntry(final String nameId, final int offset) - { - return null; - } + public static PsiElement findSymbolWithNameAndOffsetInEntry(String nameId, int offset) { + return null; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/inspections/qucikFixes/BaseCreateFix.java b/base-impl/src/main/java/com/intellij/lang/javascript/inspections/qucikFixes/BaseCreateFix.java index 47e03606..4f1abc69 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/inspections/qucikFixes/BaseCreateFix.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/inspections/qucikFixes/BaseCreateFix.java @@ -22,7 +22,7 @@ import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; import com.intellij.lang.javascript.psi.util.JSUtils; import consulo.annotation.access.RequiredReadAction; -import consulo.application.ApplicationManager; +import consulo.application.Application; import consulo.codeEditor.Editor; import consulo.document.Document; import consulo.document.util.TextRange; @@ -46,448 +46,389 @@ import consulo.xml.psi.xml.XmlFile; import consulo.xml.psi.xml.XmlTag; import consulo.xml.psi.xml.XmlText; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.Collections; import java.util.Set; /** * @author Maxim.Mossienko */ -public abstract class BaseCreateFix implements LocalQuickFix -{ - private static final String ANY_TYPE = "*"; - private static final String SCRIPT_TAG_NAME = "Script"; - - @Override - @RequiredReadAction - public void applyFix(@Nonnull Project project, @Nonnull ProblemDescriptor descriptor) - { - final PsiElement psiElement = descriptor.getPsiElement(); - PsiFile file = psiElement.getContainingFile(); - PsiFile realFile = file.getContext() != null ? file.getContext().getContainingFile() : file; - Set features = JavaScriptVersionUtil.getFeatures(psiElement); - - JSReferenceExpression referenceExpression = (JSReferenceExpression) psiElement.getParent(); - final JSExpression qualifier = referenceExpression.getQualifier(); - PsiElement predefinedAnchor = null; - - boolean classFeature = features.contains(JavaScriptFeature.CLASS); - if(qualifier != null && classFeature) - { - PsiElement type = getType(qualifier, file, features); - if(type == null) - { - return; // can not resolve - } - - if(type.isWritable()) - { - if(type instanceof XmlBackedJSClassImpl) - { - type = type.getParent().getContainingFile(); - } - final PsiElement element = JSResolveUtil.unwrapProxy(type); - - if(element instanceof JSClass) - { - file = type.getContainingFile(); - realFile = file; - predefinedAnchor = element.getLastChild().getPrevSibling(); - } - else if(element instanceof XmlFile) - { - file = type.getContainingFile(); - realFile = file; - predefinedAnchor = element; - } - } - } - - Editor editor = getEditor(project, realFile); - if(editor == null) - { - return; - } - - PsiElement anchor = predefinedAnchor != null ? predefinedAnchor : JSUtils.findStatementAnchor(referenceExpression, file); - boolean insertAtEnd = false; - PsiElement anchorParent = null; - - String prefix = ""; - String suffix = ""; - - if(anchor != null && classFeature) - { - anchorParent = anchor.getParent(); - while(anchorParent != null && !(anchorParent instanceof JSClass) && !(anchorParent instanceof JSFile)) - { - anchor = anchorParent; - anchorParent = anchor.getParent(); - } - - insertAtEnd = anchorParent instanceof JSClass; - - XmlFile contextFile = null; - if(anchorParent instanceof JSFile && anchorParent.getContext() != null) - { - final PsiElement context = anchorParent.getContext(); - if(context instanceof XmlAttributeValue || context instanceof XmlText && !(SCRIPT_TAG_NAME.equals(((XmlTag) context.getParent()).getLocalName()))) - { - contextFile = (XmlFile) context.getContainingFile(); - } - } - else if(realFile instanceof XmlFile) - { - contextFile = (XmlFile) realFile; - } - - if(contextFile != null) - { - final XmlTag rootTag = contextFile.getDocument().getRootTag(); - JSClass jsClass = XmlBackedJSClassImpl.getXmlBackedClass(rootTag); - JSFile jsFile = ((XmlBackedJSClassImpl) jsClass).findFirstScriptTag(); - - if(jsFile != null) - { - anchor = jsFile.getFirstChild(); - while(anchor instanceof PsiWhiteSpace || anchor instanceof PsiComment || anchor instanceof JSImportStatement) - { - PsiElement nextSibling = anchor.getNextSibling(); - if(nextSibling == null) - { - break; - } - anchor = nextSibling; - } - } - else - { - jsFile = ((XmlBackedJSClassImpl) jsClass).createScriptTag(); - Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(contextFile.getContainingFile()); - PsiDocumentManager.getInstance(file.getProject()).doPostponedOperationsAndUnblockDocument(document); - anchor = PsiTreeUtil.firstChild(jsFile.getContext()); - insertAtEnd = true; - } - } - } - - if(anchor != null) - { - final TemplateManager templateManager = TemplateManager.getInstance(project); - Template template = templateManager.createTemplate("", ""); - - if(prefix.length() > 0) - { - template.addTextSegment(prefix); - } - if(insertAtEnd) - { - template.addTextSegment("\n"); - } - template.setToReformat(true); - - boolean isStatic = false; - if(classFeature) - { - if(qualifier != null) - { - if(qualifier instanceof JSReferenceExpression) - { - PsiElement qualifierResolve = ((JSReferenceExpression) qualifier).resolve(); - - if(qualifierResolve instanceof JSClass || qualifierResolve instanceof XmlFile) - { - isStatic = true; - } - } - } - else - { - JSAttributeListOwner attributeListOwner = PsiTreeUtil.getNonStrictParentOfType(psiElement, JSAttributeListOwner.class); - if(attributeListOwner instanceof JSVariable) - { - PsiElement grandParent = JSResolveUtil.findParent(attributeListOwner); - - if(!(grandParent instanceof JSFile) && !(grandParent instanceof JSClass)) - { - attributeListOwner = PsiTreeUtil.getNonStrictParentOfType(grandParent, JSAttributeListOwner.class); - } - } - if(attributeListOwner != null) - { - JSAttributeList attributeList = attributeListOwner.getAttributeList(); - if(attributeList != null && attributeList.hasModifier(JSAttributeList.ModifierType.STATIC)) - { - isStatic = true; - } - } - } - } - - int cdataStartOffset = 0, at; - if(!insertAtEnd && anchor instanceof PsiWhiteSpace && (at = anchor.getText().indexOf(" 0) - { - template.addTextSegment(suffix); - } - - if(!insertAtEnd && anchor instanceof PsiWhiteSpace && anchor.textToCharArray()[0] == '\n' && anchor.getPrevSibling() instanceof PsiComment) - { - insertAtEnd = true; - } - - final TextRange anchorRange = anchor.getTextRange(); - int offset = insertAtEnd ? anchorRange.getEndOffset() : anchorRange.getStartOffset(); - - if(file != realFile || file instanceof XmlFile) - { - final PsiFile anchorContainingFile = anchor.getContainingFile(); - final PsiElement anchorFileContext = anchorContainingFile.getContext(); - - if(anchorFileContext != null) - { - if(anchorFileContext instanceof XmlText) - { - if(cdataStartOffset != 0) - { // - offset += cdataStartOffset; - } - else - { - offset += ((XmlText) anchorFileContext).displayToPhysical(0); - } - } - offset += anchorFileContext.getTextOffset(); - } - } - editor.getCaretModel().moveToOffset(offset); - templateManager.startTemplate(editor, template); - } - } - - @Nullable - public static Editor getEditor(final Project project, final PsiFile realFile) - { - if(!FileModificationService.getInstance().prepareFileForWrite(realFile)) - { - return null; - } - - return FileEditorManager.getInstance(project).openTextEditor(OpenFileDescriptorFactory.getInstance(project).builder(realFile.getVirtualFile()).build(), true); - } - - @RequiredReadAction - protected abstract void buildTemplate(final Template template, - JSReferenceExpression referenceExpression, - Set features, - boolean staticContext, - PsiFile file, - PsiElement anchorParent); - - private static String getTypeOfValue(final JSExpression passedParameterValue, final PsiFile file, Set features) - { - final PsiElement type = getType(passedParameterValue, file, features); - return type != null ? type instanceof JSClass ? ((JSClass) type).getQualifiedName() : ((PsiNamedElement) type).getName() : ANY_TYPE; - } - - @RequiredReadAction - static PsiElement getType(final JSExpression passedParameterValue, final PsiFile file, Set features) - { - if(passedParameterValue instanceof JSReferenceExpression) - { - JavaScriptType type = passedParameterValue.getType(); - - PsiElement targetElement = type.getTargetElement(); - if(targetElement instanceof JSClass) - { - return targetElement; - } - } - return null; - } - - protected static JSExpression addAccessModifier(final Template template, final JSReferenceExpression referenceExpression, final boolean ecma, boolean staticContext) - { - final JSExpression qualifier = referenceExpression.getQualifier(); - - if(ecma) - { - if((qualifier == null || qualifier instanceof JSThisExpression)) - { - template.addTextSegment("private "); - } - if(staticContext) - { - template.addTextSegment("static "); - } - } - return qualifier; - } - - private int uniqueCounter; - - protected void addCompletionVar(final Template template) - { - final Expression paramTypeExpr = new MacroCallNode(MacroFactory.createMacro("complete")); - template.addVariable("__Type" + (uniqueCounter++), paramTypeExpr, paramTypeExpr, true); - } - - protected void addSemicolonSegment(final Template template, final PsiFile file) - { - final String semicolon = JSChangeUtil.getSemicolon(file.getProject()); - if(semicolon.length() > 0) - { - template.addTextSegment(semicolon); - } - } - - public static void guessExprTypeAndAddSuchVariable(final JSExpression passedParameterValue, final Template template, final String var1, final PsiFile file, final Set features) - { - String type = getTypeOfValue(passedParameterValue, file, features); - - if(ApplicationManager.getApplication().isUnitTestMode()) - { - template.addTextSegment(type); - } - else - { - final MyExpression paramTypeExpr = new MyExpression(type); - template.addVariable(var1 + "Type", paramTypeExpr, paramTypeExpr, true); - } - } - - protected void guessTypeAndAddTemplateVariable(Template template, JSExpression referenceExpression, PsiFile file) - { - String type = null; - PsiElement elementForWhichExprTypeToEvaluate = null; - PsiElement parent = referenceExpression.getParent(); - boolean isCall = false; - - if(parent instanceof JSCallExpression) - { - isCall = true; - parent = parent.getParent(); - } - - if(parent instanceof JSDefinitionExpression) - { - PsiElement grandParent = parent.getParent(); - - if(grandParent instanceof JSAssignmentExpression) - { - elementForWhichExprTypeToEvaluate = ((JSAssignmentExpression) grandParent).getROperand(); - } - } - else if(parent instanceof JSReturnStatement) - { - final JSFunction fun = PsiTreeUtil.getParentOfType(referenceExpression, JSFunction.class); - - if(fun != null) - { - final String typeString = fun.getReturnTypeString(); - - if(typeString != null) - { - type = typeString; - } - } - } - else if(parent instanceof JSExpressionStatement && isCall) - { - type = "void"; - } - else if(parent instanceof JSVariable) - { - type = ((JSVariable) parent).getTypeString(); - } - else if(parent instanceof JSArgumentList) - { - JSParameter parameter = JSResolveUtil.findParameterForUsedArgument(isCall ? (JSExpression) referenceExpression.getParent() : referenceExpression, (JSArgumentList) parent); - if(parameter != null) - { - type = parameter.getTypeString(); - } - } - else if(parent instanceof JSAssignmentExpression) - { - JSExpression lOperand = ((JSAssignmentExpression) parent).getLOperand(); - if(lOperand != null) - { - type = getTypeOfValue(lOperand, file, Collections.singleton(JavaScriptFeature.CLASS)); - } - } - - String expressionType = elementForWhichExprTypeToEvaluate instanceof JSExpression ? JSResolveUtil.getExpressionType((JSExpression) elementForWhichExprTypeToEvaluate, file) : null; - if(expressionType != null && !expressionType.equals("*")) - { - type = expressionType; - } - if(type == null) - { - addCompletionVar(template); - } - else - { - MyExpression expression = new MyExpression(type); - template.addVariable("__type" + referenceExpression.getText(), expression, expression, true); - } - } - - @Nullable - protected static JSClass findClass(PsiFile file, final PsiElement anchorParent) - { - if(anchorParent instanceof JSClass) - { - return (JSClass) anchorParent; - } - - if(file instanceof JSFile) - { - return JSResolveUtil.getXmlBackedClass((JSFile) file); - } - return null; - } - - public static class MyExpression extends Expression - { - TextResult result; - private final String myVar1; - - public MyExpression(final String var1) - { - myVar1 = var1; - result = new TextResult(myVar1); - } - - @Override - public Result calculateResult(ExpressionContext context) - { - return result; - } - - @Override - public Result calculateQuickResult(ExpressionContext context) - { - return result; - } - - @Override - public LookupElement[] calculateLookupItems(ExpressionContext context) - { - return LookupItem.EMPTY_ARRAY; - } - } +public abstract class BaseCreateFix implements LocalQuickFix { + private static final String ANY_TYPE = "*"; + private static final String SCRIPT_TAG_NAME = "Script"; + + @Override + @RequiredReadAction + public void applyFix(@Nonnull Project project, @Nonnull ProblemDescriptor descriptor) { + PsiElement psiElement = descriptor.getPsiElement(); + PsiFile file = psiElement.getContainingFile(); + PsiFile realFile = file.getContext() != null ? file.getContext().getContainingFile() : file; + Set features = JavaScriptVersionUtil.getFeatures(psiElement); + + JSReferenceExpression referenceExpression = (JSReferenceExpression)psiElement.getParent(); + JSExpression qualifier = referenceExpression.getQualifier(); + PsiElement predefinedAnchor = null; + + boolean classFeature = features.contains(JavaScriptFeature.CLASS); + if (qualifier != null && classFeature) { + PsiElement type = getType(qualifier, file, features); + if (type == null) { + return; // can not resolve + } + + if (type.isWritable()) { + if (type instanceof XmlBackedJSClassImpl) { + type = type.getParent().getContainingFile(); + } + PsiElement element = JSResolveUtil.unwrapProxy(type); + + if (element instanceof JSClass) { + file = type.getContainingFile(); + realFile = file; + predefinedAnchor = element.getLastChild().getPrevSibling(); + } + else if (element instanceof XmlFile) { + file = type.getContainingFile(); + realFile = file; + predefinedAnchor = element; + } + } + } + + Editor editor = getEditor(project, realFile); + if (editor == null) { + return; + } + + PsiElement anchor = predefinedAnchor != null ? predefinedAnchor : JSUtils.findStatementAnchor(referenceExpression, file); + boolean insertAtEnd = false; + PsiElement anchorParent = null; + + String prefix = ""; + String suffix = ""; + + if (anchor != null && classFeature) { + anchorParent = anchor.getParent(); + while (anchorParent != null && !(anchorParent instanceof JSClass) && !(anchorParent instanceof JSFile)) { + anchor = anchorParent; + anchorParent = anchor.getParent(); + } + + insertAtEnd = anchorParent instanceof JSClass; + + XmlFile contextFile = null; + if (anchorParent instanceof JSFile && anchorParent.getContext() != null) { + PsiElement context = anchorParent.getContext(); + if (context instanceof XmlAttributeValue + || context instanceof XmlText && !(SCRIPT_TAG_NAME.equals(((XmlTag)context.getParent()).getLocalName()))) { + contextFile = (XmlFile)context.getContainingFile(); + } + } + else if (realFile instanceof XmlFile xmlFile) { + contextFile = xmlFile; + } + + if (contextFile != null) { + XmlTag rootTag = contextFile.getDocument().getRootTag(); + JSClass jsClass = XmlBackedJSClassImpl.getXmlBackedClass(rootTag); + JSFile jsFile = ((XmlBackedJSClassImpl)jsClass).findFirstScriptTag(); + + if (jsFile != null) { + anchor = jsFile.getFirstChild(); + while (anchor instanceof PsiWhiteSpace || anchor instanceof PsiComment || anchor instanceof JSImportStatement) { + PsiElement nextSibling = anchor.getNextSibling(); + if (nextSibling == null) { + break; + } + anchor = nextSibling; + } + } + else { + jsFile = ((XmlBackedJSClassImpl)jsClass).createScriptTag(); + Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(contextFile.getContainingFile()); + PsiDocumentManager.getInstance(file.getProject()).doPostponedOperationsAndUnblockDocument(document); + anchor = PsiTreeUtil.firstChild(jsFile.getContext()); + insertAtEnd = true; + } + } + } + + if (anchor != null) { + TemplateManager templateManager = TemplateManager.getInstance(project); + Template template = templateManager.createTemplate("", ""); + + if (prefix.length() > 0) { + template.addTextSegment(prefix); + } + if (insertAtEnd) { + template.addTextSegment("\n"); + } + template.setToReformat(true); + + boolean isStatic = false; + if (classFeature) { + if (qualifier != null) { + if (qualifier instanceof JSReferenceExpression qualifierRefExpr) { + PsiElement qualifierResolve = qualifierRefExpr.resolve(); + + if (qualifierResolve instanceof JSClass || qualifierResolve instanceof XmlFile) { + isStatic = true; + } + } + } + else { + JSAttributeListOwner attributeListOwner = PsiTreeUtil.getNonStrictParentOfType(psiElement, JSAttributeListOwner.class); + if (attributeListOwner instanceof JSVariable) { + PsiElement grandParent = JSResolveUtil.findParent(attributeListOwner); + + if (!(grandParent instanceof JSFile) && !(grandParent instanceof JSClass)) { + attributeListOwner = PsiTreeUtil.getNonStrictParentOfType(grandParent, JSAttributeListOwner.class); + } + } + if (attributeListOwner != null) { + JSAttributeList attributeList = attributeListOwner.getAttributeList(); + if (attributeList != null && attributeList.hasModifier(JSAttributeList.ModifierType.STATIC)) { + isStatic = true; + } + } + } + } + + int cdataStartOffset = 0, at; + if (!insertAtEnd && anchor instanceof PsiWhiteSpace && (at = anchor.getText().indexOf(" 0) { + template.addTextSegment(suffix); + } + + if (!insertAtEnd + && anchor instanceof PsiWhiteSpace + && anchor.textToCharArray()[0] == '\n' + && anchor.getPrevSibling() instanceof PsiComment) { + insertAtEnd = true; + } + + TextRange anchorRange = anchor.getTextRange(); + int offset = insertAtEnd ? anchorRange.getEndOffset() : anchorRange.getStartOffset(); + + if (file != realFile || file instanceof XmlFile) { + PsiFile anchorContainingFile = anchor.getContainingFile(); + PsiElement anchorFileContext = anchorContainingFile.getContext(); + + if (anchorFileContext != null) { + if (anchorFileContext instanceof XmlText xmlText) { + if (cdataStartOffset != 0) { // + offset += cdataStartOffset; + } + else { + offset += xmlText.displayToPhysical(0); + } + } + offset += anchorFileContext.getTextOffset(); + } + } + editor.getCaretModel().moveToOffset(offset); + templateManager.startTemplate(editor, template); + } + } + + @Nullable + public static Editor getEditor(Project project, PsiFile realFile) { + if (!FileModificationService.getInstance().prepareFileForWrite(realFile)) { + return null; + } + + return FileEditorManager.getInstance(project) + .openTextEditor(OpenFileDescriptorFactory.getInstance(project).builder(realFile.getVirtualFile()).build(), true); + } + + @RequiredReadAction + protected abstract void buildTemplate( + Template template, + JSReferenceExpression referenceExpression, + Set features, + boolean staticContext, + PsiFile file, + PsiElement anchorParent + ); + + @RequiredReadAction + private static String getTypeOfValue(JSExpression passedParameterValue, PsiFile file, Set features) { + PsiElement type = getType(passedParameterValue, file, features); + return type != null ? type instanceof JSClass jsClass ? jsClass.getQualifiedName() : ((PsiNamedElement)type).getName() : ANY_TYPE; + } + + @RequiredReadAction + static PsiElement getType(JSExpression passedParameterValue, PsiFile file, Set features) { + if (passedParameterValue instanceof JSReferenceExpression) { + JavaScriptType type = passedParameterValue.getType(); + + PsiElement targetElement = type.getTargetElement(); + if (targetElement instanceof JSClass) { + return targetElement; + } + } + return null; + } + + protected static JSExpression addAccessModifier( + Template template, + JSReferenceExpression referenceExpression, + boolean ecma, + boolean staticContext + ) { + JSExpression qualifier = referenceExpression.getQualifier(); + + if (ecma) { + if (qualifier == null || qualifier instanceof JSThisExpression) { + template.addTextSegment("private "); + } + if (staticContext) { + template.addTextSegment("static "); + } + } + return qualifier; + } + + private int uniqueCounter; + + protected void addCompletionVar(Template template) { + Expression paramTypeExpr = new MacroCallNode(MacroFactory.createMacro("complete")); + template.addVariable("__Type" + (uniqueCounter++), paramTypeExpr, paramTypeExpr, true); + } + + protected void addSemicolonSegment(Template template, PsiFile file) { + String semicolon = JSChangeUtil.getSemicolon(file.getProject()); + if (semicolon.length() > 0) { + template.addTextSegment(semicolon); + } + } + + @RequiredReadAction + public static void guessExprTypeAndAddSuchVariable( + JSExpression passedParameterValue, + Template template, + String var1, + PsiFile file, + Set features + ) { + String type = getTypeOfValue(passedParameterValue, file, features); + + if (Application.get().isUnitTestMode()) { + template.addTextSegment(type); + } + else { + MyExpression paramTypeExpr = new MyExpression(type); + template.addVariable(var1 + "Type", paramTypeExpr, paramTypeExpr, true); + } + } + + @RequiredReadAction + protected void guessTypeAndAddTemplateVariable(Template template, JSExpression referenceExpression, PsiFile file) { + String type = null; + PsiElement elementForWhichExprTypeToEvaluate = null; + PsiElement parent = referenceExpression.getParent(); + boolean isCall = false; + + if (parent instanceof JSCallExpression) { + isCall = true; + parent = parent.getParent(); + } + + if (parent instanceof JSDefinitionExpression definition) { + if (definition.getParent() instanceof JSAssignmentExpression assignment) { + elementForWhichExprTypeToEvaluate = assignment.getROperand(); + } + } + else if (parent instanceof JSReturnStatement) { + JSFunction fun = PsiTreeUtil.getParentOfType(referenceExpression, JSFunction.class); + + if (fun != null) { + String typeString = fun.getReturnTypeString(); + + if (typeString != null) { + type = typeString; + } + } + } + else if (parent instanceof JSExpressionStatement && isCall) { + type = "void"; + } + else if (parent instanceof JSVariable variable) { + type = variable.getTypeString(); + } + else if (parent instanceof JSArgumentList argumentList) { + JSParameter parameter = JSResolveUtil.findParameterForUsedArgument( + isCall ? (JSExpression)referenceExpression.getParent() : referenceExpression, + argumentList + ); + if (parameter != null) { + type = parameter.getTypeString(); + } + } + else if (parent instanceof JSAssignmentExpression assignment) { + JSExpression lOperand = assignment.getLOperand(); + if (lOperand != null) { + type = getTypeOfValue(lOperand, file, Collections.singleton(JavaScriptFeature.CLASS)); + } + } + + String expressionType = elementForWhichExprTypeToEvaluate instanceof JSExpression expression + ? JSResolveUtil.getExpressionType(expression, file) + : null; + if (expressionType != null && !expressionType.equals("*")) { + type = expressionType; + } + if (type == null) { + addCompletionVar(template); + } + else { + MyExpression expression = new MyExpression(type); + template.addVariable("__type" + referenceExpression.getText(), expression, expression, true); + } + } + + @Nullable + protected static JSClass findClass(PsiFile file, PsiElement anchorParent) { + return anchorParent instanceof JSClass jsClass + ? jsClass + : file instanceof JSFile jsFile + ? JSResolveUtil.getXmlBackedClass(jsFile) + : null; + } + + public static class MyExpression extends Expression { + private TextResult result; + private final String myVar1; + + public MyExpression(String var1) { + myVar1 = var1; + result = new TextResult(myVar1); + } + + @Override + public Result calculateResult(ExpressionContext context) { + return result; + } + + @Override + public Result calculateQuickResult(ExpressionContext context) { + return result; + } + + @Override + public LookupElement[] calculateLookupItems(ExpressionContext context) { + return LookupItem.EMPTY_ARRAY; + } + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/inspections/qucikFixes/CreateJSFunctionOrMethodFix.java b/base-impl/src/main/java/com/intellij/lang/javascript/inspections/qucikFixes/CreateJSFunctionOrMethodFix.java index 4a307112..91880392 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/inspections/qucikFixes/CreateJSFunctionOrMethodFix.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/inspections/qucikFixes/CreateJSFunctionOrMethodFix.java @@ -24,6 +24,7 @@ import consulo.annotation.access.RequiredReadAction; import consulo.javascript.inspections.qucikFixes.CreateJSFunctionFixBase; import consulo.javascript.language.JavaScriptFeature; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.editor.template.Expression; import consulo.language.editor.template.Template; import consulo.language.psi.PsiElement; @@ -31,93 +32,93 @@ import java.util.Set; -public class CreateJSFunctionOrMethodFix extends CreateJSFunctionFixBase -{ - protected final boolean myIsMethod; - - public CreateJSFunctionOrMethodFix(String name, boolean isMethod) - { - super(name, isMethod ? "javascript.create.method.intention.name" : "javascript.create.function.intention.name"); - myIsMethod = isMethod; - } - - @Override - protected void writeFunctionAndName(Template template, String createdMethodName, Set features) - { - boolean ecma = features.contains(JavaScriptFeature.CLASS); - if(!myIsMethod || ecma) - { - template.addTextSegment("function "); - } - template.addTextSegment(createdMethodName); - if(myIsMethod && !ecma) - { - template.addTextSegment(" = function "); - } - } - - @Override - protected void addParameters(Template template, JSReferenceExpression referenceExpression, PsiFile file, Set features) - { - JSCallExpression methodInvokation = (JSCallExpression) referenceExpression.getParent(); - final JSArgumentList list = methodInvokation.getArgumentList(); - final JSExpression[] expressions = list.getArguments(); - int paramCount = expressions.length; - - for(int i = 0; i < paramCount; ++i) - { - if(i != 0) - { - template.addTextSegment(", "); - } - String var = null; - - final JSExpression passedParameterValue = expressions[i]; - if(passedParameterValue instanceof JSReferenceExpression) - { - var = ((JSReferenceExpression) passedParameterValue).getReferencedName(); - } - - if(var == null || var.length() == 0) - { - var = "param" + (i != 0 ? Integer.toString(i + 1) : ""); - } - - final String var1 = var; - Expression expression = new MyExpression(var1); - - template.addVariable(var, expression, expression, true); - if(features.contains(JavaScriptFeature.CLASS)) - { - template.addTextSegment(":"); - BaseCreateFix.guessExprTypeAndAddSuchVariable(passedParameterValue, template, var1, file, features); - } - } - - } - - @Override - protected void addReturnType(Template template, JSReferenceExpression referenceExpression, PsiFile file) - { - guessTypeAndAddTemplateVariable(template, referenceExpression, file); - } - - @Override - protected void addBody(Template template, JSReferenceExpression refExpr, PsiFile file) - { - template.addEndVariable(); - } - - @RequiredReadAction - @Override - protected void buildTemplate(final Template template, JSReferenceExpression referenceExpression, Set features, boolean staticContext, - PsiFile file, PsiElement anchorParent) - { - super.buildTemplate(template, referenceExpression, features, staticContext, file, anchorParent); - - if(myIsMethod && !features.contains(JavaScriptFeature.CLASS)) - { - addSemicolonSegment(template, file); - } - } +public class CreateJSFunctionOrMethodFix extends CreateJSFunctionFixBase { + protected final boolean myIsMethod; + + public CreateJSFunctionOrMethodFix(String name, boolean isMethod) { + super( + isMethod + ? JavaScriptLocalize.javascriptCreateMethodIntentionName(name) + : JavaScriptLocalize.javascriptCreateFunctionIntentionName(name) + ); + myIsMethod = isMethod; + } + + @Override + protected void writeFunctionAndName(Template template, String createdMethodName, Set features) { + boolean ecma = features.contains(JavaScriptFeature.CLASS); + if (!myIsMethod || ecma) { + template.addTextSegment("function "); + } + template.addTextSegment(createdMethodName); + if (myIsMethod && !ecma) { + template.addTextSegment(" = function "); + } + } + + @Override + @RequiredReadAction + protected void addParameters( + Template template, + JSReferenceExpression referenceExpression, + PsiFile file, + Set features + ) { + JSCallExpression methodInvokation = (JSCallExpression)referenceExpression.getParent(); + JSArgumentList list = methodInvokation.getArgumentList(); + JSExpression[] expressions = list.getArguments(); + int paramCount = expressions.length; + + for (int i = 0; i < paramCount; ++i) { + if (i != 0) { + template.addTextSegment(", "); + } + String var = null; + + JSExpression passedParameterValue = expressions[i]; + if (passedParameterValue instanceof JSReferenceExpression parameterRefExpr) { + var = parameterRefExpr.getReferencedName(); + } + + if (var == null || var.length() == 0) { + var = "param" + (i != 0 ? Integer.toString(i + 1) : ""); + } + + String var1 = var; + Expression expression = new MyExpression(var1); + + template.addVariable(var, expression, expression, true); + if (features.contains(JavaScriptFeature.CLASS)) { + template.addTextSegment(":"); + BaseCreateFix.guessExprTypeAndAddSuchVariable(passedParameterValue, template, var1, file, features); + } + } + } + + @Override + @RequiredReadAction + protected void addReturnType(Template template, JSReferenceExpression referenceExpression, PsiFile file) { + guessTypeAndAddTemplateVariable(template, referenceExpression, file); + } + + @Override + protected void addBody(Template template, JSReferenceExpression refExpr, PsiFile file) { + template.addEndVariable(); + } + + @RequiredReadAction + @Override + protected void buildTemplate( + Template template, + JSReferenceExpression referenceExpression, + Set features, + boolean staticContext, + PsiFile file, PsiElement anchorParent + ) { + super.buildTemplate(template, referenceExpression, features, staticContext, file, anchorParent); + + if (myIsMethod && !features.contains(JavaScriptFeature.CLASS)) { + addSemicolonSegment(template, file); + } + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/parsing/JSDocParsing.java b/base-impl/src/main/java/com/intellij/lang/javascript/parsing/JSDocParsing.java index 6d661592..838d44c8 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/parsing/JSDocParsing.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/parsing/JSDocParsing.java @@ -16,135 +16,114 @@ package com.intellij.lang.javascript.parsing; -import org.jetbrains.annotations.NonNls; -import consulo.language.parser.PsiBuilder; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.JSDocTokenTypes; import com.intellij.lang.javascript.JSTokenTypes; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.ast.IElementType; +import consulo.language.parser.PsiBuilder; +import org.jetbrains.annotations.NonNls; /** * @author Maxim.Mossienko - * Date: Aug 5, 2008 - * Time: 3:55:54 PM + * Date: Aug 5, 2008 + * Time: 3:55:54 PM */ -public class JSDocParsing -{ - public static void parseJSDoc(final PsiBuilder builder) - { - final PsiBuilder.Marker root = builder.mark(); - - while(!builder.eof()) - { - final IElementType tokenType = builder.getTokenType(); - - if(tokenType == JSDocTokenTypes.DOC_TAG_NAME) - { - if(parseDocTag(builder)) - { - continue; - } - } - - builder.advanceLexer(); - } - - root.done(JSTokenTypes.DOC_COMMENT); - } - - private static boolean parseDocTag(final PsiBuilder builder) - { - assert builder.getTokenType() == JSDocTokenTypes.DOC_TAG_NAME; - final PsiBuilder.Marker docTagMarker = builder.mark(); - - try - { - final @NonNls String tagName = builder.getTokenText(); - - builder.advanceLexer(); - if("@param".equals(tagName)) - { - - if(isInvalidTokenType(builder)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.doc.tag.name")); - return false; - } - - String currentText = builder.getTokenText(); - if(currentText != null && currentText.startsWith("{")) - { - createDocTagValue(builder); - builder.getTokenType(); - } - builder.advanceLexer(); - currentText = builder.getTokenText(); - if(currentText != null) - { - if(currentText.equals(":")) - { - builder.advanceLexer(); - } - else if(!currentText.startsWith("{")) - { - return true; - } - } - - if(isInvalidTokenType(builder)) - { - return true; - } - } - else - { - final boolean hasDocTagValue = isToCreateDocTagValue(tagName); - if(!hasDocTagValue) - { - return true; - } - - if(isInvalidTokenType(builder)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.doc.tag.value")); - return false; - } - } - - createDocTagValue(builder); - } - finally - { - docTagMarker.done(JSDocTokenTypes.DOC_TAG); - } - - return true; - } - - private static void createDocTagValue(final PsiBuilder builder) - { - PsiBuilder.Marker marker = builder.mark(); - builder.advanceLexer(); - marker.done(JSDocTokenTypes.DOC_TAG_VALUE); - } - - private static boolean isInvalidTokenType(final PsiBuilder builder) - { - final IElementType tokenType = builder.getTokenType(); - return builder.eof() || tokenType == JSDocTokenTypes.DOC_COMMENT_LEADING_ASTERISK || tokenType == JSDocTokenTypes.DOC_COMMENT_END; - } - - private static boolean isToCreateDocTagValue(final @NonNls String tokenText) - { - return tokenText.equals("@see") || - tokenText.equals("@class") || - tokenText.equals("@member") || - tokenText.equals("@requires") || - tokenText.equals("@type") || - tokenText.equals("@copy") || - tokenText.equals("@extends") || - tokenText.equals("@base") || - tokenText.equals("@base") || - tokenText.equals("@returns"); - } +public class JSDocParsing { + public static void parseJSDoc(PsiBuilder builder) { + PsiBuilder.Marker root = builder.mark(); + + while (!builder.eof()) { + IElementType tokenType = builder.getTokenType(); + + if (tokenType == JSDocTokenTypes.DOC_TAG_NAME) { + if (parseDocTag(builder)) { + continue; + } + } + + builder.advanceLexer(); + } + + root.done(JSTokenTypes.DOC_COMMENT); + } + + private static boolean parseDocTag(PsiBuilder builder) { + assert builder.getTokenType() == JSDocTokenTypes.DOC_TAG_NAME; + PsiBuilder.Marker docTagMarker = builder.mark(); + + try { + @NonNls String tagName = builder.getTokenText(); + + builder.advanceLexer(); + if ("@param".equals(tagName)) { + + if (isInvalidTokenType(builder)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedDocTagName()); + return false; + } + + String currentText = builder.getTokenText(); + if (currentText != null && currentText.startsWith("{")) { + createDocTagValue(builder); + builder.getTokenType(); + } + builder.advanceLexer(); + currentText = builder.getTokenText(); + if (currentText != null) { + if (currentText.equals(":")) { + builder.advanceLexer(); + } + else if (!currentText.startsWith("{")) { + return true; + } + } + + if (isInvalidTokenType(builder)) { + return true; + } + } + else { + boolean hasDocTagValue = isToCreateDocTagValue(tagName); + if (!hasDocTagValue) { + return true; + } + + if (isInvalidTokenType(builder)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedDocTagValue()); + return false; + } + } + + createDocTagValue(builder); + } + finally { + docTagMarker.done(JSDocTokenTypes.DOC_TAG); + } + + return true; + } + + private static void createDocTagValue(PsiBuilder builder) { + PsiBuilder.Marker marker = builder.mark(); + builder.advanceLexer(); + marker.done(JSDocTokenTypes.DOC_TAG_VALUE); + } + + private static boolean isInvalidTokenType(PsiBuilder builder) { + IElementType tokenType = builder.getTokenType(); + return builder.eof() || tokenType == JSDocTokenTypes.DOC_COMMENT_LEADING_ASTERISK || tokenType == JSDocTokenTypes.DOC_COMMENT_END; + } + + private static boolean isToCreateDocTagValue(@NonNls String tokenText) { + return tokenText.equals("@see") || + tokenText.equals("@class") || + tokenText.equals("@member") || + tokenText.equals("@requires") || + tokenText.equals("@type") || + tokenText.equals("@copy") || + tokenText.equals("@extends") || + tokenText.equals("@base") || + tokenText.equals("@base") || + tokenText.equals("@returns"); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSArgumentListImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSArgumentListImpl.java index ee186ac3..9863dda9 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSArgumentListImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSArgumentListImpl.java @@ -24,36 +24,30 @@ import consulo.language.util.IncorrectOperationException; import consulo.language.ast.ASTNode; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * User: max - * Date: Jan 30, 2005 - * Time: 9:15:02 PM + * @author max + * @since 2005-01-30 */ -public class JSArgumentListImpl extends JSElementImpl implements JSArgumentList -{ - public JSArgumentListImpl(final ASTNode node) - { - super(node); - } +public class JSArgumentListImpl extends JSElementImpl implements JSArgumentList { + public JSArgumentListImpl(ASTNode node) { + super(node); + } - @Override - public JSExpression[] getArguments() - { - return findChildrenByClass(JSExpression.class); - } + @Override + public JSExpression[] getArguments() { + return findChildrenByClass(JSExpression.class); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSArgumentList(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSArgumentList(this); + } - @Override - public void delete() throws IncorrectOperationException - { - PsiElement element = getParent(); - element.replace(((JSCallExpression) element).getMethodExpression()); - } + @Override + public void delete() throws IncorrectOperationException { + PsiElement element = getParent(); + element.replace(((JSCallExpression)element).getMethodExpression()); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSArrayLiteralExpressionImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSArrayLiteralExpressionImpl.java index a9e5b482..6b8860bb 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSArrayLiteralExpressionImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSArrayLiteralExpressionImpl.java @@ -20,61 +20,52 @@ import com.intellij.lang.javascript.psi.JSArrayLiteralExpression; import com.intellij.lang.javascript.psi.JSElementVisitor; import com.intellij.lang.javascript.psi.JSExpression; +import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.ASTNode; import consulo.language.ast.IElementType; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; + import java.util.ArrayList; import java.util.List; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 11:32:23 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSArrayLiteralExpressionImpl extends JSExpressionImpl implements JSArrayLiteralExpression -{ - public JSArrayLiteralExpressionImpl(final ASTNode node) - { - super(node); - } +public class JSArrayLiteralExpressionImpl extends JSExpressionImpl implements JSArrayLiteralExpression { + public JSArrayLiteralExpressionImpl(ASTNode node) { + super(node); + } - @Override - public JSExpression[] getExpressions() - { - List result = new ArrayList(); - ASTNode child = getNode().getFirstChildNode(); - boolean wasExpression = false; - while(child != null) - { - final IElementType type = child.getElementType(); - if(child.getPsi() instanceof JSExpression) - { - result.add((JSExpression) child.getPsi()); - wasExpression = true; - } - else if(type == JSTokenTypes.COMMA) - { - if(wasExpression) - { - wasExpression = false; - } - else - { - result.add(null); // Skipped expression like [a,,b] - } - } - child = child.getTreeNext(); - } + @Override + @RequiredReadAction + public JSExpression[] getExpressions() { + List result = new ArrayList<>(); + ASTNode child = getNode().getFirstChildNode(); + boolean wasExpression = false; + while (child != null) { + IElementType type = child.getElementType(); + if (child.getPsi() instanceof JSExpression jsExpression) { + result.add(jsExpression); + wasExpression = true; + } + else if (type == JSTokenTypes.COMMA) { + if (wasExpression) { + wasExpression = false; + } + else { + result.add(null); // Skipped expression like [a,,b] + } + } + child = child.getTreeNext(); + } - return result.toArray(new JSExpression[result.size()]); - } + return result.toArray(new JSExpression[result.size()]); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSArrayLiteralExpression(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSArrayLiteralExpression(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSAssignmentExpressionImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSAssignmentExpressionImpl.java index 5e48bb64..50485990 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSAssignmentExpressionImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSAssignmentExpressionImpl.java @@ -20,25 +20,19 @@ import com.intellij.lang.javascript.psi.JSElementVisitor; import consulo.language.ast.ASTNode; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 11:41:42 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSAssignmentExpressionImpl extends JSBinaryExpressionImpl implements JSAssignmentExpression -{ - public JSAssignmentExpressionImpl(final ASTNode node) - { - super(node); - } +public class JSAssignmentExpressionImpl extends JSBinaryExpressionImpl implements JSAssignmentExpression { + public JSAssignmentExpressionImpl(ASTNode node) { + super(node); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSAssignmentExpression(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSAssignmentExpression(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSAttributeImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSAttributeImpl.java index 963792a6..d5d8a3c1 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSAttributeImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSAttributeImpl.java @@ -16,205 +16,193 @@ package com.intellij.lang.javascript.psi.impl; -import consulo.language.ast.ASTNode; import com.intellij.lang.javascript.JSElementTypes; import com.intellij.lang.javascript.JSTokenTypes; import com.intellij.lang.javascript.psi.JSAttribute; import com.intellij.lang.javascript.psi.JSAttributeNameValuePair; import com.intellij.lang.javascript.psi.JSElementVisitor; import com.intellij.lang.javascript.psi.stubs.JSAttributeStub; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.document.util.TextRange; +import consulo.language.ast.ASTNode; +import consulo.language.psi.EmptyResolveMessageProvider; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiReference; import consulo.language.util.IncorrectOperationException; -import consulo.language.psi.EmptyResolveMessageProvider; +import consulo.localize.LocalizeValue; import consulo.util.collection.ArrayUtil; -import org.jetbrains.annotations.NonNls; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * @by Maxim.Mossienko + * @author Maxim.Mossienko */ -public class JSAttributeImpl extends JSStubElementImpl implements JSAttribute -{ - private PsiReference[] myReferences; - private static - @NonNls - String[] myPossibleMetaData = new String[]{ - "AccessibilityClass", - "ArrayElementType", - "Bindable", - "DefaultProperty", - "Deprecated", - "Effect", - "Embed", - "Event", - "Exclude", - "ExcludeClass", - "IconFile", - "Inspectable", - "InstanceType", - "HostComponent", - "NonCommittingChangeEvent", - "Frame", - "RemoteClass", - "ResourceBundle", - "Style", - "Transient" - }; - - public JSAttributeImpl(final ASTNode node) - { - super(node); - } - - public JSAttributeImpl(final JSAttributeStub node) - { - super(node, JSElementTypes.ATTRIBUTE); - } - - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSAttribute(this); - } - - @Override - public String getName() - { - final JSAttributeStub attributeStub = getStub(); - if(attributeStub != null) - { - return attributeStub.getName(); - } - final ASTNode node = getNode().findChildByType(JSTokenTypes.IDENTIFIER); - return node != null ? node.getText() : null; - } - - @Override - public PsiElement setName(@NonNls @Nonnull final String name) throws IncorrectOperationException - { - throw new IncorrectOperationException(); - } - - @Override - public JSAttributeNameValuePair[] getValues() - { - return getStubOrPsiChildren(JSElementTypes.ATTRIBUTE_NAME_VALUE_PAIR, JSAttributeNameValuePair.EMPTY_ARRAY); - } - - @Override - public JSAttributeNameValuePair getValueByName(final String name) - { - for(JSAttributeNameValuePair p : getValues()) - { - final String pName = p.getName(); - - if((name != null && name.equals(pName)) || (name == null && name == pName)) - { - return p; - } - } - return null; - } - - @Override - public PsiReference[] getReferences() - { - if(myReferences == null) - { - final ASTNode node = getNode().findChildByType(JSTokenTypes.IDENTIFIER); - - if(node == null) - { - myReferences = PsiReference.EMPTY_ARRAY; - } - else - { - final int startOffsetInParent = node.getPsi().getStartOffsetInParent(); - final TextRange range = new TextRange(startOffsetInParent, startOffsetInParent + node.getTextLength()); - - myReferences = new PsiReference[]{new AttrNameReference(range)}; - } - } - - return myReferences; - } - - private class AttrNameReference implements PsiReference, EmptyResolveMessageProvider - { - private final TextRange myRange; - - public AttrNameReference(final TextRange range) - { - myRange = range; - } - - @Override - public PsiElement getElement() - { - return JSAttributeImpl.this; - } - - @Override - public TextRange getRangeInElement() - { - return myRange; - } - - @Override - public PsiElement resolve() - { - final String s = getCanonicalText(); - return ArrayUtil.indexOf(myPossibleMetaData, s) >= 0 ? JSAttributeImpl.this : null; - } - - @Override - public String getCanonicalText() - { - return getName(); - } - - @Override - public PsiElement handleElementRename(final String newElementName) throws IncorrectOperationException - { - return null; - } - - @Override - public PsiElement bindToElement(@Nonnull final PsiElement element) throws IncorrectOperationException - { - return null; - } - - @Override - public boolean isReferenceTo(final PsiElement element) - { - if(element instanceof JSAttribute) - { - final String name = getName(); - return name != null && name.equals(((JSAttribute) element).getName()); - } - return false; - } - - @Override - public Object[] getVariants() - { - return myPossibleMetaData; - } - - @Override - public boolean isSoft() - { - return true; - } - - @Override - public String getUnresolvedMessagePattern() - { - return "Unknown metadata tag"; - } - } +public class JSAttributeImpl extends JSStubElementImpl implements JSAttribute { + private PsiReference[] myReferences; + private static final String[] POSSIBLE_META_DATA = new String[]{ + "AccessibilityClass", + "ArrayElementType", + "Bindable", + "DefaultProperty", + "Deprecated", + "Effect", + "Embed", + "Event", + "Exclude", + "ExcludeClass", + "IconFile", + "Inspectable", + "InstanceType", + "HostComponent", + "NonCommittingChangeEvent", + "Frame", + "RemoteClass", + "ResourceBundle", + "Style", + "Transient" + }; + + public JSAttributeImpl(ASTNode node) { + super(node); + } + + public JSAttributeImpl(JSAttributeStub node) { + super(node, JSElementTypes.ATTRIBUTE); + } + + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSAttribute(this); + } + + @Override + @RequiredReadAction + public String getName() { + JSAttributeStub attributeStub = getStub(); + if (attributeStub != null) { + return attributeStub.getName(); + } + ASTNode node = getNode().findChildByType(JSTokenTypes.IDENTIFIER); + return node != null ? node.getText() : null; + } + + @Override + @RequiredWriteAction + public PsiElement setName(@Nonnull String name) throws IncorrectOperationException { + throw new IncorrectOperationException(); + } + + @Override + public JSAttributeNameValuePair[] getValues() { + return getStubOrPsiChildren(JSElementTypes.ATTRIBUTE_NAME_VALUE_PAIR, JSAttributeNameValuePair.EMPTY_ARRAY); + } + + @Override + public JSAttributeNameValuePair getValueByName(String name) { + for (JSAttributeNameValuePair p : getValues()) { + String pName = p.getName(); + + if ((name != null && name.equals(pName)) || (name == null && name == pName)) { + return p; + } + } + return null; + } + + @Nonnull + @Override + @RequiredReadAction + public PsiReference[] getReferences() { + if (myReferences == null) { + ASTNode node = getNode().findChildByType(JSTokenTypes.IDENTIFIER); + + if (node == null) { + myReferences = PsiReference.EMPTY_ARRAY; + } + else { + int startOffsetInParent = node.getPsi().getStartOffsetInParent(); + TextRange range = new TextRange(startOffsetInParent, startOffsetInParent + node.getTextLength()); + + myReferences = new PsiReference[]{new AttrNameReference(range)}; + } + } + + return myReferences; + } + + private class AttrNameReference implements PsiReference, EmptyResolveMessageProvider { + private final TextRange myRange; + + public AttrNameReference(TextRange range) { + myRange = range; + } + + @Override + @RequiredReadAction + public PsiElement getElement() { + return JSAttributeImpl.this; + } + + @Nonnull + @Override + @RequiredReadAction + public TextRange getRangeInElement() { + return myRange; + } + + @Override + @RequiredReadAction + public PsiElement resolve() { + String s = getCanonicalText(); + return ArrayUtil.indexOf(POSSIBLE_META_DATA, s) >= 0 ? JSAttributeImpl.this : null; + } + + @Nonnull + @Override + @RequiredReadAction + public String getCanonicalText() { + return getName(); + } + + @Override + @RequiredWriteAction + public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException { + return null; + } + + @Override + @RequiredWriteAction + public PsiElement bindToElement(@Nonnull PsiElement element) throws IncorrectOperationException { + return null; + } + + @Override + @RequiredReadAction + public boolean isReferenceTo(PsiElement element) { + if (element instanceof JSAttribute attribute) { + String name = getName(); + return name != null && name.equals(attribute.getName()); + } + return false; + } + + @Nonnull + @Override + @RequiredReadAction + public Object[] getVariants() { + return POSSIBLE_META_DATA; + } + + @Override + @RequiredReadAction + public boolean isSoft() { + return true; + } + + @Nonnull + @Override + public LocalizeValue buildUnresolvedMessage(@Nonnull String referenceText) { + return LocalizeValue.localizeTODO("Unknown metadata tag"); + } + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSAttributeListImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSAttributeListImpl.java index 707b5e24..1aee060a 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSAttributeListImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSAttributeListImpl.java @@ -16,7 +16,6 @@ package com.intellij.lang.javascript.psi.impl; -import consulo.language.ast.ASTNode; import com.intellij.lang.javascript.JSElementTypes; import com.intellij.lang.javascript.JSTokenTypes; import com.intellij.lang.javascript.psi.JSAttribute; @@ -24,166 +23,139 @@ import com.intellij.lang.javascript.psi.JSElementVisitor; import com.intellij.lang.javascript.psi.JSReferenceExpression; import com.intellij.lang.javascript.psi.stubs.JSAttributeListStub; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; +import consulo.language.ast.ASTNode; +import consulo.language.ast.IElementType; import consulo.language.ast.TokenSet; import consulo.language.psi.PsiElement; -import consulo.language.ast.IElementType; import consulo.language.util.IncorrectOperationException; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; +import java.util.Map; /** - * @author Maxim.Mossienko + * @author Maxim.Mossienko */ -public class JSAttributeListImpl extends JSStubElementImpl implements JSAttributeList -{ - private static final TokenSet ourModifiersTypeSet = TokenSet.create(JSTokenTypes.PUBLIC_KEYWORD, JSTokenTypes.PRIVATE_KEYWORD, - JSTokenTypes.PROTECTED_KEYWORD, JSTokenTypes.INTERNAL_KEYWORD); - - public JSAttributeListImpl(final ASTNode node) - { - super(node); - } - - public JSAttributeListImpl(final JSAttributeListStub stub) - { - super(stub, JSElementTypes.ATTRIBUTE_LIST); - } - - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSAttributeList(this); - } - - @Override - @Nullable - public String getNamespace() - { - final JSAttributeListStub attributeListStub = getStub(); - if(attributeListStub != null) - { - return attributeListStub.getNamespace(); - } - final JSReferenceExpression namespaceElement = getNamespaceElement(); - return namespaceElement != null ? namespaceElement.getText() : null; - } - - @Override - public JSReferenceExpression getNamespaceElement() - { - final ASTNode node = getNode().findChildByType(JSElementTypes.REFERENCE_EXPRESSION); - return node != null ? (JSReferenceExpression) node.getPsi() : null; - } - - @Override - public JSAttribute[] getAttributes() - { - return getStubOrPsiChildren(JSElementTypes.ATTRIBUTE, JSAttribute.ARRAY_FACTORY); - } - - @Nonnull - @Override - public JSAttribute[] getAttributesByName(final @Nonnull String name) - { - List attributes = null; - for(JSAttribute attr : getAttributes()) - { - if(name.equals(attr.getName())) - { - if(attributes == null) - { - attributes = new ArrayList(); - } - attributes.add(attr); - } - } - return attributes != null ? attributes.toArray(new JSAttribute[attributes.size()]) : JSAttribute.EMPTY_ARRAY; - } - - @Override - public AccessType getAccessType() - { - final JSAttributeListStub stub = getStub(); - if(stub != null) - { - return stub.getAccessType(); - } - - final ASTNode node = getNode().findChildByType(ourModifiersTypeSet); - if(node != null) - { - final IElementType nodeType = node.getElementType(); - if(nodeType == JSTokenTypes.PUBLIC_KEYWORD) - { - return AccessType.PUBLIC; - } - if(nodeType == JSTokenTypes.PROTECTED_KEYWORD) - { - return AccessType.PROTECTED; - } - if(nodeType == JSTokenTypes.PRIVATE_KEYWORD) - { - return AccessType.PRIVATE; - } - if(nodeType == JSTokenTypes.INTERNAL_KEYWORD) - { - return AccessType.PACKAGE_LOCAL; - } - } - return AccessType.PACKAGE_LOCAL; - } - - @Override - public PsiElement findAccessTypeElement() - { - final ASTNode modifier = getNode().findChildByType(ourModifiersTypeSet); - return modifier != null ? modifier.getPsi() : null; - } - - @Override - public boolean hasModifier(final ModifierType modifier) - { - final JSAttributeListStub stub = getStub(); - if(stub != null) - { - return stub.hasModifier(modifier); - } - - IElementType type = null; - switch(modifier) - { - case DYNAMIC: - type = JSTokenTypes.DYNAMIC_KEYWORD; - break; - case OVERRIDE: - type = JSTokenTypes.OVERRIDE_KEYWORD; - break; - case NATIVE: - type = JSTokenTypes.NATIVE_KEYWORD; - break; - case STATIC: - type = JSTokenTypes.STATIC_KEYWORD; - break; - case FINAL: - type = JSTokenTypes.FINAL_KEYWORD; - break; - case VIRTUAL: - type = JSTokenTypes.VIRTUAL_KEYWORD; - break; - } - return type != null && getNode().findChildByType(type) != null; - } - - @Override - public PsiElement add(@Nonnull final PsiElement element) throws IncorrectOperationException - { - if(element.getNode().getElementType() == JSTokenTypes.OVERRIDE_KEYWORD) - { - return JSChangeUtil.doDoAddBefore(this, element, getFirstChild()); - } - return JSChangeUtil.doDoAddAfter(this, element, getLastChild()); - } +public class JSAttributeListImpl extends JSStubElementImpl implements JSAttributeList { + private static final TokenSet MODIFIERS_TYPE_SET = TokenSet.create( + JSTokenTypes.PUBLIC_KEYWORD, + JSTokenTypes.PRIVATE_KEYWORD, + JSTokenTypes.PROTECTED_KEYWORD, + JSTokenTypes.INTERNAL_KEYWORD + ); + + private static final Map ACCESS_TYPE_MAP = Map.of( + JSTokenTypes.PUBLIC_KEYWORD, AccessType.PUBLIC, + JSTokenTypes.PROTECTED_KEYWORD, AccessType.PROTECTED, + JSTokenTypes.PRIVATE_KEYWORD, AccessType.PRIVATE, + JSTokenTypes.INTERNAL_KEYWORD, AccessType.PACKAGE_LOCAL + ); + + public JSAttributeListImpl(ASTNode node) { + super(node); + } + + public JSAttributeListImpl(JSAttributeListStub stub) { + super(stub, JSElementTypes.ATTRIBUTE_LIST); + } + + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSAttributeList(this); + } + + @Nullable + @Override + @RequiredReadAction + public String getNamespace() { + JSAttributeListStub attributeListStub = getStub(); + if (attributeListStub != null) { + return attributeListStub.getNamespace(); + } + JSReferenceExpression namespaceElement = getNamespaceElement(); + return namespaceElement != null ? namespaceElement.getText() : null; + } + + @Override + @RequiredReadAction + public JSReferenceExpression getNamespaceElement() { + ASTNode node = getNode().findChildByType(JSElementTypes.REFERENCE_EXPRESSION); + return node != null ? (JSReferenceExpression)node.getPsi() : null; + } + + @Override + public JSAttribute[] getAttributes() { + return getStubOrPsiChildren(JSElementTypes.ATTRIBUTE, JSAttribute.ARRAY_FACTORY); + } + + @Nonnull + @Override + @RequiredReadAction + public JSAttribute[] getAttributesByName(@Nonnull String name) { + List attributes = null; + for (JSAttribute attr : getAttributes()) { + if (name.equals(attr.getName())) { + if (attributes == null) { + attributes = new ArrayList<>(); + } + attributes.add(attr); + } + } + return attributes != null ? attributes.toArray(new JSAttribute[attributes.size()]) : JSAttribute.EMPTY_ARRAY; + } + + @Override + @RequiredReadAction + public AccessType getAccessType() { + JSAttributeListStub stub = getStub(); + if (stub != null) { + return stub.getAccessType(); + } + + ASTNode node = getNode().findChildByType(MODIFIERS_TYPE_SET); + if (node == null) { + return AccessType.PACKAGE_LOCAL; + } + return ACCESS_TYPE_MAP.getOrDefault(node.getElementType(), AccessType.PACKAGE_LOCAL); + } + + @Override + @RequiredReadAction + public PsiElement findAccessTypeElement() { + ASTNode modifier = getNode().findChildByType(MODIFIERS_TYPE_SET); + return modifier != null ? modifier.getPsi() : null; + } + + @Override + @RequiredReadAction + public boolean hasModifier(ModifierType modifier) { + JSAttributeListStub stub = getStub(); + if (stub != null) { + return stub.hasModifier(modifier); + } + + IElementType type = switch (modifier) { + case DYNAMIC -> JSTokenTypes.DYNAMIC_KEYWORD; + case OVERRIDE -> JSTokenTypes.OVERRIDE_KEYWORD; + case NATIVE -> JSTokenTypes.NATIVE_KEYWORD; + case STATIC -> JSTokenTypes.STATIC_KEYWORD; + case FINAL -> JSTokenTypes.FINAL_KEYWORD; + case VIRTUAL -> JSTokenTypes.VIRTUAL_KEYWORD; + default -> null; + }; + return type != null && getNode().findChildByType(type) != null; + } + + @Override + @RequiredWriteAction + public PsiElement add(@Nonnull PsiElement element) throws IncorrectOperationException { + if (element.getNode().getElementType() == JSTokenTypes.OVERRIDE_KEYWORD) { + return JSChangeUtil.doDoAddBefore(this, element, getFirstChild()); + } + return JSChangeUtil.doDoAddAfter(this, element, getLastChild()); + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSAttributeNameValuePairImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSAttributeNameValuePairImpl.java index f4f9cdb9..1be66e9a 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSAttributeNameValuePairImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSAttributeNameValuePairImpl.java @@ -16,7 +16,6 @@ package com.intellij.lang.javascript.psi.impl; -import consulo.language.ast.ASTNode; import com.intellij.lang.javascript.JSElementTypes; import com.intellij.lang.javascript.JSTokenTypes; import com.intellij.lang.javascript.psi.JSAttribute; @@ -24,169 +23,154 @@ import com.intellij.lang.javascript.psi.JSElementVisitor; import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.stubs.JSAttributeNameValuePairStub; -import consulo.language.psi.PsiReference; -import consulo.language.util.IncorrectOperationException; +import consulo.annotation.access.RequiredReadAction; import consulo.javascript.lang.JavaScriptTokenSets; +import consulo.language.ast.ASTNode; import consulo.language.psi.PsiElement; +import consulo.language.psi.PsiReference; +import consulo.language.util.IncorrectOperationException; import consulo.util.lang.StringUtil; -import org.jetbrains.annotations.NonNls; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * @by Maxim.Mossienko + * @author Maxim.Mossienko */ -public class JSAttributeNameValuePairImpl extends JSStubElementImpl implements JSAttributeNameValuePair -{ - private JSReferenceSet myReferenceSet; - @NonNls - private static final String EMBED_ANNOTATION_NAME = "Embed"; - - public JSAttributeNameValuePairImpl(final ASTNode node) - { - super(node); - } - - public JSAttributeNameValuePairImpl(final JSAttributeNameValuePairStub node) - { - super(node, JSElementTypes.ATTRIBUTE_NAME_VALUE_PAIR); - } - - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSAttributeNameValuePair(this); - } - - @Override - public String getName() - { - final JSAttributeNameValuePairStub stub = getStub(); - if(stub != null) - { - return stub.getName(); - } - final ASTNode node = getNode().findChildByType(JSTokenTypes.IDENTIFIER); - return node != null ? node.getText() : null; - } - - @Override - public PsiElement setName(@NonNls @Nonnull final String name) throws IncorrectOperationException - { - throw new IncorrectOperationException(); - } - - @Override - public JSExpression getValue() - { - final ASTNode astNode = findValueNode(); - return astNode != null ? (JSExpression) astNode.getPsi() : null; - } - - @Override - public String getSimpleValue() - { - final JSAttributeNameValuePairStub stub = getStub(); - if(stub != null) - { - return stub.getValue(); - } - final ASTNode expression = findValueNode(); - return expression != null ? StringUtil.stripQuotesAroundValue(expression.getText()) : null; - } - - private ASTNode findValueNode() - { - return getNode().findChildByType(JavaScriptTokenSets.STRING_LITERALS); - } - - @Override - @Nonnull - public PsiReference[] getReferences() - { - final @NonNls String name = getName(); - - if("source".equals(name)) - { - return getPathRefsCheckingParent(); - } - else if("type".equals(name) || "arrayType".equals(name)) - { - return getClassRefs(); - } - else if(name == null) - { - return getDefaultPropertyRefs(); - } - return PsiReference.EMPTY_ARRAY; - } - - private PsiReference[] getClassRefs() - { - final ASTNode valueNode = findValueNode(); - - if(valueNode != null) - { - if(myReferenceSet == null) - { - myReferenceSet = new JSReferenceSet(this, false); - } - myReferenceSet.update(valueNode.getText(), valueNode.getPsi().getStartOffsetInParent()); - return myReferenceSet.getReferences(); - } - return PsiReference.EMPTY_ARRAY; - } - - private PsiReference[] getDefaultPropertyRefs() - { - final @NonNls String parentName = ((JSAttribute) getParent()).getName(); - - if("HostComponent".equals(parentName) || "ArrayElementType".equals(parentName)) - { - return getClassRefs(); - } - - if(EMBED_ANNOTATION_NAME.equals(parentName)) - { - return getPathRefs(); - } - if("DefaultProperty".equals(parentName)) - { - final ASTNode valueNode = findValueNode(); - if(valueNode != null) - { - if(myReferenceSet == null) - { - myReferenceSet = new JSReferenceSet(this, false); - } - myReferenceSet.update(valueNode.getText(), valueNode.getPsi().getStartOffsetInParent()); - return myReferenceSet.getReferences(); - } - } - - return PsiReference.EMPTY_ARRAY; - } - - private PsiReference[] getPathRefsCheckingParent() - { - final @NonNls String parentName = ((JSAttribute) getParent()).getName(); - - if(!EMBED_ANNOTATION_NAME.equals(parentName)) - { - return PsiReference.EMPTY_ARRAY; - } - return getPathRefs(); - } - - private PsiReference[] getPathRefs() - { - final ASTNode valueNode = findValueNode(); - - if(valueNode != null) - { - return ReferenceSupport.getFileRefs(this, valueNode.getPsi(), valueNode.getPsi().getStartOffsetInParent() + 1, - ReferenceSupport.LookupOptions.EMBEDDED_ASSET); - } - return PsiReference.EMPTY_ARRAY; - } +public class JSAttributeNameValuePairImpl extends JSStubElementImpl implements JSAttributeNameValuePair { + private JSReferenceSet myReferenceSet; + private static final String EMBED_ANNOTATION_NAME = "Embed"; + + public JSAttributeNameValuePairImpl(ASTNode node) { + super(node); + } + + public JSAttributeNameValuePairImpl(JSAttributeNameValuePairStub node) { + super(node, JSElementTypes.ATTRIBUTE_NAME_VALUE_PAIR); + } + + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSAttributeNameValuePair(this); + } + + @Override + @RequiredReadAction + public String getName() { + JSAttributeNameValuePairStub stub = getStub(); + if (stub != null) { + return stub.getName(); + } + ASTNode node = getNode().findChildByType(JSTokenTypes.IDENTIFIER); + return node != null ? node.getText() : null; + } + + @Override + @RequiredReadAction + public PsiElement setName(@Nonnull String name) throws IncorrectOperationException { + throw new IncorrectOperationException(); + } + + @Override + @RequiredReadAction + public JSExpression getValue() { + ASTNode astNode = findValueNode(); + return astNode != null ? (JSExpression)astNode.getPsi() : null; + } + + @Override + @RequiredReadAction + public String getSimpleValue() { + JSAttributeNameValuePairStub stub = getStub(); + if (stub != null) { + return stub.getValue(); + } + ASTNode expression = findValueNode(); + return expression != null ? StringUtil.stripQuotesAroundValue(expression.getText()) : null; + } + + @RequiredReadAction + private ASTNode findValueNode() { + return getNode().findChildByType(JavaScriptTokenSets.STRING_LITERALS); + } + + @Override + @Nonnull + @RequiredReadAction + public PsiReference[] getReferences() { + String name = getName(); + + if ("source".equals(name)) { + return getPathRefsCheckingParent(); + } + else if ("type".equals(name) || "arrayType".equals(name)) { + return getClassRefs(); + } + else if (name == null) { + return getDefaultPropertyRefs(); + } + return PsiReference.EMPTY_ARRAY; + } + + @RequiredReadAction + private PsiReference[] getClassRefs() { + ASTNode valueNode = findValueNode(); + + if (valueNode != null) { + if (myReferenceSet == null) { + myReferenceSet = new JSReferenceSet(this, false); + } + myReferenceSet.update(valueNode.getText(), valueNode.getPsi().getStartOffsetInParent()); + return myReferenceSet.getReferences(); + } + return PsiReference.EMPTY_ARRAY; + } + + @RequiredReadAction + private PsiReference[] getDefaultPropertyRefs() { + String parentName = ((JSAttribute)getParent()).getName(); + + if ("HostComponent".equals(parentName) || "ArrayElementType".equals(parentName)) { + return getClassRefs(); + } + + if (EMBED_ANNOTATION_NAME.equals(parentName)) { + return getPathRefs(); + } + if ("DefaultProperty".equals(parentName)) { + ASTNode valueNode = findValueNode(); + if (valueNode != null) { + if (myReferenceSet == null) { + myReferenceSet = new JSReferenceSet(this, false); + } + myReferenceSet.update(valueNode.getText(), valueNode.getPsi().getStartOffsetInParent()); + return myReferenceSet.getReferences(); + } + } + + return PsiReference.EMPTY_ARRAY; + } + + @RequiredReadAction + private PsiReference[] getPathRefsCheckingParent() { + String parentName = ((JSAttribute)getParent()).getName(); + + if (!EMBED_ANNOTATION_NAME.equals(parentName)) { + return PsiReference.EMPTY_ARRAY; + } + return getPathRefs(); + } + + @RequiredReadAction + private PsiReference[] getPathRefs() { + ASTNode valueNode = findValueNode(); + + if (valueNode != null) { + return ReferenceSupport.getFileRefs( + this, + valueNode.getPsi(), + valueNode.getPsi().getStartOffsetInParent() + 1, + ReferenceSupport.LookupOptions.EMBEDDED_ASSET + ); + } + return PsiReference.EMPTY_ARRAY; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSBinaryExpressionImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSBinaryExpressionImpl.java index bda9362f..ce95d814 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSBinaryExpressionImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSBinaryExpressionImpl.java @@ -30,79 +30,73 @@ import consulo.annotation.access.RequiredReadAction; import consulo.language.psi.util.PsiTreeUtil; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 11:41:42 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSBinaryExpressionImpl extends JSExpressionImpl implements JSBinaryExpression -{ - private static final TokenSet BINARY_OPERATIONS = TokenSet.orSet(JSTokenTypes.OPERATIONS, JSTokenTypes.RELATIONAL_OPERATIONS); - private static final TokenSet BINARY_OPERATIONS_WITH_DEFS = TokenSet.create(JSTokenTypes.COMMA, JSTokenTypes.EQ); +public class JSBinaryExpressionImpl extends JSExpressionImpl implements JSBinaryExpression { + private static final TokenSet BINARY_OPERATIONS = TokenSet.orSet(JSTokenTypes.OPERATIONS, JSTokenTypes.RELATIONAL_OPERATIONS); + private static final TokenSet BINARY_OPERATIONS_WITH_DEFS = TokenSet.create(JSTokenTypes.COMMA, JSTokenTypes.EQ); - public JSBinaryExpressionImpl(final ASTNode node) - { - super(node); - } + public JSBinaryExpressionImpl(ASTNode node) { + super(node); + } - @Override - public JSExpression getLOperand() - { - final ASTNode astNode = getNode(); - final JSExpression firstExpression = PsiTreeUtil.findChildOfType(astNode.getPsi(), JSExpression.class); - if(firstExpression != null && astNode.findChildByType(BINARY_OPERATIONS, firstExpression.getNode()) == null) - { - return null; // =a - } - return firstExpression != null ? firstExpression : null; - } + @Override + @RequiredReadAction + public JSExpression getLOperand() { + ASTNode astNode = getNode(); + JSExpression firstExpression = PsiTreeUtil.findChildOfType(astNode.getPsi(), JSExpression.class); + if (firstExpression != null && astNode.findChildByType(BINARY_OPERATIONS, firstExpression.getNode()) == null) { + return null; // =a + } + return firstExpression != null ? firstExpression : null; + } - @Override - public JSExpression getROperand() - { - final ASTNode myNode = getNode(); - final ASTNode secondExpression = myNode.findChildByType(JSElementTypes.EXPRESSIONS, myNode.findChildByType(BINARY_OPERATIONS)); - return secondExpression != null ? (JSExpression) secondExpression.getPsi() : null; - } + @Override + @RequiredReadAction + public JSExpression getROperand() { + ASTNode myNode = getNode(); + ASTNode secondExpression = myNode.findChildByType(JSElementTypes.EXPRESSIONS, myNode.findChildByType(BINARY_OPERATIONS)); + return secondExpression != null ? (JSExpression)secondExpression.getPsi() : null; + } - @RequiredReadAction - @Nullable - @Override - public PsiElement getOperationElement() - { - final ASTNode operationASTNode = getNode().findChildByType(BINARY_OPERATIONS); - return operationASTNode != null ? operationASTNode.getPsi() : null; - } + @Nullable + @Override + @RequiredReadAction + public PsiElement getOperationElement() { + ASTNode operationASTNode = getNode().findChildByType(BINARY_OPERATIONS); + return operationASTNode != null ? operationASTNode.getPsi() : null; + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSBinaryExpression(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSBinaryExpression(this); + } - @Override - public boolean processDeclarations(@Nonnull PsiScopeProcessor processor, @Nonnull ResolveState state, PsiElement lastParent, - @Nonnull PsiElement place) - { - final IElementType operationType = getOperationSign(); + @Override + @RequiredReadAction + public boolean processDeclarations( + @Nonnull PsiScopeProcessor processor, + @Nonnull ResolveState state, + PsiElement lastParent, + @Nonnull PsiElement place + ) { + IElementType operationType = getOperationSign(); - if(BINARY_OPERATIONS_WITH_DEFS.contains(operationType)) - { - final JSExpression loperand = getLOperand(); - final JSExpression roperand = getROperand(); + if (BINARY_OPERATIONS_WITH_DEFS.contains(operationType)) { + JSExpression loperand = getLOperand(); + JSExpression roperand = getROperand(); - if(loperand != null) - { - return loperand.processDeclarations(processor, state, lastParent, place) && (roperand != null ? roperand.processDeclarations(processor, state, - lastParent, place) : true); - } - } + if (loperand != null) { + return loperand.processDeclarations(processor, state, lastParent, place) + && (roperand == null || roperand.processDeclarations(processor, state, lastParent, place)); + } + } - return true; - } + return true; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSBlockStatementImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSBlockStatementImpl.java index 49230730..3d1e4da7 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSBlockStatementImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSBlockStatementImpl.java @@ -21,57 +21,47 @@ import com.intellij.lang.javascript.psi.JSElementVisitor; import com.intellij.lang.javascript.psi.JSLabeledStatement; import com.intellij.lang.javascript.psi.JSStatement; +import consulo.annotation.access.RequiredWriteAction; import consulo.language.ast.ASTNode; import consulo.language.codeStyle.CodeStyleManager; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 9:17:15 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSBlockStatementImpl extends JSStatementImpl implements JSBlockStatement -{ - public JSBlockStatementImpl(final ASTNode node) - { - super(node); - } +public class JSBlockStatementImpl extends JSStatementImpl implements JSBlockStatement { + public JSBlockStatementImpl(ASTNode node) { + super(node); + } - @Override - public JSStatement[] getStatements() - { - return findChildrenByClass(JSStatement.class); - } + @Override + public JSStatement[] getStatements() { + return findChildrenByClass(JSStatement.class); + } - public JSLabeledStatement setLabel(String label) - { - throw new UnsupportedOperationException("TODO: implement"); - } + public JSLabeledStatement setLabel(String label) { + throw new UnsupportedOperationException("TODO: implement"); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSBlock(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSBlock(this); + } - @Override - public PsiElement add(@Nonnull final PsiElement element) throws IncorrectOperationException - { - if(element instanceof JSStatement) - { - ASTNode node = getNode().findChildByType(JSTokenTypes.RBRACE); - if(node != null) - { - PsiElement psiElement = super.addAfter(element, node.getTreePrev().getPsi()); - CodeStyleManager.getInstance(getProject()).reformatNewlyAddedElement(getNode(), psiElement.getNode()); - return psiElement; - } - } - return super.add(element); - } + @Override + @RequiredWriteAction + public PsiElement add(@Nonnull PsiElement element) throws IncorrectOperationException { + if (element instanceof JSStatement statement) { + ASTNode node = getNode().findChildByType(JSTokenTypes.RBRACE); + if (node != null) { + PsiElement psiElement = super.addAfter(statement, node.getTreePrev().getPsi()); + CodeStyleManager.getInstance(getProject()).reformatNewlyAddedElement(getNode(), psiElement.getNode()); + return psiElement; + } + } + return super.add(element); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSBreakStatementImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSBreakStatementImpl.java index 0569134b..ce33bbba 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSBreakStatementImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSBreakStatementImpl.java @@ -16,43 +16,35 @@ package com.intellij.lang.javascript.psi.impl; +import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.ASTNode; import com.intellij.lang.javascript.psi.*; import consulo.language.psi.util.PsiTreeUtil; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 9:52:04 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSBreakStatementImpl extends JSStatementWithLabelReferenceImpl implements JSBreakStatement -{ - public JSBreakStatementImpl(final ASTNode node) - { - super(node); - } +public class JSBreakStatementImpl extends JSStatementWithLabelReferenceImpl implements JSBreakStatement { + public JSBreakStatementImpl(ASTNode node) { + super(node); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSBreakStatement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSBreakStatement(this); + } - @Override - public JSStatement getStatementToBreak() - { - String label = getLabel(); - if(label == null) - { - return PsiTreeUtil.getParentOfType(this, JSLoopStatement.class, JSSwitchStatement.class); - } - else - { - return (JSStatement) getReferences()[0].resolve(); - } - } + @Override + @RequiredReadAction + public JSStatement getStatementToBreak() { + String label = getLabel(); + if (label == null) { + return PsiTreeUtil.getParentOfType(this, JSLoopStatement.class, JSSwitchStatement.class); + } + else { + return (JSStatement)getReferences()[0].resolve(); + } + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSCallExpressionImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSCallExpressionImpl.java index 75b731c8..f6bab133 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSCallExpressionImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSCallExpressionImpl.java @@ -16,6 +16,7 @@ package com.intellij.lang.javascript.psi.impl; +import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.ASTNode; import com.intellij.lang.javascript.JSElementTypes; import com.intellij.lang.javascript.psi.JSArgumentList; @@ -23,38 +24,31 @@ import com.intellij.lang.javascript.psi.JSElementVisitor; import com.intellij.lang.javascript.psi.JSExpression; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 31, 2005 - * Time: 12:02:38 AM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-31 */ -public class JSCallExpressionImpl extends JSExpressionImpl implements JSCallExpression -{ - public JSCallExpressionImpl(final ASTNode node) - { - super(node); - } +public class JSCallExpressionImpl extends JSExpressionImpl implements JSCallExpression { + public JSCallExpressionImpl(ASTNode node) { + super(node); + } - @Override - public JSExpression getMethodExpression() - { - return findChildByClass(JSExpression.class); - } + @Override + public JSExpression getMethodExpression() { + return findChildByClass(JSExpression.class); + } - @Override - public JSArgumentList getArgumentList() - { - ASTNode node = getNode().findChildByType(JSElementTypes.ARGUMENT_LIST); - return node != null ? (JSArgumentList) node.getPsi() : null; - } + @Override + @RequiredReadAction + public JSArgumentList getArgumentList() { + ASTNode node = getNode().findChildByType(JSElementTypes.ARGUMENT_LIST); + return node != null ? (JSArgumentList)node.getPsi() : null; + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSCallExpression(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSCallExpression(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSCaseClauseImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSCaseClauseImpl.java index 2e4c8869..25c89e04 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSCaseClauseImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSCaseClauseImpl.java @@ -21,49 +21,38 @@ import com.intellij.lang.javascript.psi.JSElementVisitor; import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.JSStatement; +import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.ASTNode; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 10:11:23 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSCaseClauseImpl extends JSElementImpl implements JSCaseClause -{ - public JSCaseClauseImpl(final ASTNode node) - { - super(node); - } - - @Override - public boolean isDefault() - { - return getNode().findChildByType(JSTokenTypes.DEFAULT_KEYWORD) != null; - } - - @Override - public JSExpression getCaseExpression() - { - if(isDefault()) - { - return null; - } - return findChildByClass(JSExpression.class); - } - - @Override - public JSStatement[] getStatements() - { - return findChildrenByClass(JSStatement.class); - } - - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSCaseClause(this); - } +public class JSCaseClauseImpl extends JSElementImpl implements JSCaseClause { + public JSCaseClauseImpl(ASTNode node) { + super(node); + } + + @Override + @RequiredReadAction + public boolean isDefault() { + return getNode().findChildByType(JSTokenTypes.DEFAULT_KEYWORD) != null; + } + + @Override + @RequiredReadAction + public JSExpression getCaseExpression() { + return isDefault() ? null : findChildByClass(JSExpression.class); + } + + @Override + public JSStatement[] getStatements() { + return findChildrenByClass(JSStatement.class); + } + + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSCaseClause(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSCatchBlockImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSCatchBlockImpl.java index 159fc8ed..81655477 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSCatchBlockImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSCatchBlockImpl.java @@ -21,67 +21,62 @@ import com.intellij.lang.javascript.psi.JSElementVisitor; import com.intellij.lang.javascript.psi.JSParameter; import com.intellij.lang.javascript.psi.JSStatement; +import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.ASTNode; import consulo.language.psi.PsiElement; import consulo.language.psi.resolve.PsiScopeProcessor; import consulo.language.psi.resolve.ResolveState; import consulo.language.util.IncorrectOperationException; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 10:06:09 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSCatchBlockImpl extends JSElementImpl implements JSCatchBlock -{ - public JSCatchBlockImpl(final ASTNode node) - { - super(node); - } +public class JSCatchBlockImpl extends JSElementImpl implements JSCatchBlock { + public JSCatchBlockImpl(ASTNode node) { + super(node); + } - @Override - public JSParameter getParameter() - { - final ASTNode node = getNode().findChildByType(JSElementTypes.FORMAL_PARAMETER); - return node != null ? (JSParameter) node.getPsi() : null; - } + @Override + @RequiredReadAction + public JSParameter getParameter() { + ASTNode node = getNode().findChildByType(JSElementTypes.FORMAL_PARAMETER); + return node != null ? (JSParameter)node.getPsi() : null; + } - @Override - public JSStatement getStatement() - { - return findChildByClass(JSStatement.class); - } + @Override + public JSStatement getStatement() { + return findChildByClass(JSStatement.class); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSCatchBlock(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSCatchBlock(this); + } - @Override - public boolean processDeclarations(@Nonnull PsiScopeProcessor processor, @Nonnull ResolveState state, PsiElement lastParent, - @Nonnull PsiElement place) - { - if(lastParent != null) - { - final JSParameter param = getParameter(); - if(param != null) - { - return processor.execute(param, state); - } - } + @Override + @RequiredReadAction + public boolean processDeclarations( + @Nonnull PsiScopeProcessor processor, + @Nonnull ResolveState state, + PsiElement lastParent, + @Nonnull PsiElement place + ) { + if (lastParent != null) { + JSParameter param = getParameter(); + if (param != null) { + return processor.execute(param, state); + } + } - return true; - } + return true; + } - @Override - public void delete() throws IncorrectOperationException - { - final ASTNode astNode = getNode(); - astNode.getTreeParent().removeChild(astNode); - } + @Override + public void delete() throws IncorrectOperationException { + ASTNode astNode = getNode(); + astNode.getTreeParent().removeChild(astNode); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSChangeUtil.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSChangeUtil.java index 7f0e72f6..33aff1e0 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSChangeUtil.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSChangeUtil.java @@ -20,6 +20,8 @@ import com.intellij.lang.javascript.formatter.JSCodeStyleSettings; import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.util.JSUtils; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.javascript.language.JavaScriptLanguage; import consulo.javascript.lang.JavaScriptTokenSets; import consulo.language.ast.ASTNode; @@ -32,390 +34,349 @@ import consulo.language.util.IncorrectOperationException; import consulo.project.Project; import consulo.util.lang.StringUtil; +import jakarta.annotation.Nullable; import org.jetbrains.annotations.NonNls; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 31, 2005 - * Time: 7:56:28 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-31 */ -public class JSChangeUtil -{ - private JSChangeUtil() - { - } - - public static ASTNode createNameIdentifier(Project project, String name, IElementType type) - { - if(JSTokenTypes.IDENTIFIER_TOKENS_SET.contains(type)) - { - return createNameIdentifier(project, name); - } - else if(JavaScriptTokenSets.STRING_LITERALS.contains(type) && !StringUtil.isQuotedString(name)) - { - return createExpressionFromText(project, "\"" + name + "\"").getNode().getFirstChildNode(); - } - else - { - return createExpressionFromText(project, name).getNode().getFirstChildNode(); - } - } - - public static ASTNode createNameIdentifier(Project project, String name) - { - final JSExpressionStatement expressionStatement = (JSExpressionStatement) createJSTreeFromTextImpl(project, name + ";"); - final JSReferenceExpressionImpl refExpression = (JSReferenceExpressionImpl) expressionStatement.getFirstChild(); - - return refExpression.getNode().getFirstChildNode(); - } - - @Nonnull - public static JSExpression createExpressionFromText(Project project, @NonNls String text) - { - text = "{\n" + text + "\n}"; - PsiElement element = createJSTreeFromTextImpl(project, text); - assert element instanceof JSBlockStatement : "\"" + text + "\" was not parsed as BlockStatement"; - element = ((JSBlockStatement) element).getStatements()[0]; - final JSExpressionStatement expressionStatement = (JSExpressionStatement) element; - return (JSExpression) expressionStatement.getFirstChild(); - } - - - public static ASTNode createStatementFromText(Project project, @NonNls String text) - { - final PsiElement element = createJSTreeFromTextImpl(project, text); - final JSSourceElement stmt = element instanceof JSSourceElement ? (JSSourceElement) element : null; - return stmt != null ? stmt.getNode() : null; - } - - @Nullable - private static PsiElement createJSTreeFromTextImpl(Project project, @NonNls String text) - { - final PsiFile dummyFile; - dummyFile = PsiFileFactory.getInstance(project).createFileFromText("dummy.js", JavaScriptLanguage.INSTANCE, text); - - return dummyFile.getFirstChild(); - } - - public static ASTNode createJSTreeFromText(Project project, @NonNls String text) - { - final PsiElement element = createJSTreeFromTextImpl(project, text); - if(element != null) - { - return element.getNode(); - } - return null; - } - - public static JSExpression replaceExpression(JSExpression oldExpr, JSExpression newExpr) - { - if(JSUtils.isNeedParenthesis(oldExpr, newExpr)) - { - ASTNode parenthesized = createExpressionFromText(oldExpr.getProject(), "(a)").getNode(); - final JSParenthesizedExpression parenthPsi = (JSParenthesizedExpression) parenthesized.getPsi(); - parenthesized.replaceChild(parenthPsi.getInnerExpression().getNode(), newExpr.getNode().copyElement()); - oldExpr.getParent().getNode().replaceChild(oldExpr.getNode(), parenthesized); - return parenthPsi; - } - else - { - final ASTNode newNode = newExpr.getNode().copyElement(); - oldExpr.getParent().getNode().replaceChild(oldExpr.getNode(), newNode); - return (JSExpression) newNode.getPsi(); - } - } - - public static JSStatement replaceStatement(JSStatement oldStatement, JSStatement newStatement) - { - final ASTNode newNode = newStatement.getNode().copyElement(); - oldStatement.getParent().getNode().replaceChild(oldStatement.getNode(), newNode); - return (JSStatement) newNode.getPsi(); - } - - public static void doIdentifierReplacement(PsiElement parent, PsiElement identifier, String name) - { - final ASTNode nameElement = JSChangeUtil.createNameIdentifier(parent.getProject(), name); - parent.getNode().replaceChild(identifier.getNode(), nameElement); - } - - public static PsiElement doAddBefore(final PsiElement jsElement, final PsiElement element, - final PsiElement anchor) throws IncorrectOperationException - { - if(!JSChangeUtil.isStatementOrComment(element) && !(element instanceof PsiWhiteSpace)) - { - throw new UnsupportedOperationException("js statement or whitespace expected"); - } - - return doDoAddBefore(jsElement, element, anchor); - } - - public static PsiElement doDoAddBefore(final PsiElement jsElement, final PsiElement element, - final PsiElement anchor) throws IncorrectOperationException - { - final ASTNode elementNode = element.getNode(); - if(elementNode == null) - { - throw new IncorrectOperationException("node should not be null"); - } - ASTNode copiedElementNode = elementNode.copyElement(); - final ASTNode parentNode = jsElement.getNode(); - ASTNode anchorNode = anchor != null ? anchor.getNode() : null; - - anchorNode = insertWhitespaceIfNeeded(anchorNode, elementNode, parentNode, anchorNode); - - parentNode.addChild(copiedElementNode, anchorNode != null ? anchorNode : null); - if(copiedElementNode.getPsi() instanceof PsiComment && parentNode.getPsi().isPhysical()) - { // HACK ! - CodeStyleManager.getInstance(element.getProject()).reformatNewlyAddedElement(parentNode, copiedElementNode); - } - - return copiedElementNode.getPsi(); - } - - private static ASTNode insertWhitespaceIfNeeded(ASTNode anchorNode, final ASTNode elementNode, final ASTNode parentNode, - final ASTNode insertionPlaceNode) throws IncorrectOperationException - { - ParserDefinition parserDef = ParserDefinition.forLanguage(parentNode.getPsi().getLanguage()); - final TokenSet comments = parserDef.getCommentTokens(parentNode.getPsi().getLanguage().getVersions()[0]); - final TokenSet whitespaces = parserDef.getWhitespaceTokens(parentNode.getPsi().getLanguage().getVersions()[0]); - - if(anchorNode != null && ((!whitespaces.contains(anchorNode.getElementType()) && !whitespaces.contains(elementNode.getElementType())) || - comments.contains(anchorNode.getElementType()) || - comments.contains(elementNode.getElementType()) || - elementNode.getPsi() instanceof PsiComment)) - { - String commentString = " "; - if(comments.contains(anchorNode.getElementType()) || - comments.contains(elementNode.getElementType()) || - elementNode.getPsi() instanceof PsiComment) - { - commentString = "\n"; - } - - final ASTNode wsNode = PsiParserFacade.SERVICE.getInstance(parentNode.getPsi().getProject()).createWhiteSpaceFromText(commentString).getNode(); - parentNode.addChild(wsNode, insertionPlaceNode); - anchorNode = wsNode; - } - return anchorNode; - } - - public static boolean isStatementContainer(final PsiElement jsElement) - { - return jsElement instanceof JSBlockStatement || jsElement instanceof JSEmbeddedContentImpl || jsElement instanceof JSClass || - jsElement instanceof JSPackageStatement; - } - - public static boolean isStatementOrComment(final PsiElement jsElement) - { - return jsElement instanceof JSSourceElement || jsElement instanceof PsiComment; - } - - public static PsiElement doAddAfter(final PsiElement jsElement, final PsiElement element, - final PsiElement anchor) throws IncorrectOperationException - { - if(!JSChangeUtil.isStatementOrComment(element) && !(element instanceof PsiWhiteSpace)) - { - throw new UnsupportedOperationException("js statement or whitespace expected"); - } - - return doDoAddAfter(jsElement, element, anchor); - } - - public static PsiElement doDoAddAfter(final PsiElement jsElement, final PsiElement element, - final PsiElement anchor) throws IncorrectOperationException - { - final ASTNode parentNode = jsElement.getNode(); - final ASTNode node = element.getNode(); - ASTNode anchorNode = anchor != null ? anchor.getNode() : parentNode.getLastChildNode(); - anchorNode = insertWhitespaceIfNeeded(anchorNode, node, parentNode, anchorNode != null ? anchorNode.getTreeNext() : null); - - final ASTNode nodeCopy = node.copyElement(); - - if(anchor == null) - { - parentNode.addChild(nodeCopy); - } - else - { - parentNode.addChild(nodeCopy, anchorNode.getTreeNext()); - } - - final ASTNode nextAfter = nodeCopy.getTreeNext(); - insertWhitespaceIfNeeded(nextAfter, node, parentNode, nextAfter); - - return nodeCopy.getPsi(); - } - - public static PsiElement doAddRangeBefore(PsiElement parent, PsiElement first, final PsiElement last, - final PsiElement anchor) throws IncorrectOperationException - { - final PsiElement resultElement; - PsiElement psiElement = resultElement = doAddBefore(parent, first, anchor); - - while(first != last) - { - first = first.getNextSibling(); - if(first == null) - { - break; - } - psiElement = doAddAfter(parent, first, psiElement); - } - - return resultElement; - } - - public static PsiElement doAddRangeAfter(final PsiElement jsElement, PsiElement first, final PsiElement last, - final PsiElement anchor) throws IncorrectOperationException - { - final PsiElement resultElement; - PsiElement psiElement = resultElement = doAddAfter(jsElement, first, anchor); - - while(first != last) - { - first = first.getNextSibling(); - if(first == null) - { - break; - } - psiElement = doAddAfter(jsElement, first, psiElement); - } - - return resultElement; - } - - public static boolean isBlockStatementContainer(final JSElement jsElement) - { - return jsElement instanceof JSIfStatement || jsElement instanceof JSLoopStatement; - } - - public static PsiElement blockDoAddRangeBefore(final PsiElement first, final PsiElement last, final @Nonnull PsiElement anchor) throws - IncorrectOperationException - { - BlockAddContext addContext = new BlockAddContext(anchor) - { - @Override - PsiElement doAddElement(PsiElement... element) throws IncorrectOperationException - { - return newlyAddedBlock.addRangeBefore(element[0], element[1], codeBlockAnchor); - } - }; - - return addContext.doAddElement(first, last); - } - - public static PsiElement blockDoAddRangeAfter(final PsiElement first, final PsiElement last, final @Nonnull PsiElement anchor) throws - IncorrectOperationException - { - BlockAddContext addContext = new BlockAddContext(anchor) - { - @Override - PsiElement doAddElement(PsiElement... element) throws IncorrectOperationException - { - return newlyAddedBlock.addRangeAfter(element[0], element[1], codeBlockAnchor); - } - }; - - return addContext.doAddElement(first, last); - } - - public static PsiElement blockDoAddAfter(final PsiElement element, final @Nonnull PsiElement anchor) throws IncorrectOperationException - { - BlockAddContext addContext = new BlockAddContext(anchor) - { - @Override - PsiElement doAddElement(PsiElement... element) throws IncorrectOperationException - { - return newlyAddedBlock.addAfter(element[0], codeBlockAnchor); - } - }; - - return addContext.doAddElement(element); - } - - public static PsiElement blockDoAddBefore(final PsiElement element, final @Nonnull PsiElement anchor) throws IncorrectOperationException - { - BlockAddContext addContext = new BlockAddContext(anchor) - { - @Override - PsiElement doAddElement(PsiElement... element) throws IncorrectOperationException - { - return newlyAddedBlock.addBefore(element[0], codeBlockAnchor); - } - }; - - return addContext.doAddElement(element); - } - - public static String getSemicolon(final Project project) - { - return CodeStyleSettingsManager.getInstance(project).getCurrentSettings().getCustomSettings(JSCodeStyleSettings.class) - .USE_SEMICOLON_AFTER_STATEMENT ? ";" : ""; - } - - abstract static class BlockAddContext - { - final JSBlockStatement newlyAddedBlock; - final PsiElement codeBlockAnchor; - - BlockAddContext(final @Nonnull PsiElement _anchor) throws IncorrectOperationException - { - final ASTNode codeBlockNode = JSChangeUtil.createStatementFromText(_anchor.getProject(), "{ a }"); - - newlyAddedBlock = (JSBlockStatement) _anchor.replace(((JSBlockStatement) codeBlockNode.getPsi())); - - final JSStatement artificiallyAddedBlockAnchor = newlyAddedBlock.getStatements()[0]; - codeBlockAnchor = newlyAddedBlock.addBefore(_anchor, artificiallyAddedBlockAnchor); - artificiallyAddedBlockAnchor.delete(); - } - - abstract PsiElement doAddElement(PsiElement... element) throws IncorrectOperationException; - } - - static void removeRangeWithRemovalOfCommas(final ASTNode myNode, final ASTNode parent) - { - ASTNode from = myNode, to = myNode.getTreeNext(); - boolean seenComma = false; - - if(to != null && to.getElementType() == JSTokenTypes.WHITE_SPACE) - { - to = to.getTreeNext(); - } - - if(to != null && to.getElementType() == JSTokenTypes.COMMA) - { - to = to.getTreeNext(); - seenComma = true; - - if(to != null && to.getElementType() == JSTokenTypes.WHITE_SPACE) - { - to = to.getTreeNext(); - } - } - - if(!seenComma) - { - ASTNode treePrev = from.getTreePrev(); - - if(treePrev != null && treePrev.getElementType() == JSTokenTypes.WHITE_SPACE) - { - treePrev = treePrev.getTreePrev(); - } - if(treePrev != null && treePrev.getElementType() == JSTokenTypes.COMMA) - { - from = treePrev; - } - - if(to != null && to.getElementType() == JSTokenTypes.WHITE_SPACE) - { - to = to.getTreeNext(); - } - } - parent.removeRange(from, to); - } +public class JSChangeUtil { + private JSChangeUtil() { + } + + @RequiredReadAction + public static ASTNode createNameIdentifier(Project project, String name, IElementType type) { + if (JSTokenTypes.IDENTIFIER_TOKENS_SET.contains(type)) { + return createNameIdentifier(project, name); + } + else if (JavaScriptTokenSets.STRING_LITERALS.contains(type) && !StringUtil.isQuotedString(name)) { + return createExpressionFromText(project, "\"" + name + "\"").getNode().getFirstChildNode(); + } + else { + return createExpressionFromText(project, name).getNode().getFirstChildNode(); + } + } + + @RequiredReadAction + public static ASTNode createNameIdentifier(Project project, String name) { + JSExpressionStatement expression = (JSExpressionStatement)createJSTreeFromTextImpl(project, name + ";"); + JSReferenceExpressionImpl refExpr = (JSReferenceExpressionImpl)expression.getFirstChild(); + + return refExpr.getNode().getFirstChildNode(); + } + + @Nonnull + @RequiredReadAction + public static JSExpression createExpressionFromText(Project project, @NonNls String text) { + text = "{\n" + text + "\n}"; + PsiElement element = createJSTreeFromTextImpl(project, text); + assert element instanceof JSBlockStatement : "\"" + text + "\" was not parsed as BlockStatement"; + element = ((JSBlockStatement)element).getStatements()[0]; + JSExpressionStatement expressionStatement = (JSExpressionStatement)element; + return (JSExpression)expressionStatement.getFirstChild(); + } + + @RequiredReadAction + public static ASTNode createStatementFromText(Project project, String text) { + PsiElement element = createJSTreeFromTextImpl(project, text); + JSSourceElement stmt = element instanceof JSSourceElement sourceElement ? sourceElement : null; + return stmt != null ? stmt.getNode() : null; + } + + @Nullable + @RequiredReadAction + private static PsiElement createJSTreeFromTextImpl(Project project, String text) { + PsiFile dummyFile = + PsiFileFactory.getInstance(project).createFileFromText("dummy.js", JavaScriptLanguage.INSTANCE, text); + + return dummyFile.getFirstChild(); + } + + @RequiredReadAction + public static ASTNode createJSTreeFromText(Project project, String text) { + PsiElement element = createJSTreeFromTextImpl(project, text); + return element != null ? element.getNode() : null; + } + + @RequiredWriteAction + public static JSExpression replaceExpression(JSExpression oldExpr, JSExpression newExpr) { + if (JSUtils.isNeedParenthesis(oldExpr, newExpr)) { + ASTNode parenthesized = createExpressionFromText(oldExpr.getProject(), "(a)").getNode(); + JSParenthesizedExpression parenthPsi = (JSParenthesizedExpression)parenthesized.getPsi(); + parenthesized.replaceChild(parenthPsi.getInnerExpression().getNode(), newExpr.getNode().copyElement()); + oldExpr.getParent().getNode().replaceChild(oldExpr.getNode(), parenthesized); + return parenthPsi; + } + else { + ASTNode newNode = newExpr.getNode().copyElement(); + oldExpr.getParent().getNode().replaceChild(oldExpr.getNode(), newNode); + return (JSExpression)newNode.getPsi(); + } + } + + @RequiredWriteAction + public static JSStatement replaceStatement(JSStatement oldStatement, JSStatement newStatement) { + ASTNode newNode = newStatement.getNode().copyElement(); + oldStatement.getParent().getNode().replaceChild(oldStatement.getNode(), newNode); + return (JSStatement)newNode.getPsi(); + } + + @RequiredWriteAction + public static void doIdentifierReplacement(PsiElement parent, PsiElement identifier, String name) { + ASTNode nameElement = JSChangeUtil.createNameIdentifier(parent.getProject(), name); + parent.getNode().replaceChild(identifier.getNode(), nameElement); + } + + @RequiredWriteAction + public static PsiElement doAddBefore(PsiElement jsElement, PsiElement element, PsiElement anchor) + throws IncorrectOperationException { + if (!JSChangeUtil.isStatementOrComment(element) && !(element instanceof PsiWhiteSpace)) { + throw new UnsupportedOperationException("js statement or whitespace expected"); + } + + return doDoAddBefore(jsElement, element, anchor); + } + + @RequiredWriteAction + public static PsiElement doDoAddBefore(PsiElement jsElement, PsiElement element, PsiElement anchor) throws IncorrectOperationException { + ASTNode elementNode = element.getNode(); + if (elementNode == null) { + throw new IncorrectOperationException("node should not be null"); + } + ASTNode copiedElementNode = elementNode.copyElement(); + ASTNode parentNode = jsElement.getNode(); + ASTNode anchorNode = anchor != null ? anchor.getNode() : null; + + anchorNode = insertWhitespaceIfNeeded(anchorNode, elementNode, parentNode, anchorNode); + + parentNode.addChild(copiedElementNode, anchorNode != null ? anchorNode : null); + if (copiedElementNode.getPsi() instanceof PsiComment comment && parentNode.getPsi().isPhysical()) { // HACK ! + CodeStyleManager.getInstance(element.getProject()).reformatNewlyAddedElement(parentNode, copiedElementNode); + } + + return copiedElementNode.getPsi(); + } + + @RequiredWriteAction + private static ASTNode insertWhitespaceIfNeeded( + ASTNode anchorNode, + ASTNode elementNode, + ASTNode parentNode, + ASTNode insertionPlaceNode + ) throws IncorrectOperationException { + ParserDefinition parserDef = ParserDefinition.forLanguage(parentNode.getPsi().getLanguage()); + TokenSet comments = parserDef.getCommentTokens(parentNode.getPsi().getLanguage().getVersions()[0]); + TokenSet whitespaces = parserDef.getWhitespaceTokens(parentNode.getPsi().getLanguage().getVersions()[0]); + + if (anchorNode != null + && (!whitespaces.contains(anchorNode.getElementType()) && !whitespaces.contains(elementNode.getElementType()) + || comments.contains(anchorNode.getElementType()) + || comments.contains(elementNode.getElementType()) + || elementNode.getPsi() instanceof PsiComment)) { + String commentString = " "; + if (comments.contains(anchorNode.getElementType()) + || comments.contains(elementNode.getElementType()) + || elementNode.getPsi() instanceof PsiComment) { + commentString = "\n"; + } + + ASTNode wsNode = + PsiParserFacade.SERVICE.getInstance(parentNode.getPsi().getProject()).createWhiteSpaceFromText(commentString).getNode(); + parentNode.addChild(wsNode, insertionPlaceNode); + anchorNode = wsNode; + } + return anchorNode; + } + + public static boolean isStatementContainer(PsiElement jsElement) { + return jsElement instanceof JSBlockStatement + || jsElement instanceof JSEmbeddedContentImpl + || jsElement instanceof JSClass + || jsElement instanceof JSPackageStatement; + } + + public static boolean isStatementOrComment(PsiElement jsElement) { + return jsElement instanceof JSSourceElement || jsElement instanceof PsiComment; + } + + @RequiredWriteAction + public static PsiElement doAddAfter(PsiElement jsElement, PsiElement element, PsiElement anchor) + throws IncorrectOperationException { + if (!JSChangeUtil.isStatementOrComment(element) && !(element instanceof PsiWhiteSpace)) { + throw new UnsupportedOperationException("js statement or whitespace expected"); + } + + return doDoAddAfter(jsElement, element, anchor); + } + + @RequiredWriteAction + public static PsiElement doDoAddAfter(PsiElement jsElement, PsiElement element, PsiElement anchor) throws IncorrectOperationException { + ASTNode parentNode = jsElement.getNode(); + ASTNode node = element.getNode(); + ASTNode anchorNode = anchor != null ? anchor.getNode() : parentNode.getLastChildNode(); + anchorNode = insertWhitespaceIfNeeded(anchorNode, node, parentNode, anchorNode != null ? anchorNode.getTreeNext() : null); + + ASTNode nodeCopy = node.copyElement(); + + if (anchor == null) { + parentNode.addChild(nodeCopy); + } + else { + parentNode.addChild(nodeCopy, anchorNode.getTreeNext()); + } + + ASTNode nextAfter = nodeCopy.getTreeNext(); + insertWhitespaceIfNeeded(nextAfter, node, parentNode, nextAfter); + + return nodeCopy.getPsi(); + } + + @RequiredWriteAction + public static PsiElement doAddRangeBefore(PsiElement parent, PsiElement first, PsiElement last, PsiElement anchor) + throws IncorrectOperationException { + PsiElement resultElement; + PsiElement psiElement = resultElement = doAddBefore(parent, first, anchor); + + while (first != last) { + first = first.getNextSibling(); + if (first == null) { + break; + } + psiElement = doAddAfter(parent, first, psiElement); + } + + return resultElement; + } + + @RequiredWriteAction + public static PsiElement doAddRangeAfter(PsiElement jsElement, PsiElement first, PsiElement last, PsiElement anchor) + throws IncorrectOperationException { + PsiElement resultElement; + PsiElement psiElement = resultElement = doAddAfter(jsElement, first, anchor); + + while (first != last) { + first = first.getNextSibling(); + if (first == null) { + break; + } + psiElement = doAddAfter(jsElement, first, psiElement); + } + + return resultElement; + } + + public static boolean isBlockStatementContainer(JSElement jsElement) { + return jsElement instanceof JSIfStatement || jsElement instanceof JSLoopStatement; + } + + @RequiredWriteAction + public static PsiElement blockDoAddRangeBefore(PsiElement first, PsiElement last, @Nonnull PsiElement anchor) + throws IncorrectOperationException { + BlockAddContext addContext = new BlockAddContext(anchor) { + @Override + PsiElement doAddElement(PsiElement... element) throws IncorrectOperationException { + return newlyAddedBlock.addRangeBefore(element[0], element[1], codeBlockAnchor); + } + }; + + return addContext.doAddElement(first, last); + } + + @RequiredWriteAction + public static PsiElement blockDoAddRangeAfter(PsiElement first, PsiElement last, @Nonnull PsiElement anchor) + throws IncorrectOperationException { + BlockAddContext addContext = new BlockAddContext(anchor) { + @Override + PsiElement doAddElement(PsiElement... element) throws IncorrectOperationException { + return newlyAddedBlock.addRangeAfter(element[0], element[1], codeBlockAnchor); + } + }; + + return addContext.doAddElement(first, last); + } + + @RequiredWriteAction + public static PsiElement blockDoAddAfter(PsiElement element, @Nonnull PsiElement anchor) throws IncorrectOperationException { + BlockAddContext addContext = new BlockAddContext(anchor) { + @Override + PsiElement doAddElement(PsiElement... element) throws IncorrectOperationException { + return newlyAddedBlock.addAfter(element[0], codeBlockAnchor); + } + }; + + return addContext.doAddElement(element); + } + + @RequiredWriteAction + public static PsiElement blockDoAddBefore(PsiElement element, @Nonnull PsiElement anchor) throws IncorrectOperationException { + BlockAddContext addContext = new BlockAddContext(anchor) { + @Override + PsiElement doAddElement(PsiElement... element) throws IncorrectOperationException { + return newlyAddedBlock.addBefore(element[0], codeBlockAnchor); + } + }; + + return addContext.doAddElement(element); + } + + public static String getSemicolon(Project project) { + return CodeStyleSettingsManager.getInstance(project).getCurrentSettings().getCustomSettings(JSCodeStyleSettings.class) + .USE_SEMICOLON_AFTER_STATEMENT ? ";" : ""; + } + + abstract static class BlockAddContext { + final JSBlockStatement newlyAddedBlock; + final PsiElement codeBlockAnchor; + + @RequiredWriteAction + BlockAddContext(@Nonnull PsiElement _anchor) throws IncorrectOperationException { + ASTNode codeBlockNode = JSChangeUtil.createStatementFromText(_anchor.getProject(), "{ a }"); + + newlyAddedBlock = (JSBlockStatement)_anchor.replace(codeBlockNode.getPsi()); + + JSStatement artificiallyAddedBlockAnchor = newlyAddedBlock.getStatements()[0]; + codeBlockAnchor = newlyAddedBlock.addBefore(_anchor, artificiallyAddedBlockAnchor); + artificiallyAddedBlockAnchor.delete(); + } + + abstract PsiElement doAddElement(PsiElement... element) throws IncorrectOperationException; + } + + @RequiredWriteAction + static void removeRangeWithRemovalOfCommas(ASTNode myNode, ASTNode parent) { + ASTNode from = myNode, to = myNode.getTreeNext(); + boolean seenComma = false; + + if (to != null && to.getElementType() == JSTokenTypes.WHITE_SPACE) { + to = to.getTreeNext(); + } + + if (to != null && to.getElementType() == JSTokenTypes.COMMA) { + to = to.getTreeNext(); + seenComma = true; + + if (to != null && to.getElementType() == JSTokenTypes.WHITE_SPACE) { + to = to.getTreeNext(); + } + } + + if (!seenComma) { + ASTNode treePrev = from.getTreePrev(); + + if (treePrev != null && treePrev.getElementType() == JSTokenTypes.WHITE_SPACE) { + treePrev = treePrev.getTreePrev(); + } + if (treePrev != null && treePrev.getElementType() == JSTokenTypes.COMMA) { + from = treePrev; + } + + if (to != null && to.getElementType() == JSTokenTypes.WHITE_SPACE) { + to = to.getTreeNext(); + } + } + parent.removeRange(from, to); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSClassBase.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSClassBase.java index a0e53a6b..e0b3116d 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSClassBase.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSClassBase.java @@ -22,7 +22,11 @@ import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; import com.intellij.lang.javascript.psi.resolve.ResolveProcessor; import com.intellij.lang.javascript.psi.stubs.JSClassStub; -import consulo.application.util.*; +import consulo.annotation.access.RequiredReadAction; +import consulo.application.util.CachedValueProvider; +import consulo.application.util.CachedValuesManager; +import consulo.application.util.ParameterizedCachedValue; +import consulo.application.util.UserDataCache; import consulo.javascript.impl.language.psi.JSStubElementType; import consulo.language.ast.ASTNode; import consulo.language.ast.IElementType; @@ -35,506 +39,420 @@ import consulo.util.collection.ArrayFactory; import consulo.util.collection.ArrayUtil; import consulo.util.dataholder.Key; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.*; /** * @author Maxim.Mossienko */ -public abstract class JSClassBase extends JSStubElementImpl implements JSClass -{ - private volatile Map myName2FunctionMap; - private volatile Map myName2FieldsMap; - private static Key, Object>> ourImplementsListCacheKey = Key.create("implements.list.cache"); - private static Key, Object>> ourExtendsListCacheKey = Key.create("implements.list.cache"); - private static UserDataCache, Object>, JSClassBase, Object> ourImplementsListCache = new - ClassesUserDataCache(); - private static UserDataCache, Object>, JSClassBase, - Object> ourExtendsListCache = new ExtendsClassesUserDataCache(); - - protected JSClassBase(final ASTNode node) - { - super(node); - } - - public JSClassBase(final JSClassStub stub, final JSStubElementType aClass) - { - super(stub, aClass); - } - - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSClass(this); - } - - @Override - public void subtreeChanged() - { - dropCaches(); - - super.subtreeChanged(); - } - - @Override - protected Object clone() - { - final JSClassBase o = (JSClassBase) super.clone(); - o.dropCaches(); - return o; - } - - private void dropCaches() - { - synchronized(this) - { - myName2FunctionMap = null; - myName2FieldsMap = null; - } - } - - @Override - public JSFunction[] getFunctions() - { - final JSClassStub classStub = getStub(); - if(classStub != null) - { - return getStubChildrenByType(classStub, JSElementTypes.FUNCTION_DECLARATION, JSFunction.ARRAY_FACTORY); - } - else - { - final List functions = new ArrayList(); - processDeclarations(new PsiScopeProcessor() - { - @Override - public boolean execute(final PsiElement element, final ResolveState state) - { - if(element instanceof JSFunction) - { - functions.add((JSFunction) element); - } - return true; - } - - @Override - public T getHint(final Key hintClass) - { - return null; - } - - @Override - public void handleEvent(final Event event, final Object associated) - { - } - }, ResolveState.initial(), this, this); - return functions.toArray(JSFunction.EMPTY_ARRAY); - } - } - - @Override - public JSFunction findFunctionByName(String functionName) - { - if(functionName == null) - { - return null; - } - final Map name2FunctionMap = initFunctions(); - final Object o = name2FunctionMap.get(functionName); - if(o instanceof JSFunction) - { - return (JSFunction) o; - } - else if(o instanceof JSFunction[]) - { - return ((JSFunction[]) o)[0]; - } - return null; - } - - @Override - public JSVariable[] getFields() - { - final JSClassStub classStub = getStub(); - final List vars = new ArrayList(3); - - if(classStub != null) - { - for(JSVarStatement var : getStubChildrenByType(classStub, JSElementTypes.VAR_STATEMENT, new ArrayFactory() - { - @Override - public JSVarStatement[] create(final int count) - { - return new JSVarStatement[count]; - } - })) - { - vars.addAll(Arrays.asList(var.getVariables())); - } - } - else - { - processDeclarations(new PsiScopeProcessor() - { - @Override - public boolean execute(final PsiElement element, final ResolveState state) - { - if(element instanceof JSVariable) - { - vars.add((JSVariable) element); - } - return true; - } - - @Override - public T getHint(final Key hintClass) - { - return null; - } - - @Override - public void handleEvent(final Event event, final Object associated) - { - } - }, ResolveState.initial(), this, this); - } - return vars.toArray(JSVariable.EMPTY_ARRAY); - } - - @Override - public JSVariable findFieldByName(String name) - { - return initFields().get(name); - } - - private - @Nonnull - Map initFields() - { - Map name2FieldsMap = myName2FieldsMap; - - if(name2FieldsMap == null) - { - synchronized(this) - { - name2FieldsMap = myName2FieldsMap; - - if(name2FieldsMap == null) - { - name2FieldsMap = new HashMap(); - - for(JSVariable variable : getFields()) - { - final String name = variable.getName(); - - if(name != null) - { - name2FieldsMap.put(name, variable); - } - } - myName2FieldsMap = name2FieldsMap; - } - } - } - return name2FieldsMap; - } - - private - @Nonnull - Map initFunctions() - { - Map name2FunctionMap = myName2FunctionMap; - - if(name2FunctionMap == null) - { - synchronized(this) - { - name2FunctionMap = myName2FunctionMap; - - if(name2FunctionMap == null) - { - name2FunctionMap = new HashMap(); - - for(JSFunction function : getFunctions()) - { - final String name = function.getName(); - - if(name != null) - { - final Object o = name2FunctionMap.get(name); - if(o == null) - { - name2FunctionMap.put(name, function); - } - else if(o instanceof JSFunction) - { - name2FunctionMap.put(name, new JSFunction[]{ - (JSFunction) o, - function - }); - } - else if(o instanceof JSFunction[]) - { - name2FunctionMap.put(name, ArrayUtil.append((JSFunction[]) o, function)); - } - } - } - myName2FunctionMap = name2FunctionMap; - } - } - } - return name2FunctionMap; - } - - @Override - public JSFunction findFunctionByNameAndKind(final String name, JSFunction.FunctionKind kind) - { - if(name == null) - { - return null; - } - Map name2FunctionMap = initFunctions(); - final Object o = name2FunctionMap.get(name); - - if(o instanceof JSFunction) - { - final JSFunction function = (JSFunction) o; - return function.getKind() == kind ? function : null; - } - else if(o instanceof JSFunction[]) - { - for(JSFunction fun : (JSFunction[]) o) - { - if(fun.getKind() == kind) - { - return fun; - } - } - } - return null; - } - - @Override - public JSClass[] getSupers() - { - List superClasses = new ArrayList(getClassesFromReferenceList(getExtendsList(), JSElementTypes.EXTENDS_LIST)); - superClasses.addAll(getClassesFromReferenceList(getImplementsList(), JSElementTypes.IMPLEMENTS_LIST)); - return superClasses.toArray(new JSClass[superClasses.size()]); - } - - private List getClassesFromReferenceList(final @Nullable JSReferenceList extendsList, @Nonnull IElementType type) - { - final PsiElement element = extendsList != null ? extendsList : this; - - if(type == JSElementTypes.EXTENDS_LIST) - { - return ourExtendsListCache.get(ourExtendsListCacheKey, this, extendsList).getValue(element); - } - else - { - return ourImplementsListCache.get(ourImplementsListCacheKey, this, extendsList).getValue(element); - } - } - - @Override - public boolean processDeclarations(@Nonnull final PsiScopeProcessor processor, @Nonnull final ResolveState substitutor, - final PsiElement lastParent, @Nonnull final PsiElement place) - { - final ResolveProcessor resolveProcessor = processor instanceof ResolveProcessor ? (ResolveProcessor) processor : null; - final boolean toProcessClass = resolveProcessor != null && resolveProcessor.isTypeContext(); - - if(toProcessClass) - { - if(!processor.execute(this, null)) - { - return false; - } - } - - if(lastParent == null) - { - return true; - } - - processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, this); - final boolean toProcessMembers = (resolveProcessor == null || (!resolveProcessor.isToSkipClassDeclarationOnce() && resolveProcessor - .isToProcessMembers())); - if(toProcessMembers) - { - if(!processMembers(processor, substitutor, lastParent, place)) - { - return false; - } - } - else - { - resolveProcessor.setToSkipClassDeclarationsOnce(false); - } - - final boolean toProcessInHierarchy = processor instanceof ResolveProcessor && ((ResolveProcessor) processor).isToProcessHierarchy(); - - if(!toProcessInHierarchy || ((ResolveProcessor) processor).checkVisited(getQualifiedName())) - { - return true; - } - - for(JSClass clazz : getSuperClasses()) - { - if(!clazz.processDeclarations(processor, ResolveState.initial(), lastParent, place)) - { - return false; - } - } - - return true; - } - - protected abstract boolean processMembers(final PsiScopeProcessor processor, final ResolveState substitutor, final PsiElement lastParent, - final PsiElement place); - - @Override - public JSClass[] getSuperClasses() - { - final JSReferenceList extendsList = getExtendsList(); - final List supers = getClassesFromReferenceList(extendsList, JSElementTypes.EXTENDS_LIST); - return supers.toArray(new JSClass[supers.size()]); - } - - public static PsiElement findClassFromNamespace(final String qname, PsiElement context) - { - PsiElement realClazz = null; - final PsiElement clazz = JSResolveUtil.findClassByQName(qname, context); - - realClazz = clazz; - return realClazz; - } - - @Override - public JSClass[] getImplementedInterfaces() - { - final JSReferenceList implementsList = getImplementsList(); - if(implementsList == null) - { - return JSClass.EMPTY_ARRAY; - } - final List classes = getClassesFromReferenceList(implementsList, JSElementTypes.IMPLEMENTS_LIST); - return classes.toArray(new JSClass[classes.size()]); - } - - private static class ExtendsClassesUserDataCache extends ClassesUserDataCache - { - @Override - protected List doCompute(final Object extendsList) - { - if(extendsList instanceof JSClass) - { - final JSClass jsClass = (JSClass) extendsList; - - final ArrayList supers = new ArrayList(1); - if(!"Object".equals(jsClass.getQualifiedName())) - { - final PsiElement element = findClassFromNamespace("Object", jsClass); - if(element instanceof JSClass) - { - supers.add((JSClass) element); - } - } - - return supers; - } - return super.doCompute(extendsList); - } - } - - private static class ClassesUserDataCache extends UserDataCache, Object>, JSClassBase, Object> - { - @Override - protected ParameterizedCachedValue, Object> compute(final JSClassBase jsClassBase, final Object p) - { - return CachedValuesManager.getManager(jsClassBase.getProject()).createParameterizedCachedValue(new - ParameterizedCachedValueProvider, Object>() - { - @Override - public CachedValueProvider.Result> compute(Object list) - { - return new CachedValueProvider.Result>(doCompute(list), PsiModificationTracker.MODIFICATION_COUNT); - } - }, false); - } - - protected List doCompute(final Object object) - { - if(object instanceof JSClass) - { - return Collections.emptyList(); - } - - final ArrayList supers = new ArrayList(1); - final JSReferenceList extendsList = (JSReferenceList) object; - - for(String refText : extendsList.getReferenceTexts()) - { - refText = JSImportHandlingUtil.resolveTypeName(refText, extendsList.getParent()); - final PsiElement element = findClassFromNamespace(refText, extendsList.getParent()); - if(element instanceof JSClass) - { - supers.add((JSClass) element); - } - } - return supers; - } - } - - private static E[] getStubChildrenByType(JSClassStub stub, final IElementType elementType, ArrayFactory f) - { - assert JSElementTypes.INCLUDE_DIRECTIVE != elementType; - - ArrayList result = new ArrayList(Arrays.asList(stub.getChildrenByType(elementType, f))); - JSIncludeDirective[] includes = stub.getChildrenByType(JSElementTypes.INCLUDE_DIRECTIVE, new ArrayFactory() - { - @Override - public JSIncludeDirective[] create(final int count) - { - return new JSIncludeDirective[count]; - } - }); - Collection visited = new HashSet(); - TokenSet filter = TokenSet.create(JSElementTypes.INCLUDE_DIRECTIVE, elementType); - for(JSIncludeDirective include : includes) - { - PsiFile file = include.resolveFile(); - if(file instanceof JSFile) - { - process(filter, (JSFile) file, result, visited); - } - } - return result.toArray(f.create(result.size())); - } - - private static void process(TokenSet filter, final JSFile file, final ArrayList result, final Collection visited) - { - if(visited.contains(file)) - { - return; - } - visited.add(file); - for(PsiElement element : JSResolveUtil.getStubbedChildren(file, filter)) - { - if(element instanceof JSIncludeDirective) - { - PsiFile includedFile = ((JSIncludeDirective) element).resolveFile(); - if(includedFile instanceof JSFile) - { - process(filter, (JSFile) includedFile, result, visited); - } - } - else - { - result.add((E) element); - } - } - } - - +public abstract class JSClassBase extends JSStubElementImpl implements JSClass { + private static final Key, Object>> IMPLEMENTS_LIST_CACHE_KEY = Key.create("implements.list.cache"); + private static final Key, Object>> EXTENDS_LIST_CACHE_KEY = Key.create("implements.list.cache"); + private static final UserDataCache, Object>, JSClassBase, Object> IMPLEMENTS_LIST_CACHE = + new ClassesUserDataCache(); + private static final UserDataCache, Object>, JSClassBase, Object> EXTENDS_LIST_CACHE = + new ExtendsClassesUserDataCache(); + + private volatile Map myName2FunctionMap; + private volatile Map myName2FieldsMap; + + protected JSClassBase(ASTNode node) { + super(node); + } + + public JSClassBase(JSClassStub stub, JSStubElementType aClass) { + super(stub, aClass); + } + + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSClass(this); + } + + @Override + public void subtreeChanged() { + dropCaches(); + + super.subtreeChanged(); + } + + @Override + protected Object clone() { + JSClassBase o = (JSClassBase)super.clone(); + o.dropCaches(); + return o; + } + + private void dropCaches() { + synchronized (this) { + myName2FunctionMap = null; + myName2FieldsMap = null; + } + } + + @Override + @RequiredReadAction + public JSFunction[] getFunctions() { + JSClassStub classStub = getStub(); + if (classStub != null) { + return getStubChildrenByType(classStub, JSElementTypes.FUNCTION_DECLARATION, JSFunction.ARRAY_FACTORY); + } + else { + final List functions = new ArrayList<>(); + processDeclarations( + new PsiScopeProcessor() { + @Override + public boolean execute(@Nonnull PsiElement element, ResolveState state) { + if (element instanceof JSFunction function) { + functions.add(function); + } + return true; + } + + @Override + public T getHint(@Nonnull Key hintClass) { + return null; + } + + @Override + public void handleEvent(Event event, Object associated) { + } + }, + ResolveState.initial(), + this, + this + ); + return functions.toArray(JSFunction.EMPTY_ARRAY); + } + } + + @Override + @RequiredReadAction + public JSFunction findFunctionByName(String functionName) { + if (functionName == null) { + return null; + } + Map name2FunctionMap = initFunctions(); + Object o = name2FunctionMap.get(functionName); + if (o instanceof JSFunction function) { + return function; + } + else if (o instanceof JSFunction[] functions) { + return functions[0]; + } + return null; + } + + @Override + @RequiredReadAction + public JSVariable[] getFields() { + JSClassStub classStub = getStub(); + final List vars = new ArrayList<>(3); + + if (classStub != null) { + for (JSVarStatement var : getStubChildrenByType(classStub, JSElementTypes.VAR_STATEMENT, JSVarStatement[]::new)) { + vars.addAll(Arrays.asList(var.getVariables())); + } + } + else { + processDeclarations( + new PsiScopeProcessor() { + @Override + public boolean execute(@Nonnull PsiElement element, ResolveState state) { + if (element instanceof JSVariable variable) { + vars.add(variable); + } + return true; + } + + @Override + public T getHint(@Nonnull Key hintClass) { + return null; + } + + @Override + public void handleEvent(Event event, Object associated) { + } + }, + ResolveState.initial(), + this, + this + ); + } + return vars.toArray(JSVariable.EMPTY_ARRAY); + } + + @Override + @RequiredReadAction + public JSVariable findFieldByName(String name) { + return initFields().get(name); + } + + @Nonnull + @RequiredReadAction + private Map initFields() { + Map name2FieldsMap = myName2FieldsMap; + + if (name2FieldsMap == null) { + synchronized (this) { + name2FieldsMap = myName2FieldsMap; + + if (name2FieldsMap == null) { + name2FieldsMap = new HashMap<>(); + + for (JSVariable variable : getFields()) { + String name = variable.getName(); + + if (name != null) { + name2FieldsMap.put(name, variable); + } + } + myName2FieldsMap = name2FieldsMap; + } + } + } + return name2FieldsMap; + } + + @Nonnull + @RequiredReadAction + private Map initFunctions() { + Map name2FunctionMap = myName2FunctionMap; + + if (name2FunctionMap == null) { + synchronized (this) { + name2FunctionMap = myName2FunctionMap; + + if (name2FunctionMap == null) { + name2FunctionMap = new HashMap<>(); + + for (JSFunction function : getFunctions()) { + String name = function.getName(); + + if (name != null) { + Object o = name2FunctionMap.get(name); + if (o == null) { + name2FunctionMap.put(name, function); + } + else if (o instanceof JSFunction sameNameFunction) { + name2FunctionMap.put(name, new JSFunction[]{sameNameFunction, function}); + } + else if (o instanceof JSFunction[] sameNameFunctions) { + name2FunctionMap.put(name, ArrayUtil.append(sameNameFunctions, function)); + } + } + } + myName2FunctionMap = name2FunctionMap; + } + } + } + return name2FunctionMap; + } + + @Override + @RequiredReadAction + public JSFunction findFunctionByNameAndKind(String name, JSFunction.FunctionKind kind) { + if (name == null) { + return null; + } + Map name2FunctionMap = initFunctions(); + Object o = name2FunctionMap.get(name); + + if (o instanceof JSFunction function) { + return function.getKind() == kind ? function : null; + } + else if (o instanceof JSFunction[] functions) { + for (JSFunction fun : functions) { + if (fun.getKind() == kind) { + return fun; + } + } + } + return null; + } + + @Override + public JSClass[] getSupers() { + List superClasses = new ArrayList<>(getClassesFromReferenceList(getExtendsList(), JSElementTypes.EXTENDS_LIST)); + superClasses.addAll(getClassesFromReferenceList(getImplementsList(), JSElementTypes.IMPLEMENTS_LIST)); + return superClasses.toArray(new JSClass[superClasses.size()]); + } + + private List getClassesFromReferenceList(@Nullable JSReferenceList extendsList, @Nonnull IElementType type) { + PsiElement element = extendsList != null ? extendsList : this; + + if (type == JSElementTypes.EXTENDS_LIST) { + return EXTENDS_LIST_CACHE.get(EXTENDS_LIST_CACHE_KEY, this, extendsList).getValue(element); + } + else { + return IMPLEMENTS_LIST_CACHE.get(IMPLEMENTS_LIST_CACHE_KEY, this, extendsList).getValue(element); + } + } + + @Override + @RequiredReadAction + public boolean processDeclarations( + @Nonnull PsiScopeProcessor processor, + @Nonnull ResolveState substitutor, + PsiElement lastParent, + @Nonnull PsiElement place + ) { + ResolveProcessor resolveProcessor = processor instanceof ResolveProcessor rProcessor ? rProcessor : null; + boolean toProcessClass = resolveProcessor != null && resolveProcessor.isTypeContext(); + + if (toProcessClass) { + if (!processor.execute(this, null)) { + return false; + } + } + + if (lastParent == null) { + return true; + } + + processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, this); + boolean toProcessMembers = resolveProcessor == null + || !resolveProcessor.isToSkipClassDeclarationOnce() && resolveProcessor.isToProcessMembers(); + if (toProcessMembers) { + if (!processMembers(processor, substitutor, lastParent, place)) { + return false; + } + } + else { + resolveProcessor.setToSkipClassDeclarationsOnce(false); + } + + boolean toProcessInHierarchy = resolveProcessor != null && resolveProcessor.isToProcessHierarchy(); + + if (!toProcessInHierarchy || resolveProcessor.checkVisited(getQualifiedName())) { + return true; + } + + for (JSClass clazz : getSuperClasses()) { + if (!clazz.processDeclarations(processor, ResolveState.initial(), lastParent, place)) { + return false; + } + } + + return true; + } + + protected abstract boolean processMembers( + PsiScopeProcessor processor, + ResolveState substitutor, + PsiElement lastParent, + PsiElement place + ); + + @Override + public JSClass[] getSuperClasses() { + JSReferenceList extendsList = getExtendsList(); + List supers = getClassesFromReferenceList(extendsList, JSElementTypes.EXTENDS_LIST); + return supers.toArray(new JSClass[supers.size()]); + } + + @RequiredReadAction + public static PsiElement findClassFromNamespace(String qName, PsiElement context) { + return JSResolveUtil.findClassByQName(qName, context); + } + + @Override + public JSClass[] getImplementedInterfaces() { + JSReferenceList implementsList = getImplementsList(); + if (implementsList == null) { + return JSClass.EMPTY_ARRAY; + } + List classes = getClassesFromReferenceList(implementsList, JSElementTypes.IMPLEMENTS_LIST); + return classes.toArray(new JSClass[classes.size()]); + } + + private static class ExtendsClassesUserDataCache extends ClassesUserDataCache { + @Override + @RequiredReadAction + protected List doCompute(Object extendsList) { + if (extendsList instanceof JSClass jsClass) { + ArrayList supers = new ArrayList<>(1); + if (!"Object".equals(jsClass.getQualifiedName())) { + PsiElement element = findClassFromNamespace("Object", jsClass); + if (element instanceof JSClass elementClass) { + supers.add(elementClass); + } + } + + return supers; + } + return super.doCompute(extendsList); + } + } + + private static class ClassesUserDataCache extends UserDataCache, Object>, JSClassBase, Object> { + @Override + protected ParameterizedCachedValue, Object> compute(JSClassBase jsClassBase, Object p) { + return CachedValuesManager.getManager(jsClassBase.getProject()).createParameterizedCachedValue( + list -> new CachedValueProvider.Result<>(doCompute(list), PsiModificationTracker.MODIFICATION_COUNT), + false + ); + } + + @RequiredReadAction + protected List doCompute(Object object) { + if (object instanceof JSClass) { + return Collections.emptyList(); + } + + ArrayList supers = new ArrayList<>(1); + JSReferenceList extendsList = (JSReferenceList)object; + + for (String refText : extendsList.getReferenceTexts()) { + refText = JSImportHandlingUtil.resolveTypeName(refText, extendsList.getParent()); + PsiElement element = findClassFromNamespace(refText, extendsList.getParent()); + if (element instanceof JSClass jsClass) { + supers.add(jsClass); + } + } + return supers; + } + } + + private static E[] getStubChildrenByType(JSClassStub stub, IElementType elementType, ArrayFactory f) { + assert JSElementTypes.INCLUDE_DIRECTIVE != elementType; + + ArrayList result = new ArrayList<>(Arrays.asList(stub.getChildrenByType(elementType, f))); + JSIncludeDirective[] includes = stub.getChildrenByType(JSElementTypes.INCLUDE_DIRECTIVE, JSIncludeDirective[]::new); + Collection visited = new HashSet<>(); + TokenSet filter = TokenSet.create(JSElementTypes.INCLUDE_DIRECTIVE, elementType); + for (JSIncludeDirective include : includes) { + PsiFile file = include.resolveFile(); + if (file instanceof JSFile jsFile) { + process(filter, jsFile, result, visited); + } + } + return result.toArray(f.create(result.size())); + } + + @SuppressWarnings("unchecked") + private static void process( + TokenSet filter, + JSFile file, + ArrayList result, + Collection visited + ) { + if (visited.contains(file)) { + return; + } + visited.add(file); + for (PsiElement element : JSResolveUtil.getStubbedChildren(file, filter)) { + if (element instanceof JSIncludeDirective includeDirective) { + PsiFile includedFile = includeDirective.resolveFile(); + if (includedFile instanceof JSFile jsFile) { + process(filter, jsFile, result, visited); + } + } + else { + result.add((E)element); + } + } + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSClassExpressionImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSClassExpressionImpl.java index fe01504a..e934fa45 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSClassExpressionImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSClassExpressionImpl.java @@ -8,38 +8,33 @@ import consulo.javascript.language.psi.JavaScriptType; import consulo.javascript.lang.psi.impl.JavaScriptClassType; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL - * @since 11/12/2021 + * @since 2021-12-11 */ -public class JSClassExpressionImpl extends JSExpressionImpl implements JSClassExpression -{ - public JSClassExpressionImpl(ASTNode node) - { - super(node); - } +public class JSClassExpressionImpl extends JSExpressionImpl implements JSClassExpression { + public JSClassExpressionImpl(ASTNode node) { + super(node); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSExpression(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSExpression(this); + } - @RequiredReadAction - @Nonnull - @Override - public JSClass getClassElement() - { - return findNotNullChildByClass(JSClass.class); - } + @Nonnull + @Override + @RequiredReadAction + public JSClass getClassElement() { + return findNotNullChildByClass(JSClass.class); + } - @RequiredReadAction - @Nonnull - @Override - public JavaScriptType getType() - { - return new JavaScriptClassType(getClassElement()); - } + @Nonnull + @Override + @RequiredReadAction + public JavaScriptType getType() { + return new JavaScriptClassType(getClassElement()); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSClassImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSClassImpl.java index b8cc7fc2..5d86428d 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSClassImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSClassImpl.java @@ -16,228 +16,192 @@ package com.intellij.lang.javascript.psi.impl; -import javax.annotation.Nonnull; - -import consulo.language.psi.PsiElement; -import org.jetbrains.annotations.NonNls; import com.intellij.javascript.documentation.JSDocumentationUtils; -import consulo.language.ast.ASTNode; import com.intellij.lang.javascript.JSElementTypes; import com.intellij.lang.javascript.JSTokenTypes; -import com.intellij.lang.javascript.psi.JSAttributeList; -import com.intellij.lang.javascript.psi.JSClass; -import com.intellij.lang.javascript.psi.JSFile; -import com.intellij.lang.javascript.psi.JSFunction; -import com.intellij.lang.javascript.psi.JSReferenceExpression; -import com.intellij.lang.javascript.psi.JSReferenceList; -import consulo.javascript.impl.language.psi.JSStubElementType; -import com.intellij.lang.javascript.psi.JSSuppressionHolder; +import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.resolve.JSImportHandlingUtil; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; import com.intellij.lang.javascript.psi.stubs.JSClassStub; -import consulo.language.psi.resolve.ResolveState; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; +import consulo.javascript.impl.language.psi.JSStubElementType; +import consulo.javascript.lang.JavaScriptTokenSets; +import consulo.language.ast.ASTNode; import consulo.language.codeStyle.CodeStyleManager; +import consulo.language.psi.PsiElement; import consulo.language.psi.resolve.PsiScopeProcessor; +import consulo.language.psi.resolve.ResolveState; import consulo.language.util.IncorrectOperationException; -import consulo.annotation.access.RequiredReadAction; -import consulo.javascript.lang.JavaScriptTokenSets; +import jakarta.annotation.Nonnull; /** - * @by Maxim.Mossienko + * @author Maxim.Mossienko */ -public class JSClassImpl extends JSClassBase implements JSSuppressionHolder -{ - public JSClassImpl(final ASTNode node) - { - super(node); - } - - public JSClassImpl(final JSClassStub stub, JSStubElementType elementType) - { - super(stub, elementType); - } - - @RequiredReadAction - @Override - public int getTextOffset() - { - PsiElement nameIdentifier = getNameIdentifier(); - return nameIdentifier == null ? super.getTextOffset() : nameIdentifier.getTextOffset(); - } - - @Override - public JSAttributeList getAttributeList() - { - return getStubOrPsiChild(JSElementTypes.ATTRIBUTE_LIST); - } - - @Override - @RequiredReadAction - public String getName() - { - final JSClassStub classStub = getStub(); - if(classStub != null) - { - return classStub.getName(); - } - - PsiElement nameIdentifier = getNameIdentifier(); - if(nameIdentifier instanceof JSReferenceExpression) - { - return ((JSReferenceExpression) nameIdentifier).getReferencedName(); - } - else if(nameIdentifier != null) - { - return nameIdentifier.getText(); - } - return null; - } - - @Override - @RequiredReadAction - public PsiElement setName(@NonNls @Nonnull String newName) throws IncorrectOperationException - { - newName = newName.substring(newName.lastIndexOf('.') + 1); - final String oldName = getName(); - if(newName.equals(oldName)) - { - return this; - } - final JSFunction constructor = findFunctionByName(oldName); - - PsiElement nameIdentifier = getNameIdentifier(); - assert nameIdentifier != null; - getNode().replaceChild(nameIdentifier.getNode(), JSChangeUtil.createExpressionFromText(getProject(), newName).getNode()); - - if(constructor != null) - { - constructor.setName(newName); - } - - JSPsiImplUtils.updateFileName(this, newName, oldName); - - return this; - } - - @Override - @RequiredReadAction - public PsiElement getNameIdentifier() - { - return findChildByType(JavaScriptTokenSets.NAME_TOKEN_TYPES); - } - - @Override - public JSReferenceList getExtendsList() - { - return getStubOrPsiChild(JSElementTypes.EXTENDS_LIST); - } - - @Override - public JSReferenceList getImplementsList() - { - return getStubOrPsiChild(JSElementTypes.IMPLEMENTS_LIST); - } - - @Override - public - @NonNls - String getQualifiedName() - { - final JSClassStub classStub = getStub(); - if(classStub != null) - { - return classStub.getQualifiedName(); - } - return JSPsiImplUtils.getQName(this); - } - - @Override - public boolean isInterface() - { - final JSClassStub classStub = getStub(); - if(classStub != null) - { - return classStub.isInterface(); - } - return getNode().findChildByType(JSTokenTypes.INTERFACE_KEYWORD) != null; - } - - @Override - public void delete() throws IncorrectOperationException - { - getNode().getTreeParent().removeChild(getNode()); - } - - @Override - public boolean isDeprecated() - { - final JSClassStub stub = getStub(); - if(stub != null) - { - return stub.isDeprecated(); - } - return JSDocumentationUtils.calculateDeprecated(this); - } - - @Override - protected boolean processMembers(final PsiScopeProcessor processor, final ResolveState substitutor, final PsiElement lastParent, final PsiElement place) - { - return JSResolveUtil.processDeclarationsInScope(this, processor, substitutor, lastParent, place); - } - - @Override - public boolean processDeclarations(@Nonnull final PsiScopeProcessor processor, @Nonnull final ResolveState substitutor, final PsiElement lastParent, @Nonnull final PsiElement place) - { - boolean b = super.processDeclarations(processor, substitutor, lastParent, place); - - if(b && lastParent != null && lastParent.getParent() == this && getParent() instanceof JSFile) - { - b = JSImportHandlingUtil.tryResolveImports(processor, this, place); - } - return b; - } - - @Override - public PsiElement addAfter(@Nonnull final PsiElement element, PsiElement anchor) throws IncorrectOperationException - { - if(anchor == null) - { - ASTNode node = getNode().findChildByType(JSTokenTypes.RBRACE); - if(node != null) - { - PsiElement psiElement = super.addAfter(element, node.getTreePrev().getPsi()); - CodeStyleManager.getInstance(getProject()).reformatNewlyAddedElement(getNode(), psiElement.getNode()); - return psiElement; - } - } - - final PsiElement psiElement = super.addAfter(element, anchor); - CodeStyleManager.getInstance(getProject()).reformatNewlyAddedElement(getNode(), psiElement.getNode()); - return psiElement; - } - - @Override - public PsiElement addBefore(@Nonnull final PsiElement element, final PsiElement anchor) throws IncorrectOperationException - { - final PsiElement superElement = super.addBefore(element, anchor); - CodeStyleManager.getInstance(getProject()).reformatNewlyAddedElement(getNode(), superElement.getNode()); - return superElement; - } - - @Override - public boolean isEquivalentTo(PsiElement another) - { - return super.isEquivalentTo(another) || - (another instanceof JSFile && - ((JSFile) another).getVirtualFile().getNameWithoutExtension().equals(getName()) && - another == getParent().getParent()) || - JSPsiImplUtils.isTheSameClass(another, this); - } - - @Override - public PsiElement getNavigationElement() - { - return JSPsiImplUtils.findTopLevelNavigatableElement(this); - } - +public class JSClassImpl extends JSClassBase implements JSSuppressionHolder { + public JSClassImpl(ASTNode node) { + super(node); + } + + public JSClassImpl(JSClassStub stub, JSStubElementType elementType) { + super(stub, elementType); + } + + @RequiredReadAction + @Override + public int getTextOffset() { + PsiElement nameIdentifier = getNameIdentifier(); + return nameIdentifier == null ? super.getTextOffset() : nameIdentifier.getTextOffset(); + } + + @Override + public JSAttributeList getAttributeList() { + return getStubOrPsiChild(JSElementTypes.ATTRIBUTE_LIST); + } + + @Override + @RequiredReadAction + public String getName() { + JSClassStub classStub = getStub(); + if (classStub != null) { + return classStub.getName(); + } + + PsiElement nameIdentifier = getNameIdentifier(); + if (nameIdentifier instanceof JSReferenceExpression referenceExpression) { + return referenceExpression.getReferencedName(); + } + else if (nameIdentifier != null) { + return nameIdentifier.getText(); + } + return null; + } + + @Override + @RequiredWriteAction + public PsiElement setName(@Nonnull String newName) throws IncorrectOperationException { + newName = newName.substring(newName.lastIndexOf('.') + 1); + String oldName = getName(); + if (newName.equals(oldName)) { + return this; + } + JSFunction constructor = findFunctionByName(oldName); + + PsiElement nameIdentifier = getNameIdentifier(); + assert nameIdentifier != null; + getNode().replaceChild(nameIdentifier.getNode(), JSChangeUtil.createExpressionFromText(getProject(), newName).getNode()); + + if (constructor != null) { + constructor.setName(newName); + } + + JSPsiImplUtils.updateFileName(this, newName, oldName); + + return this; + } + + @Override + @RequiredReadAction + public PsiElement getNameIdentifier() { + return findChildByType(JavaScriptTokenSets.NAME_TOKEN_TYPES); + } + + @Override + public JSReferenceList getExtendsList() { + return getStubOrPsiChild(JSElementTypes.EXTENDS_LIST); + } + + @Override + public JSReferenceList getImplementsList() { + return getStubOrPsiChild(JSElementTypes.IMPLEMENTS_LIST); + } + + @Override + @RequiredReadAction + public String getQualifiedName() { + JSClassStub classStub = getStub(); + return classStub != null ? classStub.getQualifiedName() : JSPsiImplUtils.getQName(this); + } + + @Override + @RequiredReadAction + public boolean isInterface() { + JSClassStub classStub = getStub(); + return classStub != null ? classStub.isInterface() : getNode().findChildByType(JSTokenTypes.INTERFACE_KEYWORD) != null; + } + + @Override + @RequiredWriteAction + public void delete() throws IncorrectOperationException { + getNode().getTreeParent().removeChild(getNode()); + } + + @Override + public boolean isDeprecated() { + JSClassStub stub = getStub(); + return stub != null ? stub.isDeprecated() : JSDocumentationUtils.calculateDeprecated(this); + } + + @Override + protected boolean processMembers(PsiScopeProcessor processor, ResolveState substitutor, PsiElement lastParent, PsiElement place) { + return JSResolveUtil.processDeclarationsInScope(this, processor, substitutor, lastParent, place); + } + + @Override + @RequiredReadAction + public boolean processDeclarations( + @Nonnull PsiScopeProcessor processor, + @Nonnull ResolveState substitutor, + PsiElement lastParent, + @Nonnull PsiElement place + ) { + boolean b = super.processDeclarations(processor, substitutor, lastParent, place); + + if (b && lastParent != null && lastParent.getParent() == this && getParent() instanceof JSFile) { + b = JSImportHandlingUtil.tryResolveImports(processor, this, place); + } + return b; + } + + @Override + @RequiredWriteAction + public PsiElement addAfter(@Nonnull PsiElement element, PsiElement anchor) throws IncorrectOperationException { + if (anchor == null) { + ASTNode node = getNode().findChildByType(JSTokenTypes.RBRACE); + if (node != null) { + PsiElement psiElement = super.addAfter(element, node.getTreePrev().getPsi()); + CodeStyleManager.getInstance(getProject()).reformatNewlyAddedElement(getNode(), psiElement.getNode()); + return psiElement; + } + } + + PsiElement psiElement = super.addAfter(element, anchor); + CodeStyleManager.getInstance(getProject()).reformatNewlyAddedElement(getNode(), psiElement.getNode()); + return psiElement; + } + + @Override + @RequiredWriteAction + public PsiElement addBefore(@Nonnull PsiElement element, PsiElement anchor) throws IncorrectOperationException { + PsiElement superElement = super.addBefore(element, anchor); + CodeStyleManager.getInstance(getProject()).reformatNewlyAddedElement(getNode(), superElement.getNode()); + return superElement; + } + + @Override + @RequiredReadAction + public boolean isEquivalentTo(PsiElement another) { + return super.isEquivalentTo(another) + || (another instanceof JSFile file + && file.getVirtualFile().getNameWithoutExtension().equals(getName()) + && another == getParent().getParent()) + || JSPsiImplUtils.isTheSameClass(another, this); + } + + @Nonnull + @Override + @RequiredReadAction + public PsiElement getNavigationElement() { + return JSPsiImplUtils.findTopLevelNavigatableElement(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSCommaExpressionImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSCommaExpressionImpl.java index e076e84e..cfd6fd3c 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSCommaExpressionImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSCommaExpressionImpl.java @@ -19,26 +19,19 @@ import consulo.language.ast.ASTNode; import com.intellij.lang.javascript.psi.JSCommaExpression; import com.intellij.lang.javascript.psi.JSElementVisitor; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 11:41:42 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSCommaExpressionImpl extends JSBinaryExpressionImpl implements JSCommaExpression -{ - public JSCommaExpressionImpl(final ASTNode node) - { - super(node); - } +public class JSCommaExpressionImpl extends JSBinaryExpressionImpl implements JSCommaExpression { + public JSCommaExpressionImpl(ASTNode node) { + super(node); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSCommaExpression(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSCommaExpression(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSConditionalExpressionImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSConditionalExpressionImpl.java index 4adc3fcc..aba3db4e 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSConditionalExpressionImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSConditionalExpressionImpl.java @@ -16,6 +16,7 @@ package com.intellij.lang.javascript.psi.impl; +import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.ASTNode; import com.intellij.lang.javascript.JSElementTypes; import com.intellij.lang.javascript.JSTokenTypes; @@ -24,98 +25,81 @@ import com.intellij.lang.javascript.psi.JSExpression; import consulo.language.ast.IElementType; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 11:47:35 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSConditionalExpressionImpl extends JSExpressionImpl implements JSConditionalExpression -{ - public JSConditionalExpressionImpl(final ASTNode node) - { - super(node); - } +public class JSConditionalExpressionImpl extends JSExpressionImpl implements JSConditionalExpression { + public JSConditionalExpressionImpl(ASTNode node) { + super(node); + } - @Override - public JSExpression getCondition() - { - ASTNode child = getNode().getFirstChildNode(); - while(child != null) - { - final IElementType type = child.getElementType(); - if(type == JSTokenTypes.QUEST) - { - return null; - } - if(JSElementTypes.EXPRESSIONS.contains(type)) - { - return (JSExpression) child.getPsi(); - } - child = child.getTreeNext(); - } - return null; - } + @Override + @RequiredReadAction + public JSExpression getCondition() { + ASTNode child = getNode().getFirstChildNode(); + while (child != null) { + IElementType type = child.getElementType(); + if (type == JSTokenTypes.QUEST) { + return null; + } + if (JSElementTypes.EXPRESSIONS.contains(type)) { + return (JSExpression)child.getPsi(); + } + child = child.getTreeNext(); + } + return null; + } - @Override - public JSExpression getThen() - { - boolean questPassed = false; - ASTNode child = getNode().getFirstChildNode(); - while(child != null) - { - final IElementType type = child.getElementType(); - if(type == JSTokenTypes.QUEST) - { - questPassed = true; - } - if(type == JSTokenTypes.COLON) - { - return null; - } - if(questPassed && JSElementTypes.EXPRESSIONS.contains(type)) - { - return (JSExpression) child.getPsi(); - } + @Override + @RequiredReadAction + public JSExpression getThen() { + boolean questPassed = false; + ASTNode child = getNode().getFirstChildNode(); + while (child != null) { + IElementType type = child.getElementType(); + if (type == JSTokenTypes.QUEST) { + questPassed = true; + } + if (type == JSTokenTypes.COLON) { + return null; + } + if (questPassed && JSElementTypes.EXPRESSIONS.contains(type)) { + return (JSExpression)child.getPsi(); + } - child = child.getTreeNext(); - } - return null; - } + child = child.getTreeNext(); + } + return null; + } - @Override - public JSExpression getElse() - { - boolean questPassed = false; - boolean colonPassed = false; - ASTNode child = getNode().getFirstChildNode(); - while(child != null) - { - final IElementType type = child.getElementType(); - if(type == JSTokenTypes.QUEST) - { - questPassed = true; - } - if(type == JSTokenTypes.COLON) - { - colonPassed = true; - } - if(questPassed && colonPassed && JSElementTypes.EXPRESSIONS.contains(type)) - { - return (JSExpression) child.getPsi(); - } + @Override + @RequiredReadAction + public JSExpression getElse() { + boolean questPassed = false; + boolean colonPassed = false; + ASTNode child = getNode().getFirstChildNode(); + while (child != null) { + IElementType type = child.getElementType(); + if (type == JSTokenTypes.QUEST) { + questPassed = true; + } + if (type == JSTokenTypes.COLON) { + colonPassed = true; + } + if (questPassed && colonPassed && JSElementTypes.EXPRESSIONS.contains(type)) { + return (JSExpression)child.getPsi(); + } - child = child.getTreeNext(); - } - return null; - } + child = child.getTreeNext(); + } + return null; + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSConditionalExpression(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSConditionalExpression(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSContinueStatementImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSContinueStatementImpl.java index 625689eb..72e9f1da 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSContinueStatementImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSContinueStatementImpl.java @@ -17,42 +17,35 @@ package com.intellij.lang.javascript.psi.impl; import com.intellij.lang.javascript.psi.*; +import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.ASTNode; import consulo.language.psi.util.PsiTreeUtil; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 9:52:04 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSContinueStatementImpl extends JSStatementWithLabelReferenceImpl implements JSContinueStatement -{ - public JSContinueStatementImpl(final ASTNode node) - { - super(node); - } +public class JSContinueStatementImpl extends JSStatementWithLabelReferenceImpl implements JSContinueStatement { + public JSContinueStatementImpl(ASTNode node) { + super(node); + } - @Override - public JSStatement getStatementToContinue() - { - String label = getLabel(); - if(label == null) - { - return PsiTreeUtil.getParentOfType(this, JSLoopStatement.class, JSSwitchStatement.class); - } - else - { - return (JSStatement) getReferences()[0].resolve(); - } - } + @Override + @RequiredReadAction + public JSStatement getStatementToContinue() { + String label = getLabel(); + if (label == null) { + return PsiTreeUtil.getParentOfType(this, JSLoopStatement.class, JSSwitchStatement.class); + } + else { + return (JSStatement)getReferences()[0].resolve(); + } + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSContinueStatement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSContinueStatement(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSDefinitionExpressionImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSDefinitionExpressionImpl.java index 13cdf87c..1ad69372 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSDefinitionExpressionImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSDefinitionExpressionImpl.java @@ -17,105 +17,87 @@ package com.intellij.lang.javascript.psi.impl; import com.intellij.lang.javascript.psi.*; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.language.psi.PsiElement; import consulo.language.psi.resolve.ResolveState; import consulo.language.psi.resolve.PsiScopeProcessor; import consulo.language.util.IncorrectOperationException; import consulo.language.ast.ASTNode; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: maxim.mossienko - * Date: Dec 14, 2005 - * Time: 6:40:04 PM - * To change this template use File | Settings | File Templates. + * @author maxim.mossienko + * @since 2005-12-14 */ -public class JSDefinitionExpressionImpl extends JSExpressionImpl implements JSDefinitionExpression -{ - public JSDefinitionExpressionImpl(final ASTNode node) - { - super(node); - } +public class JSDefinitionExpressionImpl extends JSExpressionImpl implements JSDefinitionExpression { + public JSDefinitionExpressionImpl(ASTNode node) { + super(node); + } - @Override - public JSExpression getExpression() - { - return findChildByClass(JSExpression.class); - } + @Override + public JSExpression getExpression() { + return findChildByClass(JSExpression.class); + } - @Override - public String getName() - { - final JSExpression expression = getExpression(); - if(expression instanceof JSReferenceExpression) - { - return ((JSReferenceExpression) expression).getReferencedName(); - } - return null; - } + @Override + @RequiredReadAction + public String getName() { + return getExpression() instanceof JSReferenceExpression referenceExpression + ? referenceExpression.getReferencedName() + : null; + } - @Override - public PsiElement setName(@Nonnull String name) throws IncorrectOperationException - { - final JSExpression expression = getExpression(); - if(expression instanceof JSReferenceExpressionImpl) - { - return ((JSReferenceExpressionImpl) expression).handleElementRenameInternal(name); - } - return null; - } + @Override + @RequiredWriteAction + public PsiElement setName(@Nonnull String name) throws IncorrectOperationException { + return getExpression() instanceof JSReferenceExpressionImpl referenceExpression + ? referenceExpression.handleElementRenameInternal(name) + : null; + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSDefinitionExpression(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSDefinitionExpression(this); + } - @Override - public boolean processDeclarations(@Nonnull PsiScopeProcessor processor, @Nonnull ResolveState state, PsiElement lastParent, - @Nonnull PsiElement place) - { - if(lastParent == null) - { - return processor.execute(this, state); - } - return true; - } + @Override + public boolean processDeclarations( + @Nonnull PsiScopeProcessor processor, + @Nonnull ResolveState state, + PsiElement lastParent, + @Nonnull PsiElement place + ) { + return lastParent != null || processor.execute(this, state); + } - @Override - public void delete() throws IncorrectOperationException - { - final PsiElement parent = getParent(); + @Override + @RequiredWriteAction + public void delete() throws IncorrectOperationException { + if (getParent() instanceof JSAssignmentExpression assignment) { + PsiElement assignmentParent = assignment.getParent(); - if(parent instanceof JSAssignmentExpression) - { - final PsiElement grandParent = parent.getParent(); + if (assignmentParent instanceof JSStatement statement) { + statement.delete(); + return; + } + else if (assignmentParent instanceof JSBinaryExpression binaryExpression) { + binaryExpression.getROperand().replace(assignment.getROperand()); + return; + } + else if (assignmentParent instanceof JSVariable variable) { + JSExpression initializer = variable.getInitializer(); + initializer.replace(assignment.getROperand()); + return; + } + } + super.delete(); + } - if(grandParent instanceof JSStatement) - { - grandParent.delete(); - return; - } - else if(grandParent instanceof JSBinaryExpression) - { - ((JSBinaryExpression) grandParent).getROperand().replace(((JSAssignmentExpression) parent).getROperand()); - return; - } - else if(grandParent instanceof JSVariable) - { - final JSExpression initializerExpression = ((JSVariable) grandParent).getInitializer(); - initializerExpression.replace(((JSAssignmentExpression) parent).getROperand()); - return; - } - } - super.delete(); - } - - @Override - public PsiElement getNameIdentifier() - { - return null; - } + @Override + @RequiredReadAction + public PsiElement getNameIdentifier() { + return null; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSDoWhileStatementImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSDoWhileStatementImpl.java index 50064f10..e1bbd0a5 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSDoWhileStatementImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSDoWhileStatementImpl.java @@ -20,39 +20,32 @@ import com.intellij.lang.javascript.psi.JSElementVisitor; import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.JSStatement; +import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.ASTNode; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 10:15:13 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSDoWhileStatementImpl extends JSStatementImpl implements JSDoWhileStatement -{ - public JSDoWhileStatementImpl(final ASTNode node) - { - super(node); - } +public class JSDoWhileStatementImpl extends JSStatementImpl implements JSDoWhileStatement { + public JSDoWhileStatementImpl(ASTNode node) { + super(node); + } - @Override - public JSExpression getCondition() - { - return findChildByClass(JSExpression.class); - } + @Override + public JSExpression getCondition() { + return findChildByClass(JSExpression.class); + } - @Override - public JSStatement getBody() - { - return findChildByClass(JSStatement.class); - } + @Override + @RequiredReadAction + public JSStatement getBody() { + return findChildByClass(JSStatement.class); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSDoWhileStatement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSDoWhileStatement(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSDocCommentImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSDocCommentImpl.java index 80c15906..865d2b80 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSDocCommentImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSDocCommentImpl.java @@ -20,39 +20,32 @@ import com.intellij.lang.javascript.psi.JSDocComment; import com.intellij.lang.javascript.psi.JSDocTag; import com.intellij.lang.javascript.psi.JSElementVisitor; +import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.IElementType; -import consulo.language.psi.PsiElement; import consulo.language.ast.ASTNode; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; +public class JSDocCommentImpl extends JSElementImpl implements JSDocComment { + public JSDocCommentImpl(ASTNode node) { + super(node); + } -public class JSDocCommentImpl extends JSElementImpl implements JSDocComment -{ - public JSDocCommentImpl(final ASTNode node) - { - super(node); - } + @Override + @RequiredReadAction + public IElementType getTokenType() { + return getNode().getElementType(); + } - @Override - public IElementType getTokenType() - { - return getNode().getElementType(); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSDocComment(this); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSDocComment(this); - } - - @Override - public JSDocTag[] getTags() - { - final PsiElement firstChild = getFirstChild(); - if(firstChild instanceof JSDocComment) - { - return ((JSDocComment) firstChild).getTags(); - } - return findChildrenByType(JSDocTokenTypes.DOC_TAG, JSDocTag.class); - } + @Override + @RequiredReadAction + public JSDocTag[] getTags() { + return getFirstChild() instanceof JSDocComment docComment + ? docComment.getTags() + : findChildrenByType(JSDocTokenTypes.DOC_TAG, JSDocTag.class); + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSDocTagImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSDocTagImpl.java index 9315b9a8..44acae55 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSDocTagImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSDocTagImpl.java @@ -17,325 +17,269 @@ package com.intellij.lang.javascript.psi.impl; import com.intellij.lang.javascript.JSDocTokenTypes; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.util.JSLookupUtil; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.document.util.TextRange; +import consulo.javascript.localize.JavaScriptLocalize; +import consulo.language.ast.ASTNode; import consulo.language.editor.util.PsiUtilBase; import consulo.language.psi.*; -import consulo.language.util.IncorrectOperationException; -import consulo.language.ast.ASTNode; import consulo.language.psi.util.PsiTreeUtil; +import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; import consulo.util.collection.ArrayUtil; -import org.jetbrains.annotations.NonNls; - -import javax.annotation.Nonnull; - -public class JSDocTagImpl extends JSElementImpl implements JSDocTag -{ - private volatile PsiReference[] myRefs; - private volatile long myModificationCount = -1; - - public JSDocTagImpl(final ASTNode node) - { - super(node); - } - - @Override - public String getName() - { - final PsiElement element = findChildByType(JSDocTokenTypes.DOC_TAG_NAME); - return element != null ? element.getText().substring(1) : null; - } - - @Override - public PsiElement setName(@NonNls @Nonnull final String name) throws IncorrectOperationException - { - throw new IncorrectOperationException(); - } - - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSDocTag(this); - } - - @Override - public JSDocTagValue getValue() - { - return findChildByClass(JSDocTagValue.class); - } - - @Nonnull - @Override - public PsiReference[] getReferences() - { - final long count = getManager().getModificationTracker().getModificationCount(); - - if(count != myModificationCount) - { - final @NonNls String name = getName(); - PsiReference[] result = PsiReference.EMPTY_ARRAY; - - if("param".equals(name)) - { - final PsiElement data = findChildByType(JSDocTokenTypes.DOC_COMMENT_DATA); - if(data != null) - { - result = new PsiReference[]{new ParamReference(this)}; - } - } - - myRefs = result; - myModificationCount = count; - } - - return myRefs; - } - - private static class ParamReference implements PsiReference, EmptyResolveMessageProvider - { - private PsiElement myJsDocTagValue; - private TextRange myRange; - - public ParamReference(final JSDocTagImpl elt) - { - reset(elt); - } - - private void reset(final JSDocTagImpl elt) - { - myJsDocTagValue = elt.findChildByType(JSDocTokenTypes.DOC_COMMENT_DATA); - int offsetInParent = myJsDocTagValue.getStartOffsetInParent(); - int textLength; - - if(myJsDocTagValue.textContains('[')) - { - final String text = myJsDocTagValue.getText(); - final int at = text.indexOf('['); - offsetInParent += at + 1; - - // @param [name] | //@param[name="something"] | [obj.prop2(='somestring')?] - int rBracketIndex = text.indexOf(']'); - int eqIndex = text.indexOf('='); - int dotIndex = text.indexOf('.'); - int combinedIndex = text.length(); - - if(rBracketIndex != -1) - { - combinedIndex = rBracketIndex; - } - if(eqIndex != -1) - { - combinedIndex = eqIndex; - } - if(dotIndex != -1 && (eqIndex == -1 || dotIndex < eqIndex)) - { - combinedIndex = dotIndex; - } - textLength = combinedIndex - at - 1; - - } - else if(myJsDocTagValue.textContains('=')) - { - textLength = myJsDocTagValue.getText().indexOf('='); // @param name="" - } - else - { - if(myJsDocTagValue.textContains('.')) - { //@param userInfo.email - textLength = myJsDocTagValue.getText().indexOf('.'); - } - else - { - textLength = myJsDocTagValue.getTextLength(); - } - } - myRange = new TextRange(offsetInParent, offsetInParent + textLength); - } - - @Override - public PsiElement getElement() - { - return myJsDocTagValue.getParent(); - } - - @Override - public TextRange getRangeInElement() - { - return myRange; - } - - @Override - public String getCanonicalText() - { - final int offsetInText = myRange.getStartOffset() - myJsDocTagValue.getStartOffsetInParent(); - return myJsDocTagValue.getText().substring(offsetInText, offsetInText + myRange.getLength()); - } - - @Override - public PsiElement handleElementRename(final String newElementName) throws IncorrectOperationException - { - JSDocTag jsDocTag = (JSDocTag) myJsDocTagValue.getParent(); - final ElementManipulator manipulator = ElementManipulators.getManipulator(jsDocTag); - jsDocTag = manipulator.handleContentChange(jsDocTag, myRange, newElementName); - reset((JSDocTagImpl) jsDocTag); - return myJsDocTagValue; - } - - @Override - public PsiElement bindToElement(@Nonnull final PsiElement element) throws IncorrectOperationException - { - return null; - } - - @Override - public boolean isReferenceTo(final PsiElement element) - { - return element.isEquivalentTo(resolve()); - } - - private static JSParameterList findParameterList(PsiElement elt) - { - if(elt == null) - { - return null; - } - PsiComment psiComment = PsiTreeUtil.getParentOfType(elt, PsiComment.class); - if(psiComment == null) - { - return null; - } - final PsiElement parent = psiComment.getParent(); - if(parent instanceof PsiComment) - { - psiComment = (PsiComment) parent; - } - - PsiElement next = psiComment.getNextSibling(); - if(next instanceof PsiWhiteSpace) - { - next = next.getNextSibling(); - } - if(next instanceof PsiComment) - { - next = next.getNextSibling(); - if(next instanceof PsiWhiteSpace) - { - next = next.getNextSibling(); - } - } - - if(next instanceof JSExpressionStatement) - { - final JSExpression expression = ((JSExpressionStatement) next).getExpression(); - - if(expression instanceof JSAssignmentExpression) - { - JSExpression roperand = ((JSAssignmentExpression) expression).getROperand(); - if(roperand instanceof JSNewExpression) - { - roperand = ((JSNewExpression) roperand).getMethodExpression(); - } - - if(roperand instanceof JSFunctionExpression) - { - next = roperand; - } - } - } - else if(next instanceof JSProperty) - { - next = ((JSProperty) next).getValue(); - } - else if(next instanceof JSVarStatement) - { - JSVariable[] variables = ((JSVarStatement) next).getVariables(); - if(variables.length > 0) - { - JSExpression initializer = variables[0].getInitializer(); - if(initializer instanceof JSFunctionExpression) - { - next = initializer; - } - } - } - else if(next != null) - { - if(next instanceof JSVariable) - { - JSExpression expression = ((JSVariable) next).getInitializer(); - if(expression instanceof JSFunctionExpression) - { - next = expression; - } - } - PsiElement nextParent = next.getParent(); - if(nextParent instanceof JSFunction) - { - next = nextParent; - } - } - if(next instanceof JSFunction) - { - return ((JSFunction) next).getParameterList(); - } - - return null; - } - - @Override - public PsiElement resolve() - { - final JSParameterList parameterList = findParameterList(getElement()); - - if(parameterList != null) - { - final String name = getCanonicalText(); - for(JSParameter param : parameterList.getParameters()) - { - if(name.equals(param.getName())) - { - return param; - } - } - } - - return null; - } - - @Override - public Object[] getVariants() - { - final PsiElement elt = getElement(); - final JSParameterList parameterList = findParameterList(PsiUtilBase.getOriginalElement(elt, elt.getClass())); - - if(parameterList != null) - { - final JSParameter[] parameters = parameterList.getParameters(); - final Object[] result = new Object[parameters.length]; - - for(int i = 0; i < parameters.length; ++i) - { - result[i] = JSLookupUtil.createLookupItem(parameters[i], parameters[i].getName(), JSLookupUtil.LookupPriority.HIGHEST); - } - return result; - } - - return ArrayUtil.EMPTY_OBJECT_ARRAY; - } - - @Override - public boolean isSoft() - { - return false; - } - - @Override - public String getUnresolvedMessagePattern() - { - return JavaScriptBundle.message("javascript.validation.message.incorrect.parameter.name"); - } - } - +import jakarta.annotation.Nonnull; + +public class JSDocTagImpl extends JSElementImpl implements JSDocTag { + private volatile PsiReference[] myRefs; + private volatile long myModificationCount = -1; + + public JSDocTagImpl(ASTNode node) { + super(node); + } + + @Override + @RequiredReadAction + public String getName() { + PsiElement element = findChildByType(JSDocTokenTypes.DOC_TAG_NAME); + return element != null ? element.getText().substring(1) : null; + } + + @Override + @RequiredWriteAction + public PsiElement setName(@Nonnull String name) throws IncorrectOperationException { + throw new IncorrectOperationException(); + } + + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSDocTag(this); + } + + @Override + public JSDocTagValue getValue() { + return findChildByClass(JSDocTagValue.class); + } + + @Nonnull + @Override + @RequiredReadAction + public PsiReference[] getReferences() { + long count = getManager().getModificationTracker().getModificationCount(); + + if (count != myModificationCount) { + String name = getName(); + PsiReference[] result = PsiReference.EMPTY_ARRAY; + + if ("param".equals(name)) { + PsiElement data = findChildByType(JSDocTokenTypes.DOC_COMMENT_DATA); + if (data != null) { + result = new PsiReference[]{new ParamReference(this)}; + } + } + + myRefs = result; + myModificationCount = count; + } + + return myRefs; + } + + private static class ParamReference implements PsiReference, EmptyResolveMessageProvider { + private PsiElement myJsDocTagValue; + private TextRange myRange; + + public ParamReference(JSDocTagImpl elt) { + reset(elt); + } + + private void reset(JSDocTagImpl elt) { + myJsDocTagValue = elt.findChildByType(JSDocTokenTypes.DOC_COMMENT_DATA); + int offsetInParent = myJsDocTagValue.getStartOffsetInParent(); + int textLength; + + if (myJsDocTagValue.textContains('[')) { + String text = myJsDocTagValue.getText(); + int at = text.indexOf('['); + offsetInParent += at + 1; + + // @param [name] | //@param[name="something"] | [obj.prop2(='somestring')?] + int rBracketIndex = text.indexOf(']'); + int eqIndex = text.indexOf('='); + int dotIndex = text.indexOf('.'); + int combinedIndex = text.length(); + + if (rBracketIndex != -1) { + combinedIndex = rBracketIndex; + } + if (eqIndex != -1) { + combinedIndex = eqIndex; + } + if (dotIndex != -1 && (eqIndex == -1 || dotIndex < eqIndex)) { + combinedIndex = dotIndex; + } + textLength = combinedIndex - at - 1; + + } + else if (myJsDocTagValue.textContains('=')) { + textLength = myJsDocTagValue.getText().indexOf('='); // @param name="" + } + else if (myJsDocTagValue.textContains('.')) { //@param userInfo.email + textLength = myJsDocTagValue.getText().indexOf('.'); + } + else { + textLength = myJsDocTagValue.getTextLength(); + } + myRange = new TextRange(offsetInParent, offsetInParent + textLength); + } + + @Override + @RequiredReadAction + public PsiElement getElement() { + return myJsDocTagValue.getParent(); + } + + @Nonnull + @Override + @RequiredReadAction + public TextRange getRangeInElement() { + return myRange; + } + + @Nonnull + @Override + @RequiredReadAction + public String getCanonicalText() { + int offsetInText = myRange.getStartOffset() - myJsDocTagValue.getStartOffsetInParent(); + return myJsDocTagValue.getText().substring(offsetInText, offsetInText + myRange.getLength()); + } + + @Override + @RequiredWriteAction + public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException { + JSDocTag jsDocTag = (JSDocTag)myJsDocTagValue.getParent(); + ElementManipulator manipulator = ElementManipulators.getManipulator(jsDocTag); + jsDocTag = manipulator.handleContentChange(jsDocTag, myRange, newElementName); + reset((JSDocTagImpl)jsDocTag); + return myJsDocTagValue; + } + + @Override + @RequiredWriteAction + public PsiElement bindToElement(@Nonnull PsiElement element) throws IncorrectOperationException { + return null; + } + + @Override + @RequiredReadAction + public boolean isReferenceTo(PsiElement element) { + return element.isEquivalentTo(resolve()); + } + + @RequiredReadAction + private static JSParameterList findParameterList(PsiElement elt) { + if (elt == null) { + return null; + } + PsiComment psiComment = PsiTreeUtil.getParentOfType(elt, PsiComment.class); + if (psiComment == null) { + return null; + } + PsiElement parent = psiComment.getParent(); + if (parent instanceof PsiComment comment) { + psiComment = comment; + } + + PsiElement next = psiComment.getNextSibling(); + if (next instanceof PsiWhiteSpace whiteSpace) { + next = whiteSpace.getNextSibling(); + } + if (next instanceof PsiComment comment) { + next = comment.getNextSibling(); + if (next instanceof PsiWhiteSpace whiteSpace) { + next = whiteSpace.getNextSibling(); + } + } + + if (next instanceof JSExpressionStatement expressionStatement) { + if (expressionStatement.getExpression() instanceof JSAssignmentExpression assignment) { + JSExpression roperand = assignment.getROperand(); + if (roperand instanceof JSNewExpression newExpression) { + roperand = newExpression.getMethodExpression(); + } + + if (roperand instanceof JSFunctionExpression functionExpr) { + next = functionExpr; + } + } + } + else if (next instanceof JSProperty property) { + next = property.getValue(); + } + else if (next instanceof JSVarStatement varStatement) { + JSVariable[] variables = varStatement.getVariables(); + if (variables.length > 0 && variables[0].getInitializer() instanceof JSFunctionExpression functionExpr) { + next = functionExpr; + } + } + else if (next != null) { + if (next instanceof JSVariable variable && variable.getInitializer() instanceof JSFunctionExpression functionExpr) { + next = functionExpr; + } + if (next.getParent() instanceof JSFunction function) { + next = function; + } + } + if (next instanceof JSFunction function) { + return function.getParameterList(); + } + + return null; + } + + @Override + @RequiredReadAction + public PsiElement resolve() { + JSParameterList parameterList = findParameterList(getElement()); + + if (parameterList != null) { + String name = getCanonicalText(); + for (JSParameter param : parameterList.getParameters()) { + if (name.equals(param.getName())) { + return param; + } + } + } + + return null; + } + + @Nonnull + @Override + @RequiredReadAction + public Object[] getVariants() { + PsiElement elt = getElement(); + JSParameterList parameterList = findParameterList(PsiUtilBase.getOriginalElement(elt, elt.getClass())); + + if (parameterList != null) { + JSParameter[] parameters = parameterList.getParameters(); + Object[] result = new Object[parameters.length]; + + for (int i = 0; i < parameters.length; ++i) { + result[i] = JSLookupUtil.createLookupItem(parameters[i], parameters[i].getName(), JSLookupUtil.LookupPriority.HIGHEST); + } + return result; + } + + return ArrayUtil.EMPTY_OBJECT_ARRAY; + } + + @Nonnull + @Override + public LocalizeValue buildUnresolvedMessage(@Nonnull String referenceText) { + return JavaScriptLocalize.javascriptValidationMessageIncorrectParameterName(); + } + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSDocTagValueImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSDocTagValueImpl.java index 8ac7cde1..23eae001 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSDocTagValueImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSDocTagValueImpl.java @@ -19,115 +19,97 @@ import com.intellij.lang.javascript.psi.JSDocTagValue; import com.intellij.lang.javascript.psi.JSElementVisitor; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; +import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.ASTNode; import consulo.language.psi.PsiNamedElement; import consulo.language.psi.PsiReference; import consulo.util.collection.ArrayUtil; import consulo.util.lang.text.StringTokenizer; -import org.jetbrains.annotations.NonNls; - -import javax.annotation.Nonnull; - -public class JSDocTagValueImpl extends JSElementImpl implements JSDocTagValue -{ - private volatile PsiReference[] myRefs; - private volatile long myModificationCount = -1; - - public JSDocTagValueImpl(final ASTNode node) - { - super(node); - } - - @Nonnull - @Override - public PsiReference[] getReferences() - { - final long count = getManager().getModificationTracker().getModificationCount(); - - if(count != myModificationCount) - { - final @NonNls String name = ((PsiNamedElement) getParent()).getName(); - PsiReference[] result = PsiReference.EMPTY_ARRAY; - - if(name != null) - { - @NonNls String text = getText(); - - boolean soft = false; - - if("class".equals(name)) - { - soft = text.indexOf('.') == -1; - } - else if("see".equals(name)) - { - soft = true; - if(!text.startsWith("http:")) - { - if(text.indexOf('#') != -1) - { //Array#length, flash.ui.ContextMenu#customItems, #updateProperties() - soft = false; - } - else - { - int dotPos = text.lastIndexOf('.'); - if(dotPos != -1 && dotPos + 1 < text.length() && Character.isUpperCase(text.charAt(dotPos + 1))) - { - soft = false; // flash.ui.ContextMenu - } - } - } - } - else if("returns".equals(name)) - { - soft = true; - } - - int offset = 0; - if(text.startsWith("{")) - { - text = text.substring(1); - offset++; - soft = false; - } - if(text.endsWith("}")) - { - text = text.substring(0, text.length() - 1); - } - - final StringTokenizer tokenizer = new StringTokenizer(text, JSResolveUtil.COMMENT_DELIMITERS); - while(tokenizer.hasMoreElements()) - { - @NonNls String textFragment = tokenizer.nextElement(); - int localOffset = offset + tokenizer.getCurrentPosition() - textFragment.length(); - if(textFragment.endsWith("[]")) - { - textFragment = textFragment.substring(0, textFragment.length() - 2); - } - int i = textFragment.indexOf('?'); - if(i != -1) - { - textFragment = textFragment.substring(0, i); - } - - if(!"void".equals(textFragment)) - { - final JSReferenceSet set = new JSReferenceSet(this, textFragment, localOffset, soft, false, false); - result = ArrayUtil.mergeArrays(result, set.getReferences(), PsiReference.ARRAY_FACTORY); - } - } - } - - myRefs = result; - myModificationCount = count; - } - - return myRefs; - } - - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSDocTagValue(this); - } +import jakarta.annotation.Nonnull; + +public class JSDocTagValueImpl extends JSElementImpl implements JSDocTagValue { + private volatile PsiReference[] myRefs; + private volatile long myModificationCount = -1; + + public JSDocTagValueImpl(ASTNode node) { + super(node); + } + + @Nonnull + @Override + @RequiredReadAction + public PsiReference[] getReferences() { + long count = getManager().getModificationTracker().getModificationCount(); + + if (count != myModificationCount) { + String name = ((PsiNamedElement)getParent()).getName(); + PsiReference[] result = PsiReference.EMPTY_ARRAY; + + if (name != null) { + String text = getText(); + + boolean soft = false; + + if ("class".equals(name)) { + soft = text.indexOf('.') == -1; + } + else if ("see".equals(name)) { + soft = true; + if (!text.startsWith("http:")) { + if (text.indexOf('#') != -1) { //Array#length, flash.ui.ContextMenu#customItems, #updateProperties() + soft = false; + } + else { + int dotPos = text.lastIndexOf('.'); + if (dotPos != -1 && dotPos + 1 < text.length() && Character.isUpperCase(text.charAt(dotPos + 1))) { + soft = false; // flash.ui.ContextMenu + } + } + } + } + else if ("returns".equals(name)) { + soft = true; + } + + int offset = 0; + if (text.startsWith("{")) { + text = text.substring(1); + offset++; + soft = false; + } + if (text.endsWith("}")) { + text = text.substring(0, text.length() - 1); + } + + StringTokenizer tokenizer = new StringTokenizer(text, JSResolveUtil.COMMENT_DELIMITERS); + while (tokenizer.hasMoreElements()) { + String textFragment = tokenizer.nextElement(); + int localOffset = offset + tokenizer.getCurrentPosition() - textFragment.length(); + if (textFragment.endsWith("[]")) { + textFragment = textFragment.substring(0, textFragment.length() - 2); + } + int i = textFragment.indexOf('?'); + if (i != -1) { + textFragment = textFragment.substring(0, i); + } + + if (!"void".equals(textFragment)) { + JSReferenceSet set = + new JSReferenceSet(this, textFragment, localOffset, soft, false, false); + result = ArrayUtil.mergeArrays(result, set.getReferences(), PsiReference.ARRAY_FACTORY); + } + } + } + + myRefs = result; + myModificationCount = count; + } + + return myRefs; + } + + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSDocTagValue(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSElementImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSElementImpl.java index 57527f84..b12fe804 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSElementImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSElementImpl.java @@ -21,12 +21,10 @@ /** * @author max - * @since Jan 30, 2005 8:23:10 PM + * @since 2005-01-30 */ -public abstract class JSElementImpl extends JSStubElementImpl -{ - public JSElementImpl(final ASTNode node) - { - super(node); - } +public abstract class JSElementImpl extends JSStubElementImpl { + public JSElementImpl(ASTNode node) { + super(node); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSEmbeddedContentImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSEmbeddedContentImpl.java index 2550ba3a..75f03772 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSEmbeddedContentImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSEmbeddedContentImpl.java @@ -19,6 +19,8 @@ import com.intellij.lang.javascript.JSElementTypes; import com.intellij.lang.javascript.psi.JSElementVisitor; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.language.ast.ASTNode; import consulo.language.ast.IElementType; import consulo.language.psi.PsiElement; @@ -29,91 +31,73 @@ import consulo.xml.psi.xml.XmlTag; import consulo.xml.psi.xml.XmlTagChild; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 31, 2005 - * Time: 12:02:38 AM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-31 */ -public class JSEmbeddedContentImpl extends JSElementImpl implements XmlTagChild -{ - public JSEmbeddedContentImpl(final ASTNode node) - { - super(node); - } +public class JSEmbeddedContentImpl extends JSElementImpl implements XmlTagChild { + public JSEmbeddedContentImpl(ASTNode node) { + super(node); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSElement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSElement(this); + } - @Override - public XmlTag getParentTag() - { - final PsiElement parent = getParent(); - if(parent instanceof XmlTag) - { - return (XmlTag) parent; - } - return null; - } + @Override + public XmlTag getParentTag() { + PsiElement parent = getParent(); + return parent instanceof XmlTag parentTag ? parentTag : null; + } - @Override - public XmlTagChild getNextSiblingInTag() - { - PsiElement nextSibling = getNextSibling(); - if(nextSibling instanceof XmlTagChild) - { - return (XmlTagChild) nextSibling; - } - return null; - } + @Override + @RequiredReadAction + public XmlTagChild getNextSiblingInTag() { + PsiElement nextSibling = getNextSibling(); + return nextSibling instanceof XmlTagChild tagChild ? tagChild : null; + } - @Override - public XmlTagChild getPrevSiblingInTag() - { - final PsiElement prevSibling = getPrevSibling(); - if(prevSibling instanceof XmlTagChild) - { - return (XmlTagChild) prevSibling; - } - return null; - } + @Override + @RequiredReadAction + public XmlTagChild getPrevSiblingInTag() { + PsiElement prevSibling = getPrevSibling(); + return prevSibling instanceof XmlTagChild tagChild ? tagChild : null; + } - @Override - public boolean processElements(PsiElementProcessor processor, PsiElement place) - { - // TODO - return true; - } + @Override + public boolean processElements(PsiElementProcessor processor, PsiElement place) { + // TODO + return true; + } - @Override - public boolean processDeclarations(@Nonnull PsiScopeProcessor processor, @Nonnull ResolveState state, PsiElement lastParent, - @Nonnull PsiElement place) - { - return JSResolveUtil.processDeclarationsInScope(this, processor, state, lastParent, place); - } + @Override + public boolean processDeclarations( + @Nonnull PsiScopeProcessor processor, + @Nonnull ResolveState state, + PsiElement lastParent, + @Nonnull PsiElement place + ) { + return JSResolveUtil.processDeclarationsInScope(this, processor, state, lastParent, place); + } - @Override - public String toString() - { - String s = super.toString(); - final IElementType type = getNode().getElementType(); - if(type != JSElementTypes.EMBEDDED_CONTENT) - { - s += ":" + type; - } - return s; - } + @Override + @RequiredReadAction + public String toString() { + String s = super.toString(); + IElementType type = getNode().getElementType(); + if (type != JSElementTypes.EMBEDDED_CONTENT) { + s += ":" + type; + } + return s; + } - @Override - public void delete() throws IncorrectOperationException - { - final ASTNode astNode = getNode(); - astNode.getTreeParent().removeChild(astNode); - } + @Override + @RequiredWriteAction + public void delete() throws IncorrectOperationException { + ASTNode astNode = getNode(); + astNode.getTreeParent().removeChild(astNode); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSEmptyStatementImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSEmptyStatementImpl.java index 6d2142c1..3e1691b4 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSEmptyStatementImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSEmptyStatementImpl.java @@ -19,26 +19,19 @@ import consulo.language.ast.ASTNode; import com.intellij.lang.javascript.psi.JSElementVisitor; import com.intellij.lang.javascript.psi.JSEmptyStatement; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 9:48:05 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSEmptyStatementImpl extends JSStatementImpl implements JSEmptyStatement -{ - public JSEmptyStatementImpl(final ASTNode node) - { - super(node); - } +public class JSEmptyStatementImpl extends JSStatementImpl implements JSEmptyStatement { + public JSEmptyStatementImpl(ASTNode node) { + super(node); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSEmptyStatement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSEmptyStatement(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSExpressionCodeFragmentImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSExpressionCodeFragmentImpl.java index 9faa5146..d6b753f1 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSExpressionCodeFragmentImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSExpressionCodeFragmentImpl.java @@ -17,6 +17,7 @@ package com.intellij.lang.javascript.psi.impl; import com.intellij.lang.javascript.psi.JSExpressionCodeFragment; +import consulo.annotation.access.RequiredReadAction; import consulo.language.file.FileTypeManager; import consulo.language.file.FileViewProvider; import consulo.language.file.light.LightVirtualFile; @@ -27,77 +28,62 @@ import consulo.project.Project; import org.jetbrains.annotations.NonNls; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author nik */ -public class JSExpressionCodeFragmentImpl extends JSFileImpl implements JSExpressionCodeFragment -{ - private PsiElement myContext; - private boolean myPhysical; - private FileViewProvider myViewProvider; +public class JSExpressionCodeFragmentImpl extends JSFileImpl implements JSExpressionCodeFragment { + private PsiElement myContext; + private boolean myPhysical; + private FileViewProvider myViewProvider; - public JSExpressionCodeFragmentImpl(Project project, @NonNls String name, CharSequence text, boolean isPhysical) - { - super(new SingleRootFileViewProvider(PsiManager.getInstance(project), new LightVirtualFile(name, FileTypeManager.getInstance().getFileTypeByFileName(name), text), isPhysical)); - myPhysical = isPhysical; - ((SingleRootFileViewProvider) getViewProvider()).forceCachedPsi(this); - } + public JSExpressionCodeFragmentImpl(Project project, @NonNls String name, CharSequence text, boolean isPhysical) { + super(new SingleRootFileViewProvider( + PsiManager.getInstance(project), + new LightVirtualFile(name, FileTypeManager.getInstance().getFileTypeByFileName(name), text), + isPhysical + )); + myPhysical = isPhysical; + ((SingleRootFileViewProvider)getViewProvider()).forceCachedPsi(this); + } - //todo[nik] extract these methods from PsiCodeFragmentImpl? - @Override - protected JSExpressionCodeFragmentImpl clone() - { - final JSExpressionCodeFragmentImpl clone = (JSExpressionCodeFragmentImpl) cloneImpl((FileElement) calcTreeElement().clone()); - clone.myPhysical = false; - clone.myOriginalFile = this; - SingleRootFileViewProvider cloneViewProvider = new SingleRootFileViewProvider(getManager(), new LightVirtualFile(getName(), getLanguage(), getText()), false); - cloneViewProvider.forceCachedPsi(clone); - clone.myViewProvider = cloneViewProvider; - return clone; - } + //todo[nik] extract these methods from PsiCodeFragmentImpl? + @Override + @RequiredReadAction + protected JSExpressionCodeFragmentImpl clone() { + JSExpressionCodeFragmentImpl clone = (JSExpressionCodeFragmentImpl)cloneImpl((FileElement)calcTreeElement().clone()); + clone.myPhysical = false; + clone.myOriginalFile = this; + SingleRootFileViewProvider cloneViewProvider = + new SingleRootFileViewProvider(getManager(), new LightVirtualFile(getName(), getLanguage(), getText()), false); + cloneViewProvider.forceCachedPsi(clone); + clone.myViewProvider = cloneViewProvider; + return clone; + } - @Override - public PsiElement getContext() - { - return myContext; - } + @Override + public PsiElement getContext() { + return myContext; + } - @Override - @Nonnull - public FileViewProvider getViewProvider() - { - if(myViewProvider != null) - { - return myViewProvider; - } - return super.getViewProvider(); - } + @Override + @Nonnull + public FileViewProvider getViewProvider() { + return myViewProvider != null ? myViewProvider : super.getViewProvider(); + } - @Override - public boolean isValid() - { - if(!super.isValid()) - { - return false; - } - if(myContext != null && !myContext.isValid()) - { - return false; - } - return true; - } + @Override + public boolean isValid() { + return super.isValid() && myContext == null || myContext.isValid(); + } - @Override - public boolean isPhysical() - { - return myPhysical; - } - - public void setContext(PsiElement context) - { - myContext = context; - } + @Override + public boolean isPhysical() { + return myPhysical; + } + public void setContext(PsiElement context) { + myContext = context; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSExpressionImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSExpressionImpl.java index 2a126e88..4f50f921 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSExpressionImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSExpressionImpl.java @@ -18,32 +18,30 @@ import com.intellij.lang.javascript.psi.JSExpression; import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.javascript.language.psi.JavaScriptType; import consulo.language.ast.ASTNode; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author ven */ -public abstract class JSExpressionImpl extends JSElementImpl implements JSExpression -{ - public JSExpressionImpl(final ASTNode node) - { - super(node); - } +public abstract class JSExpressionImpl extends JSElementImpl implements JSExpression { + public JSExpressionImpl(ASTNode node) { + super(node); + } - @RequiredReadAction - @Nonnull - @Override - public JavaScriptType getType() - { - return JavaScriptType.UNKNOWN; - } + @Nonnull + @Override + @RequiredReadAction + public JavaScriptType getType() { + return JavaScriptType.UNKNOWN; + } - @Override - public JSExpression replace(JSExpression newExpr) - { - return JSChangeUtil.replaceExpression(this, newExpr); - } + @Nonnull + @Override + @RequiredWriteAction + public JSExpression replace(JSExpression newExpr) { + return JSChangeUtil.replaceExpression(this, newExpr); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSExpressionStatementImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSExpressionStatementImpl.java index a6ea348e..28125ffd 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSExpressionStatementImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSExpressionStatementImpl.java @@ -28,74 +28,65 @@ import consulo.navigation.ItemPresentation; import consulo.ui.image.Image; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 9:26:39 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSExpressionStatementImpl extends JSStatementImpl implements JSExpressionStatement -{ - public JSExpressionStatementImpl(final ASTNode node) - { - super(node); - } +public class JSExpressionStatementImpl extends JSStatementImpl implements JSExpressionStatement { + public JSExpressionStatementImpl(ASTNode node) { + super(node); + } - @RequiredReadAction - @Override - public JSExpression getExpression() - { - return findChildByClass(JSExpression.class); - } + @RequiredReadAction + @Override + public JSExpression getExpression() { + return findChildByClass(JSExpression.class); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSExpressionStatement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSExpressionStatement(this); + } - @Override - public boolean processDeclarations(@Nonnull PsiScopeProcessor processor, @Nonnull ResolveState state, PsiElement lastParent, - @Nonnull PsiElement place) - { - if(lastParent == null) - { - final JSExpression expression = getExpression(); - if(expression != null) - { - return expression.processDeclarations(processor, state, lastParent, place); - } - } + @Override + @RequiredReadAction + public boolean processDeclarations( + @Nonnull PsiScopeProcessor processor, + @Nonnull ResolveState state, + PsiElement lastParent, + @Nonnull PsiElement place + ) { + if (lastParent == null) { + JSExpression expression = getExpression(); + if (expression != null) { + return expression.processDeclarations(processor, state, lastParent, place); + } + } - return super.processDeclarations(processor, state, lastParent, place); - } + return super.processDeclarations(processor, state, lastParent, place); + } - @Override - public ItemPresentation getPresentation() - { - return new ItemPresentation() - { - @Override - public String getPresentableText() - { - return getText(); - } + @Override + public ItemPresentation getPresentation() { + return new ItemPresentation() { + @Override + @RequiredReadAction + public String getPresentableText() { + return getText(); + } - @Override - public String getLocationString() - { - return ""; - } + @Override + public String getLocationString() { + return ""; + } - @Override - public Image getIcon() - { - return IconDescriptorUpdaters.getIcon(JSExpressionStatementImpl.this, 0); - } - }; - - } + @Override + @RequiredReadAction + public Image getIcon() { + return IconDescriptorUpdaters.getIcon(JSExpressionStatementImpl.this, 0); + } + }; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSFileImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSFileImpl.java index 3884d3ca..92837d37 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSFileImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSFileImpl.java @@ -18,8 +18,8 @@ import java.util.List; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import consulo.annotation.access.RequiredReadAction; +import jakarta.annotation.Nonnull; import com.intellij.lang.javascript.JSElementTypes; import com.intellij.lang.javascript.psi.JSElementVisitor; @@ -38,155 +38,136 @@ import consulo.javascript.language.JavaScriptLanguage; import consulo.language.file.FileViewProvider; import consulo.language.impl.psi.PsiFileBase; +import jakarta.annotation.Nullable; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 28, 2005 - * Time: 12:25:04 AM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-28 */ -public class JSFileImpl extends PsiFileBase implements JSFile -{ - public JSFileImpl(FileViewProvider fileViewProvider) - { - super(fileViewProvider, JavaScriptLanguage.INSTANCE); - } - - @Override - public String toString() - { - return "JSFile:" + getName(); - } - - @Override - public boolean processDeclarations(@Nonnull final PsiScopeProcessor processor, @Nonnull final ResolveState state, @Nullable PsiElement lastParent, - @Nonnull PsiElement place) - { - boolean result = JSResolveUtil.processDeclarationsInScope(this, processor, state, lastParent, place); - if(lastParent == null) - { - return result; - } - - if(result) - { - if(getContext() == null) - { - if(!(lastParent instanceof JSPackageStatement)) - { - result = JSImportHandlingUtil.tryResolveImports(processor, this, place); - } - - if(result && - JSResolveUtil.isNewResolveAndCompletion(this) && - (JSResolveUtil.shouldProcessImports(place, processor))) - { - result = JSResolveUtil.processGlobalThings(processor, state, place, this); - } - } - } - - return result; - } - - @Override - public void accept(@Nonnull PsiElementVisitor visitor) - { - if(visitor instanceof JSElementVisitor) - { - ((JSElementVisitor) visitor).visitJSElement(this); - } - else - { - super.accept(visitor); - } - } - - @Override - public PsiElement addRangeBefore(@Nonnull PsiElement first, @Nonnull PsiElement last, PsiElement anchor) throws IncorrectOperationException - { - if(JSChangeUtil.isStatementOrComment(first)) - { - return JSChangeUtil.doAddRangeBefore(this, first, last, anchor); - } - return super.addRangeBefore(first, last, anchor); - } - - @Override - public PsiElement addRange(PsiElement first, PsiElement last) throws IncorrectOperationException - { - return addRangeAfter(first, last, null); - } - - @Override - public PsiElement addAfter(@Nonnull PsiElement element, PsiElement anchor) throws IncorrectOperationException - { - if(JSChangeUtil.isStatementOrComment(element)) - { - return JSChangeUtil.doAddAfter(this, element, anchor); - } - return super.addAfter(element, anchor); - } - - @Override - public PsiElement addBefore(@Nonnull PsiElement element, PsiElement anchor) throws IncorrectOperationException - { - if(JSChangeUtil.isStatementOrComment(element)) - { - return JSChangeUtil.doAddBefore(this, element, anchor); - } - return super.addBefore(element, anchor); - } - - @Override - public PsiElement addRangeAfter(PsiElement first, PsiElement last, PsiElement anchor) throws IncorrectOperationException - { - if(JSChangeUtil.isStatementOrComment(first)) - { - return JSChangeUtil.doAddRangeAfter(this, first, last, anchor); - } - - return super.addRangeAfter(first, last, anchor); - } - - @Override - public PsiElement add(@Nonnull PsiElement element) throws IncorrectOperationException - { - return addAfter(element, null); - } - - @Override - public StubBasedPsiElement findStubbedElementAtOffset(final int offset, final Class clazz) - { - final StubElement stub = getStub(); - - if(stub != null) - { - final List children = stub.getChildrenStubs(); - - for(StubElement child : children) - { - final PsiElement psi = child.getPsi(); - - if(psi.getTextRange().getStartOffset() == offset && clazz.isInstance(psi)) - { - return (StubBasedPsiElement) psi; - } - } - } - return null; - } - - @Override - public JSSourceElement[] getStatements() - { - final StubElement stub = getStub(); - if(stub != null) - { - return (JSSourceElement[]) stub.getChildrenByType(JSElementTypes.SOURCE_ELEMENTS, JSSourceElement.EMPTY_ARRAY); - } - return findChildrenByClass(JSSourceElement.class); - } +public class JSFileImpl extends PsiFileBase implements JSFile { + public JSFileImpl(FileViewProvider fileViewProvider) { + super(fileViewProvider, JavaScriptLanguage.INSTANCE); + } + + @Override + @RequiredReadAction + public String toString() { + return "JSFile:" + getName(); + } + + @Override + @RequiredReadAction + public boolean processDeclarations( + @Nonnull PsiScopeProcessor processor, + @Nonnull ResolveState state, + @Nullable PsiElement lastParent, + @Nonnull PsiElement place + ) { + boolean result = JSResolveUtil.processDeclarationsInScope(this, processor, state, lastParent, place); + if (lastParent == null) { + return result; + } + + if (result) { + if (getContext() == null) { + if (!(lastParent instanceof JSPackageStatement)) { + result = JSImportHandlingUtil.tryResolveImports(processor, this, place); + } + + if (result + && JSResolveUtil.isNewResolveAndCompletion(this) + && JSResolveUtil.shouldProcessImports(place, processor)) { + result = JSResolveUtil.processGlobalThings(processor, state, place, this); + } + } + } + + return result; + } + + @Override + public void accept(@Nonnull PsiElementVisitor visitor) { + if (visitor instanceof JSElementVisitor elementVisitor) { + elementVisitor.visitJSElement(this); + } + else { + super.accept(visitor); + } + } + + @Override + public PsiElement addRangeBefore( + @Nonnull PsiElement first, + @Nonnull PsiElement last, + PsiElement anchor + ) throws IncorrectOperationException { + if (JSChangeUtil.isStatementOrComment(first)) { + return JSChangeUtil.doAddRangeBefore(this, first, last, anchor); + } + return super.addRangeBefore(first, last, anchor); + } + + @Override + public PsiElement addRange(PsiElement first, PsiElement last) throws IncorrectOperationException { + return addRangeAfter(first, last, null); + } + + @Override + public PsiElement addAfter(@Nonnull PsiElement element, PsiElement anchor) throws IncorrectOperationException { + if (JSChangeUtil.isStatementOrComment(element)) { + return JSChangeUtil.doAddAfter(this, element, anchor); + } + return super.addAfter(element, anchor); + } + + @Override + public PsiElement addBefore(@Nonnull PsiElement element, PsiElement anchor) throws IncorrectOperationException { + if (JSChangeUtil.isStatementOrComment(element)) { + return JSChangeUtil.doAddBefore(this, element, anchor); + } + return super.addBefore(element, anchor); + } + + @Override + public PsiElement addRangeAfter(PsiElement first, PsiElement last, PsiElement anchor) throws IncorrectOperationException { + if (JSChangeUtil.isStatementOrComment(first)) { + return JSChangeUtil.doAddRangeAfter(this, first, last, anchor); + } + + return super.addRangeAfter(first, last, anchor); + } + + @Override + public PsiElement add(@Nonnull PsiElement element) throws IncorrectOperationException { + return addAfter(element, null); + } + + @Override + @RequiredReadAction + public StubBasedPsiElement findStubbedElementAtOffset(int offset, Class clazz) { + StubElement stub = getStub(); + + if (stub != null) { + List children = stub.getChildrenStubs(); + + for (StubElement child : children) { + PsiElement psi = child.getPsi(); + + if (psi.getTextRange().getStartOffset() == offset && clazz.isInstance(psi)) { + return (StubBasedPsiElement)psi; + } + } + } + return null; + } + + @Override + public JSSourceElement[] getStatements() { + StubElement stub = getStub(); + if (stub != null) { + return (JSSourceElement[])stub.getChildrenByType(JSElementTypes.SOURCE_ELEMENTS, JSSourceElement.EMPTY_ARRAY); + } + return findChildrenByClass(JSSourceElement.class); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSForInStatementImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSForInStatementImpl.java index eda1a5e5..809fcb4f 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSForInStatementImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSForInStatementImpl.java @@ -25,122 +25,106 @@ import consulo.language.ast.TokenSet; import consulo.annotation.access.RequiredReadAction; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 11:20:30 PM + * @author max + * @since 2005-01-30 */ -public class JSForInStatementImpl extends JSStatementImpl implements JSForInStatement -{ - private static final TokenSet ourSeparatorElementType = TokenSet.create(JSTokenTypes.IN_KEYWORD, JSTokenTypes.OF_KEYWORD); +public class JSForInStatementImpl extends JSStatementImpl implements JSForInStatement { + private static final TokenSet SEPARATOR_ELEMENT_TYPE = TokenSet.create(JSTokenTypes.IN_KEYWORD, JSTokenTypes.OF_KEYWORD); - public JSForInStatementImpl(final ASTNode node) - { - super(node); - } + public JSForInStatementImpl(ASTNode node) { + super(node); + } - @Override - public JSVarStatement getDeclarationStatement() - { - return findChildByClass(JSVarStatement.class); - } + @Override + public JSVarStatement getDeclarationStatement() { + return findChildByClass(JSVarStatement.class); + } - @Override - public JSExpression getVariableExpression() - { - ASTNode child = getNode().getFirstChildNode(); - while(child != null) - { - if(ourSeparatorElementType.contains(child.getElementType())) - { - return null; - } - if(child.getPsi() instanceof JSExpression) - { - return (JSExpression) child.getPsi(); - } - child = child.getTreeNext(); - } - return null; - } + @Override + @RequiredReadAction + public JSExpression getVariableExpression() { + ASTNode child = getNode().getFirstChildNode(); + while (child != null) { + if (SEPARATOR_ELEMENT_TYPE.contains(child.getElementType())) { + return null; + } + if (child.getPsi() instanceof JSExpression expression) { + return expression; + } + child = child.getTreeNext(); + } + return null; + } - @Override - public JSExpression getCollectionExpression() - { - ASTNode child = getNode().getFirstChildNode(); - boolean inPassed = false; - while(child != null) - { - if(ourSeparatorElementType.contains(child.getElementType())) - { - inPassed = true; - } - if(inPassed && child.getPsi() instanceof JSExpression) - { - return (JSExpression) child.getPsi(); - } - child = child.getTreeNext(); - } + @Override + @RequiredReadAction + public JSExpression getCollectionExpression() { + ASTNode child = getNode().getFirstChildNode(); + boolean inPassed = false; + while (child != null) { + if (SEPARATOR_ELEMENT_TYPE.contains(child.getElementType())) { + inPassed = true; + } + if (inPassed && child.getPsi() instanceof JSExpression expression) { + return expression; + } + child = child.getTreeNext(); + } - return null; - } + return null; + } - @Override - @RequiredReadAction - public boolean isForEach() - { - return findChildByType(TokenSet.create(JSTokenTypes.EACH_KEYWORD, JSTokenTypes.OF_KEYWORD)) != null ; - } + @Override + @RequiredReadAction + public boolean isForEach() { + return findChildByType(TokenSet.create(JSTokenTypes.EACH_KEYWORD, JSTokenTypes.OF_KEYWORD)) != null; + } - @Override - public JSStatement getBody() - { - ASTNode child = getNode().getFirstChildNode(); - boolean passedRParen = false; - while(child != null) - { - if(child.getElementType() == JSTokenTypes.RPAR) - { - passedRParen = true; - } - else if(passedRParen && child.getPsi() instanceof JSStatement) - { - return (JSStatement) child.getPsi(); - } - child = child.getTreeNext(); - } + @Override + @RequiredReadAction + public JSStatement getBody() { + ASTNode child = getNode().getFirstChildNode(); + boolean passedRParen = false; + while (child != null) { + if (child.getElementType() == JSTokenTypes.RPAR) { + passedRParen = true; + } + else if (passedRParen && child.getPsi() instanceof JSStatement statement) { + return statement; + } + child = child.getTreeNext(); + } - return null; - } + return null; + } - @Override - public boolean processDeclarations(@Nonnull PsiScopeProcessor processor, @Nonnull ResolveState state, PsiElement lastParent, @Nonnull PsiElement place) - { - if(lastParent != null) - { - final JSVarStatement statement = getDeclarationStatement(); - if(statement != null) - { - return statement.processDeclarations(processor, state, lastParent, place); - } - else - { - final JSExpression expression = getVariableExpression(); - if(expression != null && !processor.execute(expression, null)) - { - return false; - } - } - } - return true; - } + @Override + public boolean processDeclarations( + @Nonnull PsiScopeProcessor processor, + @Nonnull ResolveState state, + PsiElement lastParent, + @Nonnull PsiElement place + ) { + if (lastParent != null) { + JSVarStatement statement = getDeclarationStatement(); + if (statement != null) { + return statement.processDeclarations(processor, state, lastParent, place); + } + else { + JSExpression expression = getVariableExpression(); + if (expression != null && !processor.execute(expression, null)) { + return false; + } + } + } + return true; + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSForInStatement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSForInStatement(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSForStatementImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSForStatementImpl.java index 7dec90dd..09454ef8 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSForStatementImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSForStatementImpl.java @@ -16,6 +16,7 @@ package com.intellij.lang.javascript.psi.impl; +import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.ASTNode; import com.intellij.lang.javascript.JSElementTypes; import com.intellij.lang.javascript.JSTokenTypes; @@ -24,135 +25,119 @@ import consulo.language.psi.resolve.ResolveState; import consulo.language.psi.resolve.PsiScopeProcessor; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author max */ -public class JSForStatementImpl extends JSStatementImpl implements JSForStatement -{ - public JSForStatementImpl(final ASTNode node) - { - super(node); - } +public class JSForStatementImpl extends JSStatementImpl implements JSForStatement { + public JSForStatementImpl(ASTNode node) { + super(node); + } - @Override - public JSVarStatement getVarDeclaration() - { - final ASTNode node = getNode().findChildByType(JSElementTypes.VAR_STATEMENT); - return (JSVarStatement) (node != null ? node.getPsi() : null); - } + @Override + @RequiredReadAction + public JSVarStatement getVarDeclaration() { + ASTNode node = getNode().findChildByType(JSElementTypes.VAR_STATEMENT); + return (JSVarStatement)(node != null ? node.getPsi() : null); + } - @Override - public JSExpression getInitialization() - { - ASTNode child = getNode().getFirstChildNode(); - while(child != null) - { - if(child.getElementType() == JSTokenTypes.SEMICOLON) - { - return null; - } - if(JSElementTypes.EXPRESSIONS.contains(child.getElementType())) - { - return (JSExpression) child.getPsi(); - } - child = child.getTreeNext(); - } - return null; - } + @Override + @RequiredReadAction + public JSExpression getInitialization() { + ASTNode child = getNode().getFirstChildNode(); + while (child != null) { + if (child.getElementType() == JSTokenTypes.SEMICOLON) { + return null; + } + if (JSElementTypes.EXPRESSIONS.contains(child.getElementType())) { + return (JSExpression)child.getPsi(); + } + child = child.getTreeNext(); + } + return null; + } - @Override - public JSExpression getCondition() - { - ASTNode child = getNode().getFirstChildNode(); - int semicolonCount = 0; - while(child != null) - { - if(child.getElementType() == JSTokenTypes.SEMICOLON) - { - semicolonCount++; - if(semicolonCount == 2) - { - return null; - } - } - else if(semicolonCount == 1 && JSElementTypes.EXPRESSIONS.contains(child.getElementType())) - { - return (JSExpression) child.getPsi(); - } - child = child.getTreeNext(); - } - return null; - } + @Override + @RequiredReadAction + public JSExpression getCondition() { + ASTNode child = getNode().getFirstChildNode(); + int semicolonCount = 0; + while (child != null) { + if (child.getElementType() == JSTokenTypes.SEMICOLON) { + semicolonCount++; + if (semicolonCount == 2) { + return null; + } + } + else if (semicolonCount == 1 && JSElementTypes.EXPRESSIONS.contains(child.getElementType())) { + return (JSExpression)child.getPsi(); + } + child = child.getTreeNext(); + } + return null; + } - @Override - public JSExpression getUpdate() - { - ASTNode child = getNode().getFirstChildNode(); - int semicolonCount = 0; - while(child != null) - { - if(child.getElementType() == JSTokenTypes.SEMICOLON) - { - semicolonCount++; - } - else if(semicolonCount == 2 && JSElementTypes.EXPRESSIONS.contains(child.getElementType())) - { - return (JSExpression) child.getPsi(); - } - child = child.getTreeNext(); - } - return null; - } + @Override + @RequiredReadAction + public JSExpression getUpdate() { + ASTNode child = getNode().getFirstChildNode(); + int semicolonCount = 0; + while (child != null) { + if (child.getElementType() == JSTokenTypes.SEMICOLON) { + semicolonCount++; + } + else if (semicolonCount == 2 && JSElementTypes.EXPRESSIONS.contains(child.getElementType())) { + return (JSExpression)child.getPsi(); + } + child = child.getTreeNext(); + } + return null; + } - @Override - public JSStatement getBody() - { - ASTNode child = getNode().getFirstChildNode(); - boolean passedRParen = false; - while(child != null) - { - if(child.getElementType() == JSTokenTypes.RPAR) - { - passedRParen = true; - } - else if(passedRParen && child.getPsi() instanceof JSStatement) - { - return (JSStatement) child.getPsi(); - } - child = child.getTreeNext(); - } + @Override + @RequiredReadAction + public JSStatement getBody() { + ASTNode child = getNode().getFirstChildNode(); + boolean passedRParen = false; + while (child != null) { + if (child.getElementType() == JSTokenTypes.RPAR) { + passedRParen = true; + } + else if (passedRParen && child.getPsi() instanceof JSStatement statement) { + return statement; + } + child = child.getTreeNext(); + } - return null; - } + return null; + } - @Override - public boolean processDeclarations(@Nonnull PsiScopeProcessor processor, @Nonnull ResolveState state, PsiElement lastParent, - @Nonnull PsiElement place) - { - if(lastParent != null) - { - final JSVarStatement statement = getVarDeclaration(); - if(statement != null) - { - return statement.processDeclarations(processor, state, lastParent, place); - } - else - { - final JSExpression initialization = getInitialization(); - if(initialization != null) - { - return initialization.processDeclarations(processor, state, null, place); - } - } - } - return true; - } + @Override + @RequiredReadAction + public boolean processDeclarations( + @Nonnull PsiScopeProcessor processor, + @Nonnull ResolveState state, + PsiElement lastParent, + @Nonnull PsiElement place + ) { + if (lastParent != null) { + JSVarStatement statement = getVarDeclaration(); + if (statement != null) { + return statement.processDeclarations(processor, state, lastParent, place); + } + else { + JSExpression initialization = getInitialization(); + if (initialization != null) { + return initialization.processDeclarations(processor, state, null, place); + } + } + } + return true; + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSForStatement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSForStatement(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSFunctionBaseImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSFunctionBaseImpl.java index 151b7ea2..6cf4fcb4 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSFunctionBaseImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSFunctionBaseImpl.java @@ -23,6 +23,7 @@ import com.intellij.lang.javascript.psi.resolve.JSImportHandlingUtil; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; import com.intellij.lang.javascript.psi.stubs.JSFunctionStub; +import consulo.annotation.access.RequiredWriteAction; import consulo.language.psi.PsiElement; import consulo.language.psi.resolve.ResolveState; import consulo.language.psi.resolve.PsiScopeProcessor; @@ -35,258 +36,213 @@ import consulo.javascript.language.psi.JavaScriptTypeElement; import consulo.language.ast.ASTNode; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 8:25:27 PM + * @author max + * @since 2005-01-30 */ -abstract class JSFunctionBaseImpl extends JSStubElementImpl implements JSFunction -{ - private boolean referencesArgumentsCalculated; - private boolean referencesArguments; - - public JSFunctionBaseImpl(final ASTNode node) - { - super(node); - } - - public JSFunctionBaseImpl(final T stub, IStubElementType type) - { - super(stub, type); - } - - @Override - public void subtreeChanged() - { - super.subtreeChanged(); - referencesArgumentsCalculated = false; - referencesArguments = false; - } - - @RequiredReadAction - @Override - public JSParameterList getParameterList() - { - return getStubOrPsiChild(JSElementTypes.PARAMETER_LIST); - } - - @Override - public JSSourceElement[] getBody() - { - final ASTNode[] children = getNode().getChildren(JSElementTypes.SOURCE_ELEMENTS); - if(children.length == 0) - { - return JSSourceElement.EMPTY_ARRAY; - } - JSSourceElement[] result = new JSSourceElement[children.length]; - for(int i = 0; i < children.length; i++) - { - result[i] = (JSSourceElement) children[i].getPsi(); - } - return result; - } - - @Nonnull - @Override - public JavaScriptType getReturnType() - { - return JavaScriptType.UNKNOWN; - } - - @Override - public String getReturnTypeString() - { - final T stub = getStub(); - if(stub != null) - { - return stub.getReturnTypeString(); - } - return JSPsiImplUtils.getType(this); - } - - @Override - public JavaScriptTypeElement getReturnTypeElement() - { - return JSPsiImplUtils.findTypeElement(this); - } - - @Override - public PsiElement setName(@Nonnull String name) throws IncorrectOperationException - { - final ASTNode newNameElement = createNameIdentifier(name); - final ASTNode nameIdentifier = getNameIdentifier().getNode(); - nameIdentifier.getTreeParent().replaceChild(nameIdentifier, newNameElement); - return this; - } - - protected ASTNode createNameIdentifier(final String name) - { - return JSChangeUtil.createExpressionFromText(getProject(), name).getNode(); - } - - @Override - @RequiredReadAction - public String getName() - { - final JSFunctionStub stub = getStub(); - if(stub != null) - { - return stub.getName(); - } - final PsiElement name = getNameIdentifier(); - - if(name != null) - { - if(name instanceof JSReferenceExpression) - { - return ((JSReferenceExpression) name).getReferencedName(); - } - else - { - return name.getText(); - } - } - return null; - } - - private static ASTNode advance(ASTNode astNode) - { - astNode = astNode != null ? astNode.getTreeNext() : null; - - if(astNode != null && astNode.getElementType() == JSTokenTypes.WHITE_SPACE) - { - astNode = astNode.getTreeNext(); - } - return astNode; - } - - @RequiredReadAction - @Override - public int getTextOffset() - { - final PsiElement name = getNameIdentifier(); - return name != null ? name.getTextOffset() : super.getTextOffset(); - } - - @Override - public boolean processDeclarations(@Nonnull PsiScopeProcessor processor, @Nonnull ResolveState state, PsiElement lastParent, - @Nonnull PsiElement place) - { - if(lastParent != null && lastParent.getParent() == this) - { - if(place instanceof JSReferenceExpression) - { - boolean b = JSImportHandlingUtil.tryResolveImports(processor, this, place); - if(!b || JSResolveUtil.isExprInStrictTypeContext((JSReferenceExpression) place)) - { - return b; - } - } - - final JSParameter[] params = getParameterList().getParameters(); - for(JSParameter param : params) - { - if(!param.processDeclarations(processor, state, lastParent, place)) - { - return false; - } - } - - boolean b = JSResolveUtil.processDeclarationsInScope(this, processor, state, lastParent, place); - if(b) - { - processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, this); - } - return b; - } - - return processor.execute(this, state); - } - - @Override - public PsiElement addBefore(@Nonnull final PsiElement element, final PsiElement anchor) throws IncorrectOperationException - { - if(anchor == getFirstChild() && element instanceof JSAttributeList && anchor.getNode().getElementType() == JSTokenTypes.FUNCTION_KEYWORD) - { - return JSChangeUtil.doDoAddBefore(this, element, anchor); - } - return super.addBefore(element, anchor); - } - - @Override - public boolean isDeprecated() - { - final T stub = getStub(); - if(stub != null) - { - return stub.isDeprecated(); - } - return JSDocumentationUtils.calculateDeprecated(this); - } - - @Override - public boolean isReferencesArguments() - { - final T stub = getStub(); - if(stub != null) - { - return stub.isReferencesArguments(); - } - - if(!referencesArgumentsCalculated) - { - acceptChildren(new JSElementVisitor() - { - boolean continueVisiting = true; - - @Override - public void visitJSReferenceExpression(final JSReferenceExpression node) - { - if(isInJS(node) && node.getQualifier() == null) - { - if("arguments".equals(node.getText())) - { - referencesArguments = true; - continueVisiting = false; - return; - } - } - super.visitJSReferenceExpression(node); - } - - @Override - public void visitJSElement(final JSElement node) - { - if(continueVisiting) - { - node.acceptChildren(this); - } - } - }); - - referencesArgumentsCalculated = true; - } - - return referencesArguments; - } - - private static boolean isInJS(final JSReferenceExpression node) - { - final PsiElement parent = node.getParent(); - if(parent != null && !(parent.getLanguage() instanceof JavaScriptLanguage)) - { - return false; - } - return true; - } - - @Override - @RequiredReadAction - public PsiElement getNameIdentifier() - { - return findChildByType(JavaScriptTokenSets.NAME_TOKEN_TYPES); - } +abstract class JSFunctionBaseImpl extends JSStubElementImpl implements JSFunction { + private boolean referencesArgumentsCalculated; + private boolean referencesArguments; + + public JSFunctionBaseImpl(ASTNode node) { + super(node); + } + + public JSFunctionBaseImpl(T stub, IStubElementType type) { + super(stub, type); + } + + @Override + public void subtreeChanged() { + super.subtreeChanged(); + referencesArgumentsCalculated = false; + referencesArguments = false; + } + + @RequiredReadAction + @Override + public JSParameterList getParameterList() { + return getStubOrPsiChild(JSElementTypes.PARAMETER_LIST); + } + + @Override + @RequiredReadAction + public JSSourceElement[] getBody() { + ASTNode[] children = getNode().getChildren(JSElementTypes.SOURCE_ELEMENTS); + if (children.length == 0) { + return JSSourceElement.EMPTY_ARRAY; + } + JSSourceElement[] result = new JSSourceElement[children.length]; + for (int i = 0; i < children.length; i++) { + result[i] = (JSSourceElement)children[i].getPsi(); + } + return result; + } + + @Nonnull + @Override + public JavaScriptType getReturnType() { + return JavaScriptType.UNKNOWN; + } + + @Override + @RequiredReadAction + public String getReturnTypeString() { + T stub = getStub(); + if (stub != null) { + return stub.getReturnTypeString(); + } + return JSPsiImplUtils.getType(this); + } + + @Override + @RequiredReadAction + public JavaScriptTypeElement getReturnTypeElement() { + return JSPsiImplUtils.findTypeElement(this); + } + + @Override + @RequiredWriteAction + public PsiElement setName(@Nonnull String name) throws IncorrectOperationException { + ASTNode newNameElement = createNameIdentifier(name); + ASTNode nameIdentifier = getNameIdentifier().getNode(); + nameIdentifier.getTreeParent().replaceChild(nameIdentifier, newNameElement); + return this; + } + + @RequiredReadAction + protected ASTNode createNameIdentifier(String name) { + return JSChangeUtil.createExpressionFromText(getProject(), name).getNode(); + } + + @Override + @RequiredReadAction + public String getName() { + JSFunctionStub stub = getStub(); + if (stub != null) { + return stub.getName(); + } + PsiElement name = getNameIdentifier(); + + if (name != null) { + return name instanceof JSReferenceExpression nameRefExpr ? nameRefExpr.getReferencedName() : name.getText(); + } + return null; + } + + private static ASTNode advance(ASTNode astNode) { + astNode = astNode != null ? astNode.getTreeNext() : null; + + if (astNode != null && astNode.getElementType() == JSTokenTypes.WHITE_SPACE) { + astNode = astNode.getTreeNext(); + } + return astNode; + } + + @RequiredReadAction + @Override + public int getTextOffset() { + PsiElement name = getNameIdentifier(); + return name != null ? name.getTextOffset() : super.getTextOffset(); + } + + @Override + @RequiredReadAction + public boolean processDeclarations( + @Nonnull PsiScopeProcessor processor, + @Nonnull ResolveState state, + PsiElement lastParent, + @Nonnull PsiElement place + ) { + if (lastParent != null && lastParent.getParent() == this) { + if (place instanceof JSReferenceExpression referenceExpression) { + boolean b = JSImportHandlingUtil.tryResolveImports(processor, this, place); + if (!b || JSResolveUtil.isExprInStrictTypeContext(referenceExpression)) { + return b; + } + } + + JSParameter[] params = getParameterList().getParameters(); + for (JSParameter param : params) { + if (!param.processDeclarations(processor, state, lastParent, place)) { + return false; + } + } + + boolean b = JSResolveUtil.processDeclarationsInScope(this, processor, state, lastParent, place); + if (b) { + processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, this); + } + return b; + } + + return processor.execute(this, state); + } + + @Override + @RequiredWriteAction + public PsiElement addBefore(@Nonnull PsiElement element, PsiElement anchor) throws IncorrectOperationException { + if (anchor == getFirstChild() && element instanceof JSAttributeList attributeList + && anchor.getNode().getElementType() == JSTokenTypes.FUNCTION_KEYWORD) { + return JSChangeUtil.doDoAddBefore(this, attributeList, anchor); + } + return super.addBefore(element, anchor); + } + + @Override + public boolean isDeprecated() { + T stub = getStub(); + return stub != null ? stub.isDeprecated() : JSDocumentationUtils.calculateDeprecated(this); + } + + @Override + @RequiredReadAction + public boolean isReferencesArguments() { + T stub = getStub(); + if (stub != null) { + return stub.isReferencesArguments(); + } + + if (!referencesArgumentsCalculated) { + acceptChildren(new JSElementVisitor() { + boolean continueVisiting = true; + + @Override + @RequiredReadAction + public void visitJSReferenceExpression(JSReferenceExpression node) { + if (isInJS(node) && node.getQualifier() == null && "arguments".equals(node.getText())) { + referencesArguments = true; + continueVisiting = false; + return; + } + super.visitJSReferenceExpression(node); + } + + @Override + public void visitJSElement(JSElement node) { + if (continueVisiting) { + node.acceptChildren(this); + } + } + }); + + referencesArgumentsCalculated = true; + } + + return referencesArguments; + } + + @RequiredReadAction + private static boolean isInJS(JSReferenceExpression node) { + PsiElement parent = node.getParent(); + return parent == null || parent.getLanguage() instanceof JavaScriptLanguage; + } + + @Override + @RequiredReadAction + public PsiElement getNameIdentifier() { + return findChildByType(JavaScriptTokenSets.NAME_TOKEN_TYPES); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSFunctionExpressionImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSFunctionExpressionImpl.java index b50ae806..7d0e61f7 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSFunctionExpressionImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSFunctionExpressionImpl.java @@ -16,6 +16,7 @@ package com.intellij.lang.javascript.psi.impl; +import consulo.annotation.access.RequiredWriteAction; import consulo.language.ast.ASTNode; import com.intellij.lang.javascript.JSTokenTypes; import com.intellij.lang.javascript.psi.*; @@ -26,147 +27,125 @@ import consulo.annotation.access.RequiredReadAction; import consulo.javascript.language.psi.JavaScriptType; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 11:55:33 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSFunctionExpressionImpl extends JSFunctionBaseImpl implements JSFunctionExpression -{ - public JSFunctionExpressionImpl(final ASTNode node) - { - super(node); - } - - public JSFunctionExpressionImpl(final JSFunctionStub stub, IStubElementType type) - { - super(stub, type); - } - - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSFunctionExpression(this); - } - - @Override - protected ASTNode createNameIdentifier(final String name) - { - return JSChangeUtil.createNameIdentifier(getProject(), name); - } - - @Override - public JSExpression replace(JSExpression newExpr) - { - return JSChangeUtil.replaceExpression(this, newExpr); - } - - @RequiredReadAction - @Nonnull - @Override - public JavaScriptType getType() - { - return JavaScriptType.UNKNOWN; - } - - @Override - public JSAttributeList getAttributeList() - { - return null; - } - - @RequiredReadAction - @Override - public int getTextOffset() - { - final PsiElement name = getNameIdentifier(); - return name != null ? name.getTextOffset() : super.getTextOffset(); - } - - @Override - public void delete() throws IncorrectOperationException - { - final PsiElement parent = getParent(); - if(parent instanceof JSAssignmentExpression) - { - ((JSAssignmentExpression) parent).getLOperand().delete(); - return; - } - super.delete(); - } - - @RequiredReadAction - @Override - public boolean isGetProperty() - { - return false; - } - - @RequiredReadAction - @Override - public boolean isSetProperty() - { - return false; - } - - @RequiredReadAction - @Override - public boolean isConstructor() - { - return false; - } - - @Override - public String getQualifiedName() - { - return getName(); - } - - @RequiredReadAction - @Override - public PsiElement getNameIdentifier() - { - final ASTNode treeParent = getNode().getTreeParent(); - PsiElement psi = treeParent != null ? treeParent.getPsi() : null; - if(psi instanceof JSCallExpression) - { - psi = psi.getParent(); - } - if(psi instanceof JSAssignmentExpression) - { - final JSExpression jsExpression = ((JSAssignmentExpression) psi).getLOperand(); - final JSExpression lOperand = jsExpression instanceof JSDefinitionExpression ? ((JSDefinitionExpression) jsExpression).getExpression() : null; - - if(lOperand instanceof JSReferenceExpression) - { - ASTNode childByType = lOperand.getNode().findChildByType(JSTokenTypes.IDENTIFIER_TOKENS_SET); - return childByType != null ? childByType.getPsi() : null; - } - } - else if(psi instanceof JSProperty) - { - ASTNode childByType = psi.getNode().findChildByType(JSTokenTypes.IDENTIFIER_TOKENS_SET); - return childByType != null ? childByType.getPsi() : null; - } - else - { - final PsiElement node = super.getNameIdentifier(); - - if(node != null) - { - return node; - } - - if(psi instanceof JSVariable) - { - ASTNode childByType = psi.getNode().findChildByType(JSTokenTypes.IDENTIFIER_TOKENS_SET); - return childByType != null ? childByType.getPsi() : null; - } - } - return null; - } +public class JSFunctionExpressionImpl extends JSFunctionBaseImpl implements JSFunctionExpression { + public JSFunctionExpressionImpl(ASTNode node) { + super(node); + } + + public JSFunctionExpressionImpl(JSFunctionStub stub, IStubElementType type) { + super(stub, type); + } + + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSFunctionExpression(this); + } + + @Override + @RequiredReadAction + protected ASTNode createNameIdentifier(String name) { + return JSChangeUtil.createNameIdentifier(getProject(), name); + } + + @Nonnull + @Override + @RequiredWriteAction + public JSExpression replace(JSExpression newExpr) { + return JSChangeUtil.replaceExpression(this, newExpr); + } + + @Nonnull + @Override + @RequiredReadAction + public JavaScriptType getType() { + return JavaScriptType.UNKNOWN; + } + + @Override + public JSAttributeList getAttributeList() { + return null; + } + + @Override + @RequiredReadAction + public int getTextOffset() { + PsiElement name = getNameIdentifier(); + return name != null ? name.getTextOffset() : super.getTextOffset(); + } + + @Override + public void delete() throws IncorrectOperationException { + PsiElement parent = getParent(); + if (parent instanceof JSAssignmentExpression assignment) { + assignment.getLOperand().delete(); + return; + } + super.delete(); + } + + @Override + @RequiredReadAction + public boolean isGetProperty() { + return false; + } + + @Override + @RequiredReadAction + public boolean isSetProperty() { + return false; + } + + @Override + @RequiredReadAction + public boolean isConstructor() { + return false; + } + + @Override + @RequiredReadAction + public String getQualifiedName() { + return getName(); + } + + @RequiredReadAction + @Override + public PsiElement getNameIdentifier() { + ASTNode treeParent = getNode().getTreeParent(); + PsiElement psi = treeParent != null ? treeParent.getPsi() : null; + if (psi instanceof JSCallExpression call) { + psi = call.getParent(); + } + if (psi instanceof JSAssignmentExpression assignment) { + JSExpression jsExpression = assignment.getLOperand(); + JSExpression lOperand = jsExpression instanceof JSDefinitionExpression definition ? definition.getExpression() : null; + + if (lOperand instanceof JSReferenceExpression refExpr) { + ASTNode childByType = refExpr.getNode().findChildByType(JSTokenTypes.IDENTIFIER_TOKENS_SET); + return childByType != null ? childByType.getPsi() : null; + } + } + else if (psi instanceof JSProperty property) { + ASTNode childByType = property.getNode().findChildByType(JSTokenTypes.IDENTIFIER_TOKENS_SET); + return childByType != null ? childByType.getPsi() : null; + } + else { + PsiElement node = super.getNameIdentifier(); + + if (node != null) { + return node; + } + + if (psi instanceof JSVariable variable) { + ASTNode childByType = variable.getNode().findChildByType(JSTokenTypes.IDENTIFIER_TOKENS_SET); + return childByType != null ? childByType.getPsi() : null; + } + } + return null; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSFunctionImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSFunctionImpl.java index dc03f7c4..eed6ebbe 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSFunctionImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSFunctionImpl.java @@ -16,6 +16,7 @@ package com.intellij.lang.javascript.psi.impl; +import consulo.annotation.access.RequiredWriteAction; import consulo.content.scope.SearchScope; import consulo.language.ast.ASTNode; import com.intellij.lang.javascript.JSElementTypes; @@ -29,142 +30,118 @@ import consulo.language.psi.PsiElement; import consulo.util.lang.Comparing; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 8:25:27 PM + * @author max + * @since 2005-01-30 */ -public class JSFunctionImpl extends JSFunctionBaseImpl implements JSSuppressionHolder -{ - public JSFunctionImpl(final ASTNode node) - { - super(node); - } - - public JSFunctionImpl(final JSFunctionStub stub, IStubElementType type) - { - super(stub, type); - } - - @RequiredReadAction - @Override - public boolean isGetProperty() - { - final JSFunctionStub stub = getStub(); - if(stub != null) - { - return stub.isGetProperty(); - } - return findChildByType(JSTokenTypes.GET_KEYWORD) != null; - } - - @RequiredReadAction - @Override - public boolean isSetProperty() - { - final JSFunctionStub stub = getStub(); - if(stub != null) - { - return stub.isGetProperty(); - } - return findChildByType(JSTokenTypes.SET_KEYWORD) != null; - } - - @RequiredReadAction - @Override - public boolean isConstructor() - { - final JSFunctionStub stub = getStub(); - if(stub != null) - { - return stub.isConstructor(); - } - final PsiElement parent = JSResolveUtil.findParent(this); - if(parent instanceof JSClass && Comparing.equal("constructor", getName(), true)) - { - return true; - } - return false; - } - - @Override - public JSAttributeList getAttributeList() - { - return getStubOrPsiChild(JSElementTypes.ATTRIBUTE_LIST); - } - - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSFunctionDeclaration(this); - } - - @Override - public void delete() throws IncorrectOperationException - { - getNode().getTreeParent().removeChild(getNode()); - } - - @Override - public String getQualifiedName() - { - final JSFunctionStub jsFunctionStub = getStub(); - if(jsFunctionStub != null) - { - return jsFunctionStub.getQualifiedName(); - } - final PsiElement parent = JSResolveUtil.findParent(this); - - if(parent instanceof JSFile || parent instanceof JSPackageStatement) - { - return JSPsiImplUtils.getQName(this); - } - else - { - return getName(); - } - } - - @Override - @Nonnull - public SearchScope getUseScope() - { - if(isConstructor()) - { - return super.getUseScope(); - } - return JSResolveUtil.findUseScope(this); - } - - @Override - public PsiElement getNavigationElement() - { - PsiElement parent = getParent(); - if(parent instanceof JSClass) - { - PsiElement parentOriginalElement = parent.getNavigationElement(); - - if(parentOriginalElement != parent) - { - JSFunction functionByNameAndKind = ((JSClass) parentOriginalElement).findFunctionByNameAndKind(getName(), getKind()); - return functionByNameAndKind != null ? functionByNameAndKind : this; - } - } - return JSPsiImplUtils.findTopLevelNavigatableElement(this); - } - - @Override - public PsiElement setName(@Nonnull String name) throws IncorrectOperationException - { - String oldName = getName(); - PsiElement element = super.setName(name); - if(getParent() instanceof JSPackageStatement) - { - JSPsiImplUtils.updateFileName(this, name, oldName); - } - return element; - } +public class JSFunctionImpl extends JSFunctionBaseImpl implements JSSuppressionHolder { + public JSFunctionImpl(ASTNode node) { + super(node); + } + + public JSFunctionImpl(JSFunctionStub stub, IStubElementType type) { + super(stub, type); + } + + @Override + @RequiredReadAction + public boolean isGetProperty() { + JSFunctionStub stub = getStub(); + if (stub != null) { + return stub.isGetProperty(); + } + return findChildByType(JSTokenTypes.GET_KEYWORD) != null; + } + + @Override + @RequiredReadAction + public boolean isSetProperty() { + JSFunctionStub stub = getStub(); + if (stub != null) { + return stub.isGetProperty(); + } + return findChildByType(JSTokenTypes.SET_KEYWORD) != null; + } + + @Override + @RequiredReadAction + public boolean isConstructor() { + JSFunctionStub stub = getStub(); + if (stub != null) { + return stub.isConstructor(); + } + PsiElement parent = JSResolveUtil.findParent(this); + return parent instanceof JSClass && Comparing.equal("constructor", getName(), true); + } + + @Override + public JSAttributeList getAttributeList() { + return getStubOrPsiChild(JSElementTypes.ATTRIBUTE_LIST); + } + + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSFunctionDeclaration(this); + } + + @Override + @RequiredWriteAction + public void delete() throws IncorrectOperationException { + getNode().getTreeParent().removeChild(getNode()); + } + + @Override + @RequiredReadAction + public String getQualifiedName() { + JSFunctionStub jsFunctionStub = getStub(); + if (jsFunctionStub != null) { + return jsFunctionStub.getQualifiedName(); + } + PsiElement parent = JSResolveUtil.findParent(this); + + if (parent instanceof JSFile || parent instanceof JSPackageStatement) { + return JSPsiImplUtils.getQName(this); + } + else { + return getName(); + } + } + + @Nonnull + @Override + @RequiredReadAction + public SearchScope getUseScope() { + if (isConstructor()) { + return super.getUseScope(); + } + return JSResolveUtil.findUseScope(this); + } + + @Nonnull + @Override + @RequiredReadAction + public PsiElement getNavigationElement() { + if (getParent() instanceof JSClass jsClass) { + PsiElement parentOriginalElement = jsClass.getNavigationElement(); + + if (parentOriginalElement != jsClass) { + JSFunction functionByNameAndKind = ((JSClass)parentOriginalElement).findFunctionByNameAndKind(getName(), getKind()); + return functionByNameAndKind != null ? functionByNameAndKind : this; + } + } + return JSPsiImplUtils.findTopLevelNavigatableElement(this); + } + + @Override + @RequiredWriteAction + public PsiElement setName(@Nonnull String name) throws IncorrectOperationException { + String oldName = getName(); + PsiElement element = super.setName(name); + if (getParent() instanceof JSPackageStatement) { + JSPsiImplUtils.updateFileName(this, name, oldName); + } + return element; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSFunctionPropertyImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSFunctionPropertyImpl.java index 2cc98bc6..988906f4 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSFunctionPropertyImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSFunctionPropertyImpl.java @@ -11,94 +11,82 @@ import consulo.javascript.language.psi.JavaScriptType; import consulo.javascript.language.psi.JavaScriptTypeElement; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL - * @since 19/12/2021 + * @since 2021-12-19 */ -public class JSFunctionPropertyImpl extends JSPropertyImpl implements JSFunctionProperty -{ - public JSFunctionPropertyImpl(ASTNode node) - { - super(node); - } +public class JSFunctionPropertyImpl extends JSPropertyImpl implements JSFunctionProperty { + public JSFunctionPropertyImpl(ASTNode node) { + super(node); + } - @RequiredReadAction - @Override - public boolean isGetProperty() - { - return findChildByType(JSTokenTypes.GET_KEYWORD) != null; - } + @RequiredReadAction + @Override + public boolean isGetProperty() { + return findChildByType(JSTokenTypes.GET_KEYWORD) != null; + } - @RequiredReadAction - @Override - public boolean isSetProperty() - { - return findChildByType(JSTokenTypes.SET_KEYWORD) != null; - } + @RequiredReadAction + @Override + public boolean isSetProperty() { + return findChildByType(JSTokenTypes.SET_KEYWORD) != null; + } - @RequiredReadAction - @Nullable - @Override - public JSParameterList getParameterList() - { - return (JSParameterList) findChildByType(JSElementTypes.PARAMETER_LIST); - } + @RequiredReadAction + @Nullable + @Override + public JSParameterList getParameterList() { + return (JSParameterList)findChildByType(JSElementTypes.PARAMETER_LIST); + } - @Override - public JSSourceElement[] getBody() - { - final ASTNode[] children = getNode().getChildren(JSElementTypes.SOURCE_ELEMENTS); - if(children.length == 0) - { - return JSSourceElement.EMPTY_ARRAY; - } - JSSourceElement[] result = new JSSourceElement[children.length]; - for(int i = 0; i < children.length; i++) - { - result[i] = (JSSourceElement) children[i].getPsi(); - } - return result; - } + @Override + @RequiredReadAction + public JSSourceElement[] getBody() { + ASTNode[] children = getNode().getChildren(JSElementTypes.SOURCE_ELEMENTS); + if (children.length == 0) { + return JSSourceElement.EMPTY_ARRAY; + } + JSSourceElement[] result = new JSSourceElement[children.length]; + for (int i = 0; i < children.length; i++) { + result[i] = (JSSourceElement)children[i].getPsi(); + } + return result; + } - @Nonnull - @Override - public JavaScriptType getReturnType() - { - return JavaScriptType.UNKNOWN; - } + @Nonnull + @Override + public JavaScriptType getReturnType() { + return JavaScriptType.UNKNOWN; + } - @Override - public String getReturnTypeString() - { - return null; - } + @Override + public String getReturnTypeString() { + return null; + } - @Nullable - @Override - public JavaScriptTypeElement getReturnTypeElement() - { - return null; - } + @Nullable + @Override + public JavaScriptTypeElement getReturnTypeElement() { + return null; + } - @Override - public boolean isDeprecated() - { - return false; - } + @Override + public boolean isDeprecated() { + return false; + } - @Nullable - @Override - public JSAttributeList getAttributeList() - { - return null; - } + @Nullable + @Override + public JSAttributeList getAttributeList() { + return null; + } - @Override - public String getQualifiedName() - { - return null; - } + @Override + @RequiredReadAction + public String getQualifiedName() { + return null; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSGenericSignatureImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSGenericSignatureImpl.java index 5d93fd7a..c398fb18 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSGenericSignatureImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSGenericSignatureImpl.java @@ -20,18 +20,15 @@ import com.intellij.lang.javascript.psi.JSGenericSignature; import consulo.language.ast.ASTNode; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; -public class JSGenericSignatureImpl extends JSElementImpl implements JSGenericSignature -{ - public JSGenericSignatureImpl(final ASTNode node) - { - super(node); - } +public class JSGenericSignatureImpl extends JSElementImpl implements JSGenericSignature { + public JSGenericSignatureImpl(ASTNode node) { + super(node); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSGenericSignature(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSGenericSignature(this); + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSIfStatementImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSIfStatementImpl.java index 2a5a963d..dd465852 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSIfStatementImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSIfStatementImpl.java @@ -16,6 +16,7 @@ package com.intellij.lang.javascript.psi.impl; +import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.ASTNode; import com.intellij.lang.javascript.JSElementTypes; import com.intellij.lang.javascript.JSTokenTypes; @@ -23,65 +24,53 @@ import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.JSIfStatement; import com.intellij.lang.javascript.psi.JSStatement; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 9:49:01 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSIfStatementImpl extends JSStatementImpl implements JSIfStatement -{ - public JSIfStatementImpl(final ASTNode node) - { - super(node); - } +public class JSIfStatementImpl extends JSStatementImpl implements JSIfStatement { + public JSIfStatementImpl(ASTNode node) { + super(node); + } - @Override - public JSExpression getCondition() - { - return findChildByClass(JSExpression.class); - } + @Override + public JSExpression getCondition() { + return findChildByClass(JSExpression.class); + } - @Override - public JSStatement getThen() - { - return findChildByClass(JSStatement.class); - } + @Override + public JSStatement getThen() { + return findChildByClass(JSStatement.class); + } - @Override - public JSStatement getElse() - { - final ASTNode myNode = getNode(); - final ASTNode elseNode = myNode.findChildByType(JSTokenTypes.ELSE_KEYWORD); - final ASTNode node = elseNode != null ? myNode.findChildByType(JSElementTypes.STATEMENTS, elseNode) : null; - return node != null ? (JSStatement) node.getPsi() : null; - } + @Override + @RequiredReadAction + public JSStatement getElse() { + ASTNode myNode = getNode(); + ASTNode elseNode = myNode.findChildByType(JSTokenTypes.ELSE_KEYWORD); + ASTNode node = elseNode != null ? myNode.findChildByType(JSElementTypes.STATEMENTS, elseNode) : null; + return node != null ? (JSStatement)node.getPsi() : null; + } - @Override - public void setThen(JSStatement statement) - { - throw new UnsupportedOperationException("TODO: implement"); - } + @Override + public void setThen(JSStatement statement) { + throw new UnsupportedOperationException("TODO: implement"); + } - @Override - public void setElse(JSStatement statement) - { - throw new UnsupportedOperationException("TODO: implement"); - } + @Override + public void setElse(JSStatement statement) { + throw new UnsupportedOperationException("TODO: implement"); + } - @Override - public void setCondition(JSExpression expr) - { - throw new UnsupportedOperationException("TODO: implement"); - } + @Override + public void setCondition(JSExpression expr) { + throw new UnsupportedOperationException("TODO: implement"); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSIfStatement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSIfStatement(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSImportStatementImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSImportStatementImpl.java index e03ebe1d..e0303e1a 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSImportStatementImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSImportStatementImpl.java @@ -16,6 +16,7 @@ package com.intellij.lang.javascript.psi.impl; +import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.ASTNode; import com.intellij.lang.javascript.JSElementTypes; import com.intellij.lang.javascript.psi.JSElementVisitor; @@ -25,45 +26,43 @@ import consulo.language.psi.resolve.PsiScopeProcessor; import consulo.language.psi.resolve.ResolveState; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * @by Maxim.Mossienko + * @author Maxim.Mossienko */ -public class JSImportStatementImpl extends JSStubbedStatementImpl implements JSImportStatement -{ - public JSImportStatementImpl(final ASTNode node) - { - super(node); - } +public class JSImportStatementImpl extends JSStubbedStatementImpl implements JSImportStatement { + public JSImportStatementImpl(ASTNode node) { + super(node); + } - public JSImportStatementImpl(final JSImportStatementStub stub) - { - super(stub, JSElementTypes.ES4_IMPORT_STATEMENT); - } + public JSImportStatementImpl(JSImportStatementStub stub) { + super(stub, JSElementTypes.ES4_IMPORT_STATEMENT); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSImportStatement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSImportStatement(this); + } - @Override - public boolean processDeclarations(@Nonnull final PsiScopeProcessor processor, @Nonnull final ResolveState state, final PsiElement lastParent, - @Nonnull final PsiElement place) - { - return true; - } + @Override + public boolean processDeclarations( + @Nonnull PsiScopeProcessor processor, + @Nonnull ResolveState state, + PsiElement lastParent, + @Nonnull PsiElement place + ) { + return true; + } - @Override - public String getImportText() - { - final JSImportStatementStub stub = getStub(); - if(stub != null) - { - return stub.getImportText(); - } - final ASTNode node = getNode().findChildByType(JSElementTypes.REFERENCE_EXPRESSION); - return node != null ? node.getText() : null; - } + @Override + @RequiredReadAction + public String getImportText() { + JSImportStatementStub stub = getStub(); + if (stub != null) { + return stub.getImportText(); + } + ASTNode node = getNode().findChildByType(JSElementTypes.REFERENCE_EXPRESSION); + return node != null ? node.getText() : null; + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSIncludeDirectiveImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSIncludeDirectiveImpl.java index 43e34497..ebbee666 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSIncludeDirectiveImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSIncludeDirectiveImpl.java @@ -16,93 +16,90 @@ package com.intellij.lang.javascript.psi.impl; -import consulo.language.ast.ASTNode; import com.intellij.lang.javascript.JSElementTypes; import com.intellij.lang.javascript.psi.JSElementVisitor; import com.intellij.lang.javascript.psi.JSIncludeDirective; import com.intellij.lang.javascript.psi.stubs.JSIncludeDirectiveStub; +import consulo.annotation.access.RequiredReadAction; import consulo.application.util.SystemInfo; +import consulo.javascript.lang.JavaScriptTokenSets; +import consulo.language.ast.ASTNode; +import consulo.language.psi.PsiFile; import consulo.language.psi.PsiReference; import consulo.language.psi.path.FileReference; -import consulo.util.lang.StringUtil; -import consulo.language.psi.PsiElement; -import consulo.language.psi.PsiFile; import consulo.language.psi.path.FileReferenceSet; -import consulo.javascript.lang.JavaScriptTokenSets; - -import javax.annotation.Nonnull; +import consulo.util.lang.StringUtil; +import jakarta.annotation.Nonnull; /** - * @by Maxim.Mossienko + * @author Maxim.Mossienko */ -public class JSIncludeDirectiveImpl extends JSStubbedStatementImpl implements JSIncludeDirective -{ - public JSIncludeDirectiveImpl(final ASTNode node) - { - super(node); - } +public class JSIncludeDirectiveImpl extends JSStubbedStatementImpl implements JSIncludeDirective { + public JSIncludeDirectiveImpl(ASTNode node) { + super(node); + } - public JSIncludeDirectiveImpl(final JSIncludeDirectiveStub stub) - { - super(stub, JSElementTypes.INCLUDE_DIRECTIVE); - } + public JSIncludeDirectiveImpl(JSIncludeDirectiveStub stub) { + super(stub, JSElementTypes.INCLUDE_DIRECTIVE); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSIncludeDirective(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSIncludeDirective(this); + } - @Override - @Nonnull - public PsiReference[] getReferences() - { - ASTNode node = getIncludedFileNode(); + @Nonnull + @Override + @RequiredReadAction + public PsiReference[] getReferences() { + ASTNode node = getIncludedFileNode(); - if(node != null) - { - return new FileReferenceSet(StringUtil.stripQuotesAroundValue(node.getText()), this, node.getPsi().getStartOffsetInParent() + 1, null, - SystemInfo.isFileSystemCaseSensitive).getAllReferences(); - } - return PsiReference.EMPTY_ARRAY; - } + if (node != null) { + return new FileReferenceSet( + StringUtil.stripQuotesAroundValue(node.getText()), + this, + node.getPsi().getStartOffsetInParent() + 1, + null, + SystemInfo.isFileSystemCaseSensitive + ).getAllReferences(); + } + return PsiReference.EMPTY_ARRAY; + } - private ASTNode getIncludedFileNode() - { - return getNode().findChildByType(JavaScriptTokenSets.STRING_LITERALS); - } + @RequiredReadAction + private ASTNode getIncludedFileNode() { + return getNode().findChildByType(JavaScriptTokenSets.STRING_LITERALS); + } - @Override - public String getIncludeText() - { - final JSIncludeDirectiveStub stub = getStub(); - if(stub != null) - { - return stub.getIncludeText(); - } - final ASTNode astNode = getIncludedFileNode(); + @Override + @RequiredReadAction + public String getIncludeText() { + JSIncludeDirectiveStub stub = getStub(); + if (stub != null) { + return stub.getIncludeText(); + } + ASTNode astNode = getIncludedFileNode(); - return astNode != null ? StringUtil.stripQuotesAroundValue(astNode.getText()) : null; - } + return astNode != null ? StringUtil.stripQuotesAroundValue(astNode.getText()) : null; + } - @Override - public PsiFile resolveFile() - { - final String includeText = getIncludeText(); - if(includeText == null) - { - return null; - } - final FileReference[] references = new FileReferenceSet(includeText, this, 0, null, SystemInfo.isFileSystemCaseSensitive).getAllReferences(); + @Override + @RequiredReadAction + public PsiFile resolveFile() { + String includeText = getIncludeText(); + if (includeText == null) { + return null; + } + FileReference[] references = new FileReferenceSet( + includeText, + this, + 0, + null, + SystemInfo.isFileSystemCaseSensitive + ).getAllReferences(); - if(references != null && references.length > 0) - { - final PsiElement element = references[references.length - 1].resolve(); - if(element instanceof PsiFile) - { - return (PsiFile) element; - } - } - return null; - } + return references != null && references.length > 0 && references[references.length - 1].resolve() instanceof PsiFile file + ? file + : null; + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSIndexedPropertyAccessExpressionImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSIndexedPropertyAccessExpressionImpl.java index 6662f52f..bbf2c2cd 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSIndexedPropertyAccessExpressionImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSIndexedPropertyAccessExpressionImpl.java @@ -16,73 +16,61 @@ package com.intellij.lang.javascript.psi.impl; +import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.ASTNode; import com.intellij.lang.javascript.JSTokenTypes; import com.intellij.lang.javascript.psi.JSElementVisitor; import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.JSIndexedPropertyAccessExpression; import consulo.language.ast.IElementType; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 11:59:36 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSIndexedPropertyAccessExpressionImpl extends JSExpressionImpl implements JSIndexedPropertyAccessExpression -{ - public JSIndexedPropertyAccessExpressionImpl(final ASTNode node) - { - super(node); - } +public class JSIndexedPropertyAccessExpressionImpl extends JSExpressionImpl implements JSIndexedPropertyAccessExpression { + public JSIndexedPropertyAccessExpressionImpl(ASTNode node) { + super(node); + } - @Override - public JSExpression getQualifier() - { - ASTNode child = getNode().getFirstChildNode(); - while(child != null) - { - final IElementType type = child.getElementType(); - if(type == JSTokenTypes.LBRACKET) - { - return null; - } - if(child.getPsi() instanceof JSExpression) - { - return (JSExpression) child.getPsi(); - } - child = child.getTreeNext(); - } - return null; - } + @Override + @RequiredReadAction + public JSExpression getQualifier() { + ASTNode child = getNode().getFirstChildNode(); + while (child != null) { + IElementType type = child.getElementType(); + if (type == JSTokenTypes.LBRACKET) { + return null; + } + if (child.getPsi() instanceof JSExpression expression) { + return expression; + } + child = child.getTreeNext(); + } + return null; + } - @Override - public JSExpression getIndexExpression() - { - ASTNode child = getNode().getFirstChildNode(); - boolean bracketPassed = false; - while(child != null) - { - final IElementType type = child.getElementType(); - if(type == JSTokenTypes.LBRACKET) - { - bracketPassed = true; - } - if(bracketPassed && child.getPsi() instanceof JSExpression) - { - return (JSExpression) child.getPsi(); - } - child = child.getTreeNext(); - } - return null; - } + @Override + @RequiredReadAction + public JSExpression getIndexExpression() { + ASTNode child = getNode().getFirstChildNode(); + boolean bracketPassed = false; + while (child != null) { + IElementType type = child.getElementType(); + if (type == JSTokenTypes.LBRACKET) { + bracketPassed = true; + } + if (bracketPassed && child.getPsi() instanceof JSExpression expression) { + return expression; + } + child = child.getTreeNext(); + } + return null; + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSIndexedPropertyAccessExpression(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSIndexedPropertyAccessExpression(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSLabeledStatementImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSLabeledStatementImpl.java index f836ce54..3ebf274c 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSLabeledStatementImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSLabeledStatementImpl.java @@ -21,77 +21,70 @@ import com.intellij.lang.javascript.psi.JSLabeledStatement; import com.intellij.lang.javascript.psi.JSNamedElement; import com.intellij.lang.javascript.psi.JSStatement; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.language.util.IncorrectOperationException; import consulo.language.ast.ASTNode; import consulo.language.psi.PsiElement; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 9:20:04 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSLabeledStatementImpl extends JSStatementImpl implements JSLabeledStatement, JSNamedElement -{ - public JSLabeledStatementImpl(final ASTNode node) - { - super(node); - } +public class JSLabeledStatementImpl extends JSStatementImpl implements JSLabeledStatement, JSNamedElement { + public JSLabeledStatementImpl(ASTNode node) { + super(node); + } - @Override - public String getLabel() - { - return getNameIdentifier().getText(); - } + @Override + @RequiredReadAction + public String getLabel() { + return getNameIdentifier().getText(); + } - @Override - public PsiElement getLabelIdentifier() - { - return getNameIdentifier(); - } + @Override + @RequiredReadAction + public PsiElement getLabelIdentifier() { + return getNameIdentifier(); + } - @Override - public JSStatement getStatement() - { - return findChildByClass(JSStatement.class); - } + @Override + public JSStatement getStatement() { + return findChildByClass(JSStatement.class); + } - @Override - public JSStatement unlabel() - { - throw new UnsupportedOperationException("TODO: implement"); - } + @Override + public JSStatement unlabel() { + throw new UnsupportedOperationException("TODO: implement"); + } - public JSLabeledStatement setLabel(String label) - { - throw new UnsupportedOperationException("TODO: implement"); - } + public JSLabeledStatement setLabel(String label) { + throw new UnsupportedOperationException("TODO: implement"); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSLabeledStatement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSLabeledStatement(this); + } - @Override - public String getName() - { - return getLabel(); - } + @Override + @RequiredReadAction + public String getName() { + return getLabel(); + } - @Override - public PsiElement setName(@Nonnull String name) throws IncorrectOperationException - { - JSChangeUtil.doIdentifierReplacement(this, getLabelIdentifier(), name); - return this; - } + @Override + @RequiredWriteAction + public PsiElement setName(@Nonnull String name) throws IncorrectOperationException { + JSChangeUtil.doIdentifierReplacement(this, getLabelIdentifier(), name); + return this; + } - @Override - public PsiElement getNameIdentifier() - { - return findChildByType(JSTokenTypes.IDENTIFIER); - } + @Override + @RequiredReadAction + public PsiElement getNameIdentifier() { + return findChildByType(JSTokenTypes.IDENTIFIER); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSLetExpressionImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSLetExpressionImpl.java index 6a815796..cf82c557 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSLetExpressionImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSLetExpressionImpl.java @@ -20,32 +20,25 @@ import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.JSLetExpression; import consulo.language.ast.ASTNode; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * Created by IntelliJ IDEA. - * User: maxim.mossienko - * Date: Dec 14, 2005 - * Time: 6:40:04 PM - * To change this template use File | Settings | File Templates. + * @author maxim.mossienko + * @since 2005-12-14 */ -public class JSLetExpressionImpl extends JSExpressionImpl implements JSLetExpression -{ - public JSLetExpressionImpl(final ASTNode node) - { - super(node); - } +public class JSLetExpressionImpl extends JSExpressionImpl implements JSLetExpression { + public JSLetExpressionImpl(ASTNode node) { + super(node); + } - @Override - public JSExpression getExpression() - { - return findChildByClass(JSExpression.class); - } + @Override + public JSExpression getExpression() { + return findChildByClass(JSExpression.class); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSLetExpression(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSLetExpression(this); + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSLetStatementImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSLetStatementImpl.java index 7cd6d4ba..f111a911 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSLetStatementImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSLetStatementImpl.java @@ -22,33 +22,28 @@ import com.intellij.lang.javascript.psi.JSLetStatement; import consulo.language.ast.ASTNode; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author maxim */ -public class JSLetStatementImpl extends JSStatementImpl implements JSLetStatement -{ - public JSLetStatementImpl(final ASTNode node) - { - super(node); - } +public class JSLetStatementImpl extends JSStatementImpl implements JSLetStatement { + public JSLetStatementImpl(ASTNode node) { + super(node); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSLetStatement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSLetStatement(this); + } - @Override - public JSExpression[] getExpressions() - { - return findChildrenByClass(JSExpression.class); - } + @Override + public JSExpression[] getExpressions() { + return findChildrenByClass(JSExpression.class); + } - @Override - public JSBlockStatement getBody() - { - return findChildByClass(JSBlockStatement.class); - } + @Override + public JSBlockStatement getBody() { + return findChildByClass(JSBlockStatement.class); + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSLiteralExpressionImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSLiteralExpressionImpl.java index e3402c2f..5f324282 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSLiteralExpressionImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSLiteralExpressionImpl.java @@ -20,6 +20,7 @@ import com.intellij.lang.javascript.psi.JSElementVisitor; import com.intellij.lang.javascript.psi.JSExpression; import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.javascript.lang.JavaScriptTokenSets; import consulo.javascript.language.psi.JavaScriptPrimitiveType; import consulo.javascript.language.psi.JavaScriptType; @@ -30,124 +31,104 @@ import consulo.language.psi.PsiElement; import consulo.language.psi.PsiLanguageInjectionHost; import consulo.language.psi.PsiReference; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author max - * @since 11:24:42 PM Jan 30, 2005 + * @since 2005-01-30 */ -public class JSLiteralExpressionImpl extends JSExpressionImpl implements JSSimpleLiteralExpression, PsiLanguageInjectionHost -{ - private volatile JSReferenceSet myReferenceSet; - private volatile long myModCount; +public class JSLiteralExpressionImpl extends JSExpressionImpl implements JSSimpleLiteralExpression, PsiLanguageInjectionHost { + private volatile JSReferenceSet myReferenceSet; + private volatile long myModCount; - public JSLiteralExpressionImpl(final ASTNode node) - { - super(node); - } + public JSLiteralExpressionImpl(ASTNode node) { + super(node); + } - @RequiredReadAction - @Nonnull - @Override - public IElementType getLiteralElementType() - { - PsiElement firstChild = getFirstChild(); - assert firstChild != null; - return firstChild.getNode().getElementType(); - } + @RequiredReadAction + @Nonnull + @Override + public IElementType getLiteralElementType() { + PsiElement firstChild = getFirstChild(); + assert firstChild != null; + return firstChild.getNode().getElementType(); + } - @RequiredReadAction - @Nonnull - @Override - public JavaScriptType getType() - { - IElementType literalElementType = getLiteralElementType(); - if(literalElementType == JSTokenTypes.TRUE_KEYWORD || literalElementType == JSTokenTypes.FALSE_KEYWORD) - { - return JavaScriptPrimitiveType.BOOL; - } - else if(literalElementType == JSTokenTypes.REGEXP_LITERAL) - { - return JavaScriptPrimitiveType.REGEXP; - } - else if(literalElementType == JSTokenTypes.NUMERIC_LITERAL) - { - return JavaScriptPrimitiveType.NUMBER; - } - else if(literalElementType == JSTokenTypes.NULL_KEYWORD) - { - return JavaScriptPrimitiveType.NULL; - } - else if(JavaScriptTokenSets.STRING_LITERALS.contains(literalElementType)) - { - return JavaScriptPrimitiveType.STRING; - } - return super.getType(); - } + @RequiredReadAction + @Nonnull + @Override + public JavaScriptType getType() { + IElementType literalElementType = getLiteralElementType(); + if (literalElementType == JSTokenTypes.TRUE_KEYWORD || literalElementType == JSTokenTypes.FALSE_KEYWORD) { + return JavaScriptPrimitiveType.BOOL; + } + else if (literalElementType == JSTokenTypes.REGEXP_LITERAL) { + return JavaScriptPrimitiveType.REGEXP; + } + else if (literalElementType == JSTokenTypes.NUMERIC_LITERAL) { + return JavaScriptPrimitiveType.NUMBER; + } + else if (literalElementType == JSTokenTypes.NULL_KEYWORD) { + return JavaScriptPrimitiveType.NULL; + } + else if (JavaScriptTokenSets.STRING_LITERALS.contains(literalElementType)) { + return JavaScriptPrimitiveType.STRING; + } + return super.getType(); + } - @Override - @Nonnull - public PsiReference[] getReferences() - { - JSReferenceSet referenceSet = myReferenceSet; + @Nonnull + @Override + @RequiredReadAction + public PsiReference[] getReferences() { + JSReferenceSet referenceSet = myReferenceSet; - if(referenceSet == null) - { - synchronized(this) - { - referenceSet = myReferenceSet; - if(referenceSet == null) - { - referenceSet = new JSReferenceSet(this); - referenceSet.update(getText(), 0); - myReferenceSet = referenceSet; - } - } - } - else - { - final long count = getManager().getModificationTracker().getModificationCount(); + if (referenceSet == null) { + synchronized (this) { + referenceSet = myReferenceSet; + if (referenceSet == null) { + referenceSet = new JSReferenceSet(this); + referenceSet.update(getText(), 0); + myReferenceSet = referenceSet; + } + } + } + else { + long count = getManager().getModificationTracker().getModificationCount(); - if(count != myModCount) - { - synchronized(this) - { - if(count != myModCount) - { - referenceSet.update(getText(), 0); - myModCount = count; - } - } - } - } + if (count != myModCount) { + synchronized (this) { + if (count != myModCount) { + referenceSet.update(getText(), 0); + myModCount = count; + } + } + } + } - return myReferenceSet.getReferences(); - } + return myReferenceSet.getReferences(); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSLiteralExpression(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSLiteralExpression(this); + } - @Override - public boolean isValidHost() - { - return true; - } + @Override + public boolean isValidHost() { + return true; + } - @Override - public PsiLanguageInjectionHost updateText(@Nonnull String text) - { - JSExpression expressionFromText = JSChangeUtil.createExpressionFromText(getProject(), text); - return (PsiLanguageInjectionHost) replace(expressionFromText); - } + @Override + @RequiredWriteAction + public PsiLanguageInjectionHost updateText(@Nonnull String text) { + JSExpression expressionFromText = JSChangeUtil.createExpressionFromText(getProject(), text); + return (PsiLanguageInjectionHost)replace(expressionFromText); + } - @Nonnull - @Override - public LiteralTextEscaper createLiteralTextEscaper() - { - return LiteralTextEscaper.createSimple(this); - } + @Nonnull + @Override + public LiteralTextEscaper createLiteralTextEscaper() { + return LiteralTextEscaper.createSimple(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSNamespaceDeclarationImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSNamespaceDeclarationImpl.java index 6bc53b76..0b500e08 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSNamespaceDeclarationImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSNamespaceDeclarationImpl.java @@ -16,137 +16,127 @@ package com.intellij.lang.javascript.psi.impl; -import consulo.language.ast.ASTNode; import com.intellij.lang.javascript.JSElementTypes; import com.intellij.lang.javascript.JSTokenTypes; import com.intellij.lang.javascript.psi.JSAttributeList; import com.intellij.lang.javascript.psi.JSElementVisitor; import com.intellij.lang.javascript.psi.JSNamespaceDeclaration; import com.intellij.lang.javascript.psi.stubs.JSNamespaceDeclarationStub; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; +import consulo.javascript.lang.JavaScriptTokenSets; +import consulo.language.ast.ASTNode; import consulo.language.psi.PsiElement; import consulo.language.psi.resolve.PsiScopeProcessor; import consulo.language.psi.resolve.ResolveState; import consulo.language.util.IncorrectOperationException; -import consulo.javascript.lang.JavaScriptTokenSets; -import org.jetbrains.annotations.NonNls; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * @by Maxim.Mossienko + * @author Maxim.Mossienko */ -public class JSNamespaceDeclarationImpl extends JSStubbedStatementImpl implements JSNamespaceDeclaration -{ - public JSNamespaceDeclarationImpl(final ASTNode node) - { - super(node); - } - - public JSNamespaceDeclarationImpl(final JSNamespaceDeclarationStub node) - { - super(node, JSElementTypes.NAMESPACE_DECLARATION); - } - - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSNamespaceDeclaration(this); - } - - @Override - public JSAttributeList getAttributeList() - { - return getStubOrPsiChild(JSElementTypes.ATTRIBUTE_LIST); - } - - @Override - public PsiElement setName(@NonNls @Nonnull String newName) throws IncorrectOperationException - { - final String oldName = getName(); - if(newName.equals(oldName)) - { - return this; - } - - getNode().replaceChild(getNameIdentifier().getNode(), JSChangeUtil.createExpressionFromText(getProject(), newName).getNode()); - - JSPsiImplUtils.updateFileName(this, newName, oldName); - return this; - } - - @Override - public String getName() - { - final JSNamespaceDeclarationStub stub = getStub(); - if(stub != null) - { - return stub.getName(); - } - final PsiElement node = getNameIdentifier(); - return node != null ? node.getText() : null; - } - - @Override - public int getTextOffset() - { - final PsiElement node = getNameIdentifier(); - return node == null ? super.getTextOffset() : node.getTextOffset(); - } - - @Override - public String getQualifiedName() - { - final JSNamespaceDeclarationStub stub = getStub(); - if(stub != null) - { - return stub.getQualifiedName(); - } - return JSPsiImplUtils.getQName(this); - } - - @Override - public PsiElement getNameIdentifier() - { - return findChildByType(JSElementTypes.REFERENCE_EXPRESSION); - } - - @Override - public String getInitialValueString() - { - final JSNamespaceDeclarationStub stub = getStub(); - if(stub != null) - { - return stub.getInitialValueString(); - } - final ASTNode anchor = getNode().findChildByType(JSTokenTypes.EQ); - - if(anchor != null) - { - ASTNode node = anchor.getTreeNext(); - - if(node != null && node.getElementType() == JSTokenTypes.WHITE_SPACE) - { - node = node.getTreeNext(); - } - - if(node != null && JavaScriptTokenSets.STRING_LITERALS.contains(node.getElementType())) - { - return node.getText(); - } - } - return null; - } - - @Override - public boolean isDeprecated() - { - return false; - } - - @Override - public boolean processDeclarations(@Nonnull final PsiScopeProcessor processor, @Nonnull final ResolveState state, final PsiElement lastParent, - @Nonnull final PsiElement place) - { - return processor.execute(lastParent, state); - } +public class JSNamespaceDeclarationImpl extends JSStubbedStatementImpl implements JSNamespaceDeclaration { + public JSNamespaceDeclarationImpl(ASTNode node) { + super(node); + } + + public JSNamespaceDeclarationImpl(JSNamespaceDeclarationStub node) { + super(node, JSElementTypes.NAMESPACE_DECLARATION); + } + + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSNamespaceDeclaration(this); + } + + @Override + public JSAttributeList getAttributeList() { + return getStubOrPsiChild(JSElementTypes.ATTRIBUTE_LIST); + } + + @Override + @RequiredWriteAction + public PsiElement setName(@Nonnull String newName) throws IncorrectOperationException { + String oldName = getName(); + if (newName.equals(oldName)) { + return this; + } + + getNode().replaceChild(getNameIdentifier().getNode(), JSChangeUtil.createExpressionFromText(getProject(), newName).getNode()); + + JSPsiImplUtils.updateFileName(this, newName, oldName); + return this; + } + + @Override + @RequiredReadAction + public String getName() { + JSNamespaceDeclarationStub stub = getStub(); + if (stub != null) { + return stub.getName(); + } + PsiElement node = getNameIdentifier(); + return node != null ? node.getText() : null; + } + + @Override + @RequiredReadAction + public int getTextOffset() { + PsiElement node = getNameIdentifier(); + return node == null ? super.getTextOffset() : node.getTextOffset(); + } + + @Override + @RequiredReadAction + public String getQualifiedName() { + JSNamespaceDeclarationStub stub = getStub(); + if (stub != null) { + return stub.getQualifiedName(); + } + return JSPsiImplUtils.getQName(this); + } + + @Override + @RequiredReadAction + public PsiElement getNameIdentifier() { + return findChildByType(JSElementTypes.REFERENCE_EXPRESSION); + } + + @Override + @RequiredReadAction + public String getInitialValueString() { + JSNamespaceDeclarationStub stub = getStub(); + if (stub != null) { + return stub.getInitialValueString(); + } + ASTNode anchor = getNode().findChildByType(JSTokenTypes.EQ); + + if (anchor != null) { + ASTNode node = anchor.getTreeNext(); + + if (node != null && node.getElementType() == JSTokenTypes.WHITE_SPACE) { + node = node.getTreeNext(); + } + + if (node != null && JavaScriptTokenSets.STRING_LITERALS.contains(node.getElementType())) { + return node.getText(); + } + } + return null; + } + + @Override + public boolean isDeprecated() { + return false; + } + + @Override + public boolean processDeclarations( + @Nonnull PsiScopeProcessor processor, + @Nonnull ResolveState state, + PsiElement lastParent, + @Nonnull PsiElement place + ) { + return processor.execute(lastParent, state); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSNewExpressionImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSNewExpressionImpl.java index a30eaada..55243527 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSNewExpressionImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSNewExpressionImpl.java @@ -16,64 +16,57 @@ package com.intellij.lang.javascript.psi.impl; -import consulo.language.ast.ASTNode; import com.intellij.lang.javascript.JSElementTypes; import com.intellij.lang.javascript.psi.*; -import consulo.language.psi.PsiElement; import consulo.annotation.access.RequiredReadAction; -import consulo.javascript.language.psi.JavaScriptType; import consulo.javascript.lang.psi.impl.JavaScriptClassType; - -import javax.annotation.Nonnull; +import consulo.javascript.language.psi.JavaScriptType; +import consulo.language.ast.ASTNode; +import consulo.language.psi.PsiElement; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 11:57:36 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSNewExpressionImpl extends JSExpressionImpl implements JSNewExpression -{ - public JSNewExpressionImpl(final ASTNode node) - { - super(node); - } +public class JSNewExpressionImpl extends JSExpressionImpl implements JSNewExpression { + public JSNewExpressionImpl(ASTNode node) { + super(node); + } + + @Nonnull + @Override + @RequiredReadAction + public JavaScriptType getType() { + JSExpression methodExpression = getMethodExpression(); - @RequiredReadAction - @Nonnull - @Override - public JavaScriptType getType() - { - JSExpression methodExpression = getMethodExpression(); + if (methodExpression instanceof JSReferenceExpression referenceExpression) { + PsiElement element = referenceExpression.resolve(); + if (element instanceof JSClass jsClass) { + return new JavaScriptClassType(jsClass); + } - if(methodExpression instanceof JSReferenceExpression) - { - PsiElement resolvedElement = ((JSReferenceExpression) methodExpression).resolve(); - if(resolvedElement instanceof JSClass) - { - return new JavaScriptClassType((JSClass) resolvedElement); - } - } - return super.getType(); - } + if (element instanceof JSVariable jsVar) { + return jsVar.getType(); + } + } + return super.getType(); + } - @Override - public JSExpression getMethodExpression() - { - return findChildByClass(JSExpression.class); - } + @Override + public JSExpression getMethodExpression() { + return findChildByClass(JSExpression.class); + } - @Override - public JSArgumentList getArgumentList() - { - final ASTNode node = getNode().findChildByType(JSElementTypes.ARGUMENT_LIST); - return node != null ? (JSArgumentList) node.getPsi() : null; - } + @Override + @RequiredReadAction + public JSArgumentList getArgumentList() { + ASTNode node = getNode().findChildByType(JSElementTypes.ARGUMENT_LIST); + return node != null ? (JSArgumentList)node.getPsi() : null; + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSNewExpression(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSNewExpression(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSObjectLiteralExpressionImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSObjectLiteralExpressionImpl.java index 48f685b1..900a5757 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSObjectLiteralExpressionImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSObjectLiteralExpressionImpl.java @@ -24,51 +24,45 @@ import consulo.language.psi.PsiElement; import consulo.language.psi.resolve.ResolveState; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 11:36:30 PM + * @author max + * @since 2005-01-30 */ -public class JSObjectLiteralExpressionImpl extends JSExpressionImpl implements JSObjectLiteralExpression -{ - public JSObjectLiteralExpressionImpl(final ASTNode node) - { - super(node); - } +public class JSObjectLiteralExpressionImpl extends JSExpressionImpl implements JSObjectLiteralExpression { + public JSObjectLiteralExpressionImpl(ASTNode node) { + super(node); + } - @Override - public JSProperty[] getProperties() - { - return findChildrenByClass(JSProperty.class); - } + @Override + public JSProperty[] getProperties() { + return findChildrenByClass(JSProperty.class); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSObjectLiteralExpression(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSObjectLiteralExpression(this); + } - @Override - public boolean processDeclarations(@Nonnull final PsiScopeProcessor processor, @Nonnull final ResolveState state, final PsiElement lastParent, - @Nonnull final PsiElement place) - { - if(lastParent == null || !(place instanceof JSProperty)) - { - return true; - } - final JSProperty[] props = getProperties(); + @Override + public boolean processDeclarations( + @Nonnull PsiScopeProcessor processor, + @Nonnull ResolveState state, + PsiElement lastParent, + @Nonnull PsiElement place + ) { + if (lastParent == null || !(place instanceof JSProperty)) { + return true; + } + JSProperty[] props = getProperties(); - for(JSProperty property : props) - { - if(!processor.execute(property, state)) - { - return false; - } - } + for (JSProperty property : props) { + if (!processor.execute(property, state)) { + return false; + } + } - return true; - } + return true; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSPackageStatementImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSPackageStatementImpl.java index 6aec140c..6da72905 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSPackageStatementImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSPackageStatementImpl.java @@ -25,193 +25,165 @@ import com.intellij.lang.javascript.psi.resolve.JSImportHandlingUtil; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; import com.intellij.lang.javascript.psi.stubs.JSPackageStatementStub; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; +import consulo.language.ast.ASTNode; import consulo.language.codeStyle.CodeStyleManager; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiWhiteSpace; import consulo.language.psi.resolve.PsiScopeProcessor; -import consulo.language.util.IncorrectOperationException; -import consulo.language.ast.ASTNode; import consulo.language.psi.resolve.ResolveState; +import consulo.language.util.IncorrectOperationException; import consulo.project.Project; import consulo.virtualFileSystem.VirtualFile; -import org.jetbrains.annotations.NonNls; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; import java.io.IOException; /** - * @by Maxim.Mossienko + * @author Maxim.Mossienko */ -public class JSPackageStatementImpl extends JSStubbedStatementImpl implements JSPackageStatement -{ - public JSPackageStatementImpl(final ASTNode node) - { - super(node); - } - - public JSPackageStatementImpl(final JSPackageStatementStub stub) - { - super(stub, JSElementTypes.PACKAGE_STATEMENT); - } - - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSPackageStatement(this); - } - - @Override - public String getName() - { - final JSPackageStatementStub stub = getStub(); - if(stub != null) - { - return stub.getName(); - } - final PsiElement node = getNameIdentifier(); - if(node != null) - { - return ((JSReferenceExpression) node).getReferencedName(); - } - return null; - } - - @Override - public String getQualifiedName() - { - final JSPackageStatementStub stub = getStub(); - if(stub != null) - { - return stub.getQualifiedName(); - } - - final PsiElement node = getNameIdentifier(); - if(node != null) - { - return node.getText(); - } - return null; - } - - @Override - public JSSourceElement[] getStatements() - { - return getStubOrPsiChildren(JSElementTypes.SOURCE_ELEMENTS, JSSourceElement.EMPTY_ARRAY); - } - - @Override - public void setQualifiedName(final String expectedPackageNameFromFile) - { - doChangeName(getProject(), this, expectedPackageNameFromFile); - } - - @Override - public PsiElement setName(@NonNls @Nonnull String name) throws IncorrectOperationException - { - VirtualFile virtualFile = getContainingFile().getVirtualFile(); - String expectedPackageNameFromFile = JSResolveUtil.getExpectedPackageNameFromFile(virtualFile, getProject(), false); - if(expectedPackageNameFromFile != null && expectedPackageNameFromFile.equals(getQualifiedName())) - { - try - { - JSPsiImplUtils.doRenameParentDirectoryIfNeeded(virtualFile, name, this); - } - catch(IOException ex) - { - throw new IncorrectOperationException("", ex); - } - } - - PsiElement child = getNameIdentifier(); - if(child instanceof JSReferenceExpression) - { - JSReferenceExpression expr = (JSReferenceExpression) child; - PsiElement element = expr.getReferenceNameElement(); - if(element != null) - { - JSChangeUtil.doIdentifierReplacement(expr, element, name); - } - } - - return this; - } - - @Override - public boolean processDeclarations(@Nonnull final PsiScopeProcessor processor, @Nonnull final ResolveState substitutor, - final PsiElement lastParent, @Nonnull final PsiElement place) - { - if(lastParent != null && lastParent.getParent() == this) - { - return JSImportHandlingUtil.tryResolveImports(processor, this, place); - } - else - { - return true; - } - } - - @Override - public PsiElement getNameIdentifier() - { - return findChildByType(JSElementTypes.REFERENCE_EXPRESSION); - } - - @Override - public PsiElement addBefore(@Nonnull PsiElement element, PsiElement anchor) throws IncorrectOperationException - { - if(JSChangeUtil.isStatementOrComment(element)) - { - final PsiElement insertedElement = JSChangeUtil.doAddBefore(this, element, anchor); - CodeStyleManager.getInstance(getProject()).reformatNewlyAddedElement(getNode(), insertedElement.getNode()); - return insertedElement; - } - return super.addBefore(element, anchor); - } - - @Override - public PsiElement addAfter(@Nonnull PsiElement element, PsiElement anchor) throws IncorrectOperationException - { - if(JSChangeUtil.isStatementOrComment(element)) - { - final PsiElement insertedElement = JSChangeUtil.doAddAfter(this, element, anchor); - CodeStyleManager.getInstance(getProject()).reformatNewlyAddedElement(getNode(), insertedElement.getNode()); - return insertedElement; - } - return super.addAfter(element, anchor); - } - - public static void doChangeName(final Project project, final JSPackageStatement packageStatement, final String expected) - { - if(expected == null) - { - return; - } - final PsiElement node = packageStatement.getNameIdentifier(); - final ASTNode parent = packageStatement.getNode(); - - if(expected.length() == 0) - { - if(node != null) - { - final ASTNode treeNext = node.getNode().getTreeNext(); - parent.removeChild(node.getNode()); - if(treeNext.getPsi() instanceof PsiWhiteSpace) - { - parent.removeChild(treeNext); - } - } - } - else - { - final ASTNode child = JSChangeUtil.createExpressionFromText(project, expected).getNode(); - if(node != null) - { - parent.replaceChild(node.getNode(), child); - } - else - { - parent.addChild(child, parent.findChildByType(JSTokenTypes.LBRACE)); - } - } - } +public class JSPackageStatementImpl extends JSStubbedStatementImpl implements JSPackageStatement { + public JSPackageStatementImpl(ASTNode node) { + super(node); + } + + public JSPackageStatementImpl(JSPackageStatementStub stub) { + super(stub, JSElementTypes.PACKAGE_STATEMENT); + } + + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSPackageStatement(this); + } + + @Override + @RequiredReadAction + public String getName() { + JSPackageStatementStub stub = getStub(); + if (stub != null) { + return stub.getName(); + } + PsiElement node = getNameIdentifier(); + if (node != null) { + return ((JSReferenceExpression)node).getReferencedName(); + } + return null; + } + + @Override + @RequiredReadAction + public String getQualifiedName() { + JSPackageStatementStub stub = getStub(); + if (stub != null) { + return stub.getQualifiedName(); + } + + PsiElement node = getNameIdentifier(); + return node != null ? node.getText() : null; + } + + @Override + public JSSourceElement[] getStatements() { + return getStubOrPsiChildren(JSElementTypes.SOURCE_ELEMENTS, JSSourceElement.EMPTY_ARRAY); + } + + @Override + @RequiredWriteAction + public void setQualifiedName(String expectedPackageNameFromFile) { + doChangeName(getProject(), this, expectedPackageNameFromFile); + } + + @Override + @RequiredWriteAction + public PsiElement setName(@Nonnull String name) throws IncorrectOperationException { + VirtualFile virtualFile = getContainingFile().getVirtualFile(); + String expectedPackageNameFromFile = + JSResolveUtil.getExpectedPackageNameFromFile(virtualFile, getProject(), false); + if (expectedPackageNameFromFile != null && expectedPackageNameFromFile.equals(getQualifiedName())) { + try { + JSPsiImplUtils.doRenameParentDirectoryIfNeeded(virtualFile, name, this); + } + catch (IOException ex) { + throw new IncorrectOperationException("", ex); + } + } + + PsiElement child = getNameIdentifier(); + if (child instanceof JSReferenceExpression expr) { + PsiElement element = expr.getReferenceNameElement(); + if (element != null) { + JSChangeUtil.doIdentifierReplacement(expr, element, name); + } + } + + return this; + } + + @Override + public boolean processDeclarations( + @Nonnull PsiScopeProcessor processor, + @Nonnull ResolveState substitutor, + PsiElement lastParent, + @Nonnull PsiElement place + ) { + return !(lastParent != null && lastParent.getParent() == this) + || JSImportHandlingUtil.tryResolveImports(processor, this, place); + } + + @Override + @RequiredReadAction + public PsiElement getNameIdentifier() { + return findChildByType(JSElementTypes.REFERENCE_EXPRESSION); + } + + @Override + @RequiredWriteAction + public PsiElement addBefore(@Nonnull PsiElement element, PsiElement anchor) throws IncorrectOperationException { + if (JSChangeUtil.isStatementOrComment(element)) { + PsiElement insertedElement = JSChangeUtil.doAddBefore(this, element, anchor); + CodeStyleManager.getInstance(getProject()).reformatNewlyAddedElement(getNode(), insertedElement.getNode()); + return insertedElement; + } + return super.addBefore(element, anchor); + } + + @Override + @RequiredWriteAction + public PsiElement addAfter(@Nonnull PsiElement element, PsiElement anchor) throws IncorrectOperationException { + if (JSChangeUtil.isStatementOrComment(element)) { + PsiElement insertedElement = JSChangeUtil.doAddAfter(this, element, anchor); + CodeStyleManager.getInstance(getProject()).reformatNewlyAddedElement(getNode(), insertedElement.getNode()); + return insertedElement; + } + return super.addAfter(element, anchor); + } + + @RequiredWriteAction + public static void doChangeName(Project project, JSPackageStatement packageStatement, String expected) { + if (expected == null) { + return; + } + PsiElement node = packageStatement.getNameIdentifier(); + ASTNode parent = packageStatement.getNode(); + + if (expected.length() == 0) { + if (node != null) { + ASTNode treeNext = node.getNode().getTreeNext(); + parent.removeChild(node.getNode()); + if (treeNext.getPsi() instanceof PsiWhiteSpace) { + parent.removeChild(treeNext); + } + } + } + else { + ASTNode child = JSChangeUtil.createExpressionFromText(project, expected).getNode(); + if (node != null) { + parent.replaceChild(node.getNode(), child); + } + else { + parent.addChild(child, parent.findChildByType(JSTokenTypes.LBRACE)); + } + } + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSParameterImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSParameterImpl.java index ef89f26d..80501d68 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSParameterImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSParameterImpl.java @@ -17,6 +17,7 @@ package com.intellij.lang.javascript.psi.impl; import com.intellij.javascript.documentation.JSDocumentationUtils; +import consulo.annotation.access.RequiredWriteAction; import consulo.language.ast.ASTNode; import com.intellij.lang.javascript.JSElementTypes; import com.intellij.lang.javascript.JSTokenTypes; @@ -31,122 +32,102 @@ import consulo.language.psi.resolve.ResolveState; import consulo.language.util.IncorrectOperationException; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 9:12:51 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSParameterImpl extends JSVariableBaseImpl implements JSParameter -{ - public JSParameterImpl(final ASTNode node) - { - super(node); - } - - public JSParameterImpl(final JSParameterStub stub) - { - super(stub, JSElementTypes.FORMAL_PARAMETER); - } - - @Override - public JSFunction getDeclaringFunction() - { - return (JSFunction) getNode().getTreeParent().getTreeParent().getPsi(); - } - - @Override - @RequiredReadAction - public boolean isRest() - { - final JSParameterStub parameterStub = getStub(); - if(parameterStub != null) - { - return parameterStub.isRest(); - } - return getRestElement() != null; - } - - @Nullable - @Override - @RequiredReadAction - public PsiElement getRestElement() - { - return findChildByType(JSTokenTypes.DOT_DOT_DOT); - } - - @Override - public boolean isOptional() - { - final JSParameterStub parameterStub = getStub(); - if(parameterStub != null) - { - return parameterStub.isOptional(); - } - if(getInitializer() != null) - { - return true; - } - - return JSDocumentationUtils.findOptionalStatusFromComments(this); - } - - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSParameter(this); - } - - @Override - public JSAttributeList getAttributeList() - { - return null; - } - - @Override - public void delete() throws IncorrectOperationException - { - final ASTNode myNode = getNode(); - final ASTNode parent = myNode.getTreeParent(); - - if(parent.getElementType() == JSElementTypes.PARAMETER_LIST) - { - JSChangeUtil.removeRangeWithRemovalOfCommas(myNode, parent); - return; - } - - throw new IncorrectOperationException("Cannot delete variable from parent : " + parent.getElementType()); - } - - @Override - protected String doGetType() - { - String s = super.doGetType(); - - if(s == null) - { - final ASTNode astNode = getNode(); - final ASTNode anchor = astNode.findChildByType(JSTokenTypes.INSTANCEOF_KEYWORD); - - if(anchor != null) - { - ASTNode type = astNode.findChildByType(JSTokenTypes.IDENTIFIER_TOKENS_SET, anchor); - if(type != null) - { - s = type.getText(); - } - } - } - return s; - } - - @Override - public boolean processDeclarations(@Nonnull PsiScopeProcessor processor, @Nonnull ResolveState state, PsiElement lastParent, @Nonnull PsiElement place) - { - return processor.execute(this, state); - } +public class JSParameterImpl extends JSVariableBaseImpl implements JSParameter { + public JSParameterImpl(ASTNode node) { + super(node); + } + + public JSParameterImpl(JSParameterStub stub) { + super(stub, JSElementTypes.FORMAL_PARAMETER); + } + + @Override + @RequiredReadAction + public JSFunction getDeclaringFunction() { + return (JSFunction)getNode().getTreeParent().getTreeParent().getPsi(); + } + + @Override + @RequiredReadAction + public boolean isRest() { + JSParameterStub parameterStub = getStub(); + return parameterStub != null ? parameterStub.isRest() : getRestElement() != null; + } + + @Nullable + @Override + @RequiredReadAction + public PsiElement getRestElement() { + return findChildByType(JSTokenTypes.DOT_DOT_DOT); + } + + @Override + @RequiredReadAction + public boolean isOptional() { + JSParameterStub parameterStub = getStub(); + if (parameterStub != null) { + return parameterStub.isOptional(); + } + return getInitializer() != null || JSDocumentationUtils.findOptionalStatusFromComments(this); + } + + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSParameter(this); + } + + @Override + public JSAttributeList getAttributeList() { + return null; + } + + @Override + @RequiredWriteAction + public void delete() throws IncorrectOperationException { + ASTNode myNode = getNode(); + ASTNode parent = myNode.getTreeParent(); + + if (parent.getElementType() == JSElementTypes.PARAMETER_LIST) { + JSChangeUtil.removeRangeWithRemovalOfCommas(myNode, parent); + return; + } + + throw new IncorrectOperationException("Cannot delete variable from parent : " + parent.getElementType()); + } + + @Override + @RequiredReadAction + protected String doGetType() { + String s = super.doGetType(); + + if (s == null) { + ASTNode astNode = getNode(); + ASTNode anchor = astNode.findChildByType(JSTokenTypes.INSTANCEOF_KEYWORD); + + if (anchor != null) { + ASTNode type = astNode.findChildByType(JSTokenTypes.IDENTIFIER_TOKENS_SET, anchor); + if (type != null) { + s = type.getText(); + } + } + } + return s; + } + + @Override + public boolean processDeclarations( + @Nonnull PsiScopeProcessor processor, + @Nonnull ResolveState state, + PsiElement lastParent, + @Nonnull PsiElement place + ) { + return processor.execute(this, state); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSParameterListImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSParameterListImpl.java index 3a5f9264..3108d08b 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSParameterListImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSParameterListImpl.java @@ -23,36 +23,28 @@ import com.intellij.lang.javascript.psi.stubs.JSParameterListStub; import consulo.language.ast.ASTNode; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 8:41:53 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSParameterListImpl extends JSStubElementImpl implements JSParameterList -{ - public JSParameterListImpl(final ASTNode node) - { - super(node); - } +public class JSParameterListImpl extends JSStubElementImpl implements JSParameterList { + public JSParameterListImpl(ASTNode node) { + super(node); + } - public JSParameterListImpl(final JSParameterListStub stub) - { - super(stub, JSElementTypes.PARAMETER_LIST); - } + public JSParameterListImpl(JSParameterListStub stub) { + super(stub, JSElementTypes.PARAMETER_LIST); + } - @Override - public JSParameter[] getParameters() - { - return getStubOrPsiChildren(JSElementTypes.PARAMETERS, JSParameter.EMPTY_ARRAY); - } + @Override + public JSParameter[] getParameters() { + return getStubOrPsiChildren(JSElementTypes.PARAMETERS, JSParameter.EMPTY_ARRAY); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSParameterList(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSParameterList(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSParenthesizedExpressionImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSParenthesizedExpressionImpl.java index e6e3d2bc..0604a6b5 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSParenthesizedExpressionImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSParenthesizedExpressionImpl.java @@ -20,30 +20,24 @@ import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.JSParenthesizedExpression; import consulo.language.ast.ASTNode; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * User: max - * Date: Jan 30, 2005 - * Time: 11:30:44 PM + * @author max + * @since 2005-01-30 */ -public class JSParenthesizedExpressionImpl extends JSExpressionImpl implements JSParenthesizedExpression -{ - public JSParenthesizedExpressionImpl(final ASTNode node) - { - super(node); - } +public class JSParenthesizedExpressionImpl extends JSExpressionImpl implements JSParenthesizedExpression { + public JSParenthesizedExpressionImpl(ASTNode node) { + super(node); + } - @Override - public JSExpression getInnerExpression() - { - return findChildByClass(JSExpression.class); - } + @Override + public JSExpression getInnerExpression() { + return findChildByClass(JSExpression.class); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSParenthesizedExpression(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSParenthesizedExpression(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSPostfixExpressionImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSPostfixExpressionImpl.java index 3c6debaa..faf52c14 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSPostfixExpressionImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSPostfixExpressionImpl.java @@ -25,45 +25,39 @@ import consulo.language.ast.ASTNode; import consulo.language.ast.IElementType; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * User: max - * Date: Jan 30, 2005 - * Time: 11:52:13 PM + * @author max + * @since 2005-01-30 */ -public class JSPostfixExpressionImpl extends JSExpressionImpl implements JSPostfixExpression -{ - public JSPostfixExpressionImpl(final ASTNode node) - { - super(node); - } - - @RequiredReadAction - @Nonnull - @Override - public JavaScriptType getType() - { - JSExpression expression = getExpression(); - return expression == null ? JavaScriptType.UNKNOWN : expression.getType(); - } - - @Override - public JSExpression getExpression() - { - return findChildByClass(JSExpression.class); - } - - @Override - public IElementType getOperationSign() - { - final ASTNode[] nodes = getNode().getChildren(JSTokenTypes.OPERATIONS); - return nodes.length == 1 ? nodes[0].getElementType() : null; - } - - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSPostfixExpression(this); - } +public class JSPostfixExpressionImpl extends JSExpressionImpl implements JSPostfixExpression { + public JSPostfixExpressionImpl(ASTNode node) { + super(node); + } + + @Nonnull + @Override + @RequiredReadAction + public JavaScriptType getType() { + JSExpression expression = getExpression(); + return expression == null ? JavaScriptType.UNKNOWN : expression.getType(); + } + + @Override + public JSExpression getExpression() { + return findChildByClass(JSExpression.class); + } + + @Override + @RequiredReadAction + public IElementType getOperationSign() { + ASTNode[] nodes = getNode().getChildren(JSTokenTypes.OPERATIONS); + return nodes.length == 1 ? nodes[0].getElementType() : null; + } + + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSPostfixExpression(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSPrefixExpressionImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSPrefixExpressionImpl.java index d82216bc..1ad0a8ff 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSPrefixExpressionImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSPrefixExpressionImpl.java @@ -26,58 +26,48 @@ import consulo.language.ast.ASTNode; import consulo.language.psi.PsiElement; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 11:52:13 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSPrefixExpressionImpl extends JSExpressionImpl implements JSPrefixExpression -{ - public JSPrefixExpressionImpl(final ASTNode node) - { - super(node); - } +public class JSPrefixExpressionImpl extends JSExpressionImpl implements JSPrefixExpression { + public JSPrefixExpressionImpl(ASTNode node) { + super(node); + } - @Override - public JSExpression getExpression() - { - return findChildByClass(JSExpression.class); - } + @Override + public JSExpression getExpression() { + return findChildByClass(JSExpression.class); + } - @Nullable - @RequiredReadAction - @Override - public IElementType getOperationSign() - { - PsiElement operatorElement = getOperatorElement(); - return operatorElement != null ? operatorElement.getNode().getElementType() : null; - } + @Nullable + @RequiredReadAction + @Override + public IElementType getOperationSign() { + PsiElement operatorElement = getOperatorElement(); + return operatorElement != null ? operatorElement.getNode().getElementType() : null; + } - @RequiredReadAction - @Nullable - @Override - public PsiElement getOperatorElement() - { - return findChildByType(JSTokenTypes.OPERATIONS); - } + @RequiredReadAction + @Nullable + @Override + public PsiElement getOperatorElement() { + return findChildByType(JSTokenTypes.OPERATIONS); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSPrefixExpression(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSPrefixExpression(this); + } - @RequiredReadAction - @Nonnull - @Override - public JavaScriptType getType() - { - JSExpression expression = getExpression(); - return expression == null ? JavaScriptType.UNKNOWN : expression.getType(); - } + @RequiredReadAction + @Nonnull + @Override + public JavaScriptType getType() { + JSExpression expression = getExpression(); + return expression == null ? JavaScriptType.UNKNOWN : expression.getType(); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSPropertyImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSPropertyImpl.java index 26aa824b..c77acb83 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSPropertyImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSPropertyImpl.java @@ -21,6 +21,7 @@ import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.JSProperty; import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.application.util.CachedValueProvider; import consulo.javascript.lang.JavaScriptTokenSets; import consulo.javascript.language.psi.JavaScriptType; @@ -35,148 +36,129 @@ import consulo.language.util.IncorrectOperationException; import consulo.util.lang.StringUtil; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author max */ -public class JSPropertyImpl extends JSElementImpl implements JSProperty -{ - private static TokenSet IDENTIFIER_TOKENS_SET = TokenSet.orSet(TokenSet.create(JSTokenTypes.NUMERIC_LITERAL, JSTokenTypes.IDENTIFIER), JavaScriptTokenSets.STRING_LITERALS); - - public JSPropertyImpl(final ASTNode node) - { - super(node); - } - - @Override - @Nonnull - public PsiReference[] getReferences() - { - return LanguageCachedValueUtil.getCachedValue(this, new CachedValueProvider() - { - @Nullable - @Override - @RequiredReadAction - public Result compute() - { - return Result.create(buildReferences(), JSPropertyImpl.this, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT); - } - }); - } - - @Nonnull - @RequiredReadAction - private PsiReference[] buildReferences() - { - PsiElement nameIdentifier = getNameIdentifier(); - if(nameIdentifier == null) - { - return PsiReference.EMPTY_ARRAY; - } - PsiReference reference = JSPropertyNameReferenceProvider.EP_NAME.computeSafeIfAny(it -> it.getReference(this)); - if(reference != null) - { - return new PsiReference[]{reference}; - } - return PsiReference.EMPTY_ARRAY; - } - - @Override - @RequiredReadAction - public String getName() - { - final PsiElement nameIdentifier = getNameIdentifier(); - if(nameIdentifier != null) - { - return StringUtil.stripQuotesAroundValue(nameIdentifier.getText()); - } - return null; - } - - @Override - public PsiElement setName(@Nonnull String name) throws IncorrectOperationException - { - final PsiElement nameNode = getNameIdentifier(); - assert nameNode != null; - final ASTNode nameElement = JSChangeUtil.createNameIdentifier(getProject(), name, nameNode.getNode().getElementType()); - getNode().replaceChild(nameNode.getNode(), nameElement); - return this; - } - - @RequiredReadAction - @Nonnull - @Override - public JavaScriptType getType() - { - JSExpression value = getValue(); - if(value != null) - { - return value.getType(); - } - return JavaScriptType.UNKNOWN; - } - - @RequiredReadAction - @Override - public JSExpression getValue() - { - return findChildByClass(JSExpression.class); - } - - @RequiredReadAction - @Nullable - @Override - public PsiElement getColonElement() - { - return findChildByType(JSTokenTypes.COLON); - } - - @RequiredReadAction - @Nullable - @Override - public JSComputedName getComputedName() - { - return findChildByClass(JSComputedName.class); - } - - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSProperty(this); - } - - @RequiredReadAction - @Override - public int getTextOffset() - { - final PsiElement name = getNameIdentifier(); - return name != null ? name.getTextOffset() : super.getTextOffset(); - } - - @Override - @RequiredReadAction - public void delete() throws IncorrectOperationException - { - final ASTNode myNode = getNode(); - JSChangeUtil.removeRangeWithRemovalOfCommas(myNode, myNode.getTreeParent()); - } - - @Override - @RequiredReadAction - public PsiElement getNameIdentifier() - { - PsiElement nameIdentifier = findChildByType(IDENTIFIER_TOKENS_SET); - if(nameIdentifier == null) - { - JSExpression value = getValue(); - // auto-property name - if(value != null && getColonElement() == null) - { - return value; - } - } - return nameIdentifier; - } +public class JSPropertyImpl extends JSElementImpl implements JSProperty { + private static TokenSet IDENTIFIER_TOKENS_SET = + TokenSet.orSet(TokenSet.create(JSTokenTypes.NUMERIC_LITERAL, JSTokenTypes.IDENTIFIER), JavaScriptTokenSets.STRING_LITERALS); + + public JSPropertyImpl(ASTNode node) { + super(node); + } + + @Override + @Nonnull + public PsiReference[] getReferences() { + return LanguageCachedValueUtil.getCachedValue(this, new CachedValueProvider() { + @Nullable + @Override + @RequiredReadAction + public Result compute() { + return Result.create( + buildReferences(), + JSPropertyImpl.this, + PsiModificationTracker.MODIFICATION_COUNT + ); + } + }); + } + + @Nonnull + @RequiredReadAction + private PsiReference[] buildReferences() { + PsiElement nameIdentifier = getNameIdentifier(); + if (nameIdentifier == null) { + return PsiReference.EMPTY_ARRAY; + } + PsiReference reference = JSPropertyNameReferenceProvider.EP_NAME.computeSafeIfAny(it -> it.getReference(this)); + if (reference != null) { + return new PsiReference[]{reference}; + } + return PsiReference.EMPTY_ARRAY; + } + + @Override + @RequiredReadAction + public String getName() { + PsiElement nameIdentifier = getNameIdentifier(); + return nameIdentifier != null ? StringUtil.stripQuotesAroundValue(nameIdentifier.getText()) : null; + } + + @Override + @RequiredWriteAction + public PsiElement setName(@Nonnull String name) throws IncorrectOperationException { + PsiElement nameNode = getNameIdentifier(); + assert nameNode != null; + ASTNode nameElement = JSChangeUtil.createNameIdentifier(getProject(), name, nameNode.getNode().getElementType()); + getNode().replaceChild(nameNode.getNode(), nameElement); + return this; + } + + @RequiredReadAction + @Nonnull + @Override + public JavaScriptType getType() { + JSExpression value = getValue(); + if (value != null) { + return value.getType(); + } + return JavaScriptType.UNKNOWN; + } + + @RequiredReadAction + @Override + public JSExpression getValue() { + return findChildByClass(JSExpression.class); + } + + @RequiredReadAction + @Nullable + @Override + public PsiElement getColonElement() { + return findChildByType(JSTokenTypes.COLON); + } + + @RequiredReadAction + @Nullable + @Override + public JSComputedName getComputedName() { + return findChildByClass(JSComputedName.class); + } + + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSProperty(this); + } + + @RequiredReadAction + @Override + public int getTextOffset() { + PsiElement name = getNameIdentifier(); + return name != null ? name.getTextOffset() : super.getTextOffset(); + } + + @Override + @RequiredWriteAction + public void delete() throws IncorrectOperationException { + ASTNode myNode = getNode(); + JSChangeUtil.removeRangeWithRemovalOfCommas(myNode, myNode.getTreeParent()); + } + + @Override + @RequiredReadAction + public PsiElement getNameIdentifier() { + PsiElement nameIdentifier = findChildByType(IDENTIFIER_TOKENS_SET); + if (nameIdentifier == null) { + JSExpression value = getValue(); + // auto-property name + if (value != null && getColonElement() == null) { + return value; + } + } + return nameIdentifier; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSPsiImplUtils.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSPsiImplUtils.java index 5701df90..6227bcf3 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSPsiImplUtils.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSPsiImplUtils.java @@ -22,9 +22,10 @@ import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.content.base.SourcesOrderRootType; -import consulo.javascript.language.psi.JavaScriptTypeElement; import consulo.javascript.lang.psi.impl.elementType.BaseJavaScriptElementType; +import consulo.javascript.language.psi.JavaScriptTypeElement; import consulo.javascript.language.psi.stub.JavaScriptIndexKeys; import consulo.javascript.psi.JavaScriptImportStatementBase; import consulo.language.ast.ASTNode; @@ -41,463 +42,396 @@ import consulo.project.DumbService; import consulo.project.Project; import consulo.util.collection.HashingStrategy; -import consulo.util.lang.Comparing; import consulo.util.lang.StringUtil; import consulo.virtualFileSystem.VirtualFile; import consulo.xml.psi.xml.XmlFile; -import org.jetbrains.annotations.NonNls; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.io.IOException; import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.Objects; import java.util.function.Consumer; /** * @author Maxim.Mossienko - * Date: Jun 8, 2008 - * Time: 3:23:37 PM + * @since 2008-06-08 */ -public class JSPsiImplUtils -{ - @NonNls - private static final String ARRAY_TYPE_NAME = "Array"; - @NonNls - private static final String ARRAY_ELEMENT_TYPE_ANNOTATION_NAME = "ArrayElementType"; - - @Nullable - @RequiredReadAction - public static JavaScriptTypeElement findTypeElement(@Nonnull PsiElement element) - { - if(element instanceof StubBasedPsiElement) - { - StubElement stub = ((StubBasedPsiElement) element).getStub(); - if(stub != null) - { - List childrenStubs = stub.getChildrenStubs(); - for(StubElement childrenStub : childrenStubs) - { - IStubElementType stubType = childrenStub.getStubType(); - if(stubType instanceof BaseJavaScriptElementType) - { - return (JavaScriptTypeElement) stub.getPsi(); - } - } - } - } - - return findChildrenByClass(element, JavaScriptTypeElement.class); - } - - @Nullable - @RequiredReadAction - @SuppressWarnings("unchecked") - private static T findChildrenByClass(@Nonnull PsiElement element, Class aClass) - { - for(PsiElement cur = element.getFirstChild(); cur != null; cur = cur.getNextSibling()) - { - if(aClass.isInstance(cur)) - { - return (T) cur; - } - } - return null; - } - - @Deprecated - public static ASTNode getTypeExpressionFromDeclaration(JSNamedElement element) - { - final ASTNode myNode = element.getNode(); - final ASTNode node = myNode != null ? myNode.findChildByType(JSTokenTypes.COLON) : null; - String s = null; - - if(node != null) - { - return myNode.findChildByType(JSDocumentationUtils.ourTypeFilter, node); - } - - return null; - } - - @Deprecated - public static String getTypeFromDeclaration(JSNamedElement element) - { - ASTNode typeExpr = getTypeExpressionFromDeclaration(element); - - String s = null; - if(typeExpr != null) - { - s = typeExpr.getText(); - } - else if(element instanceof JSParameter && ((JSParameter) element).isRest()) - { - s = ARRAY_TYPE_NAME; - } - - if(ARRAY_TYPE_NAME.equals(s)) - { - final PsiComment psiComment = typeExpr != null ? PsiTreeUtil.getPrevSiblingOfType(typeExpr.getPsi(), PsiComment.class) : null; - - if(psiComment != null) - { - final String elementType = JSDocumentationUtils.unwrapCommentDelimiters(psiComment.getText()).trim(); - - if(elementType.length() > 0) - { - return s + "[" + elementType; - } - } - - if(element instanceof JSAttributeListOwner) - { - final JSAttributeListOwner attributeListOwner = (JSAttributeListOwner) element; - final JSAttributeList attributeList = attributeListOwner.getAttributeList(); - - if(attributeList != null) - { - String type = getArrayElementTypeFromAnnotation(attributeList); - if(type != null && type.length() > 0) - { - return s + "[" + type; - } - } - } - - } - - return s; - } - - public static - @Nullable - String getArrayElementTypeFromAnnotation(JSAttributeList attributeList) - { - return getTypeFromAnnotationParameter(attributeList, ARRAY_ELEMENT_TYPE_ANNOTATION_NAME, null); - } - - public static String getType(JSNamedElement element) - { - final String typeFromDeclaration = getTypeFromDeclaration(element); - if(typeFromDeclaration != null) - { - return typeFromDeclaration; - } - - return JSDocumentationUtils.findTypeFromComments(element); - } - - public static void updateFileName(JSQualifiedNamedElement jsClassBase, final String newName, final String oldName) throws IncorrectOperationException - { - final PsiFile containingFile = jsClassBase.getContainingFile(); - - if(containingFile.getContext() == null) - { - final VirtualFile virtualFile = containingFile.getVirtualFile(); - - if(virtualFile != null && virtualFile.getNameWithoutExtension().equals(oldName)) - { - final String s = containingFile.getName(); - containingFile.setName(newName + "." + s.substring(s.lastIndexOf('.') + 1)); - } - } - } - - public static - @Nullable - JSPackageStatement findPackageStatement(JSFile file) - { - JSPackageStatement packageStatement = null; - - for(PsiElement statement : file.getChildren()) - { - if(statement instanceof JSPackageStatement) - { - packageStatement = (JSPackageStatement) statement; - break; - } - } - return packageStatement; - } - - static - @Nonnull - PsiElement findTopLevelNavigatableElement(@Nonnull JSQualifiedNamedElement jsClass) - { - PsiElement sourceElement = findTopLevelNavigatableElementWithSource(jsClass, null); - if(sourceElement != null) - { - return sourceElement; - } - return jsClass; - } - - @Nullable - public static PsiElement findTopLevelNavigatableElementWithSource(@Nonnull JSQualifiedNamedElement jsClass, @Nullable Consumer candidatesConsumer) - { - if(candidatesConsumer != null) - { - candidatesConsumer.accept(jsClass); - } - - PsiElement sourceElement = findSourceElement(jsClass); - if(sourceElement != null) - { - return sourceElement; - } - - if(DumbService.isDumb(jsClass.getProject())) - { - return null; - } - - GlobalSearchScope searchScope = jsClass.getResolveScope(); - final String qName = jsClass.getQualifiedName(); - final Collection candidates = StubIndex.getElements(JavaScriptIndexKeys.ELEMENTS_BY_QNAME, qName, jsClass.getProject(), searchScope, JSQualifiedNamedElement.class); - for(Iterator i = candidates.iterator(); i.hasNext(); ) - { - if(!qName.equals(i.next().getQualifiedName())) - { - i.remove(); - } - } - - for(JSQualifiedNamedElement candidate : candidates) - { - if(candidate == jsClass) - { - continue; - } - - if(candidatesConsumer != null) - { - candidatesConsumer.accept(candidate); - } - - PsiElement candidateSourceElement = findSourceElement(candidate); - if(candidateSourceElement != null) - { - return candidateSourceElement; - } - } - return null; - } - - @Nullable - private static PsiElement findSourceElement(JSQualifiedNamedElement jsClass) - { - PsiFile containingFile = jsClass.getContainingFile(); - if(containingFile == null) - { - return null; - } - - VirtualFile vFile = containingFile.getVirtualFile(); - ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(jsClass.getProject()).getFileIndex(); - if(vFile == null || projectFileIndex.getClassRootForFile(vFile) == null) - { - return null; - } - - final List orderEntries = projectFileIndex.getOrderEntriesForFile(vFile); - - String qName = jsClass.getQualifiedName(); - String baseSourceName = jsClass.getName(); - int index = qName != null ? qName.lastIndexOf('.') : -1; - String packageName = index != -1 ? qName.substring(0, index) : ""; - String relativeFilePath = packageName.length() == 0 ? baseSourceName : packageName.replace('.', '/') + '/' + baseSourceName; - String relativeFilePath2 = relativeFilePath + ".mxml"; - String relativeFilePath3 = relativeFilePath + ".mxm"; - relativeFilePath += ".as"; - - for(OrderEntry orderEntry : orderEntries) - { - VirtualFile[] files = orderEntry.getFiles(SourcesOrderRootType.getInstance()); - - for(VirtualFile file : files) - { - VirtualFile source = file.findFileByRelativePath(relativeFilePath); - - if(source != null) - { - PsiFile psiSource = jsClass.getManager().findFile(source); - - if(psiSource instanceof JSFile) - { - JSPackageStatement statement = findPackageStatement((JSFile) psiSource); - - if(statement != null) - { - for(JSSourceElement el : statement.getStatements()) - { - if(el.getClass() == jsClass.getClass() && jsClass.getName().equals(el.getName())) - { - return el; - } - } - } - return psiSource; - } - } - else - { - source = file.findFileByRelativePath(relativeFilePath2); - if(source == null) - { - source = file.findFileByRelativePath(relativeFilePath3); - } - if(source != null) - { - PsiFile psiSource = jsClass.getManager().findFile(source); - if(psiSource instanceof XmlFile) - { - return XmlBackedJSClassImpl.getXmlBackedClass((XmlFile) psiSource); - } - } - } - } - } - return null; - } - - static String getQName(final JSNamedElement element) - { - final PsiElement node = element.getNameIdentifier(); - final String name = node != null ? node.getText() : null; - PsiElement responsibleParent = element.getParent(); - - if(responsibleParent instanceof JSVarStatement) - { - responsibleParent = responsibleParent.getParent(); - } - - if(responsibleParent instanceof JSPackageStatement && name != null) - { - final String packageName = ((JSPackageStatement) responsibleParent).getQualifiedName(); - if(!StringUtil.isEmpty(packageName)) - { - return packageName.concat(".").concat(name); - } - } - return name; - } - - public static - @Nullable - String getTypeFromAnnotationParameter(@Nonnull JSAttributeList attributeList, @Nonnull String annotationName, @Nullable String annotationParameter) - { - String arrayType = null; - final JSAttribute[] byName = attributeList.getAttributesByName(annotationName); - if(byName.length > 0) - { - final JSAttributeNameValuePair jsAttributeNameValuePair = byName[0].getValueByName(annotationParameter); - arrayType = jsAttributeNameValuePair != null ? jsAttributeNameValuePair.getSimpleValue() : null; - } - return arrayType; - } - - /** - * @see QUALIFIED_NAME_HASHING_STRATEGY - */ - static boolean isTheSameClass(final PsiElement typeSource, final JSClass jsClass) - { - if(typeSource == jsClass) - { - return true; - } - if(typeSource instanceof JSClass && jsClass != null) - { - final String qName = ((JSClass) typeSource).getQualifiedName(); - return qName != null && qName.equals(jsClass.getQualifiedName()); - } - return false; - } - - public static final HashingStrategy QUALIFIED_NAME_HASHING_STRATEGY = new HashingStrategy<>() - { - @Override - public int hashCode(final JSQualifiedNamedElement object) - { - return object == null || object.getQualifiedName() == null ? 0 : object.getQualifiedName().hashCode(); - } - - @Override - public boolean equals(final JSQualifiedNamedElement o1, final JSQualifiedNamedElement o2) - { - return Comparing.equal(o1.getQualifiedName(), o2.getQualifiedName()); - } - }; - - static void doRenameParentDirectoryIfNeeded(VirtualFile file, String name, Object requestor) throws IOException - { - VirtualFile directory = file.isDirectory() ? file : file.getParent(); - if(!name.equals(directory.getName())) - { - directory.rename(requestor, name); - } - } - - static - @Nullable - String getQNameForMove(@Nonnull PsiElement targetElement, PsiElement elementToBind) - { - String qName = null; - Project project = targetElement.getProject(); - - if(elementToBind instanceof PsiFile) - { - String newName = ((PsiNamedElement) elementToBind).getName(); - int index = newName.lastIndexOf('.'); - if(index != -1) - { - newName = newName.substring(0, index); - } - VirtualFile elementToBindFile = elementToBind.getContainingFile().getVirtualFile(); - - String packageName = JSResolveUtil.getExpectedPackageNameFromFile(elementToBindFile, project, false); - - if(targetElement instanceof JSReferenceExpression) - { - JSExpression qualifier = ((JSReferenceExpression) targetElement).getQualifier(); - String targetElementPackageName = qualifier != null ? qualifier.getText() : JSResolveUtil.getExpectedPackageNameFromFile(targetElement.getContainingFile().getVirtualFile(), project, - false); - if(!differentPackageName(targetElementPackageName, packageName)) - { - return null; - } - if(qualifier == null) - { - if(!(targetElement.getParent() instanceof JavaScriptImportStatementBase)) - { - return null; - } - } - } - - qName = packageName.isEmpty() ? newName : packageName + "." + newName; - } - else if(elementToBind instanceof PsiDirectoryContainer) - { - PsiDirectory[] directories = ((PsiDirectoryContainer) elementToBind).getDirectories(targetElement.getResolveScope()); - if(directories.length > 0) - { - qName = JSResolveUtil.getExpectedPackageNameFromFile(directories[0].getVirtualFile(), project, false); - } - } - return qName; - } - - public static boolean differentPackageName(final String s, final String expectedPackageNameFromFile) - { - final boolean sIsEmpty = isEmpty(s); - final boolean expectedIsEmpty = isEmpty(expectedPackageNameFromFile); - - return (sIsEmpty && !expectedIsEmpty) || (!sIsEmpty && (expectedIsEmpty || !s.equals(expectedPackageNameFromFile))); - } - - public static boolean isEmpty(final String expectedPackageNameFromFile) - { - return expectedPackageNameFromFile == null || expectedPackageNameFromFile.length() == 0; - } +public class JSPsiImplUtils { + private static final String ARRAY_TYPE_NAME = "Array"; + private static final String ARRAY_ELEMENT_TYPE_ANNOTATION_NAME = "ArrayElementType"; + + @Nullable + @RequiredReadAction + public static JavaScriptTypeElement findTypeElement(@Nonnull PsiElement element) { + if (element instanceof StubBasedPsiElement stubBasedPsiElement) { + StubElement stub = stubBasedPsiElement.getStub(); + if (stub != null) { + List childrenStubs = stub.getChildrenStubs(); + for (StubElement childrenStub : childrenStubs) { + IStubElementType stubType = childrenStub.getStubType(); + if (stubType instanceof BaseJavaScriptElementType) { + return (JavaScriptTypeElement)stub.getPsi(); + } + } + } + } + + return findChildrenByClass(element, JavaScriptTypeElement.class); + } + + @Nullable + @RequiredReadAction + @SuppressWarnings("unchecked") + private static T findChildrenByClass(@Nonnull PsiElement element, Class aClass) { + for (PsiElement cur = element.getFirstChild(); cur != null; cur = cur.getNextSibling()) { + if (aClass.isInstance(cur)) { + return (T)cur; + } + } + return null; + } + + @Deprecated + public static ASTNode getTypeExpressionFromDeclaration(JSNamedElement element) { + ASTNode myNode = element.getNode(); + ASTNode node = myNode != null ? myNode.findChildByType(JSTokenTypes.COLON) : null; + + return node != null ? myNode.findChildByType(JSDocumentationUtils.TYPE_FILTER, node) : null; + } + + @Deprecated + @RequiredReadAction + public static String getTypeFromDeclaration(JSNamedElement element) { + ASTNode typeExpr = getTypeExpressionFromDeclaration(element); + + String s = null; + if (typeExpr != null) { + s = typeExpr.getText(); + } + else if (element instanceof JSParameter parameter && parameter.isRest()) { + s = ARRAY_TYPE_NAME; + } + + if (ARRAY_TYPE_NAME.equals(s)) { + PsiComment psiComment = typeExpr != null ? PsiTreeUtil.getPrevSiblingOfType(typeExpr.getPsi(), PsiComment.class) : null; + + if (psiComment != null) { + String elementType = JSDocumentationUtils.unwrapCommentDelimiters(psiComment.getText()).trim(); + + if (elementType.length() > 0) { + return s + "[" + elementType; + } + } + + if (element instanceof JSAttributeListOwner attributeListOwner) { + JSAttributeList attributeList = attributeListOwner.getAttributeList(); + + if (attributeList != null) { + String type = getArrayElementTypeFromAnnotation(attributeList); + if (type != null && type.length() > 0) { + return s + "[" + type; + } + } + } + + } + + return s; + } + + @Nullable + @RequiredReadAction + public static String getArrayElementTypeFromAnnotation(JSAttributeList attributeList) { + return getTypeFromAnnotationParameter(attributeList, ARRAY_ELEMENT_TYPE_ANNOTATION_NAME, null); + } + + @RequiredReadAction + public static String getType(JSNamedElement element) { + String typeFromDeclaration = getTypeFromDeclaration(element); + if (typeFromDeclaration != null) { + return typeFromDeclaration; + } + + return JSDocumentationUtils.findTypeFromComments(element); + } + + @RequiredWriteAction + public static void updateFileName(JSQualifiedNamedElement jsClassBase, String newName, String oldName) + throws IncorrectOperationException { + + PsiFile containingFile = jsClassBase.getContainingFile(); + + if (containingFile.getContext() == null) { + VirtualFile virtualFile = containingFile.getVirtualFile(); + + if (virtualFile != null && virtualFile.getNameWithoutExtension().equals(oldName)) { + String s = containingFile.getName(); + containingFile.setName(newName + "." + s.substring(s.lastIndexOf('.') + 1)); + } + } + } + + @Nullable + @RequiredReadAction + public static JSPackageStatement findPackageStatement(JSFile file) { + JSPackageStatement packageStatement = null; + + for (PsiElement statement : file.getChildren()) { + if (statement instanceof JSPackageStatement packageStmt) { + packageStatement = packageStmt; + break; + } + } + return packageStatement; + } + + @Nonnull + @RequiredReadAction + static PsiElement findTopLevelNavigatableElement(@Nonnull JSQualifiedNamedElement jsClass) { + PsiElement sourceElement = findTopLevelNavigatableElementWithSource(jsClass, null); + if (sourceElement != null) { + return sourceElement; + } + return jsClass; + } + + @Nullable + @RequiredReadAction + public static PsiElement findTopLevelNavigatableElementWithSource( + @Nonnull JSQualifiedNamedElement jsClass, + @Nullable Consumer candidatesConsumer + ) { + if (candidatesConsumer != null) { + candidatesConsumer.accept(jsClass); + } + + PsiElement sourceElement = findSourceElement(jsClass); + if (sourceElement != null) { + return sourceElement; + } + + if (DumbService.isDumb(jsClass.getProject())) { + return null; + } + + GlobalSearchScope searchScope = jsClass.getResolveScope(); + String qName = jsClass.getQualifiedName(); + Collection candidates = StubIndex.getElements( + JavaScriptIndexKeys.ELEMENTS_BY_QNAME, + qName, + jsClass.getProject(), + searchScope, + JSQualifiedNamedElement.class + ); + for (Iterator i = candidates.iterator(); i.hasNext(); ) { + if (!qName.equals(i.next().getQualifiedName())) { + i.remove(); + } + } + + for (JSQualifiedNamedElement candidate : candidates) { + if (candidate == jsClass) { + continue; + } + + if (candidatesConsumer != null) { + candidatesConsumer.accept(candidate); + } + + PsiElement candidateSourceElement = findSourceElement(candidate); + if (candidateSourceElement != null) { + return candidateSourceElement; + } + } + return null; + } + + @Nullable + @RequiredReadAction + private static PsiElement findSourceElement(JSQualifiedNamedElement jsClass) { + PsiFile containingFile = jsClass.getContainingFile(); + if (containingFile == null) { + return null; + } + + VirtualFile vFile = containingFile.getVirtualFile(); + ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(jsClass.getProject()).getFileIndex(); + if (vFile == null || projectFileIndex.getClassRootForFile(vFile) == null) { + return null; + } + + List orderEntries = projectFileIndex.getOrderEntriesForFile(vFile); + + String qName = jsClass.getQualifiedName(); + String baseSourceName = jsClass.getName(); + int index = qName != null ? qName.lastIndexOf('.') : -1; + String packageName = index != -1 ? qName.substring(0, index) : ""; + String relativeFilePath = packageName.length() == 0 ? baseSourceName : packageName.replace('.', '/') + '/' + baseSourceName; + String relativeFilePath2 = relativeFilePath + ".mxml"; + String relativeFilePath3 = relativeFilePath + ".mxm"; + relativeFilePath += ".as"; + + for (OrderEntry orderEntry : orderEntries) { + VirtualFile[] files = orderEntry.getFiles(SourcesOrderRootType.getInstance()); + + for (VirtualFile file : files) { + VirtualFile source = file.findFileByRelativePath(relativeFilePath); + + if (source != null) { + PsiFile psiSource = jsClass.getManager().findFile(source); + + if (psiSource instanceof JSFile jsFile) { + JSPackageStatement statement = findPackageStatement(jsFile); + + if (statement != null) { + for (JSSourceElement el : statement.getStatements()) { + if (el.getClass() == jsClass.getClass() && jsClass.getName().equals(el.getName())) { + return el; + } + } + } + return psiSource; + } + } + else { + source = file.findFileByRelativePath(relativeFilePath2); + if (source == null) { + source = file.findFileByRelativePath(relativeFilePath3); + } + if (source != null) { + PsiFile psiSource = jsClass.getManager().findFile(source); + if (psiSource instanceof XmlFile xmlFile) { + return XmlBackedJSClassImpl.getXmlBackedClass(xmlFile); + } + } + } + } + } + return null; + } + + @RequiredReadAction + static String getQName(JSNamedElement element) { + PsiElement node = element.getNameIdentifier(); + String name = node != null ? node.getText() : null; + PsiElement responsibleParent = element.getParent(); + + if (responsibleParent instanceof JSVarStatement varStatement) { + responsibleParent = varStatement.getParent(); + } + + if (responsibleParent instanceof JSPackageStatement packageStatement && name != null) { + String packageName = packageStatement.getQualifiedName(); + if (!StringUtil.isEmpty(packageName)) { + return packageName.concat(".").concat(name); + } + } + return name; + } + + @Nullable + @RequiredReadAction + public static String getTypeFromAnnotationParameter( + @Nonnull JSAttributeList attributeList, + @Nonnull String annotationName, + @Nullable String annotationParameter + ) { + String arrayType = null; + JSAttribute[] byName = attributeList.getAttributesByName(annotationName); + if (byName.length > 0) { + JSAttributeNameValuePair jsAttributeNameValuePair = byName[0].getValueByName(annotationParameter); + arrayType = jsAttributeNameValuePair != null ? jsAttributeNameValuePair.getSimpleValue() : null; + } + return arrayType; + } + + /** + * @see QUALIFIED_NAME_HASHING_STRATEGY + */ + @RequiredReadAction + static boolean isTheSameClass(PsiElement typeSource, JSClass jsClass) { + if (typeSource == jsClass) { + return true; + } + if (typeSource instanceof JSClass typeSourceClass && jsClass != null) { + String qName = typeSourceClass.getQualifiedName(); + return qName != null && qName.equals(jsClass.getQualifiedName()); + } + return false; + } + + public static final HashingStrategy QUALIFIED_NAME_HASHING_STRATEGY = new HashingStrategy<>() { + @Override + @RequiredReadAction + public int hashCode(JSQualifiedNamedElement object) { + return object == null || object.getQualifiedName() == null ? 0 : object.getQualifiedName().hashCode(); + } + + @Override + @RequiredReadAction + public boolean equals(JSQualifiedNamedElement o1, JSQualifiedNamedElement o2) { + return Objects.equals(o1.getQualifiedName(), o2.getQualifiedName()); + } + }; + + static void doRenameParentDirectoryIfNeeded(VirtualFile file, String name, Object requestor) throws IOException { + VirtualFile directory = file.isDirectory() ? file : file.getParent(); + if (!name.equals(directory.getName())) { + directory.rename(requestor, name); + } + } + + @Nullable + @RequiredReadAction + static String getQNameForMove(@Nonnull PsiElement targetElement, PsiElement elementToBind) { + String qName = null; + Project project = targetElement.getProject(); + + if (elementToBind instanceof PsiFile file) { + String newName = file.getName(); + int index = newName.lastIndexOf('.'); + if (index != -1) { + newName = newName.substring(0, index); + } + VirtualFile elementToBindFile = file.getContainingFile().getVirtualFile(); + + String packageName = JSResolveUtil.getExpectedPackageNameFromFile(elementToBindFile, project, false); + + if (targetElement instanceof JSReferenceExpression targetRefExpr) { + JSExpression qualifier = targetRefExpr.getQualifier(); + String targetElementPackageName = qualifier != null + ? qualifier.getText() + : JSResolveUtil.getExpectedPackageNameFromFile(targetRefExpr.getContainingFile().getVirtualFile(), project, false); + if (!differentPackageName(targetElementPackageName, packageName)) { + return null; + } + if (qualifier == null && !(targetRefExpr.getParent() instanceof JavaScriptImportStatementBase)) { + return null; + } + } + + qName = packageName.isEmpty() ? newName : packageName + "." + newName; + } + else if (elementToBind instanceof PsiDirectoryContainer directoryContainer) { + PsiDirectory[] directories = directoryContainer.getDirectories(targetElement.getResolveScope()); + if (directories.length > 0) { + qName = JSResolveUtil.getExpectedPackageNameFromFile(directories[0].getVirtualFile(), project, false); + } + } + return qName; + } + + public static boolean differentPackageName(String s, String expectedPackageNameFromFile) { + boolean sIsEmpty = isEmpty(s); + boolean expectedIsEmpty = isEmpty(expectedPackageNameFromFile); + + return (sIsEmpty && !expectedIsEmpty) || (!sIsEmpty && (expectedIsEmpty || !s.equals(expectedPackageNameFromFile))); + } + + public static boolean isEmpty(String expectedPackageNameFromFile) { + return expectedPackageNameFromFile == null || expectedPackageNameFromFile.isEmpty(); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSReferenceExpressionImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSReferenceExpressionImpl.java index 6fe0349b..aedafc52 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSReferenceExpressionImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSReferenceExpressionImpl.java @@ -21,12 +21,13 @@ import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.resolve.*; import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.document.util.TextRange; +import consulo.javascript.lang.psi.impl.resolve.ResolveHelper; import consulo.javascript.language.JavaScriptFeature; import consulo.javascript.language.JavaScriptLanguage; import consulo.javascript.language.JavaScriptVersionUtil; import consulo.javascript.language.psi.JavaScriptType; -import consulo.javascript.lang.psi.impl.resolve.ResolveHelper; import consulo.language.ast.ASTNode; import consulo.language.ast.TokenSet; import consulo.language.editor.refactoring.NamesValidator; @@ -39,756 +40,649 @@ import consulo.util.collection.ArrayUtil; import consulo.xml.psi.xml.XmlFile; import consulo.xml.psi.xml.XmlToken; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.Set; -public class JSReferenceExpressionImpl extends JSExpressionImpl implements JSReferenceExpression, BindablePsiReference -{ - private static final TokenSet IDENTIFIER_TOKENS_SET = TokenSet.orSet(JSTokenTypes.IDENTIFIER_TOKENS_SET, TokenSet.create(JSTokenTypes.ANY_IDENTIFIER)); - - public JSReferenceExpressionImpl(final ASTNode node) - { - super(node); - } - - @RequiredReadAction - @Nonnull - @Override - public JavaScriptType getType() - { - PsiElement resolvedElement = resolve(); - if(resolvedElement instanceof JSVariable) - { - return ((JSVariable) resolvedElement).getType(); - } - else if(resolvedElement instanceof JSFunction) - { - return ((JSFunction) resolvedElement).getReturnType(); - } - return super.getType(); - } - - @Override - @Nullable - @RequiredReadAction - public JSExpression getQualifier() - { - PsiElement firstChild = getFirstChild(); - return firstChild instanceof JSExpression ? (JSExpression) firstChild : null; - } - - @Override - @Nullable - @RequiredReadAction - public String getReferencedName() - { - final PsiElement nameElement = getNameElement(); - return nameElement != null ? nameElement.getText() : null; - } - - @Override - @Nullable - @RequiredReadAction - public PsiElement getReferenceNameElement() - { - final PsiElement element = getNameElement(); - return element != null ? element : null; - } - - @RequiredReadAction - @Override - public PsiElement getElement() - { - return this; - } - - @Override - public PsiReference getReference() - { - return this; - } - - @Nonnull - @Override - @RequiredReadAction - public TextRange getRangeInElement() - { - PsiElement nameElement = getNameElement(); - - if(nameElement != null) - { - int offset = nameElement.getStartOffsetInParent(); - return new TextRange(offset, offset + nameElement.getTextLength()); - } - else - { - return new TextRange(0, getTextLength()); - } - } - - @Nullable - @RequiredReadAction - private PsiElement getNameElement() - { - return findChildByType(IDENTIFIER_TOKENS_SET); - } - - @Override - public PsiElement resolve() - { - final ResolveResult[] resolveResults = multiResolve(true); - - return resolveResults.length == 0 || resolveResults.length > 1 ? null : resolveResults[0].getElement(); - } - - @Nonnull - @Override - @RequiredReadAction - public String getCanonicalText() - { - return getText(); - } - - @Override - public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException - { - return this; - } - - @RequiredReadAction - PsiElement handleElementRenameInternal(String newElementName) throws IncorrectOperationException - { - final int i = newElementName.lastIndexOf('.'); - if(i != -1) - { - newElementName = newElementName.substring(0, i); - } - if(!NamesValidator.forLanguage(JavaScriptLanguage.INSTANCE).isIdentifier(newElementName, null)) - { - throw new IncorrectOperationException("Invalid javascript element name:" + newElementName); - } - final PsiElement parent = getParent(); - if(parent instanceof JSClass || parent instanceof JSFunction) - { - final PsiElement node = ((JSNamedElement) parent).getNameIdentifier(); - if(node != null && node == this) - { - return this; // JSNamedElement.setName will care of things - } - } - JSChangeUtil.doIdentifierReplacement(this, getNameElement(), newElementName); - return getParent(); - } - - @Override - @RequiredReadAction - public PsiElement bindToElement(@Nonnull PsiElement element) throws IncorrectOperationException - { - final PsiElement parent = getParent(); - - if(parent instanceof JSClass || - parent instanceof JSNamespaceDeclaration || - parent instanceof JSFunction) - { - final PsiElement node = ((JSNamedElement) parent).getNameIdentifier(); - - if(node != null && node == this) - { - if(parent == element || element instanceof PsiFile) - { - return this; // JSNamedElement.setName will care of things - } - } - } - - String qName = JSPsiImplUtils.getQNameForMove(this, element); - - if(qName != null) - { - PsiElement newChild = JSChangeUtil.createExpressionFromText(getProject(), qName); - getParent().getNode().replaceChild(getNode(), newChild.getNode()); - return newChild; - } - - String newName = ((PsiNamedElement) element).getName(); - if(element instanceof PsiFile) - { - int index = newName.lastIndexOf('.'); - if(index != -1) - { - newName = newName.substring(0, index); - } - } - - final ASTNode nameElement = JSChangeUtil.createNameIdentifier(getProject(), newName); - getNode().replaceChild(getNameElement().getNode(), nameElement); - return this; - } - - @RequiredReadAction - @Override - public boolean isReferenceTo(PsiElement element) - { - ResolveHelper helper = ResolveHelper.find(this); - if(helper.isResolveTo(this, element)) - { - return true; - } - - PsiElement resolvedElement = resolve(); - if(resolvedElement != null && resolvedElement.isEquivalentTo(element)) - { - return true; - } - -// if(element instanceof PsiNamedElement || element instanceof XmlAttributeValue) -// { -// final String referencedName = getReferencedName(); +public class JSReferenceExpressionImpl extends JSExpressionImpl implements JSReferenceExpression, BindablePsiReference { + private static final TokenSet IDENTIFIER_TOKENS_SET = + TokenSet.orSet(JSTokenTypes.IDENTIFIER_TOKENS_SET, TokenSet.create(JSTokenTypes.ANY_IDENTIFIER)); + + public JSReferenceExpressionImpl(ASTNode node) { + super(node); + } + + @RequiredReadAction + @Nonnull + @Override + public JavaScriptType getType() { + PsiElement resolvedElement = resolve(); + if (resolvedElement instanceof JSVariable variable) { + return variable.getType(); + } + else if (resolvedElement instanceof JSFunction function) { + return function.getReturnType(); + } + return super.getType(); + } + + @Override + @Nullable + @RequiredReadAction + public JSExpression getQualifier() { + return getFirstChild() instanceof JSExpression expression ? expression : null; + } + + @Override + @Nullable + @RequiredReadAction + public String getReferencedName() { + PsiElement nameElement = getNameElement(); + return nameElement != null ? nameElement.getText() : null; + } + + @Override + @Nullable + @RequiredReadAction + public PsiElement getReferenceNameElement() { + PsiElement element = getNameElement(); + return element != null ? element : null; + } + + @RequiredReadAction + @Override + public PsiElement getElement() { + return this; + } + + @Override + public PsiReference getReference() { + return this; + } + + @Nonnull + @Override + @RequiredReadAction + public TextRange getRangeInElement() { + PsiElement nameElement = getNameElement(); + + if (nameElement != null) { + int offset = nameElement.getStartOffsetInParent(); + return new TextRange(offset, offset + nameElement.getTextLength()); + } + else { + return new TextRange(0, getTextLength()); + } + } + + @Nullable + @RequiredReadAction + private PsiElement getNameElement() { + return findChildByType(IDENTIFIER_TOKENS_SET); + } + + @Override + @RequiredReadAction + public PsiElement resolve() { + ResolveResult[] resolveResults = multiResolve(true); + + return resolveResults.length == 0 || resolveResults.length > 1 ? null : resolveResults[0].getElement(); + } + + @Nonnull + @Override + @RequiredReadAction + public String getCanonicalText() { + return getText(); + } + + @Override + @RequiredWriteAction + public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException { + return this; + } + + @RequiredWriteAction + PsiElement handleElementRenameInternal(String newElementName) throws IncorrectOperationException { + int i = newElementName.lastIndexOf('.'); + if (i != -1) { + newElementName = newElementName.substring(0, i); + } + if (!NamesValidator.forLanguage(JavaScriptLanguage.INSTANCE).isIdentifier(newElementName, null)) { + throw new IncorrectOperationException("Invalid javascript element name:" + newElementName); + } + PsiElement parent = getParent(); + if (parent instanceof JSClass || parent instanceof JSFunction) { + PsiElement node = ((JSNamedElement)parent).getNameIdentifier(); + if (node != null && node == this) { + return this; // JSNamedElement.setName will care of things + } + } + JSChangeUtil.doIdentifierReplacement(this, getNameElement(), newElementName); + return getParent(); + } + + @Override + @RequiredReadAction + public PsiElement bindToElement(@Nonnull PsiElement element) throws IncorrectOperationException { + PsiElement parent = getParent(); + + if (parent instanceof JSClass || parent instanceof JSNamespaceDeclaration || parent instanceof JSFunction) { + PsiElement node = ((JSNamedElement)parent).getNameIdentifier(); + + if (node != null && node == this && (parent == element || element instanceof PsiFile)) { + return this; // JSNamedElement.setName will care of things + } + } + + String qName = JSPsiImplUtils.getQNameForMove(this, element); + + if (qName != null) { + PsiElement newChild = JSChangeUtil.createExpressionFromText(getProject(), qName); + getParent().getNode().replaceChild(getNode(), newChild.getNode()); + return newChild; + } + + String newName = ((PsiNamedElement)element).getName(); + if (element instanceof PsiFile) { + int index = newName.lastIndexOf('.'); + if (index != -1) { + newName = newName.substring(0, index); + } + } + + ASTNode nameElement = JSChangeUtil.createNameIdentifier(getProject(), newName); + getNode().replaceChild(getNameElement().getNode(), nameElement); + return this; + } + + @Override + @RequiredReadAction + public boolean isReferenceTo(PsiElement element) { + ResolveHelper helper = ResolveHelper.find(this); + if (helper.isResolveTo(this, element)) { + return true; + } + + PsiElement resolvedElement = resolve(); + if (resolvedElement != null && resolvedElement.isEquivalentTo(element)) { + return true; + } + +// if (element instanceof PsiNamedElement || element instanceof XmlAttributeValue) { +// String referencedName = getReferencedName(); // -// if(referencedName != null) -// { -// if(element instanceof JSDefinitionExpression && referencedName.equals(((JSDefinitionExpression) element).getName())) -// { -// final JSExpression expression = ((JSDefinitionExpression) element).getExpression(); -// if(expression instanceof JSReferenceExpression) -// { -// final JSReferenceExpression jsReferenceExpression = (JSReferenceExpression) expression; -// final JSExpression qualifier = jsReferenceExpression.getQualifier(); -// final JSExpression myQualifier = getQualifier(); +// if (referencedName != null) { +// if (element instanceof JSDefinitionExpression definition && referencedName.equals(definition.getName())) { +// if (definition.getExpression() instanceof JSReferenceExpression jsReferenceExpression) { +// JSExpression qualifier = jsReferenceExpression.getQualifier(); +// JSExpression myQualifier = getQualifier(); // -// return (myQualifier != null || (qualifier == myQualifier || "window".equals(qualifier.getText()))); -// } -// else -// { -// return true; -// } -// } -// else if(element instanceof JSProperty && referencedName.equals(((JSProperty) element).getName())) -// { -// if(getQualifier() != null) -// { -// return true; // TODO: check for type of element to be the same -// } -// //return false; -// } -// } -// return JSResolveUtil.isReferenceTo(this, referencedName, element); -// } - return false; - } - - private void doProcessLocalDeclarations(final JSExpression qualifier, final ResolveProcessor processor, Set features, boolean completion) - { - final JSClass jsClass = findEnclosingClass(this); - processor.configureClassScope(jsClass); - - final boolean inTypeContext = JSResolveUtil.isExprInTypeContext(this); - final boolean whereTypeCanBe = inTypeContext || (completion && features.contains(JavaScriptFeature.CLASS) && JSResolveUtil.isInPlaceWhereTypeCanBeDuringCompletion(this)); - PsiElement elToProcess = this; - PsiElement scopeToStopAt = null; - - final PsiElement parent = getParent(); - boolean strictClassOffset = JSResolveUtil.getTopReferenceParent(parent) instanceof JSImportStatement; - boolean toProcessMembers = !strictClassOffset; - - if(qualifier != null) - { - elToProcess = jsClass; - - if(jsClass == null) - { - if(qualifier instanceof JSThisExpression) - { - if(features.contains(JavaScriptFeature.CLASS)) - { - final JSFunction nearestFunction = PsiTreeUtil.getParentOfType(this, JSFunction.class); - elToProcess = nearestFunction != null ? nearestFunction : this; - } - else - { - elToProcess = PsiTreeUtil.getParentOfType(this, JSProperty.class); - if(elToProcess != null) - { - scopeToStopAt = elToProcess.getParent(); - } - } - } - else if(qualifier instanceof JSSuperExpression) - { - elToProcess = JSResolveUtil.getClassFromTagNameInMxml(this); - } - } - } - else if(whereTypeCanBe) - { - if(inTypeContext) - { - if(!(parent instanceof JSNewExpression) && - !(parent instanceof JSAttributeList) && - !(parent instanceof JSBinaryExpression)) - { - toProcessMembers = false; - // get function since it can have imports - final JSFunction nearestFunction = PsiTreeUtil.getParentOfType(this, JSFunction.class); - elToProcess = nearestFunction != null ? nearestFunction.getFirstChild() : jsClass; - } - } - else if(parent instanceof JSExpressionStatement && JSResolveUtil.isPlaceWhereNsCanBe(parent)) - { - toProcessMembers = false; - elToProcess = null; - } - } - - if((qualifier instanceof JSThisExpression || qualifier instanceof JSSuperExpression) && jsClass != null) - { - scopeToStopAt = jsClass; - if(features.contains(JavaScriptFeature.CLASS)) - { - JSFunctionExpression expression = PsiTreeUtil.getParentOfType(this, JSFunctionExpression.class); - if(expression != null) - { - elToProcess = expression.getFirstChild(); - } - } - } - - if(elToProcess == null && whereTypeCanBe) - { - elToProcess = PsiTreeUtil.getParentOfType(this, JSPackageStatement.class, JSFile.class); - if(elToProcess != null) - { - elToProcess = PsiTreeUtil.getChildOfType(elToProcess, PsiWhiteSpace.class); // this is hack, get rid of it - if(elToProcess == null) - { - elToProcess = this; - } - } - } - - processor.setTypeContext(whereTypeCanBe || (qualifier == null && parent instanceof JSReferenceExpression) || strictClassOffset); - processor.setToProcessMembers(toProcessMembers); - - if(elToProcess != null) - { - processor.setToProcessHierarchy(qualifier != null || !inTypeContext); - processor.setToSkipClassDeclarationsOnce(qualifier instanceof JSSuperExpression); - JSResolveUtil.treeWalkUp(processor, elToProcess, elToProcess, this, scopeToStopAt); - - processor.setToProcessHierarchy(false); - processor.setToSkipClassDeclarationsOnce(false); - } - } - - private static - @Nullable - JSClass findEnclosingClass(PsiElement elt) - { - JSClass jsClass = PsiTreeUtil.getParentOfType(elt, JSClass.class); - if(jsClass == null && elt != null) - { - final PsiElement element = JSResolveUtil.getClassReferenceForXmlFromContext(elt.getContainingFile()); - if(element instanceof JSClass) - { - jsClass = (JSClass) element; - } - } - return jsClass; - } - - @Nonnull - @Override - @RequiredReadAction - public Object[] getVariants() - { - final PsiFile containingFile = getContainingFile(); - Set features = JavaScriptVersionUtil.getFeatures(this); - final boolean classFeature = features.contains(JavaScriptFeature.CLASS); - Object[] smartVariants = JSSmartCompletionVariantsHandler.getSmartVariants(this, classFeature); - if(smartVariants != null) - { - return smartVariants; - } - final JSExpression qualifier = getResolveQualifier(); - - if(qualifier == null) - { - if(JSResolveUtil.isSelfReference(getParent(), this)) - { // Prevent Rulezz to appear - return ArrayUtil.EMPTY_OBJECT_ARRAY; - } - - ResolveProcessor localProcessor = new ResolveProcessor(null, this); - - doProcessLocalDeclarations(qualifier, localProcessor, features, true); - final VariantsProcessor processor = new VariantsProcessor(null, containingFile, false, this); - - processor.addLocalResults(localProcessor.getResults()); - - JSResolveUtil.processGlobalSymbols(this, processor); - - return processor.getResult(); - } - else - { - final MyTypeProcessor processor = new MyTypeProcessor(null, features, this); - BaseJSSymbolProcessor.doEvalForExpr(BaseJSSymbolProcessor.getOriginalQualifier(qualifier), containingFile, processor); - - if(processor.resolved == MyTypeProcessor.TypeResolveState.Resolved || - processor.resolved == MyTypeProcessor.TypeResolveState.Undefined || - (processor.resolved == MyTypeProcessor.TypeResolveState.PrefixUnknown && classFeature)) - { - String qualifiedNameToSkip = null; - if(JSResolveUtil.isSelfReference(getParent(), this)) - { - PsiElement originalParent = PsiUtilBase.getOriginalElement(getParent(), JSQualifiedNamedElement.class); - if(originalParent instanceof JSQualifiedNamedElement) - { - qualifiedNameToSkip = ((JSQualifiedNamedElement) originalParent).getQualifiedName(); - } - } - return processor.getResultsAsObjects(qualifiedNameToSkip); - } - - return processor.getResultsAsObjects(); - } - } - - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSReferenceExpression(this); - } - - @Override - @Nonnull - public ResolveResult[] multiResolve(final boolean incompleteCode) - { - return ResolveCache.getInstance(getContainingFile().getProject()).resolveWithCaching(this, MyResolver.INSTANCE, true, incompleteCode); - } - - private static class MyResolver implements ResolveCache.PolyVariantResolver - { - private static final MyResolver INSTANCE = new MyResolver(); - - @Nonnull - @Override - @RequiredReadAction - public ResolveResult[] resolve(@Nonnull JSReferenceExpressionImpl referenceExpression, boolean incompleteCode) - { - return referenceExpression.doResolve(); - } - } - - @RequiredReadAction - private ResolveResult[] doResolve() - { - PsiFile containingFile = getContainingFile(); - final String referencedName = getReferencedName(); - if(referencedName == null) - { - return ResolveResult.EMPTY_ARRAY; - } - - final PsiElement parent = getParent(); - final JSExpression qualifier = getResolveQualifier(); - Set features = JavaScriptVersionUtil.getFeatures(this); - final boolean classFeature = features.contains(JavaScriptFeature.CLASS); - - final boolean localResolve = qualifier == null; - final boolean parentIsDefinition = parent instanceof JSDefinitionExpression; - - // Handle self references - PsiElement currentParent = JSResolveUtil.getTopReferenceParent(parent); - if(JSResolveUtil.isSelfReference(currentParent, this)) - { - if(!(currentParent instanceof JSPackageStatement) || parent == currentParent) - { - return new ResolveResult[]{new JSResolveUtil.MyResolveResult(currentParent)}; - } - } - - JSExpression realQualifier = getQualifier(); - if(isE4XAttributeReference(realQualifier)) - { // TODO: fix tree - return new ResolveResult[]{new JSResolveUtil.MyResolveResult(this)}; - } - - if("*".equals(referencedName) && currentParent instanceof JSImportStatement && qualifier instanceof JSReferenceExpression) - { // TODO: move to some processor - return ((JSReferenceExpression) qualifier).multiResolve(false); - } - - ResolveProcessor localProcessor; - - if(qualifier == null) - { - localProcessor = new ResolveProcessor(referencedName, this); - - final boolean canResolveAllLocally = !parentIsDefinition || !classFeature; - doProcessLocalDeclarations(realQualifier, localProcessor, features, false); - - if(canResolveAllLocally) - { - final PsiElement jsElement = localProcessor.getResult(); - - if(jsElement != null || (qualifier != null && classFeature && localProcessor.foundAllValidResults())) - { - return localProcessor.getResultsAsResolveResults(); - } - } - return doOldResolve(containingFile, referencedName, parent, qualifier, classFeature, localResolve, parentIsDefinition, localProcessor); - } - else - { - final MyTypeProcessor processor = new MyTypeProcessor(referencedName, features, this); - BaseJSSymbolProcessor.doEvalForExpr(qualifier, containingFile, processor); - - if(processor.resolved == MyTypeProcessor.TypeResolveState.PrefixUnknown && classFeature) - { - return new ResolveResult[]{new JSResolveUtil.MyResolveResult(this)}; - } - - if(processor.resolved == MyTypeProcessor.TypeResolveState.Resolved || - processor.resolved == MyTypeProcessor.TypeResolveState.Undefined || - processor.getResult() != null) - { - return processor.getResultsAsResolveResults(); - } - else - { - return processor.getResultsAsResolveResults(); - } - } - } - - private boolean isE4XAttributeReference(JSExpression realQualifier) - { - return getNode().findChildByType(JSTokenTypes.AT) != null || (realQualifier != null && realQualifier.getNode().findChildByType(JSTokenTypes.AT) != null); - } - - @Nullable - public JSExpression getResolveQualifier() - { - final JSExpression qualifier = getQualifier(); - - if(qualifier instanceof JSReferenceExpression) - { - final ASTNode astNode = getNode(); - ASTNode selection = astNode.getTreeNext(); - // TODO:this is not accurate - if(selection != null && selection.getElementType() == JSTokenTypes.COLON_COLON) - { - return null; - } - - final ASTNode nsSelection = astNode.findChildByType(JSTokenTypes.COLON_COLON); - if(nsSelection != null) - { - return ((JSReferenceExpressionImpl) qualifier).getResolveQualifier(); - } - } - else if(qualifier == null) - { - final ASTNode node = getNode().getFirstChildNode(); - - if(node.getElementType() == JSTokenTypes.AT) - { - PsiElement parent = getParent(); - if(parent instanceof JSBinaryExpression) - { - PsiElement element = parent.getParent().getParent(); - if(element instanceof JSCallExpression) - { - parent = ((JSCallExpression) element).getMethodExpression(); - } - } - if(parent instanceof JSExpression) - { - return (JSExpression) parent; - } - return null; - } - } - return qualifier; - } - - private ResolveResult[] doOldResolve(final PsiFile containingFile, - final String referencedName, - final PsiElement parent, - final JSExpression qualifier, - final boolean ecma, - final boolean localResolve, - final boolean parentIsDefinition, - ResolveProcessor localProcessor) - { - if(parentIsDefinition && ((ecma && !localResolve) || (!ecma && qualifier != null))) - { - return new ResolveResult[]{new JSResolveUtil.MyResolveResult(parent)}; - } - - if(localResolve && parentIsDefinition && ecma) - { - if(!localProcessor.processingEncounteredAbsenceOfTypes()) - { - return localProcessor.getResultsAsResolveResults(); - } - - // Fallback for finding some assignment in global scope - } - - final WalkUpResolveProcessor processor = new WalkUpResolveProcessor(referencedName, null, containingFile, false, this); - - if(localProcessor != null) - { - processor.addLocalResults(localProcessor.getResultsAsResolveResults()); - } - - JSResolveUtil.processGlobalSymbols(this, processor); - return processor.getResults(); - } - - @Override - public boolean shouldCheckReferences() - { - return true; - } - - private static class MyTypeProcessor extends ResolveProcessor implements BaseJSSymbolProcessor.TypeProcessor - { - private final Set myFeatures; - - public MyTypeProcessor(String referenceName, final Set features, PsiElement _place) - { - super(referenceName, _place); - myFeatures = features; - setToProcessHierarchy(true); - - configureClassScope(findEnclosingClass(_place)); - } - - enum TypeResolveState - { - Unknown, Resolved, Undefined, PrefixUnknown - } - - TypeResolveState resolved = TypeResolveState.Unknown; - - @Override - public Set getFeatures() - { - return myFeatures; - } - - @Override - public void process(String type, @Nonnull final BaseJSSymbolProcessor.EvaluateContext evaluateContext, PsiElement source) - { - if(evaluateContext.visitedTypes.contains(type)) - { - return; - } - evaluateContext.visitedTypes.add(type); - - if("*".equals(type) || "Object".equals(type)) - { - return; - } - - if(JSTypeEvaluateManager.isArrayType(type)) - { - int index = type.indexOf('['); - if(index != -1) - { - type = type.substring(0, index); - } - } - - PsiElement typeSource = evaluateContext.getSource(); - - setProcessStatics(false); - - final PsiElement placeParent = place.getParent(); - boolean setTypeContext = placeParent instanceof JSReferenceList; - final PsiElement clazz = source != null && (source instanceof JSClass || source instanceof XmlFile) ? source : JSClassImpl.findClassFromNamespace(type, place); - - if(clazz instanceof JSClass) - { - final JSClass jsClass = (JSClass) clazz; - - final boolean statics = ecma() && JSPsiImplUtils.isTheSameClass(typeSource, jsClass) && !(((JSReferenceExpression) place).getQualifier() instanceof JSCallExpression); - setProcessStatics(statics); - if(statics) - { - setTypeName(jsClass.getQualifiedName()); - } - - final boolean saveSetTypeContext = isTypeContext(); - final boolean saveToProcessMembers = isToProcessMembers(); - - if(setTypeContext) - { - setTypeContext(setTypeContext); - setToProcessMembers(false); - } - - try - { - final boolean b = clazz.processDeclarations(this, ResolveState.initial(), clazz, place); - if(!b) - { - resolved = TypeResolveState.Resolved; - } - else if(ecma()) - { - final JSAttributeList attrList = jsClass.getAttributeList(); - if(attrList == null || !attrList.hasModifier(JSAttributeList.ModifierType.DYNAMIC)) - { - resolved = TypeResolveState.Resolved; - } - } - } - finally - { - if(setTypeContext) - { - setTypeContext(saveSetTypeContext); - setToProcessMembers(saveToProcessMembers); - } - } - } - else if(ecma()) - { - resolved = TypeResolveState.Undefined; - } - } - - @Override - public boolean execute(PsiElement element, ResolveState state) - { - boolean b = super.execute(element, state); - if(ecma() && getResult() != null) - { - resolved = MyTypeProcessor.TypeResolveState.Resolved; - } - return b; - } - - @Override - public boolean ecma() - { - return myFeatures.contains(JavaScriptFeature.CLASS); - } - - @Override - public void setUnknownElement(@Nonnull final PsiElement element) - { - if(!(element instanceof XmlToken)) - { - boolean currentIsNotResolved = element == BaseJSSymbolProcessor.getOriginalQualifier(((JSReferenceExpression) place).getQualifier()); - resolved = currentIsNotResolved ? TypeResolveState.PrefixUnknown : TypeResolveState.Unknown; - } - } - } +// return (myQualifier != null || (qualifier == myQualifier || "window".equals(qualifier.getText()))); +// } +// else { +// return true; +// } +// } +// else if (element instanceof JSProperty property && referencedName.equals(property.getName())) { +// if (getQualifier() != null) { +// return true; // TODO: check for type of element to be the same +// } +// //return false; +// } +// } +// return JSResolveUtil.isReferenceTo(this, referencedName, element); +// } + return false; + } + + @RequiredReadAction + private void doProcessLocalDeclarations( + JSExpression qualifier, + ResolveProcessor processor, + Set features, + boolean completion + ) { + JSClass jsClass = findEnclosingClass(this); + processor.configureClassScope(jsClass); + + boolean inTypeContext = JSResolveUtil.isExprInTypeContext(this); + boolean whereTypeCanBe = inTypeContext + || (completion && features.contains(JavaScriptFeature.CLASS) && JSResolveUtil.isInPlaceWhereTypeCanBeDuringCompletion(this)); + PsiElement elToProcess = this; + PsiElement scopeToStopAt = null; + + PsiElement parent = getParent(); + boolean strictClassOffset = JSResolveUtil.getTopReferenceParent(parent) instanceof JSImportStatement; + boolean toProcessMembers = !strictClassOffset; + + if (qualifier != null) { + elToProcess = jsClass; + + if (jsClass == null) { + if (qualifier instanceof JSThisExpression) { + if (features.contains(JavaScriptFeature.CLASS)) { + JSFunction nearestFunction = PsiTreeUtil.getParentOfType(this, JSFunction.class); + elToProcess = nearestFunction != null ? nearestFunction : this; + } + else { + elToProcess = PsiTreeUtil.getParentOfType(this, JSProperty.class); + if (elToProcess != null) { + scopeToStopAt = elToProcess.getParent(); + } + } + } + else if (qualifier instanceof JSSuperExpression) { + elToProcess = JSResolveUtil.getClassFromTagNameInMxml(this); + } + } + } + else if (whereTypeCanBe) { + if (inTypeContext) { + if (!(parent instanceof JSNewExpression || parent instanceof JSAttributeList || parent instanceof JSBinaryExpression)) { + toProcessMembers = false; + // get function since it can have imports + JSFunction nearestFunction = PsiTreeUtil.getParentOfType(this, JSFunction.class); + elToProcess = nearestFunction != null ? nearestFunction.getFirstChild() : jsClass; + } + } + else if (parent instanceof JSExpressionStatement expression && JSResolveUtil.isPlaceWhereNsCanBe(expression)) { + toProcessMembers = false; + elToProcess = null; + } + } + + if ((qualifier instanceof JSThisExpression || qualifier instanceof JSSuperExpression) && jsClass != null) { + scopeToStopAt = jsClass; + if (features.contains(JavaScriptFeature.CLASS)) { + JSFunctionExpression expression = PsiTreeUtil.getParentOfType(this, JSFunctionExpression.class); + if (expression != null) { + elToProcess = expression.getFirstChild(); + } + } + } + + if (elToProcess == null && whereTypeCanBe) { + elToProcess = PsiTreeUtil.getParentOfType(this, JSPackageStatement.class, JSFile.class); + if (elToProcess != null) { + elToProcess = PsiTreeUtil.getChildOfType(elToProcess, PsiWhiteSpace.class); // this is hack, get rid of it + if (elToProcess == null) { + elToProcess = this; + } + } + } + + processor.setTypeContext(whereTypeCanBe || (qualifier == null && parent instanceof JSReferenceExpression) || strictClassOffset); + processor.setToProcessMembers(toProcessMembers); + + if (elToProcess != null) { + processor.setToProcessHierarchy(qualifier != null || !inTypeContext); + processor.setToSkipClassDeclarationsOnce(qualifier instanceof JSSuperExpression); + JSResolveUtil.treeWalkUp(processor, elToProcess, elToProcess, this, scopeToStopAt); + + processor.setToProcessHierarchy(false); + processor.setToSkipClassDeclarationsOnce(false); + } + } + + @Nullable + private static JSClass findEnclosingClass(PsiElement elt) { + JSClass jsClass = PsiTreeUtil.getParentOfType(elt, JSClass.class); + if (jsClass == null && elt != null) { + PsiElement element = JSResolveUtil.getClassReferenceForXmlFromContext(elt.getContainingFile()); + if (element instanceof JSClass jsClassClass) { + jsClass = jsClassClass; + } + } + return jsClass; + } + + @Nonnull + @Override + @RequiredReadAction + public Object[] getVariants() { + PsiFile containingFile = getContainingFile(); + Set features = JavaScriptVersionUtil.getFeatures(this); + boolean classFeature = features.contains(JavaScriptFeature.CLASS); + Object[] smartVariants = JSSmartCompletionVariantsHandler.getSmartVariants(this, classFeature); + if (smartVariants != null) { + return smartVariants; + } + JSExpression qualifier = getResolveQualifier(); + + if (qualifier == null) { + if (JSResolveUtil.isSelfReference(getParent(), this)) { // Prevent Rulezz to appear + return ArrayUtil.EMPTY_OBJECT_ARRAY; + } + + ResolveProcessor localProcessor = new ResolveProcessor(null, this); + + doProcessLocalDeclarations(qualifier, localProcessor, features, true); + VariantsProcessor processor = new VariantsProcessor(null, containingFile, false, this); + + processor.addLocalResults(localProcessor.getResults()); + + JSResolveUtil.processGlobalSymbols(this, processor); + + return processor.getResult(); + } + else { + MyTypeProcessor processor = new MyTypeProcessor(null, features, this); + BaseJSSymbolProcessor.doEvalForExpr(BaseJSSymbolProcessor.getOriginalQualifier(qualifier), containingFile, processor); + + if (processor.resolved == MyTypeProcessor.TypeResolveState.Resolved || + processor.resolved == MyTypeProcessor.TypeResolveState.Undefined || + (processor.resolved == MyTypeProcessor.TypeResolveState.PrefixUnknown && classFeature)) { + String qualifiedNameToSkip = null; + if (JSResolveUtil.isSelfReference(getParent(), this)) { + PsiElement originalParent = PsiUtilBase.getOriginalElement(getParent(), JSQualifiedNamedElement.class); + if (originalParent instanceof JSQualifiedNamedElement qualifiedNamedElement) { + qualifiedNameToSkip = qualifiedNamedElement.getQualifiedName(); + } + } + return processor.getResultsAsObjects(qualifiedNameToSkip); + } + + return processor.getResultsAsObjects(); + } + } + + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSReferenceExpression(this); + } + + @Nonnull + @Override + @RequiredReadAction + public ResolveResult[] multiResolve(boolean incompleteCode) { + return ResolveCache.getInstance(getContainingFile().getProject()) + .resolveWithCaching(this, MyResolver.INSTANCE, true, incompleteCode); + } + + private static class MyResolver implements ResolveCache.PolyVariantResolver { + private static final MyResolver INSTANCE = new MyResolver(); + + @Nonnull + @Override + @RequiredReadAction + public ResolveResult[] resolve(@Nonnull JSReferenceExpressionImpl referenceExpression, boolean incompleteCode) { + return referenceExpression.doResolve(); + } + } + + @RequiredReadAction + private ResolveResult[] doResolve() { + PsiFile containingFile = getContainingFile(); + String referencedName = getReferencedName(); + if (referencedName == null) { + return ResolveResult.EMPTY_ARRAY; + } + + PsiElement parent = getParent(); + JSExpression qualifier = getResolveQualifier(); + Set features = JavaScriptVersionUtil.getFeatures(this); + boolean classFeature = features.contains(JavaScriptFeature.CLASS); + + boolean localResolve = qualifier == null; + boolean parentIsDefinition = parent instanceof JSDefinitionExpression; + + // Handle self references + PsiElement currentParent = JSResolveUtil.getTopReferenceParent(parent); + if (JSResolveUtil.isSelfReference(currentParent, this) + && (!(currentParent instanceof JSPackageStatement) || parent == currentParent)) { + return new ResolveResult[]{new JSResolveUtil.MyResolveResult(currentParent)}; + } + + JSExpression realQualifier = getQualifier(); + if (isE4XAttributeReference(realQualifier)) { // TODO: fix tree + return new ResolveResult[]{new JSResolveUtil.MyResolveResult(this)}; + } + + if ("*".equals(referencedName) && currentParent instanceof JSImportStatement + && qualifier instanceof JSReferenceExpression refExpr) { // TODO: move to some processor + return refExpr.multiResolve(false); + } + + ResolveProcessor localProcessor; + + if (qualifier == null) { + localProcessor = new ResolveProcessor(referencedName, this); + + boolean canResolveAllLocally = !parentIsDefinition || !classFeature; + doProcessLocalDeclarations(realQualifier, localProcessor, features, false); + + if (canResolveAllLocally) { + PsiElement jsElement = localProcessor.getResult(); + + if (jsElement != null || (qualifier != null && classFeature && localProcessor.foundAllValidResults())) { + return localProcessor.getResultsAsResolveResults(); + } + } + return doOldResolve( + containingFile, + referencedName, + parent, + qualifier, + classFeature, + localResolve, + parentIsDefinition, + localProcessor + ); + } + else { + MyTypeProcessor processor = new MyTypeProcessor(referencedName, features, this); + BaseJSSymbolProcessor.doEvalForExpr(qualifier, containingFile, processor); + + if (processor.resolved == MyTypeProcessor.TypeResolveState.PrefixUnknown && classFeature) { + return new ResolveResult[]{new JSResolveUtil.MyResolveResult(this)}; + } + + if (processor.resolved == MyTypeProcessor.TypeResolveState.Resolved || + processor.resolved == MyTypeProcessor.TypeResolveState.Undefined || + processor.getResult() != null) { + return processor.getResultsAsResolveResults(); + } + else { + return processor.getResultsAsResolveResults(); + } + } + } + + @RequiredReadAction + private boolean isE4XAttributeReference(JSExpression realQualifier) { + return getNode().findChildByType(JSTokenTypes.AT) != null + || (realQualifier != null && realQualifier.getNode().findChildByType(JSTokenTypes.AT) != null); + } + + @Nullable + @RequiredReadAction + public JSExpression getResolveQualifier() { + JSExpression qualifier = getQualifier(); + + if (qualifier instanceof JSReferenceExpression) { + ASTNode astNode = getNode(); + ASTNode selection = astNode.getTreeNext(); + // TODO:this is not accurate + if (selection != null && selection.getElementType() == JSTokenTypes.COLON_COLON) { + return null; + } + + ASTNode nsSelection = astNode.findChildByType(JSTokenTypes.COLON_COLON); + if (nsSelection != null) { + return ((JSReferenceExpressionImpl)qualifier).getResolveQualifier(); + } + } + else if (qualifier == null) { + ASTNode node = getNode().getFirstChildNode(); + + if (node.getElementType() == JSTokenTypes.AT) { + PsiElement parent = getParent(); + if (parent instanceof JSBinaryExpression binary && binary.getParent().getParent() instanceof JSCallExpression call) { + parent = call.getMethodExpression(); + } + return parent instanceof JSExpression expression ? expression : null; + } + } + return qualifier; + } + + @RequiredReadAction + private ResolveResult[] doOldResolve( + PsiFile containingFile, + String referencedName, + PsiElement parent, + JSExpression qualifier, + boolean ecma, + boolean localResolve, + boolean parentIsDefinition, + ResolveProcessor localProcessor + ) { + if (parentIsDefinition && ((ecma && !localResolve) || (!ecma && qualifier != null))) { + return new ResolveResult[]{new JSResolveUtil.MyResolveResult(parent)}; + } + + if (localResolve && parentIsDefinition && ecma) { + if (!localProcessor.processingEncounteredAbsenceOfTypes()) { + return localProcessor.getResultsAsResolveResults(); + } + + // Fallback for finding some assignment in global scope + } + + WalkUpResolveProcessor processor = + new WalkUpResolveProcessor(referencedName, null, containingFile, false, this); + + if (localProcessor != null) { + processor.addLocalResults(localProcessor.getResultsAsResolveResults()); + } + + JSResolveUtil.processGlobalSymbols(this, processor); + return processor.getResults(); + } + + @Override + public boolean shouldCheckReferences() { + return true; + } + + private static class MyTypeProcessor extends ResolveProcessor implements BaseJSSymbolProcessor.TypeProcessor { + private final Set myFeatures; + + public MyTypeProcessor(String referenceName, Set features, PsiElement _place) { + super(referenceName, _place); + myFeatures = features; + setToProcessHierarchy(true); + + configureClassScope(findEnclosingClass(_place)); + } + + enum TypeResolveState { + Unknown, + Resolved, + Undefined, + PrefixUnknown + } + + TypeResolveState resolved = TypeResolveState.Unknown; + + @Override + public Set getFeatures() { + return myFeatures; + } + + @Override + @RequiredReadAction + public void process(@Nonnull String type, @Nonnull BaseJSSymbolProcessor.EvaluateContext evaluateContext, PsiElement source) { + if (evaluateContext.visitedTypes.contains(type)) { + return; + } + evaluateContext.visitedTypes.add(type); + + if ("*".equals(type) || "Object".equals(type)) { + return; + } + + if (JSTypeEvaluateManager.isArrayType(type)) { + int index = type.indexOf('['); + if (index != -1) { + type = type.substring(0, index); + } + } + + PsiElement typeSource = evaluateContext.getSource(); + + setProcessStatics(false); + + PsiElement placeParent = place.getParent(); + boolean setTypeContext = placeParent instanceof JSReferenceList; + PsiElement clazz = source != null && (source instanceof JSClass || source instanceof XmlFile) + ? source + : JSClassImpl.findClassFromNamespace(type, place); + + if (clazz instanceof JSClass jsClass) { + boolean statics = ecma() && JSPsiImplUtils.isTheSameClass(typeSource, jsClass) + && !(((JSReferenceExpression)place).getQualifier() instanceof JSCallExpression); + setProcessStatics(statics); + if (statics) { + setTypeName(jsClass.getQualifiedName()); + } + + boolean saveSetTypeContext = isTypeContext(); + boolean saveToProcessMembers = isToProcessMembers(); + + if (setTypeContext) { + setTypeContext(setTypeContext); + setToProcessMembers(false); + } + + try { + boolean b = clazz.processDeclarations(this, ResolveState.initial(), clazz, place); + if (!b) { + resolved = TypeResolveState.Resolved; + } + else if (ecma()) { + JSAttributeList attrList = jsClass.getAttributeList(); + if (attrList == null || !attrList.hasModifier(JSAttributeList.ModifierType.DYNAMIC)) { + resolved = TypeResolveState.Resolved; + } + } + } + finally { + if (setTypeContext) { + setTypeContext(saveSetTypeContext); + setToProcessMembers(saveToProcessMembers); + } + } + } + else if (ecma()) { + resolved = TypeResolveState.Undefined; + } + } + + @Override + @RequiredReadAction + public boolean execute(@Nonnull PsiElement element, ResolveState state) { + boolean b = super.execute(element, state); + if (ecma() && getResult() != null) { + resolved = MyTypeProcessor.TypeResolveState.Resolved; + } + return b; + } + + @Override + public boolean ecma() { + return myFeatures.contains(JavaScriptFeature.CLASS); + } + + @Override + public void setUnknownElement(@Nonnull PsiElement element) { + if (!(element instanceof XmlToken)) { + boolean currentIsNotResolved = + element == BaseJSSymbolProcessor.getOriginalQualifier(((JSReferenceExpression)place).getQualifier()); + resolved = currentIsNotResolved ? TypeResolveState.PrefixUnknown : TypeResolveState.Unknown; + } + } + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSReferenceListImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSReferenceListImpl.java index eda7fbb4..75a99596 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSReferenceListImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSReferenceListImpl.java @@ -19,128 +19,113 @@ import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.resolve.JSImportHandlingUtil; import com.intellij.lang.javascript.psi.stubs.JSReferenceListStub; -import consulo.language.psi.PsiElement; -import consulo.language.psi.stub.IStubElementType; -import consulo.language.psi.stub.StubIndex; -import consulo.util.collection.ArrayUtil; import consulo.annotation.access.RequiredReadAction; import consulo.javascript.language.psi.stub.JavaScriptIndexKeys; import consulo.language.ast.ASTNode; +import consulo.language.psi.PsiElement; +import consulo.language.psi.stub.IStubElementType; +import consulo.language.psi.stub.StubIndex; import consulo.project.Project; -import org.jetbrains.annotations.NonNls; +import consulo.util.collection.ArrayUtil; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.Collection; /** * @author Maxim.Mossienko */ -public class JSReferenceListImpl extends JSStubElementImpl implements JSReferenceList -{ - public JSReferenceListImpl(final ASTNode node) - { - super(node); - } - - public JSReferenceListImpl(final JSReferenceListStub stub, IStubElementType stubElementType) - { - super(stub, stubElementType); - } - - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSReferenceList(this); - } - - @RequiredReadAction - @Nonnull - @Override - public JSReferenceExpression[] getExpressions() - { - return findChildrenByClass(JSReferenceExpression.class); - } - - @Nonnull - @Override - @RequiredReadAction - public String[] getReferenceTexts() - { - final JSReferenceListStub stub = getStub(); - if(stub != null) - { - return stub.getReferenceTexts(); - } - - final JSReferenceExpression[] referenceExpressions = getExpressions(); - if(referenceExpressions.length == 0) - { - return ArrayUtil.EMPTY_STRING_ARRAY; - } - int count = referenceExpressions.length; - final String[] result = ArrayUtil.newStringArray(count); - - for(int i = 0; i < count; ++i) - { - result[i] = referenceExpressions[i].getText(); - } - return result; - } - - @Nonnull - @RequiredReadAction - @Override - public JSClass[] getReferencedClasses() - { - @NonNls String[] texts = getReferenceTexts(); - - if(texts.length == 0) - { - return JSClass.EMPTY_ARRAY; - } - - final Project project = getProject(); - final ArrayList supers = new ArrayList(1); - - for(String text : texts) - { - final int index = supers.size(); - - text = JSImportHandlingUtil.resolveTypeName(text, this); - - final Collection candidates = StubIndex.getElements(JavaScriptIndexKeys.ELEMENTS_BY_QNAME, text, project, getResolveScope(), JSQualifiedNamedElement.class); - for(JSQualifiedNamedElement _clazz : candidates) - { - if(!(_clazz instanceof JSClass)) - { - continue; - } - final JSClass clazz = (JSClass) _clazz; - - if(text.equals(clazz.getQualifiedName())) - { - if(clazz.canNavigate()) - { - supers.add(index, clazz); - } - else - { - supers.add(clazz); - } - } - } - - if(candidates.size() == 0) - { - final PsiElement element = JSClassImpl.findClassFromNamespace(text, this); - if(element instanceof JSClass) - { - supers.add((JSClass) element); - } - } - } - - return supers.toArray(new JSClass[supers.size()]); - } +public class JSReferenceListImpl extends JSStubElementImpl implements JSReferenceList { + public JSReferenceListImpl(ASTNode node) { + super(node); + } + + public JSReferenceListImpl(JSReferenceListStub stub, IStubElementType stubElementType) { + super(stub, stubElementType); + } + + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSReferenceList(this); + } + + @RequiredReadAction + @Nonnull + @Override + public JSReferenceExpression[] getExpressions() { + return findChildrenByClass(JSReferenceExpression.class); + } + + @Nonnull + @Override + @RequiredReadAction + public String[] getReferenceTexts() { + JSReferenceListStub stub = getStub(); + if (stub != null) { + return stub.getReferenceTexts(); + } + + JSReferenceExpression[] referenceExpressions = getExpressions(); + if (referenceExpressions.length == 0) { + return ArrayUtil.EMPTY_STRING_ARRAY; + } + int count = referenceExpressions.length; + String[] result = ArrayUtil.newStringArray(count); + + for (int i = 0; i < count; ++i) { + result[i] = referenceExpressions[i].getText(); + } + return result; + } + + @Nonnull + @Override + @RequiredReadAction + public JSClass[] getReferencedClasses() { + String[] texts = getReferenceTexts(); + + if (texts.length == 0) { + return JSClass.EMPTY_ARRAY; + } + + Project project = getProject(); + ArrayList supers = new ArrayList<>(1); + + for (String text : texts) { + int index = supers.size(); + + text = JSImportHandlingUtil.resolveTypeName(text, this); + + Collection candidates = StubIndex.getElements(JavaScriptIndexKeys.ELEMENTS_BY_QNAME, + text, + project, + getResolveScope(), + JSQualifiedNamedElement.class + ); + for (JSQualifiedNamedElement _clazz : candidates) { + if (!(_clazz instanceof JSClass)) { + continue; + } + JSClass clazz = (JSClass)_clazz; + + if (text.equals(clazz.getQualifiedName())) { + if (clazz.canNavigate()) { + supers.add(index, clazz); + } + else { + supers.add(clazz); + } + } + } + + if (candidates.size() == 0) { + PsiElement element = JSClassImpl.findClassFromNamespace(text, this); + if (element instanceof JSClass jsClass) { + supers.add(jsClass); + } + } + } + + return supers.toArray(new JSClass[supers.size()]); + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSReferenceSet.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSReferenceSet.java index 96541daa..79e6f10d 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSReferenceSet.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSReferenceSet.java @@ -16,599 +16,532 @@ package com.intellij.lang.javascript.psi.impl; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.JavaScriptSupportLoader; import com.intellij.lang.javascript.flex.XmlBackedJSClassImpl; import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.resolve.*; import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.document.util.TextRange; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.ast.ASTNode; import consulo.language.psi.*; import consulo.language.psi.resolve.ResolveCache; import consulo.language.psi.resolve.ResolveState; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; import consulo.project.Project; import consulo.util.collection.ArrayUtil; import consulo.util.lang.StringUtil; import consulo.xml.psi.xml.*; -import org.jetbrains.annotations.NonNls; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; /** * @author Maxim.Mossienko */ -public class JSReferenceSet -{ - private static final String GLOBAL_PREFIX = "global#"; - - private String myReferenceText; - private PsiReference[] myReferences; - private final PsiElement element; - private final boolean isSoft; - private final boolean onlyPackages; - private final boolean onlyFqns; - private boolean myOnlyDefaultPackage; - - public JSReferenceSet(final PsiElement element, String text, int offset, boolean soft) - { - this(element, text, offset, soft, false, false); - } - - public JSReferenceSet(final PsiElement element, String text, int offset, boolean soft, boolean _onlyPackages, boolean _onlyFqns) - { - this.element = element; - isSoft = soft; - myReferenceText = text; - myReferences = reparse(text, offset); - onlyPackages = _onlyPackages; - onlyFqns = _onlyFqns; - } - - public JSReferenceSet(final PsiElement element, boolean soft) - { - this.element = element; - isSoft = soft; - onlyPackages = false; - onlyFqns = false; - } - - public JSReferenceSet(final PsiElement element) - { - this(element, true); - } - - public PsiReference[] getReferences() - { - return myReferences; - } - - public void update(String text, int offset) - { - if(myReferences != null && - myReferenceText != null && - myReferenceText.equals(text)) - { - return; - } - - if(!StringUtil.startsWithChar(text, '"') && !StringUtil.startsWithChar(text, '\'')) - { - myReferenceText = text; - myReferences = PsiReference.EMPTY_ARRAY; - } - else - { - final PsiReference[] list = reparse(StringUtil.stripQuotesAroundValue(text), offset + 1); - myReferenceText = text; - myReferences = list; - } - } - - private PsiReference[] reparse(String value, int offset) - { - if(value.startsWith(GLOBAL_PREFIX)) - { - value = value.substring(GLOBAL_PREFIX.length()); - offset += GLOBAL_PREFIX.length(); - myOnlyDefaultPackage = true; - } - List refs = new ArrayList(1); - int lastPos = 0; - int dotPos = findSeparatorPosition(value, lastPos); - - while(dotPos != -1) - { - final String s = value.substring(lastPos, dotPos).trim(); - - if(s.length() > 0) - { - refs.add(new MyPsiReference(s, offset + lastPos, false)); - } - - lastPos = dotPos + 1; - dotPos = findSeparatorPosition(value, lastPos); - } - - int end = value.length(); - - final int lpar = value.indexOf('(', lastPos); - if(lpar != -1) - { - end = lpar; - } - - final String s = value.substring(lastPos, end).trim(); - - if(s.length() > 0) - { - refs.add(new MyPsiReference(s, offset + lastPos, lastPos > 0 && value.charAt(lastPos - 1) == '#')); - } - - return refs.toArray(new PsiReference[refs.size()]); - } - - private static int findSeparatorPosition(final String s, int fromIndex) - { - int pos = s.indexOf('.', fromIndex); - // no more than one ':' and '#' symbol after last '.' - if(pos == -1 && s.indexOf(":") >= fromIndex) - { - pos = s.indexOf(":", fromIndex); - } - if(pos == -1 && s.indexOf("#") >= fromIndex) - { - pos = s.indexOf("#", fromIndex); - } - return pos; - } - - public boolean isSoft() - { - return isSoft; - } - - private class MyPsiReference implements PsiPolyVariantReference, EmptyResolveMessageProvider - { - private - @NonNls - String myText; - private int myOffset; - private boolean myMethodRef; - - MyPsiReference(final String s, final int i, boolean methodRef) - { - myText = s; - myOffset = i; - myMethodRef = methodRef; - } - - @Override - public PsiElement getElement() - { - return element; - } - - @Override - public TextRange getRangeInElement() - { - return new TextRange(myOffset, myOffset + myText.length()); - } - - @Override - @Nullable - public PsiElement resolve() - { - final ResolveResult[] resolveResults = multiResolve(false); - return resolveResults.length == 1 ? resolveResults[0].getElement() : null; - } - - @Override - public String getCanonicalText() - { - return myText; - } - - @Override - public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException - { - int i = newElementName.lastIndexOf('.'); - if(i != -1) - { - newElementName = newElementName.substring(0, i); - } - return handleContentChange(getElement(), getRangeInElement(), newElementName); - } - - @Override - public PsiElement bindToElement(@Nonnull PsiElement element) throws IncorrectOperationException - { - String qName = JSPsiImplUtils.getQNameForMove(getElement(), element); - if(qName != null) - { - handleContentChange(getElement(), new TextRange(myReferences[0].getRangeInElement().getStartOffset(), getRangeInElement().getEndOffset()), - qName); - } - return null; - } - - @Override - public boolean isReferenceTo(PsiElement element) - { - if(element instanceof PsiNamedElement || element instanceof XmlAttributeValue) - { - return JSResolveUtil.isReferenceTo(this, myText, element); - } - return false; - } - - @Override - public Object[] getVariants() - { - final PsiFile containingFile = element.getContainingFile(); - ResolveProcessor processor = null; - - if(isNewResolveAndCompletion(containingFile)) - { - processor = doProcess(element.getContainingFile(), null); - if(!(element instanceof JSLiteralExpression)) - { - return processor.getResultsAsObjects(); - } - } - return getOldVariants(containingFile, processor); - } - - private Object[] getOldVariants(PsiFile containingFile, ResolveProcessor localProcessor) - { - final List contextIds = fillContextIds(); - final VariantsProcessor processor = new VariantsProcessor(contextIds != null ? ArrayUtil.toStringArray(contextIds) : null, containingFile, false, element); - - processor.setAddOnlyCompleteMatches(contextIds != null || !(element instanceof JSLiteralExpression)); - if(localProcessor != null) - { - processor.addLocalResults(localProcessor.getResults()); // TODO: remove this stuff as we create new js index - } - //JSResolveUtil.processGlobalSymbols(containingFile, processor); - - final PsiElement context = containingFile.getContext(); - if(context != null) - { - JSResolveUtil.treeWalkUp(processor, containingFile, containingFile, element); - } - - return processor.getResult(); - } - - @Nullable - private List fillContextIds() - { - List contextIds = null; - PsiReference prevContextReference = null; - for(final PsiReference ref : myReferences) - { - if(ref == this) - { - break; - } - if(contextIds == null) - { - contextIds = new ArrayList(3); - } - contextIds.add(ref.getCanonicalText()); - prevContextReference = ref; - } - - if(contextIds == null && myOffset > 0) - { - PsiElement elt = findNearestClass(); - - if(elt instanceof JSClass && !(getElement() instanceof JSLiteralExpression)) - { - final String qName = ((JSClass) elt).getQualifiedName(); - BaseJSSymbolProcessor.addIndexListFromQName(qName, elt, contextIds = new ArrayList()); - } - } - else if(contextIds != null) - { - PsiElement psiElement = JSResolveUtil.unwrapProxy(prevContextReference.resolve()); - - if(psiElement instanceof XmlToken) - { - final BaseJSSymbolProcessor.TagContextBuilder builder = new BaseJSSymbolProcessor.TagContextBuilder(psiElement, - BaseJSSymbolProcessor.HTML_ELEMENT_TYPE_NAME); - psiElement = builder.element; - } - if(psiElement instanceof JSClass) - { - final String qName = ((JSClass) psiElement).getQualifiedName(); - BaseJSSymbolProcessor.addIndexListFromQName(qName, psiElement, contextIds = new ArrayList()); - } - } - - return contextIds; - } - - @Override - public boolean isSoft() - { - return JSReferenceSet.this.isSoft(); - } - - @Override - @Nonnull - @RequiredReadAction - public ResolveResult[] multiResolve(final boolean incompleteCode) - { - PsiFile containingFile = element.getContainingFile(); - if(containingFile == null) - { - return ResolveResult.EMPTY_ARRAY; - } - return ResolveCache.getInstance(containingFile.getProject()).resolveWithCaching(this, MyResolver.INSTANCE, true, incompleteCode, containingFile); - } - - private ResolveResult[] doResolve(PsiFile psiFile) - { - if("int".equals(myText) || - "uint".equals(myText) || - (onlyPackages && "*".equals(myText))) - { - return new ResolveResult[]{new JSResolveUtil.MyResolveResult(element)}; - } - - if(isNewResolveAndCompletion(psiFile)) - { - ResolveProcessor processor = doProcess(psiFile, myText); - - return processor.getResultsAsResolveResults(); - } - - return doOldResolve(psiFile); - } - - private boolean isNewResolveAndCompletion(PsiFile psiFile) - { - return JSResolveUtil.isNewResolveAndCompletion(psiFile) || onlyFqns; - } - - private ResolveProcessor doProcess(PsiFile psiFile, String text) - { - ResolveProcessor processor = new ResolveProcessor(text) - { - @Override - public boolean execute(PsiElement element, ResolveState state) - { - if(onlyPackages) - { - return false; - } - if(onlyFqns) - { - return true; - } - if(myOnlyDefaultPackage && element instanceof JSQualifiedNamedElement) - { - String qName = ((JSQualifiedNamedElement) element).getQualifiedName(); - if(qName != null && !StringUtil.isEmpty(StringUtil.getPackageName(qName))) - { - return true; - } - } - return super.execute(element, state); - } - }; - - int i; - for(i = 0; i < myReferences.length && myReferences[i] != this; ++i) - { - ; - } - - if(i == 0) - { - PsiElement elt = findNearestClass(); - - if(myOffset > 0) - { - if(elt instanceof JSClass && !(element instanceof JSLiteralExpression)) - { - processor.setToProcessHierarchy(true); - processor.setTypeContext(true); - if(!elt.processDeclarations(processor, ResolveState.initial(), elt, elt)) - { - return processor; - } - } - } - else if(elt instanceof JSClass) - { - processor.setTypeContext(true); - processor.setToProcessMembers(false); - if(!elt.processDeclarations(processor, ResolveState.initial(), elt, elt)) - { - return processor; - } - } - JSResolveUtil.treeWalkUp(processor, element, element.getParent(), element); - } - else - { - PsiElement psiElement = JSResolveUtil.unwrapProxy(myReferences[i - 1].resolve()); - - if(psiElement instanceof XmlToken) - { - final BaseJSSymbolProcessor.TagContextBuilder builder = new BaseJSSymbolProcessor.TagContextBuilder(psiElement, - BaseJSSymbolProcessor.HTML_ELEMENT_TYPE_NAME); - psiElement = builder.element; - } - if(psiElement != null) - { - if(psiElement instanceof JSClass) - { - processor.setToProcessHierarchy(true); - } - psiElement.processDeclarations(processor, ResolveState.initial(), psiElement, psiElement); - } - } - - if(psiFile instanceof XmlFile && !JavaScriptSupportLoader.isFlexMxmFile(psiFile)) - { - // TODO: short names during completion should be - JSResolveUtil.processTopLevelClasses(processor, ResolveState.initial(), psiFile.getProject(), psiFile.getResolveScope(), onlyFqns, - false); - } - return processor; - } - - private PsiElement findNearestClass() - { - PsiElement elt = element; - PsiElement parent; - while(!((parent = elt.getParent()) instanceof JSFile) && !(parent instanceof JSPackageStatement)) - { - if(parent instanceof XmlTagChild) - { - break; - } - elt = parent; - if(elt == null || elt instanceof JSClass) - { - break; - } - } - - if(parent instanceof XmlTag && XmlBackedJSClassImpl.isInlineComponentTag((XmlTag) parent)) - { - elt = XmlBackedJSClassImpl.getXmlBackedClass((XmlTag) parent); - } - - if(elt != null && !(elt instanceof JSClass)) - { - elt = elt.getNextSibling(); - if(elt instanceof PsiWhiteSpace) - { - elt = elt.getNextSibling(); - } - } - return elt; - } - - private ResolveResult[] doOldResolve(PsiFile psiFile) - { - if("*".equals(myText)) - { - return new ResolveResult[]{new JSResolveUtil.MyResolveResult(element)}; - } - final List contextIds = fillContextIds(); - - String text = myText; - - if(getElement() instanceof JSDocTagValue) - { - if(myReferences.length == 1 && - myReferences[myReferences.length - 1] == this && - !myMethodRef) - { - text = StringUtil.capitalize(text); - } - } - - final WalkUpResolveProcessor processor = new WalkUpResolveProcessor(text, contextIds != null ? ArrayUtil.toStringArray(contextIds) : - null, psiFile, false, element); - - processor.setAddOnlyCompleteMatches(contextIds != null || !(element instanceof JSLiteralExpression)); - //JSResolveUtil.processGlobalSymbols(psiFile, processor); - final StringBuilder b = new StringBuilder(); - - for(final PsiReference ref : myReferences) - { - if(b.length() > 0) - { - b.append('.'); - } - b.append(ref.getCanonicalText()); - if(ref == this) - { - break; - } - } - final String str = b.toString(); - - final PsiElement context = psiFile.getContext(); - if(context != null && str.indexOf('.') == -1) - { - JSResolveUtil.treeWalkUp(processor, psiFile, psiFile, element); - } - - return processor.getResults(); - } - - @Override - public String getUnresolvedMessagePattern() - { - String text = getCanonicalText(); - text = "'" + text.replace("'", "''") + "'"; - return JavaScriptBundle.message("javascript.unresolved.variable.or.type.name.message2", text); - } - } - - static class MyResolver implements ResolveCache.PolyVariantContextResolver - { - private static final MyResolver INSTANCE = new MyResolver(); - - @Nonnull - @Override - public ResolveResult[] resolve(@Nonnull MyPsiReference ref, @Nonnull PsiFile containingFile, boolean incompleteCode) - { - return ref.doResolve(containingFile); - } - } - - private static PsiElement handleContentChange(PsiElement elt, TextRange range, String newElementName) - { - if(elt instanceof XmlTag || elt instanceof XmlAttributeValue) - { - int i = newElementName.indexOf('.'); - if(i != -1) - { - newElementName = newElementName.substring(0, i); - } - return ElementManipulators.getManipulator(elt).handleContentChange(elt, range, newElementName); - } - - String myReferenceText = elt.getText(); - String newLiteralText = myReferenceText.substring(0, range.getStartOffset()) + newElementName + myReferenceText.substring(range.getEndOffset()); - final ASTNode expressionFromText; - - Project project = elt.getProject(); - if(elt instanceof JSExpression) - { - expressionFromText = JSChangeUtil.createExpressionFromText(project, newLiteralText).getNode(); - } - else if(elt instanceof JSAttributeNameValuePair) - { - final PsiElement element = JSChangeUtil.createJSTreeFromText(project, "[XXX(" + newLiteralText + ")]").getPsi(); - expressionFromText = ((JSAttribute) element.getFirstChild()).getValues()[0].getNode(); - } - else - { - assert elt instanceof JSDocTagValue; - final PsiElement tag = JSChangeUtil.createJSTreeFromText(project, "/** @see " + newLiteralText + " */").getPsi(); - expressionFromText = ((JSDocTag) tag.getFirstChild().getChildren()[0]).getValue().getNode(); - } - - if(expressionFromText.getPsi().getClass() == elt.getClass()) - { - final ASTNode astNode = elt.getNode(); - astNode.replaceChild(astNode.getFirstChildNode(), expressionFromText.getFirstChildNode()); - } - - return null; - } - +public class JSReferenceSet { + private static final String GLOBAL_PREFIX = "global#"; + + private String myReferenceText; + private PsiReference[] myReferences; + private final PsiElement element; + private final boolean isSoft; + private final boolean onlyPackages; + private final boolean onlyFqns; + private boolean myOnlyDefaultPackage; + + public JSReferenceSet(PsiElement element, String text, int offset, boolean soft) { + this(element, text, offset, soft, false, false); + } + + public JSReferenceSet(PsiElement element, String text, int offset, boolean soft, boolean _onlyPackages, boolean _onlyFqns) { + this.element = element; + isSoft = soft; + myReferenceText = text; + myReferences = reparse(text, offset); + onlyPackages = _onlyPackages; + onlyFqns = _onlyFqns; + } + + public JSReferenceSet(PsiElement element, boolean soft) { + this.element = element; + isSoft = soft; + onlyPackages = false; + onlyFqns = false; + } + + public JSReferenceSet(PsiElement element) { + this(element, true); + } + + public PsiReference[] getReferences() { + return myReferences; + } + + public void update(String text, int offset) { + if (myReferences != null && + myReferenceText != null && + myReferenceText.equals(text)) { + return; + } + + if (!StringUtil.startsWithChar(text, '"') && !StringUtil.startsWithChar(text, '\'')) { + myReferenceText = text; + myReferences = PsiReference.EMPTY_ARRAY; + } + else { + PsiReference[] list = reparse(StringUtil.stripQuotesAroundValue(text), offset + 1); + myReferenceText = text; + myReferences = list; + } + } + + private PsiReference[] reparse(String value, int offset) { + if (value.startsWith(GLOBAL_PREFIX)) { + value = value.substring(GLOBAL_PREFIX.length()); + offset += GLOBAL_PREFIX.length(); + myOnlyDefaultPackage = true; + } + List refs = new ArrayList<>(1); + int lastPos = 0; + int dotPos = findSeparatorPosition(value, lastPos); + + while (dotPos != -1) { + String s = value.substring(lastPos, dotPos).trim(); + + if (s.length() > 0) { + refs.add(new MyPsiReference(s, offset + lastPos, false)); + } + + lastPos = dotPos + 1; + dotPos = findSeparatorPosition(value, lastPos); + } + + int end = value.length(); + + int lpar = value.indexOf('(', lastPos); + if (lpar != -1) { + end = lpar; + } + + String s = value.substring(lastPos, end).trim(); + + if (s.length() > 0) { + refs.add(new MyPsiReference(s, offset + lastPos, lastPos > 0 && value.charAt(lastPos - 1) == '#')); + } + + return refs.toArray(new PsiReference[refs.size()]); + } + + private static int findSeparatorPosition(String s, int fromIndex) { + int pos = s.indexOf('.', fromIndex); + // no more than one ':' and '#' symbol after last '.' + if (pos == -1 && s.indexOf(":") >= fromIndex) { + pos = s.indexOf(":", fromIndex); + } + if (pos == -1 && s.indexOf("#") >= fromIndex) { + pos = s.indexOf("#", fromIndex); + } + return pos; + } + + public boolean isSoft() { + return isSoft; + } + + private class MyPsiReference implements PsiPolyVariantReference, EmptyResolveMessageProvider { + private String myText; + private int myOffset; + private boolean myMethodRef; + + MyPsiReference(String s, int i, boolean methodRef) { + myText = s; + myOffset = i; + myMethodRef = methodRef; + } + + @Override + @RequiredReadAction + public PsiElement getElement() { + return element; + } + + @Nonnull + @Override + @RequiredReadAction + public TextRange getRangeInElement() { + return new TextRange(myOffset, myOffset + myText.length()); + } + + @Nullable + @Override + @RequiredReadAction + public PsiElement resolve() { + ResolveResult[] resolveResults = multiResolve(false); + return resolveResults.length == 1 ? resolveResults[0].getElement() : null; + } + + @Nonnull + @Override + @RequiredReadAction + public String getCanonicalText() { + return myText; + } + + @Override + @RequiredWriteAction + public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException { + int i = newElementName.lastIndexOf('.'); + if (i != -1) { + newElementName = newElementName.substring(0, i); + } + return handleContentChange(getElement(), getRangeInElement(), newElementName); + } + + @Override + @RequiredWriteAction + public PsiElement bindToElement(@Nonnull PsiElement element) throws IncorrectOperationException { + String qName = JSPsiImplUtils.getQNameForMove(getElement(), element); + if (qName != null) { + handleContentChange( + getElement(), + new TextRange(myReferences[0].getRangeInElement().getStartOffset(), getRangeInElement().getEndOffset()), + qName + ); + } + return null; + } + + @Override + @RequiredReadAction + public boolean isReferenceTo(PsiElement element) { + return (element instanceof PsiNamedElement || element instanceof XmlAttributeValue) + && JSResolveUtil.isReferenceTo(this, myText, element); + } + + @Nonnull + @Override + @RequiredReadAction + public Object[] getVariants() { + PsiFile containingFile = element.getContainingFile(); + ResolveProcessor processor = null; + + if (isNewResolveAndCompletion(containingFile)) { + processor = doProcess(element.getContainingFile(), null); + if (!(element instanceof JSLiteralExpression)) { + return processor.getResultsAsObjects(); + } + } + return getOldVariants(containingFile, processor); + } + + @RequiredReadAction + private Object[] getOldVariants(PsiFile containingFile, ResolveProcessor localProcessor) { + List contextIds = fillContextIds(); + VariantsProcessor processor = + new VariantsProcessor(contextIds != null ? ArrayUtil.toStringArray(contextIds) : null, containingFile, false, element); + + processor.setAddOnlyCompleteMatches(contextIds != null || !(element instanceof JSLiteralExpression)); + if (localProcessor != null) { + processor.addLocalResults(localProcessor.getResults()); // TODO: remove this stuff as we create new js index + } + //JSResolveUtil.processGlobalSymbols(containingFile, processor); + + PsiElement context = containingFile.getContext(); + if (context != null) { + JSResolveUtil.treeWalkUp(processor, containingFile, containingFile, element); + } + + return processor.getResult(); + } + + @Nullable + @RequiredReadAction + private List fillContextIds() { + List contextIds = null; + PsiReference prevContextReference = null; + for (PsiReference ref : myReferences) { + if (ref == this) { + break; + } + if (contextIds == null) { + contextIds = new ArrayList<>(3); + } + contextIds.add(ref.getCanonicalText()); + prevContextReference = ref; + } + + if (contextIds == null && myOffset > 0) { + PsiElement elt = findNearestClass(); + + if (elt instanceof JSClass jsClass && !(getElement() instanceof JSLiteralExpression)) { + String qName = jsClass.getQualifiedName(); + BaseJSSymbolProcessor.addIndexListFromQName(qName, elt, contextIds = new ArrayList<>()); + } + } + else if (contextIds != null) { + PsiElement psiElement = JSResolveUtil.unwrapProxy(prevContextReference.resolve()); + + if (psiElement instanceof XmlToken xmlToken) { + BaseJSSymbolProcessor.TagContextBuilder builder = + new BaseJSSymbolProcessor.TagContextBuilder(xmlToken, BaseJSSymbolProcessor.HTML_ELEMENT_TYPE_NAME); + psiElement = builder.element; + } + if (psiElement instanceof JSClass jsClass) { + String qName = jsClass.getQualifiedName(); + BaseJSSymbolProcessor.addIndexListFromQName(qName, jsClass, contextIds = new ArrayList<>()); + } + } + + return contextIds; + } + + @Override + @RequiredReadAction + public boolean isSoft() { + return JSReferenceSet.this.isSoft(); + } + + @Override + @Nonnull + @RequiredReadAction + public ResolveResult[] multiResolve(boolean incompleteCode) { + PsiFile containingFile = element.getContainingFile(); + if (containingFile == null) { + return ResolveResult.EMPTY_ARRAY; + } + return ResolveCache.getInstance(containingFile.getProject()) + .resolveWithCaching(this, MyResolver.INSTANCE, true, incompleteCode, containingFile); + } + + @RequiredReadAction + private ResolveResult[] doResolve(PsiFile psiFile) { + if ("int".equals(myText) || + "uint".equals(myText) || + (onlyPackages && "*".equals(myText))) { + return new ResolveResult[]{new JSResolveUtil.MyResolveResult(element)}; + } + + if (isNewResolveAndCompletion(psiFile)) { + ResolveProcessor processor = doProcess(psiFile, myText); + + return processor.getResultsAsResolveResults(); + } + + return doOldResolve(psiFile); + } + + private boolean isNewResolveAndCompletion(PsiFile psiFile) { + return JSResolveUtil.isNewResolveAndCompletion(psiFile) || onlyFqns; + } + + @RequiredReadAction + private ResolveProcessor doProcess(PsiFile psiFile, String text) { + ResolveProcessor processor = new ResolveProcessor(text) { + @Override + @RequiredReadAction + public boolean execute(PsiElement element, ResolveState state) { + if (onlyPackages) { + return false; + } + if (onlyFqns) { + return true; + } + if (myOnlyDefaultPackage && element instanceof JSQualifiedNamedElement qualifiedNamedElement) { + String qName = qualifiedNamedElement.getQualifiedName(); + if (qName != null && !StringUtil.isEmpty(StringUtil.getPackageName(qName))) { + return true; + } + } + return super.execute(element, state); + } + }; + + int i; + for (i = 0; i < myReferences.length && myReferences[i] != this; ++i) { + ; + } + + if (i == 0) { + PsiElement elt = findNearestClass(); + + if (myOffset > 0) { + if (elt instanceof JSClass jsClass && !(element instanceof JSLiteralExpression)) { + processor.setToProcessHierarchy(true); + processor.setTypeContext(true); + if (!jsClass.processDeclarations(processor, ResolveState.initial(), jsClass, jsClass)) { + return processor; + } + } + } + else if (elt instanceof JSClass jsClass) { + processor.setTypeContext(true); + processor.setToProcessMembers(false); + if (!jsClass.processDeclarations(processor, ResolveState.initial(), jsClass, jsClass)) { + return processor; + } + } + JSResolveUtil.treeWalkUp(processor, element, element.getParent(), element); + } + else { + PsiElement psiElement = JSResolveUtil.unwrapProxy(myReferences[i - 1].resolve()); + + if (psiElement instanceof XmlToken xmlToken) { + BaseJSSymbolProcessor.TagContextBuilder builder = + new BaseJSSymbolProcessor.TagContextBuilder(xmlToken, BaseJSSymbolProcessor.HTML_ELEMENT_TYPE_NAME); + psiElement = builder.element; + } + if (psiElement != null) { + if (psiElement instanceof JSClass) { + processor.setToProcessHierarchy(true); + } + psiElement.processDeclarations(processor, ResolveState.initial(), psiElement, psiElement); + } + } + + if (psiFile instanceof XmlFile xmlFile && !JavaScriptSupportLoader.isFlexMxmFile(xmlFile)) { + // TODO: short names during completion should be + JSResolveUtil.processTopLevelClasses( + processor, + ResolveState.initial(), + xmlFile.getProject(), + xmlFile.getResolveScope(), + onlyFqns, + false + ); + } + return processor; + } + + @RequiredReadAction + private PsiElement findNearestClass() { + PsiElement elt = element; + PsiElement parent; + while (!((parent = elt.getParent()) instanceof JSFile) && !(parent instanceof JSPackageStatement)) { + if (parent instanceof XmlTagChild) { + break; + } + elt = parent; + if (elt == null || elt instanceof JSClass) { + break; + } + } + + if (parent instanceof XmlTag tag && XmlBackedJSClassImpl.isInlineComponentTag(tag)) { + elt = XmlBackedJSClassImpl.getXmlBackedClass(tag); + } + + if (elt != null && !(elt instanceof JSClass)) { + elt = elt.getNextSibling(); + if (elt instanceof PsiWhiteSpace whiteSpace) { + elt = whiteSpace.getNextSibling(); + } + } + return elt; + } + + @RequiredReadAction + private ResolveResult[] doOldResolve(PsiFile psiFile) { + if ("*".equals(myText)) { + return new ResolveResult[]{new JSResolveUtil.MyResolveResult(element)}; + } + List contextIds = fillContextIds(); + + String text = myText; + + if (getElement() instanceof JSDocTagValue + && myReferences.length == 1 && myReferences[myReferences.length - 1] == this && !myMethodRef) { + text = StringUtil.capitalize(text); + } + + WalkUpResolveProcessor processor = new WalkUpResolveProcessor( + text, + contextIds != null ? ArrayUtil.toStringArray(contextIds) : null, + psiFile, + false, + element + ); + + processor.setAddOnlyCompleteMatches(contextIds != null || !(element instanceof JSLiteralExpression)); + //JSResolveUtil.processGlobalSymbols(psiFile, processor); + StringBuilder b = new StringBuilder(); + + for (PsiReference ref : myReferences) { + if (b.length() > 0) { + b.append('.'); + } + b.append(ref.getCanonicalText()); + if (ref == this) { + break; + } + } + String str = b.toString(); + + PsiElement context = psiFile.getContext(); + if (context != null && str.indexOf('.') == -1) { + JSResolveUtil.treeWalkUp(processor, psiFile, psiFile, element); + } + + return processor.getResults(); + } + + @Nonnull + @Override + public LocalizeValue buildUnresolvedMessage(@Nonnull String text) { + text = "'" + text.replace("'", "''") + "'"; + return JavaScriptLocalize.javascriptUnresolvedVariableOrTypeNameMessage2(text); + } + } + + static class MyResolver implements ResolveCache.PolyVariantContextResolver { + private static final MyResolver INSTANCE = new MyResolver(); + + @Nonnull + @Override + @RequiredReadAction + public ResolveResult[] resolve(@Nonnull MyPsiReference ref, @Nonnull PsiFile containingFile, boolean incompleteCode) { + return ref.doResolve(containingFile); + } + } + + @RequiredReadAction + private static PsiElement handleContentChange(PsiElement elt, TextRange range, String newElementName) { + if (elt instanceof XmlTag || elt instanceof XmlAttributeValue) { + int i = newElementName.indexOf('.'); + if (i != -1) { + newElementName = newElementName.substring(0, i); + } + return ElementManipulators.getManipulator(elt).handleContentChange(elt, range, newElementName); + } + + String myReferenceText = elt.getText(); + String newLiteralText = + myReferenceText.substring(0, range.getStartOffset()) + newElementName + myReferenceText.substring(range.getEndOffset()); + ASTNode expressionFromText; + + Project project = elt.getProject(); + if (elt instanceof JSExpression) { + expressionFromText = JSChangeUtil.createExpressionFromText(project, newLiteralText).getNode(); + } + else if (elt instanceof JSAttributeNameValuePair) { + PsiElement element = JSChangeUtil.createJSTreeFromText(project, "[XXX(" + newLiteralText + ")]").getPsi(); + expressionFromText = ((JSAttribute)element.getFirstChild()).getValues()[0].getNode(); + } + else { + assert elt instanceof JSDocTagValue; + PsiElement tag = JSChangeUtil.createJSTreeFromText(project, "/** @see " + newLiteralText + " */").getPsi(); + expressionFromText = ((JSDocTag)tag.getFirstChild().getChildren()[0]).getValue().getNode(); + } + + if (expressionFromText.getPsi().getClass() == elt.getClass()) { + ASTNode astNode = elt.getNode(); + astNode.replaceChild(astNode.getFirstChildNode(), expressionFromText.getFirstChildNode()); + } + + return null; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSReturnStatementImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSReturnStatementImpl.java index fbc084e7..86b170e8 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSReturnStatementImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSReturnStatementImpl.java @@ -20,30 +20,24 @@ import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.JSReturnStatement; import consulo.language.ast.ASTNode; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * User: max - * Date: Jan 30, 2005 - * Time: 9:57:08 PM + * @author max + * @since 2005-01-30 */ -public class JSReturnStatementImpl extends JSStatementImpl implements JSReturnStatement -{ - public JSReturnStatementImpl(final ASTNode node) - { - super(node); - } +public class JSReturnStatementImpl extends JSStatementImpl implements JSReturnStatement { + public JSReturnStatementImpl(ASTNode node) { + super(node); + } - @Override - public JSExpression getExpression() - { - return findChildByClass(JSExpression.class); - } + @Override + public JSExpression getExpression() { + return findChildByClass(JSExpression.class); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSReturnStatement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSReturnStatement(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSSmartCompletionVariantsHandler.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSSmartCompletionVariantsHandler.java index 991084da..6d140991 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSSmartCompletionVariantsHandler.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSSmartCompletionVariantsHandler.java @@ -22,6 +22,7 @@ import com.intellij.lang.javascript.psi.resolve.ResolveProcessor; import com.intellij.lang.javascript.psi.util.JSLookupUtil; import com.intellij.lang.javascript.search.JSClassSearch; +import consulo.annotation.access.RequiredReadAction; import consulo.application.util.query.Query; import consulo.language.psi.PsiElement; import consulo.language.psi.ResolveResult; @@ -30,11 +31,11 @@ import consulo.project.Project; import consulo.util.lang.StringUtil; import consulo.util.lang.ref.Ref; +import consulo.util.lang.ref.SimpleReference; import consulo.xml.psi.xml.XmlFile; import consulo.xml.psi.xml.XmlTag; -import org.jetbrains.annotations.NonNls; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -42,202 +43,173 @@ /** * @author Maxim.Mossienko - * Date: Jan 25, 2008 - * Time: 12:40:48 AM + * @since 2008-01-25 */ -public class JSSmartCompletionVariantsHandler -{ - static Object[] getSmartVariants(final @Nonnull PsiElement expr, final boolean ecma) - { - final PsiElement parent = expr.getParent(); - - if(parent instanceof JSArgumentList && - ((JSArgumentList) parent).getArguments()[0] == expr && - ecma && - ((JSReferenceExpression) expr).getQualifier() == null) - { - final JSExpression calledExpr = ((JSCallExpression) parent.getParent()).getMethodExpression(); - - if(calledExpr instanceof JSReferenceExpression) - { - final JSReferenceExpression expression = (JSReferenceExpression) calledExpr; - final @NonNls String s = expression.getReferencedName(); - - if("addEventListener".equals(s) || "removeEventListener".equals(s)) - { - final List variants = new ArrayList(); - final MyEventSubclassesProcessor subclassesProcessor = new MyEventSubclassesProcessor(expr, variants); - subclassesProcessor.findAcceptableVariants(expression, parent.getProject()); - if(variants.size() > 0) - { - return variants.toArray(new Object[variants.size()]); - } - } - } - } - - return null; - } - - private static class MyEventSubclassesProcessor extends ResolveProcessor implements JSResolveUtil.MetaDataProcessor - { - private final PsiElement myExpr; - private final List myVariants; - private final ResolveState state = new ResolveState(); - private final Map myCandidatesMap = new HashMap(); - private boolean findAcceptableEvents; - - public MyEventSubclassesProcessor(final PsiElement expr, final List variants) - { - super(null); - myExpr = expr; - myVariants = variants; - - setToProcessHierarchy(true); - } - - public boolean process(final JSClass clazz) - { - clazz.processDeclarations(this, state, clazz, clazz); - - return true; - } - - @Override - public boolean execute(final PsiElement element, final ResolveState state) - { - if(element instanceof JSVariable) - { - final JSVariable variable = (JSVariable) element; - final JSAttributeList attributeList = variable.getAttributeList(); - - if(attributeList != null && - attributeList.getAccessType() == JSAttributeList.AccessType.PUBLIC && - attributeList.hasModifier(JSAttributeList.ModifierType.STATIC) && - "String".equals(variable.getTypeString())) - { - final String s = variable.getInitializerText(); - if(s != null && StringUtil.startsWith(s, "\"") && StringUtil.endsWith(s, "\"")) - { - myCandidatesMap.put(StringUtil.stripQuotesAroundValue(s), variable); - } - } - } - - if(findAcceptableEvents && element instanceof JSClass) - { - JSResolveUtil.processMetaAttributesForClass(element, this); - } - - return true; - } - - public void findAcceptableVariants(JSReferenceExpression expression, final Project project) - { - - PsiElement clazz = JSResolveUtil.findClassByQName("flash.events.Event", expression.getResolveScope(), project); - clazz = JSResolveUtil.unwrapProxy(clazz); - if(!(clazz instanceof JSClass)) - { - return; - } - final Query query = JSClassSearch.searchClassInheritors((JSClass) clazz, true); - - for(JSClass extendedClass : query.findAll()) - { - process(extendedClass); - } - - final JSExpression qualifier = expression.getQualifier(); - - JSClass clazzToProcess = null; - - if(qualifier instanceof JSThisExpression || qualifier instanceof JSSuperExpression) - { - clazzToProcess = PsiTreeUtil.getParentOfType(qualifier, JSClass.class); - } - else if(qualifier instanceof JSReferenceExpression) - { - final ResolveResult[] results = ((JSReferenceExpression) qualifier).multiResolve(false); - if(results.length > 0 && results[0].getElement() instanceof JSClass) - { - clazzToProcess = (JSClass) results[0].getElement(); - } - } - - if(clazzToProcess == null) - { - final PsiElement context = expression.getContainingFile().getContext(); - clazzToProcess = JSResolveUtil.getClassFromTagNameInMxml(context); - if(clazzToProcess == null && context != null) - { - XmlFile file = PsiTreeUtil.getParentOfType(context, XmlFile.class); - if(file != null) - { - final XmlTag rootTag = file.getDocument().getRootTag(); - final XmlTag[] tags = rootTag != null ? XmlBackedJSClassImpl.findMxmlSubTags(rootTag, "Metadata") : XmlTag.EMPTY; - final MyJSInjectedFilesVisitor injectedFilesVisitor = new MyJSInjectedFilesVisitor(); - - for(XmlTag tag : tags) - { - JSResolveUtil.processInjectedFileForTag(tag, injectedFilesVisitor); - } - } - } - } - - if(clazzToProcess != null) - { - findAcceptableEvents = true; - setToProcessMembers(false); - setTypeContext(true); - - clazzToProcess.processDeclarations(this, ResolveState.initial(), clazz, clazz); - } - } - - @Override - public boolean process(final @Nonnull JSAttribute jsAttribute) - { - if("Event".equals(jsAttribute.getName())) - { - final JSAttributeNameValuePair eventName = jsAttribute.getValueByName("name"); - - if(eventName != null) - { - final String value = eventName.getSimpleValue(); - final JSVariable variable = myCandidatesMap.get(value); - - if(variable != null) - { - myCandidatesMap.remove(value); - myVariants.add(JSLookupUtil.createLookupItem(variable, ((JSClass) variable.getParent().getParent()).getName() + "." + variable - .getName(), JSLookupUtil.LookupPriority.HIGHER)); - } - } - } - return true; - } - - @Override - public boolean handleOtherElement(final PsiElement el, final PsiElement context, final Ref continuePassElement) - { - return true; - } - - private class MyJSInjectedFilesVisitor extends JSResolveUtil.JSInjectedFilesVisitor - { - @Override - protected void process(final JSFile file) - { - for(PsiElement element : file.getChildren()) - { - if(element instanceof JSAttributeList) - { - JSResolveUtil.processAttributeList(MyEventSubclassesProcessor.this, null, (JSAttributeList) element, true); - } - } - } - } - } +public class JSSmartCompletionVariantsHandler { + @RequiredReadAction + static Object[] getSmartVariants(@Nonnull PsiElement expr, boolean ecma) { + PsiElement parent = expr.getParent(); + + if (parent instanceof JSArgumentList argumentList && argumentList.getArguments()[0] == expr && ecma + && ((JSReferenceExpression)expr).getQualifier() == null) { + JSExpression calledExpr = ((JSCallExpression)parent.getParent()).getMethodExpression(); + + if (calledExpr instanceof JSReferenceExpression expression) { + String s = expression.getReferencedName(); + + if ("addEventListener".equals(s) || "removeEventListener".equals(s)) { + List variants = new ArrayList<>(); + MyEventSubclassesProcessor subclassesProcessor = new MyEventSubclassesProcessor(expr, variants); + subclassesProcessor.findAcceptableVariants(expression, parent.getProject()); + if (variants.size() > 0) { + return variants.toArray(new Object[variants.size()]); + } + } + } + } + + return null; + } + + private static class MyEventSubclassesProcessor extends ResolveProcessor implements JSResolveUtil.MetaDataProcessor { + private final PsiElement myExpr; + private final List myVariants; + private final ResolveState state = new ResolveState(); + private final Map myCandidatesMap = new HashMap<>(); + private boolean findAcceptableEvents; + + public MyEventSubclassesProcessor(PsiElement expr, List variants) { + super(null); + myExpr = expr; + myVariants = variants; + + setToProcessHierarchy(true); + } + + public boolean process(JSClass clazz) { + clazz.processDeclarations(this, state, clazz, clazz); + + return true; + } + + @Override + @RequiredReadAction + public boolean execute(@Nonnull PsiElement element, ResolveState state) { + if (element instanceof JSVariable variable) { + JSAttributeList attributeList = variable.getAttributeList(); + + if (attributeList != null + && attributeList.getAccessType() == JSAttributeList.AccessType.PUBLIC + && attributeList.hasModifier(JSAttributeList.ModifierType.STATIC) + && "String".equals(variable.getTypeString())) { + String s = variable.getInitializerText(); + if (s != null && StringUtil.startsWith(s, "\"") && StringUtil.endsWith(s, "\"")) { + myCandidatesMap.put(StringUtil.stripQuotesAroundValue(s), variable); + } + } + } + + if (findAcceptableEvents && element instanceof JSClass jsClass) { + JSResolveUtil.processMetaAttributesForClass(jsClass, this); + } + + return true; + } + + @RequiredReadAction + public void findAcceptableVariants(JSReferenceExpression expression, Project project) { + PsiElement clazz = JSResolveUtil.findClassByQName("flash.events.Event", expression.getResolveScope(), project); + clazz = JSResolveUtil.unwrapProxy(clazz); + if (!(clazz instanceof JSClass)) { + return; + } + Query query = JSClassSearch.searchClassInheritors((JSClass)clazz, true); + + for (JSClass extendedClass : query.findAll()) { + process(extendedClass); + } + + JSExpression qualifier = expression.getQualifier(); + + JSClass clazzToProcess = null; + + if (qualifier instanceof JSThisExpression || qualifier instanceof JSSuperExpression) { + clazzToProcess = PsiTreeUtil.getParentOfType(qualifier, JSClass.class); + } + else if (qualifier instanceof JSReferenceExpression referenceExpression) { + ResolveResult[] results = referenceExpression.multiResolve(false); + if (results.length > 0 && results[0].getElement() instanceof JSClass jsClass) { + clazzToProcess = jsClass; + } + } + + if (clazzToProcess == null) { + PsiElement context = expression.getContainingFile().getContext(); + clazzToProcess = JSResolveUtil.getClassFromTagNameInMxml(context); + if (clazzToProcess == null && context != null) { + XmlFile file = PsiTreeUtil.getParentOfType(context, XmlFile.class); + if (file != null) { + XmlTag rootTag = file.getDocument().getRootTag(); + XmlTag[] tags = rootTag != null + ? XmlBackedJSClassImpl.findMxmlSubTags(rootTag, "Metadata") + : XmlTag.EMPTY; + MyJSInjectedFilesVisitor injectedFilesVisitor = new MyJSInjectedFilesVisitor(); + + for (XmlTag tag : tags) { + JSResolveUtil.processInjectedFileForTag(tag, injectedFilesVisitor); + } + } + } + } + + if (clazzToProcess != null) { + findAcceptableEvents = true; + setToProcessMembers(false); + setTypeContext(true); + + clazzToProcess.processDeclarations(this, ResolveState.initial(), clazz, clazz); + } + } + + @Override + @RequiredReadAction + public boolean process(@Nonnull JSAttribute jsAttribute) { + if ("Event".equals(jsAttribute.getName())) { + JSAttributeNameValuePair eventName = jsAttribute.getValueByName("name"); + + if (eventName != null) { + String value = eventName.getSimpleValue(); + JSVariable variable = myCandidatesMap.get(value); + + if (variable != null) { + myCandidatesMap.remove(value); + myVariants.add(JSLookupUtil.createLookupItem( + variable, + ((JSClass)variable.getParent().getParent()).getName() + "." + variable + .getName(), + JSLookupUtil.LookupPriority.HIGHER + )); + } + } + } + return true; + } + + @Override + public boolean handleOtherElement(PsiElement el, PsiElement context, SimpleReference continuePassElement) { + return true; + } + + private class MyJSInjectedFilesVisitor extends JSResolveUtil.JSInjectedFilesVisitor { + @Override + @RequiredReadAction + protected void process(JSFile file) { + for (PsiElement element : file.getChildren()) { + if (element instanceof JSAttributeList attributeList) { + JSResolveUtil.processAttributeList(MyEventSubclassesProcessor.this, null, attributeList, true); + } + } + } + } + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSStatementImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSStatementImpl.java index c1d21650..857e12d1 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSStatementImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSStatementImpl.java @@ -21,10 +21,8 @@ /** * @author ven */ -public abstract class JSStatementImpl extends JSStubbedStatementImpl -{ - public JSStatementImpl(final ASTNode node) - { - super(node); - } +public abstract class JSStatementImpl extends JSStubbedStatementImpl { + public JSStatementImpl(ASTNode node) { + super(node); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSStatementWithLabelReferenceImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSStatementWithLabelReferenceImpl.java index 02a90e8c..e05e49e1 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSStatementWithLabelReferenceImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSStatementWithLabelReferenceImpl.java @@ -19,6 +19,8 @@ import com.intellij.lang.javascript.JSTokenTypes; import com.intellij.lang.javascript.psi.JSFunction; import com.intellij.lang.javascript.psi.JSLabeledStatement; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.document.util.TextRange; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiReference; @@ -27,169 +29,149 @@ import consulo.language.ast.ASTNode; import consulo.util.collection.ArrayUtil; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; + import java.util.ArrayList; import java.util.List; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 9:52:04 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -abstract class JSStatementWithLabelReferenceImpl extends JSStatementImpl -{ - private PsiReference[] myReferences; - private String myReferencesText; - - protected JSStatementWithLabelReferenceImpl(final ASTNode node) - { - super(node); - } - - public String getLabel() - { - final ASTNode label = getNode().findChildByType(JSTokenTypes.IDENTIFIER); - return label != null ? label.getText() : null; - } - - @Override - @Nonnull - public PsiReference[] getReferences() - { - final String text = getText(); - - if(!text.equals(myReferencesText) || myReferences == null) - { - final ASTNode label = getNode().findChildByType(JSTokenTypes.IDENTIFIER); - if(label != null) - { - myReferences = new PsiReference[]{new JSStatementWithLabelReferenceImpl.LabelReference(label.getPsi())}; - } - else - { - myReferences = PsiReference.EMPTY_ARRAY; - } - myReferencesText = text; - } - return myReferences; - } - - private class LabelReference implements PsiReference - { - private PsiElement labelNode; - - LabelReference(PsiElement _labelNode) - { - labelNode = _labelNode; - } - - @Override - public PsiElement getElement() - { - return JSStatementWithLabelReferenceImpl.this; - } - - @Override - public TextRange getRangeInElement() - { - final int startOffsetInParent = labelNode.getStartOffsetInParent(); - return new TextRange(startOffsetInParent, startOffsetInParent + labelNode.getTextLength()); - } - - @Override - @Nullable - public PsiElement resolve() - { - final PsiElement[] result = new PsiElement[1]; - - processElements(new PsiElementProcessor() - { - private final String label = getCanonicalText(); - - @Override - public boolean execute(final JSLabeledStatement element) - { - if(label.equals(element.getLabel())) - { - result[0] = element; - return false; - } - return true; - } - }); - - return result[0]; - } - - @Override - public String getCanonicalText() - { - return labelNode.getText(); - } - - @Override - public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException - { - JSChangeUtil.doIdentifierReplacement(getElement(), labelNode, newElementName); - return getElement(); - } - - @Override - public PsiElement bindToElement(@Nonnull PsiElement element) throws IncorrectOperationException - { - return null; - } - - @Override - public boolean isReferenceTo(PsiElement element) - { - return getManager().areElementsEquivalent(resolve(), element); - } - - @Override - public Object[] getVariants() - { - final List labels = new ArrayList(1); - processElements(new PsiElementProcessor() - { - @Override - public boolean execute(final JSLabeledStatement element) - { - labels.add(element.getLabel()); - return true; - } - }); - return ArrayUtil.toStringArray(labels); - } - - private void processElements(PsiElementProcessor processor) - { - PsiElement run = getParent(); - while(run != null) - { - if(run instanceof JSLabeledStatement) - { - if(!processor.execute((JSLabeledStatement) run)) - { - return; - } - } - - if(run instanceof JSFunction) - { - break; - } - run = run.getParent(); - } - } - - @Override - public boolean isSoft() - { - return false; - } - } +abstract class JSStatementWithLabelReferenceImpl extends JSStatementImpl { + private PsiReference[] myReferences; + private String myReferencesText; + + protected JSStatementWithLabelReferenceImpl(ASTNode node) { + super(node); + } + + @RequiredReadAction + public String getLabel() { + ASTNode label = getNode().findChildByType(JSTokenTypes.IDENTIFIER); + return label != null ? label.getText() : null; + } + + @Nonnull + @Override + @RequiredReadAction + public PsiReference[] getReferences() { + String text = getText(); + + if (!text.equals(myReferencesText) || myReferences == null) { + ASTNode label = getNode().findChildByType(JSTokenTypes.IDENTIFIER); + if (label != null) { + myReferences = new PsiReference[]{new JSStatementWithLabelReferenceImpl.LabelReference(label.getPsi())}; + } + else { + myReferences = PsiReference.EMPTY_ARRAY; + } + myReferencesText = text; + } + return myReferences; + } + + private class LabelReference implements PsiReference { + private PsiElement labelNode; + + LabelReference(PsiElement _labelNode) { + labelNode = _labelNode; + } + + @Override + @RequiredReadAction + public PsiElement getElement() { + return JSStatementWithLabelReferenceImpl.this; + } + + @Nonnull + @Override + @RequiredReadAction + public TextRange getRangeInElement() { + int startOffsetInParent = labelNode.getStartOffsetInParent(); + return new TextRange(startOffsetInParent, startOffsetInParent + labelNode.getTextLength()); + } + + @Override + @Nullable + @RequiredReadAction + public PsiElement resolve() { + PsiElement[] result = new PsiElement[1]; + + processElements(new PsiElementProcessor<>() { + private final String label = getCanonicalText(); + + @Override + @RequiredReadAction + public boolean execute(@Nonnull JSLabeledStatement element) { + if (label.equals(element.getLabel())) { + result[0] = element; + return false; + } + return true; + } + }); + + return result[0]; + } + + @Nonnull + @Override + @RequiredReadAction + public String getCanonicalText() { + return labelNode.getText(); + } + + @Override + @RequiredWriteAction + public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException { + JSChangeUtil.doIdentifierReplacement(getElement(), labelNode, newElementName); + return getElement(); + } + + @Override + @RequiredWriteAction + public PsiElement bindToElement(@Nonnull PsiElement element) throws IncorrectOperationException { + return null; + } + + @Override + @RequiredReadAction + public boolean isReferenceTo(PsiElement element) { + return getManager().areElementsEquivalent(resolve(), element); + } + + @Nonnull + @Override + @RequiredReadAction + public Object[] getVariants() { + List labels = new ArrayList<>(1); + processElements(element -> { + labels.add(element.getLabel()); + return true; + }); + return ArrayUtil.toStringArray(labels); + } + + private void processElements(PsiElementProcessor processor) { + PsiElement run = getParent(); + while (run != null) { + if (run instanceof JSLabeledStatement labeledStatement && !processor.execute(labeledStatement)) { + return; + } + + if (run instanceof JSFunction) { + break; + } + run = run.getParent(); + } + } + + @Override + @RequiredReadAction + public boolean isSoft() { + return false; + } + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSStubElementImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSStubElementImpl.java index 9554378c..e7644816 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSStubElementImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSStubElementImpl.java @@ -20,6 +20,8 @@ import com.intellij.lang.javascript.psi.JSElement; import com.intellij.lang.javascript.psi.JSElementVisitor; import com.intellij.lang.javascript.psi.JSNamedElement; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.content.scope.SearchScope; import consulo.language.ast.ASTNode; import consulo.language.impl.psi.stub.StubBasedPsiElementBase; @@ -31,157 +33,130 @@ import consulo.navigation.ItemPresentation; import consulo.navigation.NavigationItem; import consulo.util.dataholder.Key; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * User: max - * Date: Jan 30, 2005 - * Time: 8:23:10 PM + * @author max + * @since 2005-01-30 */ -public abstract class JSStubElementImpl extends StubBasedPsiElementBase implements JSElement -{ - public static Key ORIGINAL_ELEMENT = Key.create("ORIGINAL_NAMED_ELEMENT"); - - public JSStubElementImpl(final ASTNode node) - { - super(node); - } - - public JSStubElementImpl(final T t, IStubElementType type) - { - super(t, type); - } - - protected abstract void accept(@Nonnull JSElementVisitor visitor); - - @Override - public final void accept(@Nonnull PsiElementVisitor visitor) - { - if(visitor instanceof JSElementVisitor) - { - accept((JSElementVisitor)visitor); - } - else - { - super.accept(visitor); - } - } - - public SearchScope getDefaultUseScope() - { - return super.getUseScope(); - } - - @Override - public ItemPresentation getPresentation() - { - if(this instanceof JSNamedElement) - { - final NavigationItem element = getUserData(ORIGINAL_ELEMENT); - if(element == null) - { - return new JSItemPresentation((JSNamedElement) this); - } - return element.getPresentation(); - } - return null; - } - - @Override - public PsiElement addBefore(@Nonnull PsiElement element, PsiElement anchor) throws IncorrectOperationException - { - if(JSChangeUtil.isStatementOrComment(element)) - { - if(JSChangeUtil.isStatementContainer(this)) - { - return JSChangeUtil.doAddBefore(this, element, anchor); - } - else if(JSChangeUtil.isBlockStatementContainer(this) && anchor != null) - { - return JSChangeUtil.blockDoAddBefore(element, anchor); - } - } - - return super.addBefore(element, anchor); - } - - @Override - public PsiElement addAfter(@Nonnull PsiElement element, PsiElement anchor) throws IncorrectOperationException - { - if(JSChangeUtil.isStatementOrComment(element)) - { - if(JSChangeUtil.isStatementContainer(this)) - { - return JSChangeUtil.doAddAfter(this, element, anchor); - } - else if(JSChangeUtil.isBlockStatementContainer(this) && anchor != null) - { - return JSChangeUtil.blockDoAddAfter(element, anchor); - } - } - return super.addAfter(element, anchor); - } - - @Override - public PsiElement addRangeBefore(@Nonnull PsiElement first, @Nonnull PsiElement last, PsiElement anchor) throws IncorrectOperationException - { - if(JSChangeUtil.isStatementOrComment(first)) - { - if(JSChangeUtil.isStatementContainer(this)) - { - return JSChangeUtil.doAddRangeBefore(this, first, last, anchor); - } - else if(JSChangeUtil.isBlockStatementContainer(this) && anchor != null) - { - return JSChangeUtil.blockDoAddRangeBefore(first, last, anchor); - } - } - return super.addRangeBefore(first, last, anchor); - } - - @Override - public PsiElement addRangeAfter(PsiElement first, PsiElement last, PsiElement anchor) throws IncorrectOperationException - { - if(JSChangeUtil.isStatementOrComment(first)) - { - if(JSChangeUtil.isStatementContainer(this)) - { - return JSChangeUtil.doAddRangeAfter(this, first, last, anchor); - } - else if(JSChangeUtil.isBlockStatementContainer(this) && anchor != null) - { - return JSChangeUtil.blockDoAddRangeAfter(first, last, anchor); - } - } - - return super.addRangeAfter(first, last, anchor); - } - - @Override - public PsiElement add(@Nonnull PsiElement element) throws IncorrectOperationException - { - return addAfter(element, null); - } - - @Override - public PsiElement addRange(PsiElement first, PsiElement last) throws IncorrectOperationException - { - return addRangeAfter(first, last, null); - } - - @Override - public PsiElement replace(@Nonnull PsiElement newElement) throws IncorrectOperationException - { - final ASTNode myNode = getNode(); - final ASTNode result = newElement.getNode().copyElement(); - myNode.getTreeParent().replaceChild(myNode, result); - return result.getPsi(); - } - - @Override - public PsiElement getParent() - { - return getParentByStub(); - } +public abstract class JSStubElementImpl extends StubBasedPsiElementBase implements JSElement { + public static Key ORIGINAL_ELEMENT = Key.create("ORIGINAL_NAMED_ELEMENT"); + + public JSStubElementImpl(ASTNode node) { + super(node); + } + + public JSStubElementImpl(T t, IStubElementType type) { + super(t, type); + } + + protected abstract void accept(@Nonnull JSElementVisitor visitor); + + @Override + public final void accept(@Nonnull PsiElementVisitor visitor) { + if (visitor instanceof JSElementVisitor elementVisitor) { + accept(elementVisitor); + } + else { + super.accept(visitor); + } + } + + public SearchScope getDefaultUseScope() { + return super.getUseScope(); + } + + @Override + public ItemPresentation getPresentation() { + if (this instanceof JSNamedElement namedThis) { + NavigationItem element = getUserData(ORIGINAL_ELEMENT); + return element == null ? new JSItemPresentation(namedThis) : element.getPresentation(); + } + return null; + } + + @Override + @RequiredWriteAction + public PsiElement addBefore(@Nonnull PsiElement element, PsiElement anchor) throws IncorrectOperationException { + if (JSChangeUtil.isStatementOrComment(element)) { + if (JSChangeUtil.isStatementContainer(this)) { + return JSChangeUtil.doAddBefore(this, element, anchor); + } + else if (JSChangeUtil.isBlockStatementContainer(this) && anchor != null) { + return JSChangeUtil.blockDoAddBefore(element, anchor); + } + } + + return super.addBefore(element, anchor); + } + + @Override + @RequiredWriteAction + public PsiElement addAfter(@Nonnull PsiElement element, PsiElement anchor) throws IncorrectOperationException { + if (JSChangeUtil.isStatementOrComment(element)) { + if (JSChangeUtil.isStatementContainer(this)) { + return JSChangeUtil.doAddAfter(this, element, anchor); + } + else if (JSChangeUtil.isBlockStatementContainer(this) && anchor != null) { + return JSChangeUtil.blockDoAddAfter(element, anchor); + } + } + return super.addAfter(element, anchor); + } + + @Override + @RequiredWriteAction + public PsiElement addRangeBefore(@Nonnull PsiElement first, @Nonnull PsiElement last, PsiElement anchor) + throws IncorrectOperationException { + if (JSChangeUtil.isStatementOrComment(first)) { + if (JSChangeUtil.isStatementContainer(this)) { + return JSChangeUtil.doAddRangeBefore(this, first, last, anchor); + } + else if (JSChangeUtil.isBlockStatementContainer(this) && anchor != null) { + return JSChangeUtil.blockDoAddRangeBefore(first, last, anchor); + } + } + return super.addRangeBefore(first, last, anchor); + } + + @Override + @RequiredWriteAction + public PsiElement addRangeAfter(PsiElement first, PsiElement last, PsiElement anchor) throws IncorrectOperationException { + if (JSChangeUtil.isStatementOrComment(first)) { + if (JSChangeUtil.isStatementContainer(this)) { + return JSChangeUtil.doAddRangeAfter(this, first, last, anchor); + } + else if (JSChangeUtil.isBlockStatementContainer(this) && anchor != null) { + return JSChangeUtil.blockDoAddRangeAfter(first, last, anchor); + } + } + + return super.addRangeAfter(first, last, anchor); + } + + @Override + @RequiredWriteAction + public PsiElement add(@Nonnull PsiElement element) throws IncorrectOperationException { + return addAfter(element, null); + } + + @Override + @RequiredWriteAction + public PsiElement addRange(PsiElement first, PsiElement last) throws IncorrectOperationException { + return addRangeAfter(first, last, null); + } + + @Override + @RequiredReadAction + public PsiElement replace(@Nonnull PsiElement newElement) throws IncorrectOperationException { + ASTNode myNode = getNode(); + ASTNode result = newElement.getNode().copyElement(); + myNode.getTreeParent().replaceChild(myNode, result); + return result.getPsi(); + } + + @Override + public PsiElement getParent() { + return getParentByStub(); + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSStubbedStatementImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSStubbedStatementImpl.java index feb03299..d91acb1e 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSStubbedStatementImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSStubbedStatementImpl.java @@ -20,7 +20,9 @@ import com.intellij.lang.javascript.psi.JSStatement; import com.intellij.lang.javascript.psi.JSSuppressionHolder; import com.intellij.lang.javascript.types.JSFileElementType; +import consulo.annotation.access.RequiredWriteAction; import consulo.language.ast.ASTNode; +import consulo.language.ast.IElementType; import consulo.language.codeStyle.CodeStyleManager; import consulo.language.psi.stub.IStubElementType; import consulo.language.psi.stub.StubElement; @@ -29,72 +31,65 @@ /** * @author ven */ -abstract class JSStubbedStatementImpl extends JSStubElementImpl implements JSStatement, JSSuppressionHolder -{ - JSStubbedStatementImpl(final ASTNode node) - { - super(node); - } +abstract class JSStubbedStatementImpl extends JSStubElementImpl implements JSStatement, JSSuppressionHolder { + JSStubbedStatementImpl(ASTNode node) { + super(node); + } - JSStubbedStatementImpl(final T t, IStubElementType type) - { - super(t, type); - } + JSStubbedStatementImpl(T t, IStubElementType type) { + super(t, type); + } - @Override - public JSStatement addStatementBefore(JSStatement toAdd) throws IncorrectOperationException - { - return addStatementImpl(toAdd, true); - } + @Override + @RequiredWriteAction + public JSStatement addStatementBefore(JSStatement toAdd) throws IncorrectOperationException { + return addStatementImpl(toAdd, true); + } - @Override - public JSStatement addStatementAfter(JSStatement toAdd) throws IncorrectOperationException - { - return addStatementImpl(toAdd, false); - } + @Override + @RequiredWriteAction + public JSStatement addStatementAfter(JSStatement toAdd) throws IncorrectOperationException { + return addStatementImpl(toAdd, false); + } - //TODO: [lesya] the formatter stuff definitely needs more intelligence - private JSStatement addStatementImpl(final JSStatement toAdd, final boolean before) throws IncorrectOperationException - { - final ASTNode treeParent = getNode().getTreeParent(); + //TODO: [lesya] the formatter stuff definitely needs more intelligence + @RequiredWriteAction + private JSStatement addStatementImpl(JSStatement toAdd, boolean before) throws IncorrectOperationException { + ASTNode treeParent = getNode().getTreeParent(); - if(treeParent.getElementType() != JSElementTypes.BLOCK_STATEMENT && - !(treeParent.getElementType() instanceof JSFileElementType) && - treeParent.getElementType() != JSElementTypes.CLASS && - treeParent.getElementType() != JSElementTypes.EMBEDDED_CONTENT) - { - if(before) - { - return (JSStatement) treeParent.getPsi().addBefore(toAdd, this); - } - else - { - return (JSStatement) treeParent.getPsi().addAfter(toAdd, this); - } - } - else - { - final ASTNode copy = toAdd.getNode().copyElement(); - addChildAndReformat(treeParent, copy, before ? getNode() : getNode().getTreeNext()); - return (JSStatement) copy.getPsi(); - } - } + IElementType elementType = treeParent.getElementType(); + if (elementType != JSElementTypes.BLOCK_STATEMENT + && !(elementType instanceof JSFileElementType) + && elementType != JSElementTypes.CLASS + && elementType != JSElementTypes.EMBEDDED_CONTENT) { + if (before) { + return (JSStatement)treeParent.getPsi().addBefore(toAdd, this); + } + else { + return (JSStatement)treeParent.getPsi().addAfter(toAdd, this); + } + } + else { + ASTNode copy = toAdd.getNode().copyElement(); + addChildAndReformat(treeParent, copy, before ? getNode() : getNode().getTreeNext()); + return (JSStatement)copy.getPsi(); + } + } - private void addChildAndReformat(final ASTNode block, final ASTNode addedElement, final ASTNode anchorBefore) throws IncorrectOperationException - { - block.addChild(addedElement, anchorBefore); - CodeStyleManager.getInstance(getProject()).reformatNewlyAddedElement(block, addedElement); - } + private void addChildAndReformat(ASTNode block, ASTNode addedElement, ASTNode anchorBefore) throws IncorrectOperationException { + block.addChild(addedElement, anchorBefore); + CodeStyleManager.getInstance(getProject()).reformatNewlyAddedElement(block, addedElement); + } - @Override - public JSStatement replace(JSStatement newStatement) - { - return JSChangeUtil.replaceStatement(this, newStatement); - } + @Override + @RequiredWriteAction + public JSStatement replace(JSStatement newStatement) { + return JSChangeUtil.replaceStatement(this, newStatement); + } - @Override - public void delete() throws IncorrectOperationException - { - getNode().getTreeParent().removeChild(getNode()); - } + @Override + @RequiredWriteAction + public void delete() throws IncorrectOperationException { + getNode().getTreeParent().removeChild(getNode()); + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSSuperExpressionImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSSuperExpressionImpl.java index 6e175373..0c89e2d8 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSSuperExpressionImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSSuperExpressionImpl.java @@ -19,6 +19,8 @@ import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; import com.intellij.lang.javascript.psi.resolve.ResolveProcessor; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiReference; import consulo.language.psi.util.PsiTreeUtil; @@ -29,139 +31,126 @@ import consulo.language.psi.resolve.ResolveState; import consulo.util.collection.ArrayUtil; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 11:24:42 PM + * @author max + * @since 2005-01-30 */ -public class JSSuperExpressionImpl extends JSExpressionImpl implements JSSuperExpression -{ - public JSSuperExpressionImpl(final ASTNode node) - { - super(node); - } - - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSSuperExpression(this); - } - - @Override - public PsiReference getReference() - { - return getReferences()[0]; - } - - @Override - @Nonnull - public PsiReference[] getReferences() - { - PsiReference[] refs = { - new PsiReference() - { - @Override - public PsiElement getElement() - { - return JSSuperExpressionImpl.this; - } - - @Override - public TextRange getRangeInElement() - { - return new TextRange(0, getTextLength()); - } - - @Override - @Nullable - public PsiElement resolve() - { - final PsiElement element = findClass(); - - if(getElement().getParent() instanceof JSCallExpression && element instanceof JSClass) - { - final JSClass clazz = (JSClass) element; - final ResolveProcessor processor = new ResolveProcessor(clazz.getName(), JSSuperExpressionImpl.this); - element.processDeclarations(processor, ResolveState.initial(), clazz, getElement()); - if(processor.getResult() != null) - { - return processor.getResult(); - } - } - - return element; - } - - private PsiElement findClass() - { - final JSClass jsClass = PsiTreeUtil.getParentOfType(getElement(), JSClass.class); - - if(jsClass != null) - { - final JSReferenceList extendsList = jsClass.getExtendsList(); - if(extendsList != null) - { - final JSReferenceExpression[] referenceExpressions = extendsList.getExpressions(); - if(referenceExpressions != null && referenceExpressions.length > 0) - { - final ResolveResult[] results = referenceExpressions[0].multiResolve(false); - return results.length > 0 ? results[0].getElement() : null; - } - } - } - else - { - final JSFile jsFile = PsiTreeUtil.getParentOfType(getElement(), JSFile.class); - - if(jsFile != null) - { - return JSResolveUtil.getClassReferenceForXmlFromContext(jsFile); - } - } - return null; - } - - @Override - public String getCanonicalText() - { - return getText(); - } - - @Override - public PsiElement handleElementRename(final String newElementName) throws IncorrectOperationException - { - return null; - } - - @Override - public PsiElement bindToElement(@Nonnull final PsiElement element) throws IncorrectOperationException - { - return null; - } - - @Override - public boolean isReferenceTo(final PsiElement element) - { - return false; - } - - @Override - public Object[] getVariants() - { - return ArrayUtil.EMPTY_OBJECT_ARRAY; - } - - @Override - public boolean isSoft() - { - return true; - } - } - }; - return refs; - } +public class JSSuperExpressionImpl extends JSExpressionImpl implements JSSuperExpression { + public JSSuperExpressionImpl(ASTNode node) { + super(node); + } + + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSSuperExpression(this); + } + + @Override + public PsiReference getReference() { + return getReferences()[0]; + } + + @Override + @Nonnull + public PsiReference[] getReferences() { + PsiReference[] refs = { + new PsiReference() { + @Override + @RequiredReadAction + public PsiElement getElement() { + return JSSuperExpressionImpl.this; + } + + @Nonnull + @Override + @RequiredReadAction + public TextRange getRangeInElement() { + return new TextRange(0, getTextLength()); + } + + @Nullable + @Override + @RequiredReadAction + public PsiElement resolve() { + PsiElement element = findClass(); + + if (getElement().getParent() instanceof JSCallExpression && element instanceof JSClass jsClass) { + ResolveProcessor processor = new ResolveProcessor(jsClass.getName(), JSSuperExpressionImpl.this); + element.processDeclarations(processor, ResolveState.initial(), jsClass, getElement()); + if (processor.getResult() != null) { + return processor.getResult(); + } + } + + return element; + } + + @RequiredReadAction + private PsiElement findClass() { + JSClass jsClass = PsiTreeUtil.getParentOfType(getElement(), JSClass.class); + + if (jsClass != null) { + JSReferenceList extendsList = jsClass.getExtendsList(); + if (extendsList != null) { + JSReferenceExpression[] referenceExpressions = extendsList.getExpressions(); + if (referenceExpressions != null && referenceExpressions.length > 0) { + ResolveResult[] results = referenceExpressions[0].multiResolve(false); + return results.length > 0 ? results[0].getElement() : null; + } + } + } + else { + JSFile jsFile = PsiTreeUtil.getParentOfType(getElement(), JSFile.class); + + if (jsFile != null) { + return JSResolveUtil.getClassReferenceForXmlFromContext(jsFile); + } + } + return null; + } + + @Nonnull + @Override + @RequiredReadAction + public String getCanonicalText() { + return getText(); + } + + @Override + @RequiredWriteAction + public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException { + return null; + } + + @Override + @RequiredWriteAction + public PsiElement bindToElement(@Nonnull PsiElement element) throws IncorrectOperationException { + return null; + } + + @Override + @RequiredReadAction + public boolean isReferenceTo(PsiElement element) { + return false; + } + + @Nonnull + @Override + @RequiredReadAction + public Object[] getVariants() { + return ArrayUtil.EMPTY_OBJECT_ARRAY; + } + + @Override + @RequiredReadAction + public boolean isSoft() { + return true; + } + } + }; + return refs; + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSSwitchStatementImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSSwitchStatementImpl.java index f4895467..d8dcd6ef 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSSwitchStatementImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSSwitchStatementImpl.java @@ -23,40 +23,31 @@ import com.intellij.lang.javascript.psi.JSSwitchStatement; import consulo.language.ast.ASTNode; import consulo.language.ast.TokenSet; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 10:08:20 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSSwitchStatementImpl extends JSStatementImpl implements JSSwitchStatement -{ - private static final TokenSet CASE_CLAUSE_FILTER = TokenSet.create(JSElementTypes.CASE_CLAUSE); - - public JSSwitchStatementImpl(final ASTNode node) - { - super(node); - } - - @Override - public JSExpression getSwitchExpression() - { - return findChildByClass(JSExpression.class); - } - - @Override - public JSCaseClause[] getCaseClauses() - { - return findChildrenByClass(JSCaseClause.class); - } - - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSSwitchStatement(this); - } +public class JSSwitchStatementImpl extends JSStatementImpl implements JSSwitchStatement { + private static final TokenSet CASE_CLAUSE_FILTER = TokenSet.create(JSElementTypes.CASE_CLAUSE); + + public JSSwitchStatementImpl(ASTNode node) { + super(node); + } + + @Override + public JSExpression getSwitchExpression() { + return findChildByClass(JSExpression.class); + } + + @Override + public JSCaseClause[] getCaseClauses() { + return findChildrenByClass(JSCaseClause.class); + } + + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSSwitchStatement(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSThisExpressionImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSThisExpressionImpl.java index fe59da9b..66777356 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSThisExpressionImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSThisExpressionImpl.java @@ -20,25 +20,19 @@ import com.intellij.lang.javascript.psi.JSThisExpression; import consulo.language.ast.ASTNode; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 11:24:42 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSThisExpressionImpl extends JSExpressionImpl implements JSThisExpression -{ - public JSThisExpressionImpl(final ASTNode node) - { - super(node); - } +public class JSThisExpressionImpl extends JSExpressionImpl implements JSThisExpression { + public JSThisExpressionImpl(ASTNode node) { + super(node); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSThisExpression(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSThisExpression(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSThrowStatementImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSThrowStatementImpl.java index 5bf27e86..3aaf49f5 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSThrowStatementImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSThrowStatementImpl.java @@ -20,32 +20,24 @@ import com.intellij.lang.javascript.psi.JSElementVisitor; import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.JSThrowStatement; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 9:57:08 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSThrowStatementImpl extends JSStatementImpl implements JSThrowStatement -{ - public JSThrowStatementImpl(final ASTNode node) - { - super(node); - } +public class JSThrowStatementImpl extends JSStatementImpl implements JSThrowStatement { + public JSThrowStatementImpl(ASTNode node) { + super(node); + } - @Override - public JSExpression getExpression() - { - return findChildByClass(JSExpression.class); - } + @Override + public JSExpression getExpression() { + return findChildByClass(JSExpression.class); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSThrowStatement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSThrowStatement(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSTryStatementImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSTryStatementImpl.java index 1eb555f0..8e6da9f5 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSTryStatementImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSTryStatementImpl.java @@ -16,6 +16,7 @@ package com.intellij.lang.javascript.psi.impl; +import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.ASTNode; import com.intellij.lang.javascript.JSElementTypes; import com.intellij.lang.javascript.JSTokenTypes; @@ -26,87 +27,75 @@ import consulo.language.ast.IElementType; import consulo.language.ast.TokenSet; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 9:59:44 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSTryStatementImpl extends JSStatementImpl implements JSTryStatement -{ - private static TokenSet ourCatchesTypeSet = TokenSet.create(JSElementTypes.CATCH_BLOCK); +public class JSTryStatementImpl extends JSStatementImpl implements JSTryStatement { + private static final TokenSet CATCHES_TYPE_SET = TokenSet.create(JSElementTypes.CATCH_BLOCK); - public JSTryStatementImpl(final ASTNode node) - { - super(node); - } + public JSTryStatementImpl(ASTNode node) { + super(node); + } - @Override - public JSStatement getStatement() - { - ASTNode child = getNode().getFirstChildNode(); - while(child != null) - { - final IElementType type = child.getElementType(); - if(child.getPsi() instanceof JSStatement) - { - return (JSStatement) child.getPsi(); - } - if(type == JSTokenTypes.FINALLY_KEYWORD) - { - break; - } - child = child.getTreeNext(); - } - return null; - } + @Override + @RequiredReadAction + public JSStatement getStatement() { + ASTNode child = getNode().getFirstChildNode(); + while (child != null) { + IElementType type = child.getElementType(); + if (child.getPsi() instanceof JSStatement statement) { + return statement; + } + if (type == JSTokenTypes.FINALLY_KEYWORD) { + break; + } + child = child.getTreeNext(); + } + return null; + } - @Override - @Nullable - public JSCatchBlock getCatchBlock() - { - final ASTNode catchChild = getNode().findChildByType(JSElementTypes.CATCH_BLOCK); - if(catchChild == null) - { - return null; - } - return (JSCatchBlock) catchChild.getPsi(); - } + @Override + @Nullable + @RequiredReadAction + public JSCatchBlock getCatchBlock() { + ASTNode catchChild = getNode().findChildByType(JSElementTypes.CATCH_BLOCK); + if (catchChild == null) { + return null; + } + return (JSCatchBlock)catchChild.getPsi(); + } - @Override - public JSCatchBlock[] getAllCatchBlocks() - { - return findChildrenByClass(JSCatchBlock.class); - } + @Nonnull + @Override + @RequiredReadAction + public JSCatchBlock[] getAllCatchBlocks() { + return findChildrenByClass(JSCatchBlock.class); + } - @Override - public JSStatement getFinallyStatement() - { - ASTNode child = getNode().getFirstChildNode(); - boolean foundFinally = false; - while(child != null) - { - final IElementType type = child.getElementType(); - if(foundFinally && child.getPsi() instanceof JSStatement) - { - return (JSStatement) child.getPsi(); - } - if(type == JSTokenTypes.FINALLY_KEYWORD) - { - foundFinally = true; - } - child = child.getTreeNext(); - } - return null; - } + @Override + @RequiredReadAction + public JSStatement getFinallyStatement() { + ASTNode child = getNode().getFirstChildNode(); + boolean foundFinally = false; + while (child != null) { + IElementType type = child.getElementType(); + if (foundFinally && child.getPsi() instanceof JSStatement statement) { + return statement; + } + if (type == JSTokenTypes.FINALLY_KEYWORD) { + foundFinally = true; + } + child = child.getTreeNext(); + } + return null; + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSTryStatement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSTryStatement(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSUseNamespaceDirectiveImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSUseNamespaceDirectiveImpl.java index 0e3747e7..7cf92043 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSUseNamespaceDirectiveImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSUseNamespaceDirectiveImpl.java @@ -16,6 +16,7 @@ package com.intellij.lang.javascript.psi.impl; +import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.ASTNode; import com.intellij.lang.javascript.JSElementTypes; import com.intellij.lang.javascript.psi.JSElementVisitor; @@ -26,49 +27,44 @@ import consulo.language.psi.resolve.PsiScopeProcessor; import consulo.language.psi.resolve.ResolveState; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * @by Maxim.Mossienko + * @author Maxim.Mossienko */ -public class JSUseNamespaceDirectiveImpl extends JSStubbedStatementImpl implements JSUseNamespaceDirective -{ - public JSUseNamespaceDirectiveImpl(final ASTNode node) - { - super(node); - } +public class JSUseNamespaceDirectiveImpl extends JSStubbedStatementImpl implements JSUseNamespaceDirective { + public JSUseNamespaceDirectiveImpl(ASTNode node) { + super(node); + } - public JSUseNamespaceDirectiveImpl(final JSUseNamespaceDirectiveStub stub) - { - super(stub, JSElementTypes.USE_NAMESPACE_DIRECTIVE); - } + public JSUseNamespaceDirectiveImpl(JSUseNamespaceDirectiveStub stub) { + super(stub, JSElementTypes.USE_NAMESPACE_DIRECTIVE); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSUseNamespaceDirective(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSUseNamespaceDirective(this); + } - @Override - public String getNamespaceToBeUsed() - { - final JSUseNamespaceDirectiveStub stub = getStub(); - if(stub != null) - { - return stub.getNamespaceToUse(); - } - final ASTNode node = getNode().findChildByType(JSElementTypes.REFERENCE_EXPRESSION); - return node != null ? node.getText() : null; - } + @Override + @RequiredReadAction + public String getNamespaceToBeUsed() { + JSUseNamespaceDirectiveStub stub = getStub(); + if (stub != null) { + return stub.getNamespaceToUse(); + } + ASTNode node = getNode().findChildByType(JSElementTypes.REFERENCE_EXPRESSION); + return node != null ? node.getText() : null; + } - @Override - public boolean processDeclarations(@Nonnull PsiScopeProcessor processor, @Nonnull ResolveState state, PsiElement lastParent, - @Nonnull PsiElement place) - { - if(processor instanceof ResolveProcessor && ((ResolveProcessor) processor).lookingForUseNamespaces()) - { - return processor.execute(this, state); - } - return true; - } + @Override + public boolean processDeclarations( + @Nonnull PsiScopeProcessor processor, + @Nonnull ResolveState state, + PsiElement lastParent, + @Nonnull PsiElement place + ) { + return !(processor instanceof ResolveProcessor resolveProcessor && resolveProcessor.lookingForUseNamespaces()) + || processor.execute(this, state); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSVarStatementImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSVarStatementImpl.java index 261d59e1..8d313d9e 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSVarStatementImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSVarStatementImpl.java @@ -25,78 +25,69 @@ import consulo.language.psi.resolve.PsiScopeProcessor; import consulo.annotation.access.RequiredReadAction; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 9:35:47 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSVarStatementImpl extends JSStubbedStatementImpl implements JSVarStatement -{ - public JSVarStatementImpl(final ASTNode node) - { - super(node); - } +public class JSVarStatementImpl extends JSStubbedStatementImpl implements JSVarStatement { + public JSVarStatementImpl(ASTNode node) { + super(node); + } - public JSVarStatementImpl(final JSVarStatementStub node) - { - super(node, JSElementTypes.VAR_STATEMENT); - } + public JSVarStatementImpl(JSVarStatementStub node) { + super(node, JSElementTypes.VAR_STATEMENT); + } - @Override - public JSVariable[] getVariables() - { - JSDestructuringElement destructuringElement = getDestructuringElement(); - if(destructuringElement != null) - { - return destructuringElement.getVariables(); - } - return getStubOrPsiChildren(JSElementTypes.VARIABLE, JSVariable.EMPTY_ARRAY); - } + @Override + @RequiredReadAction + public JSVariable[] getVariables() { + JSDestructuringElement destructuringElement = getDestructuringElement(); + if (destructuringElement != null) { + return destructuringElement.getVariables(); + } + return getStubOrPsiChildren(JSElementTypes.VARIABLE, JSVariable.EMPTY_ARRAY); + } - @RequiredReadAction - @Nullable - @Override - public JSDestructuringElement getDestructuringElement() - { - return findChildByClass(JSDestructuringElement.class); - } + @Nullable + @Override + @RequiredReadAction + public JSDestructuringElement getDestructuringElement() { + return findChildByClass(JSDestructuringElement.class); + } - @Override - public void declareVariable(String name, JSExpression initializer) - { - throw new UnsupportedOperationException("TODO: implement"); - } + @Override + public void declareVariable(String name, JSExpression initializer) { + throw new UnsupportedOperationException("TODO: implement"); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSVarStatement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSVarStatement(this); + } - @Override - public boolean processDeclarations(@Nonnull PsiScopeProcessor processor, @Nonnull ResolveState state, PsiElement lastParent, - @Nonnull PsiElement place) - { - final JSVariable[] vars = getVariables(); + @Override + @RequiredReadAction + public boolean processDeclarations( + @Nonnull PsiScopeProcessor processor, + @Nonnull ResolveState state, + PsiElement lastParent, + @Nonnull PsiElement place + ) { + JSVariable[] vars = getVariables(); - for(JSVariable var : vars) - { - if(lastParent != null && lastParent.getParent() == var) - { - break; - } + for (JSVariable var : vars) { + if (lastParent != null && lastParent.getParent() == var) { + break; + } - if(!processor.execute(var, state)) - { - return false; - } - } + if (!processor.execute(var, state)) { + return false; + } + } - return true; - } + return true; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSVariableBaseImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSVariableBaseImpl.java index 4fa7d7e7..4779bf23 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSVariableBaseImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSVariableBaseImpl.java @@ -17,304 +17,271 @@ package com.intellij.lang.javascript.psi.impl; import com.intellij.javascript.documentation.JSDocumentationUtils; -import consulo.application.util.RecursionManager; -import consulo.application.util.function.Computable; -import consulo.content.scope.SearchScope; -import consulo.javascript.impl.language.psi.JSStubElementType; -import consulo.language.ast.ASTNode; import com.intellij.lang.javascript.JSElementTypes; import com.intellij.lang.javascript.JSTokenTypes; import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; import com.intellij.lang.javascript.psi.stubs.JSVariableStubBase; -import consulo.language.psi.PsiElement; -import consulo.language.ast.IElementType; -import consulo.language.util.IncorrectOperationException; import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; +import consulo.application.util.RecursionManager; +import consulo.content.scope.SearchScope; +import consulo.javascript.impl.language.psi.JSStubElementType; import consulo.javascript.lang.JavaScriptTokenSets; import consulo.javascript.language.psi.JavaScriptType; import consulo.javascript.language.psi.JavaScriptTypeElement; +import consulo.language.ast.ASTNode; +import consulo.language.ast.IElementType; +import consulo.language.psi.PsiElement; import consulo.language.psi.resolve.PsiScopeProcessor; import consulo.language.psi.resolve.ResolveState; +import consulo.language.util.IncorrectOperationException; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; +import java.util.function.Supplier; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 8:47:58 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSVariableBaseImpl, T2 extends JSVariable> extends JSStubElementImpl implements JSVariable -{ - protected JSVariableBaseImpl(ASTNode node) - { - super(node); - } - - protected JSVariableBaseImpl(final T stub, final JSStubElementType elementType) - { - super(stub, elementType); - } - - @Override - public boolean hasInitializer() - { - return getInitializerText() != null; - } - - @RequiredReadAction - @Override - public JSExpression getInitializer() - { - PsiElement element = findChildByType(JSTokenTypes.EQ); - if(element == null) - { - return null; - } - - while((element = element.getNextSibling()) != null) - { - if(element instanceof JSExpression) - { - return (JSExpression) element; - } - } - return null; - } - - @Override - public String getInitializerText() - { - final T stub = getStub(); - if(stub != null) - { - return stub.getInitializerText(); - } - - final JSExpression expression = getInitializer(); - return expression != null ? expression.getText() : null; - } - - @Override - @Nonnull - public SearchScope getUseScope() - { - return JSResolveUtil.findUseScope(this); - } - - @Override - public String getName() - { - final T stub = getStub(); - if(stub != null) - { - return stub.getName(); - } - final PsiElement name = getNameIdentifier(); - - if(name != null) - { - if(name instanceof JSReferenceExpression) - { - return ((JSReferenceExpression) name).getReferencedName(); - } - } - return name != null ? name.getText() : ""; - } - - @Override - public JSAttributeList getAttributeList() - { - PsiElement parent = getParent(); - if(!(parent instanceof JSVarStatement)) - { - return null; - } - return ((JSVarStatementImpl) getParent()).getStubOrPsiChild(JSElementTypes.ATTRIBUTE_LIST); - } - - @Override - public void setInitializer(JSExpression expr) throws IncorrectOperationException - { - throw new UnsupportedOperationException("TODO: implement"); - } - - @Nonnull - @Override - public JavaScriptType getType() - { - final JSExpression initializer = getInitializer(); - if(initializer != null) - { - JavaScriptType javaScriptType = RecursionManager.doPreventingRecursion(this, false, new Computable() - { - @Override - @RequiredReadAction - public JavaScriptType compute() - { - return initializer.getType(); - } - }); - return javaScriptType == null ? JavaScriptType.UNKNOWN : javaScriptType; - } - return JavaScriptType.UNKNOWN; - } - - @Override - public String getTypeString() - { - final T stub = getStub(); - if(stub != null) - { - return stub.getTypeString(); - } - return doGetType(); - } - - @RequiredReadAction - @Override - public JavaScriptTypeElement getTypeElement() - { - return JSPsiImplUtils.findTypeElement(this); - } - - protected String doGetType() - { - return JSPsiImplUtils.getType(this); - } - - @Override - public PsiElement setName(@Nonnull String name) throws IncorrectOperationException - { - final PsiElement nameNode = getNameIdentifier(); - if(nameNode == null) - { - return this; - } - final ASTNode nameElement = JSChangeUtil.createNameIdentifier(getProject(), name); - getNode().replaceChild(nameNode.getNode(), nameElement); - return this; - } - - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSVariable(this); - } - - @RequiredReadAction - @Override - public int getTextOffset() - { - final PsiElement name = getNameIdentifier(); - return name != null ? name.getTextOffset() : super.getTextOffset(); - } - - @Override - public boolean isConst() - { - final T stub = getStub(); - if(stub != null) - { - return stub.isConst(); - } - final ASTNode parent = getNode().getTreeParent(); - - if(parent.getElementType() == JSElementTypes.VAR_STATEMENT) - { - ASTNode node = parent.getFirstChildNode(); - IElementType type = node.getElementType(); - - if(type == JSElementTypes.ATTRIBUTE_LIST || type == JSElementTypes.REFERENCE_EXPRESSION) - { - node = node.getTreeNext(); - - if(node != null && node.getElementType() == JSTokenTypes.WHITE_SPACE) - { - node = node.getTreeNext(); - } - } - return node != null && node.getElementType() == JSTokenTypes.CONST_KEYWORD; - } - - return false; - } - - @Override - public boolean isLocal() - { - final T stub = getStub(); - if(stub != null) - { - return stub.isLocal(); - } - final ASTNode parent = getNode().getTreeParent(); - return parent.getElementType() == JSElementTypes.VAR_STATEMENT && parent.getFirstChildNode().getElementType() == JSTokenTypes.LET_KEYWORD; - } - - @Override - public boolean isDeprecated() - { - final T stub = getStub(); - if(stub != null) - { - return stub.isDeprecated(); - } - return JSDocumentationUtils.calculateDeprecated(this); - } - - @Override - public void delete() throws IncorrectOperationException - { - final ASTNode myNode = getNode(); - final ASTNode parent = myNode.getTreeParent(); - - if(parent.getElementType() == JSElementTypes.VAR_STATEMENT) - { - final JSVariable[] jsVariables = ((JSVarStatement) parent.getPsi()).getVariables(); - - if(jsVariables.length == 1) - { - parent.getPsi().delete(); - } - else - { - JSChangeUtil.removeRangeWithRemovalOfCommas(myNode, parent); - } - return; - } - - throw new IncorrectOperationException("Cannot delete variable from parent : " + parent.getElementType()); - } - - @Override - public boolean processDeclarations(@Nonnull final PsiScopeProcessor processor, @Nonnull final ResolveState state, final PsiElement lastParent, - @Nonnull final PsiElement place) - { - if(lastParent != null && lastParent.getParent() == this) - { - processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, this); - } - return processor.execute(this, state); - } - - @Override - public String getQualifiedName() - { - final T stub = getStub(); - if(stub != null) - { - return stub.getQualifiedName(); - } - return JSPsiImplUtils.getQName(this); - } - - @Override - @RequiredReadAction - public PsiElement getNameIdentifier() - { - return findChildByType(JavaScriptTokenSets.NAME_TOKEN_TYPES); - } +public class JSVariableBaseImpl, T2 extends JSVariable> + extends JSStubElementImpl implements JSVariable { + protected JSVariableBaseImpl(ASTNode node) { + super(node); + } + + protected JSVariableBaseImpl(T stub, JSStubElementType elementType) { + super(stub, elementType); + } + + @Override + @RequiredReadAction + public boolean hasInitializer() { + return getInitializerText() != null; + } + + @Override + @RequiredReadAction + public JSExpression getInitializer() { + PsiElement element = findChildByType(JSTokenTypes.EQ); + if (element == null) { + return null; + } + + while ((element = element.getNextSibling()) != null) { + if (element instanceof JSExpression expression) { + return expression; + } + } + return null; + } + + @Override + @RequiredReadAction + public String getInitializerText() { + T stub = getStub(); + if (stub != null) { + return stub.getInitializerText(); + } + + JSExpression expression = getInitializer(); + return expression != null ? expression.getText() : null; + } + + @Nonnull + @Override + @RequiredReadAction + public SearchScope getUseScope() { + return JSResolveUtil.findUseScope(this); + } + + @Override + @RequiredReadAction + public String getName() { + T stub = getStub(); + if (stub != null) { + return stub.getName(); + } + PsiElement name = getNameIdentifier(); + + if (name instanceof JSReferenceExpression refExpr) { + return refExpr.getReferencedName(); + } + return name != null ? name.getText() : ""; + } + + @Override + public JSAttributeList getAttributeList() { + if (getParent() instanceof JSVarStatement varStatement) { + return ((JSVarStatementImpl)varStatement).getStubOrPsiChild(JSElementTypes.ATTRIBUTE_LIST); + } + return null; + } + + @Override + public void setInitializer(JSExpression expr) throws IncorrectOperationException { + throw new UnsupportedOperationException("TODO: implement"); + } + + @Nonnull + @Override + @RequiredReadAction + public JavaScriptType getType() { + JSExpression initializer = getInitializer(); + if (initializer != null) { + if (initializer instanceof JSObjectLiteralExpression lit) { + return new JavaScriptSimpleType(getName(), lit); + } + + JavaScriptType javaScriptType = RecursionManager.doPreventingRecursion( + this, + false, + new Supplier() { + @Override + @RequiredReadAction + public JavaScriptType get() { + return initializer.getType(); + } + } + ); + return javaScriptType == null ? JavaScriptType.UNKNOWN : javaScriptType; + } + return JavaScriptType.UNKNOWN; + } + + @Override + @RequiredReadAction + public String getTypeString() { + T stub = getStub(); + return stub != null ? stub.getTypeString() : doGetType(); + } + + @RequiredReadAction + @Override + public JavaScriptTypeElement getTypeElement() { + return JSPsiImplUtils.findTypeElement(this); + } + + @RequiredReadAction + protected String doGetType() { + return JSPsiImplUtils.getType(this); + } + + @Override + @RequiredWriteAction + public PsiElement setName(@Nonnull String name) throws IncorrectOperationException { + PsiElement nameNode = getNameIdentifier(); + if (nameNode == null) { + return this; + } + ASTNode nameElement = JSChangeUtil.createNameIdentifier(getProject(), name); + getNode().replaceChild(nameNode.getNode(), nameElement); + return this; + } + + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSVariable(this); + } + + @RequiredReadAction + @Override + public int getTextOffset() { + PsiElement name = getNameIdentifier(); + return name != null ? name.getTextOffset() : super.getTextOffset(); + } + + @Override + @RequiredReadAction + public boolean isConst() { + T stub = getStub(); + if (stub != null) { + return stub.isConst(); + } + ASTNode parent = getNode().getTreeParent(); + + if (parent.getElementType() == JSElementTypes.VAR_STATEMENT) { + ASTNode node = parent.getFirstChildNode(); + IElementType type = node.getElementType(); + + if (type == JSElementTypes.ATTRIBUTE_LIST || type == JSElementTypes.REFERENCE_EXPRESSION) { + node = node.getTreeNext(); + + if (node != null && node.getElementType() == JSTokenTypes.WHITE_SPACE) { + node = node.getTreeNext(); + } + } + return node != null && node.getElementType() == JSTokenTypes.CONST_KEYWORD; + } + + return false; + } + + @Override + @RequiredReadAction + public boolean isLocal() { + T stub = getStub(); + if (stub != null) { + return stub.isLocal(); + } + ASTNode parent = getNode().getTreeParent(); + return parent.getElementType() == JSElementTypes.VAR_STATEMENT + && parent.getFirstChildNode().getElementType() == JSTokenTypes.LET_KEYWORD; + } + + @Override + public boolean isDeprecated() { + T stub = getStub(); + if (stub != null) { + return stub.isDeprecated(); + } + return JSDocumentationUtils.calculateDeprecated(this); + } + + @Override + @RequiredWriteAction + public void delete() throws IncorrectOperationException { + ASTNode myNode = getNode(); + ASTNode parent = myNode.getTreeParent(); + + if (parent.getElementType() == JSElementTypes.VAR_STATEMENT) { + JSVariable[] jsVariables = ((JSVarStatement)parent.getPsi()).getVariables(); + + if (jsVariables.length == 1) { + parent.getPsi().delete(); + } + else { + JSChangeUtil.removeRangeWithRemovalOfCommas(myNode, parent); + } + return; + } + + throw new IncorrectOperationException("Cannot delete variable from parent : " + parent.getElementType()); + } + + @Override + public boolean processDeclarations( + @Nonnull PsiScopeProcessor processor, + @Nonnull ResolveState state, + PsiElement lastParent, + @Nonnull PsiElement place + ) { + if (lastParent != null && lastParent.getParent() == this) { + processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, this); + } + return processor.execute(this, state); + } + + @Override + @RequiredReadAction + public String getQualifiedName() { + T stub = getStub(); + return stub != null ? stub.getQualifiedName() : JSPsiImplUtils.getQName(this); + } + + @Override + @RequiredReadAction + public PsiElement getNameIdentifier() { + return findChildByType(JavaScriptTokenSets.NAME_TOKEN_TYPES); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSVariableImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSVariableImpl.java index de9d3f11..3b0ade94 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSVariableImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSVariableImpl.java @@ -16,62 +16,54 @@ package com.intellij.lang.javascript.psi.impl; -import javax.annotation.Nonnull; - import com.intellij.lang.javascript.JSElementTypes; import com.intellij.lang.javascript.psi.JSClass; import com.intellij.lang.javascript.psi.JSPackageStatement; import com.intellij.lang.javascript.psi.JSVariable; import com.intellij.lang.javascript.psi.stubs.JSVariableStub; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.language.psi.PsiElement; import consulo.language.ast.ASTNode; import consulo.language.util.IncorrectOperationException; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 8:47:58 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSVariableImpl extends JSVariableBaseImpl -{ - public JSVariableImpl(final ASTNode node) - { - super(node); - } +public class JSVariableImpl extends JSVariableBaseImpl { + public JSVariableImpl(ASTNode node) { + super(node); + } - public JSVariableImpl(final JSVariableStub stub) - { - super(stub, JSElementTypes.VARIABLE); - } + public JSVariableImpl(JSVariableStub stub) { + super(stub, JSElementTypes.VARIABLE); + } - @Override - public PsiElement getNavigationElement() - { - PsiElement parent = getParent().getParent(); - if(parent instanceof JSClass) - { - PsiElement parentOriginalElement = parent.getNavigationElement(); + @Nonnull + @Override + @RequiredReadAction + public PsiElement getNavigationElement() { + if (getParent().getParent() instanceof JSClass jsClass) { + PsiElement parentOriginalElement = jsClass.getNavigationElement(); - if(parentOriginalElement != parent) - { - JSVariable jsVariable = ((JSClass) parentOriginalElement).findFieldByName(getName()); - return jsVariable != null ? jsVariable : this; - } - } - return JSPsiImplUtils.findTopLevelNavigatableElement(this); - } + if (parentOriginalElement != jsClass) { + JSVariable jsVariable = ((JSClass)parentOriginalElement).findFieldByName(getName()); + return jsVariable != null ? jsVariable : this; + } + } + return JSPsiImplUtils.findTopLevelNavigatableElement(this); + } - @Override - public PsiElement setName(@Nonnull String name) throws IncorrectOperationException - { - String oldName = getName(); - PsiElement element = super.setName(name); - if(getParent().getParent() instanceof JSPackageStatement) - { - JSPsiImplUtils.updateFileName(this, name, oldName); - } - return element; - } + @Override + @RequiredWriteAction + public PsiElement setName(@Nonnull String name) throws IncorrectOperationException { + String oldName = getName(); + PsiElement element = super.setName(name); + if (getParent().getParent() instanceof JSPackageStatement) { + JSPsiImplUtils.updateFileName(this, name, oldName); + } + return element; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSWhileStatementImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSWhileStatementImpl.java index 320bc5aa..a6fc239f 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSWhileStatementImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSWhileStatementImpl.java @@ -16,41 +16,37 @@ package com.intellij.lang.javascript.psi.impl; +import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.ASTNode; import com.intellij.lang.javascript.psi.JSElementVisitor; import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.JSStatement; import com.intellij.lang.javascript.psi.JSWhileStatement; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * User: max - * Date: Jan 30, 2005 - * Time: 10:15:13 PM + * @author max + * @since 2005-01-30 */ -public class JSWhileStatementImpl extends JSStatementImpl implements JSWhileStatement -{ - public JSWhileStatementImpl(final ASTNode node) - { - super(node); - } +public class JSWhileStatementImpl extends JSStatementImpl implements JSWhileStatement { + public JSWhileStatementImpl(ASTNode node) { + super(node); + } - @Override - public JSExpression getCondition() - { - return findChildByClass(JSExpression.class); - } + @Override + public JSExpression getCondition() { + return findChildByClass(JSExpression.class); + } - @Override - public JSStatement getBody() - { - return findChildByClass(JSStatement.class); - } + @Override + @RequiredReadAction + public JSStatement getBody() { + return findChildByClass(JSStatement.class); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSWhileStatement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSWhileStatement(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSWithStatementImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSWithStatementImpl.java index e59f792e..890faccd 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSWithStatementImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSWithStatementImpl.java @@ -21,38 +21,29 @@ import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.JSStatement; import com.intellij.lang.javascript.psi.JSWithStatement; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 30, 2005 - * Time: 9:54:56 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-30 */ -public class JSWithStatementImpl extends JSStatementImpl implements JSWithStatement -{ - public JSWithStatementImpl(final ASTNode node) - { - super(node); - } +public class JSWithStatementImpl extends JSStatementImpl implements JSWithStatement { + public JSWithStatementImpl(ASTNode node) { + super(node); + } - @Override - public JSExpression getExpression() - { - return findChildByClass(JSExpression.class); - } + @Override + public JSExpression getExpression() { + return findChildByClass(JSExpression.class); + } - @Override - public JSStatement getStatement() - { - return findChildByClass(JSStatement.class); - } + @Override + public JSStatement getStatement() { + return findChildByClass(JSStatement.class); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSWithStatement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSWithStatement(this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSXmlLiteralExpressionImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSXmlLiteralExpressionImpl.java index 6bb28569..d6b1df99 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSXmlLiteralExpressionImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSXmlLiteralExpressionImpl.java @@ -32,10 +32,9 @@ import consulo.language.psi.resolve.PsiElementProcessor; import consulo.language.util.IncorrectOperationException; import consulo.xml.psi.xml.*; -import org.jetbrains.annotations.NonNls; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -44,338 +43,298 @@ /** * @since Maxim.Mossienko */ -public class JSXmlLiteralExpressionImpl extends JSExpressionImpl implements JSLiteralExpression, XmlTag -{ - private static class LightXmlValue extends LightElement implements XmlTagValue - { - protected LightXmlValue(PsiManager manager, Language language) - { - super(manager, language); - } - - @Override - public TextRange getTextRange() - { - return TextRange.EMPTY_RANGE; - } - - @Nonnull - @Override - public XmlTagChild[] getChildren() - { - return XmlTagChild.EMPTY_ARRAY; - } - - @Override - public String toString() - { - return null; - } - - @Override - public int getTextOffset() - { - return 0; - } - - @Nonnull - @Override - public XmlText[] getTextElements() - { - return new XmlText[0]; - } - - @Nonnull - @Override - public String getTrimmedText() - { - return ""; - } - - @Override - public void setText(String s) - { - - } - - @Override - public void setEscapedText(String s) - { - - } - - @Override - public boolean hasCDATA() - { - return false; - } - } - - public JSXmlLiteralExpressionImpl(final ASTNode node) - { - super(node); - } - - @Nonnull - @Override - public PsiReference[] getReferences() - { - return ReferenceProvidersRegistry.getReferencesFromProviders(this); - } - - @RequiredReadAction - @Nonnull - @Override - public PsiElement[] getChildren() - { - PsiElement psiChild = getFirstChild(); - if(psiChild == null) - { - return PsiElement.EMPTY_ARRAY; - } - - List result = new ArrayList<>(); - while(psiChild != null) - { - result.add(psiChild); - - psiChild = psiChild.getNextSibling(); - } - return PsiUtilCore.toPsiElementArray(result); - } - - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSElement(this); - } - - @Override - @RequiredReadAction - public String getName() - { - PsiElement childByType = findChildByType(JSTokenTypes.XML_NAME); - return childByType != null ? childByType.getText() : ""; - } - - @RequiredWriteAction - @Override - public PsiElement setName(@Nonnull @NonNls String s) throws IncorrectOperationException - { - return null; - } - - @Nonnull - @Override - public String getNamespace() - { - return ""; - } - - @Nonnull - @Override - public String getLocalName() - { - return getName(); - } - - @Nullable - @Override - public XmlElementDescriptor getDescriptor() - { - return null; - } - - @Nonnull - @Override - public XmlAttribute[] getAttributes() - { - return new XmlAttribute[0]; - } - - @Nullable - @Override - public XmlAttribute getAttribute(@NonNls String name, @NonNls String namespace) - { - return null; - } - - @Nullable - @Override - public XmlAttribute getAttribute(@NonNls String qname) - { - return null; - } - - @Nullable - @Override - public String getAttributeValue(@NonNls String name, @NonNls String namespace) - { - return null; - } - - @Nullable - @Override - public String getAttributeValue(@NonNls String qname) - { - return null; - } - - @Override - public XmlAttribute setAttribute(@NonNls String name, @NonNls String namespace, @NonNls String value) throws IncorrectOperationException - { - return null; - } - - @Override - public XmlAttribute setAttribute(@NonNls String qname, @NonNls String value) throws IncorrectOperationException - { - return null; - } - - @Override - public XmlTag createChildTag(@NonNls String localName, @NonNls String namespace, @Nullable @NonNls String bodyText, boolean enforceNamespacesDeep) - { - return null; - } - - @Override - public XmlTag addSubTag(XmlTag subTag, boolean first) - { - return null; - } - - @Nonnull - @Override - public XmlTag[] getSubTags() - { - return new XmlTag[0]; - } - - @Nonnull - @Override - public XmlTag[] findSubTags(@NonNls String qname) - { - return new XmlTag[0]; - } - - @Nonnull - @Override - public XmlTag[] findSubTags(@NonNls String localName, @Nullable String namespace) - { - return new XmlTag[0]; - } - - @Nullable - @Override - public XmlTag findFirstSubTag(@NonNls String qname) - { - return null; - } - - @Nonnull - @Override - public String getNamespacePrefix() - { - return ""; - } - - @Nonnull - @Override - public String getNamespaceByPrefix(@NonNls String prefix) - { - return ""; - } - - @Nullable - @Override - public String getPrefixByNamespace(@NonNls String namespace) - { - return null; - } - - @Override - public String[] knownNamespaces() - { - return new String[0]; - } - - @Override - public boolean hasNamespaceDeclarations() - { - return false; - } - - @Nonnull - @Override - public Map getLocalNamespaceDeclarations() - { - return Collections.emptyMap(); - } - - @Nonnull - @Override - public XmlTagValue getValue() - { - return new LightXmlValue(getManager(), getLanguage()); - } - - @Nullable - @Override - public XmlNSDescriptor getNSDescriptor(@NonNls String namespace, boolean strict) - { - return null; - } - - @Override - public boolean isEmpty() - { - return true; - } - - @Override - public void collapseIfEmpty() - { - - } - - @Nullable - @Override - public String getSubTagText(@NonNls String qname) - { - return null; - } - - @Nullable - @Override - public PsiMetaData getMetaData() - { - return null; - } - - @Override - public XmlTag getParentTag() - { - return null; - } - - @Nullable - @Override - public XmlTagChild getNextSiblingInTag() - { - return null; - } - - @Nullable - @Override - public XmlTagChild getPrevSiblingInTag() - { - return null; - } - - @Override - public boolean processElements(PsiElementProcessor processor, PsiElement place) - { - return false; - } +public class JSXmlLiteralExpressionImpl extends JSExpressionImpl implements JSLiteralExpression, XmlTag { + private static class LightXmlValue extends LightElement implements XmlTagValue { + protected LightXmlValue(PsiManager manager, Language language) { + super(manager, language); + } + + @Nonnull + @Override + @RequiredReadAction + public TextRange getTextRange() { + return TextRange.EMPTY_RANGE; + } + + @Nonnull + @Override + @RequiredReadAction + public XmlTagChild[] getChildren() { + return XmlTagChild.EMPTY_ARRAY; + } + + @Override + public String toString() { + return null; + } + + @Override + public int getTextOffset() { + return 0; + } + + @Nonnull + @Override + public XmlText[] getTextElements() { + return new XmlText[0]; + } + + @Nonnull + @Override + public String getTrimmedText() { + return ""; + } + + @Override + public void setText(String s) { + + } + + @Override + public void setEscapedText(String s) { + + } + + @Override + public boolean hasCDATA() { + return false; + } + } + + public JSXmlLiteralExpressionImpl(ASTNode node) { + super(node); + } + + @Nonnull + @Override + public PsiReference[] getReferences() { + return ReferenceProvidersRegistry.getReferencesFromProviders(this); + } + + @RequiredReadAction + @Nonnull + @Override + public PsiElement[] getChildren() { + PsiElement psiChild = getFirstChild(); + if (psiChild == null) { + return PsiElement.EMPTY_ARRAY; + } + + List result = new ArrayList<>(); + while (psiChild != null) { + result.add(psiChild); + + psiChild = psiChild.getNextSibling(); + } + return PsiUtilCore.toPsiElementArray(result); + } + + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSElement(this); + } + + @Nonnull + @Override + @RequiredReadAction + public String getName() { + PsiElement childByType = findChildByType(JSTokenTypes.XML_NAME); + return childByType != null ? childByType.getText() : ""; + } + + @RequiredWriteAction + @Override + public PsiElement setName(@Nonnull String s) throws IncorrectOperationException { + return null; + } + + @Nonnull + @Override + public String getNamespace() { + return ""; + } + + @Nonnull + @Override + @RequiredReadAction + public String getLocalName() { + return getName(); + } + + @Nullable + @Override + public XmlElementDescriptor getDescriptor() { + return null; + } + + @Nonnull + @Override + public XmlAttribute[] getAttributes() { + return new XmlAttribute[0]; + } + + @Nullable + @Override + public XmlAttribute getAttribute(String name, String namespace) { + return null; + } + + @Nullable + @Override + public XmlAttribute getAttribute(String qname) { + return null; + } + + @Nullable + @Override + public String getAttributeValue(String name, String namespace) { + return null; + } + + @Nullable + @Override + public String getAttributeValue(String qname) { + return null; + } + + @Override + public XmlAttribute setAttribute(String name, String namespace, String value) + throws IncorrectOperationException { + return null; + } + + @Override + public XmlAttribute setAttribute(String qname, String value) throws IncorrectOperationException { + return null; + } + + @Override + public XmlTag createChildTag(String localName, String namespace, @Nullable String bodyText, boolean enforceNamespacesDeep) { + return null; + } + + @Override + public XmlTag addSubTag(XmlTag subTag, boolean first) { + return null; + } + + @Nonnull + @Override + public XmlTag[] getSubTags() { + return new XmlTag[0]; + } + + @Nonnull + @Override + public XmlTag[] findSubTags(String qname) { + return new XmlTag[0]; + } + + @Nonnull + @Override + public XmlTag[] findSubTags(String localName, @Nullable String namespace) { + return new XmlTag[0]; + } + + @Nullable + @Override + public XmlTag findFirstSubTag(String qname) { + return null; + } + + @Nonnull + @Override + public String getNamespacePrefix() { + return ""; + } + + @Nonnull + @Override + public String getNamespaceByPrefix(String prefix) { + return ""; + } + + @Nullable + @Override + public String getPrefixByNamespace(String namespace) { + return null; + } + + @Override + public String[] knownNamespaces() { + return new String[0]; + } + + @Override + public boolean hasNamespaceDeclarations() { + return false; + } + + @Nonnull + @Override + public Map getLocalNamespaceDeclarations() { + return Collections.emptyMap(); + } + + @RequiredReadAction + @Override + public int getTextOffset() { + return 0; + } + + @Nonnull + @Override + public XmlTagValue getValue() { + return new LightXmlValue(getManager(), getLanguage()); + } + + @Nullable + @Override + public XmlNSDescriptor getNSDescriptor(String namespace, boolean strict) { + return null; + } + + @Override + public boolean isEmpty() { + return true; + } + + @Override + public void collapseIfEmpty() { + + } + + @Nullable + @Override + public String getSubTagText(String qname) { + return null; + } + + @Nullable + @Override + public PsiMetaData getMetaData() { + return null; + } + + @Override + public XmlTag getParentTag() { + return null; + } + + @Nullable + @Override + public XmlTagChild getNextSiblingInTag() { + return null; + } + + @Nullable + @Override + public XmlTagChild getPrevSiblingInTag() { + return null; + } + + @Override + public boolean processElements(PsiElementProcessor processor, PsiElement place) { + return false; + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSYieldStatementImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSYieldStatementImpl.java index 9dc2d9c9..97410bc5 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSYieldStatementImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JSYieldStatementImpl.java @@ -21,27 +21,23 @@ import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.JSYieldStatement; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author maxim */ -public class JSYieldStatementImpl extends JSStatementImpl implements JSYieldStatement -{ - public JSYieldStatementImpl(final ASTNode node) - { - super(node); - } +public class JSYieldStatementImpl extends JSStatementImpl implements JSYieldStatement { + public JSYieldStatementImpl(ASTNode node) { + super(node); + } - @Override - public JSExpression getExpression() - { - return findChildByClass(JSExpression.class); - } + @Override + public JSExpression getExpression() { + return findChildByClass(JSExpression.class); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSYieldStatement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSYieldStatement(this); + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JavaScriptSimpleType.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JavaScriptSimpleType.java new file mode 100644 index 00000000..52cb8d41 --- /dev/null +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/JavaScriptSimpleType.java @@ -0,0 +1,55 @@ +/* + * Copyright 2013-2015 must-be.org + * + * 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.lang.javascript.psi.impl; + +import consulo.annotation.access.RequiredReadAction; +import consulo.javascript.language.psi.JavaScriptType; +import consulo.language.psi.PsiElement; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; + +/** + * @author VISTALL + * @since 2015-12-13 + */ +public class JavaScriptSimpleType implements JavaScriptType { + private String myReferenceName; + private PsiElement myElement; + + public JavaScriptSimpleType(@Nonnull String referenceName, @Nullable PsiElement element) { + myReferenceName = referenceName; + myElement = element; + } + + @RequiredReadAction + @Nonnull + @Override + public String getPresentableText() { + return myReferenceName; + } + + @Nullable + @Override + public PsiElement getTargetElement() { + return myElement; + } + + @Override + public String toString() { + return "JavaScriptSimpleType: " + myReferenceName; + } +} diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/ReferenceSupport.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/ReferenceSupport.java index a5726e1f..91aa0016 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/ReferenceSupport.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/ReferenceSupport.java @@ -16,6 +16,7 @@ package com.intellij.lang.javascript.psi.impl; +import consulo.annotation.access.RequiredReadAction; import consulo.application.util.SystemInfo; import consulo.content.base.BinariesOrderRootType; import consulo.language.psi.*; @@ -27,6 +28,7 @@ import consulo.module.content.ProjectRootManager; import consulo.module.content.layer.orderEntry.OrderEntry; import consulo.module.content.layer.orderEntry.OrderEntryWithTracking; +import consulo.platform.Platform; import consulo.project.Project; import consulo.util.lang.StringUtil; import consulo.virtualFileSystem.LocalFileSystem; @@ -38,189 +40,162 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; -import java.util.function.Function; /** - * Created by IntelliJ IDEA. - * User: Maxim.Mossienko - * Date: 08.04.2009 - * Time: 20:48:38 - * To change this template use File | Settings | File Templates. + * @author Maxim.Mossienko + * @since 2009-04-08 */ -public class ReferenceSupport -{ - - public static PsiReference[] getFileRefs(final PsiElement elt, final PsiElement valueNode, final int offset, final LookupOptions lookupOptions) - { - String str = StringUtil.stripQuotesAroundValue(valueNode.getText()); - return getFileRefs(elt, offset, str, lookupOptions); - } - - public static PsiReference[] getFileRefs(final PsiElement elt, final int offset, String str, final LookupOptions lookupOptions) - { - - if(lookupOptions.IGNORE_TEXT_ARTER_HASH) - { - int hashIndex = str.indexOf('#'); - if(hashIndex != -1) - { - str = str.substring(0, hashIndex); - } - } - - final FileReferenceSet base = new FileReferenceSet(str, elt, offset, null, SystemInfo.isFileSystemCaseSensitive); - - final boolean lookForAbsolutePath = lookupOptions.ABSOLUTE && new File(str).isAbsolute(); - final boolean startsWithSlash = str.startsWith("/"); - - base.addCustomization(FileReferenceSet.DEFAULT_PATH_EVALUATOR_OPTION, new Function>() - { - @Override - public Collection apply(PsiFile psiFile) - { - final PsiElement context = psiFile.getContext(); - if(context instanceof PsiLanguageInjectionHost) - { - psiFile = context.getContainingFile(); - } - PsiFile originalFile = psiFile.getOriginalFile(); - if(originalFile != null) - { - psiFile = originalFile; - } - - final List dirs = new ArrayList(); - - // paths relative to file should not start with slash - if(lookupOptions.RELATIVE_TO_FILE && !startsWithSlash) - { - appendFileLocation(dirs, psiFile); - } - - if((lookupOptions.RELATIVE_TO_SOURCE_ROOTS_START_WITH_SLASH && startsWithSlash) || (lookupOptions.RELATIVE_TO_SOURCE_ROOTS_START_WITHOUT_SLASH - && !startsWithSlash)) - { - appendSourceRoots(dirs, psiFile); - } - - if(lookForAbsolutePath) - { - appendFileSystemRoot(dirs, psiFile.getProject()); - } - - if(lookupOptions.RELATIVE_TO_PROJECT_BASE_DIR) - { - dirs.add(psiFile.getProject().getBaseDir()); - } - - if(lookupOptions.IN_SDK_AND_LIBRARY_CLASS_ROOTS) - { - appendSdkAndLibraryClassRoots(dirs, psiFile); - } - - final Collection result = new ArrayList(); - final PsiManager psiManager = PsiManager.getInstance(psiFile.getProject()); - for(final VirtualFile dir : dirs) - { - if(dir != null) - { - final PsiDirectory psiDir = psiManager.findDirectory(dir); - if(psiDir != null) - { - result.add(psiDir); - } - } - } - return result; - } - }); - return base.getAllReferences(); - } - - private static void appendFileLocation(final List dirs, final PsiFile psiFile) - { - final VirtualFile file = psiFile.getVirtualFile(); - if(file != null) - { - dirs.add(file.getParent()); - } - } - - private static void appendSourceRoots(final Collection dirs, final PsiFile psiFile) - { - final VirtualFile file = psiFile.getVirtualFile(); - if(file == null) - { - return; - } - final Project project = psiFile.getProject(); - final ProjectFileIndex index = ProjectRootManager.getInstance(project).getFileIndex(); - final Module module = index.getModuleForFile(file); - if(module != null && index.getSourceRootForFile(file) != null) - { - dirs.addAll(Arrays.asList(ModuleRootManager.getInstance(module).getSourceRoots())); - } - } - - private static void appendFileSystemRoot(final Collection dirs, final Project project) - { - final VirtualFile fileSystemRoot; - if(SystemInfo.isWindows) - { - fileSystemRoot = ManagingFS.getInstance().findRoot("", LocalFileSystem.getInstance()); - } - else - { - fileSystemRoot = LocalFileSystem.getInstance().findFileByPath("/"); - } - dirs.add(fileSystemRoot); - } - - private static void appendSdkAndLibraryClassRoots(List dirs, PsiFile psiFile) - { - final Module module = ModuleUtilCore.findModuleForPsiElement(psiFile); - if(module != null) - { - final OrderEntry[] orderEntries = ModuleRootManager.getInstance(module).getOrderEntries(); - for(final OrderEntry orderEntry : orderEntries) - { - if(orderEntry instanceof OrderEntryWithTracking) - { - dirs.addAll(Arrays.asList(orderEntry.getFiles(BinariesOrderRootType.getInstance()))); - } - } - } - } - - public static class LookupOptions - { - // default is absolute or relative to current file - public static final LookupOptions DEFAULT = new LookupOptions(false, true, true, false, false, false, false); - public static final LookupOptions MX_STYLE_SOURCE = new LookupOptions(false, true, true, true, true, false, true); - public static final LookupOptions EMBEDDED_ASSET = new LookupOptions(true, true, true, true, true, false, true); - public static final LookupOptions NON_EMBEDDED_ASSET = new LookupOptions(false, true, false, false, true, false, false); - public static final LookupOptions FLEX_COMPILER_CONFIG_PATH_ELEMENT = new LookupOptions(false, true, true, false, false, true, false); - - public final boolean IGNORE_TEXT_ARTER_HASH; - public final boolean ABSOLUTE; - public final boolean RELATIVE_TO_FILE; - public final boolean RELATIVE_TO_SOURCE_ROOTS_START_WITH_SLASH; - public final boolean RELATIVE_TO_SOURCE_ROOTS_START_WITHOUT_SLASH; - public final boolean RELATIVE_TO_PROJECT_BASE_DIR; // better name would be RELATIVE_TO_FCSH_START_DIR but FlexUtils.getFlexCompilerStartDirectory - // () is not accessible from this class - public final boolean IN_SDK_AND_LIBRARY_CLASS_ROOTS; - - public LookupOptions(boolean IGNORE_TEXT_ARTER_HASH, boolean ABSOLUTE, boolean RELATIVE_TO_FILE, - boolean RELATIVE_TO_SOURCE_ROOTS_START_WITH_SLASH, boolean RELATIVE_TO_SOURCE_ROOTS_START_WITHOUT_SLASH, boolean RELATIVE_TO_PROJECT_BASE_DIR, - boolean IN_SDK_AND_LIBRARY_CLASS_ROOTS) - { - this.IGNORE_TEXT_ARTER_HASH = IGNORE_TEXT_ARTER_HASH; - this.ABSOLUTE = ABSOLUTE; - this.RELATIVE_TO_FILE = RELATIVE_TO_FILE; - this.RELATIVE_TO_SOURCE_ROOTS_START_WITH_SLASH = RELATIVE_TO_SOURCE_ROOTS_START_WITH_SLASH; - this.RELATIVE_TO_SOURCE_ROOTS_START_WITHOUT_SLASH = RELATIVE_TO_SOURCE_ROOTS_START_WITHOUT_SLASH; - this.RELATIVE_TO_PROJECT_BASE_DIR = RELATIVE_TO_PROJECT_BASE_DIR; - this.IN_SDK_AND_LIBRARY_CLASS_ROOTS = IN_SDK_AND_LIBRARY_CLASS_ROOTS; - } - } +public class ReferenceSupport { + @RequiredReadAction + public static PsiReference[] getFileRefs(PsiElement elt, PsiElement valueNode, int offset, LookupOptions lookupOptions) { + String str = StringUtil.stripQuotesAroundValue(valueNode.getText()); + return getFileRefs(elt, offset, str, lookupOptions); + } + + public static PsiReference[] getFileRefs(PsiElement elt, int offset, String str, LookupOptions lookupOptions) { + if (lookupOptions.IGNORE_TEXT_ARTER_HASH) { + int hashIndex = str.indexOf('#'); + if (hashIndex != -1) { + str = str.substring(0, hashIndex); + } + } + + FileReferenceSet base = new FileReferenceSet(str, elt, offset, null, SystemInfo.isFileSystemCaseSensitive); + + boolean lookForAbsolutePath = lookupOptions.ABSOLUTE && new File(str).isAbsolute(); + boolean startsWithSlash = str.startsWith("/"); + + base.addCustomization( + FileReferenceSet.DEFAULT_PATH_EVALUATOR_OPTION, + psiFile -> { + PsiElement context = psiFile.getContext(); + if (context instanceof PsiLanguageInjectionHost languageInjectionHost) { + psiFile = languageInjectionHost.getContainingFile(); + } + PsiFile originalFile = psiFile.getOriginalFile(); + if (originalFile != null) { + psiFile = originalFile; + } + + List dirs = new ArrayList<>(); + + // paths relative to file should not start with slash + if (lookupOptions.RELATIVE_TO_FILE && !startsWithSlash) { + appendFileLocation(dirs, psiFile); + } + + if ((lookupOptions.RELATIVE_TO_SOURCE_ROOTS_START_WITH_SLASH && startsWithSlash) + || (lookupOptions.RELATIVE_TO_SOURCE_ROOTS_START_WITHOUT_SLASH && !startsWithSlash)) { + appendSourceRoots(dirs, psiFile); + } + + if (lookForAbsolutePath) { + appendFileSystemRoot(dirs, psiFile.getProject()); + } + + if (lookupOptions.RELATIVE_TO_PROJECT_BASE_DIR) { + dirs.add(psiFile.getProject().getBaseDir()); + } + + if (lookupOptions.IN_SDK_AND_LIBRARY_CLASS_ROOTS) { + appendSdkAndLibraryClassRoots(dirs, psiFile); + } + + Collection result = new ArrayList<>(); + PsiManager psiManager = PsiManager.getInstance(psiFile.getProject()); + for (VirtualFile dir : dirs) { + if (dir != null) { + PsiDirectory psiDir = psiManager.findDirectory(dir); + if (psiDir != null) { + result.add(psiDir); + } + } + } + return result; + } + ); + return base.getAllReferences(); + } + + private static void appendFileLocation(List dirs, PsiFile psiFile) { + VirtualFile file = psiFile.getVirtualFile(); + if (file != null) { + dirs.add(file.getParent()); + } + } + + private static void appendSourceRoots(Collection dirs, PsiFile psiFile) { + VirtualFile file = psiFile.getVirtualFile(); + if (file == null) { + return; + } + Project project = psiFile.getProject(); + ProjectFileIndex index = ProjectRootManager.getInstance(project).getFileIndex(); + Module module = index.getModuleForFile(file); + if (module != null && index.getSourceRootForFile(file) != null) { + dirs.addAll(Arrays.asList(ModuleRootManager.getInstance(module).getSourceRoots())); + } + } + + private static void appendFileSystemRoot(Collection dirs, Project project) { + VirtualFile fileSystemRoot; + if (Platform.current().os().isWindows()) { + fileSystemRoot = ManagingFS.getInstance().findRoot("", LocalFileSystem.getInstance()); + } + else { + fileSystemRoot = LocalFileSystem.getInstance().findFileByPath("/"); + } + dirs.add(fileSystemRoot); + } + + @RequiredReadAction + private static void appendSdkAndLibraryClassRoots(List dirs, PsiFile psiFile) { + Module module = ModuleUtilCore.findModuleForPsiElement(psiFile); + if (module != null) { + OrderEntry[] orderEntries = ModuleRootManager.getInstance(module).getOrderEntries(); + for (OrderEntry orderEntry : orderEntries) { + if (orderEntry instanceof OrderEntryWithTracking) { + dirs.addAll(Arrays.asList(orderEntry.getFiles(BinariesOrderRootType.getInstance()))); + } + } + } + } + + public static class LookupOptions { + // default is absolute or relative to current file + public static final LookupOptions DEFAULT = new LookupOptions(false, true, true, false, false, false, false); + public static final LookupOptions MX_STYLE_SOURCE = new LookupOptions(false, true, true, true, true, false, true); + public static final LookupOptions EMBEDDED_ASSET = new LookupOptions(true, true, true, true, true, false, true); + public static final LookupOptions NON_EMBEDDED_ASSET = new LookupOptions(false, true, false, false, true, false, false); + public static final LookupOptions FLEX_COMPILER_CONFIG_PATH_ELEMENT = + new LookupOptions(false, true, true, false, false, true, false); + + public final boolean IGNORE_TEXT_ARTER_HASH; + public final boolean ABSOLUTE; + public final boolean RELATIVE_TO_FILE; + public final boolean RELATIVE_TO_SOURCE_ROOTS_START_WITH_SLASH; + public final boolean RELATIVE_TO_SOURCE_ROOTS_START_WITHOUT_SLASH; + public final boolean RELATIVE_TO_PROJECT_BASE_DIR; + // better name would be RELATIVE_TO_FCSH_START_DIR but FlexUtils.getFlexCompilerStartDirectory + // () is not accessible from this class + public final boolean IN_SDK_AND_LIBRARY_CLASS_ROOTS; + + public LookupOptions( + boolean IGNORE_TEXT_ARTER_HASH, + boolean ABSOLUTE, + boolean RELATIVE_TO_FILE, + boolean RELATIVE_TO_SOURCE_ROOTS_START_WITH_SLASH, + boolean RELATIVE_TO_SOURCE_ROOTS_START_WITHOUT_SLASH, + boolean RELATIVE_TO_PROJECT_BASE_DIR, + boolean IN_SDK_AND_LIBRARY_CLASS_ROOTS + ) { + this.IGNORE_TEXT_ARTER_HASH = IGNORE_TEXT_ARTER_HASH; + this.ABSOLUTE = ABSOLUTE; + this.RELATIVE_TO_FILE = RELATIVE_TO_FILE; + this.RELATIVE_TO_SOURCE_ROOTS_START_WITH_SLASH = RELATIVE_TO_SOURCE_ROOTS_START_WITH_SLASH; + this.RELATIVE_TO_SOURCE_ROOTS_START_WITHOUT_SLASH = RELATIVE_TO_SOURCE_ROOTS_START_WITHOUT_SLASH; + this.RELATIVE_TO_PROJECT_BASE_DIR = RELATIVE_TO_PROJECT_BASE_DIR; + this.IN_SDK_AND_LIBRARY_CLASS_ROOTS = IN_SDK_AND_LIBRARY_CLASS_ROOTS; + } + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/reference/JSPropertyNameReference.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/reference/JSPropertyNameReference.java index aba9d663..4f967f5f 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/reference/JSPropertyNameReference.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/impl/reference/JSPropertyNameReference.java @@ -31,107 +31,91 @@ import consulo.language.util.IncorrectOperationException; import consulo.util.lang.StringUtil; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public class JSPropertyNameReference implements PsiReference -{ - private final JSProperty myProperty; - private final PsiElement myNameIdentifier; - - public JSPropertyNameReference(JSProperty property, PsiElement nameIdentifier) - { - this.myProperty = property; - myNameIdentifier = nameIdentifier; - } - - @Override - public PsiElement getElement() - { - return myNameIdentifier; - } - - @Override - @RequiredReadAction - public TextRange getRangeInElement() - { - int quotesDelta = myNameIdentifier.getNode().getElementType() == JSTokenTypes.STRING_LITERAL ? 1 : 0; - final int startOffsetInParent = myNameIdentifier.getStartOffsetInParent(); - int startOffset = startOffsetInParent + quotesDelta; - int endOffset = startOffsetInParent + myNameIdentifier.getTextLength() - quotesDelta; - if(endOffset <= startOffset) - { - return new TextRange(0, myProperty.getTextLength()); - } - return new TextRange(startOffset, endOffset); - } - - @Override - @Nullable - public PsiElement resolve() - { - return myProperty; - } - - @Nonnull - @Override - @RequiredReadAction - public String getCanonicalText() - { - return StringUtil.stripQuotesAroundValue(myNameIdentifier.getText()); - } - - @Override - public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException - { - myProperty.setName(newElementName); - return null; - } - - @Override - public PsiElement bindToElement(@Nonnull PsiElement element) throws IncorrectOperationException - { - return null; - } - - @Override - @RequiredReadAction - public boolean isReferenceTo(PsiElement element) - { - final PsiElement element2 = resolve(); - boolean proxyExpanded = false; - - if(element instanceof JSDefinitionExpression) - { - final JSExpression expression = ((JSDefinitionExpression) element).getExpression(); - if(expression instanceof JSReferenceExpression) - { - return ((JSReferenceExpression) expression).isReferenceTo(element2); - } - } - - if(element != element2 && element instanceof JSProperty && element2 instanceof JSProperty) - { - return ((JSProperty) element).getName().equals(((JSProperty) element2).getName()); - } - return proxyExpanded && element == element2; - } - - @Nonnull - @Override - @RequiredReadAction - public Object[] getVariants() - { - final VariantsProcessor processor = new VariantsProcessor(null, myProperty.getContainingFile(), false, myProperty); - - JSResolveUtil.processGlobalSymbols(myProperty, processor); - - return processor.getResult(); - } - - @Override - public boolean isSoft() - { - return true; - } +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; + +public class JSPropertyNameReference implements PsiReference { + private final JSProperty myProperty; + private final PsiElement myNameIdentifier; + + public JSPropertyNameReference(JSProperty property, PsiElement nameIdentifier) { + this.myProperty = property; + myNameIdentifier = nameIdentifier; + } + + @Override + public PsiElement getElement() { + return myNameIdentifier; + } + + @Override + @RequiredReadAction + public TextRange getRangeInElement() { + int quotesDelta = myNameIdentifier.getNode().getElementType() == JSTokenTypes.STRING_LITERAL ? 1 : 0; + int startOffsetInParent = myNameIdentifier.getStartOffsetInParent(); + int startOffset = startOffsetInParent + quotesDelta; + int endOffset = startOffsetInParent + myNameIdentifier.getTextLength() - quotesDelta; + if (endOffset <= startOffset) { + return new TextRange(0, myProperty.getTextLength()); + } + return new TextRange(startOffset, endOffset); + } + + @Override + @Nullable + public PsiElement resolve() { + return myProperty; + } + + @Nonnull + @Override + @RequiredReadAction + public String getCanonicalText() { + return StringUtil.stripQuotesAroundValue(myNameIdentifier.getText()); + } + + @Override + public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException { + myProperty.setName(newElementName); + return null; + } + + @Override + public PsiElement bindToElement(@Nonnull PsiElement element) throws IncorrectOperationException { + return null; + } + + @Override + @RequiredReadAction + public boolean isReferenceTo(PsiElement element) { + PsiElement element2 = resolve(); + boolean proxyExpanded = false; + + if (element instanceof JSDefinitionExpression definition + && definition.getExpression() instanceof JSReferenceExpression referenceExpression) { + return referenceExpression.isReferenceTo(element2); + } + + if (element != element2 && element instanceof JSProperty elem1Prop && element2 instanceof JSProperty elem2Prop) { + return elem1Prop.getName().equals(elem2Prop.getName()); + } + return proxyExpanded && element == element2; + } + + @Nonnull + @Override + @RequiredReadAction + public Object[] getVariants() { + VariantsProcessor processor = + new VariantsProcessor(null, myProperty.getContainingFile(), false, myProperty); + + JSResolveUtil.processGlobalSymbols(myProperty, processor); + + return processor.getResult(); + } + + @Override + public boolean isSoft() { + return true; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/BaseJSSymbolProcessor.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/BaseJSSymbolProcessor.java index f83d484a..6db49aa8 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/BaseJSSymbolProcessor.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/BaseJSSymbolProcessor.java @@ -21,10 +21,12 @@ import com.intellij.lang.javascript.index.JSSymbolUtil; import com.intellij.lang.javascript.index.JSTypeEvaluateManager; import com.intellij.lang.javascript.psi.*; +import consulo.annotation.access.RequiredReadAction; import consulo.document.util.TextRange; -import consulo.javascript.language.JavaScriptFeature; import consulo.javascript.lang.JavaScriptTokenSets; +import consulo.javascript.language.JavaScriptFeature; import consulo.javascript.language.JavaScriptVersionUtil; +import consulo.javascript.language.psi.JavaScriptType; import consulo.language.ast.ASTNode; import consulo.language.ast.IElementType; import consulo.language.inject.InjectedLanguageManager; @@ -42,9 +44,8 @@ import consulo.xml.psi.xml.XmlFile; import consulo.xml.psi.xml.XmlTag; import consulo.xml.psi.xml.XmlToken; -import org.jetbrains.annotations.NonNls; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -53,1200 +54,1008 @@ /** * @author Maxim.Mossienko */ -abstract public class BaseJSSymbolProcessor implements PsiScopeProcessor -{ - protected final PsiFile myTargetFile; - protected PsiFile myCurrentFile; - protected final boolean mySkipDclsInTargetFile; - protected final PsiElement myContext; - protected final String myWindowIndex; - protected final String myFunctionIndex; - - protected String[] myContextNameIds; - @Deprecated - protected boolean ecmal4; - protected Set myFeatures; - protected boolean myDefinitelyGlobalReference; - protected boolean myDefinitelyNonglobalReference; - protected boolean myAddOnlyCompleteMatches; - protected boolean myAllowPartialResults = true; - - @NonNls - private static final String ANY_TYPE = "*"; - @NonNls - public static final String ARRAY_TYPE_NAME = "Array"; - @NonNls - public static final String STRING_TYPE_NAME = "String"; - @NonNls - public static final String REG_EXP_TYPE_NAME = "RegExp"; - @NonNls - public static final String XML_TYPE_NAME = "XML"; - @NonNls - public static final String XML_LIST_TYPE_NAME = "XMLList"; - @NonNls - public static final String NUMBER_TYPE_NAME = "Number"; - @NonNls - public static final String FUNCTION_TYPE_NAME = "Function"; - @NonNls - public static final String HTML_ELEMENT_TYPE_NAME = "HTMLElement"; - @NonNls - private static final String INT_TYPE = "int"; - @NonNls - private static final String BOOLEAN_TYPE_NAME = "Boolean"; - protected String myIteratedTypeName; - - protected BaseJSSymbolProcessor(final PsiFile targetFile, final boolean skipDclsInTargetFile, final PsiElement context, String[] contextIds) - { - myTargetFile = targetFile; - mySkipDclsInTargetFile = skipDclsInTargetFile; - myContext = context; - - myWindowIndex = "window"; - myFunctionIndex = "Function"; - - myFeatures = JavaScriptVersionUtil.getFeatures(targetFile); - ecmal4 = myFeatures.contains(JavaScriptFeature.CLASS); - - if(contextIds == null && context instanceof JSReferenceExpression) - { - contextIds = calculateContextIds((JSReferenceExpression) context); - } - - if(contextIds == null) - { // TODO: workaround for NPE - contextIds = new String[0]; - } - - myContextNameIds = contextIds; - - final boolean notWithinWithStatement = PsiTreeUtil.getParentOfType(myContext, JSWithStatement.class) == null; - - if(((contextIds == null || contextIds.length == 0) && - myContext instanceof JSReferenceExpression && - ((JSReferenceExpression) myContext).getQualifier() == null && notWithinWithStatement && - JSResolveUtil.getRealRefExprQualifier((JSReferenceExpression) myContext) == null) || (contextIds != null && contextIds.length == 1 && - contextIds[0].equals(myWindowIndex) && notWithinWithStatement)) - { - myDefinitelyGlobalReference = true; - } - - if(contextIds != null && (contextIds.length > 1 || (contextIds.length == 1 && - contextIds[0].length() > 0 && - !contextIds[0].equals(myWindowIndex)))) - { - myDefinitelyNonglobalReference = true; - } - } - - protected abstract String[] calculateContextIds(final JSReferenceExpression jsReferenceExpression); - - public void setAddOnlyCompleteMatches(final boolean addOnlyCompleteMatches) - { - myAddOnlyCompleteMatches = addOnlyCompleteMatches; - myAllowPartialResults = false; - } - - - protected boolean isFromRelevantFileOrDirectory() - { - final PsiFile psiFile = myCurrentFile; - - return myTargetFile == psiFile || false; - //(myTargetFile != null && - // psiFile != null && - // myTargetFile.getContainingDirectory() == psiFile.getContainingDirectory() - //); - } - - private static ThreadLocal contextHolder = new ThreadLocal(); - - public static void doEvalForExpr(JSExpression rawqualifier, final PsiFile myTargetFile, TypeProcessor typeProcessor) - { - EvaluateContext context = contextHolder.get(); - boolean contextHolderInitialized = false; - - if(context == null) - { - context = new EvaluateContext(myTargetFile); - contextHolder.set(context); - contextHolderInitialized = true; - } - else if(context.isAlreadyProcessingItem(rawqualifier)) - { - return; - } - else - { - context.addProcessingItem(rawqualifier); - } - - try - { - doEvalForExpr(rawqualifier, typeProcessor, contextHolderInitialized ? context : new EvaluateContext(myTargetFile)); - } - finally - { - if(!contextHolderInitialized) - { - context.removeProcessingItem(rawqualifier); - } - if(contextHolderInitialized) - { - contextHolder.set(null); - } - } - } - - public static JSExpression getOriginalQualifier(JSExpression rawqualifier) - { - if(rawqualifier instanceof JSReferenceExpression) - { - JSReferenceExpression qualifier = ((JSReferenceExpression) rawqualifier); - final TextRange textRange = qualifier.getTextRange(); - PsiFile targetFile = rawqualifier.getContainingFile(); - final PsiElement context = targetFile.getContext(); - if(context != null) - { - targetFile = context.getContainingFile(); - } - - PsiFile originalFile = targetFile.getOriginalFile(); - - if(!targetFile.isPhysical() && originalFile != null) - { - PsiElement startElement; - if(context != null) - { - final PsiElement at = PsiTreeUtil.getNonStrictParentOfType(originalFile.findElementAt(context.getTextOffset()), PsiLanguageInjectionHost.class); - if(at instanceof PsiLanguageInjectionHost) - { - List> injectedPsiFiles = InjectedLanguageManager.getInstance(at.getProject()).getInjectedPsiFiles(at); - if(injectedPsiFiles != null) - { - for(Pair pair : injectedPsiFiles) - { - if(pair.getFirst() instanceof JSFile) - { - originalFile = (PsiFile) pair.getFirst(); - break; - } - } - } - } - } - startElement = originalFile.findElementAt(qualifier.getTextOffset()); - - do - { - qualifier = PsiTreeUtil.getParentOfType(startElement, JSReferenceExpression.class); - if(qualifier == null) - { - break; - } - startElement = qualifier; - } - while(!textRange.equals(qualifier.getTextRange())); - } - - rawqualifier = qualifier; - } - else if(rawqualifier instanceof JSIndexedPropertyAccessExpression) - { - final JSExpression qualifier = ((JSIndexedPropertyAccessExpression) rawqualifier).getQualifier(); - if(qualifier != null) - { - final JSExpression jsExpression = getOriginalQualifier(qualifier); - if(jsExpression != null && jsExpression.getParent() instanceof JSIndexedPropertyAccessExpression) - { - return (JSExpression) jsExpression.getParent(); - } - } - } - else if(rawqualifier instanceof JSCallExpression) - { - final JSExpression qualifier = ((JSCallExpression) rawqualifier).getMethodExpression(); - if(qualifier != null) - { - final JSExpression jsExpression = getOriginalQualifier(qualifier); - if(jsExpression != null && jsExpression.getParent() instanceof JSCallExpression) - { - return (JSExpression) jsExpression.getParent(); - } - } - } - return rawqualifier; - } - - private static void doEvalForExpr(JSExpression rawqualifier, TypeProcessor typeProcessor, EvaluateContext context) - { - if(rawqualifier instanceof JSDefinitionExpression) - { - rawqualifier = ((JSDefinitionExpression) rawqualifier).getExpression(); - } - - if(rawqualifier instanceof JSNewExpression) - { - JSExpression methodExpr = ((JSNewExpression) rawqualifier).getMethodExpression(); - if(methodExpr != null) - { - String text = methodExpr.getText(); - if(methodExpr instanceof JSReferenceExpression && typeProcessor.ecma()) - { - final SimpleTypeProcessor processor = new SimpleTypeProcessor(typeProcessor.getFeatures()); - doEvalForExpr(methodExpr, context.targetFile, processor); - - if(processor.type != null && !"*".equals(processor.type)) - { - text = "Class".equals(processor.type) ? "*" : processor.type; - } - } - addType(text, typeProcessor, context, methodExpr); - } - return; - } - - if(rawqualifier instanceof JSCallExpression) - { - rawqualifier = ((JSCallExpression) rawqualifier).getMethodExpression(); - } - - if(rawqualifier instanceof JSReferenceExpression) - { - JSReferenceExpression qualifier = ((JSReferenceExpression) rawqualifier); - - boolean wasPrototype = false; - - if(qualifier != null && "prototype".equals(qualifier.getReferencedName())) - { - final JSExpression expression = qualifier.getQualifier(); - if(expression instanceof JSReferenceExpression) - { - qualifier = (JSReferenceExpression) expression; - wasPrototype = true; - } - } - - boolean topLevelQualifier = qualifier.getQualifier() == null; - - if(topLevelQualifier) - { - final JSReferenceExpression expression = typeProcessor.ecma() ? qualifier : JSSymbolUtil.findReferenceExpressionUsedForClassExtending(qualifier); - if(!typeProcessor.ecma() && expression != qualifier && expression.getQualifier() == null) - { - addType(expression.getText(), typeProcessor, context, qualifier); - return; - } - } - - final ResolveResult[] resolveResults = qualifier != null ? qualifier.multiResolve(false) : ResolveResult.EMPTY_ARRAY; - - if(resolveResults.length > 0) - { - for(ResolveResult r : resolveResults) - { - PsiElement psiElement = r.getElement(); - context.setSource(psiElement); - if(psiElement == qualifier.getParent()) - { - continue; - } - - //if (psiElement == qualifier && ((JSReferenceExpressionImpl)qualifier).isAttributeReference()) { - // addType(STRING_TYPE_NAME, typeProcessor, context, null); continue; - //} - String type = psiElement instanceof JSNamedElement ? null : null; - - if(type == null) - { - if(psiElement instanceof JSVariable) - { - final JSVariable jsVariable = (JSVariable) psiElement; - String parameterType = jsVariable.getTypeString(); - - if(isSomeFunctionCall(rawqualifier, parameterType)) - { - parameterType = ANY_TYPE; - - if(jsVariable.hasInitializer()) - { - JSExpression jsExpression = jsVariable.getInitializer(); - if(jsExpression instanceof JSFunctionExpression) - { - String typeString = ((JSFunctionExpression) jsExpression).getFunction().getReturnTypeString(); - if(isValidType(typeString)) - { - parameterType = typeString; - } - } - } - } - - if(isValidType(parameterType)) - { - addType(JSImportHandlingUtil.resolveTypeName(parameterType, jsVariable), typeProcessor, context, null); - } - - if(!typeProcessor.ecma() || parameterType == null) - { - final JSExpression expression = jsVariable.getInitializer(); - if(expression != null) - { - doEvalForExpr(expression, context.targetFile, typeProcessor); - } - else - { - boolean hasSomeInfoAboutVar = false; - - if(topLevelQualifier) - { - final ResolveProcessor processor = new ResolveProcessor(qualifier.getText(), true); - hasSomeInfoAboutVar = findDef(typeProcessor, context, qualifier, processor); - } - - if(!hasSomeInfoAboutVar && parameterType == null) - { - PsiElement grandParent; - - if((grandParent = jsVariable.getParent().getParent()) instanceof JSForInStatement && jsVariable.getParent() == ((JSForInStatement) - grandParent).getDeclarationStatement()) - { - parameterType = evalComponentTypeFromArrayExpression(rawqualifier, typeProcessor, context, - ((JSForInStatement) grandParent).getCollectionExpression()); - } - } - if(!hasSomeInfoAboutVar && parameterType == null) - { - typeProcessor.setUnknownElement(jsVariable); - } - } - } - } - else - { - boolean hasSomeType = false; - - if(psiElement instanceof JSProperty) - { - psiElement = ((JSProperty) psiElement).getValue(); - } - - if(psiElement instanceof JSClass) - { - addType(((JSClass) psiElement).getQualifiedName(), typeProcessor, context, psiElement); - hasSomeType = true; - } - else if(psiElement instanceof JSObjectLiteralExpression && typeProcessor instanceof ResolveProcessor) - { - addTypeFromObjectLiteralExpression((JSExpression) psiElement, typeProcessor); - } - else if(psiElement instanceof JSDefinitionExpression) - { - PsiElement parent; - String parameterType = null; - - if((parent = psiElement.getParent()) instanceof JSForInStatement && psiElement == ((JSForInStatement) parent).getVariableExpression()) - { - parameterType = evalComponentTypeFromArrayExpression(rawqualifier, typeProcessor, context, - ((JSForInStatement) parent).getCollectionExpression()); - } - if(parameterType == null) - { - addTypeFromDefExpr(typeProcessor, context, psiElement); - } - } - else if(psiElement instanceof XmlToken) - { - hasSomeType = true; - - final TagContextBuilder builder = new TagContextBuilder(psiElement, HTML_ELEMENT_TYPE_NAME); - final PsiElement element = builder.element; - final String typeName = builder.typeName; - - if(HTML_ELEMENT_TYPE_NAME.equals(typeName)) - { - hasSomeType = false; - } - - addType(typeName, typeProcessor, context, element); - } - else if(psiElement instanceof JSNamedElement) - { - if(psiElement instanceof JSFunction) - { - final JSFunction function = (JSFunction) psiElement; - final boolean inCall = rawqualifier.getParent() instanceof JSCallExpression; - - if(!inCall && (!function.isGetProperty() && !function.isSetProperty())) - { - addType(FUNCTION_TYPE_NAME, typeProcessor, context, psiElement); - hasSomeType = true; - if(wasPrototype) - { - final String name = ((JSNamedElement) psiElement).getName(); - if(name != null) - { - addType(name, typeProcessor, context, null); - } - } - } - else - { - if(function.isConstructor()) - { - PsiElement parentClass = JSResolveUtil.findParent(function); - if(parentClass instanceof JSClass) - { - final JSClass clazz = (JSClass) parentClass; - addType(clazz.getQualifiedName(), typeProcessor, context, clazz); - hasSomeType = true; - } - } - else - { - String s = null; - if(function.isSetProperty()) - { - final JSParameterList parameterList = function.getParameterList(); - final JSParameter[] parameters = parameterList != null ? parameterList.getParameters() : JSParameter.EMPTY_ARRAY; - s = parameters.length == 1 ? parameters[0].getTypeString() : null; - } - - if(s == null) - { - s = function.getReturnTypeString(); - if(isSomeFunctionCall(rawqualifier, s)) - { - s = ANY_TYPE; - } - } - if(isValidType(s)) - { - addType(JSImportHandlingUtil.resolveTypeName(s, function), typeProcessor, context, null); - hasSomeType = true; - } - else - { - addQNameFromElementAsType(typeProcessor, context, psiElement, false); - } - } - } - } - else - { - boolean hasTypeKnowledge = false; - boolean passSource = false; - - if(!hasTypeKnowledge || wasPrototype) - { - addQNameFromElementAsType(typeProcessor, context, psiElement, passSource); - } - } - } - else if(psiElement instanceof JSLiteralExpression) - { - getTypeFromConstant((JSExpression) psiElement, typeProcessor, context); - hasSomeType = true; - } - else if(psiElement instanceof JSExpressionStatement) - { - final String s = JSDocumentationUtils.findType(psiElement); - if(isValidType(s)) - { - addType(JSImportHandlingUtil.resolveTypeName(s, psiElement), typeProcessor, context, null); - hasSomeType = true; - } - } - if(!hasSomeType && psiElement != null) - { - typeProcessor.setUnknownElement(psiElement); - } - } - //myTargetFiles.add(psiElement.getContainingFile()); - } - else if(!context.visitedTypes.contains(type)) - { - //if (context.typeEvaluateManager.isArrayType(type))) type = ARRAY_TYPE_NAME; - addType(type, typeProcessor, context, null); - } - } - } - else - { - typeProcessor.setUnknownElement(qualifier); - } - - JSReferenceExpression localQualifier = qualifier; - - while(true) - { - JSExpression expression = localQualifier.getQualifier(); - - if(expression instanceof JSCallExpression) - { - JSExpression methodExpression = ((JSCallExpression) expression).getMethodExpression(); - - if(methodExpression instanceof JSReferenceExpression) - { - localQualifier = (JSReferenceExpression) methodExpression; - continue; - } - } - - break; - } - - if("$".equals(localQualifier.getText())) - { - addType("jQuery", typeProcessor, context, localQualifier); - } - if("$".equals(qualifier.getText())) - { - addType(HTML_ELEMENT_TYPE_NAME, typeProcessor, context, null); - } - else if("getComponentById".equals(qualifier.getReferencedName())) - { - tryAddBindowsType(qualifier, typeProcessor, context); - } - } - else if(rawqualifier instanceof JSBinaryExpression) - { - final JSBinaryExpression binaryExpression = (JSBinaryExpression) rawqualifier; - final IElementType sign = binaryExpression.getOperationSign(); - final JSExpression rOperand = binaryExpression.getROperand(); - final JSExpression lOperand = binaryExpression.getLOperand(); - - if(rOperand != null) - { - if(sign == JSTokenTypes.AS_KEYWORD) - { - addType(JSImportHandlingUtil.resolveTypeName(rOperand.getText(), rOperand), typeProcessor, context, null); - } - else if(JSTokenTypes.RELATIONAL_OPERATIONS.contains(sign) || JSTokenTypes.EQUALITY_OPERATIONS.contains(sign) || - sign == JSTokenTypes.IS_KEYWORD) - { - addType(BOOLEAN_TYPE_NAME, typeProcessor, context, null); - } - else if(JSTokenTypes.ADDITIVE_OPERATIONS.contains(sign) || - JSTokenTypes.MULTIPLICATIVE_OPERATIONS.contains(sign) || - sign == JSTokenTypes.ANDAND || - sign == JSTokenTypes.OROR) - { - - final SimpleTypeProcessor lprocessor = new SimpleTypeProcessor(typeProcessor.getFeatures()); - final SimpleTypeProcessor rprocessor = new SimpleTypeProcessor(typeProcessor.getFeatures()); - doEvalForExpr(lOperand, lprocessor, context); - doEvalForExpr(rOperand, rprocessor, context); - - String evaluatedType = lprocessor.type != null && lprocessor.type.equals(rprocessor.type) ? lprocessor.type : null; - if(evaluatedType != null) - { - addType(evaluatedType, typeProcessor, context, rawqualifier); - } - else - { - typeProcessor.setUnknownElement(rawqualifier); - } - } - else if(sign == JSTokenTypes.EQ) - { - final SimpleTypeProcessor rprocessor = new SimpleTypeProcessor(typeProcessor.getFeatures()); - doEvalForExpr(rOperand, rprocessor, context); - - String evaluatedType = rprocessor.type; - if(evaluatedType != null) - { - addType(evaluatedType, typeProcessor, context, rawqualifier); - } - else - { - typeProcessor.setUnknownElement(rawqualifier); - } - } - } - } - else if(rawqualifier instanceof JSLiteralExpression) - { - getTypeFromConstant(rawqualifier, typeProcessor, context); - } - else if(rawqualifier instanceof JSArrayLiteralExpression) - { - addType(ARRAY_TYPE_NAME, typeProcessor, context, rawqualifier); - if(typeProcessor instanceof ResolveProcessor) - { - ((ResolveProcessor) typeProcessor).execute(rawqualifier, ResolveState.initial()); - } - } - else if(rawqualifier instanceof JSIndexedPropertyAccessExpression) - { - final JSIndexedPropertyAccessExpression propertyAccessExpression = (JSIndexedPropertyAccessExpression) rawqualifier; - final SimpleTypeProcessor lprocessor = new SimpleTypeProcessor(typeProcessor.getFeatures()); - - doEvalForExpr(propertyAccessExpression.getQualifier(), lprocessor, context); - - if(lprocessor.result instanceof JSArrayLiteralExpression && typeProcessor instanceof ResolveProcessor) - { - for(JSExpression expr : ((JSArrayLiteralExpression) lprocessor.result).getExpressions()) - { - if(expr instanceof JSObjectLiteralExpression) - { - addTypeFromObjectLiteralExpression(expr, typeProcessor); - } - } - } - - addComponentTypeFromProcessor(rawqualifier, typeProcessor, context, lprocessor); - } - else if(rawqualifier instanceof JSObjectLiteralExpression && typeProcessor instanceof ResolveProcessor) - { - addTypeFromObjectLiteralExpression(rawqualifier, typeProcessor); - } - else if(rawqualifier instanceof JSParenthesizedExpression) - { - doEvalForExpr(((JSParenthesizedExpression) rawqualifier).getInnerExpression(), typeProcessor, context); - } - else if(rawqualifier instanceof JSThisExpression) - { - final JSClass jsClass = JSResolveUtil.getClassOfContext(rawqualifier); - if(jsClass != null) - { - addType(jsClass.getQualifiedName(), typeProcessor, context, jsClass); - } - else - { - typeProcessor.setUnknownElement(rawqualifier); - } - } - else if(rawqualifier instanceof JSSuperExpression) - { - final JSClass jsClass = JSResolveUtil.getClassOfContext(rawqualifier); - if(jsClass != null) - { - final JSClass[] classes = jsClass.getSuperClasses(); - if(classes.length > 0) - { - addType(classes[0].getQualifiedName(), typeProcessor, context, classes[0]); - } - } - } - else if(rawqualifier != null) - { - typeProcessor.setUnknownElement(rawqualifier); - } - } - - private static boolean isSomeFunctionCall(JSExpression rawqualifier, String parameterType) - { - return FUNCTION_TYPE_NAME.equals(parameterType) && rawqualifier.getParent() instanceof JSCallExpression; - } - - private static void addQNameFromElementAsType(TypeProcessor typeProcessor, EvaluateContext context, PsiElement psiElement, boolean passSource) - { - String name = ((JSNamedElement) psiElement).getName(); - if(name == null) - { - return; - } - if(psiElement instanceof JSQualifiedNamedElement) - { - String qName = ((JSQualifiedNamedElement) psiElement).getQualifiedName(); - if(qName != null) - { - name = qName; - } - } - addType(name, typeProcessor, context, passSource ? psiElement : null); - } - - private static String evalComponentTypeFromArrayExpression(JSExpression rawqualifier, TypeProcessor typeProcessor, EvaluateContext context, - JSExpression collectionExpression) - { - if(collectionExpression != null) - { - if(context.isAlreadyProcessingItem(rawqualifier)) - { - return null; - } - context.addProcessingItem(rawqualifier); - final SimpleTypeProcessor lprocessor = new SimpleTypeProcessor(typeProcessor.getFeatures()); - doEvalForExpr(collectionExpression, lprocessor, context); - return addComponentTypeFromProcessor(rawqualifier, typeProcessor, context, lprocessor); - } - - return null; - } - - private static String addComponentTypeFromProcessor(JSExpression rawqualifier, TypeProcessor typeProcessor, EvaluateContext context, - SimpleTypeProcessor lprocessor) - { - if(lprocessor.type != null) - { - String type = lprocessor.type; - if(JSTypeEvaluateManager.isArrayType(type)) - { - type = JSTypeEvaluateManager.getComponentType(type); - } - else - { - type = "*"; - } - addType(JSImportHandlingUtil.resolveTypeName(type, rawqualifier), typeProcessor, context, rawqualifier); - return type; - } - return null; - } - - private static boolean isValidType(String parameterType) - { - return parameterType != null && parameterType.length() > 0; - } - - private static boolean findDef(final TypeProcessor typeProcessor, final EvaluateContext context, final JSReferenceExpression qualifier, - final ResolveProcessor processor) - { - final PsiElement parent = qualifier.getParent(); - JSResolveUtil.treeWalkUp(processor, qualifier, parent, qualifier); - - PsiElement jsElement = processor.getResult(); - if(jsElement instanceof JSDefinitionExpression) - { - addTypeFromDefExpr(typeProcessor, context, jsElement); - return true; - } - return false; - } - - private static void tryAddBindowsType(final JSReferenceExpression qualifier, final TypeProcessor typeProcessor, final EvaluateContext context) - { - final PsiElement element = qualifier.getParent(); - if(!(element instanceof JSCallExpression)) - { - return; - } - final JSArgumentList argumentList = ((JSCallExpression) element).getArgumentList(); - if(argumentList == null) - { - return; - } - final JSExpression[] expressions = argumentList.getArguments(); - if(expressions.length == 0 || !(expressions[0] instanceof JSLiteralExpression)) - { - return; - } - - final String val = StringUtil.stripQuotesAroundValue(expressions[0].getText()); - final PsiElement contextElement = qualifier.getContainingFile().getContext(); - - if(contextElement != null) - { - final PsiFile containingFile = contextElement.getContainingFile(); - - if(isBindowsXml(containingFile)) - { - } - } - } - - private static boolean isBindowsXml(final PsiFile containingFile) - { - return containingFile.getName().endsWith(".xml") && containingFile instanceof XmlFile; - } - - private static void addTypeFromObjectLiteralExpression(final JSExpression rawqualifier, final TypeProcessor typeProcessor) - { - final JSProperty[] properties = ((JSObjectLiteralExpression) rawqualifier).getProperties(); - - final boolean b = properties.length > 0 ? rawqualifier.processDeclarations((ResolveProcessor) typeProcessor, ResolveState.initial(), - properties[0], properties[0]) : true; - if(b) - { - typeProcessor.setUnknownElement(rawqualifier); - } - } - - private static void addTypeFromDefExpr(final TypeProcessor typeProcessor, final EvaluateContext context, final PsiElement psiElement) - { - final String type; - type = psiElement.getText(); - - if(!context.visitedTypes.contains(type)) - { - context.visitedTypes.add(type); - final PsiElement parentElement = psiElement.getParent(); - if(parentElement instanceof JSAssignmentExpression) - { - JSExpression expr = ((JSAssignmentExpression) parentElement).getROperand(); - while(expr instanceof JSAssignmentExpression) - { - expr = ((JSAssignmentExpression) expr).getROperand(); - } - if(expr != null) - { - doEvalForExpr(expr, typeProcessor, context); - } - } - else - { - typeProcessor.setUnknownElement(parentElement); - } - } - } - - private static void getTypeFromConstant(final JSExpression rawqualifier, TypeProcessor typeProcessor, EvaluateContext context) - { - final ASTNode childNode = rawqualifier.getNode().getFirstChildNode(); - IElementType constantType = childNode.getElementType(); - - String type = JavaScriptTokenSets.STRING_LITERALS.contains(constantType) ? STRING_TYPE_NAME : - constantType == JSTokenTypes.NUMERIC_LITERAL ? NUMBER_TYPE_NAME : constantType == JSTokenTypes.REGEXP_LITERAL ? REG_EXP_TYPE_NAME : constantType - == JSTokenTypes.XML_START_TAG_START ? XML_TYPE_NAME : constantType == JSTokenTypes.XML_START_TAG_LIST ? XML_LIST_TYPE_NAME : constantType == - JSTokenTypes.TRUE_KEYWORD || constantType == JSTokenTypes.FALSE_KEYWORD ? BOOLEAN_TYPE_NAME : null; - - if(type == NUMBER_TYPE_NAME && typeProcessor.ecma()) - { - final String text = childNode.getText(); - if(text.indexOf('.') == -1) - { - type = INT_TYPE; - } - } - - if(type != null) - { - addType(type, typeProcessor, context, rawqualifier); - } - else - { - typeProcessor.setUnknownElement(rawqualifier); - } - } - - protected void addPackageScope(final List possibleNameIds, final JSClass jsClass, final PsiElement expression) - { - final String packageQualifier = JSResolveUtil.findPackageStatementQualifier(expression); - String qName; - - if(packageQualifier != null) - { - buildIndexListFromQNameAndCorrectQName(packageQualifier, jsClass, possibleNameIds); - } - else if(jsClass != null && (qName = jsClass.getQualifiedName()) != null && !qName.equals(jsClass.getName())) - { - final int index = qName.lastIndexOf('.'); - if(index > 0) - { - buildIndexListFromQNameAndCorrectQName(qName.substring(0, index), jsClass, possibleNameIds); - } - } - else if(jsClass == null) - { - String s = JSResolveUtil.findPackageForMxml(expression); - if(isValidType(s)) - { - buildIndexListFromQNameAndCorrectQName(s, expression, possibleNameIds); - } - } - } - - protected String buildIndexListFromQNameAndCorrectQName(String type, final PsiElement source, List possibleNameIds) - { - final List list = new ArrayList(); - type = addIndexListFromQName(type, source, list); - - possibleNameIds.add(ArrayUtil.toStringArray(list)); - return type; - } - - public static String addIndexListFromQName(String type, final PsiElement source, final List list) - { - int i = type.indexOf('.'); - int lastI = 0; - - while(i != -1) - { - list.add(type.substring(lastI, i)); - lastI = i + 1; - i = type.indexOf('.', lastI); - } - - if(i != type.length()) - { - String s = type.substring(lastI, type.length()); - if(source == null) - { - s = StringUtil.capitalize(s); // when type name goes from comments - } - if(lastI == 0 && !s.equals(type)) - { - type = s; - } - list.add(s); - } - return type; - } - - private static void addType(String type, TypeProcessor typeProcessor, EvaluateContext context, final PsiElement source) - { - if(type == null) - { - return; - } - int spacePos = type.indexOf(' '); - if(spacePos != -1) - { - type = type.substring(0, spacePos); - } - - if(!(typeProcessor instanceof GenericTypeParametersClient)) - { - final int gtPos = type.indexOf('<'); - if(gtPos > 0 && type.charAt(gtPos - 1) == '.') - { - type = type.substring(0, gtPos - 1); - } - } - - if(!typeProcessor.ecma()) - { - type = JSTypeEvaluateManager.getInstanceNameByType(type); - } - typeProcessor.process(type, context, source); - } - - @Override - public T getHint(final Key hintClass) - { - return null; - } - - @Override - public void handleEvent(Event event, Object associated) - { - } - - enum MatchType - { - COMPLETE_TYPE, COMPLETE, COMPLETE_NS, PARTIAL, NOMATCH - } - - interface HierarchyProcessor - { - boolean processClass(JSClass clazz); - } - - protected void doIterateTypeHierarchy(final String[] contextIds, final HierarchyProcessor processor) - { - StringBuilder builder = new StringBuilder(); - for(String cnameId : contextIds) - { - if(builder.length() > 0) - { - builder.append('.'); - } - builder.append(cnameId); - } - - final String typeName = builder.toString(); - if(typeName.length() == 0) - { - return; - } - - myIteratedTypeName = typeName; - doIterateHierarchy(typeName, processor); - myIteratedTypeName = null; - } - - protected void doIterateHierarchy(final String typeName, final HierarchyProcessor processor) - { - final PsiElement clazz = JSResolveUtil.findClassByQName(typeName, myContext); - if(clazz instanceof JSClass) - { - for(JSClass superClazz : ((JSClass) clazz).getSuperClasses()) - { - superClazz.processDeclarations(new ResolveProcessor(null) - { - { - setToProcessMembers(false); - setToProcessHierarchy(true); - setTypeContext(true); - } - - @Override - public boolean execute(final PsiElement element, final ResolveState state) - { - if(element instanceof JSClass) - { - if(!processor.processClass((JSClass) element)) - { - return false; - } - } - return true; - } - }, ResolveState.initial(), null, clazz); - } - - return; - } - } - - - public static class EvaluateContext - { - public final PsiFile targetFile; - public final Set visitedTypes = new HashSet(); - private Set processingItems; - private PsiElement source; - - public EvaluateContext(final PsiFile targetFile) - { - this.targetFile = targetFile; - } - - public boolean isAlreadyProcessingItem(final JSExpression rawqualifier) - { - if(processingItems != null) - { - return processingItems.contains(rawqualifier); - } - return false; - } - - public void addProcessingItem(final JSExpression rawqualifier) - { - if(processingItems == null) - { - processingItems = new HashSet(); - } - processingItems.add(rawqualifier); - } - - public void removeProcessingItem(final JSExpression rawqualifier) - { - processingItems.remove(rawqualifier); - } - - public PsiElement getSource() - { - return source; - } - - public void setSource(final PsiElement source) - { - this.source = source; - } - } - - public interface TypeProcessor - { - void process(@Nonnull String type, @Nonnull EvaluateContext evaluateContext, final PsiElement source); - - @Deprecated - boolean ecma(); - - Set getFeatures(); - - void setUnknownElement(@Nonnull PsiElement element); - } - - public interface GenericTypeParametersClient - { - } - - public static class SimpleTypeProcessor extends ResolveProcessor implements TypeProcessor, GenericTypeParametersClient - { - private String type; - private PsiElement result; - private PsiElement source; - private final Set myFeatures; - - public SimpleTypeProcessor(Set features) - { - super(null); - myFeatures = features; - } - - @Override - public void process(@Nonnull final String _type, @Nonnull final EvaluateContext evaluateContext, final PsiElement _source) - { - setType(type != null && !type.equals(_type) ? ANY_TYPE : _type, _source); - } - - private void setType(final String s, final PsiElement _source) - { - type = s; - source = _source; - } - - @Override - public Set getFeatures() - { - return myFeatures; - } - - @Override - public boolean ecma() - { - return myFeatures.contains(JavaScriptFeature.CLASS); - } - - @Override - public boolean execute(final PsiElement element, final ResolveState state) - { - result = element; - return true; - } - - @Override - public void setUnknownElement(@Nonnull final PsiElement _element) - { - setType(ANY_TYPE, _element); - } - - public String getType() - { - return type; - } - - public PsiElement getSource() - { - return source; - } - } - - public static class TagContextBuilder - { - public final PsiElement element; - public final String typeName; - - public TagContextBuilder(PsiElement psiElement, String defaultName) - { - String typeName = null; - final XmlTag tag = PsiTreeUtil.getParentOfType(psiElement, XmlTag.class); - JSClass element = null; - - if(tag != null) - { - final PsiFile containingFile = tag.getContainingFile(); - - if(isBindowsXml(containingFile)) - { - typeName = "Bi" + tag.getLocalName(); - } - else - { - element = JSResolveUtil.getClassFromTagNameInMxml(tag); - typeName = element != null ? element.getQualifiedName() : null; - } - } - - if(typeName == null) - { - typeName = defaultName; - } - - this.typeName = typeName; - this.element = element; - } - } +abstract public class BaseJSSymbolProcessor implements PsiScopeProcessor { + protected final PsiFile myTargetFile; + protected PsiFile myCurrentFile; + protected final boolean mySkipDclsInTargetFile; + protected final PsiElement myContext; + protected final String myWindowIndex; + protected final String myFunctionIndex; + + protected String[] myContextNameIds; + @Deprecated + protected boolean ecmal4; + protected Set myFeatures; + protected boolean myDefinitelyGlobalReference; + protected boolean myDefinitelyNonglobalReference; + protected boolean myAddOnlyCompleteMatches; + protected boolean myAllowPartialResults = true; + + private static final String ANY_TYPE = "*"; + public static final String ARRAY_TYPE_NAME = "Array"; + public static final String STRING_TYPE_NAME = "String"; + public static final String REG_EXP_TYPE_NAME = "RegExp"; + public static final String XML_TYPE_NAME = "XML"; + public static final String XML_LIST_TYPE_NAME = "XMLList"; + public static final String NUMBER_TYPE_NAME = "Number"; + public static final String FUNCTION_TYPE_NAME = "Function"; + public static final String HTML_ELEMENT_TYPE_NAME = "HTMLElement"; + private static final String INT_TYPE = "int"; + private static final String BOOLEAN_TYPE_NAME = "Boolean"; + protected String myIteratedTypeName; + + protected BaseJSSymbolProcessor( + PsiFile targetFile, + boolean skipDclsInTargetFile, + PsiElement context, + String[] contextIds + ) { + myTargetFile = targetFile; + mySkipDclsInTargetFile = skipDclsInTargetFile; + myContext = context; + + myWindowIndex = "window"; + myFunctionIndex = "Function"; + + myFeatures = JavaScriptVersionUtil.getFeatures(targetFile); + ecmal4 = myFeatures.contains(JavaScriptFeature.CLASS); + + if (contextIds == null && context instanceof JSReferenceExpression) { + contextIds = calculateContextIds((JSReferenceExpression)context); + } + + if (contextIds == null) { // TODO: workaround for NPE + contextIds = new String[0]; + } + + myContextNameIds = contextIds; + + boolean notWithinWithStatement = PsiTreeUtil.getParentOfType(myContext, JSWithStatement.class) == null; + + if (((contextIds == null || contextIds.length == 0) + && myContext instanceof JSReferenceExpression referenceExpression + && referenceExpression.getQualifier() == null && notWithinWithStatement + && JSResolveUtil.getRealRefExprQualifier(referenceExpression) == null) + || (contextIds != null && contextIds.length == 1 && contextIds[0].equals(myWindowIndex) && notWithinWithStatement)) { + myDefinitelyGlobalReference = true; + } + + if (contextIds != null + && (contextIds.length > 1 || (contextIds.length == 1 && !contextIds[0].isEmpty() && !contextIds[0].equals(myWindowIndex)))) { + myDefinitelyNonglobalReference = true; + } + } + + protected abstract String[] calculateContextIds(JSReferenceExpression jsReferenceExpression); + + public void setAddOnlyCompleteMatches(boolean addOnlyCompleteMatches) { + myAddOnlyCompleteMatches = addOnlyCompleteMatches; + myAllowPartialResults = false; + } + + + protected boolean isFromRelevantFileOrDirectory() { + PsiFile psiFile = myCurrentFile; + + return myTargetFile == psiFile || false; + //(myTargetFile != null && + // psiFile != null && + // myTargetFile.getContainingDirectory() == psiFile.getContainingDirectory() + //); + } + + private static ThreadLocal contextHolder = new ThreadLocal<>(); + + @RequiredReadAction + public static void doEvalForExpr(JSExpression rawqualifier, PsiFile myTargetFile, TypeProcessor typeProcessor) { + EvaluateContext context = contextHolder.get(); + boolean contextHolderInitialized = false; + + if (context == null) { + context = new EvaluateContext(myTargetFile); + contextHolder.set(context); + contextHolderInitialized = true; + } + else if (context.isAlreadyProcessingItem(rawqualifier)) { + return; + } + else { + context.addProcessingItem(rawqualifier); + } + + try { + doEvalForExpr(rawqualifier, typeProcessor, contextHolderInitialized ? context : new EvaluateContext(myTargetFile)); + } + finally { + if (!contextHolderInitialized) { + context.removeProcessingItem(rawqualifier); + } + if (contextHolderInitialized) { + contextHolder.set(null); + } + } + } + + @RequiredReadAction + public static JSExpression getOriginalQualifier(JSExpression rawQualifier) { + if (rawQualifier instanceof JSReferenceExpression qualifier) { + TextRange textRange = qualifier.getTextRange(); + PsiFile targetFile = rawQualifier.getContainingFile(); + PsiElement context = targetFile.getContext(); + if (context != null) { + targetFile = context.getContainingFile(); + } + + PsiFile originalFile = targetFile.getOriginalFile(); + + if (!targetFile.isPhysical() && originalFile != null) { + PsiElement startElement; + if (context != null) { + PsiElement at = PsiTreeUtil.getNonStrictParentOfType( + originalFile.findElementAt(context.getTextOffset()), + PsiLanguageInjectionHost.class + ); + if (at instanceof PsiLanguageInjectionHost) { + List> injectedPsiFiles = + InjectedLanguageManager.getInstance(at.getProject()).getInjectedPsiFiles(at); + if (injectedPsiFiles != null) { + for (Pair pair : injectedPsiFiles) { + if (pair.getFirst() instanceof JSFile) { + originalFile = (PsiFile)pair.getFirst(); + break; + } + } + } + } + } + startElement = originalFile.findElementAt(qualifier.getTextOffset()); + + do { + qualifier = PsiTreeUtil.getParentOfType(startElement, JSReferenceExpression.class); + if (qualifier == null) { + break; + } + startElement = qualifier; + } + while (!textRange.equals(qualifier.getTextRange())); + } + + rawQualifier = qualifier; + } + else if (rawQualifier instanceof JSIndexedPropertyAccessExpression indexedPropertyAccessExpression) { + JSExpression qualifier = indexedPropertyAccessExpression.getQualifier(); + if (qualifier != null) { + JSExpression jsExpression = getOriginalQualifier(qualifier); + if (jsExpression != null && jsExpression.getParent() instanceof JSIndexedPropertyAccessExpression) { + return (JSExpression)jsExpression.getParent(); + } + } + } + else if (rawQualifier instanceof JSCallExpression call) { + JSExpression qualifier = call.getMethodExpression(); + if (qualifier != null) { + JSExpression jsExpression = getOriginalQualifier(qualifier); + if (jsExpression != null && jsExpression.getParent() instanceof JSCallExpression parentCall) { + return parentCall; + } + } + } + return rawQualifier; + } + + @RequiredReadAction + private static void doEvalForExpr(JSExpression rawQualifier, TypeProcessor typeProcessor, EvaluateContext context) { + if (rawQualifier instanceof JSDefinitionExpression definition) { + rawQualifier = definition.getExpression(); + } + + if (rawQualifier instanceof JSNewExpression newExpression) { + JSExpression methodExpr = newExpression.getMethodExpression(); + if (methodExpr != null) { + String text = methodExpr.getText(); + if (methodExpr instanceof JSReferenceExpression && typeProcessor.ecma()) { + SimpleTypeProcessor processor = new SimpleTypeProcessor(typeProcessor.getFeatures()); + doEvalForExpr(methodExpr, context.targetFile, processor); + + if (processor.type != null && !"*".equals(processor.type)) { + text = "Class".equals(processor.type) ? "*" : processor.type; + } + } + addType(text, typeProcessor, context, methodExpr); + } + return; + } + + if (rawQualifier instanceof JSCallExpression call) { + rawQualifier = call.getMethodExpression(); + } + + if (rawQualifier instanceof JSReferenceExpression qualifier) { + boolean wasPrototype = false; + + if (qualifier != null && "prototype".equals(qualifier.getReferencedName())) { + JSExpression expression = qualifier.getQualifier(); + if (expression instanceof JSReferenceExpression refExpr) { + qualifier = refExpr; + wasPrototype = true; + } + } + + boolean topLevelQualifier = qualifier.getQualifier() == null; + + if (topLevelQualifier) { + JSReferenceExpression expression = + typeProcessor.ecma() ? qualifier : JSSymbolUtil.findReferenceExpressionUsedForClassExtending(qualifier); + if (!typeProcessor.ecma() && expression != qualifier && expression.getQualifier() == null) { + addType(expression.getText(), typeProcessor, context, qualifier); + return; + } + } + + ResolveResult[] resolveResults = qualifier != null ? qualifier.multiResolve(false) : ResolveResult.EMPTY_ARRAY; + + if (resolveResults.length > 0) { + for (ResolveResult r : resolveResults) { + PsiElement psiElement = r.getElement(); + context.setSource(psiElement); + if (psiElement == qualifier.getParent()) { + continue; + } + + //if (psiElement == qualifier && ((JSReferenceExpressionImpl)qualifier).isAttributeReference()) { + // addType(STRING_TYPE_NAME, typeProcessor, context, null); continue; + //} + String type = psiElement instanceof JSNamedElement ? null : null; + + if (type == null) { + if (psiElement instanceof JSVariable jsVariable) { + String parameterType = jsVariable.getTypeString(); + + if (isSomeFunctionCall(rawQualifier, parameterType)) { + parameterType = ANY_TYPE; + + if (jsVariable.hasInitializer() + && jsVariable.getInitializer() instanceof JSFunctionExpression functionExpr) { + String typeString = functionExpr.getFunction().getReturnTypeString(); + if (isValidType(typeString)) { + parameterType = typeString; + } + } + } + + if (isValidType(parameterType)) { + addType(JSImportHandlingUtil.resolveTypeName(parameterType, jsVariable), typeProcessor, context, null); + } + + if (!typeProcessor.ecma() || parameterType == null) { + JSExpression expression = jsVariable.getInitializer(); + if (expression != null) { + doEvalForExpr(expression, context.targetFile, typeProcessor); + } + else { + boolean hasSomeInfoAboutVar = false; + + if (topLevelQualifier) { + ResolveProcessor processor = new ResolveProcessor(qualifier.getText(), true); + hasSomeInfoAboutVar = findDef(typeProcessor, context, qualifier, processor); + } + + if (!hasSomeInfoAboutVar && parameterType == null + && jsVariable.getParent().getParent() instanceof JSForInStatement forInStatement + && jsVariable.getParent() == forInStatement.getDeclarationStatement()) { + parameterType = evalComponentTypeFromArrayExpression( + rawQualifier, + typeProcessor, + context, + forInStatement.getCollectionExpression() + ); + } + if (!hasSomeInfoAboutVar && parameterType == null) { + typeProcessor.setUnknownElement(jsVariable); + } + } + } + } + else { + boolean hasSomeType = false; + + if (psiElement instanceof JSProperty property) { + psiElement = property.getValue(); + } + + if (psiElement instanceof JSClass jsClass) { + addType(jsClass.getQualifiedName(), typeProcessor, context, psiElement); + hasSomeType = true; + } + else if (psiElement instanceof JSObjectLiteralExpression objectLiteralExpression + && typeProcessor instanceof ResolveProcessor) { + addTypeFromObjectLiteralExpression(objectLiteralExpression, typeProcessor); + } + else if (psiElement instanceof JSDefinitionExpression) { + String parameterType = null; + + if (psiElement.getParent() instanceof JSForInStatement forInStatement + && psiElement == forInStatement.getVariableExpression()) { + parameterType = evalComponentTypeFromArrayExpression( + rawQualifier, + typeProcessor, + context, + forInStatement.getCollectionExpression() + ); + } + if (parameterType == null) { + addTypeFromDefExpr(typeProcessor, context, psiElement); + } + } + else if (psiElement instanceof XmlToken xmlToken) { + hasSomeType = true; + + TagContextBuilder builder = new TagContextBuilder(xmlToken, HTML_ELEMENT_TYPE_NAME); + PsiElement element = builder.element; + String typeName = builder.typeName; + + if (HTML_ELEMENT_TYPE_NAME.equals(typeName)) { + hasSomeType = false; + } + + addType(typeName, typeProcessor, context, element); + } + else if (psiElement instanceof JSNamedElement namedElement) { + if (namedElement instanceof JSFunction function) { + boolean inCall = rawQualifier.getParent() instanceof JSCallExpression; + + if (!inCall && (!function.isGetProperty() && !function.isSetProperty())) { + addType(FUNCTION_TYPE_NAME, typeProcessor, context, function); + hasSomeType = true; + if (wasPrototype) { + String name = function.getName(); + if (name != null) { + addType(name, typeProcessor, context, null); + } + } + } + else if (function.isConstructor()) { + PsiElement parentClass = JSResolveUtil.findParent(function); + if (parentClass instanceof JSClass clazz) { + addType(clazz.getQualifiedName(), typeProcessor, context, clazz); + hasSomeType = true; + } + } + else { + String s = null; + if (function.isSetProperty()) { + JSParameterList parameterList = function.getParameterList(); + JSParameter[] parameters = + parameterList != null ? parameterList.getParameters() : JSParameter.EMPTY_ARRAY; + s = parameters.length == 1 ? parameters[0].getTypeString() : null; + } + + if (s == null) { + s = function.getReturnTypeString(); + if (isSomeFunctionCall(rawQualifier, s)) { + s = ANY_TYPE; + } + } + if (isValidType(s)) { + addType(JSImportHandlingUtil.resolveTypeName(s, function), typeProcessor, context, null); + hasSomeType = true; + } + else { + addQNameFromElementAsType(typeProcessor, context, function, false); + } + } + } + else { + boolean hasTypeKnowledge = false; + boolean passSource = false; + + if (!hasTypeKnowledge || wasPrototype) { + addQNameFromElementAsType(typeProcessor, context, namedElement, passSource); + } + } + } + else if (psiElement instanceof JSLiteralExpression literal) { + getTypeFromConstant(literal, typeProcessor, context); + hasSomeType = true; + } + else if (psiElement instanceof JSExpressionStatement expression) { + String exprType = JSDocumentationUtils.findType(expression); + if (isValidType(exprType)) { + addType(JSImportHandlingUtil.resolveTypeName(exprType, expression), typeProcessor, context, null); + hasSomeType = true; + } + } + if (!hasSomeType && psiElement != null) { + typeProcessor.setUnknownElement(psiElement); + } + } + //myTargetFiles.add(psiElement.getContainingFile()); + } + else if (!context.visitedTypes.contains(type)) { + //if (context.typeEvaluateManager.isArrayType(type))) type = ARRAY_TYPE_NAME; + addType(type, typeProcessor, context, null); + } + } + } + else { + typeProcessor.setUnknownElement(qualifier); + } + + JSReferenceExpression localQualifier = qualifier; + + while (true) { + if (localQualifier.getQualifier() instanceof JSCallExpression call) { + JSExpression methodExpression = call.getMethodExpression(); + + if (methodExpression instanceof JSReferenceExpression referenceExpression) { + localQualifier = referenceExpression; + continue; + } + } + + break; + } + + if ("$".equals(localQualifier.getText())) { + addType("jQuery", typeProcessor, context, localQualifier); + } + if ("$".equals(qualifier.getText())) { + addType(HTML_ELEMENT_TYPE_NAME, typeProcessor, context, null); + } + else if ("getComponentById".equals(qualifier.getReferencedName())) { + tryAddBindowsType(qualifier, typeProcessor, context); + } + } + else if (rawQualifier instanceof JSBinaryExpression binaryExpr) { + IElementType sign = binaryExpr.getOperationSign(); + JSExpression rOperand = binaryExpr.getROperand(); + JSExpression lOperand = binaryExpr.getLOperand(); + + if (rOperand != null) { + if (sign == JSTokenTypes.AS_KEYWORD) { + addType(JSImportHandlingUtil.resolveTypeName(rOperand.getText(), rOperand), typeProcessor, context, null); + } + else if (JSTokenTypes.RELATIONAL_OPERATIONS.contains(sign) || JSTokenTypes.EQUALITY_OPERATIONS.contains(sign) || + sign == JSTokenTypes.IS_KEYWORD) { + addType(BOOLEAN_TYPE_NAME, typeProcessor, context, null); + } + else if (JSTokenTypes.ADDITIVE_OPERATIONS.contains(sign) + || JSTokenTypes.MULTIPLICATIVE_OPERATIONS.contains(sign) + || sign == JSTokenTypes.ANDAND || sign == JSTokenTypes.OROR) { + + SimpleTypeProcessor lprocessor = new SimpleTypeProcessor(typeProcessor.getFeatures()); + SimpleTypeProcessor rprocessor = new SimpleTypeProcessor(typeProcessor.getFeatures()); + doEvalForExpr(lOperand, lprocessor, context); + doEvalForExpr(rOperand, rprocessor, context); + + String evaluatedType = lprocessor.type != null && lprocessor.type.equals(rprocessor.type) ? lprocessor.type : null; + if (evaluatedType != null) { + addType(evaluatedType, typeProcessor, context, rawQualifier); + } + else { + typeProcessor.setUnknownElement(rawQualifier); + } + } + else if (sign == JSTokenTypes.EQ) { + SimpleTypeProcessor rprocessor = new SimpleTypeProcessor(typeProcessor.getFeatures()); + doEvalForExpr(rOperand, rprocessor, context); + + String evaluatedType = rprocessor.type; + if (evaluatedType != null) { + addType(evaluatedType, typeProcessor, context, rawQualifier); + } + else { + typeProcessor.setUnknownElement(rawQualifier); + } + } + } + } + else if (rawQualifier instanceof JSLiteralExpression literal) { + getTypeFromConstant(literal, typeProcessor, context); + } + else if (rawQualifier instanceof JSArrayLiteralExpression arrayLiteral) { + addType(ARRAY_TYPE_NAME, typeProcessor, context, arrayLiteral); + if (typeProcessor instanceof ResolveProcessor resolveProcessor) { + resolveProcessor.execute(arrayLiteral, ResolveState.initial()); + } + } + else if (rawQualifier instanceof JSIndexedPropertyAccessExpression propertyAccess) { + SimpleTypeProcessor lprocessor = new SimpleTypeProcessor(typeProcessor.getFeatures()); + + doEvalForExpr(propertyAccess.getQualifier(), lprocessor, context); + + if (lprocessor.result instanceof JSArrayLiteralExpression arrayLiteral && typeProcessor instanceof ResolveProcessor) { + for (JSExpression expr : arrayLiteral.getExpressions()) { + if (expr instanceof JSObjectLiteralExpression) { + addTypeFromObjectLiteralExpression(expr, typeProcessor); + } + } + } + + addComponentTypeFromProcessor(propertyAccess, typeProcessor, context, lprocessor); + } + else if (rawQualifier instanceof JSObjectLiteralExpression objectLiteral && typeProcessor instanceof ResolveProcessor) { + addTypeFromObjectLiteralExpression(objectLiteral, typeProcessor); + } + else if (rawQualifier instanceof JSParenthesizedExpression parenthesized) { + doEvalForExpr(parenthesized.getInnerExpression(), typeProcessor, context); + } + else if (rawQualifier instanceof JSThisExpression thisExpr) { + JSClass jsClass = JSResolveUtil.getClassOfContext(thisExpr); + if (jsClass != null) { + addType(jsClass.getQualifiedName(), typeProcessor, context, jsClass); + } + else { + typeProcessor.setUnknownElement(thisExpr); + } + } + else if (rawQualifier instanceof JSSuperExpression superExpr) { + JSClass jsClass = JSResolveUtil.getClassOfContext(superExpr); + if (jsClass != null) { + JSClass[] classes = jsClass.getSuperClasses(); + if (classes.length > 0) { + addType(classes[0].getQualifiedName(), typeProcessor, context, classes[0]); + } + } + } + else if (rawQualifier != null) { + typeProcessor.setUnknownElement(rawQualifier); + } + + JavaScriptType type = rawQualifier == null ? null : rawQualifier.getType(); + PsiElement targetElement = type == null ? null : type.getTargetElement(); + if (targetElement instanceof JSExpression jsTarget) { + doEvalForExpr(jsTarget, typeProcessor, context); + } + } + + private static boolean isSomeFunctionCall(JSExpression rawqualifier, String parameterType) { + return FUNCTION_TYPE_NAME.equals(parameterType) && rawqualifier.getParent() instanceof JSCallExpression; + } + + @RequiredReadAction + private static void addQNameFromElementAsType( + TypeProcessor typeProcessor, + EvaluateContext context, + PsiElement psiElement, + boolean passSource + ) { + String name = ((JSNamedElement)psiElement).getName(); + if (name == null) { + return; + } + if (psiElement instanceof JSQualifiedNamedElement qualifiedNamedElement) { + String qName = qualifiedNamedElement.getQualifiedName(); + if (qName != null) { + name = qName; + } + } + addType(name, typeProcessor, context, passSource ? psiElement : null); + } + + @RequiredReadAction + private static String evalComponentTypeFromArrayExpression( + JSExpression rawqualifier, + TypeProcessor typeProcessor, + EvaluateContext context, + JSExpression collectionExpression + ) { + if (collectionExpression != null) { + if (context.isAlreadyProcessingItem(rawqualifier)) { + return null; + } + context.addProcessingItem(rawqualifier); + SimpleTypeProcessor lprocessor = new SimpleTypeProcessor(typeProcessor.getFeatures()); + doEvalForExpr(collectionExpression, lprocessor, context); + return addComponentTypeFromProcessor(rawqualifier, typeProcessor, context, lprocessor); + } + + return null; + } + + private static String addComponentTypeFromProcessor( + JSExpression rawqualifier, + TypeProcessor typeProcessor, + EvaluateContext context, + SimpleTypeProcessor lprocessor + ) { + if (lprocessor.type != null) { + String type = lprocessor.type; + type = JSTypeEvaluateManager.isArrayType(type) ? JSTypeEvaluateManager.getComponentType(type) : "*"; + addType(JSImportHandlingUtil.resolveTypeName(type, rawqualifier), typeProcessor, context, rawqualifier); + return type; + } + return null; + } + + private static boolean isValidType(String parameterType) { + return parameterType != null && parameterType.length() > 0; + } + + private static boolean findDef( + TypeProcessor typeProcessor, + EvaluateContext context, + JSReferenceExpression qualifier, + ResolveProcessor processor + ) { + PsiElement parent = qualifier.getParent(); + JSResolveUtil.treeWalkUp(processor, qualifier, parent, qualifier); + + PsiElement jsElement = processor.getResult(); + if (jsElement instanceof JSDefinitionExpression) { + addTypeFromDefExpr(typeProcessor, context, jsElement); + return true; + } + return false; + } + + @RequiredReadAction + private static void tryAddBindowsType(JSReferenceExpression qualifier, TypeProcessor typeProcessor, EvaluateContext context) { + PsiElement element = qualifier.getParent(); + if (!(element instanceof JSCallExpression call)) { + return; + } + JSArgumentList argumentList = call.getArgumentList(); + if (argumentList == null) { + return; + } + JSExpression[] expressions = argumentList.getArguments(); + if (expressions.length == 0 || !(expressions[0] instanceof JSLiteralExpression)) { + return; + } + + String val = StringUtil.stripQuotesAroundValue(expressions[0].getText()); + PsiElement contextElement = qualifier.getContainingFile().getContext(); + + if (contextElement != null) { + PsiFile containingFile = contextElement.getContainingFile(); + + if (isBindowsXml(containingFile)) { + } + } + } + + @RequiredReadAction + private static boolean isBindowsXml(PsiFile containingFile) { + return containingFile.getName().endsWith(".xml") && containingFile instanceof XmlFile; + } + + private static void addTypeFromObjectLiteralExpression(JSExpression rawQualifier, TypeProcessor typeProcessor) { + JSProperty[] properties = ((JSObjectLiteralExpression)rawQualifier).getProperties(); + + boolean b = properties.length <= 0 || rawQualifier.processDeclarations( + (ResolveProcessor)typeProcessor, + ResolveState.initial(), + properties[0], + properties[0] + ); + if (b) { + typeProcessor.setUnknownElement(rawQualifier); + } + } + + @RequiredReadAction + private static void addTypeFromDefExpr(TypeProcessor typeProcessor, EvaluateContext context, PsiElement psiElement) { + String type = psiElement.getText(); + + if (!context.visitedTypes.contains(type)) { + context.visitedTypes.add(type); + PsiElement parentElement = psiElement.getParent(); + if (parentElement instanceof JSAssignmentExpression assignment) { + JSExpression expr = assignment.getROperand(); + while (expr instanceof JSAssignmentExpression rOperandAssignment) { + expr = rOperandAssignment.getROperand(); + } + if (expr != null) { + doEvalForExpr(expr, typeProcessor, context); + } + } + else { + typeProcessor.setUnknownElement(parentElement); + } + } + } + + private static void getTypeFromConstant(JSExpression rawqualifier, TypeProcessor typeProcessor, EvaluateContext context) { + ASTNode childNode = rawqualifier.getNode().getFirstChildNode(); + IElementType constantType = childNode.getElementType(); + + String type = JavaScriptTokenSets.STRING_LITERALS.contains(constantType) + ? STRING_TYPE_NAME + : constantType == JSTokenTypes.NUMERIC_LITERAL + ? NUMBER_TYPE_NAME + : constantType == JSTokenTypes.REGEXP_LITERAL + ? REG_EXP_TYPE_NAME + : constantType == JSTokenTypes.XML_START_TAG_START + ? XML_TYPE_NAME + : constantType == JSTokenTypes.XML_START_TAG_LIST + ? XML_LIST_TYPE_NAME + : constantType == JSTokenTypes.TRUE_KEYWORD || constantType == JSTokenTypes.FALSE_KEYWORD + ? BOOLEAN_TYPE_NAME + : null; + + if (type == NUMBER_TYPE_NAME && typeProcessor.ecma()) { + String text = childNode.getText(); + if (text.indexOf('.') == -1) { + type = INT_TYPE; + } + } + + if (type != null) { + addType(type, typeProcessor, context, rawqualifier); + } + else { + typeProcessor.setUnknownElement(rawqualifier); + } + } + + protected void addPackageScope(List possibleNameIds, JSClass jsClass, PsiElement expression) { + String packageQualifier = JSResolveUtil.findPackageStatementQualifier(expression); + String qName; + + if (packageQualifier != null) { + buildIndexListFromQNameAndCorrectQName(packageQualifier, jsClass, possibleNameIds); + } + else if (jsClass != null && (qName = jsClass.getQualifiedName()) != null && !qName.equals(jsClass.getName())) { + int index = qName.lastIndexOf('.'); + if (index > 0) { + buildIndexListFromQNameAndCorrectQName(qName.substring(0, index), jsClass, possibleNameIds); + } + } + else if (jsClass == null) { + String s = JSResolveUtil.findPackageForMxml(expression); + if (isValidType(s)) { + buildIndexListFromQNameAndCorrectQName(s, expression, possibleNameIds); + } + } + } + + protected String buildIndexListFromQNameAndCorrectQName(String type, PsiElement source, List possibleNameIds) { + List list = new ArrayList<>(); + type = addIndexListFromQName(type, source, list); + + possibleNameIds.add(ArrayUtil.toStringArray(list)); + return type; + } + + public static String addIndexListFromQName(String type, PsiElement source, List list) { + int i = type.indexOf('.'); + int lastI = 0; + + while (i != -1) { + list.add(type.substring(lastI, i)); + lastI = i + 1; + i = type.indexOf('.', lastI); + } + + if (i != type.length()) { + String s = type.substring(lastI, type.length()); + if (source == null) { + s = StringUtil.capitalize(s); // when type name goes from comments + } + if (lastI == 0 && !s.equals(type)) { + type = s; + } + list.add(s); + } + return type; + } + + private static void addType(String type, TypeProcessor typeProcessor, EvaluateContext context, PsiElement source) { + if (type == null) { + return; + } + int spacePos = type.indexOf(' '); + if (spacePos != -1) { + type = type.substring(0, spacePos); + } + + if (!(typeProcessor instanceof GenericTypeParametersClient)) { + int gtPos = type.indexOf('<'); + if (gtPos > 0 && type.charAt(gtPos - 1) == '.') { + type = type.substring(0, gtPos - 1); + } + } + + if (!typeProcessor.ecma()) { + type = JSTypeEvaluateManager.getInstanceNameByType(type); + } + typeProcessor.process(type, context, source); + } + + @Override + public T getHint(Key hintClass) { + return null; + } + + @Override + public void handleEvent(Event event, Object associated) { + } + + enum MatchType { + COMPLETE_TYPE, + COMPLETE, + COMPLETE_NS, + PARTIAL, + NOMATCH + } + + interface HierarchyProcessor { + boolean processClass(JSClass clazz); + } + + protected void doIterateTypeHierarchy(String[] contextIds, HierarchyProcessor processor) { + StringBuilder builder = new StringBuilder(); + for (String cnameId : contextIds) { + if (builder.length() > 0) { + builder.append('.'); + } + builder.append(cnameId); + } + + String typeName = builder.toString(); + if (typeName.length() == 0) { + return; + } + + myIteratedTypeName = typeName; + doIterateHierarchy(typeName, processor); + myIteratedTypeName = null; + } + + protected void doIterateHierarchy(String typeName, final HierarchyProcessor processor) { + PsiElement clazz = JSResolveUtil.findClassByQName(typeName, myContext); + if (clazz instanceof JSClass jsClass) { + for (JSClass superClazz : jsClass.getSuperClasses()) { + superClazz.processDeclarations( + new ResolveProcessor(null) { + { + setToProcessMembers(false); + setToProcessHierarchy(true); + setTypeContext(true); + } + + @Override + @RequiredReadAction + public boolean execute(@Nonnull PsiElement element, ResolveState state) { + return !(element instanceof JSClass jsClass && !processor.processClass(jsClass)); + } + }, + ResolveState.initial(), + null, + clazz + ); + } + } + } + + public static class EvaluateContext { + public final PsiFile targetFile; + public final Set visitedTypes = new HashSet<>(); + private Set processingItems; + private PsiElement source; + + public EvaluateContext(PsiFile targetFile) { + this.targetFile = targetFile; + } + + public boolean isAlreadyProcessingItem(JSExpression rawqualifier) { + return processingItems != null && processingItems.contains(rawqualifier); + } + + public void addProcessingItem(JSExpression rawqualifier) { + if (processingItems == null) { + processingItems = new HashSet<>(); + } + processingItems.add(rawqualifier); + } + + public void removeProcessingItem(JSExpression rawqualifier) { + processingItems.remove(rawqualifier); + } + + public PsiElement getSource() { + return source; + } + + public void setSource(PsiElement source) { + this.source = source; + } + } + + public interface TypeProcessor { + void process(@Nonnull String type, @Nonnull EvaluateContext evaluateContext, PsiElement source); + + @Deprecated + boolean ecma(); + + Set getFeatures(); + + void setUnknownElement(@Nonnull PsiElement element); + } + + public interface GenericTypeParametersClient { + } + + public static class SimpleTypeProcessor extends ResolveProcessor implements TypeProcessor, GenericTypeParametersClient { + private String type; + private PsiElement result; + private PsiElement source; + private final Set myFeatures; + + public SimpleTypeProcessor(Set features) { + super(null); + myFeatures = features; + } + + @Override + public void process(@Nonnull String _type, @Nonnull EvaluateContext evaluateContext, PsiElement _source) { + setType(type != null && !type.equals(_type) ? ANY_TYPE : _type, _source); + } + + private void setType(String s, PsiElement _source) { + type = s; + source = _source; + } + + @Override + public Set getFeatures() { + return myFeatures; + } + + @Override + public boolean ecma() { + return myFeatures.contains(JavaScriptFeature.CLASS); + } + + @Override + @RequiredReadAction + public boolean execute(@Nonnull PsiElement element, ResolveState state) { + result = element; + return true; + } + + @Override + public void setUnknownElement(@Nonnull PsiElement _element) { + setType(ANY_TYPE, _element); + } + + public String getType() { + return type; + } + + public PsiElement getSource() { + return source; + } + } + + public static class TagContextBuilder { + public final PsiElement element; + public final String typeName; + + public TagContextBuilder(PsiElement psiElement, String defaultName) { + String typeName = null; + XmlTag tag = PsiTreeUtil.getParentOfType(psiElement, XmlTag.class); + JSClass element = null; + + if (tag != null) { + PsiFile containingFile = tag.getContainingFile(); + + if (isBindowsXml(containingFile)) { + typeName = "Bi" + tag.getLocalName(); + } + else { + element = JSResolveUtil.getClassFromTagNameInMxml(tag); + typeName = element != null ? element.getQualifiedName() : null; + } + } + + if (typeName == null) { + typeName = defaultName; + } + + this.typeName = typeName; + this.element = element; + } + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/CompletionProcessor.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/CompletionProcessor.java index 97dca68f..7e032ce5 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/CompletionProcessor.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/CompletionProcessor.java @@ -17,15 +17,13 @@ package com.intellij.lang.javascript.psi.resolve; /** - * @by Maxim.Mossienko + * @author Maxim.Mossienko */ -public class CompletionProcessor extends ResolveProcessor -{ - private boolean myInVarDcl; - private boolean myInFuncDcl; +public class CompletionProcessor extends ResolveProcessor { + private boolean myInVarDcl; + private boolean myInFuncDcl; - public CompletionProcessor() - { - super(null); - } + public CompletionProcessor() { + super(null); + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/JSImportHandlingUtil.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/JSImportHandlingUtil.java index 84b61da6..1545185c 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/JSImportHandlingUtil.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/JSImportHandlingUtil.java @@ -44,8 +44,9 @@ import consulo.xml.psi.xml.XmlFile; import consulo.xml.psi.xml.XmlTag; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; + import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -54,543 +55,437 @@ /** * @author Maxim.Mossienko - * Date: Jul 29, 2008 - * Time: 6:52:42 PM + * @since 2008-07-29 */ -public class JSImportHandlingUtil -{ - public static final Key>> ourImportListCache = Key.create("js.import.list.cache"); - public static final UserDataCache>, PsiElement, Object> myImportListCache = new ImportListDataCache(); - public static final Key>> ourImportResolveCache = Key.create("js.import.resolve"); - public static final UserDataCache>, PsiElement, Object> myImportResolveCache = new UserDataCache>, PsiElement, Object>() - { - @Override - protected CachedValue> compute(final PsiElement psiElement, final Object p) - { - return CachedValuesManager.getManager(psiElement.getProject()).createCachedValue(new CachedValueProvider>() - { - @Override - public Result> compute() - { - return new Result>(new ConcurrentHashMap(), PsiModificationTracker.MODIFICATION_COUNT); - } - }, false); - } - }; - - public static String resolveTypeName(final String _str, @Nonnull PsiElement context) - { - final JSImportedElementResolveResult resolveResult = _resolveTypeName(_str, context); - if(resolveResult == null) - { - return _str; - } - return resolveResult.qualifiedName; - } - - // TODO _str should be JSReferenceExpression for caching! - private static JSImportedElementResolveResult _resolveTypeName(final String _name, @Nonnull PsiElement context) - { - String name = _name; - if(name == null) - { - return null; - } - final int i = name.indexOf('<'); - String signature = null; - - if(i != -1) - { - final int index = name.lastIndexOf('.', i); - if(index == -1) - { - return null; - } - signature = name.substring(index); - name = name.substring(0, index); - } - - if(name.indexOf('.') != -1) - { - return null; - } - - final Ref resultRef = new Ref(); - - final String name1 = name; - JSResolveUtil.walkOverStructure(context, new Processor() - { - @Override - public boolean process(PsiNamedElement context) - { - JSImportedElementResolveResult resolved = null; - - if(context instanceof XmlBackedJSClassImpl) - { // reference list in mxml - XmlTag rootTag = ((XmlBackedJSClassImpl) context).getParent(); - final XmlElementDescriptor descriptor = rootTag != null ? rootTag.getDescriptor() : null; - PsiElement element = descriptor != null ? descriptor.getDeclaration() : null; - if(element instanceof XmlFile) - { - element = XmlBackedJSClassImpl.getXmlBackedClass((XmlFile) element); - } - - final String s = element instanceof JSClass ? ((JSClass) element).getQualifiedName() : rootTag.getLocalName(); - resolved = new JSImportedElementResolveResult(s); - } - else if(context instanceof JSQualifiedNamedElement) - { - if(context instanceof JSClass && name1.equals(context.getName())) - { - resolved = new JSImportedElementResolveResult(((JSQualifiedNamedElement) context).getQualifiedName()); - } - else - { - resolved = resolveTypeNameUsingImports(name1, context); - - if(resolved == null) - { - final String qName = ((JSQualifiedNamedElement) context).getQualifiedName(); - final String packageName = qName != null ? context instanceof JSPackageStatement ? qName + "." : qName.substring(0, qName.lastIndexOf('.') + 1) : ""; - - if(packageName.length() != 0) - { - final PsiElement byQName = JSClassBase.findClassFromNamespace(packageName + name1, context); - - if(byQName instanceof JSQualifiedNamedElement) - { - resolved = new JSImportedElementResolveResult(((JSQualifiedNamedElement) byQName).getQualifiedName()); - } - } - } - } - } - else - { - resolved = resolveTypeNameUsingImports(name1, context); - PsiElement contextOfContext; - - if(resolved == null && context instanceof JSFile && (contextOfContext = context.getContext()) != null) - { - PsiFile containingFile = contextOfContext.getContainingFile(); - XmlBackedJSClassImpl clazz = containingFile instanceof XmlFile ? (XmlBackedJSClassImpl) XmlBackedJSClassImpl.getXmlBackedClass((XmlFile) containingFile) : null; - - if(clazz != null) - { - ResolveProcessor r = new ResolveProcessor(name1); - if(!clazz.processComponentNames(r)) - { - PsiElement resultFromProcessor = r.getResult(); - JSClass clazzFromComponent = resultFromProcessor instanceof JSClass ? (JSClass) resultFromProcessor : null; - - if(clazzFromComponent != null) - { - resolved = new JSImportedElementResolveResult(clazzFromComponent.getQualifiedName(), clazz, null); - } - } - } - } - } - - if(resolved != null) - { - resultRef.set(resolved); - return false; - } - - if(context instanceof JSPackageStatement) - { - return false; - } - return true; - } - }); - - JSImportedElementResolveResult result = resultRef.get(); - - if(signature != null && result != null) - { - result = result.appendSignature(signature); - } - return result; - } - - private static JSQualifiedNamedElement resolveTypeNameInTheSamePackage(final String str, final PsiElement context) - { - final String packageQualifierText = JSResolveUtil.findPackageStatementQualifier(context); - final String candidateText = packageQualifierText != null ? packageQualifierText + "." + str : str; - - PsiElement byQName = JSClassBase.findClassFromNamespace(candidateText, context); - if(byQName instanceof JSQualifiedNamedElement) - { - return (JSQualifiedNamedElement) byQName; - } - - if(packageQualifierText != null) - { - byQName = JSClassBase.findClassFromNamespace(str, context); - if(byQName instanceof JSQualifiedNamedElement) - { - return (JSQualifiedNamedElement) byQName; - } - } - - return null; - } - - public static - @Nullable - JSImportedElementResolveResult resolveTypeNameUsingImports(@Nonnull final JSReferenceExpression expr) - { - if(expr.getQualifier() != null) - { - return null; - } - if(JSResolveUtil.referenceExpressionShouldBeQualified(expr)) - { - return null; - } - - if(expr.getReferencedName() == null) - { - return null; - } - - return _resolveTypeName(expr.getText(), expr); - } - - private static - @Nullable - JSImportedElementResolveResult resolveTypeNameUsingImports(final @Nonnull String referencedName, PsiNamedElement parent) - { - LanguageVersion languageVersion = parent.getLanguageVersion(); - if(languageVersion instanceof JavaScriptVersionWithHelper) - { - ResolveHelper helper = ((JavaScriptVersionWithHelper) languageVersion).getHelper(); - - JSImportedElementResolveResult result = helper.resolveTypeNameUsingImports(referencedName, parent); - if(result != null) - { - return result; - } - } - - final Map map = myImportResolveCache.get(ourImportResolveCache, parent, null).getValue(); - JSImportedElementResolveResult result = map.get(referencedName); - - if(result == null) - { - result = resolveTypeNameUsingImportsInner(referencedName, parent); - map.put(referencedName, result != null ? result : JSImportedElementResolveResult.EMPTY_RESULT); - } - - return result != JSImportedElementResolveResult.EMPTY_RESULT ? result : null; - } - - private static JSImportedElementResolveResult resolveTypeNameUsingImportsInner(final String referencedName, final PsiNamedElement parent) - { - final Map value = myImportListCache.get(ourImportListCache, parent, null).getValue(); - JSImportedElementResolveResult expression = FlexImportSupport.tryFindInMap(referencedName, parent, value); - if(expression != null) - { - return expression; - } - - if(parent instanceof JSPackageStatement) - { - return checkTheSamePackageOrGlobal(referencedName, parent); - } - else if(parent instanceof JSFile && parent.getLanguage().isKindOf(JavaScriptSupportLoader.ECMA_SCRIPT_L4)) - { - final PsiElement element = JSResolveUtil.getClassReferenceForXmlFromContext(parent); - - if(element instanceof XmlBackedJSClassImpl) - { - final ResolveProcessor processor = new ResolveProcessor(referencedName); - final boolean b = ((XmlBackedJSClassImpl) element).doImportFromScripts(processor, parent); - - if(!b) - { - final JSQualifiedNamedElement jsClass = (JSQualifiedNamedElement) processor.getResult(); - return new JSImportedElementResolveResult(jsClass.getQualifiedName(), jsClass, processor.getImportUsed()); - } - - JSQualifiedNamedElement jsClass = resolveTypeNameInTheSamePackage(referencedName, element); - - if(jsClass == null) - { - final JSClass parentClass = (JSClass) element; - final JSClass[] classes = parentClass.getSuperClasses(); - - if(classes != null && classes.length > 0 && referencedName.equals(classes[0].getName())) - { - jsClass = classes[0]; - } - } - - if(jsClass != null) - { - return new JSImportedElementResolveResult(jsClass.getQualifiedName(), jsClass, null); - } - } - else - { - final JSImportedElementResolveResult resolveResult = checkTheSamePackageOrGlobal(referencedName, parent); - if(resolveResult != null) - { - return resolveResult; - } - } - - expression = FlexImportSupport.resolveTypeNameUsingImplicitImports(referencedName, (JSFile) parent); - if(expression != null) - { - return expression; - } - } - else if(parent instanceof XmlBackedJSClassImpl) - { - JSQualifiedNamedElement jsClass = resolveTypeNameInTheSamePackage(referencedName, parent); - if(jsClass != null) - { - return new JSImportedElementResolveResult(jsClass.getQualifiedName(), jsClass, null); - } - - final Ref result = new Ref(); - processInlineComponentsInScope((XmlBackedJSClassImpl) parent, new Processor() - { - @Override - public boolean process(XmlBackedJSClassImpl inlineComponent) - { - if(referencedName.equals(inlineComponent.getExplicitName())) - { - result.set(new JSImportedElementResolveResult(inlineComponent.getQualifiedName(), inlineComponent, null)); - return false; - } - return true; - } - }); - if(!result.isNull()) - { - return result.get(); - } - } - - return null; - } - - private static boolean processInlineComponentsInScope(XmlBackedJSClassImpl context, Processor processor) - { - XmlTag rootTag = ((XmlFile) context.getContainingFile()).getDocument().getRootTag(); - boolean recursive = XmlBackedJSClassImpl.isInlineComponentTag(context.getParent()); - for(XmlBackedJSClassImpl inlineComponent : XmlBackedJSClassImpl.getChildInlineComponents(rootTag, recursive)) - { - if(!processor.process(inlineComponent)) - { - return false; - } - } - return true; - } - - private static JSImportedElementResolveResult checkTheSamePackageOrGlobal(final String referencedName, final PsiNamedElement parent) - { - final JSQualifiedNamedElement jsClass = resolveTypeNameInTheSamePackage(referencedName, parent); - - if(jsClass != null) - { - return new JSImportedElementResolveResult(jsClass.getQualifiedName(), jsClass, null); - } - return null; - } - - public static boolean tryResolveImports(final PsiScopeProcessor processor, PsiNamedElement parent, @Nonnull PsiElement place) - { - if(!isAdequatePlaceForImport(parent, place)) - { - return true; - } - - return !importClass(processor, parent); - } - - public static boolean importClass(final PsiScopeProcessor processor, final PsiNamedElement parent) - { - if(processor instanceof ResolveProcessor && ((ResolveProcessor) processor).isLocalResolve()) - { - return false; - } - ResolveProcessor resolveProcessor = (ResolveProcessor) processor; - final String s = resolveProcessor.getName(); - - if(s != null) - { - if(resolveProcessor.specificallyAskingToResolveQualifiedNames()) - { - final Map value = myImportListCache.get(ourImportListCache, parent, null).getValue(); - JSImportedElementResolveResult resolveResult = FlexImportSupport.tryFindInMap(s, parent, value, resolveProcessor.getQualifiedNameToImport()); - if(dispatchResult(resolveResult, processor)) - { - return true; - } - } - - final JSImportedElementResolveResult expression = resolveTypeNameUsingImports(s, parent); - - if(dispatchResult(expression, processor)) - { - return true; - } - } - else - { - if(parent instanceof XmlBackedJSClassImpl) - { - if(!processInlineComponentsInScope((XmlBackedJSClassImpl) parent, new Processor() - { - @Override - public boolean process(XmlBackedJSClassImpl inlineComponent) - { - return processor.execute(inlineComponent, ResolveState.initial()); - } - })) - { - return false; - } - } - final String packageQualifierText = JSResolveUtil.findPackageStatementQualifier(parent); - importClassViaHelper(processor, parent, packageQualifierText); - } - - return false; - } - - private static boolean dispatchResult(JSImportedElementResolveResult expression, PsiScopeProcessor processor) - { - if(expression != null) - { - final PsiElement element = expression.resolvedElement; - - if(element != null) - { - ResolveState state = ResolveState.initial(); - if(expression.importStatement != null) - { - state = state.put(ResolveProcessor.IMPORT_KEY, expression.importStatement); - } - return !processor.execute(element, state); - } - } - - return false; - } - - public static void importClassViaHelper(final PsiScopeProcessor processor, final PsiNamedElement file, final String packageQualifierText) - { - for(JSResolveHelper helper : Extensions.getExtensions(JSResolveHelper.EP_NAME)) - { - helper.importClass(processor, file, packageQualifierText); - } - } - - public static boolean isAdequatePlaceForImport(final PsiNamedElement parent, @Nonnull PsiElement place) - { - if(parent instanceof JSFile && !parent.getLanguage().isKindOf(JavaScriptSupportLoader.ECMA_SCRIPT_L4)) - { - return false; - } - - if(place instanceof JSReferenceExpression) - { - final PsiElement placeParent = place.getParent(); - - if(placeParent instanceof JSReferenceExpression) - { - final PsiElement currentParent = JSResolveUtil.getTopReferenceParent(placeParent); - - if(JSResolveUtil.isSelfReference(currentParent, place) || - //currentParent instanceof JSDefinitionExpression || - currentParent instanceof JSReferenceList) - { - return false; - } - } - } - else if(place instanceof JSDocTagValue) - { - // further conditions to come - } - else - { - if(!(place instanceof JSFile)) - { - return false; - } - } - - return true; - } - - private static class ImportListDataCache extends UserDataCache>, PsiElement, Object> - { - @Override - protected final CachedValue> compute(final PsiElement owner, Object o) - { - return CachedValuesManager.getManager(owner.getProject()).createCachedValue(new CachedValueProvider>() - { - @Override - public Result> compute() - { - final Map result = new HashMap(); - collect(result, owner, null); - return new Result>(result, owner); - } - }, false); - } - - private static void collect(final Map result, final PsiElement owner, Set visitedIncludes) - { - PsiElement[] children = PsiElement.EMPTY_ARRAY; - - if(owner instanceof JSIncludeDirective) - { - final PsiFile file = ((JSIncludeDirective) owner).resolveFile(); - if(file != null && (visitedIncludes == null || !visitedIncludes.contains(file))) - { - if(visitedIncludes == null) - { - visitedIncludes = new HashSet(); - } - visitedIncludes.add(file); - children = JSResolveUtil.getSourceElements(file); - } - } - else if(owner instanceof JSFile || owner instanceof JSStubElementImpl) - { - children = JSResolveUtil.getSourceElements(owner); - } - else - { - children = owner.getChildren(); - } - - for(PsiElement c : children) - { - if(c instanceof JSImportStatement) - { - final JSImportStatement s = ((JSImportStatement) c); - - if(s.getImportText() != null) - { - FlexImportSupport.appendToMap(result, s); - } - } - else if(!(c instanceof JSPackageStatement) && !(c instanceof JSFunction)) - { - collect(result, c, visitedIncludes); - } - } - } - } +public class JSImportHandlingUtil { + public static final Key>> IMPORT_LIST_CACHE_KEY = Key.create("js.import.list.cache"); + public static final UserDataCache>, PsiElement, Object> IMPORT_LIST_CACHE = new ImportListDataCache(); + public static final Key>> IMPORT_RESOLVE_CACHE_KEY = + Key.create("js.import.resolve"); + public static final UserDataCache>, PsiElement, Object> + IMPORT_RESOLVE_CACHE = + new UserDataCache<>() { + @Override + protected CachedValue> compute(PsiElement psiElement, Object p) { + return CachedValuesManager.getManager(psiElement.getProject()).createCachedValue( + () -> new CachedValueProvider.Result>( + new ConcurrentHashMap<>(), + PsiModificationTracker.MODIFICATION_COUNT + ), + false + ); + } + }; + + public static String resolveTypeName(String _str, @Nonnull PsiElement context) { + JSImportedElementResolveResult resolveResult = _resolveTypeName(_str, context); + if (resolveResult == null) { + return _str; + } + return resolveResult.qualifiedName; + } + + // TODO _str should be JSReferenceExpression for caching! + private static JSImportedElementResolveResult _resolveTypeName(String _name, @Nonnull PsiElement context) { + String name = _name; + if (name == null) { + return null; + } + int i = name.indexOf('<'); + String signature = null; + + if (i != -1) { + int index = name.lastIndexOf('.', i); + if (index == -1) { + return null; + } + signature = name.substring(index); + name = name.substring(0, index); + } + + if (name.indexOf('.') != -1) { + return null; + } + + Ref resultRef = new Ref(); + + String name1 = name; + JSResolveUtil.walkOverStructure( + context, + context1 -> { + JSImportedElementResolveResult resolved = null; + + if (context1 instanceof XmlBackedJSClassImpl xmlBackedJSClass) { // reference list in mxml + XmlTag rootTag = xmlBackedJSClass.getParent(); + XmlElementDescriptor descriptor = rootTag != null ? rootTag.getDescriptor() : null; + PsiElement element = descriptor != null ? descriptor.getDeclaration() : null; + if (element instanceof XmlFile xmlFile) { + element = XmlBackedJSClassImpl.getXmlBackedClass(xmlFile); + } + + String s = element instanceof JSClass jsClass ? jsClass.getQualifiedName() : rootTag.getLocalName(); + resolved = new JSImportedElementResolveResult(s); + } + else if (context1 instanceof JSQualifiedNamedElement qualifiedNamedElement) { + if (context1 instanceof JSClass && name1.equals(context1.getName())) { + resolved = new JSImportedElementResolveResult(qualifiedNamedElement.getQualifiedName()); + } + else { + resolved = resolveTypeNameUsingImports(name1, qualifiedNamedElement); + + if (resolved == null) { + String qName = qualifiedNamedElement.getQualifiedName(); + String packageName = qName != null ? context1 instanceof JSPackageStatement + ? qName + "." + : qName.substring(0, qName.lastIndexOf('.') + 1) : ""; + + if (packageName.length() != 0) { + PsiElement byQName = JSClassBase.findClassFromNamespace(packageName + name1, context1); + + if (byQName instanceof JSQualifiedNamedElement byQNameNamed) { + resolved = new JSImportedElementResolveResult(byQNameNamed.getQualifiedName()); + } + } + } + } + } + else { + resolved = resolveTypeNameUsingImports(name1, context1); + PsiElement contextOfContext; + + if (resolved == null && context1 instanceof JSFile && (contextOfContext = context1.getContext()) != null) { + PsiFile containingFile = contextOfContext.getContainingFile(); + XmlBackedJSClassImpl clazz = containingFile instanceof XmlFile + ? (XmlBackedJSClassImpl)XmlBackedJSClassImpl.getXmlBackedClass((XmlFile)containingFile) : null; + + if (clazz != null) { + ResolveProcessor r = new ResolveProcessor(name1); + if (!clazz.processComponentNames(r)) { + PsiElement resultFromProcessor = r.getResult(); + JSClass clazzFromComponent = resultFromProcessor instanceof JSClass jsClass ? jsClass : null; + + if (clazzFromComponent != null) { + resolved = new JSImportedElementResolveResult(clazzFromComponent.getQualifiedName(), clazz, null); + } + } + } + } + } + + if (resolved != null) { + resultRef.set(resolved); + return false; + } + + return !(context1 instanceof JSPackageStatement); + } + ); + + JSImportedElementResolveResult result = resultRef.get(); + + if (signature != null && result != null) { + result = result.appendSignature(signature); + } + return result; + } + + private static JSQualifiedNamedElement resolveTypeNameInTheSamePackage(String str, PsiElement context) { + String packageQualifierText = JSResolveUtil.findPackageStatementQualifier(context); + String candidateText = packageQualifierText != null ? packageQualifierText + "." + str : str; + + PsiElement byQName = JSClassBase.findClassFromNamespace(candidateText, context); + if (byQName instanceof JSQualifiedNamedElement) { + return (JSQualifiedNamedElement)byQName; + } + + if (packageQualifierText != null) { + byQName = JSClassBase.findClassFromNamespace(str, context); + if (byQName instanceof JSQualifiedNamedElement qualifiedNamedElement) { + return qualifiedNamedElement; + } + } + + return null; + } + + public static + @Nullable + JSImportedElementResolveResult resolveTypeNameUsingImports(@Nonnull JSReferenceExpression expr) { + if (expr.getQualifier() != null) { + return null; + } + if (JSResolveUtil.referenceExpressionShouldBeQualified(expr)) { + return null; + } + + if (expr.getReferencedName() == null) { + return null; + } + + return _resolveTypeName(expr.getText(), expr); + } + + private static + @Nullable + JSImportedElementResolveResult resolveTypeNameUsingImports(@Nonnull String referencedName, PsiNamedElement parent) { + LanguageVersion languageVersion = parent.getLanguageVersion(); + if (languageVersion instanceof JavaScriptVersionWithHelper javaScriptVersionWithHelper) { + ResolveHelper helper = javaScriptVersionWithHelper.getHelper(); + + JSImportedElementResolveResult result = helper.resolveTypeNameUsingImports(referencedName, parent); + if (result != null) { + return result; + } + } + + Map map = IMPORT_RESOLVE_CACHE.get(IMPORT_RESOLVE_CACHE_KEY, parent, null).getValue(); + JSImportedElementResolveResult result = map.get(referencedName); + + if (result == null) { + result = resolveTypeNameUsingImportsInner(referencedName, parent); + map.put(referencedName, result != null ? result : JSImportedElementResolveResult.EMPTY_RESULT); + } + + return result != JSImportedElementResolveResult.EMPTY_RESULT ? result : null; + } + + private static JSImportedElementResolveResult resolveTypeNameUsingImportsInner( + String referencedName, + PsiNamedElement parent + ) { + Map value = IMPORT_LIST_CACHE.get(IMPORT_LIST_CACHE_KEY, parent, null).getValue(); + JSImportedElementResolveResult expression = FlexImportSupport.tryFindInMap(referencedName, parent, value); + if (expression != null) { + return expression; + } + + if (parent instanceof JSPackageStatement) { + return checkTheSamePackageOrGlobal(referencedName, parent); + } + else if (parent instanceof JSFile && parent.getLanguage().isKindOf(JavaScriptSupportLoader.ECMA_SCRIPT_L4)) { + PsiElement element = JSResolveUtil.getClassReferenceForXmlFromContext(parent); + + if (element instanceof XmlBackedJSClassImpl xmlBackedJSClass) { + ResolveProcessor processor = new ResolveProcessor(referencedName); + boolean b = xmlBackedJSClass.doImportFromScripts(processor, parent); + + if (!b) { + JSQualifiedNamedElement jsClass = (JSQualifiedNamedElement)processor.getResult(); + return new JSImportedElementResolveResult(jsClass.getQualifiedName(), jsClass, processor.getImportUsed()); + } + + JSQualifiedNamedElement jsClass = resolveTypeNameInTheSamePackage(referencedName, element); + + if (jsClass == null) { + JSClass parentClass = (JSClass)element; + JSClass[] classes = parentClass.getSuperClasses(); + + if (classes != null && classes.length > 0 && referencedName.equals(classes[0].getName())) { + jsClass = classes[0]; + } + } + + if (jsClass != null) { + return new JSImportedElementResolveResult(jsClass.getQualifiedName(), jsClass, null); + } + } + else { + JSImportedElementResolveResult resolveResult = checkTheSamePackageOrGlobal(referencedName, parent); + if (resolveResult != null) { + return resolveResult; + } + } + + expression = FlexImportSupport.resolveTypeNameUsingImplicitImports(referencedName, (JSFile)parent); + if (expression != null) { + return expression; + } + } + else if (parent instanceof XmlBackedJSClassImpl xmlBackedJSClass) { + JSQualifiedNamedElement jsClass = resolveTypeNameInTheSamePackage(referencedName, parent); + if (jsClass != null) { + return new JSImportedElementResolveResult(jsClass.getQualifiedName(), jsClass, null); + } + + Ref result = new Ref(); + processInlineComponentsInScope( + xmlBackedJSClass, + inlineComponent -> { + if (referencedName.equals(inlineComponent.getExplicitName())) { + result.set(new JSImportedElementResolveResult(inlineComponent.getQualifiedName(), inlineComponent, null)); + return false; + } + return true; + } + ); + if (!result.isNull()) { + return result.get(); + } + } + + return null; + } + + private static boolean processInlineComponentsInScope(XmlBackedJSClassImpl context, Processor processor) { + XmlTag rootTag = ((XmlFile)context.getContainingFile()).getDocument().getRootTag(); + boolean recursive = XmlBackedJSClassImpl.isInlineComponentTag(context.getParent()); + for (XmlBackedJSClassImpl inlineComponent : XmlBackedJSClassImpl.getChildInlineComponents(rootTag, recursive)) { + if (!processor.process(inlineComponent)) { + return false; + } + } + return true; + } + + private static JSImportedElementResolveResult checkTheSamePackageOrGlobal(String referencedName, PsiNamedElement parent) { + JSQualifiedNamedElement jsClass = resolveTypeNameInTheSamePackage(referencedName, parent); + + if (jsClass != null) { + return new JSImportedElementResolveResult(jsClass.getQualifiedName(), jsClass, null); + } + return null; + } + + public static boolean tryResolveImports(PsiScopeProcessor processor, PsiNamedElement parent, @Nonnull PsiElement place) { + return !isAdequatePlaceForImport(parent, place) || !importClass(processor, parent); + } + + public static boolean importClass(PsiScopeProcessor processor, PsiNamedElement parent) { + if (processor instanceof ResolveProcessor resolveProcessor && resolveProcessor.isLocalResolve()) { + return false; + } + ResolveProcessor resolveProcessor = (ResolveProcessor)processor; + String s = resolveProcessor.getName(); + + if (s != null) { + if (resolveProcessor.specificallyAskingToResolveQualifiedNames()) { + Map value = IMPORT_LIST_CACHE.get(IMPORT_LIST_CACHE_KEY, parent, null).getValue(); + JSImportedElementResolveResult resolveResult = + FlexImportSupport.tryFindInMap(s, parent, value, resolveProcessor.getQualifiedNameToImport()); + if (dispatchResult(resolveResult, processor)) { + return true; + } + } + + JSImportedElementResolveResult expression = resolveTypeNameUsingImports(s, parent); + + if (dispatchResult(expression, processor)) { + return true; + } + } + else { + if (parent instanceof XmlBackedJSClassImpl xmlBackedJSClass && !processInlineComponentsInScope( + xmlBackedJSClass, + inlineComponent -> processor.execute(inlineComponent, ResolveState.initial()) + )) { + return false; + } + String packageQualifierText = JSResolveUtil.findPackageStatementQualifier(parent); + importClassViaHelper(processor, parent, packageQualifierText); + } + + return false; + } + + private static boolean dispatchResult(JSImportedElementResolveResult expression, PsiScopeProcessor processor) { + if (expression != null) { + PsiElement element = expression.resolvedElement; + + if (element != null) { + ResolveState state = ResolveState.initial(); + if (expression.importStatement != null) { + state = state.put(ResolveProcessor.IMPORT_KEY, expression.importStatement); + } + return !processor.execute(element, state); + } + } + + return false; + } + + public static void importClassViaHelper( + PsiScopeProcessor processor, + PsiNamedElement file, + String packageQualifierText + ) { + for (JSResolveHelper helper : Extensions.getExtensions(JSResolveHelper.EP_NAME)) { + helper.importClass(processor, file, packageQualifierText); + } + } + + public static boolean isAdequatePlaceForImport(PsiNamedElement parent, @Nonnull PsiElement place) { + if (parent instanceof JSFile && !parent.getLanguage().isKindOf(JavaScriptSupportLoader.ECMA_SCRIPT_L4)) { + return false; + } + + if (place instanceof JSReferenceExpression) { + PsiElement placeParent = place.getParent(); + + if (placeParent instanceof JSReferenceExpression) { + PsiElement currentParent = JSResolveUtil.getTopReferenceParent(placeParent); + + if (JSResolveUtil.isSelfReference(currentParent, place) || + //currentParent instanceof JSDefinitionExpression || + currentParent instanceof JSReferenceList) { + return false; + } + } + } + else if (place instanceof JSDocTagValue) { + // further conditions to come + } + else if (!(place instanceof JSFile)) { + return false; + } + + return true; + } + + private static class ImportListDataCache extends UserDataCache>, PsiElement, Object> { + @Override + protected final CachedValue> compute(PsiElement owner, Object o) { + return CachedValuesManager.getManager(owner.getProject()).createCachedValue( + () -> { + Map result = new HashMap<>(); + collect(result, owner, null); + return new CachedValueProvider.Result<>(result, owner); + }, + false + ); + } + + private static void collect(Map result, PsiElement owner, Set visitedIncludes) { + PsiElement[] children = PsiElement.EMPTY_ARRAY; + + if (owner instanceof JSIncludeDirective includeDirective) { + PsiFile file = includeDirective.resolveFile(); + if (file != null && (visitedIncludes == null || !visitedIncludes.contains(file))) { + if (visitedIncludes == null) { + visitedIncludes = new HashSet<>(); + } + visitedIncludes.add(file); + children = JSResolveUtil.getSourceElements(file); + } + } + else if (owner instanceof JSFile || owner instanceof JSStubElementImpl) { + children = JSResolveUtil.getSourceElements(owner); + } + else { + children = owner.getChildren(); + } + + for (PsiElement c : children) { + if (c instanceof JSImportStatement) { + JSImportStatement s = ((JSImportStatement)c); + + if (s.getImportText() != null) { + FlexImportSupport.appendToMap(result, s); + } + } + else if (!(c instanceof JSPackageStatement) && !(c instanceof JSFunction)) { + collect(result, c, visitedIncludes); + } + } + } + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/JSImportedElementResolveResult.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/JSImportedElementResolveResult.java index 8cce5e44..4b98a3ab 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/JSImportedElementResolveResult.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/JSImportedElementResolveResult.java @@ -21,30 +21,25 @@ /** * @author Maxim.Mossienko - * Date: Jul 29, 2008 - * Time: 8:04:55 PM + * @since 2008-07-29 */ -public class JSImportedElementResolveResult -{ - public final String qualifiedName; - public final PsiElement resolvedElement; - public final JavaScriptImportStatementBase importStatement; - public static final JSImportedElementResolveResult EMPTY_RESULT = new JSImportedElementResolveResult(null); +public class JSImportedElementResolveResult { + public final String qualifiedName; + public final PsiElement resolvedElement; + public final JavaScriptImportStatementBase importStatement; + public static final JSImportedElementResolveResult EMPTY_RESULT = new JSImportedElementResolveResult(null); - public JSImportedElementResolveResult(String _qualifiedName) - { - this(_qualifiedName, null, null); - } + public JSImportedElementResolveResult(String _qualifiedName) { + this(_qualifiedName, null, null); + } - public JSImportedElementResolveResult(String _qualifiedName, PsiElement _resolvedElement, JavaScriptImportStatementBase _importString) - { - qualifiedName = _qualifiedName; - resolvedElement = _resolvedElement; - importStatement = _importString; - } + public JSImportedElementResolveResult(String _qualifiedName, PsiElement _resolvedElement, JavaScriptImportStatementBase _importString) { + qualifiedName = _qualifiedName; + resolvedElement = _resolvedElement; + importStatement = _importString; + } - public JSImportedElementResolveResult appendSignature(final String s) - { - return new JSImportedElementResolveResult(qualifiedName + s, resolvedElement, importStatement); - } + public JSImportedElementResolveResult appendSignature(String s) { + return new JSImportedElementResolveResult(qualifiedName + s, resolvedElement, importStatement); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/JSResolveUtil.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/JSResolveUtil.java index dcfedb92..d1a8124a 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/JSResolveUtil.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/JSResolveUtil.java @@ -33,6 +33,7 @@ import com.intellij.lang.javascript.psi.impl.JSStubElementImpl; import com.intellij.xml.XmlElementDescriptor; import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.application.util.*; import consulo.application.util.function.Processor; import consulo.component.extension.Extensions; @@ -67,6 +68,7 @@ import consulo.module.Module; import consulo.module.content.ProjectFileIndex; import consulo.module.content.ProjectRootManager; +import consulo.project.DumbService; import consulo.project.Project; import consulo.util.collection.ArrayUtil; import consulo.util.collection.SmartList; @@ -75,2991 +77,2553 @@ import consulo.util.dataholder.Key; import consulo.util.lang.Comparing; import consulo.util.lang.StringUtil; -import consulo.util.lang.ref.Ref; +import consulo.util.lang.ref.SimpleReference; import consulo.virtualFileSystem.VirtualFile; import consulo.virtualFileSystem.util.VirtualFileUtil; import consulo.xml.ide.highlighter.XmlFileType; import consulo.xml.psi.xml.*; -import org.jetbrains.annotations.NonNls; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.*; /** * @author max, maxim.mossienko */ -public class JSResolveUtil -{ - private static final Key>> MY_CACHED_STATEMENTS = Key.create("JS.RelevantStatements"); - private static UserDataCache>, JSElement, Object> ourCachedDefsCache = new RelevantDefsUserDataCache(); - @NonNls - public static final String PROTOTYPE_FIELD_NAME = "prototype"; - - @NonNls - private static final String ARRAY_TYPE_NAME = "Array"; - @NonNls - private static final String ARGUMENTS_TYPE_NAME = "Arguments"; - - public static final String COMMENT_DELIMITERS = "|/"; - - public static void processInjectedFileForTag(final @Nonnull XmlTag tag, @Nonnull JSInjectedFilesVisitor visitor) - { - InjectedLanguageManager injectedLanguageManager = InjectedLanguageManager.getInstance(tag.getProject()); - - for(XmlTagChild child : tag.getValue().getChildren()) - { - if(child instanceof XmlText) - { - injectedLanguageManager.enumerate(child, visitor); - } - } - } - - public static String findPackageForMxml(final PsiElement expression) - { - String s = null; - final PsiFile containingFile = expression.getContainingFile(); - - if(containingFile.getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4 && containingFile.getContext() != null) - { - final PsiFile contextContainigFile = containingFile.getContext().getContainingFile(); - VirtualFile file = contextContainigFile.getVirtualFile(); - if(file == null && contextContainigFile.getOriginalFile() != null) - { - file = contextContainigFile.getOriginalFile().getVirtualFile(); - } - - s = getExpectedPackageNameFromFile(file, containingFile.getProject(), true); - } - return s; - } - - public static String getExpectedPackageNameFromFile(VirtualFile file, Project project, boolean allowEvaluationFromContextRoot) - { - final ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(project).getFileIndex(); - final Module moduleForFile = file != null ? projectFileIndex.getModuleForFile(file) : null; - - if(moduleForFile != null) - { - if(file instanceof VirtualFileWindow) - { - file = ((VirtualFileWindow) file).getDelegate(); - } - VirtualFile rootForFile = projectFileIndex.getSourceRootForFile(file); - if(rootForFile == null && allowEvaluationFromContextRoot) - { - rootForFile = projectFileIndex.getContentRootForFile(file); - } - - if(rootForFile != null) - { - return VirtualFileUtil.getRelativePath(file.isDirectory() ? file : file.getParent(), rootForFile, '.'); - } - } - return null; - } - - public static void processInterfaceMethods(final JSClass clazz, final CollectMethodsToImplementProcessor implementedMethodProcessor) - { - clazz.processDeclarations(implementedMethodProcessor, ResolveState.initial(), clazz, clazz); - } - - public static String getExpressionType(final JSExpression expression, final PsiFile containingFile) - { - String type = getQualifiedExpressionType(expression, containingFile); - - return getShortenedType(type, expression); - } - - public static String getShortenedType(String type, final PsiElement context) - { - if(type == null) - { - type = "*"; - } - else - { - String shortName = getShortTypeName(type); - final String expr = JSImportHandlingUtil.resolveTypeName(shortName, context); - if(expr != null && !expr.equals(shortName)) - { - type = shortName; - } - } - return type; - } - - public static String getQualifiedExpressionType(final JSExpression expression, final PsiFile containingFile) - { - String type = null; - - if(expression != null) - { - final BaseJSSymbolProcessor.SimpleTypeProcessor processor = new BaseJSSymbolProcessor.SimpleTypeProcessor(JavaScriptVersionUtil.getFeatures(expression)); - BaseJSSymbolProcessor.doEvalForExpr(expression, containingFile, processor); - type = processor.getType(); - } - - return type; - } - - private static String getShortTypeName(String type) - { - String str = type; - - final int i = str.indexOf('<'); - String signature = null; - - if(i != -1) - { - final int index = str.lastIndexOf('.', i); - if(index == -1) - { - return type; - } - signature = str.substring(index); - str = str.substring(0, index); - } - - final int i2 = str.lastIndexOf('.'); - if(i2 != -1) - { - str = str.substring(i2 + 1); - } - - return str + (signature != null ? signature : ""); - } - - // TODO remove this method, call generic one processing includes as well (like findParent()) - public static PsiElement getClassReferenceForXmlFromContext(PsiElement parent) - { - final PsiElement context = parent != null ? parent.getContext() : null; - if(context instanceof XmlElement && context.getContainingFile() instanceof XmlFile) - { - return XmlBackedJSClassImpl.getContainingComponent((XmlElement) context); - } - return parent; - } - - @Nullable - public static XmlBackedJSClassImpl getXmlBackedClass(final JSFile injectedJsFile) - { - final PsiElement context = injectedJsFile.getContext(); - if(context instanceof XmlAttributeValue || context instanceof XmlText) - { - return XmlBackedJSClassImpl.getContainingComponent((XmlElement) context); - } - return null; - } - - - public static SearchScope findUseScope(final T jsVariableBase) - { - PsiElement element = PsiTreeUtil.getParentOfType(jsVariableBase, JSFunction.class, JSCatchBlock.class, JSClass.class, JSObjectLiteralExpression.class, JSFile.class); - PsiElement scopeElement = element; - - if(element instanceof JSFile) - { - final PsiElement xmlFromContext = getClassReferenceForXmlFromContext(element); - - if(xmlFromContext != element) - { - element = xmlFromContext; - scopeElement = element.getContainingFile(); - } - else - { - element = null; - } - } - - if(element != null) - { - if(element instanceof JSFunction) - { - final PsiElement elt = JSDocumentationUtils.findDocComment(JSDocumentationProvider.findElementForWhichPreviousCommentWillBeSearched(element)); - if(elt instanceof PsiComment) - { - return new LocalSearchScope(new PsiElement[]{ - elt, - element - }); - } - } - - if(element instanceof JSClass) - { - final JSAttributeList attributeList = jsVariableBase.getAttributeList(); - - if(attributeList == null || attributeList.getAccessType() != JSAttributeList.AccessType.PRIVATE) - { - return ((JSStubElementImpl) jsVariableBase).getDefaultUseScope(); - } - } - return new LocalSearchScope(scopeElement); - } - return ((JSStubElementImpl) jsVariableBase).getDefaultUseScope(); - } - - public static final boolean isAssignableType(@NonNls final String expectedType, @NonNls String type, PsiElement context) - { - if((expectedType != null && hasMultipleOccurenceDelimiters(expectedType)) || (type != null && hasMultipleOccurenceDelimiters(type))) - { - StringTokenizer expectedTypeIterator = new StringTokenizer(expectedType != null ? expectedType : "", COMMENT_DELIMITERS); - - while(expectedTypeIterator.hasMoreElements()) - { - String primitiveExpectedType = expectedTypeIterator.nextToken().trim(); - StringTokenizer typeIterator = new StringTokenizer(type != null ? type : "", COMMENT_DELIMITERS); - - while(typeIterator.hasMoreElements()) - { - String primitiveType = typeIterator.nextToken().trim(); - if(isAssignableType(primitiveExpectedType, primitiveType, context)) - { - return true; - } - } - } - - return false; - } - if(expectedType == null || expectedType.equals("*") || expectedType.equals(OBJECT_CLASS_NAME) || expectedType.equals("Class")) - { - return true; - } - if(expectedType.equals(type)) - { - return true; - } - - final boolean nonecma = context.getContainingFile().getLanguage() != JavaScriptSupportLoader.ECMA_SCRIPT_L4; - - if("Number".equals(expectedType) && ("int".equals(type) || "uint".equals(type) || (("Boolean".equals(type) || "String".equals(type)) && nonecma))) - { - return true; - } - if("int".equals(expectedType) && ("Number".equals(type) || - ("String".equals(type) && nonecma) || - "uint".equals(type))) - { - return true; // compatibility - } - - if("uint".equals(expectedType) && ("int".equals(type) || "Number".equals(type))) - { - return true; - } - if(ARRAY_TYPE_NAME.equals(type)) - { - if(ARGUMENTS_TYPE_NAME.equals(expectedType) || expectedType.startsWith(ARRAY_TYPE_NAME) /*Array[*/ || JSTypeEvaluateManager.isArrayType(expectedType)) - { - return true; - } - } - - if(ARGUMENTS_TYPE_NAME.equals(type) && nonecma) - { - return true; // TODO: hack for indirect call Array.slice(arguments, 0) - } - - if(ARRAY_TYPE_NAME.equals(expectedType) && JSTypeEvaluateManager.isArrayType(type)) - { - return true; - } - if("String".equals(expectedType) && (("Number".equals(type) || "int".equals(type) || "Boolean".equals(type) || "RegExp".equals(type)) && nonecma)) - { - return true; - } - - if("*".equals(type) || (OBJECT_CLASS_NAME.equals(type) && nonecma)) - { - return true; // Dynamic cast - } - if("void".equals(type)) - { - return false; - } - final PsiElement typeClass = type != null ? unwrapProxy(findClassByQName(type, context)) : null; - - if(!(typeClass instanceof JSClass)) - { - return true; - } - - boolean result = typeClass.processDeclarations(new ResolveProcessor(null) - { - { - setToProcessHierarchy(true); - setTypeContext(true); - setToProcessMembers(false); - setLocalResolve(true); - } - - @Override - public boolean execute(final PsiElement element, final ResolveState state) - { - if(!(element instanceof JSClass)) - { - return true; - } - final JSClass clazz = (JSClass) element; - boolean sameType = clazz.getQualifiedName().equals(expectedType); - - if(!sameType) - { - for(JSClass implementedClazz : clazz.getImplementedInterfaces()) - { - sameType = !implementedClazz.processDeclarations(this, ResolveState.initial(), implementedClazz, implementedClazz); - if(sameType) - { - break; - } - } - } - return !sameType; - } - }, ResolveState.initial(), typeClass, typeClass); - - if(result && isImplicitCastPossible((JSClass) typeClass, expectedType)) - { - result = false; - } - - return !result; - } - - private static boolean hasMultipleOccurenceDelimiters(String expectedType) - { - final String commentDelimiters = COMMENT_DELIMITERS; - - for(int i = 0; i < commentDelimiters.length(); ++i) - { - if(expectedType.indexOf(commentDelimiters.charAt(i)) != -1) - { - return true; - } - } - return false; - } - - private static boolean isImplicitCastPossible(JSClass typeClass, String expectedType) - { - // TODO: move to flex support plugin - if(expectedType.equals("flash.events.IEventDispatcher")) - { - JSAttributeList attributeList = typeClass.getAttributeList(); - if(attributeList != null) - { - return attributeList.getAttributesByName("Bindable").length != 0; - } - } - return false; - } - - public static PsiElement getTopReferenceParent(final PsiElement parent) - { - PsiElement currentParent = parent; - for(; currentParent instanceof JSReferenceExpression; currentParent = currentParent.getParent()) - { - ; - } - return currentParent; - } - - public static PsiElement getTopReferenceExpression(final @Nonnull PsiElement parent) - { - PsiElement element = parent; - - for(PsiElement currentParent = parent.getParent(); currentParent instanceof JSReferenceExpression; element = currentParent, currentParent = currentParent.getParent()) - - { - ; - } - return element; - } - - public static boolean isSelfReference(final PsiElement currentParent, PsiElement elt) - { - return currentParent instanceof JSPackageStatement || - currentParent instanceof JSNamespaceDeclaration || - (currentParent instanceof JSVariable && (((JSVariable) currentParent).getNameIdentifier() == elt)) || - (currentParent instanceof JSFunction && ((JSFunction) currentParent).getNameIdentifier() == elt) || - currentParent instanceof JSClass; - } - - public static PsiElement findParent(final PsiElement element) - { - PsiElement parent = element instanceof JSVariable ? element.getParent().getParent() : element.getParent(); - return parent instanceof JSFile ? findParentClass((JSFile) parent) : parent; - } - - private static PsiElement findParentClass(final JSFile file) - { - JSClass xmlBackedClass = getXmlBackedClass(file); - if(xmlBackedClass != null) - { - return xmlBackedClass; - } - - PsiElement forcedContext = file.getUserData(contextKey); - if(forcedContext != null && !forcedContext.isValid()) - { - forcedContext = null; - } - if(forcedContext instanceof JSClass) - { - return forcedContext; - } - - if(forcedContext instanceof JSFile) - { - return findParentClass((JSFile) forcedContext); - } - - if(forcedContext instanceof PsiFile && JavaScriptSupportLoader.isFlexMxmFile((PsiFile) forcedContext)) - { - return XmlBackedJSClassImpl.getXmlBackedClass((XmlFile) forcedContext); - } - - if(forcedContext instanceof XmlElement) - { - PsiFile containingFile = forcedContext.getContainingFile(); - if(JavaScriptSupportLoader.isFlexMxmFile(containingFile)) - { - return XmlBackedJSClassImpl.getXmlBackedClass((XmlFile) containingFile); - } - } - - if(forcedContext != null) - { - PsiFile containingFile = forcedContext.getContainingFile(); - if(containingFile instanceof JSFile && containingFile != file) - { - return findParentClass((JSFile) containingFile); - } - - } - return file; - } - - @Nullable - public static JSClass getClassOfContext(PsiElement node) - { - final JSClass jsClass = PsiTreeUtil.getParentOfType(node, JSClass.class); - if(jsClass != null) - { - return jsClass; - } - else - { - final PsiElement context = getClassReferenceForXmlFromContext(node.getContainingFile()); - if(context instanceof JSClass) - { - return (JSClass) context; - } - } - - return null; - } - - public static - @Nullable - JSClass findClassOfQualifier(final JSExpression qualifier, final PsiFile containingFile) - { - final String s = getQualifiedExpressionType(qualifier, containingFile); - final PsiElement qName = s != null ? unwrapProxy(findClassByQName(s, containingFile)) : null; - if(qName instanceof JSClass) - { - return (JSClass) qName; - } - return null; - } - - public static boolean referenceExpressionShouldBeQualified(final JSReferenceExpression contextExpr) - { - PsiElement parent = contextExpr.getParent(); - return parent instanceof JSImportStatement || (parent instanceof JSReferenceList && contextExpr.getContainingFile().getContext() != null); - } - - public static boolean isArtificialClassUsedForReferenceList(JSClass clazz) - { - return clazz.getContainingFile().getContext() != null; - } - - public static Collection findElementsByName(String name, Project project, GlobalSearchScope scope) - { - final Set result = new HashSet(); - Collection jsQualifiedNamedElements = StubIndex.getElements(JavaScriptIndexKeys.ELEMENTS_BY_NAME, name, project, scope, JSQualifiedNamedElement.class); - - for(JSQualifiedNamedElement e : jsQualifiedNamedElements) - { - result.add((JSQualifiedNamedElement) e.getNavigationElement()); - } - - Collection files = new ArrayList(); - files.addAll(FileBasedIndex.getInstance().getContainingFiles(FilenameIndex.NAME, name + JavaScriptSupportLoader.MXML_FILE_EXTENSION_DOT, scope)); - files.addAll(FileBasedIndex.getInstance().getContainingFiles(FilenameIndex.NAME, name + JavaScriptSupportLoader.MXML_FILE_EXTENSION2_DOT, scope)); - - for(final VirtualFile file : files) - { - if(!file.isValid()) - { - continue; - } - final PsiFile psiFile = PsiManager.getInstance(project).findFile(file); - if(psiFile != null) - { - result.add(XmlBackedJSClassImpl.getXmlBackedClass((XmlFile) psiFile)); - } - } - return result; - } - - public static boolean isNewResolveAndCompletion(PsiFile psiFile) - { - return psiFile.getLanguage().isKindOf(JavaScriptSupportLoader.ECMA_SCRIPT_L4) || JavaScriptSupportLoader.isFlexMxmFile(psiFile); - } - - public static String getTypeFromSetAccessor(final JSNamedElement jsNamedElement) - { - if(!(jsNamedElement instanceof JSFunction) || !((JSFunction) jsNamedElement).isSetProperty()) - { - return null; - } - final JSParameterList jsParameterList = ((JSFunction) jsNamedElement).getParameterList(); - if(jsParameterList == null) - { - return null; - } - final JSParameter[] jsParameters = jsParameterList.getParameters(); - if(jsParameters == null || jsParameters.length != 1) - { - return null; - } - return jsParameters[0].getTypeString(); - } - - public static boolean shouldProcessTopLevelGlobalContext(@Nonnull PsiElement place, @Nonnull PsiScopeProcessor processor) - { - PsiElement placeParent = null; - - return shouldProcessImports(place, processor) && (!((placeParent = place.getParent()) instanceof JSCallExpression) || - (place instanceof JSReferenceExpression && - ((JSReferenceExpression) place).getQualifier() != null && - ((ResolveProcessor) processor).specificallyAskingToResolveQualifiedNames()) || - placeParent instanceof JSNewExpression); - } - - public static boolean shouldProcessImports(@Nonnull PsiElement place, @Nonnull PsiScopeProcessor processor) - { - if(!(processor instanceof ResolveProcessor) || ((ResolveProcessor) processor).isLocalResolve()) - { - return false; - } - return (!(place instanceof JSReferenceExpression) || - ((JSReferenceExpression) place).getQualifier() == null || - ((ResolveProcessor) processor).specificallyAskingToResolveQualifiedNames()); - } - - public static boolean processTopLevelClasses(PsiScopeProcessor processor, ResolveState state, Project project, GlobalSearchScope scope, boolean acceptOnlyClasses, boolean acceptQualifiedElements) - { - boolean result = true; - final String resolvedName = ((ResolveProcessor) processor).getName(); - - if(resolvedName == null) - { - for(String s : StubIndex.getInstance().getAllKeys(JavaScriptIndexKeys.ELEMENTS_BY_NAME, project)) - { - for(JSQualifiedNamedElement e : StubIndex.getElements(JavaScriptIndexKeys.ELEMENTS_BY_NAME, s, project, scope, JSQualifiedNamedElement.class)) - { - if(ARGUMENTS_TYPE_NAME.equals(e.getName())) - { - continue; - } - if(acceptOnlyClasses && !(e instanceof JSClass)) - { - continue; - } - - if(!acceptQualifiedElements) - { - String qName = e.getQualifiedName(); - if(qName != null && qName.indexOf('.') != -1) - { - continue; - } - } - result &= processor.execute(e, state); - } - } - } - else - { - for(JSQualifiedNamedElement e : StubIndex.getElements(JavaScriptIndexKeys.ELEMENTS_BY_QNAME, resolvedName, project, scope, JSQualifiedNamedElement.class)) - { - if(!e.getName().equals(resolvedName)) - { - continue; - } - if(acceptOnlyClasses && !(e instanceof JSClass)) - { - continue; - } - result = processor.execute(e, state); - if(!result) - { - break; - } - } - } - return result; - } - - static boolean walkOverStructure(@Nonnull PsiElement context, Processor processor) - { - PsiNamedElement parent = PsiTreeUtil.getNonStrictParentOfType(context, JSQualifiedNamedElement.class, PsiFile.class); - - if(parent instanceof JSClass) - { - PsiElement forcedContext = parent.getUserData(contextKey); - - if(forcedContext instanceof XmlBackedJSClassImpl) - { - if(!processor.process((PsiNamedElement) forcedContext)) - { - return false; - } - } - } - - while(parent != null) - { - if(!processor.process(parent)) - { - return false; - } - - if(parent instanceof JSPackageStatement) - { - break; - } - - if(parent instanceof PsiFile) - { - final PsiElement data = parent.getUserData(contextKey); - - if(data instanceof JSElement) - { - parent = PsiTreeUtil.getNonStrictParentOfType(data, JSQualifiedNamedElement.class, PsiFile.class); - } - else - { - break; - } - } - else - { - parent = PsiTreeUtil.getParentOfType(parent, JSQualifiedNamedElement.class, PsiFile.class); - } - } - - return true; - } - - private static final Key, JSElement>> ourCachedOpenedNsesKey = Key.create("opened.nses"); - - private static final UserDataCache, JSElement>, JSElement, Object> ourCachedOpenedNsesCache = new UserDataCache, - JSElement>, JSElement, Object>() - { - @Override - protected ParameterizedCachedValue, JSElement> compute(JSElement jsElement, Object p) - { - return CachedValuesManager.getManager(jsElement.getProject()).createParameterizedCachedValue(new ParameterizedCachedValueProvider, JSElement>() - { - @Override - public CachedValueProvider.Result> compute(JSElement context) - { - class MyProcessor extends ResolveProcessor implements Processor - { - Set openedNses; - - public MyProcessor() - { - super(null); - putUserData(ResolveProcessor.LOOKING_FOR_USE_NAMESPACES, true); - } - - @Override - public boolean process(PsiNamedElement psiNamedElement) - { - if(psiNamedElement instanceof JSElement) - { - processDeclarationsInScope((JSElement) psiNamedElement, this, ResolveState.initial(), psiNamedElement, psiNamedElement); - } - else - { - // TODO: XmlFile ? - } - return true; - } - - @Override - public boolean execute(PsiElement element, ResolveState state) - { - if(!(element instanceof JSUseNamespaceDirective)) - { - return true; - } - if(openedNses == null) - { - openedNses = new HashSet(); - } - openedNses.add(((JSUseNamespaceDirective) element).getNamespaceToBeUsed()); - return true; - } - } - MyProcessor processor = new MyProcessor(); - walkOverStructure(context, processor); - return new CachedValueProvider.Result>(processor.openedNses, PsiModificationTracker.EVER_CHANGED); - } - }, false); - } - }; - - public static Set calculateOpenNses(PsiElement place) - { - final Ref> result = new Ref>(); - walkOverStructure(place, new Processor() - { - @Override - public boolean process(PsiNamedElement psiNamedElement) - { - if(psiNamedElement instanceof JSElement) - { - result.set(ourCachedOpenedNsesCache.get(ourCachedOpenedNsesKey, (JSElement) psiNamedElement, null).getValue((JSElement) psiNamedElement)); - } - return false; - } - }); - return result.get() != null ? result.get() : Collections.emptySet(); - } - - public static boolean processGlobalThings(PsiScopeProcessor processor, ResolveState state, PsiElement place, PsiElement context) - { - boolean result = true; - final Project project = context.getProject(); - final GlobalSearchScope scope = context.getResolveScope(); - - if(shouldProcessTopLevelGlobalContext(place, processor)) - { - //result = processTopPackages((ResolveProcessor) processor, state, project, scope); - } - - if(result) - { - boolean acceptOnlyClasses = place instanceof JSReferenceExpression ? isExprInTypeContext((JSReferenceExpression) place) : false; - - result = processTopLevelClasses(processor, state, project, scope, acceptOnlyClasses, true); - } - return result; - } - - public static - @Nullable - JSParameter findParameterForUsedArgument(@Nonnull JSExpression mainOccurence, @Nonnull JSArgumentList parent) - { - int paramIndex = 0; - - for(JSExpression expr : parent.getArguments()) - { - if(expr == mainOccurence) - { - break; - } - paramIndex++; - } - - final JSExpression methodExpr = ((JSCallExpression) parent.getParent()).getMethodExpression(); - if(methodExpr instanceof JSReferenceExpression) - { - final ResolveResult[] results = ((JSReferenceExpression) methodExpr).multiResolve(false); - - if(results.length > 0) - { - final PsiElement element = results[0].getElement(); - - if(element instanceof JSFunction) - { - final JSParameterList parameterList = ((JSFunction) element).getParameterList(); - if(parameterList != null) - { - final JSParameter[] params = parameterList.getParameters(); - - if(paramIndex < params.length) - { - return params[paramIndex]; - } - } - } - } - } - return null; - } - - public static abstract class JSInjectedFilesVisitor implements PsiLanguageInjectionHost.InjectedPsiVisitor, XmlBackedJSClassImpl.InjectedFileVisitor - { - @Override - public void visit(@Nonnull final PsiFile injectedPsi, @Nonnull final List places) - { - if(injectedPsi instanceof JSFile) - { - process((JSFile) injectedPsi); - } - } - - protected abstract void process(JSFile file); - - @Override - public void visit(XmlTag rootTag, JSFile file) - { - process(file); - } - } - - @NonNls - public static final String OBJECT_CLASS_NAME = "Object"; - - private JSResolveUtil() - { - } - - private static final Key> ourFileElementsValueKey = Key.create("file.elements"); - - public static void treeWalkUp(PsiScopeProcessor processor, PsiElement elt, PsiElement lastParent, PsiElement place) - { - treeWalkUp(processor, elt, lastParent, place, null, null); - } - - - public static void treeWalkUp(PsiScopeProcessor processor, PsiElement elt, PsiElement lastParent, PsiElement place, PsiElement terminatingParent) - { - treeWalkUp(processor, elt, lastParent, place, terminatingParent, null); - } - - private static void treeWalkUp(final PsiScopeProcessor processor, PsiElement elt, PsiElement lastParent, PsiElement place, PsiElement terminatingParent, PsiElement currentScope) - { - if(elt == null) - { - return; - } - - PsiElement parentElement = elt.getContext(); - if(elt instanceof JSFunction || elt instanceof JSObjectLiteralExpression) - { - currentScope = elt; - } - - if(parentElement instanceof JSDefinitionExpression || (parentElement instanceof JSAssignmentExpression && !(elt instanceof JSFunctionExpression))) - { - if(elt == terminatingParent) - { - return; - } - elt = parentElement.getParent(); - parentElement = elt.getParent(); // when walking a| = b, start from enclosing statement - if(parentElement instanceof JSExpressionStatement) - { - elt = parentElement; - parentElement = parentElement.getParent(); - } - currentScope = elt; - } - else if(parentElement instanceof JSVariable && currentScope == null) - { - // when walking from variable init start from enclosing statement (function expr / object literal could reference that could reference - // var in this case, better to check for any scope change) - currentScope = parentElement; - parentElement = parentElement.getParent(); - } - - final boolean parentIsClass = parentElement instanceof JSClass; - int index = -1; - PsiElement[] children = getChildren(parentElement); - - if(children != null && children.length > 0) - { - index = 0; - for(PsiElement el : children) - { - if(el == elt) - { - break; - } - ++index; - } - } - - boolean finish = false; - PsiElement cur = elt; - - do - { - if(!cur.processDeclarations(processor, ResolveState.initial(), cur == elt ? lastParent : null, place)) - { - if(processor instanceof ResolveProcessor) - { - return; - } - } - if(terminatingParent == cur) - { - finish = true; - break; - } - if(cur instanceof PsiFile || parentIsClass) - { - break; - } - if(cur instanceof JSStatement && parentElement instanceof JSIfStatement) - { - // Do not try to resolve variables from then branch in else branch. - break; - } - - if(index == -1) - { - cur = cur.getPrevSibling(); - } - else - { - if(index != 0) - { - cur = children[--index]; - } - else - { - cur = null; - } - } - } - while(cur != null); - - final PsiElement func = parentIsClass || finish ? null : processFunctionDeclarations(processor, parentElement); - if(func != null) - { - return; - } - - if(elt instanceof PsiFile) - { - if(elt instanceof XmlFile) - { - final XmlFile xmlFile = (XmlFile) elt; - final XmlDocument document = xmlFile.getDocument(); - final XmlTag rootTag = document != null ? document.getRootTag() : null; - final String rootNs = rootTag != null ? rootTag.getNamespace() : null; - - if(JavaScriptSupportLoader.isMxmlNs(rootNs)) - { - processXmlFile(processor, xmlFile, place); - } - else - { - if(rootTag != null && xmlFile.getFileType() == XmlFileType.INSTANCE) - { // TODO this is bindows specific - processXmlFile(processor, xmlFile, place); - } - } - } - else if(elt instanceof JSFile) - { - if(parentElement != null) - { - XmlTag tag = PsiTreeUtil.getParentOfType(parentElement, XmlTag.class); - final PsiFile containingFile = parentElement.getContainingFile(); - - while(tag != null) - { - if(XmlBackedJSClassImpl.isInlineComponentTag(tag)) - { - for(JSVariable var : ourCachedPredefinedVars.get(ourCachedPredefinedVarsKey, (XmlFile) containingFile, null).getValue()) - { - if(!processor.execute(var, ResolveState.initial())) - { - return; - } - } - JSClass clazz = XmlBackedJSClassImpl.getXmlBackedClass(tag); - clazz.processDeclarations(processor, ResolveState.initial(), clazz, place); - return; - } - tag = PsiTreeUtil.getParentOfType(tag, XmlTag.class); - } - - parentElement = containingFile; - } - else - { - parentElement = elt.getUserData(contextKey); - } - } - if(!(elt instanceof JSExpressionCodeFragment) && parentElement == null) - { - return; - } - } - - if(finish) - { - return; - } - treeWalkUp(processor, parentElement, elt, place, terminatingParent, currentScope); - } - - private static UserDataCache>, XmlFile, Object> ourCachedPredefinedVars = new UserDataCache>, XmlFile, Object>() - { - @Override - protected CachedValue> compute(final XmlFile xmlFile, Object p) - { - return CachedValuesManager.getManager(xmlFile.getProject()).createCachedValue(new CachedValueProvider>() - { - @Override - public Result> compute() - { - SmartList vars = new SmartList(); - String qName = XmlBackedJSClassImpl.getXmlBackedClass(xmlFile).getQualifiedName(); - vars.add(new ImplicitJSVariableImpl("outerDocument", qName, xmlFile)); - vars.add(new ImplicitJSVariableImpl("data", OBJECT_CLASS_NAME, xmlFile)); - return new Result>(vars, xmlFile); - } - }, false); - } - }; - - private static Key>> ourCachedPredefinedVarsKey = Key.create("ourCachedPredefinedVarsKey"); - - public static boolean processXmlFile(final PsiScopeProcessor processor, final XmlFile xmlFile, final PsiElement place) - { - JSClass clazz = XmlBackedJSClassImpl.getXmlBackedClass(xmlFile); - if(!clazz.processDeclarations(processor, ResolveState.initial(), clazz, place)) - { - return false; - } - return true; - } - - private static PsiElement[] getChildren(final PsiElement element) - { - if(!(element instanceof JSFile) && (!(element instanceof JSBlockStatement) || !(element.getParent() instanceof JSNamedElement))) - { - return null; - } - CachedValue value = element.getUserData(ourFileElementsValueKey); - - if(value == null) - { - value = CachedValuesManager.getManager(element.getProject()).createCachedValue(new CachedValueProvider() - { - @Override - public Result compute() - { - return new Result(element.getChildren(), element); - } - }, false); - element.putUserData(ourFileElementsValueKey, value); - } - - return value.getValue(); - } - - @Nullable - private static PsiElement processFunctionDeclarations(final @Nonnull PsiScopeProcessor processor, final @Nullable PsiElement context) - { - if(!(context instanceof JSElement)) - { - return null; - } - PsiElement[] children = getChildren(context); - - if(context != null) - { - int index = children != null ? children.length - 1 : -1; - PsiElement cur = index >= 0 ? children[index] : context.getLastChild(); - - while(cur != null) - { - if(cur instanceof JSFunction || cur instanceof JSClass) - { - if(!processor.execute(cur, ResolveState.initial())) - { - if(processor instanceof ResolveProcessor) - { - return ((ResolveProcessor) processor).getResult(); - } - } - } - - if(index == -1) - { - cur = cur.getPrevSibling(); - } - else - { - if(index != 0) - { - cur = children[--index]; - } - else - { - cur = null; - } - } - } - } - return null; - } - - public static JSClass findDeclaringClass(final JSFunction method) - { - final Ref lastVisitedClass = new Ref(); - iterateOverridenMethodsUp(method, new Processor() - { - @Override - public boolean process(JSClass jsClass) - { - lastVisitedClass.set(jsClass); - return true; - } - }, true); - - - Collection visited = new HashSet(); - visitAllImplementedInterfaces(lastVisitedClass.get(), visited, new Processor() - { - @Override - public boolean process(JSClass jsClass) - { - // hierarchy may contain maximum one interface declaring a certain method - JSFunction interfaceMethod = jsClass.findFunctionByNameAndKind(method.getName(), method.getKind()); - if(interfaceMethod != null) - { - // TODO check signature - lastVisitedClass.set(jsClass); - return false; - } - return true; - } - }); - - return lastVisitedClass.get(); - } - - /** - * @return true if processor said enough - */ - private static boolean visitAllImplementedInterfaces(JSClass clazz, @Nonnull Collection visited, Processor processor) - { - if(visited.contains(clazz)) - { - return true; - } - if(clazz.isInterface()) - { - visited.add(clazz); - if(!processor.process(clazz)) - { - return true; - } - } - JSClass[] interfaces = clazz.isInterface() ? clazz.getSuperClasses() : clazz.getImplementedInterfaces(); - for(JSClass anInterface : interfaces) - { - if(visitAllImplementedInterfaces(anInterface, visited, processor)) - { - return true; - } - } - return false; - } - - /** - * @return true if processor said enough - */ - private static boolean iterateOverridenMethodsUp(JSFunction function, Processor processor, boolean allowDirectParent) - { - PsiElement clazz = findParent(function); - if(!(clazz instanceof JSClass)) - { - return false; - } - final PsiElement directParent = clazz; - - while(true) - { - if((allowDirectParent || directParent != clazz) && !processor.process((JSClass) clazz)) - { - return true; - } - - JSAttributeList attributeList = function.getAttributeList(); - if(attributeList == null || !attributeList.hasModifier(JSAttributeList.ModifierType.OVERRIDE)) - { - return false; - } - - // TODO check signature - final JSNamedElement overridenMethod = findOverriddenMethod(function, (JSClass) clazz); - if(!(overridenMethod instanceof JSFunction)) - { - return false; - } - function = (JSFunction) overridenMethod; - - clazz = findParent(function); - if(!(clazz instanceof JSClass)) - { - return false; - } - } - } - - public static boolean isReferenceTo(final PsiPolyVariantReference reference, final String referencedName, PsiElement _element) - { - String elementName; - if(_element instanceof JSNamedElement) - { - elementName = ((PsiNamedElement) _element).getName(); - } - else if(_element instanceof XmlAttributeValue) - { - elementName = ((XmlAttributeValue) _element).getValue(); - } - else if(_element instanceof PsiFile) - { - elementName = ((PsiFile) _element).getVirtualFile().getNameWithoutExtension(); - } - else if(_element instanceof PsiDirectoryContainer) - { - elementName = ((PsiNamedElement) _element).getName(); - } - else - { - return false; - } - - if(Comparing.equal(referencedName, elementName, true)) - { - PsiElement element = _element; - - final ResolveResult[] resolveResults = reference.multiResolve(true); - - for(ResolveResult r : resolveResults) - { - PsiElement resolvedElement = r.getElement(); - - if(resolvedElement.isEquivalentTo(element) || - element.isEquivalentTo(resolvedElement) || - ((element instanceof JSProperty || element instanceof XmlAttributeValue) && - resolvedElement != null && - resolvedElement.getParent() == element)) - { - if(reference instanceof JSReferenceExpression && ((((JSReferenceExpression) reference).getParent() == resolvedElement && resolvedElement instanceof JSDefinitionExpression) || - resolvedElement instanceof JSFunctionExpression && ((JSFunctionExpression) resolvedElement).getFunction().getNameIdentifier().getNextSibling() == reference)) - { - return false; // do not include self to usages - } - - return true; - } - - if(resolvedElement instanceof JSFunctionExpression) - { - final PsiElement nameIdentifier = ((JSFunctionExpression) resolvedElement).getFunction().getNameIdentifier(); - if(nameIdentifier != null && nameIdentifier.getNextSibling() == element) - { - return true; - } - } - else if(resolvedElement instanceof JSFunction) - { - JSFunction fun = (JSFunction) resolvedElement; - - if(fun.isConstructor()) - { - if((element instanceof JSClass && resolvedElement.getParent() == element) || (element instanceof JSFile && - reference.getElement().getParent() != resolvedElement && - isPublicEntityReferenceToJSFile(findParent(resolvedElement), element))) - { - return true; - } - } - else if(element instanceof JSFunction) - { - JSFunction anotherFun = (JSFunction) element; - boolean getProperty; - - if((getProperty = fun.isGetProperty()) || fun.isSetProperty()) - { - if((getProperty && anotherFun.isSetProperty()) || (!getProperty && anotherFun.isGetProperty())) - { - PsiElement funParent = JSResolveUtil.findParent(fun); - PsiElement parent = JSResolveUtil.findParent(anotherFun); - if(funParent == parent || (parent != null && parent.isEquivalentTo(funParent))) - { - return true; - } - } - } - PsiElement resolvedElementParent = findParent(resolvedElement); - final PsiElement elementParent = findParent(element); - - if(elementParent instanceof JSClass && resolvedElementParent instanceof JSClass) - { - final JSClass anotherClass = (JSClass) elementParent; - - final Collection visitedInterfaces = new HashSet(); - return iterateOverridenMethodsUp((JSFunction) resolvedElement, new Processor() - { - @Override - public boolean process(JSClass jsClass) - { - if(anotherClass.isInterface()) - { - return !visitAllImplementedInterfaces(jsClass, visitedInterfaces, new Processor() - { - @Override - public boolean process(JSClass jsClass) - { - return !jsClass.isEquivalentTo(anotherClass); - } - }); - } - else - { - return !jsClass.isEquivalentTo(anotherClass); - } - } - }, anotherClass.isInterface()); - } - } - } - else if(resolvedElement instanceof JSClass && element instanceof JSFunction && element.getParent() == resolvedElement) - { - return true; - } - - if((resolvedElement instanceof JSClass || - resolvedElement instanceof JSNamespaceDeclaration || - resolvedElement instanceof JSFunction || - resolvedElement instanceof JSVariable) && ((element instanceof XmlFile && resolvedElement.getParent().getContainingFile() == element) || (element instanceof JSFile && - reference.getElement().getParent() != resolvedElement && - isPublicEntityReferenceToJSFile(resolvedElement, element)))) - { - return true; - } - - if(resolvedElement instanceof JSVariable && element instanceof JSFunction) - { - if(fieldIsImplicitAccessorMethod((JSFunction) element, (JSVariable) resolvedElement)) - { - return true; - } - } - } - } - return false; - } - - private static boolean fieldIsImplicitAccessorMethod(JSFunction fun, JSVariable var) - { - if(!fun.isGetProperty() && !fun.isSetProperty()) - { - return false; - } - PsiElement funParent = findParent(fun); - if(!(funParent instanceof JSClass) || !((JSClass) funParent).isInterface()) - { - return false; - } - JSAttributeList attributeList = var.getAttributeList(); - if(attributeList == null || attributeList.getAccessType() != JSAttributeList.AccessType.PUBLIC) - { - return false; - } - - PsiElement parent = findParent(var); - if(!(parent instanceof JSClass)) - { - return false; - } - - for(JSClass c : ((JSClass) parent).getImplementedInterfaces()) - { - if(c == funParent) - { - return true; - } - } - - return false; - } - - private static boolean isPublicEntityReferenceToJSFile(PsiElement resolvedElement, PsiElement element) - { - PsiElement parent = resolvedElement.getParent(); - if(parent instanceof JSVarStatement) - { - parent = parent.getParent(); - } - return parent instanceof JSPackageStatement && parent.getParent() == element; - } - - private static JSNamedElement findOverriddenMethod(PsiElement resolvedElement, JSClass resolvedElementClass) - { - final Ref override = new Ref(); - - iterateType((JSFunction) resolvedElement, resolvedElementClass, null, new OverrideHandler() - { - @Override - public boolean process(ResolveProcessor processor, PsiElement scope, String className) - { - PsiElement result = processor.getResult(); - if(result instanceof JSNamedElement) - { - override.set((JSNamedElement) result); - return false; - } - return true; - } - }); - return override.get(); - } - - public static boolean checkClassHasParentOfAnotherOne(final JSClass aClass, final JSClass parent, @Nullable Set visited) - { - if(visited != null && visited.contains(aClass)) - { - return false; - } - - for(JSClass superClazz : aClass.getSuperClasses()) - { - if(superClazz == parent) - { - return true; - } - if(visited == null) - { - visited = new HashSet(); - } - visited.add(aClass); - return checkClassHasParentOfAnotherOne(superClazz, parent, visited); - } - return false; - } - - public static - @Nullable - JSExpression getRealRefExprQualifier(final JSReferenceExpression expr) - { - final JSExpression qualifier = ((JSReferenceExpressionImpl) expr).getResolveQualifier(); - if(qualifier != null) - { - return qualifier; - } - - if(isExprInTypeContext(expr)) - { - final JSImportedElementResolveResult resolved = JSImportHandlingUtil.resolveTypeNameUsingImports(expr); - if(resolved == null) - { - return expr.getQualifier(); - } - - return getRealRefExprQualifierFromResult(expr, resolved); - } - - return qualifier; - } - - public static JSExpression getRealRefExprQualifierFromResult(final JSReferenceExpression expr, final JSImportedElementResolveResult resolved) - { - return ((JSReferenceExpression) JSChangeUtil.createExpressionFromText(expr.getProject(), resolved.qualifiedName)).getQualifier(); - } - - public static String findPackageStatementQualifier(final PsiElement context) - { - if(context instanceof JSClass) - { - final String s = ((JSClass) context).getQualifiedName(); - if(s != null) - { - final int i = s.lastIndexOf('.'); - if(i != -1) - { - return s.substring(0, i); - } - else - { - return null; - } - } - } - - final JSPackageStatement packageStatement = PsiTreeUtil.getNonStrictParentOfType(context, JSPackageStatement.class); - - if(packageStatement != null) - { - return packageStatement.getQualifiedName(); - } - - return null; - } - - public static boolean isExprInStrictTypeContext(final JSReferenceExpression expr) - { - final PsiElement parent = expr.getParent(); - boolean parentIsVar; - - return (((parentIsVar = (parent instanceof JSVariable)) || parent instanceof JSFunction) && parent.getNode().findChildByType(JSTokenTypes.COLON) != null && - (!parentIsVar || ((JSVariable) parent).getInitializer() != expr)) || - parent instanceof JSAttributeList || - parent instanceof JSGenericSignature || - parent instanceof JSImportStatement || - parent instanceof JSReferenceList; - } - - public static boolean isExprInTypeContext(final JSReferenceExpression expr) - { - final PsiElement parent = expr.getParent(); - - return isExprInStrictTypeContext(expr) || - parent instanceof JSNewExpression || - parent instanceof JSUseNamespaceDirective || - (parent instanceof JSBinaryExpression && - ((JSBinaryExpression) parent).getROperand() == expr && - (((JSBinaryExpression) parent).getOperationSign() == JSTokenTypes.IS_KEYWORD || ((JSBinaryExpression) parent).getOperationSign() == JSTokenTypes.AS_KEYWORD)); - } - - @Nullable - public static PsiElement findClassByQName(final String link, final @Nonnull PsiElement context) - { - return findClassByQName(link, context.getProject(), context.getResolveScope()); - } - - @Nullable - public static PsiElement findClassByQName(final String link, @Nonnull GlobalSearchScope scope, @Nonnull Project project) - { - return findClassByQName(link, project, scope); - } - - private static PsiElement findClassByQName(final String link, final Project project, final GlobalSearchScope searchScope) - { - synchronized(project) - { - final PsiElement[] result = new PsiElement[1]; - - final Collection candidates = StubIndex.getElements(JavaScriptIndexKeys.ELEMENTS_BY_QNAME, link, project, searchScope, JSQualifiedNamedElement.class); - for(JSQualifiedNamedElement clazz : candidates) - { - if(link.equals(clazz.getQualifiedName())) - { - if("Object".equals(link) && !JavaScriptIndex.ECMASCRIPT_JS2.equals(clazz.getContainingFile().getVirtualFile().getName()) // object from swf do - // not contain necessary members! - ) - { - continue; - } - result[0] = clazz; - break; - } - } - - if(result[0] == null) - { - String className = link.substring(link.lastIndexOf('.') + 1); - if(className.length() > 0 && - (Character.isUpperCase(className.charAt(0)) || Character.isLowerCase(className.charAt(0))) && - !isBuiltInClassName(className)) - { - // TODO optimization, remove when packages will be properly handled - result[0] = findClassByQNameViaHelper(link, project, className, searchScope); - } - } - - return result[0]; - } - } - - private static boolean isBuiltInClassName(final String className) - { - return OBJECT_CLASS_NAME.equals(className) || "Boolean".equals(className) || "Function".equals(className) || "String".equals(className); - } - - public static boolean isPredefinedFile(PsiFile file) - { - return false; - } - - @Nullable - private static PsiElement findClassByQNameViaHelper(final String link, final Project project, final String className, final GlobalSearchScope scope) - { - for(JSResolveHelper helper : Extensions.getExtensions(JSResolveHelper.EP_NAME)) - { - PsiElement result = helper.findClassByQName(link, project, className, scope); - if(result != null) - { - return result; - } - } - return null; - } - - public static String[] buildNameIdsForQualifier(final JSExpression qualifier) - { - String[] nameIds = null; - - if(qualifier == null) - { - nameIds = JSSymbolUtil.buildNameIndexArray(qualifier); - } - else - { - ContextResolver resolver = new ContextResolver(qualifier); - nameIds = resolver.getQualifierAsNameIndex(); - - if(nameIds == null) - { - nameIds = new String[]{""}; - } - } - - return nameIds; - } - - public static JSExpression findClassIdentifier(JSExpression _qualifier) - { - JSExpression qualifier = _qualifier; - if(qualifier instanceof JSReferenceExpression && PROTOTYPE_FIELD_NAME.equals(((JSReferenceExpression) qualifier).getReferencedName())) - { - qualifier = ((JSReferenceExpression) qualifier).getQualifier(); - if(qualifier == null) - { - qualifier = _qualifier; - } - } - - if(qualifier instanceof JSReferenceExpression && ((JSReferenceExpression) qualifier).getQualifier() == null) - { - qualifier = JSSymbolUtil.findReferenceExpressionUsedForClassExtending((JSReferenceExpression) qualifier); - } - return qualifier; - } - - public static boolean iterateType(final JSFunction node, final PsiElement jsClass, final String typeName, final OverrideHandler handler) - { - final Project project = jsClass.getProject(); - - if(jsClass instanceof JSClass) - { - String namespace = null; - JSAttributeList attributeList = node.getAttributeList(); - if(attributeList != null) - { - namespace = attributeList.getNamespace(); - } - return processOverrides(jsClass, handler, node.getName(), namespace, node); - } - - return true; - } - - public static boolean processOverrides(final PsiElement jsClass, final OverrideHandler handler, String name, final Object namespace, final PsiElement context) - { - JSClass clazz = (JSClass) jsClass; - final ResolveProcessor resolveProcessor = new ResolveProcessor(name, context) - { - { - setToProcessHierarchy(true); - } - - @Override - public boolean execute(final PsiElement element, final ResolveState state) - { - if(!(element instanceof JSFunction)) - { - return true; - } - JSFunction fun = (JSFunction) element; - final JSAttributeList attributeList = fun.getAttributeList(); - if(attributeList != null && attributeList.getAccessType() == JSAttributeList.AccessType.PRIVATE) - { - return false; - } - - if((namespace == null && attributeList != null && attributeList.getNamespace() != null) || (namespace != null && (attributeList == null || !namespace.equals(attributeList - .getNamespace())))) - { - return true; - } - return super.execute(element, state); - } - }; - - for(JSClass superClazz : clazz.getSuperClasses()) - { - if(superClazz == clazz) - { - break; - } - final boolean b = superClazz.processDeclarations(resolveProcessor, ResolveState.initial(), superClazz, context); - - if(!b) - { - final PsiElement element = resolveProcessor.getResult(); - if(element == null) - { - continue; - } - PsiElement parent = findParent(element); - - if(parent instanceof JSClass && !handler.process(resolveProcessor, superClazz, ((JSClass) parent).getQualifiedName())) - { - return false; - } - } - } - - return true; - } - - public static String getQNameToStartHierarchySearch(final JSFunction node) - { - PsiElement parentNode = node.getParent(); - parentNode = getClassReferenceForXmlFromContext(parentNode); - - if(parentNode instanceof JSClass) - { - final JSAttributeList attributeList = node.getAttributeList(); - - if(attributeList == null || - !attributeList.hasModifier(JSAttributeList.ModifierType.OVERRIDE) || - attributeList.hasModifier(JSAttributeList.ModifierType.STATIC) || - attributeList.getAccessType() == JSAttributeList.AccessType.PRIVATE) - { - return null; - } - - if(parentNode instanceof JSClass) - { - return ((JSClass) parentNode).getQualifiedName(); - } - } - else if(node instanceof JSFunctionExpression && parentNode.getContainingFile().getLanguage() != JavaScriptSupportLoader.ECMA_SCRIPT_L4) - { - final ContextResolver resolver = new ContextResolver(node.getFirstChild()); - return resolver.getQualifierAsString(); - } - else if(parentNode instanceof JSFile && parentNode.getContainingFile().getLanguage() != JavaScriptSupportLoader.ECMA_SCRIPT_L4) - { - return node.getName(); - } - return null; - } - - public static boolean isInPlaceWhereTypeCanBeDuringCompletion(PsiElement expr) - { - final PsiElement parent = expr.getParent(); - if(parent instanceof JSArgumentList || (parent instanceof JSVariable && ((JSVariable) parent).getInitializer() == expr)) - { - return true; - } - if(parent instanceof JSExpressionStatement) - { - if(expr instanceof JSReferenceExpression) - { - return ((JSReferenceExpression) expr).getQualifier() == null; - } - - return true; - } - return false; - } - - public static boolean isPlaceWhereNsCanBe(final PsiElement parent) - { - final PsiElement grandParent = parent.getParent(); - return grandParent instanceof JSClass || grandParent instanceof JSPackageStatement || (grandParent instanceof JSFile && grandParent.getContext() == null); - } - - public static - @Nullable - String getTypeFromTagNameInMxml(final @Nullable PsiElement psiElement) - { - JSClass clazz = getClassFromTagNameInMxml(psiElement); - return clazz != null ? clazz.getQualifiedName() : null; - } - - public static JSClass getClassFromTagNameInMxml(final PsiElement psiElement) - { - XmlTag tag = psiElement != null ? PsiTreeUtil.getNonStrictParentOfType(psiElement, XmlTag.class) : null; - if(tag != null && (tag.getNamespacePrefix().length() > 0 || JavaScriptSupportLoader.isFlexMxmFile(tag.getContainingFile()))) - { - if(isScriptContextTag(tag)) - { - tag = ((XmlFile) tag.getContainingFile()).getDocument().getRootTag(); - } - final XmlElementDescriptor descriptor = tag.getDescriptor(); - - if(descriptor != null) - { - PsiElement decl = descriptor.getDeclaration(); - if(decl instanceof JSClass) - { - return ((JSClass) decl); - } - else if(decl instanceof XmlFile) - { - return XmlBackedJSClassImpl.getXmlBackedClass((XmlFile) decl); - } - } - } - return null; - } - - private static boolean isScriptContextTag(final XmlTag tag) - { - final String localName = tag.getLocalName(); - return "Script".equals(localName) || (localName.length() > 0 && Character.isLowerCase(localName.charAt(0)) && !"method".equals(localName)); - } - - public static boolean processMetaAttributesForClass(final PsiElement jsClass, final MetaDataProcessor processor) - { - return doProcessMetaAttributesForClass(unwrapProxy(jsClass), processor, null, true); - } - - private static boolean doProcessMetaAttributesForClass(final PsiElement jsClass, final MetaDataProcessor processor, PsiElement lastParent, boolean forward) - { - if(jsClass instanceof JSClass) - { - if(OBJECT_CLASS_NAME.equals((((JSClass) jsClass).getQualifiedName()))) - { - return true; - } - final PsiElement[] elements = getStubbedChildren(jsClass.getParent()); - int ind = elements.length - 1; - while(ind >= 0 && elements[ind] != jsClass) - { - --ind; - } - --ind; - - - while(ind >= 0) - { - final PsiElement current = elements[ind]; - - if(current instanceof JSIncludeDirective) - { - if(!processIncludeDirective(processor, jsClass, (JSIncludeDirective) current, false)) - { - return false; - } - --ind; - } - else - { - break; - } - } - - final JSAttributeList attributeList = ((JSClass) jsClass).getAttributeList(); - if(attributeList != null) - { - if(!processAttributeList(processor, jsClass, attributeList, true)) - { - return false; - } - } - } - - final PsiElement[] elements = getStubbedChildren(jsClass); - Ref continuePassElement = new Ref(); - - for(int i = forward ? 0 : elements.length - 1; i < elements.length && i >= 0; i += (forward ? 1 : -1)) - { - PsiElement el = elements[i]; - - if(el instanceof JSIncludeDirective) - { - if(!processIncludeDirective(processor, lastParent, (JSIncludeDirective) el, forward)) - { - return false; - } - } - else if(el instanceof JSAttributeList /*&& lastParent != null*/) - { - if(!processAttributeList(processor, lastParent, (JSAttributeList) el, forward)) - { - return false; - } - } - else - { - continuePassElement.set(null); - if(!processor.handleOtherElement(el, jsClass, continuePassElement)) - { - return false; - } - PsiElement nextEl = continuePassElement.get(); - - if(nextEl instanceof JSAttributeListOwner) - { - JSAttributeList attributeList = ((JSAttributeListOwner) nextEl).getAttributeList(); - - if(attributeList != null) - { - if(!processAttributeList(processor, nextEl, attributeList, forward)) - { - return false; - } - } - } - - } - } - return true; - } - - public static boolean processAttributeList(final MetaDataProcessor processor, final PsiElement el, final JSAttributeList attributeList, boolean forward) - { - final PsiElement[] elements = getStubbedChildren(attributeList); - for(int i = forward ? 0 : elements.length - 1; i < elements.length && i >= 0; i += (forward ? 1 : -1)) - { - final PsiElement cur = elements[i]; - - if(cur instanceof JSIncludeDirective) - { - if(!processIncludeDirective(processor, el, (JSIncludeDirective) cur, forward)) - { - return false; - } - } - else if(cur instanceof JSAttribute) - { - if(!processor.process((JSAttribute) cur)) - { - return false; - } - } - else if(cur instanceof JSNamedElement) - { - break; - } - } - - if(!processor.handleOtherElement(attributeList, el, null)) - { - return false; - } - - return true; - } - - private static boolean processIncludeDirective(final MetaDataProcessor processor, final PsiElement lastParent, final JSIncludeDirective el, boolean forward) - { - final PsiFile file = el.resolveFile(); - - if(file instanceof JSFile) - { - if(!doProcessMetaAttributesForClass(file, processor, lastParent, forward)) - { - return false; - } - } - - return true; - } - - public static PsiElement unwrapProxy(PsiElement jsClass) - { - return jsClass; - } - - public static JSDefinitionExpression getDefinitionExpr(JSExpressionStatement exprStatement) - { - final JSExpression expression = exprStatement.getExpression(); - - if(expression instanceof JSAssignmentExpression) - { - return (JSDefinitionExpression) ((JSAssignmentExpression) expression).getLOperand(); - } - return null; - } - - public static boolean processDeclarationsInScope(final JSElement _scope, final PsiScopeProcessor processor, final ResolveState state, final PsiElement lastParent, final PsiElement place) - { - JSElement scope = PsiUtilBase.getOriginalElement(_scope, _scope.getClass()); - if(scope == null) - { - return true; - } - String requiredName = null; - - if(processor instanceof ResolveProcessor) - { - requiredName = ((ResolveProcessor) processor).getName(); - } - - boolean result = true; - final IntObjectMap defsMap = ourCachedDefsCache.get(MY_CACHED_STATEMENTS, scope, null).getValue(); - - if(requiredName == null) - { - for(Object value : defsMap.values()) - { - result = dispatchResolve(processor, state, place, result, value); - } - } - else - { - final Object defs = defsMap.get(requiredName.hashCode()); - if(defs != null) - { - result = dispatchResolve(processor, state, place, result, defs); - } - } - - return result; - } - - private static boolean dispatchResolve(final PsiScopeProcessor processor, final ResolveState state, final PsiElement place, boolean result, final Object o) - { - if(o instanceof JSElement[]) - { - for(JSElement s : (JSElement[]) o) - { - result &= s.processDeclarations(processor, state, null, place); - } - } - else - { - JSElement s = (JSElement) o; - result &= s.processDeclarations(processor, state, null, place); - } - return result; - } - - public static PsiElement getLocalVariableRef(JSFunction function, final JSReferenceExpression expr) - { - final ResolveProcessor processor = new ResolveProcessor(expr.getReferencedName(), true); - - while(function != null) - { - final boolean val = function.processDeclarations(processor, ResolveState.initial(), function.getParameterList(), function); - if(!val) - { - return processor.getResult(); - } - function = PsiTreeUtil.getParentOfType(function, JSFunction.class); - if(function == null) - { - break; - } - } - return null; - } - - public static class MyResolveResult implements ResolveResult - { - private final PsiElement myFunction; - private final JavaScriptImportStatementBase myImportUsed; - private boolean myValidResult; - - public MyResolveResult(final PsiElement function) - { - this(function, true); - } - - public MyResolveResult(final PsiElement function, JSImportStatement importUsed) - { - this(function, importUsed, true); - } - - public MyResolveResult(final PsiElement function, boolean validResult) - { - this(function, null, validResult); - } - - public MyResolveResult(final PsiElement function, JavaScriptImportStatementBase importUsed, boolean validResult) - { - myFunction = function; - myValidResult = validResult; - myImportUsed = importUsed; - } - - @Override - public PsiElement getElement() - { - return myFunction; - } - - @Override - public boolean isValidResult() - { - return myValidResult; - } - - public void setValid(final boolean b) - { - myValidResult = b; - } - - public JavaScriptImportStatementBase getImportUsed() - { - return myImportUsed; - } - } - - public static Key contextKey = Key.create("context.key"); // JSElement or XmlElement - - public static class RelevantDefsUserDataCache extends UserDataCache>, JSElement, Object> - { - - @Override - protected CachedValue> compute(final JSElement jsElement, final Object o) - { - return CachedValuesManager.getManager(jsElement.getProject()).createCachedValue(new CachedValueProvider>() - { - @Override - public Result> compute() - { - final IntObjectMap relevantDefs = IntMaps.newIntObjectHashMap(); - final MyJSElementVisitor elementVisitor = new MyJSElementVisitor(jsElement, relevantDefs); - elementVisitor.startVisiting(jsElement); - - return new Result>(relevantDefs, jsElement); - } - }, false); - } - - private static class MyJSElementVisitor extends JSElementVisitor - { - private HashMap checkedVarsToOurStatus; - private Set visitedIncludes; - private final IntObjectMap myRelevantDefs; - private final JSElement myBase; - private JSElement context; - - public MyJSElementVisitor(JSElement base, final IntObjectMap relevantDefs) - { - myRelevantDefs = relevantDefs; - myBase = base; - context = base; - } - - private void startVisiting(JSElement jsElement) - { - PsiElement first = null; - - JSSourceElement[] arrayElementsToScan = null; - - if(jsElement instanceof JSFunction) - { - final JSSourceElement[] body = ((JSFunction) jsElement).getBody(); - if(body.length > 0 && body[0] instanceof JSBlockStatement) - { - first = PsiTreeUtil.findChildOfType(body[0], JSStatement.class); - } - } - else if(jsElement instanceof JSFile) - { - if(myBase == context) - { - first = jsElement.getFirstChild(); - } - else - { - arrayElementsToScan = getSourceElements(jsElement); - } - } - else if(jsElement instanceof JSClass || jsElement instanceof JSPackageStatement) - { - arrayElementsToScan = getSourceElements(jsElement); - } - else - { - first = jsElement.getFirstChild(); - } - - if(arrayElementsToScan != null) - { - for(JSSourceElement elt : arrayElementsToScan) - { - elt.accept(this); - } - } - else - { - for(PsiElement e = first; e != null; e = e.getNextSibling()) - { - if(e instanceof JSSourceElement) - { - e.accept(this); - } - } - } - } - - @Override - public void visitJSDefinitionExpression(final JSDefinitionExpression node) - { - final JSExpression definedExpr = node.getExpression(); - if(definedExpr instanceof JSReferenceExpression && ((JSReferenceExpression) definedExpr).getQualifier() == null && false) - { - final String s = definedExpr.getText(); - if(checkedVarsToOurStatus == null) - { - checkedVarsToOurStatus = new HashMap(3); - } - Boolean aBoolean = checkedVarsToOurStatus.get(s); - - if(aBoolean == null) - { - final boolean isInjectedFile = isInjectedFile(myBase); - PsiElement element = null; - - if(myBase instanceof JSFunction || isInjectedFile) - { - final ResolveProcessor processor = new ResolveProcessor(s); - final PsiElement baseParent = myBase.getParent(); - treeWalkUp(processor, baseParent, baseParent, baseParent); - element = processor.getResult(); - } - - aBoolean = (element == null) ? Boolean.TRUE : Boolean.FALSE; - checkedVarsToOurStatus.put(s, aBoolean); - } - - if(aBoolean == Boolean.TRUE) - { - addRelevantDef(node); - } - } - } - - @Override - public void visitJSVariable(JSVariable node) - { - addRelevantDef(node); - } - - @Override - public void visitJSIncludeDirective(final JSIncludeDirective includeDirective) - { - final PsiFile _file = includeDirective.resolveFile(); - - if(!(_file instanceof JSFile) || myBase.getContainingFile() == _file) - { - return; - } - final JSFile file = (JSFile) _file; - if(visitedIncludes != null && visitedIncludes.contains(file)) - { - return; - } - if(visitedIncludes == null) - { - visitedIncludes = new HashSet(); - } - visitedIncludes.add(file); - - final JSElement prevContext = context; - context = file; - context.putUserData(contextKey, myBase); - startVisiting(file); - context = prevContext; - } - - @Override - public void visitJSVarStatement(final JSVarStatement node) - { - for(JSVariable var : node.getVariables()) - { - if(!var.isLocal()) - { - var.accept(this); - } - } - } - - @Override - public void visitJSParameter(JSParameter node) - { - } - - @Override - public void visitJSFunctionExpression(final JSFunctionExpression node) - { - // do not go inside other funcs - } - - @Override - public void visitJSObjectLiteralExpression(final JSObjectLiteralExpression node) - { - // do not go inside other funcs - } - - @Override - public void visitJSClass(final JSClass aClass) - { - // do not go inside other funcs - } - - @Override - public void visitJSPackageStatement(JSPackageStatement packageStatement) - { - // do not go inside other funcs - } - - @Override - public void visitJSFunctionDeclaration(final JSFunction node) - { - addRelevantDef(node); - } - - @Override - public void visitJSImportStatement(final JSImportStatement importStatement) - { - // do not expand tree - } - - @Override - public void visitJSUseNamespaceDirective(final JSUseNamespaceDirective useNamespaceDirective) - { - final String namespaceToBeUsed = useNamespaceDirective.getNamespaceToBeUsed(); - if(namespaceToBeUsed != null) - { - addNamedElement(useNamespaceDirective, namespaceToBeUsed.hashCode()); - } - } - - private void addRelevantDef(final JSNamedElement node) - { - final String name = node.getName(); - - if(name != null) - { - final int key = name.hashCode(); - addNamedElement(node, key); - } - } - - private void addNamedElement(final JSElement node, final int key) - { - final Object o = myRelevantDefs.get(key); - - if(o == null) - { - myRelevantDefs.put(key, node); - } - else if(o instanceof JSElement) - { - final JSElement[] newO = new JSElement[]{ - (JSElement) o, - node - }; - myRelevantDefs.put(key, newO); - } - else - { - final JSElement[] oldO = (JSElement[]) o; - final JSElement[] newO = new JSElement[oldO.length + 1]; - System.arraycopy(oldO, 0, newO, 0, oldO.length); - newO[oldO.length] = node; - myRelevantDefs.put(key, newO); - } - } - - @Override - public void visitElement(final PsiElement element) - { - element.acceptChildren(this); - } - } - } - - public static class ContextResolver - { - private JSElement qualifyingExpression; - private JSNamedElement parentContainer; - private String typeName; - - public ContextResolver(JSExpression expr) - { - if(expr instanceof JSThisExpression || expr instanceof JSSuperExpression) - { - // We need to resolve ns mapping for 'this', which function was the constructor of the object - resolveContext(expr); - } - else - { - qualifyingExpression = expr instanceof JSReferenceExpression ? JSSymbolUtil.findReferenceExpressionUsedForClassExtending((JSReferenceExpression) expr) : expr; - } - } - - public ContextResolver(PsiElement element) - { - resolveContext(element); - } - - private void resolveContext(final PsiElement context) - { - parentContainer = PsiTreeUtil.getParentOfType(context, JSFunction.class, JSClass.class); - - if(parentContainer instanceof JSFunctionExpression) - { - boolean changedFunctionScope = false; - - while(parentContainer instanceof JSFunctionExpression) - { - final PsiElement parentContainerParent = parentContainer.getParent(); - - if(parentContainerParent instanceof JSAssignmentExpression) - { - final JSExpression jsExpression = ((JSAssignmentExpression) parentContainerParent).getLOperand(); - final JSElement functionExpressionName = jsExpression instanceof JSDefinitionExpression ? ((JSDefinitionExpression) jsExpression).getExpression() : null; - qualifyingExpression = functionExpressionName; - - if(functionExpressionName instanceof JSReferenceExpression) - { - final JSExpression functionExpressionNameQualifier = ((JSReferenceExpression) functionExpressionName).getQualifier(); - - if(functionExpressionNameQualifier instanceof JSThisExpression) - { - parentContainer = PsiTreeUtil.getParentOfType(functionExpressionName, JSFunction.class); - qualifyingExpression = null; - changedFunctionScope = true; - continue; - } - else if(functionExpressionNameQualifier instanceof JSReferenceExpression) - { - final String functionExpressionNameQualifierText = ((JSReferenceExpression) functionExpressionNameQualifier).getReferencedName(); - - if(PROTOTYPE_FIELD_NAME.equals(functionExpressionNameQualifierText)) - { - qualifyingExpression = ((JSReferenceExpression) functionExpressionNameQualifier).getQualifier(); - } - else if(!changedFunctionScope) - { - String referencedName; - - if(((JSReferenceExpression) functionExpressionNameQualifier).getQualifier() == null && ((referencedName = ((JSReferenceExpression) functionExpressionName) - .getReferencedName()) == null || - referencedName.length() == 0 || - !Character.isUpperCase(referencedName.charAt(0)))) - { - qualifyingExpression = functionExpressionNameQualifier; - } - } - } - } - } - else if(parentContainerParent instanceof JSProperty) - { - final JSElement element = PsiTreeUtil.getParentOfType(parentContainerParent, JSVariable.class, JSAssignmentExpression.class, JSArgumentList.class); - if(element instanceof JSVariable) - { - qualifyingExpression = element; - } - else if(element instanceof JSAssignmentExpression) - { - JSExpression loperand = ((JSAssignmentExpression) element).getLOperand(); - if(loperand != null) - { - qualifyingExpression = ((JSDefinitionExpression) loperand).getExpression(); - } - } - else if(element instanceof JSArgumentList) - { - qualifyingExpression = JSSymbolUtil.findQualifyingExpressionFromArgumentList((JSArgumentList) element); - } - } - else if(parentContainerParent instanceof JSNewExpression) - { - final JSElement element = PsiTreeUtil.getParentOfType(parentContainerParent, JSVariable.class, JSAssignmentExpression.class, JSArgumentList.class); - - if(element instanceof JSVariable) - { - qualifyingExpression = element; - } - else if(element instanceof JSAssignmentExpression) - { - qualifyingExpression = ((JSDefinitionExpression) ((JSAssignmentExpression) element).getLOperand()).getExpression(); - } - } - else if(parentContainerParent instanceof JSReferenceExpression) - { - parentContainer = PsiTreeUtil.getParentOfType(parentContainerParent, JSFunction.class); - continue; - } - else if(parentContainer.getName() == null) - { - parentContainer = PsiTreeUtil.getParentOfType(parentContainerParent, JSFunction.class); - continue; - } - - break; - } - - if(qualifyingExpression instanceof JSReferenceExpression) - { - final JSReferenceExpression qualifyingReferenceExpression = ((JSReferenceExpression) qualifyingExpression); - final String functionExpressionNameQualifierText = qualifyingReferenceExpression.getReferencedName(); - - if(PROTOTYPE_FIELD_NAME.equals(functionExpressionNameQualifierText)) - { - qualifyingExpression = qualifyingReferenceExpression.getQualifier(); - } - else - { - - qualifyingExpression = JSSymbolUtil.findReferenceExpressionUsedForClassExtending(qualifyingReferenceExpression); - } - } - } - - PsiElement parentContainerParent = parentContainer != null ? parentContainer.getParent() : null; - - if(parentContainerParent instanceof JSFile) - { - parentContainerParent = getClassReferenceForXmlFromContext(parentContainerParent); - } - - if(parentContainerParent instanceof JSClass) - { - parentContainer = (JSNamedElement) parentContainerParent; - } - - if(parentContainer instanceof JSFunctionExpression && parentContainer.getContainingFile().getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4) - { - parentContainer = null; - qualifyingExpression = null; - typeName = OBJECT_CLASS_NAME; - } - } - - public - @Nullable - String getQualifierAsString() - { - String qualifierAsString = getOriginalQualifierAsString(); - return normalizeQualifier(qualifierAsString); - } - - private static String normalizeQualifier(String qualifierAsString) - { - if("Window".equals(qualifierAsString) || "Document".equals(qualifierAsString)) - { - qualifierAsString = StringUtil.decapitalize(qualifierAsString); - } - return qualifierAsString; - } - - private String getOriginalQualifierAsString() - { - if(qualifyingExpression instanceof JSLiteralExpression) - { - return StringUtil.stripQuotesAroundValue(qualifyingExpression.getText()); - } - else if(qualifyingExpression instanceof JSReferenceExpression) - { - return qualifyingExpression.getText(); - } - else if(qualifyingExpression instanceof JSNamedElement) - { - return qualifyingExpression.getName(); - } - else if(parentContainer instanceof JSQualifiedNamedElement) - { - return ((JSQualifiedNamedElement) parentContainer).getQualifiedName(); - } - - return typeName; - } - - @Nullable - public String[] getQualifierAsNameIndex() - { - String qualifierAsString = getQualifierAsString(); - if(qualifierAsString != null) - { - List list = new ArrayList(); - qualifierAsString = BaseJSSymbolProcessor.addIndexListFromQName(qualifierAsString, qualifyingExpression, list); - return ArrayUtil.toStringArray(list); - } - - return null; - } - - public static String getQualifierOfExprAsString(JSElement expr) - { - if(expr instanceof JSNamedElement) - { - return expr.getName(); - } - if(expr instanceof JSReferenceExpression && PROTOTYPE_FIELD_NAME.equals(((JSReferenceExpression) expr).getReferencedName())) - { - expr = ((JSReferenceExpression) expr).getQualifier(); - } - return normalizeQualifier(StringUtil.stripQuotesAroundValue(expr.getText())); - } - } - - private static boolean isInjectedFile(PsiElement element) - { - return element instanceof PsiFile && (((PsiFile) element).getVirtualFile() instanceof LightVirtualFile); - } - - @RequiredReadAction - public static void processGlobalSymbols(PsiElement target, PsiScopeProcessor processor) - { - Sdk sdk = ModuleUtilCore.getSdk(target, JavaScriptModuleExtension.class); - if(sdk != null) - { - VirtualFile[] files = sdk.getRootProvider().getFiles(BinariesOrderRootType.getInstance()); - - for(VirtualFile file : files) - { - PsiFile psiFile = PsiManager.getInstance(target.getProject()).findFile(file); - if(psiFile instanceof JSFile) - { - if(!psiFile.processDeclarations(processor, ResolveState.initial(), null, target)) - { - return; - } - } - } - } - } - - public interface OverrideHandler - { - boolean process(ResolveProcessor processor, final PsiElement scope, String className); - } - - public interface MetaDataProcessor - { - boolean process(final @Nonnull JSAttribute jsAttribute); - - boolean handleOtherElement(final PsiElement el, PsiElement context, @Nullable Ref continuePassElement); - } - - public static abstract class CollectMethodsToImplementProcessor extends ResolveProcessor - { - private final String myName; - - public CollectMethodsToImplementProcessor(final String name, PsiElement context) - { - super(null, context); - myName = name; - - setToSkipClassDeclarationsOnce(true); - setToProcessHierarchy(true); - setToProcessMembers(false); - setTypeContext(true); - } - - @Override - public boolean execute(final PsiElement element, final ResolveState state) - { - final ResolveProcessor processor = new ResolveProcessor(myName, place) - { - @Override - public boolean execute(final PsiElement element, final ResolveState state) - { - if(element instanceof JSFunction) - { - if(OBJECT_CLASS_NAME.equals(((JSClass) findParent((JSNamedElement) element)).getQualifiedName()) || ((JSFunction) element).isConstructor()) - { - return true; - } - } - else - { - return true; - } - return super.execute(element, state); - } - - { - setToProcessHierarchy(true); - } - }; - for(JSClass implementedInterface : ((JSClass) element).getImplementedInterfaces()) - { - if(!implementedInterface.isInterface()) - { - continue; - } - final boolean b = implementedInterface.processDeclarations(processor, ResolveState.initial(), implementedInterface, implementedInterface); - - if(!b) - { - process(processor); - break; - } - } - - if(myName == null && processor.getResults() != null) - { - process(processor); - } - return false; - } - - protected abstract boolean process(ResolveProcessor processor); - } - - static JSSourceElement[] getSourceElements(final PsiElement owner) - { - if(owner instanceof JSStubElementImpl) - { - return (JSSourceElement[]) ((JSStubElementImpl) owner).getStubOrPsiChildren(JSElementTypes.SOURCE_ELEMENTS, JSSourceElement.EMPTY_ARRAY); - } - else if(owner instanceof JSFile) - { - return ((JSFile) owner).getStatements(); - } - return JSSourceElement.EMPTY_ARRAY; - } - - public static PsiElement[] getStubbedChildren(final PsiElement owner) - { - return getStubbedChildren(owner, ourStubbedFilter); - } - - public static PsiElement[] getStubbedChildren(final PsiElement owner, TokenSet filter) - { - if(owner instanceof JSStubElementImpl) - { - final JSStubElementImpl element = (JSStubElementImpl) owner; - final StubElement stub = element.getStub(); - if(stub != null) - { - return stub.getChildrenByType(filter, PsiElement.EMPTY_ARRAY); - } - return getChildrenFromTokenSet(element.getNode(), filter); - } - else if(owner instanceof JSFile) - { - final JSFile file = (JSFile) owner; - final StubElement stub = ((JSFileImpl) file).getStub(); - if(stub != null) - { - return stub.getChildrenByType(filter, PsiElement.EMPTY_ARRAY); - } - return getChildrenFromTokenSet(file.getNode(), filter); - } - return PsiElement.EMPTY_ARRAY; - } - - private static PsiElement[] getChildrenFromTokenSet(final ASTNode astNode, TokenSet filter) - { - final ASTNode[] astNodes = astNode.getChildren(filter); - PsiElement[] result = new PsiElement[astNodes.length]; - for(int i = 0; i < astNodes.length; ++i) - { - result[i] = astNodes[i].getPsi(); - } - return result; - } - - private static final TokenSet ourStubbedFilter = TokenSet.create(JSElementTypes.CLASS, JSElementTypes.VAR_STATEMENT, JSElementTypes.FUNCTION_DECLARATION, JSElementTypes.ATTRIBUTE_LIST, - JSElementTypes.INCLUDE_DIRECTIVE, JSElementTypes.ATTRIBUTE, JSElementTypes.PACKAGE_STATEMENT); - - private static class ImplicitJSVariableImpl extends LightElement implements JSVariable - { - private final PsiFile myContainingFile; - private final String myName; - private final String myType; - - public ImplicitJSVariableImpl(final String name, String qName, PsiFile containingFile) - { - super(containingFile.getManager(), JavaScriptSupportLoader.ECMA_SCRIPT_L4.getBaseLanguage()); - myContainingFile = containingFile; - myName = name; - myType = qName; - } - - @Override - public JSAttributeList getAttributeList() - { - return null; - } - - @Override - public boolean isValid() - { - return myContainingFile.isValid(); - } - - @Override - public PsiElement getParent() - { - return myContainingFile; - } - - @Override - public PsiFile getContainingFile() - { - return myContainingFile; - } - - @RequiredReadAction - @Override - public String getText() - { - return null; - } - - @Override - public void accept(@Nonnull PsiElementVisitor visitor) - { - if(visitor instanceof JSElementVisitor) - { - ((JSElementVisitor) visitor).visitJSVariable(this); - } - else - { - visitor.visitElement(this); - } - } - - @Override - public PsiElement copy() - { - return new ImplicitJSVariableImpl(myName, myType, myContainingFile); - } - - @Override - public boolean canNavigate() - { - return false; - } - - @Override - public boolean isPhysical() - { - return false; - } - - @Nonnull - @Override - public ASTNode getNode() - { - return null; - } - - @Override - public boolean hasInitializer() - { - return false; - } - - @Override - public JSExpression getInitializer() - { - return null; - } - - @Override - public String getInitializerText() - { - return null; - } - - @Override - public void setInitializer(JSExpression expr) throws IncorrectOperationException - { - } - - @Nonnull - @Override - public JavaScriptType getType() - { - return JavaScriptType.UNKNOWN; - } - - @Override - public String getTypeString() - { - return myType; - } - - @RequiredReadAction - @Override - public JavaScriptTypeElement getTypeElement() - { - return null; - } - - @Override - public boolean isConst() - { - return false; - } - - @Override - public boolean isLocal() - { - return false; - } - - @Override - public boolean isDeprecated() - { - return false; - } - - @Override - public String getQualifiedName() - { - return myName; - } - - @Override - public String getName() - { - return myName; - } - - @Override - public PsiElement setName(@NonNls @Nonnull String name) throws IncorrectOperationException - { - throw new IncorrectOperationException(); - } - - @Override - public PsiElement getNameIdentifier() - { - return null; - } - - @Override - public String toString() - { - return "js_implicit_var:" + myName + ", type:" + myType + ", file:" + myContainingFile; - } - - @Override - public boolean isEquivalentTo(PsiElement another) - { - return another == this || (another instanceof ImplicitJSVariableImpl && - myContainingFile == ((ImplicitJSVariableImpl) another).myContainingFile && - myName.equals(((ImplicitJSVariableImpl) another).myName)); - } - } +public class JSResolveUtil { + private static final Key>> CACHED_STATEMENTS = Key.create("JS.RelevantStatements"); + private static final UserDataCache>, JSElement, Object> CACHED_DEFS_CACHE = + new RelevantDefsUserDataCache(); + public static final String PROTOTYPE_FIELD_NAME = "prototype"; + + private static final String ARRAY_TYPE_NAME = "Array"; + private static final String ARGUMENTS_TYPE_NAME = "Arguments"; + + public static final String COMMENT_DELIMITERS = "|/"; + + public static void processInjectedFileForTag(@Nonnull XmlTag tag, @Nonnull JSInjectedFilesVisitor visitor) { + InjectedLanguageManager injectedLanguageManager = InjectedLanguageManager.getInstance(tag.getProject()); + + for (XmlTagChild child : tag.getValue().getChildren()) { + if (child instanceof XmlText xmlText) { + injectedLanguageManager.enumerate(xmlText, visitor); + } + } + } + + @RequiredReadAction + public static String findPackageForMxml(PsiElement expression) { + String s = null; + PsiFile containingFile = expression.getContainingFile(); + + if (containingFile.getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4 && containingFile.getContext() != null) { + PsiFile contextContainigFile = containingFile.getContext().getContainingFile(); + VirtualFile file = contextContainigFile.getVirtualFile(); + if (file == null && contextContainigFile.getOriginalFile() != null) { + file = contextContainigFile.getOriginalFile().getVirtualFile(); + } + + s = getExpectedPackageNameFromFile(file, containingFile.getProject(), true); + } + return s; + } + + public static String getExpectedPackageNameFromFile(VirtualFile file, Project project, boolean allowEvaluationFromContextRoot) { + ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(project).getFileIndex(); + Module moduleForFile = file != null ? projectFileIndex.getModuleForFile(file) : null; + + if (moduleForFile != null) { + if (file instanceof VirtualFileWindow virtualFileWindow) { + file = virtualFileWindow.getDelegate(); + } + VirtualFile rootForFile = projectFileIndex.getSourceRootForFile(file); + if (rootForFile == null && allowEvaluationFromContextRoot) { + rootForFile = projectFileIndex.getContentRootForFile(file); + } + + if (rootForFile != null) { + return VirtualFileUtil.getRelativePath(file.isDirectory() ? file : file.getParent(), rootForFile, '.'); + } + } + return null; + } + + public static void processInterfaceMethods(JSClass clazz, CollectMethodsToImplementProcessor implementedMethodProcessor) { + clazz.processDeclarations(implementedMethodProcessor, ResolveState.initial(), clazz, clazz); + } + + @RequiredReadAction + public static String getExpressionType(JSExpression expression, PsiFile containingFile) { + String type = getQualifiedExpressionType(expression, containingFile); + + return getShortenedType(type, expression); + } + + public static String getShortenedType(String type, PsiElement context) { + if (type == null) { + type = "*"; + } + else { + String shortName = getShortTypeName(type); + String expr = JSImportHandlingUtil.resolveTypeName(shortName, context); + if (expr != null && !expr.equals(shortName)) { + type = shortName; + } + } + return type; + } + + @RequiredReadAction + public static String getQualifiedExpressionType(JSExpression expression, PsiFile containingFile) { + String type = null; + + if (expression != null) { + BaseJSSymbolProcessor.SimpleTypeProcessor processor = + new BaseJSSymbolProcessor.SimpleTypeProcessor(JavaScriptVersionUtil.getFeatures(expression)); + BaseJSSymbolProcessor.doEvalForExpr(expression, containingFile, processor); + type = processor.getType(); + } + + return type; + } + + private static String getShortTypeName(String type) { + String str = type; + + int i = str.indexOf('<'); + String signature = null; + + if (i != -1) { + int index = str.lastIndexOf('.', i); + if (index == -1) { + return type; + } + signature = str.substring(index); + str = str.substring(0, index); + } + + int i2 = str.lastIndexOf('.'); + if (i2 != -1) { + str = str.substring(i2 + 1); + } + + return str + (signature != null ? signature : ""); + } + + // TODO remove this method, call generic one processing includes as well (like findParent()) + public static PsiElement getClassReferenceForXmlFromContext(PsiElement parent) { + if (parent != null && parent.getContext() instanceof XmlElement xmlElement + && xmlElement.getContainingFile() instanceof XmlFile) { + return XmlBackedJSClassImpl.getContainingComponent(xmlElement); + } + return parent; + } + + @Nullable + public static XmlBackedJSClassImpl getXmlBackedClass(JSFile injectedJsFile) { + PsiElement context = injectedJsFile.getContext(); + if (context instanceof XmlAttributeValue || context instanceof XmlText) { + return XmlBackedJSClassImpl.getContainingComponent((XmlElement)context); + } + return null; + } + + @RequiredReadAction + public static SearchScope findUseScope(T jsVariableBase) { + PsiElement element = PsiTreeUtil.getParentOfType( + jsVariableBase, + JSFunction.class, + JSCatchBlock.class, + JSClass.class, + JSObjectLiteralExpression.class, + JSFile.class + ); + PsiElement scopeElement = element; + + if (element instanceof JSFile jsFile) { + PsiElement xmlFromContext = getClassReferenceForXmlFromContext(jsFile); + + if (xmlFromContext != jsFile) { + element = xmlFromContext; + scopeElement = element.getContainingFile(); + } + else { + element = null; + } + } + + if (element != null) { + if (element instanceof JSFunction function) { + PsiElement elt = + JSDocumentationUtils.findDocComment(JSDocumentationProvider.findElementForWhichPreviousCommentWillBeSearched(function)); + if (elt instanceof PsiComment comment) { + return new LocalSearchScope(new PsiElement[]{comment, function}); + } + } + + if (element instanceof JSClass) { + JSAttributeList attributeList = jsVariableBase.getAttributeList(); + + if (attributeList == null || attributeList.getAccessType() != JSAttributeList.AccessType.PRIVATE) { + return ((JSStubElementImpl)jsVariableBase).getDefaultUseScope(); + } + } + return new LocalSearchScope(scopeElement); + } + return ((JSStubElementImpl)jsVariableBase).getDefaultUseScope(); + } + + @RequiredReadAction + public static boolean isAssignableType(String expectedType, String type, PsiElement context) { + if ((expectedType != null && hasMultipleOccurenceDelimiters(expectedType)) + || (type != null && hasMultipleOccurenceDelimiters(type))) { + StringTokenizer expectedTypeIterator = new StringTokenizer(expectedType != null ? expectedType : "", COMMENT_DELIMITERS); + + while (expectedTypeIterator.hasMoreElements()) { + String primitiveExpectedType = expectedTypeIterator.nextToken().trim(); + StringTokenizer typeIterator = new StringTokenizer(type != null ? type : "", COMMENT_DELIMITERS); + + while (typeIterator.hasMoreElements()) { + String primitiveType = typeIterator.nextToken().trim(); + if (isAssignableType(primitiveExpectedType, primitiveType, context)) { + return true; + } + } + } + + return false; + } + if (expectedType == null || expectedType.equals("*") || expectedType.equals(OBJECT_CLASS_NAME) || expectedType.equals("Class")) { + return true; + } + if (expectedType.equals(type)) { + return true; + } + + boolean nonecma = context.getContainingFile().getLanguage() != JavaScriptSupportLoader.ECMA_SCRIPT_L4; + + if ("Number".equals(expectedType) && ("int".equals(type) || "uint".equals(type) + || (("Boolean".equals(type) || "String".equals(type)) && nonecma))) { + return true; + } + if ("int".equals(expectedType) + && ("Number".equals(type) || ("String".equals(type) && nonecma) || "uint".equals(type))) { + return true; // compatibility + } + + if ("uint".equals(expectedType) && ("int".equals(type) || "Number".equals(type))) { + return true; + } + if (ARRAY_TYPE_NAME.equals(type)) { + if (ARGUMENTS_TYPE_NAME.equals(expectedType) || expectedType.startsWith(ARRAY_TYPE_NAME) /*Array[*/ + || JSTypeEvaluateManager.isArrayType(expectedType)) { + return true; + } + } + + if (ARGUMENTS_TYPE_NAME.equals(type) && nonecma) { + return true; // TODO: hack for indirect call Array.slice(arguments, 0) + } + + if (ARRAY_TYPE_NAME.equals(expectedType) && JSTypeEvaluateManager.isArrayType(type)) { + return true; + } + if ("String".equals(expectedType) + && (("Number".equals(type) || "int".equals(type) || "Boolean".equals(type) || "RegExp".equals(type)) + && nonecma)) { + return true; + } + + if ("*".equals(type) || (OBJECT_CLASS_NAME.equals(type) && nonecma)) { + return true; // Dynamic cast + } + if ("void".equals(type)) { + return false; + } + PsiElement typeClass = type != null ? unwrapProxy(findClassByQName(type, context)) : null; + + if (!(typeClass instanceof JSClass)) { + return true; + } + + boolean result = typeClass.processDeclarations( + new ResolveProcessor(null) { + { + setToProcessHierarchy(true); + setTypeContext(true); + setToProcessMembers(false); + setLocalResolve(true); + } + + @Override + @RequiredReadAction + public boolean execute(@Nonnull PsiElement element, ResolveState state) { + if (!(element instanceof JSClass jsClass)) { + return true; + } + boolean sameType = jsClass.getQualifiedName().equals(expectedType); + + if (!sameType) { + for (JSClass implementedClazz : jsClass.getImplementedInterfaces()) { + sameType = + !implementedClazz.processDeclarations(this, ResolveState.initial(), implementedClazz, implementedClazz); + if (sameType) { + break; + } + } + } + return !sameType; + } + }, + ResolveState.initial(), + typeClass, + typeClass + ); + + if (result && isImplicitCastPossible((JSClass)typeClass, expectedType)) { + result = false; + } + + return !result; + } + + private static boolean hasMultipleOccurenceDelimiters(String expectedType) { + String commentDelimiters = COMMENT_DELIMITERS; + + for (int i = 0; i < commentDelimiters.length(); ++i) { + if (expectedType.indexOf(commentDelimiters.charAt(i)) != -1) { + return true; + } + } + return false; + } + + @RequiredReadAction + private static boolean isImplicitCastPossible(JSClass typeClass, String expectedType) { + // TODO: move to flex support plugin + if (expectedType.equals("flash.events.IEventDispatcher")) { + JSAttributeList attributeList = typeClass.getAttributeList(); + if (attributeList != null) { + return attributeList.getAttributesByName("Bindable").length != 0; + } + } + return false; + } + + public static PsiElement getTopReferenceParent(PsiElement parent) { + PsiElement currentParent = parent; + for (; currentParent instanceof JSReferenceExpression; currentParent = currentParent.getParent()) { + ; + } + return currentParent; + } + + public static PsiElement getTopReferenceExpression(@Nonnull PsiElement parent) { + PsiElement element = parent; + + for (PsiElement currentParent = parent.getParent(); currentParent instanceof JSReferenceExpression; + element = currentParent, currentParent = currentParent.getParent()) { + ; + } + return element; + } + + @RequiredReadAction + public static boolean isSelfReference(PsiElement currentParent, PsiElement elt) { + return currentParent instanceof JSPackageStatement || currentParent instanceof JSNamespaceDeclaration + || (currentParent instanceof JSVariable variable && variable.getNameIdentifier() == elt) + || (currentParent instanceof JSFunction function && function.getNameIdentifier() == elt) + || currentParent instanceof JSClass; + } + + public static PsiElement findParent(PsiElement element) { + PsiElement parent = element instanceof JSVariable variable ? variable.getParent().getParent() : element.getParent(); + return parent instanceof JSFile jsFile ? findParentClass(jsFile) : parent; + } + + private static PsiElement findParentClass(JSFile file) { + JSClass xmlBackedClass = getXmlBackedClass(file); + if (xmlBackedClass != null) { + return xmlBackedClass; + } + + PsiElement forcedContext = file.getUserData(contextKey); + if (forcedContext != null && !forcedContext.isValid()) { + forcedContext = null; + } + + if (forcedContext instanceof JSClass jsClass) { + return jsClass; + } + + if (forcedContext instanceof JSFile jsFile) { + return findParentClass(jsFile); + } + + if (forcedContext instanceof XmlFile xmlFile && JavaScriptSupportLoader.isFlexMxmFile(xmlFile)) { + return XmlBackedJSClassImpl.getXmlBackedClass(xmlFile); + } + + if (forcedContext instanceof XmlElement xmlElement) { + PsiFile containingFile = xmlElement.getContainingFile(); + if (JavaScriptSupportLoader.isFlexMxmFile(containingFile)) { + return XmlBackedJSClassImpl.getXmlBackedClass((XmlFile)containingFile); + } + } + + if (forcedContext != null) { + PsiFile containingFile = forcedContext.getContainingFile(); + if (containingFile instanceof JSFile jsFile && containingFile != file) { + return findParentClass(jsFile); + } + } + return file; + } + + @Nullable + public static JSClass getClassOfContext(PsiElement node) { + JSClass jsClass = PsiTreeUtil.getParentOfType(node, JSClass.class); + if (jsClass != null) { + return jsClass; + } + else { + PsiElement context = getClassReferenceForXmlFromContext(node.getContainingFile()); + if (context instanceof JSClass contextClass) { + return contextClass; + } + } + + return null; + } + + @Nullable + @RequiredReadAction + public static JSClass findClassOfQualifier(JSExpression qualifier, PsiFile containingFile) { + String s = getQualifiedExpressionType(qualifier, containingFile); + PsiElement qName = s != null ? unwrapProxy(findClassByQName(s, containingFile)) : null; + return qName instanceof JSClass jsClass ? jsClass : null; + } + + public static boolean referenceExpressionShouldBeQualified(JSReferenceExpression contextExpr) { + PsiElement parent = contextExpr.getParent(); + return parent instanceof JSImportStatement + || (parent instanceof JSReferenceList && contextExpr.getContainingFile().getContext() != null); + } + + public static boolean isArtificialClassUsedForReferenceList(JSClass clazz) { + return clazz.getContainingFile().getContext() != null; + } + + @RequiredReadAction + public static Collection findElementsByName(String name, Project project, GlobalSearchScope scope) { + Set result = new HashSet<>(); + Collection jsQualifiedNamedElements = + StubIndex.getElements(JavaScriptIndexKeys.ELEMENTS_BY_NAME, name, project, scope, JSQualifiedNamedElement.class); + + for (JSQualifiedNamedElement e : jsQualifiedNamedElements) { + result.add((JSQualifiedNamedElement)e.getNavigationElement()); + } + + Collection files = new ArrayList<>(); + files.addAll(FileBasedIndex.getInstance() + .getContainingFiles(FilenameIndex.NAME, name + JavaScriptSupportLoader.MXML_FILE_EXTENSION_DOT, scope)); + files.addAll(FileBasedIndex.getInstance() + .getContainingFiles(FilenameIndex.NAME, name + JavaScriptSupportLoader.MXML_FILE_EXTENSION2_DOT, scope)); + + for (VirtualFile file : files) { + if (!file.isValid()) { + continue; + } + PsiFile psiFile = PsiManager.getInstance(project).findFile(file); + if (psiFile != null) { + result.add(XmlBackedJSClassImpl.getXmlBackedClass((XmlFile)psiFile)); + } + } + return result; + } + + @RequiredReadAction + public static boolean isNewResolveAndCompletion(PsiFile psiFile) { + return psiFile.getLanguage().isKindOf(JavaScriptSupportLoader.ECMA_SCRIPT_L4) || JavaScriptSupportLoader.isFlexMxmFile(psiFile); + } + + @RequiredReadAction + public static String getTypeFromSetAccessor(JSNamedElement jsNamedElement) { + if (!(jsNamedElement instanceof JSFunction function && function.isSetProperty())) { + return null; + } + JSParameterList jsParameterList = function.getParameterList(); + if (jsParameterList == null) { + return null; + } + JSParameter[] jsParameters = jsParameterList.getParameters(); + if (jsParameters == null || jsParameters.length != 1) { + return null; + } + return jsParameters[0].getTypeString(); + } + + public static boolean shouldProcessTopLevelGlobalContext(@Nonnull PsiElement place, @Nonnull PsiScopeProcessor processor) { + PsiElement placeParent = null; + + return shouldProcessImports(place, processor) && ( + !((placeParent = place.getParent()) instanceof JSCallExpression) + || (place instanceof JSReferenceExpression refExpr && refExpr.getQualifier() != null + && ((ResolveProcessor)processor).specificallyAskingToResolveQualifiedNames()) + || placeParent instanceof JSNewExpression); + } + + public static boolean shouldProcessImports(@Nonnull PsiElement place, @Nonnull PsiScopeProcessor processor) { + if (!(processor instanceof ResolveProcessor resolveProcessor && !resolveProcessor.isLocalResolve())) { + return false; + } + return !(place instanceof JSReferenceExpression refExpr && refExpr.getQualifier() != null) + || resolveProcessor.specificallyAskingToResolveQualifiedNames(); + } + + @RequiredReadAction + public static boolean processTopLevelClasses( + PsiScopeProcessor processor, + ResolveState state, + Project project, + GlobalSearchScope scope, + boolean acceptOnlyClasses, + boolean acceptQualifiedElements + ) { + boolean result = true; + String resolvedName = ((ResolveProcessor)processor).getName(); + + if (resolvedName == null) { + for (String s : StubIndex.getInstance().getAllKeys(JavaScriptIndexKeys.ELEMENTS_BY_NAME, project)) { + for (JSQualifiedNamedElement e : StubIndex.getElements( + JavaScriptIndexKeys.ELEMENTS_BY_NAME, + s, + project, + scope, + JSQualifiedNamedElement.class + )) { + if (ARGUMENTS_TYPE_NAME.equals(e.getName())) { + continue; + } + if (acceptOnlyClasses && !(e instanceof JSClass)) { + continue; + } + + if (!acceptQualifiedElements) { + String qName = e.getQualifiedName(); + if (qName != null && qName.indexOf('.') != -1) { + continue; + } + } + result &= processor.execute(e, state); + } + } + } + else { + for (JSQualifiedNamedElement e : StubIndex.getElements( + JavaScriptIndexKeys.ELEMENTS_BY_QNAME, + resolvedName, + project, + scope, + JSQualifiedNamedElement.class + )) { + if (!e.getName().equals(resolvedName)) { + continue; + } + if (acceptOnlyClasses && !(e instanceof JSClass)) { + continue; + } + result = processor.execute(e, state); + if (!result) { + break; + } + } + } + return result; + } + + static boolean walkOverStructure(@Nonnull PsiElement context, Processor processor) { + PsiNamedElement parent = PsiTreeUtil.getNonStrictParentOfType(context, JSQualifiedNamedElement.class, PsiFile.class); + + if (parent instanceof JSClass jsClass) { + PsiElement forcedContext = jsClass.getUserData(contextKey); + + if (forcedContext instanceof XmlBackedJSClassImpl xmlBackedJSClass && !processor.process(xmlBackedJSClass)) { + return false; + } + } + + while (parent != null) { + if (!processor.process(parent)) { + return false; + } + + if (parent instanceof JSPackageStatement) { + break; + } + + if (parent instanceof PsiFile file) { + PsiElement data = file.getUserData(contextKey); + + if (data instanceof JSElement jsElement) { + parent = PsiTreeUtil.getNonStrictParentOfType(jsElement, JSQualifiedNamedElement.class, PsiFile.class); + } + else { + break; + } + } + else { + parent = PsiTreeUtil.getParentOfType(parent, JSQualifiedNamedElement.class, PsiFile.class); + } + } + + return true; + } + + private static final Key, JSElement>> ourCachedOpenedNsesKey = Key.create("opened.nses"); + + private static final UserDataCache, JSElement>, JSElement, Object> ourCachedOpenedNsesCache = + new UserDataCache<>() { + @Override + protected ParameterizedCachedValue, JSElement> compute(JSElement jsElement, Object p) { + return CachedValuesManager.getManager(jsElement.getProject()).createParameterizedCachedValue( + new ParameterizedCachedValueProvider, JSElement>() { + @Override + public CachedValueProvider.Result> compute(JSElement context) { + class MyProcessor extends ResolveProcessor implements Processor { + Set openedNses; + + public MyProcessor() { + super(null); + putUserData(ResolveProcessor.LOOKING_FOR_USE_NAMESPACES, true); + } + + @Override + public boolean process(PsiNamedElement psiNamedElement) { + if (psiNamedElement instanceof JSElement element) { + processDeclarationsInScope(element, this, ResolveState.initial(), element, element); + } + else { + // TODO: XmlFile ? + } + return true; + } + + @Override + @RequiredReadAction + public boolean execute(@Nonnull PsiElement element, ResolveState state) { + if (!(element instanceof JSUseNamespaceDirective)) { + return true; + } + if (openedNses == null) { + openedNses = new HashSet<>(); + } + openedNses.add(((JSUseNamespaceDirective)element).getNamespaceToBeUsed()); + return true; + } + } + MyProcessor processor = new MyProcessor(); + walkOverStructure(context, processor); + return new CachedValueProvider.Result<>(processor.openedNses, PsiModificationTracker.EVER_CHANGED); + } + }, + false + ); + } + }; + + public static Set calculateOpenNses(PsiElement place) { + SimpleReference> result = new SimpleReference<>(); + walkOverStructure( + place, + psiNamedElement -> { + if (psiNamedElement instanceof JSElement element) { + result.set(ourCachedOpenedNsesCache.get(ourCachedOpenedNsesKey, element, null).getValue(element)); + } + return false; + } + ); + return result.get() != null ? result.get() : Collections.emptySet(); + } + + @RequiredReadAction + public static boolean processGlobalThings(PsiScopeProcessor processor, ResolveState state, PsiElement place, PsiElement context) { + boolean result = true; + Project project = context.getProject(); + GlobalSearchScope scope = context.getResolveScope(); + + if (shouldProcessTopLevelGlobalContext(place, processor)) { + //result = processTopPackages((ResolveProcessor) processor, state, project, scope); + } + + if (result) { + boolean acceptOnlyClasses = place instanceof JSReferenceExpression refExpr && isExprInTypeContext(refExpr); + + result = processTopLevelClasses(processor, state, project, scope, acceptOnlyClasses, true); + } + return result; + } + + @Nullable + @RequiredReadAction + public static JSParameter findParameterForUsedArgument(@Nonnull JSExpression mainOccurence, @Nonnull JSArgumentList parent) { + int paramIndex = 0; + + for (JSExpression expr : parent.getArguments()) { + if (expr == mainOccurence) { + break; + } + paramIndex++; + } + + JSExpression methodExpr = ((JSCallExpression)parent.getParent()).getMethodExpression(); + if (methodExpr instanceof JSReferenceExpression refExpr) { + ResolveResult[] results = refExpr.multiResolve(false); + + if (results.length > 0 && results[0].getElement() instanceof JSFunction function) { + JSParameterList parameterList = function.getParameterList(); + if (parameterList != null) { + JSParameter[] params = parameterList.getParameters(); + + if (paramIndex < params.length) { + return params[paramIndex]; + } + } + } + } + return null; + } + + public static abstract class JSInjectedFilesVisitor + implements PsiLanguageInjectionHost.InjectedPsiVisitor, XmlBackedJSClassImpl.InjectedFileVisitor { + @Override + @RequiredReadAction + public void visit(@Nonnull PsiFile injectedPsi, @Nonnull List places) { + if (injectedPsi instanceof JSFile jsFile) { + process(jsFile); + } + } + + protected abstract void process(JSFile file); + + @Override + public void visit(XmlTag rootTag, JSFile file) { + process(file); + } + } + + public static final String OBJECT_CLASS_NAME = "Object"; + + private JSResolveUtil() { + } + + private static final Key> ourFileElementsValueKey = Key.create("file.elements"); + + @RequiredReadAction + public static void treeWalkUp(PsiScopeProcessor processor, PsiElement elt, PsiElement lastParent, PsiElement place) { + treeWalkUp(processor, elt, lastParent, place, null, null); + } + + @RequiredReadAction + public static void treeWalkUp( + PsiScopeProcessor processor, + PsiElement elt, + PsiElement lastParent, + PsiElement place, + PsiElement terminatingParent + ) { + treeWalkUp(processor, elt, lastParent, place, terminatingParent, null); + } + + @RequiredReadAction + private static void treeWalkUp( + PsiScopeProcessor processor, + PsiElement elt, + PsiElement lastParent, + PsiElement place, + PsiElement terminatingParent, + PsiElement currentScope + ) { + if (elt == null) { + return; + } + + PsiElement parentElement = elt.getContext(); + if (elt instanceof JSFunction || elt instanceof JSObjectLiteralExpression) { + currentScope = elt; + } + + if (parentElement instanceof JSDefinitionExpression + || (parentElement instanceof JSAssignmentExpression && !(elt instanceof JSFunctionExpression))) { + if (elt == terminatingParent) { + return; + } + elt = parentElement.getParent(); + parentElement = elt.getParent(); // when walking a| = b, start from enclosing statement + if (parentElement instanceof JSExpressionStatement expr) { + elt = expr; + parentElement = expr.getParent(); + } + currentScope = elt; + } + else if (parentElement instanceof JSVariable variable && currentScope == null) { + // when walking from variable init start from enclosing statement (function expr / object literal could reference that could reference + // var in this case, better to check for any scope change) + currentScope = variable; + parentElement = variable.getParent(); + } + + boolean parentIsClass = parentElement instanceof JSClass; + int index = -1; + PsiElement[] children = getChildren(parentElement); + + if (children != null && children.length > 0) { + index = 0; + for (PsiElement el : children) { + if (el == elt) { + break; + } + ++index; + } + } + + boolean finish = false; + PsiElement cur = elt; + + do { + if (!cur.processDeclarations(processor, ResolveState.initial(), cur == elt ? lastParent : null, place)) { + if (processor instanceof ResolveProcessor) { + return; + } + } + if (terminatingParent == cur) { + finish = true; + break; + } + if (cur instanceof PsiFile || parentIsClass) { + break; + } + if (cur instanceof JSStatement && parentElement instanceof JSIfStatement) { + // Do not try to resolve variables from then branch in else branch. + break; + } + + if (index == -1) { + cur = cur.getPrevSibling(); + } + else if (index != 0) { + cur = children[--index]; + } + else { + cur = null; + } + } + while (cur != null); + + PsiElement func = parentIsClass || finish ? null : processFunctionDeclarations(processor, parentElement); + if (func != null) { + return; + } + + if (elt instanceof PsiFile) { + if (elt instanceof XmlFile xmlFile) { + XmlDocument document = xmlFile.getDocument(); + XmlTag rootTag = document != null ? document.getRootTag() : null; + String rootNs = rootTag != null ? rootTag.getNamespace() : null; + + if (JavaScriptSupportLoader.isMxmlNs(rootNs)) { + processXmlFile(processor, xmlFile, place); + } + else if (rootTag != null && xmlFile.getFileType() == XmlFileType.INSTANCE) { // TODO this is bindows specific + processXmlFile(processor, xmlFile, place); + } + } + else if (elt instanceof JSFile jsFile) { + if (parentElement != null) { + XmlTag tag = PsiTreeUtil.getParentOfType(parentElement, XmlTag.class); + PsiFile containingFile = parentElement.getContainingFile(); + + while (tag != null) { + if (XmlBackedJSClassImpl.isInlineComponentTag(tag)) { + for (JSVariable var : ourCachedPredefinedVars.get(ourCachedPredefinedVarsKey, (XmlFile)containingFile, null) + .getValue()) { + if (!processor.execute(var, ResolveState.initial())) { + return; + } + } + JSClass clazz = XmlBackedJSClassImpl.getXmlBackedClass(tag); + clazz.processDeclarations(processor, ResolveState.initial(), clazz, place); + return; + } + tag = PsiTreeUtil.getParentOfType(tag, XmlTag.class); + } + + parentElement = containingFile; + } + else { + parentElement = jsFile.getUserData(contextKey); + } + } + if (!(elt instanceof JSExpressionCodeFragment) && parentElement == null) { + return; + } + } + + if (finish) { + return; + } + treeWalkUp(processor, parentElement, elt, place, terminatingParent, currentScope); + } + + private static UserDataCache>, XmlFile, Object> ourCachedPredefinedVars = + new UserDataCache<>() { + @Override + @RequiredReadAction + protected CachedValue> compute(final XmlFile xmlFile, Object p) { + return CachedValuesManager.getManager(xmlFile.getProject()).createCachedValue( + () -> { + SmartList vars = new SmartList<>(); + String qName = XmlBackedJSClassImpl.getXmlBackedClass(xmlFile).getQualifiedName(); + vars.add(new ImplicitJSVariableImpl("outerDocument", qName, xmlFile)); + vars.add(new ImplicitJSVariableImpl("data", OBJECT_CLASS_NAME, xmlFile)); + return new CachedValueProvider.Result>(vars, xmlFile); + }, + false + ); + } + }; + + private static Key>> ourCachedPredefinedVarsKey = Key.create("ourCachedPredefinedVarsKey"); + + public static boolean processXmlFile(PsiScopeProcessor processor, XmlFile xmlFile, PsiElement place) { + JSClass clazz = XmlBackedJSClassImpl.getXmlBackedClass(xmlFile); + return clazz.processDeclarations(processor, ResolveState.initial(), clazz, place); + } + + private static PsiElement[] getChildren(PsiElement element) { + if (!(element instanceof JSFile) && !(element instanceof JSBlockStatement block && block.getParent() instanceof JSNamedElement)) { + return null; + } + CachedValue value = element.getUserData(ourFileElementsValueKey); + + if (value == null) { + value = CachedValuesManager.getManager(element.getProject()) + .createCachedValue(() -> new CachedValueProvider.Result<>(element.getChildren(), element), false); + element.putUserData(ourFileElementsValueKey, value); + } + + return value.getValue(); + } + + @Nullable + @RequiredReadAction + private static PsiElement processFunctionDeclarations(@Nonnull PsiScopeProcessor processor, @Nullable PsiElement context) { + if (!(context instanceof JSElement)) { + return null; + } + PsiElement[] children = getChildren(context); + + if (context != null) { + int index = children != null ? children.length - 1 : -1; + PsiElement cur = index >= 0 ? children[index] : context.getLastChild(); + + while (cur != null) { + if ((cur instanceof JSFunction || cur instanceof JSClass) + && !processor.execute(cur, ResolveState.initial()) + && processor instanceof ResolveProcessor resolveProcessor) { + return resolveProcessor.getResult(); + } + + if (index == -1) { + cur = cur.getPrevSibling(); + } + else if (index != 0) { + cur = children[--index]; + } + else { + cur = null; + } + } + } + return null; + } + + @RequiredReadAction + public static JSClass findDeclaringClass(JSFunction method) { + SimpleReference lastVisitedClass = new SimpleReference<>(); + iterateOverridenMethodsUp( + method, + jsClass -> { + lastVisitedClass.set(jsClass); + return true; + }, + true + ); + + Collection visited = new HashSet<>(); + visitAllImplementedInterfaces( + lastVisitedClass.get(), + visited, + jsClass -> { + // hierarchy may contain maximum one interface declaring a certain method + JSFunction interfaceMethod = jsClass.findFunctionByNameAndKind(method.getName(), method.getKind()); + if (interfaceMethod != null) { + // TODO check signature + lastVisitedClass.set(jsClass); + return false; + } + return true; + } + ); + + return lastVisitedClass.get(); + } + + /** + * @return true if processor said enough + */ + private static boolean visitAllImplementedInterfaces( + JSClass clazz, + @Nonnull Collection visited, + Processor processor + ) { + if (visited.contains(clazz)) { + return true; + } + if (clazz.isInterface()) { + visited.add(clazz); + if (!processor.process(clazz)) { + return true; + } + } + JSClass[] interfaces = clazz.isInterface() ? clazz.getSuperClasses() : clazz.getImplementedInterfaces(); + for (JSClass anInterface : interfaces) { + if (visitAllImplementedInterfaces(anInterface, visited, processor)) { + return true; + } + } + return false; + } + + /** + * @return true if processor said enough + */ + @RequiredReadAction + private static boolean iterateOverridenMethodsUp(JSFunction function, Processor processor, boolean allowDirectParent) { + PsiElement clazz = findParent(function); + if (!(clazz instanceof JSClass)) { + return false; + } + PsiElement directParent = clazz; + + while (true) { + if ((allowDirectParent || directParent != clazz) && !processor.process((JSClass)clazz)) { + return true; + } + + JSAttributeList attributeList = function.getAttributeList(); + if (attributeList == null || !attributeList.hasModifier(JSAttributeList.ModifierType.OVERRIDE)) { + return false; + } + + // TODO check signature + JSNamedElement overridenMethod = findOverriddenMethod(function, (JSClass)clazz); + if (!(overridenMethod instanceof JSFunction)) { + return false; + } + function = (JSFunction)overridenMethod; + + clazz = findParent(function); + if (!(clazz instanceof JSClass)) { + return false; + } + } + } + + @RequiredReadAction + public static boolean isReferenceTo(PsiPolyVariantReference reference, String referencedName, PsiElement _element) { + String elementName; + if (_element instanceof JSNamedElement namedElement) { + elementName = namedElement.getName(); + } + else if (_element instanceof XmlAttributeValue xmlAttributeValue) { + elementName = xmlAttributeValue.getValue(); + } + else if (_element instanceof PsiFile file) { + elementName = file.getVirtualFile().getNameWithoutExtension(); + } + else if (_element instanceof PsiDirectoryContainer directoryContainer) { + elementName = directoryContainer.getName(); + } + else { + return false; + } + + if (Comparing.equal(referencedName, elementName, true)) { + PsiElement element = _element; + + ResolveResult[] resolveResults = reference.multiResolve(true); + + for (ResolveResult r : resolveResults) { + PsiElement resolvedElement = r.getElement(); + + if (resolvedElement.isEquivalentTo(element) || + element.isEquivalentTo(resolvedElement) || + ((element instanceof JSProperty || element instanceof XmlAttributeValue) + && resolvedElement != null + && resolvedElement.getParent() == element)) { + + if (reference instanceof JSReferenceExpression referenceExpression + && ((referenceExpression.getParent() == resolvedElement && resolvedElement instanceof JSDefinitionExpression) + || resolvedElement instanceof JSFunctionExpression functionExpr + && functionExpr.getFunction().getNameIdentifier().getNextSibling() == reference)) { + return false; // do not include self to usages + } + + return true; + } + + if (resolvedElement instanceof JSFunctionExpression functionExpression) { + PsiElement nameIdentifier = functionExpression.getFunction().getNameIdentifier(); + if (nameIdentifier != null && nameIdentifier.getNextSibling() == element) { + return true; + } + } + else if (resolvedElement instanceof JSFunction fun) { + if (fun.isConstructor()) { + if ((element instanceof JSClass jsClass && resolvedElement.getParent() == jsClass) + || (element instanceof JSFile jsFile && reference.getElement().getParent() != resolvedElement + && isPublicEntityReferenceToJSFile(findParent(resolvedElement), jsFile))) { + return true; + } + } + else if (element instanceof JSFunction anotherFun) { + boolean getProperty; + + if ((getProperty = fun.isGetProperty()) || fun.isSetProperty()) { + if ((getProperty && anotherFun.isSetProperty()) || (!getProperty && anotherFun.isGetProperty())) { + PsiElement funParent = JSResolveUtil.findParent(fun); + PsiElement parent = JSResolveUtil.findParent(anotherFun); + if (funParent == parent || (parent != null && parent.isEquivalentTo(funParent))) { + return true; + } + } + } + PsiElement resolvedElementParent = findParent(resolvedElement); + PsiElement elementParent = findParent(element); + + if (elementParent instanceof JSClass anotherClass && resolvedElementParent instanceof JSClass) { + Collection visitedInterfaces = new HashSet<>(); + return iterateOverridenMethodsUp( + fun, + jsClass -> { + if (anotherClass.isInterface()) { + return !visitAllImplementedInterfaces( + jsClass, + visitedInterfaces, + jsClass1 -> !jsClass1.isEquivalentTo(anotherClass) + ); + } + else { + return !jsClass.isEquivalentTo(anotherClass); + } + }, + anotherClass.isInterface() + ); + } + } + } + else if (resolvedElement instanceof JSClass jsClass + && element instanceof JSFunction function + && function.getParent() == jsClass) { + return true; + } + + if ( + (resolvedElement instanceof JSClass + || resolvedElement instanceof JSNamespaceDeclaration + || resolvedElement instanceof JSFunction + || resolvedElement instanceof JSVariable) + && ((element instanceof XmlFile xmlFile && resolvedElement.getParent().getContainingFile() == xmlFile) + || (element instanceof JSFile jsFile && reference.getElement().getParent() != resolvedElement + && isPublicEntityReferenceToJSFile(resolvedElement, jsFile))) + ) { + return true; + } + + if (resolvedElement instanceof JSVariable variable && element instanceof JSFunction function + && fieldIsImplicitAccessorMethod(function, variable)) { + return true; + } + } + } + return false; + } + + @RequiredReadAction + private static boolean fieldIsImplicitAccessorMethod(JSFunction fun, JSVariable var) { + if (!fun.isGetProperty() && !fun.isSetProperty()) { + return false; + } + PsiElement funParent = findParent(fun); + if (!(funParent instanceof JSClass jsClass && jsClass.isInterface())) { + return false; + } + JSAttributeList attributeList = var.getAttributeList(); + if (attributeList == null || attributeList.getAccessType() != JSAttributeList.AccessType.PUBLIC) { + return false; + } + + if (findParent(var) instanceof JSClass varParentClass) { + for (JSClass c : varParentClass.getImplementedInterfaces()) { + if (c == funParent) { + return true; + } + } + } + return false; + } + + private static boolean isPublicEntityReferenceToJSFile(PsiElement resolvedElement, PsiElement element) { + PsiElement parent = resolvedElement.getParent(); + if (parent instanceof JSVarStatement varStatement) { + parent = varStatement.getParent(); + } + return parent instanceof JSPackageStatement packageStatement && packageStatement.getParent() == element; + } + + @RequiredReadAction + private static JSNamedElement findOverriddenMethod(PsiElement resolvedElement, JSClass resolvedElementClass) { + SimpleReference override = new SimpleReference<>(); + + iterateType( + (JSFunction)resolvedElement, + resolvedElementClass, + null, + (processor, scope, className) -> { + PsiElement result = processor.getResult(); + if (result instanceof JSNamedElement namedElement) { + override.set(namedElement); + return false; + } + return true; + } + ); + return override.get(); + } + + public static boolean checkClassHasParentOfAnotherOne(JSClass aClass, JSClass parent, @Nullable Set visited) { + if (visited != null && visited.contains(aClass)) { + return false; + } + + for (JSClass superClazz : aClass.getSuperClasses()) { + if (superClazz == parent) { + return true; + } + if (visited == null) { + visited = new HashSet<>(); + } + visited.add(aClass); + return checkClassHasParentOfAnotherOne(superClazz, parent, visited); + } + return false; + } + + @Nullable + @RequiredReadAction + public static JSExpression getRealRefExprQualifier(JSReferenceExpression expr) { + JSExpression qualifier = ((JSReferenceExpressionImpl)expr).getResolveQualifier(); + if (qualifier != null) { + return qualifier; + } + + if (isExprInTypeContext(expr)) { + JSImportedElementResolveResult resolved = JSImportHandlingUtil.resolveTypeNameUsingImports(expr); + if (resolved == null) { + return expr.getQualifier(); + } + + return getRealRefExprQualifierFromResult(expr, resolved); + } + + return qualifier; + } + + @RequiredReadAction + public static JSExpression getRealRefExprQualifierFromResult( + JSReferenceExpression expr, + JSImportedElementResolveResult resolved + ) { + return ((JSReferenceExpression)JSChangeUtil.createExpressionFromText(expr.getProject(), resolved.qualifiedName)).getQualifier(); + } + + @RequiredReadAction + public static String findPackageStatementQualifier(PsiElement context) { + if (context instanceof JSClass jsClass) { + String s = jsClass.getQualifiedName(); + if (s != null) { + int i = s.lastIndexOf('.'); + return i != -1 ? s.substring(0, i) : null; + } + } + + JSPackageStatement packageStatement = PsiTreeUtil.getNonStrictParentOfType(context, JSPackageStatement.class); + + if (packageStatement != null) { + return packageStatement.getQualifiedName(); + } + + return null; + } + + @RequiredReadAction + public static boolean isExprInStrictTypeContext(JSReferenceExpression expr) { + PsiElement parent = expr.getParent(); + boolean parentIsVar = parent instanceof JSVariable; + + return ((parentIsVar || parent instanceof JSFunction) + && parent.getNode().findChildByType(JSTokenTypes.COLON) != null + && (!parentIsVar || ((JSVariable)parent).getInitializer() != expr)) + || parent instanceof JSAttributeList || parent instanceof JSGenericSignature + || parent instanceof JSImportStatement || parent instanceof JSReferenceList; + } + + @RequiredReadAction + public static boolean isExprInTypeContext(JSReferenceExpression expr) { + PsiElement parent = expr.getParent(); + + return isExprInStrictTypeContext(expr) || parent instanceof JSNewExpression || parent instanceof JSUseNamespaceDirective + || (parent instanceof JSBinaryExpression binaryExpression && binaryExpression.getROperand() == expr + && (binaryExpression.getOperationSign() == JSTokenTypes.IS_KEYWORD + || binaryExpression.getOperationSign() == JSTokenTypes.AS_KEYWORD)); + } + + @Nullable + @RequiredReadAction + public static PsiElement findClassByQName(String link, @Nonnull PsiElement context) { + return findClassByQName(link, context.getProject(), context.getResolveScope()); + } + + @Nullable + @RequiredReadAction + public static PsiElement findClassByQName(String link, @Nonnull GlobalSearchScope scope, @Nonnull Project project) { + return findClassByQName(link, project, scope); + } + + @RequiredReadAction + private static PsiElement findClassByQName(String link, final Project project, GlobalSearchScope searchScope) { + synchronized (project) { + if (DumbService.isDumb(project)) { + return null; + } + + PsiElement[] result = new PsiElement[1]; + + Collection candidates = + StubIndex.getElements(JavaScriptIndexKeys.ELEMENTS_BY_QNAME, link, project, searchScope, JSQualifiedNamedElement.class); + for (JSQualifiedNamedElement clazz : candidates) { + if (link.equals(clazz.getQualifiedName())) { + if ("Object".equals(link) + && !JavaScriptIndex.ECMASCRIPT_JS2.equals(clazz.getContainingFile().getVirtualFile().getName()) // object from swf do + // not contain necessary members! + ) { + continue; + } + result[0] = clazz; + break; + } + } + + if (result[0] == null) { + String className = link.substring(link.lastIndexOf('.') + 1); + if (className.length() > 0 + && (Character.isUpperCase(className.charAt(0)) || Character.isLowerCase(className.charAt(0))) + && !isBuiltInClassName(className)) { + // TODO optimization, remove when packages will be properly handled + result[0] = findClassByQNameViaHelper(link, project, className, searchScope); + } + } + + return result[0]; + } + } + + private static boolean isBuiltInClassName(String className) { + return OBJECT_CLASS_NAME.equals(className) + || "Boolean".equals(className) + || "Function".equals(className) + || "String".equals(className); + } + + public static boolean isPredefinedFile(PsiFile file) { + return false; + } + + @Nullable + private static PsiElement findClassByQNameViaHelper( + String link, + Project project, + String className, + GlobalSearchScope scope + ) { + for (JSResolveHelper helper : Extensions.getExtensions(JSResolveHelper.EP_NAME)) { + PsiElement result = helper.findClassByQName(link, project, className, scope); + if (result != null) { + return result; + } + } + return null; + } + + @RequiredReadAction + public static String[] buildNameIdsForQualifier(JSExpression qualifier) { + String[] nameIds; + + if (qualifier == null) { + nameIds = JSSymbolUtil.buildNameIndexArray(qualifier); + } + else { + ContextResolver resolver = new ContextResolver(qualifier); + nameIds = resolver.getQualifierAsNameIndex(); + + if (nameIds == null) { + nameIds = new String[]{""}; + } + } + + return nameIds; + } + + public static JSExpression findClassIdentifier(JSExpression _qualifier) { + JSExpression qualifier = _qualifier; + if (qualifier instanceof JSReferenceExpression referenceExpression + && PROTOTYPE_FIELD_NAME.equals(referenceExpression.getReferencedName())) { + qualifier = referenceExpression.getQualifier(); + if (qualifier == null) { + qualifier = _qualifier; + } + } + + if (qualifier instanceof JSReferenceExpression referenceExpression && referenceExpression.getQualifier() == null) { + qualifier = JSSymbolUtil.findReferenceExpressionUsedForClassExtending(referenceExpression); + } + return qualifier; + } + + @RequiredReadAction + public static boolean iterateType(JSFunction node, PsiElement jsClass, String typeName, OverrideHandler handler) { + if (jsClass instanceof JSClass) { + String namespace = null; + JSAttributeList attributeList = node.getAttributeList(); + if (attributeList != null) { + namespace = attributeList.getNamespace(); + } + return processOverrides(jsClass, handler, node.getName(), namespace, node); + } + + return true; + } + + @RequiredReadAction + public static boolean processOverrides( + PsiElement jsClass, + OverrideHandler handler, + String name, + Object namespace, + PsiElement context + ) { + JSClass clazz = (JSClass)jsClass; + ResolveProcessor resolveProcessor = new ResolveProcessor(name, context) { + { + setToProcessHierarchy(true); + } + + @Override + @RequiredReadAction + public boolean execute(@Nonnull PsiElement element, ResolveState state) { + if (!(element instanceof JSFunction)) { + return true; + } + JSFunction fun = (JSFunction)element; + JSAttributeList attributeList = fun.getAttributeList(); + if (attributeList != null && attributeList.getAccessType() == JSAttributeList.AccessType.PRIVATE) { + return false; + } + + if ((namespace == null && attributeList != null && attributeList.getNamespace() != null) + || (namespace != null && (attributeList == null || !namespace.equals(attributeList.getNamespace())))) { + return true; + } + return super.execute(element, state); + } + }; + + for (JSClass superClazz : clazz.getSuperClasses()) { + if (superClazz == clazz) { + break; + } + boolean b = superClazz.processDeclarations(resolveProcessor, ResolveState.initial(), superClazz, context); + + if (!b) { + PsiElement element = resolveProcessor.getResult(); + if (element == null) { + continue; + } + PsiElement parent = findParent(element); + + if (parent instanceof JSClass parentClass + && !handler.process(resolveProcessor, superClazz, parentClass.getQualifiedName())) { + return false; + } + } + } + + return true; + } + + @RequiredReadAction + public static String getQNameToStartHierarchySearch(JSFunction node) { + PsiElement parentNode = node.getParent(); + parentNode = getClassReferenceForXmlFromContext(parentNode); + + if (parentNode instanceof JSClass) { + JSAttributeList attributeList = node.getAttributeList(); + + if (attributeList == null || + !attributeList.hasModifier(JSAttributeList.ModifierType.OVERRIDE) || + attributeList.hasModifier(JSAttributeList.ModifierType.STATIC) || + attributeList.getAccessType() == JSAttributeList.AccessType.PRIVATE) { + return null; + } + + if (parentNode instanceof JSClass jsClass) { + return jsClass.getQualifiedName(); + } + } + else if (node instanceof JSFunctionExpression functionExpr + && parentNode.getContainingFile().getLanguage() != JavaScriptSupportLoader.ECMA_SCRIPT_L4) { + ContextResolver resolver = new ContextResolver(functionExpr.getFirstChild()); + return resolver.getQualifierAsString(); + } + else if (parentNode instanceof JSFile jsFile && jsFile.getContainingFile().getLanguage() != JavaScriptSupportLoader.ECMA_SCRIPT_L4) { + return node.getName(); + } + return null; + } + + @RequiredReadAction + public static boolean isInPlaceWhereTypeCanBeDuringCompletion(PsiElement expr) { + PsiElement parent = expr.getParent(); + if (parent instanceof JSArgumentList || (parent instanceof JSVariable variable && variable.getInitializer() == expr)) { + return true; + } + return parent instanceof JSExpressionStatement + && !(expr instanceof JSReferenceExpression refExpr && refExpr.getQualifier() != null); + } + + public static boolean isPlaceWhereNsCanBe(PsiElement parent) { + PsiElement grandParent = parent.getParent(); + return grandParent instanceof JSClass || grandParent instanceof JSPackageStatement + || (grandParent instanceof JSFile jsFile && jsFile.getContext() == null); + } + + @Nullable + @RequiredReadAction + public static String getTypeFromTagNameInMxml(@Nullable PsiElement psiElement) { + JSClass clazz = getClassFromTagNameInMxml(psiElement); + return clazz != null ? clazz.getQualifiedName() : null; + } + + public static JSClass getClassFromTagNameInMxml(PsiElement psiElement) { + XmlTag tag = psiElement != null ? PsiTreeUtil.getNonStrictParentOfType(psiElement, XmlTag.class) : null; + if (tag != null && (tag.getNamespacePrefix().length() > 0 || JavaScriptSupportLoader.isFlexMxmFile(tag.getContainingFile()))) { + if (isScriptContextTag(tag)) { + tag = ((XmlFile)tag.getContainingFile()).getDocument().getRootTag(); + } + XmlElementDescriptor descriptor = tag.getDescriptor(); + + if (descriptor != null) { + PsiElement decl = descriptor.getDeclaration(); + if (decl instanceof JSClass jsClass) { + return jsClass; + } + else if (decl instanceof XmlFile xmlFile) { + return XmlBackedJSClassImpl.getXmlBackedClass(xmlFile); + } + } + } + return null; + } + + private static boolean isScriptContextTag(XmlTag tag) { + String localName = tag.getLocalName(); + return "Script".equals(localName) + || (!localName.isEmpty() && Character.isLowerCase(localName.charAt(0)) && !"method".equals(localName)); + } + + @RequiredReadAction + public static boolean processMetaAttributesForClass(PsiElement jsClass, MetaDataProcessor processor) { + return doProcessMetaAttributesForClass(unwrapProxy(jsClass), processor, null, true); + } + + @RequiredReadAction + private static boolean doProcessMetaAttributesForClass( + PsiElement jsClass, + MetaDataProcessor processor, + PsiElement lastParent, + boolean forward + ) { + if (jsClass instanceof JSClass jsClassClass) { + if (OBJECT_CLASS_NAME.equals((jsClassClass.getQualifiedName()))) { + return true; + } + PsiElement[] elements = getStubbedChildren(jsClass.getParent()); + int ind = elements.length - 1; + while (ind >= 0 && elements[ind] != jsClass) { + --ind; + } + --ind; + + + while (ind >= 0) { + PsiElement current = elements[ind]; + + if (current instanceof JSIncludeDirective includeDirective) { + if (!processIncludeDirective(processor, jsClass, includeDirective, false)) { + return false; + } + --ind; + } + else { + break; + } + } + + JSAttributeList attributeList = jsClassClass.getAttributeList(); + if (attributeList != null && !processAttributeList(processor, jsClass, attributeList, true)) { + return false; + } + } + + PsiElement[] elements = getStubbedChildren(jsClass); + SimpleReference continuePassElement = new SimpleReference<>(); + + for (int i = forward ? 0 : elements.length - 1; i < elements.length && i >= 0; i += (forward ? 1 : -1)) { + PsiElement el = elements[i]; + + if (el instanceof JSIncludeDirective includeDirective) { + if (!processIncludeDirective(processor, lastParent, includeDirective, forward)) { + return false; + } + } + else if (el instanceof JSAttributeList attributeList /*&& lastParent != null*/) { + if (!processAttributeList(processor, lastParent, attributeList, forward)) { + return false; + } + } + else { + continuePassElement.set(null); + if (!processor.handleOtherElement(el, jsClass, continuePassElement)) { + return false; + } + PsiElement nextEl = continuePassElement.get(); + + if (nextEl instanceof JSAttributeListOwner attributeListOwner) { + JSAttributeList attributeList = attributeListOwner.getAttributeList(); + + if (attributeList != null && !processAttributeList(processor, nextEl, attributeList, forward)) { + return false; + } + } + } + } + return true; + } + + @RequiredReadAction + public static boolean processAttributeList( + MetaDataProcessor processor, + PsiElement el, + JSAttributeList attributeList, + boolean forward + ) { + PsiElement[] elements = getStubbedChildren(attributeList); + for (int i = forward ? 0 : elements.length - 1; i < elements.length && i >= 0; i += (forward ? 1 : -1)) { + PsiElement cur = elements[i]; + + if (cur instanceof JSIncludeDirective includeDirective) { + if (!processIncludeDirective(processor, el, includeDirective, forward)) { + return false; + } + } + else if (cur instanceof JSAttribute attribute) { + if (!processor.process(attribute)) { + return false; + } + } + else if (cur instanceof JSNamedElement) { + break; + } + } + + return processor.handleOtherElement(attributeList, el, null); + } + + @RequiredReadAction + private static boolean processIncludeDirective( + MetaDataProcessor processor, + PsiElement lastParent, + JSIncludeDirective el, + boolean forward + ) { + PsiFile file = el.resolveFile(); + return !(file instanceof JSFile) || doProcessMetaAttributesForClass(file, processor, lastParent, forward); + } + + public static PsiElement unwrapProxy(PsiElement jsClass) { + return jsClass; + } + + @RequiredReadAction + public static JSDefinitionExpression getDefinitionExpr(JSExpressionStatement exprStatement) { + JSExpression expression = exprStatement.getExpression(); + + return expression instanceof JSAssignmentExpression assignment ? (JSDefinitionExpression)assignment.getLOperand() : null; + } + + public static boolean processDeclarationsInScope( + JSElement _scope, + PsiScopeProcessor processor, + ResolveState state, + PsiElement lastParent, + PsiElement place + ) { + JSElement scope = PsiUtilBase.getOriginalElement(_scope, _scope.getClass()); + if (scope == null) { + return true; + } + String requiredName = null; + + if (processor instanceof ResolveProcessor resolveProcessor) { + requiredName = resolveProcessor.getName(); + } + + boolean result = true; + IntObjectMap defsMap = CACHED_DEFS_CACHE.get(CACHED_STATEMENTS, scope, null).getValue(); + + if (requiredName == null) { + for (Object value : defsMap.values()) { + result = dispatchResolve(processor, state, place, result, value); + } + } + else { + Object defs = defsMap.get(requiredName.hashCode()); + if (defs != null) { + result = dispatchResolve(processor, state, place, result, defs); + } + } + + return result; + } + + private static boolean dispatchResolve( + PsiScopeProcessor processor, + ResolveState state, + PsiElement place, + boolean result, + Object o + ) { + if (o instanceof JSElement[] jsElements) { + for (JSElement s : jsElements) { + result &= s.processDeclarations(processor, state, null, place); + } + } + else { + JSElement s = (JSElement)o; + result &= s.processDeclarations(processor, state, null, place); + } + return result; + } + + @RequiredReadAction + public static PsiElement getLocalVariableRef(JSFunction function, JSReferenceExpression expr) { + ResolveProcessor processor = new ResolveProcessor(expr.getReferencedName(), true); + + while (function != null) { + boolean val = function.processDeclarations(processor, ResolveState.initial(), function.getParameterList(), function); + if (!val) { + return processor.getResult(); + } + function = PsiTreeUtil.getParentOfType(function, JSFunction.class); + if (function == null) { + break; + } + } + return null; + } + + public static class MyResolveResult implements ResolveResult { + private final PsiElement myFunction; + private final JavaScriptImportStatementBase myImportUsed; + private boolean myValidResult; + + public MyResolveResult(PsiElement function) { + this(function, true); + } + + public MyResolveResult(PsiElement function, JSImportStatement importUsed) { + this(function, importUsed, true); + } + + public MyResolveResult(PsiElement function, boolean validResult) { + this(function, null, validResult); + } + + public MyResolveResult(PsiElement function, JavaScriptImportStatementBase importUsed, boolean validResult) { + myFunction = function; + myValidResult = validResult; + myImportUsed = importUsed; + } + + @Override + public PsiElement getElement() { + return myFunction; + } + + @Override + public boolean isValidResult() { + return myValidResult; + } + + public void setValid(boolean b) { + myValidResult = b; + } + + public JavaScriptImportStatementBase getImportUsed() { + return myImportUsed; + } + } + + public static Key contextKey = Key.create("context.key"); // JSElement or XmlElement + + public static class RelevantDefsUserDataCache extends UserDataCache>, JSElement, Object> { + + @Override + protected CachedValue> compute(final JSElement jsElement, final Object o) { + return CachedValuesManager.getManager(jsElement.getProject()).createCachedValue( + () -> { + IntObjectMap relevantDefs = IntMaps.newIntObjectHashMap(); + MyJSElementVisitor elementVisitor = new MyJSElementVisitor(jsElement, relevantDefs); + elementVisitor.startVisiting(jsElement); + + return new CachedValueProvider.Result<>(relevantDefs, jsElement); + }, + false + ); + } + + private static class MyJSElementVisitor extends JSElementVisitor { + private HashMap checkedVarsToOurStatus; + private Set visitedIncludes; + private final IntObjectMap myRelevantDefs; + private final JSElement myBase; + private JSElement context; + + public MyJSElementVisitor(JSElement base, IntObjectMap relevantDefs) { + myRelevantDefs = relevantDefs; + myBase = base; + context = base; + } + + @RequiredReadAction + private void startVisiting(JSElement jsElement) { + PsiElement first = null; + + JSSourceElement[] arrayElementsToScan = null; + + if (jsElement instanceof JSFunction function) { + JSSourceElement[] body = function.getBody(); + if (body.length > 0 && body[0] instanceof JSBlockStatement block) { + first = PsiTreeUtil.findChildOfType(block, JSStatement.class); + } + } + else if (jsElement instanceof JSFile jsFile) { + if (myBase == context) { + first = jsFile.getFirstChild(); + } + else { + arrayElementsToScan = getSourceElements(jsFile); + } + } + else if (jsElement instanceof JSClass || jsElement instanceof JSPackageStatement) { + arrayElementsToScan = getSourceElements(jsElement); + } + else { + first = jsElement.getFirstChild(); + } + + if (arrayElementsToScan != null) { + for (JSSourceElement elt : arrayElementsToScan) { + elt.accept(this); + } + } + else { + for (PsiElement e = first; e != null; e = e.getNextSibling()) { + if (e instanceof JSSourceElement sourceElement) { + sourceElement.accept(this); + } + } + } + } + + @Override + @RequiredReadAction + public void visitJSDefinitionExpression(JSDefinitionExpression node) { + if (node.getExpression() instanceof JSReferenceExpression refExpr && refExpr.getQualifier() == null && false) { + String s = refExpr.getText(); + if (checkedVarsToOurStatus == null) { + checkedVarsToOurStatus = new HashMap<>(3); + } + Boolean aBoolean = checkedVarsToOurStatus.get(s); + + if (aBoolean == null) { + boolean isInjectedFile = isInjectedFile(myBase); + PsiElement element = null; + + if (myBase instanceof JSFunction || isInjectedFile) { + ResolveProcessor processor = new ResolveProcessor(s); + PsiElement baseParent = myBase.getParent(); + treeWalkUp(processor, baseParent, baseParent, baseParent); + element = processor.getResult(); + } + + aBoolean = (element == null) ? Boolean.TRUE : Boolean.FALSE; + checkedVarsToOurStatus.put(s, aBoolean); + } + + if (aBoolean == Boolean.TRUE) { + addRelevantDef(node); + } + } + } + + @Override + @RequiredReadAction + public void visitJSVariable(JSVariable node) { + addRelevantDef(node); + } + + @Override + @RequiredReadAction + public void visitJSIncludeDirective(JSIncludeDirective includeDirective) { + PsiFile _file = includeDirective.resolveFile(); + + if (!(_file instanceof JSFile) || myBase.getContainingFile() == _file) { + return; + } + JSFile file = (JSFile)_file; + if (visitedIncludes != null && visitedIncludes.contains(file)) { + return; + } + if (visitedIncludes == null) { + visitedIncludes = new HashSet<>(); + } + visitedIncludes.add(file); + + JSElement prevContext = context; + context = file; + context.putUserData(contextKey, myBase); + startVisiting(file); + context = prevContext; + } + + @Override + public void visitJSVarStatement(JSVarStatement node) { + for (JSVariable var : node.getVariables()) { + if (!var.isLocal()) { + var.accept(this); + } + } + } + + @Override + public void visitJSParameter(JSParameter node) { + } + + @Override + public void visitJSFunctionExpression(JSFunctionExpression node) { + // do not go inside other funcs + } + + @Override + public void visitJSObjectLiteralExpression(JSObjectLiteralExpression node) { + // do not go inside other funcs + } + + @Override + public void visitJSClass(JSClass aClass) { + // do not go inside other funcs + } + + @Override + public void visitJSPackageStatement(JSPackageStatement packageStatement) { + // do not go inside other funcs + } + + @Override + @RequiredReadAction + public void visitJSFunctionDeclaration(JSFunction node) { + addRelevantDef(node); + } + + @Override + public void visitJSImportStatement(JSImportStatement importStatement) { + // do not expand tree + } + + @Override + @RequiredReadAction + public void visitJSUseNamespaceDirective(JSUseNamespaceDirective useNamespaceDirective) { + String namespaceToBeUsed = useNamespaceDirective.getNamespaceToBeUsed(); + if (namespaceToBeUsed != null) { + addNamedElement(useNamespaceDirective, namespaceToBeUsed.hashCode()); + } + } + + @RequiredReadAction + private void addRelevantDef(JSNamedElement node) { + String name = node.getName(); + + if (name != null) { + int key = name.hashCode(); + addNamedElement(node, key); + } + } + + private void addNamedElement(JSElement node, int key) { + Object o = myRelevantDefs.get(key); + + if (o == null) { + myRelevantDefs.put(key, node); + } + else if (o instanceof JSElement element) { + JSElement[] newO = new JSElement[]{element, node}; + myRelevantDefs.put(key, newO); + } + else { + JSElement[] oldO = (JSElement[])o; + JSElement[] newO = new JSElement[oldO.length + 1]; + System.arraycopy(oldO, 0, newO, 0, oldO.length); + newO[oldO.length] = node; + myRelevantDefs.put(key, newO); + } + } + + @Override + public void visitElement(PsiElement element) { + element.acceptChildren(this); + } + } + } + + public static class ContextResolver { + private JSElement qualifyingExpression; + private JSNamedElement parentContainer; + private String typeName; + + @RequiredReadAction + public ContextResolver(JSExpression expr) { + if (expr instanceof JSThisExpression || expr instanceof JSSuperExpression) { + // We need to resolve ns mapping for 'this', which function was the constructor of the object + resolveContext(expr); + } + else { + qualifyingExpression = expr instanceof JSReferenceExpression referenceExpression + ? JSSymbolUtil.findReferenceExpressionUsedForClassExtending(referenceExpression) : expr; + } + } + + @RequiredReadAction + public ContextResolver(PsiElement element) { + resolveContext(element); + } + + @RequiredReadAction + private void resolveContext(PsiElement context) { + parentContainer = PsiTreeUtil.getParentOfType(context, JSFunction.class, JSClass.class); + + if (parentContainer instanceof JSFunctionExpression) { + boolean changedFunctionScope = false; + + while (parentContainer instanceof JSFunctionExpression functionExpr) { + PsiElement functionExprParent = functionExpr.getParent(); + + if (functionExprParent instanceof JSAssignmentExpression assignment) { + JSExpression jsExpression = assignment.getLOperand(); + JSElement functionExprName = + jsExpression instanceof JSDefinitionExpression definition ? definition.getExpression() : null; + qualifyingExpression = functionExprName; + + if (functionExprName instanceof JSReferenceExpression refExpr) { + JSExpression functionExprNameQualifier = refExpr.getQualifier(); + + if (functionExprNameQualifier instanceof JSThisExpression) { + parentContainer = PsiTreeUtil.getParentOfType(functionExprName, JSFunction.class); + qualifyingExpression = null; + changedFunctionScope = true; + continue; + } + else if (functionExprNameQualifier instanceof JSReferenceExpression functionRefExpr) { + String functionExpressionNameQualifierText = functionRefExpr.getReferencedName(); + + if (PROTOTYPE_FIELD_NAME.equals(functionExpressionNameQualifierText)) { + qualifyingExpression = functionRefExpr.getQualifier(); + } + else if (!changedFunctionScope) { + String referencedName; + + if (functionRefExpr.getQualifier() == null + && ((referencedName = refExpr.getReferencedName()) == null + || referencedName.isEmpty() + || !Character.isUpperCase(referencedName.charAt(0)))) { + qualifyingExpression = functionExprNameQualifier; + } + } + } + } + } + else if (functionExprParent instanceof JSProperty property) { + JSElement element = PsiTreeUtil.getParentOfType( + property, + JSVariable.class, + JSAssignmentExpression.class, + JSArgumentList.class + ); + if (element instanceof JSVariable variable) { + qualifyingExpression = variable; + } + else if (element instanceof JSAssignmentExpression assignment) { + JSExpression loperand = assignment.getLOperand(); + if (loperand != null) { + qualifyingExpression = ((JSDefinitionExpression)loperand).getExpression(); + } + } + else if (element instanceof JSArgumentList argumentList) { + qualifyingExpression = JSSymbolUtil.findQualifyingExpressionFromArgumentList(argumentList); + } + } + else if (functionExprParent instanceof JSNewExpression newExpression) { + JSElement element = PsiTreeUtil.getParentOfType( + newExpression, + JSVariable.class, + JSAssignmentExpression.class, + JSArgumentList.class + ); + + if (element instanceof JSVariable variable) { + qualifyingExpression = variable; + } + else if (element instanceof JSAssignmentExpression assignment) { + qualifyingExpression = ((JSDefinitionExpression)assignment.getLOperand()).getExpression(); + } + } + else if (functionExprParent instanceof JSReferenceExpression functionRefExpr) { + parentContainer = PsiTreeUtil.getParentOfType(functionRefExpr, JSFunction.class); + continue; + } + else if (parentContainer.getName() == null) { + parentContainer = PsiTreeUtil.getParentOfType(functionExprParent, JSFunction.class); + continue; + } + + break; + } + + if (qualifyingExpression instanceof JSReferenceExpression qualifyingReferenceExpression) { + String functionExpressionNameQualifierText = qualifyingReferenceExpression.getReferencedName(); + + if (PROTOTYPE_FIELD_NAME.equals(functionExpressionNameQualifierText)) { + qualifyingExpression = qualifyingReferenceExpression.getQualifier(); + } + else { + + qualifyingExpression = JSSymbolUtil.findReferenceExpressionUsedForClassExtending(qualifyingReferenceExpression); + } + } + } + + PsiElement parentContainerParent = parentContainer != null ? parentContainer.getParent() : null; + + if (parentContainerParent instanceof JSFile jsFile) { + parentContainerParent = getClassReferenceForXmlFromContext(jsFile); + } + + if (parentContainerParent instanceof JSClass jsClass) { + parentContainer = jsClass; + } + + if (parentContainer instanceof JSFunctionExpression + && parentContainer.getContainingFile().getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4) { + parentContainer = null; + qualifyingExpression = null; + typeName = OBJECT_CLASS_NAME; + } + } + + @Nullable + @RequiredReadAction + public String getQualifierAsString() { + String qualifierAsString = getOriginalQualifierAsString(); + return normalizeQualifier(qualifierAsString); + } + + private static String normalizeQualifier(String qualifierAsString) { + if ("Window".equals(qualifierAsString) || "Document".equals(qualifierAsString)) { + qualifierAsString = StringUtil.decapitalize(qualifierAsString); + } + return qualifierAsString; + } + + @RequiredReadAction + private String getOriginalQualifierAsString() { + if (qualifyingExpression instanceof JSLiteralExpression literal) { + return StringUtil.stripQuotesAroundValue(literal.getText()); + } + else if (qualifyingExpression instanceof JSReferenceExpression refExpr) { + return refExpr.getText(); + } + else if (qualifyingExpression instanceof JSNamedElement namedElement) { + return namedElement.getName(); + } + else if (parentContainer instanceof JSQualifiedNamedElement qualifiedNamedElement) { + return qualifiedNamedElement.getQualifiedName(); + } + + return typeName; + } + + @Nullable + public String[] getQualifierAsNameIndex() { + String qualifierAsString = getQualifierAsString(); + if (qualifierAsString != null) { + List list = new ArrayList<>(); + qualifierAsString = BaseJSSymbolProcessor.addIndexListFromQName(qualifierAsString, qualifyingExpression, list); + return ArrayUtil.toStringArray(list); + } + + return null; + } + + @RequiredReadAction + public static String getQualifierOfExprAsString(JSElement expr) { + if (expr instanceof JSNamedElement namedElement) { + return namedElement.getName(); + } + if (expr instanceof JSReferenceExpression refExpr && PROTOTYPE_FIELD_NAME.equals(refExpr.getReferencedName())) { + expr = refExpr.getQualifier(); + } + return normalizeQualifier(StringUtil.stripQuotesAroundValue(expr.getText())); + } + } + + private static boolean isInjectedFile(PsiElement element) { + return element instanceof PsiFile file && file.getVirtualFile() instanceof LightVirtualFile; + } + + @RequiredReadAction + public static void processGlobalSymbols(PsiElement target, PsiScopeProcessor processor) { + Sdk sdk = ModuleUtilCore.getSdk(target, JavaScriptModuleExtension.class); + if (sdk != null) { + VirtualFile[] files = sdk.getRootProvider().getFiles(BinariesOrderRootType.getInstance()); + + for (VirtualFile file : files) { + PsiFile psiFile = PsiManager.getInstance(target.getProject()).findFile(file); + if (psiFile instanceof JSFile jsFile + && !jsFile.processDeclarations(processor, ResolveState.initial(), null, target)) { + return; + } + } + } + } + + public interface OverrideHandler { + boolean process(ResolveProcessor processor, PsiElement scope, String className); + } + + public interface MetaDataProcessor { + @RequiredReadAction + boolean process(@Nonnull JSAttribute jsAttribute); + + boolean handleOtherElement(PsiElement el, PsiElement context, @Nullable SimpleReference continuePassElement); + } + + public static abstract class CollectMethodsToImplementProcessor extends ResolveProcessor { + private final String myName; + + public CollectMethodsToImplementProcessor(String name, PsiElement context) { + super(null, context); + myName = name; + + setToSkipClassDeclarationsOnce(true); + setToProcessHierarchy(true); + setToProcessMembers(false); + setTypeContext(true); + } + + @Override + @RequiredReadAction + public boolean execute(@Nonnull PsiElement element, ResolveState state) { + ResolveProcessor processor = new ResolveProcessor(myName, place) { + @Override + @RequiredReadAction + public boolean execute(@Nonnull PsiElement element, ResolveState state) { + if (element instanceof JSFunction function) { + if (OBJECT_CLASS_NAME.equals(((JSClass)findParent(function)).getQualifiedName()) || function.isConstructor()) { + return true; + } + } + else { + return true; + } + return super.execute(element, state); + } + + { + setToProcessHierarchy(true); + } + }; + for (JSClass implementedInterface : ((JSClass)element).getImplementedInterfaces()) { + if (!implementedInterface.isInterface()) { + continue; + } + boolean b = + implementedInterface.processDeclarations(processor, ResolveState.initial(), implementedInterface, implementedInterface); + + if (!b) { + process(processor); + break; + } + } + + if (myName == null && processor.getResults() != null) { + process(processor); + } + return false; + } + + protected abstract boolean process(ResolveProcessor processor); + } + + static JSSourceElement[] getSourceElements(PsiElement owner) { + if (owner instanceof JSStubElementImpl jsStubElement) { + return (JSSourceElement[])jsStubElement.getStubOrPsiChildren(JSElementTypes.SOURCE_ELEMENTS, JSSourceElement.EMPTY_ARRAY); + } + else if (owner instanceof JSFile jsFile) { + return jsFile.getStatements(); + } + return JSSourceElement.EMPTY_ARRAY; + } + + @RequiredReadAction + public static PsiElement[] getStubbedChildren(PsiElement owner) { + return getStubbedChildren(owner, ourStubbedFilter); + } + + @RequiredReadAction + public static PsiElement[] getStubbedChildren(PsiElement owner, TokenSet filter) { + if (owner instanceof JSStubElementImpl stubElement) { + StubElement stub = stubElement.getStub(); + if (stub != null) { + return stub.getChildrenByType(filter, PsiElement.EMPTY_ARRAY); + } + return getChildrenFromTokenSet(stubElement.getNode(), filter); + } + else if (owner instanceof JSFile file) { + StubElement stub = ((JSFileImpl)file).getStub(); + if (stub != null) { + return stub.getChildrenByType(filter, PsiElement.EMPTY_ARRAY); + } + return getChildrenFromTokenSet(file.getNode(), filter); + } + return PsiElement.EMPTY_ARRAY; + } + + private static PsiElement[] getChildrenFromTokenSet(ASTNode astNode, TokenSet filter) { + ASTNode[] astNodes = astNode.getChildren(filter); + PsiElement[] result = new PsiElement[astNodes.length]; + for (int i = 0; i < astNodes.length; ++i) { + result[i] = astNodes[i].getPsi(); + } + return result; + } + + private static final TokenSet ourStubbedFilter = TokenSet.create( + JSElementTypes.CLASS, + JSElementTypes.VAR_STATEMENT, + JSElementTypes.FUNCTION_DECLARATION, + JSElementTypes.ATTRIBUTE_LIST, + JSElementTypes.INCLUDE_DIRECTIVE, + JSElementTypes.ATTRIBUTE, + JSElementTypes.PACKAGE_STATEMENT + ); + + private static class ImplicitJSVariableImpl extends LightElement implements JSVariable { + private final PsiFile myContainingFile; + private final String myName; + private final String myType; + + public ImplicitJSVariableImpl(String name, String qName, PsiFile containingFile) { + super(containingFile.getManager(), JavaScriptSupportLoader.ECMA_SCRIPT_L4.getBaseLanguage()); + myContainingFile = containingFile; + myName = name; + myType = qName; + } + + @Override + public JSAttributeList getAttributeList() { + return null; + } + + @Override + public boolean isValid() { + return myContainingFile.isValid(); + } + + @Override + public PsiElement getParent() { + return myContainingFile; + } + + @Override + public PsiFile getContainingFile() { + return myContainingFile; + } + + @RequiredReadAction + @Override + public String getText() { + return null; + } + + @Override + public void accept(@Nonnull PsiElementVisitor visitor) { + if (visitor instanceof JSElementVisitor elementVisitor) { + elementVisitor.visitJSVariable(this); + } + else { + visitor.visitElement(this); + } + } + + @Override + public PsiElement copy() { + return new ImplicitJSVariableImpl(myName, myType, myContainingFile); + } + + @Override + public boolean canNavigate() { + return false; + } + + @Override + public boolean isPhysical() { + return false; + } + + @Nonnull + @Override + public ASTNode getNode() { + return null; + } + + @Override + public boolean hasInitializer() { + return false; + } + + @Override + @RequiredReadAction + public JSExpression getInitializer() { + return null; + } + + @Override + @RequiredReadAction + public String getInitializerText() { + return null; + } + + @Override + public void setInitializer(JSExpression expr) throws IncorrectOperationException { + } + + @Nonnull + @Override + public JavaScriptType getType() { + return JavaScriptType.UNKNOWN; + } + + @Override + public String getTypeString() { + return myType; + } + + @RequiredReadAction + @Override + public JavaScriptTypeElement getTypeElement() { + return null; + } + + @Override + public boolean isConst() { + return false; + } + + @Override + public boolean isLocal() { + return false; + } + + @Override + public boolean isDeprecated() { + return false; + } + + @Override + @RequiredReadAction + public String getQualifiedName() { + return myName; + } + + @Override + @RequiredReadAction + public String getName() { + return myName; + } + + @Override + @RequiredWriteAction + public PsiElement setName(@Nonnull String name) throws IncorrectOperationException { + throw new IncorrectOperationException(); + } + + @Override + @RequiredReadAction + public PsiElement getNameIdentifier() { + return null; + } + + @Override + public String toString() { + return "js_implicit_var:" + myName + ", type:" + myType + ", file:" + myContainingFile; + } + + @Override + public boolean isEquivalentTo(PsiElement another) { + return another == this || + (another instanceof ImplicitJSVariableImpl implicitJSVar + && myContainingFile == implicitJSVar.myContainingFile && myName.equals(implicitJSVar.myName)); + } + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/ResolveProcessor.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/ResolveProcessor.java index c4d9fc04..1c1016fc 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/ResolveProcessor.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/ResolveProcessor.java @@ -38,778 +38,632 @@ import consulo.util.dataholder.UserDataHolderBase; import consulo.xml.psi.xml.XmlAttributeValue; import consulo.xml.psi.xml.XmlTag; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; /** * @author Maxim.Mossienko */ -public class ResolveProcessor extends UserDataHolderBase implements PsiScopeProcessor -{ - private static final Key ASKING_FOR_QUALIFIED_IMPORT = Key.create("asking.for.import.of.qname"); - protected static final Key LOOKING_FOR_USE_NAMESPACES = Key.create("looking.for.use.directive"); - - private final Set visitedClasses = new HashSet(); - - private boolean myToStopOnAssignment; - protected final String myName; - private PsiElement myResult; - private PsiElement myCandidateResult; - private List myResults; - private List myImportsUsed; - private List myResolveStatus; - - private boolean toProcessHierarchy; - private boolean toSkipClassDeclarationOnce; - private boolean toProcessMembers = true; - private boolean encounteredDynamicClasses; - private boolean encounteredDynamicClassesSet; - private boolean encounteredFunctionExpression; - private boolean processStatics; - private boolean acceptPrivateMembers = true; - private boolean acceptProtectedMembers = true; - private boolean acceptProtectedMembersSet; - private boolean allowUnqualifiedStaticsFromInstance; - - private boolean myTypeContext; - private boolean encounteredWithStatement; - private boolean localResolve; - protected final PsiElement place; - private String myTypeName; - private String myClassScopeTypeName; - - private Set openedNses; - private boolean defaultNsIsNotAllowed; - private boolean anyNsAllowed; - private boolean myAcceptOnlyClasses; - private boolean myAcceptOnlyInterfaces; - - public static final Key IMPORT_KEY = Key.create("import.key"); - private boolean myClassDeclarationStarted; - private PsiElement placeTopParent; - protected boolean ecma; - public static final String AS3_NAMESPACE = "AS3"; - - private ResolveHelper myResolveHelper; - - public ResolveProcessor(final String name) - { - this(name, false); - } - - public ResolveProcessor(final String name, boolean toStopOnAssignment) - { - myName = name; - myToStopOnAssignment = toStopOnAssignment; - place = null; - } - - public ResolveProcessor(final String name, PsiElement _place) - { - myName = name; - place = _place; - final boolean b = place instanceof JSReferenceExpression && ((JSReferenceExpression) place).getQualifier() == null; - allowUnqualifiedStaticsFromInstance = b; - - if(myName != null && place instanceof JSReferenceExpression) - { - final ASTNode node = place.getNode().findChildByType(JSTokenTypes.COLON_COLON); - String explicitNs = null; - - // TODO: e.g. protected is also ns - if(node != null) - { - final JSExpression expression = ((JSReferenceExpression) place).getQualifier(); - if(expression instanceof JSReferenceExpression) - { - anyNsAllowed = ((JSReferenceExpression) expression).resolve() instanceof JSVariable; - } - - explicitNs = expression != null ? expression.getText() : null; - } - else - { - final JSExpression qualifier = ((JSReferenceExpression) place).getQualifier(); - - if(qualifier instanceof JSReferenceExpression && qualifier.getNode().findChildByType(JSTokenTypes.COLON_COLON) != null) - { - anyNsAllowed = ((JSReferenceExpression) qualifier).resolve() instanceof JSVariable; - explicitNs = ((JSReferenceExpression) qualifier).getReferencedName(); - } - } - - if(explicitNs != null && !anyNsAllowed) - { - openedNses = new HashSet(); - openedNses.add(explicitNs); - defaultNsIsNotAllowed = true; - } - } - - if(myName == null && place instanceof JSReferenceExpression) - { - PsiElement parent = place.getParent(); - - if(parent instanceof JSReferenceList) - { - if(parent.getNode().getElementType() == JSElementTypes.EXTENDS_LIST) - { - final PsiElement element = parent.getParent(); - if(element instanceof JSClass) - { - if(((JSClass) element).isInterface()) - { - myAcceptOnlyClasses = false; - myAcceptOnlyInterfaces = true; - } - else - { - myAcceptOnlyClasses = true; - myAcceptOnlyInterfaces = false; - } - } - } - else - { - myAcceptOnlyClasses = false; - myAcceptOnlyInterfaces = true; - } - } - } - - ecma = place != null && place.getContainingFile().getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4; - } - - public PsiElement getResult() - { - if(myResult == null && myCandidateResult != null) - { - assert myResults == null; - return myCandidateResult; - } - return myResult; - } - - public JavaScriptImportStatementBase getImportUsed() - { - return myImportsUsed != null ? myImportsUsed.get(0) : null; - } - - public List getResults() - { - if(myResults == null && myResult == null && myCandidateResult != null) - { - myResults = new ArrayList<>(1); - myResults.add(myCandidateResult); - } - return myResults; - } - - @Override - @RequiredReadAction - public boolean execute(@Nonnull PsiElement element, ResolveState state) - { - if((element instanceof JSVariable && !(element instanceof JSParameter)) || element instanceof JSFunction) - { - final JSAttributeList attributeList = ((JSAttributeListOwner) element).getAttributeList(); - - // TODO: we should accept such values during resolve but make them invalid - if(!acceptPrivateMembers) - { - if(attributeList != null && attributeList.getAccessType() == JSAttributeList.AccessType.PRIVATE) - { - return true; - } - } - - if(!acceptProtectedMembers) - { - if(attributeList != null && attributeList.getAccessType() == JSAttributeList.AccessType.PROTECTED) - { - return true; - } - } - - if(myClassDeclarationStarted) - { - if(processStatics) - { - if(attributeList == null || !attributeList.hasModifier(JSAttributeList.ModifierType.STATIC)) - { - return true; - } - } - else if(!allowUnqualifiedStaticsFromInstance) - { - if(attributeList != null && attributeList.hasModifier(JSAttributeList.ModifierType.STATIC)) - { - return true; - } - } - } - - String attributeNs = attributeList != null ? attributeList.getNamespace() : null; - - if(openedNses == null && attributeNs != null) - { - if(!anyNsAllowed && - place instanceof JSReferenceExpression && - !JSResolveUtil.isExprInTypeContext((JSReferenceExpression) place)) - { - openedNses = JSResolveUtil.calculateOpenNses(place); - } - } - - if(openedNses != null && !openedNses.contains(attributeNs) && (!AS3_NAMESPACE.equals(attributeNs) || !ecma) // AS3 is opened by default from - // compiler settings - ) - { - if(attributeNs != null || defaultNsIsNotAllowed) - { - return true; - } - } - } - - if(myAcceptOnlyClasses || myAcceptOnlyInterfaces) - { - if(element instanceof JSClass) - { - final boolean isInterface = ((JSClass) element).isInterface(); - - if((myAcceptOnlyClasses && isInterface) || (myAcceptOnlyInterfaces && !isInterface)) - { - return true; - } - } - } - - if(place != null) - { - if(myResolveHelper == null) - { - myResolveHelper = ResolveHelper.find(place); - } - - if(myResolveHelper.execute(this, element, state)) - { - myCandidateResult = element; - return true; - } - } - - if(place != null && element instanceof JSFunction && !(element instanceof JSFunctionExpression)) - { - final JSFunction function = (JSFunction) element; - final PsiElement placeParent = place.getParent(); - - if(placeParent instanceof JSDefinitionExpression || - (myName == null && placeParent instanceof JSExpressionStatement /* when complete of setter*/) || - (place instanceof JSFunction && ((JSFunction) place).isSetProperty())) - { - PsiElement clazz; - if(function.isGetProperty() && (myName != null || !(placeParent instanceof JSExpressionStatement) || !((clazz = function.getParent()) instanceof - JSClass) || - ((JSClass) clazz).findFunctionByNameAndKind(function.getName(), JSFunction.FunctionKind.SETTER) != null)) - { - return true; - } - } - else - { - if(function.isSetProperty()) - { - return true; - } - } - } - - if(place != null && (place.getParent() instanceof JSNewExpression || place instanceof JSSuperExpression)) - { - if(element instanceof JSClass) - { - final JSFunction byName = ((JSClass) element).findFunctionByName(((JSClass) element).getName()); - if(byName != null) - { - element = byName; - } - } - else if(element instanceof JSFunction && - element.getParent() instanceof JSClass /*TODO: in mxml?*/ && - !((JSFunction) element).isConstructor() && - !((JSFunction) element).isGetProperty()) - { - return true; - } - } - else if(element instanceof JSFunction && ((JSFunction) element).isConstructor() && !(place instanceof JSClass)) - { - return true; - } - - if(placeTopParent == null && place != null) - { - placeTopParent = JSResolveUtil.getTopReferenceExpression(place); - } - if(placeTopParent instanceof JSReferenceExpression && - JSResolveUtil.isExprInStrictTypeContext((JSReferenceExpression) placeTopParent) && - place != placeTopParent) - { - if(element instanceof JSVariable || element instanceof JSFunction) - { - return true; - } - } - - boolean checkStopOnMatch = false; - boolean doStopOnMatch = false; - - PsiElement elementToCheck = element; - if(elementToCheck instanceof JSFunctionExpression) - { - final PsiElement parent = elementToCheck.getParent(); - if(parent instanceof JSAssignmentExpression) - { - elementToCheck = ((JSAssignmentExpression) parent).getLOperand(); - } - } - - if(elementToCheck instanceof JSDefinitionExpression) - { - boolean toProcess = false; - final JSExpression expression = ((JSDefinitionExpression) elementToCheck).getExpression(); - - if(expression instanceof JSReferenceExpression && ((JSReferenceExpression) expression).getQualifier() == null) - { - toProcess = true; - } - - if(!toProcess) - { - return true; - } - checkStopOnMatch = true; - doStopOnMatch = myToStopOnAssignment; - } - - if(element instanceof PsiNamedElement) - { - if(myName == null || myName.equals(getName((PsiNamedElement) element))) - { - element = getElement(element); - if(checkStopOnMatch && !doStopOnMatch) - { - myCandidateResult = element; - } - else - { - if(myName != null) - { - JavaScriptImportStatementBase s = state != null ? state.get(IMPORT_KEY) : null; - int previousResultsSize = myResults != null ? myResults.size() : 0; - - s = checkQualifiedNameHasNecessaryImport(element, s, previousResultsSize); - - if(s != null || myImportsUsed != null) - { - if(myImportsUsed == null) - { - myImportsUsed = new SmartList<>(); - for(int i = 0; i < previousResultsSize; ++i) - { - myImportsUsed.add(null); - } - } - - myImportsUsed.add(s); - } - } - if(myResults == null) - { - myResults = new ArrayList<>(1); - } - myResults.add(element); - myResult = element; - return myName == null; - } - } - } - - return true; - } - - private JavaScriptImportStatementBase checkQualifiedNameHasNecessaryImport(PsiElement element, JavaScriptImportStatementBase s, int previousResultsSize) - { - if(s == null && (element instanceof JSClass || element instanceof JSFunction || element instanceof JSVariable || - element instanceof JSNamespaceDeclaration)) - { - - if(placeTopParent instanceof JSReferenceExpression && !(placeTopParent.getParent() instanceof JavaScriptImportStatementBase)) - { - final String qName = ((JSQualifiedNamedElement) element).getQualifiedName(); - - if(qName != null && qName.indexOf('.') != -1) - { - final ResolveProcessor processor = new ResolveProcessor(myName) - { - @Override - public boolean execute(PsiElement element, ResolveState state) - { - if(element instanceof JSQualifiedNamedElement) - { - if(!qName.equals(((JSQualifiedNamedElement) element).getQualifiedName())) - { - return true; - } - } - else - { - return true; - } - return super.execute(element, state); - } - }; - - if(!JSUnusedImportsHelper.isSomeNodeThatShouldNotHaveImportsWhenQualified((JSReferenceExpression) placeTopParent, element)) - { - processor.putUserData(ASKING_FOR_QUALIFIED_IMPORT, qName); - JSResolveUtil.treeWalkUp(processor, placeTopParent, placeTopParent, place); - boolean noImportNoResolve = processor.getResult() == null; - - if(noImportNoResolve) - { - if(myResolveStatus == null) - { - myResolveStatus = new SmartList(); - for(int i = 0; i < previousResultsSize; ++i) - { - myResolveStatus.add(Boolean.TRUE); - } - } - - myResolveStatus.add(Boolean.FALSE); - } - else - { - final ResolveResult[] resultsAsResolveResults = processor.getResultsAsResolveResults(); - if(resultsAsResolveResults.length != 0) - { - s = ((JSResolveUtil.MyResolveResult) resultsAsResolveResults[0]).getImportUsed(); - } - } - } - } - } - } - return s; - } - - private static PsiElement getElement(final PsiElement element) - { - if(element instanceof XmlTag) - { - return ((XmlTag) element).getAttribute("name").getValueElement().getChildren()[1]; - } - return element; - } - - @Nullable - public static String getName(final PsiNamedElement element) - { - if(element instanceof JSNamedElement) - { - return element.getName(); - } - return null; - } - - @Override - public T getHint(@Nonnull Key hintClass) - { - return null; - } - - protected void setTypeName(final String qualifiedName) - { - myTypeName = qualifiedName; - } - - public void configureClassScope(final JSClass jsClass) - { - if(jsClass != null) - { - myClassScopeTypeName = jsClass.getQualifiedName(); - } - else - { - acceptProtectedMembers = false; - acceptProtectedMembersSet = true; - } - } - - @Override - public void handleEvent(Event event, Object associated) - { - if(event == Event.SET_DECLARATION_HOLDER) - { - if(associated instanceof JSClass) - { - myClassDeclarationStarted = true; - final JSClass jsClass = (JSClass) associated; - final String qName = jsClass.getQualifiedName(); - - if(!encounteredDynamicClassesSet) - { - final JSAttributeList attributeList = jsClass.getAttributeList(); - if(attributeList != null && attributeList.hasModifier(JSAttributeList.ModifierType.DYNAMIC)) - { - encounteredDynamicClasses = true; - } - encounteredDynamicClassesSet = true; - } - - if(acceptPrivateMembers) - { - acceptPrivateMembers = qName != null && qName.equals(myClassScopeTypeName); - } - - if(!acceptProtectedMembersSet) - { - acceptProtectedMembersSet = true; - - if(myClassScopeTypeName != null) - { - acceptProtectedMembers = myClassScopeTypeName.equals(qName); - - if(!acceptProtectedMembers) - { - final PsiElement element = JSClassImpl.findClassFromNamespace(myClassScopeTypeName, place); - if(element instanceof JSClass) - { - final boolean b = element.processDeclarations(new ResolveProcessor(null) - { - { - setTypeContext(true); - setToProcessMembers(false); - setToProcessHierarchy(true); - acceptProtectedMembers = false; - setLocalResolve(true); - } - - @Override - public boolean execute(final PsiElement element, final ResolveState state) - { - if(!(element instanceof JSClass)) - { - return true; - } - String classQName = ((JSClass) element).getQualifiedName(); - return qName == classQName || (qName != null && !qName.equals(classQName)); - } - }, ResolveState.initial(), element, element); - - acceptProtectedMembers = !b; - } - } - } - } - - if(processStatics) - { - if(myTypeName != null && !myTypeName.equals(jsClass.getQualifiedName()) || myTypeName == null && myClassScopeTypeName != null && - !myClassScopeTypeName.equals(jsClass.getQualifiedName())) - { - processStatics = false; - } - } - } - else if(associated instanceof JSAttributeListOwner) - { - final JSAttributeList attributeList = ((JSAttributeListOwner) associated).getAttributeList(); - - if(attributeList != null && - attributeList.hasModifier(JSAttributeList.ModifierType.STATIC) && - (place == null || !(place.getParent() instanceof JSNewExpression))) - { - processStatics = true; - } - - if(associated instanceof JSFunctionExpression) - { - final PsiElement context = ((PsiElement) associated).getContainingFile().getContext(); - if(!(context instanceof XmlAttributeValue)) - { - encounteredFunctionExpression = true; // we create anonymous fun exprs for event handlers - } - } - } - } - } - - public String getName() - { - return myName; - } - - public boolean isToProcessHierarchy() - { - return toProcessHierarchy; - } - - public void setToProcessHierarchy(final boolean toProcessHierarchy) - { - this.toProcessHierarchy = toProcessHierarchy; - } - - public boolean isToSkipClassDeclarationOnce() - { - return toSkipClassDeclarationOnce; - } - - public void setToSkipClassDeclarationsOnce(final boolean toSkipClassDeclarationOnce) - { - this.toSkipClassDeclarationOnce = toSkipClassDeclarationOnce; - } - - public boolean foundAllValidResults() - { - return !encounteredFunctionExpression; // TODO: with statement too? - } - - public void setTypeContext(final boolean b) - { - myTypeContext = b; - } - - public boolean isTypeContext() - { - return myTypeContext; - } - - public ResolveResult[] getResultsAsResolveResults() - { - final List processorResults = getResults(); - if(processorResults == null) - { - return ResolveResult.EMPTY_ARRAY; - } - final ResolveResult[] results = new ResolveResult[processorResults.size()]; - - for(int i = 0; i < results.length; ++i) - { - final PsiElement element = processorResults.get(i); - results[i] = new JSResolveUtil.MyResolveResult(element, myImportsUsed != null ? myImportsUsed.get(i) : null, - myResolveStatus != null ? myResolveStatus.get(i) : true); - } - return results; - } - - public boolean processingEncounteredAbsenceOfTypes() - { - return encounteredDynamicClasses || encounteredWithStatement || encounteredFunctionExpression; - } - - public Object[] getResultsAsObjects() - { - return getResultsAsObjects(null); - } - - @RequiredReadAction - public Object[] getResultsAsObjects(String qualifiedNameToSkip) - { - final List processorResults = getResults(); - if(processorResults == null) - { - return ArrayUtil.EMPTY_OBJECT_ARRAY; - } - final int numberOfVariants = processorResults.size(); - final List objects = new ArrayList(numberOfVariants); - final Set processedCandidateNames = new HashSet(numberOfVariants); - - for(int i = 0; i < numberOfVariants; ++i) - { - final PsiElement namedElement = processorResults.get(i); - final String name = getName((PsiNamedElement) namedElement); - if(name == null) - { - continue; - } - - String qName = namedElement instanceof JSQualifiedNamedElement ? ((JSQualifiedNamedElement) namedElement).getQualifiedName() : name; - - if(processedCandidateNames.contains(qName)) - { - continue; - } - processedCandidateNames.add(qName); - - if(qualifiedNameToSkip != null && qualifiedNameToSkip.equals(qName)) - { - continue; - } - - objects.add(JSLookupUtil.createLookupItem(namedElement, name, JSLookupUtil.LookupPriority.HIGHEST)); - } - return ArrayUtil.toObjectArray(objects); - } - - public boolean isToProcessMembers() - { - return toProcessMembers; - } - - public void setToProcessMembers(final boolean toProcessMembers) - { - this.toProcessMembers = toProcessMembers; - } - - public boolean checkVisited(String className) - { - if(visitedClasses.contains(className)) - { - return true; - } - visitedClasses.add(className); - return false; - } - - public void setProcessStatics(final boolean processStatics) - { - this.processStatics = processStatics; - } - - public boolean isLocalResolve() - { - return localResolve; - } - - public void setLocalResolve(final boolean localResolve) - { - this.localResolve = localResolve; - } - - public boolean specificallyAskingToResolveQualifiedNames() - { - return getUserData(ASKING_FOR_QUALIFIED_IMPORT) != null; - } - - public String getQualifiedNameToImport() - { - return getUserData(ASKING_FOR_QUALIFIED_IMPORT); - } - - public boolean lookingForUseNamespaces() - { - return getUserData(LOOKING_FOR_USE_NAMESPACES) != null; - } - - public boolean isEncounteredDynamicClasses() - { - return encounteredDynamicClasses; - } +public class ResolveProcessor extends UserDataHolderBase implements PsiScopeProcessor { + private static final Key ASKING_FOR_QUALIFIED_IMPORT = Key.create("asking.for.import.of.qname"); + protected static final Key LOOKING_FOR_USE_NAMESPACES = Key.create("looking.for.use.directive"); + + private final Set visitedClasses = new HashSet<>(); + + private boolean myToStopOnAssignment; + protected final String myName; + private PsiElement myResult; + private PsiElement myCandidateResult; + private Set myResults; + private List myImportsUsed; + private List myResolveStatus; + + private boolean toProcessHierarchy; + private boolean toSkipClassDeclarationOnce; + private boolean toProcessMembers = true; + private boolean encounteredDynamicClasses; + private boolean encounteredDynamicClassesSet; + private boolean encounteredFunctionExpression; + private boolean processStatics; + private boolean acceptPrivateMembers = true; + private boolean acceptProtectedMembers = true; + private boolean acceptProtectedMembersSet; + private boolean allowUnqualifiedStaticsFromInstance; + + private boolean myTypeContext; + private boolean encounteredWithStatement; + private boolean localResolve; + protected final PsiElement place; + private String myTypeName; + private String myClassScopeTypeName; + + private Set openedNses; + private boolean defaultNsIsNotAllowed; + private boolean anyNsAllowed; + private boolean myAcceptOnlyClasses; + private boolean myAcceptOnlyInterfaces; + + public static final Key IMPORT_KEY = Key.create("import.key"); + private boolean myClassDeclarationStarted; + private PsiElement placeTopParent; + protected boolean ecma; + public static final String AS3_NAMESPACE = "AS3"; + + private ResolveHelper myResolveHelper; + + public ResolveProcessor(String name) { + this(name, false); + } + + public ResolveProcessor(String name, boolean toStopOnAssignment) { + myName = name; + myToStopOnAssignment = toStopOnAssignment; + place = null; + } + + public ResolveProcessor(String name, PsiElement _place) { + myName = name; + place = _place; + boolean b = place instanceof JSReferenceExpression && ((JSReferenceExpression) place).getQualifier() == null; + allowUnqualifiedStaticsFromInstance = b; + + if (myName != null && place instanceof JSReferenceExpression placeRefExpr) { + ASTNode node = place.getNode().findChildByType(JSTokenTypes.COLON_COLON); + String explicitNs = null; + + // TODO: e.g. protected is also ns + JSExpression qualifier = placeRefExpr.getQualifier(); + if (node != null) { + if (qualifier instanceof JSReferenceExpression qualifierRefExpr) { + anyNsAllowed = qualifierRefExpr.resolve() instanceof JSVariable; + } + + explicitNs = qualifier != null ? qualifier.getText() : null; + } + else if (qualifier instanceof JSReferenceExpression qualifierRefExpr + && qualifier.getNode().findChildByType(JSTokenTypes.COLON_COLON) != null) { + anyNsAllowed = qualifierRefExpr.resolve() instanceof JSVariable; + explicitNs = qualifierRefExpr.getReferencedName(); + } + + if (explicitNs != null && !anyNsAllowed) { + openedNses = new HashSet<>(); + openedNses.add(explicitNs); + defaultNsIsNotAllowed = true; + } + } + + if (myName == null && place instanceof JSReferenceExpression) { + PsiElement parent = place.getParent(); + + if (parent instanceof JSReferenceList) { + if (parent.getNode().getElementType() == JSElementTypes.EXTENDS_LIST) { + PsiElement element = parent.getParent(); + if (element instanceof JSClass jsClass) { + if (jsClass.isInterface()) { + myAcceptOnlyClasses = false; + myAcceptOnlyInterfaces = true; + } + else { + myAcceptOnlyClasses = true; + myAcceptOnlyInterfaces = false; + } + } + } + else { + myAcceptOnlyClasses = false; + myAcceptOnlyInterfaces = true; + } + } + } + + ecma = place != null && place.getContainingFile().getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4; + } + + public PsiElement getResult() { + if (myResult == null && myCandidateResult != null) { + assert myResults == null; + return myCandidateResult; + } + return myResult; + } + + public JavaScriptImportStatementBase getImportUsed() { + return myImportsUsed != null ? myImportsUsed.get(0) : null; + } + + public Collection getResults() { + if (myResults == null && myResult == null && myCandidateResult != null) { + myResults = new LinkedHashSet<>(1); + myResults.add(myCandidateResult); + } + return myResults; + } + + @Override + @RequiredReadAction + public boolean execute(@Nonnull PsiElement element, ResolveState state) { + if ((element instanceof JSVariable && !(element instanceof JSParameter)) || element instanceof JSFunction) { + JSAttributeList attributeList = ((JSAttributeListOwner) element).getAttributeList(); + + // TODO: we should accept such values during resolve but make them invalid + if (!acceptPrivateMembers + && attributeList != null && attributeList.getAccessType() == JSAttributeList.AccessType.PRIVATE) { + return true; + } + + if (!acceptProtectedMembers + && attributeList != null && attributeList.getAccessType() == JSAttributeList.AccessType.PROTECTED) { + return true; + } + + if (myClassDeclarationStarted) { + if (processStatics) { + if (attributeList == null || !attributeList.hasModifier(JSAttributeList.ModifierType.STATIC)) { + return true; + } + } + else if (!allowUnqualifiedStaticsFromInstance && attributeList != null + && attributeList.hasModifier(JSAttributeList.ModifierType.STATIC)) { + return true; + } + } + + String attributeNs = attributeList != null ? attributeList.getNamespace() : null; + + if (openedNses == null && attributeNs != null && !anyNsAllowed + && place instanceof JSReferenceExpression placeRefExpr && !JSResolveUtil.isExprInTypeContext(placeRefExpr)) { + openedNses = JSResolveUtil.calculateOpenNses(place); + } + + if (openedNses != null + && !openedNses.contains(attributeNs) + && (!AS3_NAMESPACE.equals(attributeNs) || !ecma) // AS3 is opened by default from compiler settings + ) { + if (attributeNs != null || defaultNsIsNotAllowed) { + return true; + } + } + } + + if (myAcceptOnlyClasses || myAcceptOnlyInterfaces) { + if (element instanceof JSClass jsClass) { + boolean isInterface = jsClass.isInterface(); + + if ((myAcceptOnlyClasses && isInterface) || (myAcceptOnlyInterfaces && !isInterface)) { + return true; + } + } + } + + if (place != null) { + if (myResolveHelper == null) { + myResolveHelper = ResolveHelper.find(place); + } + + if (myResolveHelper.execute(this, element, state)) { + myCandidateResult = element; + return true; + } + } + + if (place != null && element instanceof JSFunction function && !(element instanceof JSFunctionExpression)) { + PsiElement placeParent = place.getParent(); + + if (placeParent instanceof JSDefinitionExpression + || (myName == null && placeParent instanceof JSExpressionStatement /* when complete of setter*/) + || (place instanceof JSFunction placeFunction && placeFunction.isSetProperty())) { + if (function.isGetProperty() && (myName != null + || !(placeParent instanceof JSExpressionStatement) + || !(function.getParent() instanceof JSClass jsClass + && jsClass.findFunctionByNameAndKind(function.getName(), JSFunction.FunctionKind.SETTER) == null))) { + return true; + } + } + else if (function.isSetProperty()) { + return true; + } + } + + if (place != null && (place.getParent() instanceof JSNewExpression || place instanceof JSSuperExpression)) { + if (element instanceof JSClass jsClass) { + JSFunction byName = jsClass.findFunctionByName(jsClass.getName()); + if (byName != null) { + element = byName; + } + } + else if (element instanceof JSFunction function + && element.getParent() instanceof JSClass /*TODO: in mxml?*/ + && !function.isConstructor() && !function.isGetProperty()) { + return true; + } + } + else if (element instanceof JSFunction function && function.isConstructor() && !(place instanceof JSClass)) { + return true; + } + + if (placeTopParent == null && place != null) { + placeTopParent = JSResolveUtil.getTopReferenceExpression(place); + } + if (placeTopParent instanceof JSReferenceExpression placeTopParentRefExpr + && JSResolveUtil.isExprInStrictTypeContext(placeTopParentRefExpr) + && place != placeTopParent + && (element instanceof JSVariable || element instanceof JSFunction)) { + return true; + } + + boolean checkStopOnMatch = false; + boolean doStopOnMatch = false; + + PsiElement elementToCheck = element; + if (elementToCheck instanceof JSFunctionExpression + && elementToCheck.getParent() instanceof JSAssignmentExpression assignment) { + elementToCheck = assignment.getLOperand(); + } + + if (elementToCheck instanceof JSDefinitionExpression definition) { + boolean toProcess = false; + + if (definition.getExpression() instanceof JSReferenceExpression refExpr && refExpr.getQualifier() == null) { + toProcess = true; + } + + if (!toProcess) { + return true; + } + checkStopOnMatch = true; + doStopOnMatch = myToStopOnAssignment; + } + + if (element instanceof PsiNamedElement namedElement && (myName == null || myName.equals(getName(namedElement)))) { + element = getElement(element); + if (checkStopOnMatch && !doStopOnMatch) { + myCandidateResult = element; + } + else { + if (myName != null) { + JavaScriptImportStatementBase s = state != null ? state.get(IMPORT_KEY) : null; + int previousResultsSize = myResults != null ? myResults.size() : 0; + + s = checkQualifiedNameHasNecessaryImport(element, s, previousResultsSize); + + if (s != null || myImportsUsed != null) { + if (myImportsUsed == null) { + myImportsUsed = new SmartList<>(); + for (int i = 0; i < previousResultsSize; ++i) { + myImportsUsed.add(null); + } + } + + myImportsUsed.add(s); + } + } + if (myResults == null) { + myResults = new LinkedHashSet<>(); + } + myResults.add(element); + myResult = element; + return myName == null; + } + } + + return true; + } + + private JavaScriptImportStatementBase checkQualifiedNameHasNecessaryImport( + PsiElement element, + JavaScriptImportStatementBase s, + int previousResultsSize + ) { + if (s == null && (element instanceof JSClass || element instanceof JSFunction || element instanceof JSVariable + || element instanceof JSNamespaceDeclaration)) { + + if (placeTopParent instanceof JSReferenceExpression placeTopParentRefExpr + && !(placeTopParent.getParent() instanceof JavaScriptImportStatementBase)) { + final String qName = ((JSQualifiedNamedElement) element).getQualifiedName(); + + if (qName != null && qName.indexOf('.') != -1) { + ResolveProcessor processor = new ResolveProcessor(myName) { + @Override + @RequiredReadAction + public boolean execute(@Nonnull PsiElement element, ResolveState state) { + if (element instanceof JSQualifiedNamedElement qualifiedNamedElement) { + if (!qName.equals(qualifiedNamedElement.getQualifiedName())) { + return true; + } + } + else { + return true; + } + return super.execute(element, state); + } + }; + + if (!JSUnusedImportsHelper.isSomeNodeThatShouldNotHaveImportsWhenQualified(placeTopParentRefExpr, element)) { + processor.putUserData(ASKING_FOR_QUALIFIED_IMPORT, qName); + JSResolveUtil.treeWalkUp(processor, placeTopParent, placeTopParent, place); + boolean noImportNoResolve = processor.getResult() == null; + + if (noImportNoResolve) { + if (myResolveStatus == null) { + myResolveStatus = new SmartList<>(); + for (int i = 0; i < previousResultsSize; ++i) { + myResolveStatus.add(Boolean.TRUE); + } + } + + myResolveStatus.add(Boolean.FALSE); + } + else { + ResolveResult[] resultsAsResolveResults = processor.getResultsAsResolveResults(); + if (resultsAsResolveResults.length != 0) { + s = ((JSResolveUtil.MyResolveResult) resultsAsResolveResults[0]).getImportUsed(); + } + } + } + } + } + } + return s; + } + + @RequiredReadAction + private static PsiElement getElement(PsiElement element) { + return element instanceof XmlTag xmlTag + ? xmlTag.getAttribute("name").getValueElement().getChildren()[1] + : element; + } + + @Nullable + @RequiredReadAction + public static String getName(PsiElement element) { + return element instanceof JSNamedElement namedElement ? namedElement.getName() : null; + } + + @Override + public T getHint(@Nonnull Key hintClass) { + return null; + } + + protected void setTypeName(String qualifiedName) { + myTypeName = qualifiedName; + } + + public void configureClassScope(JSClass jsClass) { + if (jsClass != null) { + myClassScopeTypeName = jsClass.getQualifiedName(); + } + else { + acceptProtectedMembers = false; + acceptProtectedMembersSet = true; + } + } + + @Override + @RequiredReadAction + public void handleEvent(Event event, Object associated) { + if (event == Event.SET_DECLARATION_HOLDER) { + if (associated instanceof JSClass) { + myClassDeclarationStarted = true; + JSClass jsClass = (JSClass) associated; + final String qName = jsClass.getQualifiedName(); + + if (!encounteredDynamicClassesSet) { + JSAttributeList attributeList = jsClass.getAttributeList(); + if (attributeList != null && attributeList.hasModifier(JSAttributeList.ModifierType.DYNAMIC)) { + encounteredDynamicClasses = true; + } + encounteredDynamicClassesSet = true; + } + + if (acceptPrivateMembers) { + acceptPrivateMembers = qName != null && qName.equals(myClassScopeTypeName); + } + + if (!acceptProtectedMembersSet) { + acceptProtectedMembersSet = true; + + if (myClassScopeTypeName != null) { + acceptProtectedMembers = myClassScopeTypeName.equals(qName); + + if (!acceptProtectedMembers) { + PsiElement element = JSClassImpl.findClassFromNamespace(myClassScopeTypeName, place); + if (element instanceof JSClass) { + boolean b = element.processDeclarations( + new ResolveProcessor(null) { + { + setTypeContext(true); + setToProcessMembers(false); + setToProcessHierarchy(true); + acceptProtectedMembers = false; + setLocalResolve(true); + } + + @Override + @RequiredReadAction + public boolean execute(@Nonnull PsiElement element, ResolveState state) { + if (!(element instanceof JSClass jsClass)) { + return true; + } + String classQName = jsClass.getQualifiedName(); + return Objects.equals(qName, classQName); + } + }, + ResolveState.initial(), + element, + element + ); + + acceptProtectedMembers = !b; + } + } + } + } + + if (processStatics) { + if (myTypeName != null && !myTypeName.equals(jsClass.getQualifiedName()) + || myTypeName == null && myClassScopeTypeName != null && + !myClassScopeTypeName.equals(jsClass.getQualifiedName())) { + processStatics = false; + } + } + } + else if (associated instanceof JSAttributeListOwner attributeListOwner) { + JSAttributeList attributeList = attributeListOwner.getAttributeList(); + + if (attributeList != null && attributeList.hasModifier(JSAttributeList.ModifierType.STATIC) + && (place == null || !(place.getParent() instanceof JSNewExpression))) { + processStatics = true; + } + + if (associated instanceof JSFunctionExpression functionExpression) { + PsiElement context = functionExpression.getContainingFile().getContext(); + if (!(context instanceof XmlAttributeValue)) { + encounteredFunctionExpression = true; // we create anonymous fun exprs for event handlers + } + } + } + } + } + + public String getName() { + return myName; + } + + public boolean isToProcessHierarchy() { + return toProcessHierarchy; + } + + public void setToProcessHierarchy(boolean toProcessHierarchy) { + this.toProcessHierarchy = toProcessHierarchy; + } + + public boolean isToSkipClassDeclarationOnce() { + return toSkipClassDeclarationOnce; + } + + public void setToSkipClassDeclarationsOnce(boolean toSkipClassDeclarationOnce) { + this.toSkipClassDeclarationOnce = toSkipClassDeclarationOnce; + } + + public boolean foundAllValidResults() { + return !encounteredFunctionExpression; // TODO: with statement too? + } + + public void setTypeContext(boolean b) { + myTypeContext = b; + } + + public boolean isTypeContext() { + return myTypeContext; + } + + public ResolveResult[] getResultsAsResolveResults() { + Collection processorResults = getResults(); + if (processorResults == null) { + return ResolveResult.EMPTY_ARRAY; + } + ResolveResult[] results = new ResolveResult[processorResults.size()]; + + int i = 0; + for (PsiElement element : processorResults) { + int pos = i++; + + results[pos] = new JSResolveUtil.MyResolveResult( + element, + myImportsUsed != null ? myImportsUsed.get(pos) : null, + myResolveStatus != null ? myResolveStatus.get(pos) : true + ); + } + + return results; + } + + public boolean processingEncounteredAbsenceOfTypes() { + return encounteredDynamicClasses || encounteredWithStatement || encounteredFunctionExpression; + } + + public Object[] getResultsAsObjects() { + return getResultsAsObjects(null); + } + + @RequiredReadAction + public Object[] getResultsAsObjects(String qualifiedNameToSkip) { + Collection processorResults = getResults(); + if (processorResults == null) { + return ArrayUtil.EMPTY_OBJECT_ARRAY; + } + int numberOfVariants = processorResults.size(); + List objects = new ArrayList<>(numberOfVariants); + Set processedCandidateNames = new HashSet<>(numberOfVariants); + + for (PsiElement namedElement : processorResults) { + String name = getName(namedElement); + if (name == null) { + continue; + } + + String qName = namedElement instanceof JSQualifiedNamedElement qualifiedNamedElement + ? qualifiedNamedElement.getQualifiedName() + : name; + + if (processedCandidateNames.contains(qName)) { + continue; + } + processedCandidateNames.add(qName); + + if (qualifiedNameToSkip != null && qualifiedNameToSkip.equals(qName)) { + continue; + } + + objects.add(JSLookupUtil.createLookupItem(namedElement, name, JSLookupUtil.LookupPriority.HIGHEST)); + } + return ArrayUtil.toObjectArray(objects); + } + + public boolean isToProcessMembers() { + return toProcessMembers; + } + + public void setToProcessMembers(boolean toProcessMembers) { + this.toProcessMembers = toProcessMembers; + } + + public boolean checkVisited(String className) { + if (visitedClasses.contains(className)) { + return true; + } + visitedClasses.add(className); + return false; + } + + public void setProcessStatics(boolean processStatics) { + this.processStatics = processStatics; + } + + public boolean isLocalResolve() { + return localResolve; + } + + public void setLocalResolve(boolean localResolve) { + this.localResolve = localResolve; + } + + public boolean specificallyAskingToResolveQualifiedNames() { + return getUserData(ASKING_FOR_QUALIFIED_IMPORT) != null; + } + + public String getQualifiedNameToImport() { + return getUserData(ASKING_FOR_QUALIFIED_IMPORT); + } + + public boolean lookingForUseNamespaces() { + return getUserData(LOOKING_FOR_USE_NAMESPACES) != null; + } + + public boolean isEncounteredDynamicClasses() { + return encounteredDynamicClasses; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/VariantsProcessor.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/VariantsProcessor.java index 6c8a0a12..5a21d1ca 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/VariantsProcessor.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/VariantsProcessor.java @@ -29,474 +29,398 @@ import consulo.language.psi.resolve.ResolveState; import consulo.language.psi.util.PsiTreeUtil; import consulo.util.collection.ArrayUtil; -import org.jetbrains.annotations.NonNls; +import jakarta.annotation.Nonnull; import java.util.*; /** * @author Maxim.Mossienko */ -public class VariantsProcessor extends BaseJSSymbolProcessor -{ - private Map myNames2CandidatesMap = new HashMap(); - private int myThisFileNameListCount; - private List myNamesList = new ArrayList(); - - private Map myPartialMatchNamesMap = new HashMap(); - private Map myPartialMatchNamesMapFromSameFile = new HashMap(); - //private Set myTargetFiles; - private final boolean hasSomeSmartnessAvailable; - private boolean myProcessOnlyTypes; - - private boolean myAddOnlyCompleteMatchesSet; - - @NonNls - private static final String OBJECT_CLASS_NAME = "Object"; - - public VariantsProcessor(String[] nameIds, PsiFile targetFile, boolean skipDclsInTargetFile, PsiElement context) - { - super(targetFile.getOriginalFile(), skipDclsInTargetFile, context, nameIds); - nameIds = myContextNameIds; - - boolean hasSomeInfoAvailable = nameIds != null && nameIds.length > 0; - final List possibleNameComponents = new ArrayList(1); - myCurrentFile = targetFile.getOriginalFile(); - //myTargetFiles = new HashSet(); - - boolean allTypesResolved = false; - boolean doAddContextIds = true; - - final JSClass jsClass = PsiTreeUtil.getParentOfType(context, JSClass.class); - - if(context instanceof JSReferenceExpression) - { - final JSReferenceExpression refExpr = (JSReferenceExpression) context; - JSExpression qualifier = refExpr.getQualifier(); - - if(qualifier != null) - { - if(qualifier instanceof JSThisExpression || qualifier instanceof JSSuperExpression) - { - if(jsClass != null) - { - myAddOnlyCompleteMatches = myAddOnlyCompleteMatchesSet = true; - updateCanUseOnlyCompleteMatches(jsClass); - doAddContextIds = false; - } - else if(JSResolveUtil.getTypeFromTagNameInMxml(myCurrentFile.getContext()) != null) - { - myAddOnlyCompleteMatches = myAddOnlyCompleteMatchesSet = true; - } - } - - final CompletionTypeProcessor processor = new CompletionTypeProcessor(possibleNameComponents); - doEvalForExpr(getOriginalQualifier(qualifier), myTargetFile, processor); - allTypesResolved = processor.getAllTypesResolved(); - } - else - { - final PsiElement parent = refExpr.getParent(); - - if(parent instanceof JavaScriptImportStatementBase) - { - myProcessOnlyTypes = true; - } - else if(JSResolveUtil.isExprInTypeContext(refExpr) || (ecmal4 && JSResolveUtil.isInPlaceWhereTypeCanBeDuringCompletion(refExpr))) - { - myAddOnlyCompleteMatches = myAddOnlyCompleteMatchesSet = true; - myProcessOnlyTypes = true; - allTypesResolved = true; - addPackageScope(possibleNameComponents, jsClass, refExpr); - } - else if(jsClass != null) - { - myAddOnlyCompleteMatches = myAddOnlyCompleteMatchesSet = true; - updateCanUseOnlyCompleteMatches(jsClass); - } - } - } - - if(hasSomeInfoAvailable && (!allTypesResolved || (!possibleNameComponents.isEmpty() && - possibleNameComponents.get(0).length == 1 && - "Function".equals(possibleNameComponents.get(0)[0])))) - { - if(doAddContextIds) - { - possibleNameComponents.add(nameIds); - } - - doIterateTypeHierarchy(nameIds, new HierarchyProcessor() - { - @Override - public boolean processClass(final JSClass clazz) - { - updateCanUseOnlyCompleteMatchesFromString(clazz.getQualifiedName(), clazz, clazz); - buildIndexListFromQNameAndCorrectQName(clazz.getQualifiedName(), clazz, possibleNameComponents); - return true; - } - }); - } - - String[][] nameIdsArray = new String[possibleNameComponents.size()][]; - possibleNameComponents.toArray(nameIdsArray); - - hasSomeSmartnessAvailable = nameIdsArray != null && nameIdsArray.length > 0; - } - - private void updateCanUseOnlyCompleteMatchesFromString(final String qName, Object source, PsiElement clazz) - { - final boolean wasSet = myAddOnlyCompleteMatchesSet; - - if(myAddOnlyCompleteMatches || !wasSet) - { - myAddOnlyCompleteMatchesSet = true; - if(qName.equals("*") || - (qName.equals(OBJECT_CLASS_NAME) && (myIteratedTypeName == null || - qName.equals(myIteratedTypeName) || - // skip adding complete matches when context name is qualifier - (myContextNameIds != null && - myContextNameIds.length > 0 && - myIteratedTypeName.equals(myContextNameIds[myContextNameIds.length - 1]) && - myContext instanceof JSReferenceExpression && - ((JSReferenceExpression) myContext).getQualifier() instanceof JSReferenceExpression))) /* something explicitly marked as Object*/ || - (qName.equals(FUNCTION_TYPE_NAME) && isObjectSourceThatDoesNotGiveExactKnowledgeAboutFunctionType(source))) - { - myAddOnlyCompleteMatches = false; - } - else - { - if(clazz == null) - { - clazz = JSResolveUtil.findClassByQName(qName, myContext); - } - - if(clazz instanceof JSClass) - { - if(!wasSet) - { - myAddOnlyCompleteMatches = true; - } - - final JSAttributeList attributeList = ((JSClass) clazz).getAttributeList(); - if(attributeList != null && attributeList.hasModifier(JSAttributeList.ModifierType.DYNAMIC) && !OBJECT_CLASS_NAME.equals(qName)) - { - myAddOnlyCompleteMatches = false; - } - } - } - } - } - - private static boolean isObjectSourceThatDoesNotGiveExactKnowledgeAboutFunctionType(final Object source) - { - return source instanceof JSFunctionExpression; - } - - private void updateCanUseOnlyCompleteMatches(final JSClass jsClass) - { - final JSAttributeList attributeList = jsClass != null ? jsClass.getAttributeList() : null; - if(attributeList != null && attributeList.hasModifier(JSAttributeList.ModifierType.DYNAMIC)) - { - myAddOnlyCompleteMatches = false; - } - } - - public void addLocalResults(final List results) - { - if(results == null) - { - return; - } - - final Set processedCandidateNames = new HashSet(results.size()); - - for(PsiElement e : results) - { - if(e instanceof PsiNamedElement) - { - final PsiNamedElement namedElement = (PsiNamedElement) e; - - String name = ResolveProcessor.getName(namedElement); - String qName = namedElement instanceof JSQualifiedNamedElement ? ((JSQualifiedNamedElement) namedElement).getQualifiedName() : name; - - if(processedCandidateNames.contains(qName)) - { - continue; - } - processedCandidateNames.add(qName); - - addCompleteMatch(namedElement, name, false); - } - } - } - - class CompletionTypeProcessor implements TypeProcessor - { - final List possibleNameIds; - private PsiElement myUnknownElement; - - CompletionTypeProcessor(List _possibleNameIds) - { - possibleNameIds = _possibleNameIds; - } - - @Override - public void process(String type, final EvaluateContext context, final PsiElement source) - { - if(context.visitedTypes.contains(type)) - { - return; - } - context.visitedTypes.add(type); - if(JSTypeEvaluateManager.isArrayType(type)) - { - type = ARRAY_TYPE_NAME; - } - updateCanUseOnlyCompleteMatchesFromString(type, source, null); - type = buildIndexListFromQNameAndCorrectQName(type, source, possibleNameIds); - addSupers(type, possibleNameIds, context); - } - - @Override - public Set getFeatures() - { - return myFeatures; - } - - @Override - public boolean ecma() - { - return ecmal4; - } - - @Override - public void setUnknownElement(PsiElement element) - { - myUnknownElement = element; - } - - public boolean getAllTypesResolved() - { - return myUnknownElement == null; - } - } - - private void addSupers(final String type, final List possibleNameIds, final EvaluateContext context) - { - final String iteratedType = myIteratedTypeName; - myIteratedTypeName = type; - doIterateHierarchy(type, new HierarchyProcessor() - { - @Override - public boolean processClass(final JSClass clazz) - { - String qname = clazz.getQualifiedName(); - if(!context.visitedTypes.contains(qname)) - { - context.visitedTypes.add(qname); - updateCanUseOnlyCompleteMatchesFromString(qname, clazz, clazz); - buildIndexListFromQNameAndCorrectQName(clazz.getQualifiedName(), clazz, possibleNameIds); - } - return true; - } - }); - - myIteratedTypeName = iteratedType; - } - - public Object[] getResult() - { - List results = new ArrayList(); - for(Object o : myNamesList) - { - results.add(o); - } - - for(Object o : myPartialMatchNamesMapFromSameFile.values()) - { - results.add(o); - } - - for(Object o : myPartialMatchNamesMap.values()) - { - results.add(o); - } - - return ArrayUtil.toObjectArray(results); - } - - @Override - public boolean execute(PsiElement element, ResolveState state) - { - if(element instanceof JSNamedElement) - { - final JSNamedElement namedElement = (JSNamedElement) element; - - addCompleteMatch(namedElement, namedElement.getName()); - } - - return true; - } - - private void doAdd(final String nameId, final PsiElement element) - { - final String name = nameId != null ? nameId : null; - - boolean seemsToBePrivateSymbol = name != null && name.length() > 0 && name.charAt(0) == '_' && name.length() > 1 && name.charAt(1) != '_'; - boolean privateSymbol = seemsToBePrivateSymbol; - - if(seemsToBePrivateSymbol) - { - if(!(myTargetFile instanceof JSFile)) - { - // no interest in html, jsp for private symbols - return; - } - - if(myContextNameIds == null || myContextNameIds.length == 0) - { - privateSymbol = false; - } - } - - - MatchType matchType = MatchType.COMPLETE; - - if(matchType == MatchType.COMPLETE && !ecmal4 && myProcessOnlyTypes) - { - if(((name != null && name.length() > 0 && Character.isLowerCase(name.charAt(0))) || seemsToBePrivateSymbol)) - { - matchType = MatchType.PARTIAL; - } - } - - if(matchType == MatchType.PARTIAL || (privateSymbol && matchType == MatchType.COMPLETE)) - { - addPartialMatch(element, nameId); - - } - else if(matchType == MatchType.COMPLETE) - { - addCompleteMatch(element, nameId); - } - } - - - @RequiredReadAction - private LookupElement addLookupValue(PsiElement element, final String name, JSLookupUtil.LookupPriority priority) - { - return JSLookupUtil.createLookupItem(element, name, priority); - } - - @Override - protected String[] calculateContextIds(final JSReferenceExpression jsReferenceExpression) - { - return JSResolveUtil.buildNameIdsForQualifier(JSResolveUtil.getRealRefExprQualifier(jsReferenceExpression)); - } - - @Override - protected boolean isFromRelevantFileOrDirectory() - { - return super.isFromRelevantFileOrDirectory(); // || myTargetFiles.contains(myCurrentFile); - } - - private void addCompleteMatch(final PsiElement _element, String nameId) - { - addCompleteMatch(_element, nameId, true); - } - - private void addCompleteMatch(final PsiElement _element, String nameId, boolean doFilterting) - { - if(!doAdd(_element, nameId, doFilterting)) - { - boolean removedFromPartialNames = false; - final Object el = myNames2CandidatesMap.get(nameId); - - if(el != null) - { - removedFromPartialNames = myPartialMatchNamesMapFromSameFile.remove(nameId) != null || myPartialMatchNamesMap.remove(nameId) != null; - } - if(!removedFromPartialNames) - { - return; - } - } - - PsiElement element = _element; - - if(isFromRelevantFileOrDirectory() && !myAddOnlyCompleteMatches) - { - final Object o = addLookupValue(element, nameId, JSLookupUtil.LookupPriority.HIGHEST); - if(o != null) - { - myNamesList.add(myThisFileNameListCount++, o); - } - else - { - myNames2CandidatesMap.remove(nameId); - } - } - else - { - final Object o = addLookupValue(element, nameId, JSLookupUtil.LookupPriority.HIGH); - if(o != null) - { - myNamesList.add(o); - } - else - { - myNames2CandidatesMap.remove(nameId); - } - } - } - - private boolean doAdd(Object element, String nameId, boolean doFilterting) - { - if(nameId == null || (doFilterting && myNames2CandidatesMap.get(nameId) != null)) - { - return false; - } - myNames2CandidatesMap.put(nameId, element); - return true; - } - - private void addPartialMatch(final PsiElement _element, String nameId) - { - if(myAddOnlyCompleteMatches) - { - return; - } - if(!doAdd(_element, nameId, true)) - { - return; - } - - PsiElement element = _element; - - final Map targetNamesMap; - final JSLookupUtil.LookupPriority priority; - - if(isFromRelevantFileOrDirectory()) - { - priority = hasSomeSmartnessAvailable ? JSLookupUtil.LookupPriority.HIGHER : JSLookupUtil.LookupPriority.HIGHEST; - targetNamesMap = myPartialMatchNamesMapFromSameFile; - } - else - { - priority = hasSomeSmartnessAvailable ? JSLookupUtil.LookupPriority.NORMAL : JSLookupUtil.LookupPriority.HIGH; - - targetNamesMap = myPartialMatchNamesMap; - } - - final Object o = addLookupValue(element, nameId, priority); - - if(o != null) - { - targetNamesMap.put(nameId, o); - } - else - { - myNames2CandidatesMap.remove(nameId); - } - } +public class VariantsProcessor extends BaseJSSymbolProcessor { + private Map myNames2CandidatesMap = new HashMap<>(); + private int myThisFileNameListCount; + private List myNamesList = new ArrayList<>(); + + private Map myPartialMatchNamesMap = new HashMap<>(); + private Map myPartialMatchNamesMapFromSameFile = new HashMap<>(); + //private Set myTargetFiles; + private final boolean hasSomeSmartnessAvailable; + private boolean myProcessOnlyTypes; + + private boolean myAddOnlyCompleteMatchesSet; + + private static final String OBJECT_CLASS_NAME = "Object"; + + @RequiredReadAction + public VariantsProcessor(String[] nameIds, PsiFile targetFile, boolean skipDclsInTargetFile, PsiElement context) { + super(targetFile.getOriginalFile(), skipDclsInTargetFile, context, nameIds); + nameIds = myContextNameIds; + + boolean hasSomeInfoAvailable = nameIds != null && nameIds.length > 0; + List possibleNameComponents = new ArrayList<>(1); + myCurrentFile = targetFile.getOriginalFile(); + //myTargetFiles = new HashSet(); + + boolean allTypesResolved = false; + boolean doAddContextIds = true; + + JSClass jsClass = PsiTreeUtil.getParentOfType(context, JSClass.class); + + if (context instanceof JSReferenceExpression) { + JSReferenceExpression refExpr = (JSReferenceExpression)context; + JSExpression qualifier = refExpr.getQualifier(); + + if (qualifier != null) { + if (qualifier instanceof JSThisExpression || qualifier instanceof JSSuperExpression) { + if (jsClass != null) { + myAddOnlyCompleteMatches = myAddOnlyCompleteMatchesSet = true; + updateCanUseOnlyCompleteMatches(jsClass); + doAddContextIds = false; + } + else if (JSResolveUtil.getTypeFromTagNameInMxml(myCurrentFile.getContext()) != null) { + myAddOnlyCompleteMatches = myAddOnlyCompleteMatchesSet = true; + } + } + + CompletionTypeProcessor processor = new CompletionTypeProcessor(possibleNameComponents); + doEvalForExpr(getOriginalQualifier(qualifier), myTargetFile, processor); + allTypesResolved = processor.getAllTypesResolved(); + } + else { + PsiElement parent = refExpr.getParent(); + + if (parent instanceof JavaScriptImportStatementBase) { + myProcessOnlyTypes = true; + } + else if (JSResolveUtil.isExprInTypeContext(refExpr) + || (ecmal4 && JSResolveUtil.isInPlaceWhereTypeCanBeDuringCompletion(refExpr))) { + myAddOnlyCompleteMatches = myAddOnlyCompleteMatchesSet = true; + myProcessOnlyTypes = true; + allTypesResolved = true; + addPackageScope(possibleNameComponents, jsClass, refExpr); + } + else if (jsClass != null) { + myAddOnlyCompleteMatches = myAddOnlyCompleteMatchesSet = true; + updateCanUseOnlyCompleteMatches(jsClass); + } + } + } + + if (hasSomeInfoAvailable && (!allTypesResolved || (!possibleNameComponents.isEmpty() + && possibleNameComponents.get(0).length == 1 + && "Function".equals(possibleNameComponents.get(0)[0])))) { + if (doAddContextIds) { + possibleNameComponents.add(nameIds); + } + + doIterateTypeHierarchy( + nameIds, + clazz -> { + updateCanUseOnlyCompleteMatchesFromString(clazz.getQualifiedName(), clazz, clazz); + buildIndexListFromQNameAndCorrectQName(clazz.getQualifiedName(), clazz, possibleNameComponents); + return true; + } + ); + } + + String[][] nameIdsArray = new String[possibleNameComponents.size()][]; + possibleNameComponents.toArray(nameIdsArray); + + hasSomeSmartnessAvailable = nameIdsArray != null && nameIdsArray.length > 0; + } + + @RequiredReadAction + private void updateCanUseOnlyCompleteMatchesFromString(String qName, Object source, PsiElement clazz) { + boolean wasSet = myAddOnlyCompleteMatchesSet; + + if (myAddOnlyCompleteMatches || !wasSet) { + myAddOnlyCompleteMatchesSet = true; + if (qName.equals("*") + || (qName.equals(OBJECT_CLASS_NAME) && (myIteratedTypeName == null || qName.equals(myIteratedTypeName) + // skip adding complete matches when context name is qualifier + || (myContextNameIds != null && myContextNameIds.length > 0 + && myIteratedTypeName.equals(myContextNameIds[myContextNameIds.length - 1]) + && myContext instanceof JSReferenceExpression referenceExpression + && referenceExpression.getQualifier() instanceof JSReferenceExpression))) /* something explicitly marked as Object*/ + || (qName.equals(FUNCTION_TYPE_NAME) && isObjectSourceThatDoesNotGiveExactKnowledgeAboutFunctionType(source))) { + myAddOnlyCompleteMatches = false; + } + else { + if (clazz == null) { + clazz = JSResolveUtil.findClassByQName(qName, myContext); + } + + if (clazz instanceof JSClass jsClass) { + if (!wasSet) { + myAddOnlyCompleteMatches = true; + } + + JSAttributeList attributeList = jsClass.getAttributeList(); + if (attributeList != null && attributeList.hasModifier(JSAttributeList.ModifierType.DYNAMIC) + && !OBJECT_CLASS_NAME.equals(qName)) { + myAddOnlyCompleteMatches = false; + } + } + } + } + } + + private static boolean isObjectSourceThatDoesNotGiveExactKnowledgeAboutFunctionType(Object source) { + return source instanceof JSFunctionExpression; + } + + @RequiredReadAction + private void updateCanUseOnlyCompleteMatches(JSClass jsClass) { + JSAttributeList attributeList = jsClass != null ? jsClass.getAttributeList() : null; + if (attributeList != null && attributeList.hasModifier(JSAttributeList.ModifierType.DYNAMIC)) { + myAddOnlyCompleteMatches = false; + } + } + + @RequiredReadAction + public void addLocalResults(Collection results) { + if (results == null) { + return; + } + + Set processedCandidateNames = new HashSet<>(results.size()); + + for (PsiElement e : results) { + if (e instanceof PsiNamedElement namedElement) { + String name = ResolveProcessor.getName(namedElement); + String qName = namedElement instanceof JSQualifiedNamedElement qualifiedNamedElement + ? qualifiedNamedElement.getQualifiedName() + : name; + + if (processedCandidateNames.contains(qName)) { + continue; + } + processedCandidateNames.add(qName); + + addCompleteMatch(namedElement, name, false); + } + } + } + + class CompletionTypeProcessor implements TypeProcessor { + final List possibleNameIds; + private PsiElement myUnknownElement; + + CompletionTypeProcessor(List _possibleNameIds) { + possibleNameIds = _possibleNameIds; + } + + @Override + @RequiredReadAction + public void process(@Nonnull String type, EvaluateContext context, PsiElement source) { + if (context.visitedTypes.contains(type)) { + return; + } + context.visitedTypes.add(type); + if (JSTypeEvaluateManager.isArrayType(type)) { + type = ARRAY_TYPE_NAME; + } + updateCanUseOnlyCompleteMatchesFromString(type, source, null); + type = buildIndexListFromQNameAndCorrectQName(type, source, possibleNameIds); + addSupers(type, possibleNameIds, context); + } + + @Override + public Set getFeatures() { + return myFeatures; + } + + @Override + public boolean ecma() { + return ecmal4; + } + + @Override + public void setUnknownElement(@Nonnull PsiElement element) { + myUnknownElement = element; + } + + public boolean getAllTypesResolved() { + return myUnknownElement == null; + } + } + + private void addSupers(String type, List possibleNameIds, EvaluateContext context) { + String iteratedType = myIteratedTypeName; + myIteratedTypeName = type; + doIterateHierarchy( + type, + clazz -> { + String qname = clazz.getQualifiedName(); + if (!context.visitedTypes.contains(qname)) { + context.visitedTypes.add(qname); + updateCanUseOnlyCompleteMatchesFromString(qname, clazz, clazz); + buildIndexListFromQNameAndCorrectQName(clazz.getQualifiedName(), clazz, possibleNameIds); + } + return true; + } + ); + + myIteratedTypeName = iteratedType; + } + + public Object[] getResult() { + List results = new ArrayList<>(); + for (Object o : myNamesList) { + results.add(o); + } + + for (Object o : myPartialMatchNamesMapFromSameFile.values()) { + results.add(o); + } + + for (Object o : myPartialMatchNamesMap.values()) { + results.add(o); + } + + return ArrayUtil.toObjectArray(results); + } + + @Override + @RequiredReadAction + public boolean execute(@Nonnull PsiElement element, ResolveState state) { + if (element instanceof JSNamedElement namedElement) { + addCompleteMatch(namedElement, namedElement.getName()); + } + + return true; + } + + private void doAdd(String nameId, PsiElement element) { + String name = nameId != null ? nameId : null; + + boolean seemsToBePrivateSymbol = + name != null && name.length() > 0 && name.charAt(0) == '_' && name.length() > 1 && name.charAt(1) != '_'; + boolean privateSymbol = seemsToBePrivateSymbol; + + if (seemsToBePrivateSymbol) { + if (!(myTargetFile instanceof JSFile)) { + // no interest in html, jsp for private symbols + return; + } + + if (myContextNameIds == null || myContextNameIds.length == 0) { + privateSymbol = false; + } + } + + + MatchType matchType = MatchType.COMPLETE; + + if (matchType == MatchType.COMPLETE && !ecmal4 && myProcessOnlyTypes) { + if (((name != null && name.length() > 0 && Character.isLowerCase(name.charAt(0))) || seemsToBePrivateSymbol)) { + matchType = MatchType.PARTIAL; + } + } + + if (matchType == MatchType.PARTIAL || (privateSymbol && matchType == MatchType.COMPLETE)) { + addPartialMatch(element, nameId); + + } + else if (matchType == MatchType.COMPLETE) { + addCompleteMatch(element, nameId); + } + } + + @RequiredReadAction + private LookupElement addLookupValue(PsiElement element, String name, JSLookupUtil.LookupPriority priority) { + return JSLookupUtil.createLookupItem(element, name, priority); + } + + @Override + @RequiredReadAction + protected String[] calculateContextIds(JSReferenceExpression jsReferenceExpression) { + return JSResolveUtil.buildNameIdsForQualifier(JSResolveUtil.getRealRefExprQualifier(jsReferenceExpression)); + } + + @Override + protected boolean isFromRelevantFileOrDirectory() { + return super.isFromRelevantFileOrDirectory(); // || myTargetFiles.contains(myCurrentFile); + } + + private void addCompleteMatch(PsiElement _element, String nameId) { + addCompleteMatch(_element, nameId, true); + } + + private void addCompleteMatch(PsiElement _element, String nameId, boolean doFilterting) { + if (!doAdd(_element, nameId, doFilterting)) { + boolean removedFromPartialNames = false; + Object el = myNames2CandidatesMap.get(nameId); + + if (el != null) { + removedFromPartialNames = + myPartialMatchNamesMapFromSameFile.remove(nameId) != null || myPartialMatchNamesMap.remove(nameId) != null; + } + if (!removedFromPartialNames) { + return; + } + } + + PsiElement element = _element; + + if (isFromRelevantFileOrDirectory() && !myAddOnlyCompleteMatches) { + Object o = addLookupValue(element, nameId, JSLookupUtil.LookupPriority.HIGHEST); + if (o != null) { + myNamesList.add(myThisFileNameListCount++, o); + } + else { + myNames2CandidatesMap.remove(nameId); + } + } + else { + Object o = addLookupValue(element, nameId, JSLookupUtil.LookupPriority.HIGH); + if (o != null) { + myNamesList.add(o); + } + else { + myNames2CandidatesMap.remove(nameId); + } + } + } + + private boolean doAdd(Object element, String nameId, boolean doFilterting) { + if (nameId == null || (doFilterting && myNames2CandidatesMap.get(nameId) != null)) { + return false; + } + myNames2CandidatesMap.put(nameId, element); + return true; + } + + private void addPartialMatch(PsiElement _element, String nameId) { + if (myAddOnlyCompleteMatches) { + return; + } + if (!doAdd(_element, nameId, true)) { + return; + } + + PsiElement element = _element; + + Map targetNamesMap; + JSLookupUtil.LookupPriority priority; + + if (isFromRelevantFileOrDirectory()) { + priority = hasSomeSmartnessAvailable ? JSLookupUtil.LookupPriority.HIGHER : JSLookupUtil.LookupPriority.HIGHEST; + targetNamesMap = myPartialMatchNamesMapFromSameFile; + } + else { + priority = hasSomeSmartnessAvailable ? JSLookupUtil.LookupPriority.NORMAL : JSLookupUtil.LookupPriority.HIGH; + + targetNamesMap = myPartialMatchNamesMap; + } + + Object o = addLookupValue(element, nameId, priority); + + if (o != null) { + targetNamesMap.put(nameId, o); + } + else { + myNames2CandidatesMap.remove(nameId); + } + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/WalkUpResolveProcessor.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/WalkUpResolveProcessor.java index 3c0e4adf..13e6e3f8 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/WalkUpResolveProcessor.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/resolve/WalkUpResolveProcessor.java @@ -21,6 +21,7 @@ import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.impl.JSClassImpl; import com.intellij.lang.javascript.psi.impl.JSEmbeddedContentImpl; +import consulo.annotation.access.RequiredReadAction; import consulo.javascript.language.JavaScriptFeature; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiFile; @@ -30,7 +31,8 @@ import consulo.util.collection.ArrayUtil; import consulo.xml.psi.xml.XmlAttributeValue; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; + import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -38,374 +40,319 @@ /** * @author Maxim.Mossienko */ -public class WalkUpResolveProcessor extends BaseJSSymbolProcessor -{ - protected String myReferenceName; - protected String[][] myContextIds; - private int myFilePartialResultsCount; - private List myPartialMatchResults; - private int myFileCompleteResultsCount; - private List myCompleteMatchResults; - - private int myBestMatchedContextId = -1; - private boolean myCanHaveValidPartialMatches; - private boolean embeddedToHtmlAttr; - private boolean myInNewExpression; - - public WalkUpResolveProcessor(String referenceName, String[] contextIds, PsiFile targetFile, boolean skipDclsInTargetFile, PsiElement context) - { - super(targetFile, skipDclsInTargetFile, context, contextIds); - contextIds = myContextNameIds; - - myReferenceName = referenceName; - - if(context instanceof JSReferenceExpression) - { - myInNewExpression = context.getParent() instanceof JSNewExpression; - - final List possibleNameIds = new ArrayList(1); - final JSReferenceExpression refExpr = (JSReferenceExpression) context; - final JSExpression originalQualifier = refExpr.getQualifier(); - final JSExpression qualifier = JSResolveUtil.getRealRefExprQualifier(refExpr); - - final JSClass jsClass = PsiTreeUtil.getParentOfType(context, JSClass.class); // get rid of it! - final JSElement file = PsiTreeUtil.getParentOfType(context, JSEmbeddedContentImpl.class, JSFile.class); - - if((file instanceof JSFile && file.getContext() instanceof XmlAttributeValue) || file instanceof JSEmbeddedContentImpl) - { - embeddedToHtmlAttr = true; - } - - boolean haveNotEncounteredDynamics = true; - if(qualifier instanceof JSThisExpression || - qualifier instanceof JSSuperExpression || - qualifier == null || - originalQualifier == null) - { - myDefinitelyNonglobalReference = false; - - if(qualifier instanceof JSThisExpression) - { - JSResolveUtil.ContextResolver resolver = new JSResolveUtil.ContextResolver(qualifier); - final String contextQualifierText = resolver.getQualifierAsString(); - final PsiElement clazz = contextQualifierText != null ? JSClassImpl.findClassFromNamespace(contextQualifierText, context) : null; - - if(clazz instanceof JSClass) - { - JSAttributeList attrList; - - if((attrList = ((JSClass) clazz).getAttributeList()) != null) - { - final boolean clazzIsDynamic = attrList.hasModifier(JSAttributeList.ModifierType.DYNAMIC); - if(clazzIsDynamic) - { - haveNotEncounteredDynamics = false; - } - } - - buildIndexListFromQNameAndCorrectQName(contextQualifierText, clazz, possibleNameIds); - } - else - { - possibleNameIds.add(contextIds); - } - } - - if(qualifier == null) - { - final JSImportedElementResolveResult expression = JSImportHandlingUtil.resolveTypeNameUsingImports(refExpr); - - if(expression != null) - { - possibleNameIds.add(JSResolveUtil.buildNameIdsForQualifier(JSResolveUtil.getRealRefExprQualifierFromResult(refExpr, expression))); - } - else - { - addPackageScope(possibleNameIds, jsClass, refExpr); - } - } - else if(originalQualifier == null) - { - if(refExpr.getNode().getFirstChildNode().getElementType() == JSTokenTypes.AT) - { - haveNotEncounteredDynamics = false; - } - possibleNameIds.add(contextIds); - } - - if(contextIds != null) - { - iterateContextIds(contextIds, possibleNameIds, true); - } - if(originalQualifier == null) - { - possibleNameIds.add(ArrayUtil.EMPTY_STRING_ARRAY); - } - } - else if(!ecmal4) - { - VariantsProcessor.doEvalForExpr(qualifier, myTargetFile, new VariantsProcessor.TypeProcessor() - { - @Override - public Set getFeatures() - { - return myFeatures; - } - - @Override - public void process(@Nonnull String type, @Nonnull final EvaluateContext context, final PsiElement source) - { - if(context.visitedTypes.contains(type)) - { - return; - } - context.visitedTypes.add(type); - - if("window".equals(type)) - { - possibleNameIds.add(new String[0]); - return; - } - type = buildIndexListFromQNameAndCorrectQName(type, source, possibleNameIds); - - doIterateHierarchy(type, new HierarchyProcessor() - { - @Override - public boolean processClass(final JSClass clazz) - { - buildIndexListFromQNameAndCorrectQName(clazz.getQualifiedName(), clazz, possibleNameIds); - return true; - } - }); - } - - @Override - public void setUnknownElement(@Nonnull final PsiElement element) - { - } - - @Override - public boolean ecma() - { - return ecmal4; - } - }); - } - if(possibleNameIds.size() != 0) - { - myContextIds = possibleNameIds.toArray(new String[possibleNameIds.size()][]); - myAddOnlyCompleteMatches = haveNotEncounteredDynamics; - myCanHaveValidPartialMatches = !ecmal4 && !myDefinitelyGlobalReference || !haveNotEncounteredDynamics; - } - else if(myContextIds == null && contextIds != null) - { - myContextIds = new String[][]{contextIds}; - } - } - else if(contextIds != null) - { - final List possibleNameIds = new ArrayList(1); - possibleNameIds.add(contextIds); - iterateContextIds(contextIds, possibleNameIds, false); - myContextIds = possibleNameIds.toArray(new String[possibleNameIds.size()][]); - } - } - - private void iterateContextIds(final String[] contextIds, final List possibleNameIds, final boolean allowObject) - { - doIterateTypeHierarchy(contextIds, new HierarchyProcessor() - { - @Override - public boolean processClass(final JSClass clazz) - { - buildIndexListFromQNameAndCorrectQName(clazz.getQualifiedName(), clazz, possibleNameIds); - return true; - } - }); - } - - protected MatchType isAcceptableQualifiedItem(final String nameId, final PsiElement element) - { - final boolean partialMatch = myReferenceName.equals(nameId); - - if(partialMatch) - { - int i = -1; - - if(myContextIds != null) - { - int maxContextScanCount = myBestMatchedContextId == -1 ? myContextIds.length : myBestMatchedContextId + 1; - - for(int currentContextIndex = 0; currentContextIndex < maxContextScanCount; ++currentContextIndex) - { - final String[] contextIds = myContextIds[currentContextIndex]; - - if(i < 0) - { - if(myBestMatchedContextId == -1) - { - myBestMatchedContextId = currentContextIndex; - } - else if(currentContextIndex < myBestMatchedContextId) - { - myBestMatchedContextId = currentContextIndex; - myCompleteMatchResults = null; - myFileCompleteResultsCount = 0; - } - return MatchType.COMPLETE; - } - } - } - - if(i < 0) - { - return MatchType.COMPLETE; - } - } - - return partialMatch ? MatchType.PARTIAL : MatchType.NOMATCH; - } - - private void doQualifiedCheck(String nameId, final PsiElement element) - { - final MatchType matchType = isAcceptableQualifiedItem(nameId, element); - - if(matchType == MatchType.PARTIAL) - { - addPartialResult(element); - } - else if(matchType == MatchType.COMPLETE) - { - addCompleteResult(element); - } - } - - private void addCompleteResult(PsiElement element) - { - final JSResolveUtil.MyResolveResult o = new JSResolveUtil.MyResolveResult(element); - addCompleteResult(o); - } - - private void addCompleteResult(ResolveResult o) - { - if(myCompleteMatchResults == null) - { - myCompleteMatchResults = new ArrayList(1); - } - if(isFromRelevantFileOrDirectory()) - { - myCompleteMatchResults.add(myFileCompleteResultsCount++, o); - } - else - { - myCompleteMatchResults.add(o); - } - } - - private void addPartialResult(PsiElement element) - { - if(myPartialMatchResults == null) - { - myPartialMatchResults = new ArrayList(1); - } - final JSResolveUtil.MyResolveResult o = new JSResolveUtil.MyResolveResult(element, !myAddOnlyCompleteMatches); - - if(isFromRelevantFileOrDirectory()) - { - myPartialMatchResults.add(myFilePartialResultsCount++, o); - } - else - { - myPartialMatchResults.add(o); - } - } - - protected boolean shouldProcessVariable(final String nameId, JSNamedElement var) - { - return myReferenceName.equals(nameId) && !myDefinitelyNonglobalReference; - } - - public ResolveResult[] getResults() - { - int resultCount = 0; - if(myCompleteMatchResults != null) - { - resultCount += myCompleteMatchResults.size(); - } - final boolean addPartialResults = !myAddOnlyCompleteMatches || (resultCount == 0 && myAllowPartialResults); - if(myPartialMatchResults != null && addPartialResults) - { - resultCount += myPartialMatchResults.size(); - } - - final ResolveResult[] result = resultCount != 0 ? new ResolveResult[resultCount] : ResolveResult.EMPTY_ARRAY; - - if(myCompleteMatchResults != null) - { - for(int i = 0; i < myCompleteMatchResults.size(); ++i) - { - result[i] = myCompleteMatchResults.get(i); - assert result[i] != null; - } - } - - if(myPartialMatchResults != null && addPartialResults) - { - int offset = myCompleteMatchResults != null ? myCompleteMatchResults.size() : 0; - for(int i = 0; i < myPartialMatchResults.size(); ++i) - { - final JSResolveUtil.MyResolveResult resolveResult = (JSResolveUtil.MyResolveResult) myPartialMatchResults.get(i); - - assert resolveResult != null; - result[offset + i] = resolveResult; - } - } - - return result; - } - - @Override - protected String[] calculateContextIds(final JSReferenceExpression jsReferenceExpression) - { - String[] contextNameIds = null; - JSExpression qualifier = JSResolveUtil.getRealRefExprQualifier(jsReferenceExpression); - - if(qualifier instanceof JSReferenceExpression) - { - contextNameIds = JSSymbolUtil.buildNameIndexArray(qualifier); - } - else if(qualifier instanceof JSThisExpression || qualifier instanceof JSSuperExpression) - { - contextNameIds = JSResolveUtil.buildNameIdsForQualifier(qualifier); - } - - return contextNameIds; - } - - public void addLocalResults(final ResolveResult results[]) - { - if(results == null) - { - return; - } - for(ResolveResult e : results) - { - addCompleteResult(e); - } - } - - public int getCompleteResultCount() - { - return myCompleteMatchResults == null ? 0 : myCompleteMatchResults.size(); - } - - @Override - public boolean execute(final PsiElement element, final ResolveState state) - { - if((element instanceof JSNamedElement && myReferenceName.equals(((JSNamedElement) element).getName())) || element == myContext) - { - addCompleteResult(element); - } - return true; - } +public class WalkUpResolveProcessor extends BaseJSSymbolProcessor { + protected String myReferenceName; + protected String[][] myContextIds; + private int myFilePartialResultsCount; + private List myPartialMatchResults; + private int myFileCompleteResultsCount; + private List myCompleteMatchResults; + + private int myBestMatchedContextId = -1; + private boolean myCanHaveValidPartialMatches; + private boolean embeddedToHtmlAttr; + private boolean myInNewExpression; + + @RequiredReadAction + public WalkUpResolveProcessor( + String referenceName, + String[] contextIds, + PsiFile targetFile, + boolean skipDclsInTargetFile, + PsiElement context + ) { + super(targetFile, skipDclsInTargetFile, context, contextIds); + contextIds = myContextNameIds; + + myReferenceName = referenceName; + + if (context instanceof JSReferenceExpression refExpr) { + myInNewExpression = context.getParent() instanceof JSNewExpression; + + final List possibleNameIds = new ArrayList<>(1); + JSExpression originalQualifier = refExpr.getQualifier(); + JSExpression qualifier = JSResolveUtil.getRealRefExprQualifier(refExpr); + + JSClass jsClass = PsiTreeUtil.getParentOfType(context, JSClass.class); // get rid of it! + JSElement file = PsiTreeUtil.getParentOfType(context, JSEmbeddedContentImpl.class, JSFile.class); + + if ((file instanceof JSFile && file.getContext() instanceof XmlAttributeValue) || file instanceof JSEmbeddedContentImpl) { + embeddedToHtmlAttr = true; + } + + boolean haveNotEncounteredDynamics = true; + if (qualifier instanceof JSThisExpression || qualifier instanceof JSSuperExpression + || qualifier == null || originalQualifier == null) { + myDefinitelyNonglobalReference = false; + + if (qualifier instanceof JSThisExpression) { + JSResolveUtil.ContextResolver resolver = new JSResolveUtil.ContextResolver(qualifier); + String contextQualifierText = resolver.getQualifierAsString(); + PsiElement clazz = contextQualifierText != null + ? JSClassImpl.findClassFromNamespace(contextQualifierText, context) + : null; + + if (clazz instanceof JSClass jsClass1) { + JSAttributeList attrList = jsClass1.getAttributeList(); + + if (attrList != null) { + boolean clazzIsDynamic = attrList.hasModifier(JSAttributeList.ModifierType.DYNAMIC); + if (clazzIsDynamic) { + haveNotEncounteredDynamics = false; + } + } + + buildIndexListFromQNameAndCorrectQName(contextQualifierText, clazz, possibleNameIds); + } + else { + possibleNameIds.add(contextIds); + } + } + + if (qualifier == null) { + JSImportedElementResolveResult expression = JSImportHandlingUtil.resolveTypeNameUsingImports(refExpr); + + if (expression != null) { + possibleNameIds.add(JSResolveUtil.buildNameIdsForQualifier(JSResolveUtil.getRealRefExprQualifierFromResult( + refExpr, + expression + ))); + } + else { + addPackageScope(possibleNameIds, jsClass, refExpr); + } + } + else if (originalQualifier == null) { + if (refExpr.getNode().getFirstChildNode().getElementType() == JSTokenTypes.AT) { + haveNotEncounteredDynamics = false; + } + possibleNameIds.add(contextIds); + } + + if (contextIds != null) { + iterateContextIds(contextIds, possibleNameIds, true); + } + if (originalQualifier == null) { + possibleNameIds.add(ArrayUtil.EMPTY_STRING_ARRAY); + } + } + else if (!ecmal4) { + VariantsProcessor.doEvalForExpr( + qualifier, + myTargetFile, + new VariantsProcessor.TypeProcessor() { + @Override + public Set getFeatures() { + return myFeatures; + } + + @Override + public void process(@Nonnull String type, @Nonnull EvaluateContext context, PsiElement source) { + if (context.visitedTypes.contains(type)) { + return; + } + context.visitedTypes.add(type); + + if ("window".equals(type)) { + possibleNameIds.add(new String[0]); + return; + } + type = buildIndexListFromQNameAndCorrectQName(type, source, possibleNameIds); + + doIterateHierarchy( + type, + clazz -> { + buildIndexListFromQNameAndCorrectQName(clazz.getQualifiedName(), clazz, possibleNameIds); + return true; + } + ); + } + + @Override + public void setUnknownElement(@Nonnull PsiElement element) { + } + + @Override + public boolean ecma() { + return ecmal4; + } + } + ); + } + if (possibleNameIds.size() != 0) { + myContextIds = possibleNameIds.toArray(new String[possibleNameIds.size()][]); + myAddOnlyCompleteMatches = haveNotEncounteredDynamics; + myCanHaveValidPartialMatches = !ecmal4 && !myDefinitelyGlobalReference || !haveNotEncounteredDynamics; + } + else if (myContextIds == null && contextIds != null) { + myContextIds = new String[][]{contextIds}; + } + } + else if (contextIds != null) { + List possibleNameIds = new ArrayList<>(1); + possibleNameIds.add(contextIds); + iterateContextIds(contextIds, possibleNameIds, false); + myContextIds = possibleNameIds.toArray(new String[possibleNameIds.size()][]); + } + } + + private void iterateContextIds(String[] contextIds, List possibleNameIds, boolean allowObject) { + doIterateTypeHierarchy( + contextIds, + clazz -> { + buildIndexListFromQNameAndCorrectQName(clazz.getQualifiedName(), clazz, possibleNameIds); + return true; + } + ); + } + + protected MatchType isAcceptableQualifiedItem(String nameId, PsiElement element) { + boolean partialMatch = myReferenceName.equals(nameId); + + if (partialMatch) { + int i = -1; + + if (myContextIds != null) { + int maxContextScanCount = myBestMatchedContextId == -1 ? myContextIds.length : myBestMatchedContextId + 1; + + for (int currentContextIndex = 0; currentContextIndex < maxContextScanCount; ++currentContextIndex) { + String[] contextIds = myContextIds[currentContextIndex]; + + if (i < 0) { + if (myBestMatchedContextId == -1) { + myBestMatchedContextId = currentContextIndex; + } + else if (currentContextIndex < myBestMatchedContextId) { + myBestMatchedContextId = currentContextIndex; + myCompleteMatchResults = null; + myFileCompleteResultsCount = 0; + } + return MatchType.COMPLETE; + } + } + } + + if (i < 0) { + return MatchType.COMPLETE; + } + } + + return partialMatch ? MatchType.PARTIAL : MatchType.NOMATCH; + } + + private void doQualifiedCheck(String nameId, PsiElement element) { + MatchType matchType = isAcceptableQualifiedItem(nameId, element); + + if (matchType == MatchType.PARTIAL) { + addPartialResult(element); + } + else if (matchType == MatchType.COMPLETE) { + addCompleteResult(element); + } + } + + private void addCompleteResult(PsiElement element) { + JSResolveUtil.MyResolveResult o = new JSResolveUtil.MyResolveResult(element); + addCompleteResult(o); + } + + private void addCompleteResult(ResolveResult o) { + if (myCompleteMatchResults == null) { + myCompleteMatchResults = new ArrayList<>(1); + } + if (isFromRelevantFileOrDirectory()) { + myCompleteMatchResults.add(myFileCompleteResultsCount++, o); + } + else { + myCompleteMatchResults.add(o); + } + } + + private void addPartialResult(PsiElement element) { + if (myPartialMatchResults == null) { + myPartialMatchResults = new ArrayList<>(1); + } + JSResolveUtil.MyResolveResult o = new JSResolveUtil.MyResolveResult(element, !myAddOnlyCompleteMatches); + + if (isFromRelevantFileOrDirectory()) { + myPartialMatchResults.add(myFilePartialResultsCount++, o); + } + else { + myPartialMatchResults.add(o); + } + } + + protected boolean shouldProcessVariable(String nameId, JSNamedElement var) { + return myReferenceName.equals(nameId) && !myDefinitelyNonglobalReference; + } + + public ResolveResult[] getResults() { + int resultCount = 0; + if (myCompleteMatchResults != null) { + resultCount += myCompleteMatchResults.size(); + } + boolean addPartialResults = !myAddOnlyCompleteMatches || (resultCount == 0 && myAllowPartialResults); + if (myPartialMatchResults != null && addPartialResults) { + resultCount += myPartialMatchResults.size(); + } + + ResolveResult[] result = resultCount != 0 ? new ResolveResult[resultCount] : ResolveResult.EMPTY_ARRAY; + + if (myCompleteMatchResults != null) { + for (int i = 0; i < myCompleteMatchResults.size(); ++i) { + result[i] = myCompleteMatchResults.get(i); + assert result[i] != null; + } + } + + if (myPartialMatchResults != null && addPartialResults) { + int offset = myCompleteMatchResults != null ? myCompleteMatchResults.size() : 0; + for (int i = 0; i < myPartialMatchResults.size(); ++i) { + JSResolveUtil.MyResolveResult resolveResult = (JSResolveUtil.MyResolveResult)myPartialMatchResults.get(i); + + assert resolveResult != null; + result[offset + i] = resolveResult; + } + } + + return result; + } + + @Override + @RequiredReadAction + protected String[] calculateContextIds(JSReferenceExpression jsReferenceExpression) { + String[] contextNameIds = null; + JSExpression qualifier = JSResolveUtil.getRealRefExprQualifier(jsReferenceExpression); + + if (qualifier instanceof JSReferenceExpression) { + contextNameIds = JSSymbolUtil.buildNameIndexArray(qualifier); + } + else if (qualifier instanceof JSThisExpression || qualifier instanceof JSSuperExpression) { + contextNameIds = JSResolveUtil.buildNameIdsForQualifier(qualifier); + } + + return contextNameIds; + } + + public void addLocalResults(ResolveResult results[]) { + if (results == null) { + return; + } + for (ResolveResult e : results) { + addCompleteResult(e); + } + } + + public int getCompleteResultCount() { + return myCompleteMatchResults == null ? 0 : myCompleteMatchResults.size(); + } + + @Override + @RequiredReadAction + public boolean execute(@Nonnull PsiElement element, ResolveState state) { + if ((element instanceof JSNamedElement namedElement && myReferenceName.equals(namedElement.getName())) || element == myContext) { + addCompleteResult(element); + } + return true; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSAttributeListStubImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSAttributeListStubImpl.java index e4f2e7d9..936c126c 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSAttributeListStubImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSAttributeListStubImpl.java @@ -25,114 +25,95 @@ /** * @author Maxim.Mossienko - * Date: Mar 26, 2008 - * Time: 11:29:19 PM + * Date: Mar 26, 2008 + * Time: 11:29:19 PM */ -public class JSAttributeListStubImpl extends StubBase implements JSAttributeListStub -{ - private static final int VISIBILITY_TAG_SHIFT = 0; - private static final int VISIBILITY_TAG_MASK = 0x3; - private static final int OVERRIDE_PROPERTY_SHIFT = 2; - private static final int STATIC_PROPERTY_SHIFT = 3; - private static final int DYNAMIC_PROPERTY_SHIFT = 4; - private static final int NATIVE_PROPERTY_SHIFT = 5; - private static final int FINAL_PROPERTY_SHIFT = 6; - private static final int VIRTUAL_PROPERTY_SHIFT = 7; +public class JSAttributeListStubImpl extends StubBase implements JSAttributeListStub { + private static final int VISIBILITY_TAG_SHIFT = 0; + private static final int VISIBILITY_TAG_MASK = 0x3; + private static final int OVERRIDE_PROPERTY_SHIFT = 2; + private static final int STATIC_PROPERTY_SHIFT = 3; + private static final int DYNAMIC_PROPERTY_SHIFT = 4; + private static final int NATIVE_PROPERTY_SHIFT = 5; + private static final int FINAL_PROPERTY_SHIFT = 6; + private static final int VIRTUAL_PROPERTY_SHIFT = 7; - private int myFlags; - private String myNamespace; + private int myFlags; + private String myNamespace; - public JSAttributeListStubImpl(String namespace, int flags, final StubElement parent, final IStubElementType elementType) - { - super(parent, elementType); - myNamespace = namespace; - myFlags = flags; - } + public JSAttributeListStubImpl(String namespace, int flags, StubElement parent, IStubElementType elementType) { + super(parent, elementType); + myNamespace = namespace; + myFlags = flags; + } - @Override - public JSAttributeList.AccessType getAccessType() - { - final int i = (myFlags >> VISIBILITY_TAG_SHIFT) & VISIBILITY_TAG_MASK; - return types[i]; - } + @Override + public JSAttributeList.AccessType getAccessType() { + int i = (myFlags >> VISIBILITY_TAG_SHIFT) & VISIBILITY_TAG_MASK; + return types[i]; + } - private static final JSAttributeList.AccessType[] types = JSAttributeList.AccessType.values(); + private static final JSAttributeList.AccessType[] types = JSAttributeList.AccessType.values(); - @Override - public boolean hasModifier(final JSAttributeList.ModifierType modifier) - { - return ((myFlags >> getFlagShift(modifier)) & 0x1) != 0; - } + @Override + public boolean hasModifier(JSAttributeList.ModifierType modifier) { + return ((myFlags >> getFlagShift(modifier)) & 0x1) != 0; + } - @Override - public String getNamespace() - { - return myNamespace; - } + @Override + public String getNamespace() { + return myNamespace; + } - @Override - public int getFlags() - { - return myFlags; - } + @Override + public int getFlags() { + return myFlags; + } - public static int getFlags(JSAttributeList attributeList) - { - final JSAttributeList.AccessType accessType = attributeList.getAccessType(); - final int ord = accessType.ordinal(); + public static int getFlags(JSAttributeList attributeList) { + JSAttributeList.AccessType accessType = attributeList.getAccessType(); + int ord = accessType.ordinal(); - int flags = (ord << VISIBILITY_TAG_SHIFT); + int flags = (ord << VISIBILITY_TAG_SHIFT); - for(JSAttributeList.ModifierType type : JSAttributeList.ModifierType.values()) - { - flags = setFlag(flags, type, attributeList.hasModifier(type)); - } - return flags; - } + for (JSAttributeList.ModifierType type : JSAttributeList.ModifierType.values()) { + flags = setFlag(flags, type, attributeList.hasModifier(type)); + } + return flags; + } - private static int getFlagShift(final JSAttributeList.ModifierType modifier) - { - int shift = -1; - if(modifier == JSAttributeList.ModifierType.STATIC) - { - shift = STATIC_PROPERTY_SHIFT; - } - else if(modifier == JSAttributeList.ModifierType.DYNAMIC) - { - shift = DYNAMIC_PROPERTY_SHIFT; - } - else if(modifier == JSAttributeList.ModifierType.OVERRIDE) - { - shift = OVERRIDE_PROPERTY_SHIFT; - } - else if(modifier == JSAttributeList.ModifierType.NATIVE) - { - shift = NATIVE_PROPERTY_SHIFT; - } - else if(modifier == JSAttributeList.ModifierType.FINAL) - { - shift = FINAL_PROPERTY_SHIFT; - } - else if(modifier == JSAttributeList.ModifierType.VIRTUAL) - { - shift = VIRTUAL_PROPERTY_SHIFT; - } - if(shift == -1) - { - throw new IllegalArgumentException("Illegal modifier passed:" + modifier); - } - return shift; - } + private static int getFlagShift(JSAttributeList.ModifierType modifier) { + int shift = -1; + if (modifier == JSAttributeList.ModifierType.STATIC) { + shift = STATIC_PROPERTY_SHIFT; + } + else if (modifier == JSAttributeList.ModifierType.DYNAMIC) { + shift = DYNAMIC_PROPERTY_SHIFT; + } + else if (modifier == JSAttributeList.ModifierType.OVERRIDE) { + shift = OVERRIDE_PROPERTY_SHIFT; + } + else if (modifier == JSAttributeList.ModifierType.NATIVE) { + shift = NATIVE_PROPERTY_SHIFT; + } + else if (modifier == JSAttributeList.ModifierType.FINAL) { + shift = FINAL_PROPERTY_SHIFT; + } + else if (modifier == JSAttributeList.ModifierType.VIRTUAL) { + shift = VIRTUAL_PROPERTY_SHIFT; + } + if (shift == -1) { + throw new IllegalArgumentException("Illegal modifier passed:" + modifier); + } + return shift; + } - private static int setFlag(int old, final JSAttributeList.ModifierType modifier, boolean value) - { - if(value) - { - return old | (1 << getFlagShift(modifier)); - } - else - { - return old & ~(1 << getFlagShift(modifier)); - } - } + private static int setFlag(int old, JSAttributeList.ModifierType modifier, boolean value) { + if (value) { + return old | (1 << getFlagShift(modifier)); + } + else { + return old & ~(1 << getFlagShift(modifier)); + } + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSAttributeNameValuePairStubImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSAttributeNameValuePairStubImpl.java index 329afba5..7de0571b 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSAttributeNameValuePairStubImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSAttributeNameValuePairStubImpl.java @@ -24,22 +24,19 @@ /** * @author Maxim.Mossienko - * Date: Jun 6, 2008 - * Time: 8:00:52 PM + * Date: Jun 6, 2008 + * Time: 8:00:52 PM */ -public class JSAttributeNameValuePairStubImpl extends JSNamedObjectStubBase implements JSAttributeNameValuePairStub -{ - private String myValue; +public class JSAttributeNameValuePairStubImpl extends JSNamedObjectStubBase implements JSAttributeNameValuePairStub { + private String myValue; - public JSAttributeNameValuePairStubImpl(String name, final String value, final StubElement parentStub) - { - super(name, 0, parentStub, JSElementTypes.ATTRIBUTE_NAME_VALUE_PAIR); - myValue = value; - } + public JSAttributeNameValuePairStubImpl(String name, String value, StubElement parentStub) { + super(name, 0, parentStub, JSElementTypes.ATTRIBUTE_NAME_VALUE_PAIR); + myValue = value; + } - @Override - public String getValue() - { - return myValue; - } + @Override + public String getValue() { + return myValue; + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSAttributeStubImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSAttributeStubImpl.java index 3763b7bb..cc71dba3 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSAttributeStubImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSAttributeStubImpl.java @@ -24,13 +24,11 @@ /** * @author Maxim.Mossienko - * Date: Mar 26, 2008 - * Time: 11:29:19 PM + * Date: Mar 26, 2008 + * Time: 11:29:19 PM */ -public class JSAttributeStubImpl extends JSNamedObjectStubBase implements JSAttributeStub -{ - public JSAttributeStubImpl(final String name, int flags, final StubElement parentStub) - { - super(name, flags, parentStub, JSElementTypes.ATTRIBUTE); - } +public class JSAttributeStubImpl extends JSNamedObjectStubBase implements JSAttributeStub { + public JSAttributeStubImpl(String name, int flags, StubElement parentStub) { + super(name, flags, parentStub, JSElementTypes.ATTRIBUTE); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSClassStubImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSClassStubImpl.java index 61adbf5a..5c91f281 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSClassStubImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSClassStubImpl.java @@ -24,37 +24,34 @@ /** * @author Maxim.Mossienko - * Date: Mar 26, 2008 - * Time: 7:11:48 PM + * Date: Mar 26, 2008 + * Time: 7:11:48 PM */ -public class JSClassStubImpl extends JSQualifiedObjectStubBase implements JSClassStub -{ - public static final int INTERFACE_MASK = 1; - private static final int DEPRECATED_MASK = 4; +public class JSClassStubImpl extends JSQualifiedObjectStubBase implements JSClassStub { + public static final int INTERFACE_MASK = 1; + private static final int DEPRECATED_MASK = 4; - public JSClassStubImpl(String name, - int flags, - String qName, - final StubElement parentStub, - final IStubElementType elementType) - { - super(name, flags, qName, parentStub, elementType); - } + public JSClassStubImpl( + String name, + int flags, + String qName, + StubElement parentStub, + IStubElementType elementType + ) { + super(name, flags, qName, parentStub, elementType); + } - public static int getFlags(JSClass jsClass) - { - return (jsClass.isInterface() ? INTERFACE_MASK : 0) | (jsClass.isDeprecated() ? DEPRECATED_MASK : 0); - } + public static int getFlags(JSClass jsClass) { + return (jsClass.isInterface() ? INTERFACE_MASK : 0) | (jsClass.isDeprecated() ? DEPRECATED_MASK : 0); + } - @Override - public boolean isInterface() - { - return (myFlags & INTERFACE_MASK) != 0; - } + @Override + public boolean isInterface() { + return (myFlags & INTERFACE_MASK) != 0; + } - @Override - public boolean isDeprecated() - { - return (myFlags & DEPRECATED_MASK) != 0; - } + @Override + public boolean isDeprecated() { + return (myFlags & DEPRECATED_MASK) != 0; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSFunctionStubImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSFunctionStubImpl.java index e96a1eee..8bfe4f1d 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSFunctionStubImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSFunctionStubImpl.java @@ -24,69 +24,67 @@ /** * @author Maxim.Mossienko - * Date: Mar 26, 2008 - * Time: 7:11:48 PM + * Date: Mar 26, 2008 + * Time: 7:11:48 PM */ -public class JSFunctionStubImpl extends JSQualifiedObjectStubBase implements JSFunctionStub -{ - private String myReturnType; - public static final int GET_PROPERTY_MASK = 1; - public static final int SET_PROPERTY_MASK = 2; - public static final int CONSTRUCTOR_MASK = 4; - private static final int DEPRECATED_MASK = 8; - private static final int REFERENCES_ARGUMENTS_MASK = 16; +public class JSFunctionStubImpl extends JSQualifiedObjectStubBase implements JSFunctionStub { + private String myReturnType; + public static final int GET_PROPERTY_MASK = 1; + public static final int SET_PROPERTY_MASK = 2; + public static final int CONSTRUCTOR_MASK = 4; + private static final int DEPRECATED_MASK = 8; + private static final int REFERENCES_ARGUMENTS_MASK = 16; - public JSFunctionStubImpl(final String name, - int flags, - String qName, - String returnType, - final StubElement parentStub, - final JSStubElementType elementType) - { - super(name, flags, qName, parentStub, elementType); - myReturnType = returnType; - } + public JSFunctionStubImpl( + String name, + int flags, + String qName, + String returnType, + StubElement parentStub, + JSStubElementType elementType + ) { + super(name, flags, qName, parentStub, elementType); + myReturnType = returnType; + } - public static int buildFlags(final JSFunction clazz) - { - final int val = clazz.isConstructor() ? CONSTRUCTOR_MASK : clazz.isGetProperty() ? GET_PROPERTY_MASK : clazz.isSetProperty() ? SET_PROPERTY_MASK - : 0; - return val | (clazz.isDeprecated() ? DEPRECATED_MASK : 0) | (clazz.isReferencesArguments() ? REFERENCES_ARGUMENTS_MASK : 0); - } + public static int buildFlags(JSFunction clazz) { + int val = clazz.isConstructor() + ? CONSTRUCTOR_MASK + : clazz.isGetProperty() + ? GET_PROPERTY_MASK + : clazz.isSetProperty() + ? SET_PROPERTY_MASK + : 0; + return val | (clazz.isDeprecated() ? DEPRECATED_MASK : 0) | (clazz.isReferencesArguments() ? REFERENCES_ARGUMENTS_MASK : 0); + } - @Override - public boolean isGetProperty() - { - return (myFlags & GET_PROPERTY_MASK) != 0; - } + @Override + public boolean isGetProperty() { + return (myFlags & GET_PROPERTY_MASK) != 0; + } - @Override - public boolean isSetProperty() - { - return (myFlags & SET_PROPERTY_MASK) != 0; - } + @Override + public boolean isSetProperty() { + return (myFlags & SET_PROPERTY_MASK) != 0; + } - @Override - public boolean isConstructor() - { - return (myFlags & CONSTRUCTOR_MASK) != 0; - } + @Override + public boolean isConstructor() { + return (myFlags & CONSTRUCTOR_MASK) != 0; + } - @Override - public boolean isDeprecated() - { - return (myFlags & DEPRECATED_MASK) != 0; - } + @Override + public boolean isDeprecated() { + return (myFlags & DEPRECATED_MASK) != 0; + } - @Override - public boolean isReferencesArguments() - { - return (myFlags & REFERENCES_ARGUMENTS_MASK) != 0; - } + @Override + public boolean isReferencesArguments() { + return (myFlags & REFERENCES_ARGUMENTS_MASK) != 0; + } - @Override - public String getReturnTypeString() - { - return myReturnType; - } + @Override + public String getReturnTypeString() { + return myReturnType; + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSImportStatementStubImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSImportStatementStubImpl.java index 3f699af4..0ebcdc57 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSImportStatementStubImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSImportStatementStubImpl.java @@ -25,24 +25,24 @@ /** * @author Maxim.Mossienko - * Date: Jun 6, 2008 - * Time: 8:00:52 PM + * Date: Jun 6, 2008 + * Time: 8:00:52 PM */ -public class JSImportStatementStubImpl extends StubBase implements JSImportStatementStub -{ - private final String myImportText; +public class JSImportStatementStubImpl extends StubBase implements JSImportStatementStub { + private final String myImportText; - public JSImportStatementStubImpl(final String importText, final StubElement parentStub, final JSStubElementType type) - { - super(parentStub, type); + public JSImportStatementStubImpl( + String importText, + StubElement parentStub, + JSStubElementType type + ) { + super(parentStub, type); - myImportText = importText; - } + myImportText = importText; + } - @Override - public String getImportText() - { - return myImportText; - } + @Override + public String getImportText() { + return myImportText; + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSIncludeDirectiveStubImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSIncludeDirectiveStubImpl.java index d4d8f403..240e4c2e 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSIncludeDirectiveStubImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSIncludeDirectiveStubImpl.java @@ -25,24 +25,23 @@ /** * @author Maxim.Mossienko - * Date: Jun 6, 2008 - * Time: 8:00:52 PM + * Date: Jun 6, 2008 + * Time: 8:00:52 PM */ -public class JSIncludeDirectiveStubImpl extends StubBase implements JSIncludeDirectiveStub -{ - private final String myIncludeText; +public class JSIncludeDirectiveStubImpl extends StubBase implements JSIncludeDirectiveStub { + private final String myIncludeText; - public JSIncludeDirectiveStubImpl(final String includeText, - final StubElement parentStub, - final JSStubElementType type) - { - super(parentStub, type); - myIncludeText = includeText; - } + public JSIncludeDirectiveStubImpl( + String includeText, + StubElement parentStub, + JSStubElementType type + ) { + super(parentStub, type); + myIncludeText = includeText; + } - @Override - public String getIncludeText() - { - return myIncludeText; - } + @Override + public String getIncludeText() { + return myIncludeText; + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSNamedObjectStubBase.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSNamedObjectStubBase.java index 4678ca8d..152ac25f 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSNamedObjectStubBase.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSNamedObjectStubBase.java @@ -24,29 +24,25 @@ /** * @author Maxim.Mossienko - * Date: Mar 26, 2008 - * Time: 7:11:48 PM + * Date: Mar 26, 2008 + * Time: 7:11:48 PM */ -public abstract class JSNamedObjectStubBase extends StubBase -{ - protected final String myName; - protected final int myFlags; +public abstract class JSNamedObjectStubBase extends StubBase { + protected final String myName; + protected final int myFlags; - protected JSNamedObjectStubBase(String name, int flags, final StubElement parent, final IStubElementType elementType) - { - super(parent, elementType); + protected JSNamedObjectStubBase(String name, int flags, StubElement parent, IStubElementType elementType) { + super(parent, elementType); - myName = name; - myFlags = flags; - } + myName = name; + myFlags = flags; + } - public int getFlags() - { - return myFlags; - } + public int getFlags() { + return myFlags; + } - public String getName() - { - return myName; - } + public String getName() { + return myName; + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSNamespaceDeclarationStubImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSNamespaceDeclarationStubImpl.java index a8ca1e75..56ded2a0 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSNamespaceDeclarationStubImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSNamespaceDeclarationStubImpl.java @@ -24,22 +24,26 @@ /** * @author Maxim.Mossienko - * Date: Jun 6, 2008 - * Time: 8:00:52 PM + * Date: Jun 6, 2008 + * Time: 8:00:52 PM */ -public class JSNamespaceDeclarationStubImpl extends JSQualifiedObjectStubBase implements JSNamespaceDeclarationStub -{ - private String myInitialValueString; +public class JSNamespaceDeclarationStubImpl extends JSQualifiedObjectStubBase + implements JSNamespaceDeclarationStub { + private String myInitialValueString; - public JSNamespaceDeclarationStubImpl(String name, String qName, String initialValueString, StubElement parent, IStubElementType elementType) - { - super(name, 0, qName, parent, elementType); - myInitialValueString = initialValueString; - } + public JSNamespaceDeclarationStubImpl( + String name, + String qName, + String initialValueString, + StubElement parent, + IStubElementType elementType + ) { + super(name, 0, qName, parent, elementType); + myInitialValueString = initialValueString; + } - @Override - public String getInitialValueString() - { - return myInitialValueString; - } + @Override + public String getInitialValueString() { + return myInitialValueString; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSPackageStatementStubImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSPackageStatementStubImpl.java index 053c358b..b0be2d63 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSPackageStatementStubImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSPackageStatementStubImpl.java @@ -24,13 +24,11 @@ /** * @author Maxim.Mossienko - * Date: Jun 6, 2008 - * Time: 8:00:52 PM + * Date: Jun 6, 2008 + * Time: 8:00:52 PM */ -public class JSPackageStatementStubImpl extends JSQualifiedObjectStubBase implements JSPackageStatementStub -{ - public JSPackageStatementStubImpl(String name, String qName, StubElement parent, IStubElementType elementType) - { - super(name, 0, qName, parent, elementType); - } +public class JSPackageStatementStubImpl extends JSQualifiedObjectStubBase implements JSPackageStatementStub { + public JSPackageStatementStubImpl(String name, String qName, StubElement parent, IStubElementType elementType) { + super(name, 0, qName, parent, elementType); + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSParameterListStubImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSParameterListStubImpl.java index a9b32d7c..89957dd6 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSParameterListStubImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSParameterListStubImpl.java @@ -25,13 +25,11 @@ /** * @author Maxim.Mossienko - * Date: Mar 26, 2008 - * Time: 11:29:19 PM + * Date: Mar 26, 2008 + * Time: 11:29:19 PM */ -public class JSParameterListStubImpl extends StubBase implements JSParameterListStub -{ - public JSParameterListStubImpl(StubElement parent, IStubElementType elementType) - { - super(parent, elementType); - } +public class JSParameterListStubImpl extends StubBase implements JSParameterListStub { + public JSParameterListStubImpl(StubElement parent, IStubElementType elementType) { + super(parent, elementType); + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSParameterStubImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSParameterStubImpl.java index 45a00d67..dd72be9f 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSParameterStubImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSParameterStubImpl.java @@ -24,41 +24,37 @@ /** * @author Maxim.Mossienko - * Date: Mar 26, 2008 - * Time: 11:29:19 PM + * Date: Mar 26, 2008 + * Time: 11:29:19 PM */ -public class JSParameterStubImpl extends JSVariableStubBaseImpl implements JSParameterStub -{ - public static final int REST_MASK = LAST_USED_MASK << 1; - public static final int OPTIONAL_MASK = LAST_USED_MASK << 2; - - public JSParameterStubImpl(String name, - int flags, - String type, - String initial, - String qName, - StubElement parentStub, - IStubElementType elementType) - { - super(name, flags, type, initial, qName, parentStub, elementType); - } - - - public static int buildFlags(final JSParameter clazz) - { - final int i = JSVariableStubBaseImpl.buildFlags(clazz); - return i | (clazz.isRest() ? REST_MASK : 0) | (clazz.isOptional() ? OPTIONAL_MASK : 0); - } - - @Override - public boolean isRest() - { - return (myFlags & REST_MASK) != 0; - } - - @Override - public boolean isOptional() - { - return (myFlags & OPTIONAL_MASK) != 0; - } +public class JSParameterStubImpl extends JSVariableStubBaseImpl implements JSParameterStub { + public static final int REST_MASK = LAST_USED_MASK << 1; + public static final int OPTIONAL_MASK = LAST_USED_MASK << 2; + + public JSParameterStubImpl( + String name, + int flags, + String type, + String initial, + String qName, + StubElement parentStub, + IStubElementType elementType + ) { + super(name, flags, type, initial, qName, parentStub, elementType); + } + + public static int buildFlags(JSParameter clazz) { + int i = JSVariableStubBaseImpl.buildFlags(clazz); + return i | (clazz.isRest() ? REST_MASK : 0) | (clazz.isOptional() ? OPTIONAL_MASK : 0); + } + + @Override + public boolean isRest() { + return (myFlags & REST_MASK) != 0; + } + + @Override + public boolean isOptional() { + return (myFlags & OPTIONAL_MASK) != 0; + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSQualifiedObjectStubBase.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSQualifiedObjectStubBase.java index 39aaeb61..017793d0 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSQualifiedObjectStubBase.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSQualifiedObjectStubBase.java @@ -24,23 +24,26 @@ /** * @author Maxim.Mossienko - * Date: Mar 26, 2008 - * Time: 7:11:48 PM + * Date: Mar 26, 2008 + * Time: 7:11:48 PM */ -abstract class JSQualifiedObjectStubBase extends JSNamedObjectStubBase implements JSQualifiedStub -{ - protected final String myQualifiedName; +abstract class JSQualifiedObjectStubBase extends JSNamedObjectStubBase implements JSQualifiedStub { + protected final String myQualifiedName; - protected JSQualifiedObjectStubBase(String name, int flags, String qName, final StubElement parent, final IStubElementType elementType) - { - super(name, flags, parent, elementType); + protected JSQualifiedObjectStubBase( + String name, + int flags, + String qName, + StubElement parent, + IStubElementType elementType + ) { + super(name, flags, parent, elementType); - myQualifiedName = qName; - } + myQualifiedName = qName; + } - @Override - public String getQualifiedName() - { - return myQualifiedName; - } + @Override + public String getQualifiedName() { + return myQualifiedName; + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSReferenceListStubImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSReferenceListStubImpl.java index 4ba9b59c..e7af41a0 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSReferenceListStubImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSReferenceListStubImpl.java @@ -25,23 +25,23 @@ /** * @author Maxim.Mossienko - * Date: Jun 6, 2008 - * Time: 8:00:52 PM + * Date: Jun 6, 2008 + * Time: 8:00:52 PM */ -public class JSReferenceListStubImpl extends StubBase implements JSReferenceListStub -{ - private String[] myRefs; +public class JSReferenceListStubImpl extends StubBase implements JSReferenceListStub { + private String[] myRefs; - public JSReferenceListStubImpl(final String[] refs, final StubElement parentStub, final JSStubElementType type) - { - super(parentStub, type); - myRefs = refs; - } + public JSReferenceListStubImpl( + String[] refs, + StubElement parentStub, + JSStubElementType type + ) { + super(parentStub, type); + myRefs = refs; + } - @Override - public String[] getReferenceTexts() - { - return myRefs; - } + @Override + public String[] getReferenceTexts() { + return myRefs; + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSUseNamespaceDirectiveStubImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSUseNamespaceDirectiveStubImpl.java index 69afd05d..eb60c55c 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSUseNamespaceDirectiveStubImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSUseNamespaceDirectiveStubImpl.java @@ -25,22 +25,19 @@ /** * @author Maxim.Mossienko - * Date: Jun 6, 2008 - * Time: 8:00:52 PM + * Date: Jun 6, 2008 + * Time: 8:00:52 PM */ -public class JSUseNamespaceDirectiveStubImpl extends StubBase implements JSUseNamespaceDirectiveStub -{ - private String myNamespaceToUse; +public class JSUseNamespaceDirectiveStubImpl extends StubBase implements JSUseNamespaceDirectiveStub { + private String myNamespaceToUse; - public JSUseNamespaceDirectiveStubImpl(String namespaceToUse, StubElement parent, IStubElementType elementType) - { - super(parent, elementType); - myNamespaceToUse = namespaceToUse; - } + public JSUseNamespaceDirectiveStubImpl(String namespaceToUse, StubElement parent, IStubElementType elementType) { + super(parent, elementType); + myNamespaceToUse = namespaceToUse; + } - @Override - public String getNamespaceToUse() - { - return myNamespaceToUse; - } + @Override + public String getNamespaceToUse() { + return myNamespaceToUse; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSVarStatementStubImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSVarStatementStubImpl.java index 9fb1f69b..10c6233c 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSVarStatementStubImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSVarStatementStubImpl.java @@ -25,13 +25,11 @@ /** * @author Maxim.Mossienko - * Date: Mar 26, 2008 - * Time: 11:29:19 PM + * Date: Mar 26, 2008 + * Time: 11:29:19 PM */ -public class JSVarStatementStubImpl extends StubBase implements JSVarStatementStub -{ - public JSVarStatementStubImpl(StubElement parent, IStubElementType elementType) - { - super(parent, elementType); - } +public class JSVarStatementStubImpl extends StubBase implements JSVarStatementStub { + public JSVarStatementStubImpl(StubElement parent, IStubElementType elementType) { + super(parent, elementType); + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSVariableStubBaseImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSVariableStubBaseImpl.java index 898ade13..9e83b1e8 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSVariableStubBaseImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSVariableStubBaseImpl.java @@ -24,58 +24,57 @@ /** * @author Maxim.Mossienko - * Date: Mar 26, 2008 - * Time: 11:29:19 PM + * Date: Mar 26, 2008 + * Time: 11:29:19 PM */ -public abstract class JSVariableStubBaseImpl extends JSQualifiedObjectStubBase implements JSVariableStubBase -{ - private String myTypeString; - private static final int DEPRECATED_MASK = 1; - public static final int CONST_MASK = 2; - private static final int LOCAL_MASK = 4; - static final int LAST_USED_MASK = LOCAL_MASK; - private String myInitializerText; +public abstract class JSVariableStubBaseImpl extends JSQualifiedObjectStubBase implements JSVariableStubBase { + private String myTypeString; + private static final int DEPRECATED_MASK = 1; + public static final int CONST_MASK = 2; + private static final int LOCAL_MASK = 4; + static final int LAST_USED_MASK = LOCAL_MASK; + private String myInitializerText; - public JSVariableStubBaseImpl(final String name, int flags, String type, String initial, String qName, final StubElement parentStub, - final IStubElementType elementType) - { - super(name, flags, qName, parentStub, elementType); - myTypeString = type; - myInitializerText = initial; - } + public JSVariableStubBaseImpl( + String name, + int flags, + String type, + String initial, + String qName, + StubElement parentStub, + IStubElementType elementType + ) { + super(name, flags, qName, parentStub, elementType); + myTypeString = type; + myInitializerText = initial; + } - public static int buildFlags(final JSVariable clazz) - { - return (clazz.isDeprecated() ? DEPRECATED_MASK : 0) | (clazz.isConst() ? CONST_MASK : clazz.isLocal() ? LOCAL_MASK : 0); - } + public static int buildFlags(JSVariable clazz) { + return (clazz.isDeprecated() ? DEPRECATED_MASK : 0) | (clazz.isConst() ? CONST_MASK : clazz.isLocal() ? LOCAL_MASK : 0); + } - @Override - public String getTypeString() - { - return myTypeString; - } + @Override + public String getTypeString() { + return myTypeString; + } - @Override - public boolean isDeprecated() - { - return (myFlags & DEPRECATED_MASK) != 0; - } + @Override + public boolean isDeprecated() { + return (myFlags & DEPRECATED_MASK) != 0; + } - @Override - public boolean isConst() - { - return (myFlags & CONST_MASK) != 0; - } + @Override + public boolean isConst() { + return (myFlags & CONST_MASK) != 0; + } - @Override - public String getInitializerText() - { - return myInitializerText; - } + @Override + public String getInitializerText() { + return myInitializerText; + } - @Override - public boolean isLocal() - { - return (myFlags & LOCAL_MASK) != 0; - } + @Override + public boolean isLocal() { + return (myFlags & LOCAL_MASK) != 0; + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSVariableStubImpl.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSVariableStubImpl.java index a3745f3f..143dfdda 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSVariableStubImpl.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/stubs/impl/JSVariableStubImpl.java @@ -24,14 +24,19 @@ /** * @author Maxim.Mossienko - * Date: Mar 26, 2008 - * Time: 11:29:19 PM + * Date: Mar 26, 2008 + * Time: 11:29:19 PM */ -public class JSVariableStubImpl extends JSVariableStubBaseImpl implements JSVariableStub -{ - public JSVariableStubImpl(String name, int flags, String type, String initial, String qName, StubElement parentStub, - IStubElementType elementType) - { - super(name, flags, type, initial, qName, parentStub, elementType); - } +public class JSVariableStubImpl extends JSVariableStubBaseImpl implements JSVariableStub { + public JSVariableStubImpl( + String name, + int flags, + String type, + String initial, + String qName, + StubElement parentStub, + IStubElementType elementType + ) { + super(name, flags, type, initial, qName, parentStub, elementType); + } } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/util/JSLookupUtil.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/util/JSLookupUtil.java index df2a4e13..81704a96 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/util/JSLookupUtil.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/util/JSLookupUtil.java @@ -28,70 +28,63 @@ import consulo.language.icon.IconDescriptorUpdaters; import consulo.javascript.language.psi.JavaScriptType; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; -public class JSLookupUtil -{ - public static enum LookupPriority - { - NORMAL, - HIGHER, - HIGH, - HIGHEST - } +public class JSLookupUtil { + public static enum LookupPriority { + NORMAL, + HIGHER, + HIGH, + HIGHEST + } - @Nullable - @RequiredReadAction - public static LookupElement createLookupItem(@Nonnull PsiElement value, @Nonnull String name, @Nonnull LookupPriority priority) - { - LookupElementBuilder builder = LookupElementBuilder.create(name); - builder = builder.withIcon(IconDescriptorUpdaters.getIcon(value, Iconable.ICON_FLAG_VISIBILITY)); + @Nullable + @RequiredReadAction + public static LookupElement createLookupItem(@Nonnull PsiElement value, @Nonnull String name, @Nonnull LookupPriority priority) { + LookupElementBuilder builder = LookupElementBuilder.create(name); + builder = builder.withIcon(IconDescriptorUpdaters.getIcon(value, Iconable.ICON_FLAG_VISIBILITY)); - JSFunction function = value instanceof JSFunction ? (JSFunction) value : null; - if(value instanceof JSProperty) - { - JSExpression expression = ((JSProperty) value).getValue(); - function = expression instanceof JSFunctionExpression ? ((JSFunctionExpression) expression).getFunction() : null; - } + JSFunction function = value instanceof JSFunction fun ? fun : null; + if (value instanceof JSProperty property) { + JSExpression expression = property.getValue(); + function = expression instanceof JSFunctionExpression functionExpression ? functionExpression.getFunction() : null; + } - if(function != null) - { - JSParameterList parameterList = function.getParameterList(); - JSParameter[] jsParameters = parameterList == null ? JSParameter.EMPTY_ARRAY : parameterList.getParameters(); - builder = builder.withPresentableText(name + "(" + StringUtil.join(jsParameters, jsParameter -> - { - JavaScriptType type = jsParameter.getType(); - if(type != JavaScriptType.UNKNOWN) - { - return type.getPresentableText() + " " + jsParameter.getName(); - } - return jsParameter.getName(); - }, ", ") + ")"); - builder = builder.withInsertHandler(ParenthesesInsertHandler.getInstance(jsParameters.length > 0)); - } - else if(value instanceof JSProperty) - { - JavaScriptType type = ((JSProperty) value).getType(); - if(type != JavaScriptType.UNKNOWN) - { - builder = builder.withTypeText(type.getPresentableText()); - } - } - else if(value instanceof JSVariable) - { - JavaScriptType type = ((JSVariable) value).getType(); - if(type != JavaScriptType.UNKNOWN) - { - builder = builder.withTypeText(type.getPresentableText()); - } - } + if (function != null) { + JSParameterList parameterList = function.getParameterList(); + JSParameter[] jsParameters = parameterList == null ? JSParameter.EMPTY_ARRAY : parameterList.getParameters(); + builder = builder.withPresentableText( + name + "(" + StringUtil.join( + jsParameters, + jsParameter -> { + JavaScriptType type = jsParameter.getType(); + if (type != JavaScriptType.UNKNOWN) { + return type.getPresentableText() + " " + jsParameter.getName(); + } + return jsParameter.getName(); + }, ", " + ) + ")" + ); + builder = builder.withInsertHandler(ParenthesesInsertHandler.getInstance(jsParameters.length > 0)); + } + else if (value instanceof JSProperty property) { + JavaScriptType type = property.getType(); + if (type != JavaScriptType.UNKNOWN) { + builder = builder.withTypeText(type.getPresentableText()); + } + } + else if (value instanceof JSVariable variable) { + JavaScriptType type = variable.getType(); + if (type != JavaScriptType.UNKNOWN) { + builder = builder.withTypeText(type.getPresentableText()); + } + } - //builder = builder.withTailText(value.getContainingFile().getName(), true); - if(priority == LookupPriority.NORMAL) - { - return builder; - } - return PrioritizedLookupElement.withPriority(builder, priority.ordinal()); - } + //builder = builder.withTailText(value.getContainingFile().getName(), true); + if (priority == LookupPriority.NORMAL) { + return builder; + } + return PrioritizedLookupElement.withPriority(builder, priority.ordinal()); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/psi/util/JSUtils.java b/base-impl/src/main/java/com/intellij/lang/javascript/psi/util/JSUtils.java index b1e52c19..c74d193c 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/psi/util/JSUtils.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/psi/util/JSUtils.java @@ -33,196 +33,152 @@ /** * @author max */ -public class JSUtils -{ - public static boolean isLHSExpression(JSExpression expr) - { - if(expr instanceof JSDefinitionExpression) - { - expr = ((JSDefinitionExpression) expr).getExpression(); - } - - if(expr instanceof JSReferenceExpression) - { - return true; - } - - if(expr instanceof JSParenthesizedExpression) - { - return isLHSExpression(((JSParenthesizedExpression) expr).getInnerExpression()); - } - - if(expr instanceof JSIndexedPropertyAccessExpression) - { - return true; - } - - if(expr instanceof JSCallExpression) - { - return true; - } - - if(expr instanceof JSNewExpression) - { - return true; - } - - return false; - } - - public static boolean isNeedParenthesis(JSExpression oldExpr, JSExpression newExpr) - { - int priority = getExpressionPrecedence(newExpr); - final PsiElement parent = oldExpr.getParent(); - if(!(parent instanceof JSExpression)) - { - return false; - } - int parentPriority = getExpressionPrecedence((JSExpression) parent); - if(priority < parentPriority) - { - return true; - } - if(priority == parentPriority && parent instanceof JSBinaryExpression) - { - final IElementType operationSign = ((JSBinaryExpression) parent).getOperationSign(); - if(oldExpr != ((JSBinaryExpression) parent).getROperand()) - { - return false; - } - if(!ASSOC_OPERATIONS.contains(operationSign)) - { - return true; - } - - return (((JSBinaryExpression) newExpr).getOperationSign() != operationSign); - } - - return false; - } - - private static int getExpressionPrecedence(JSExpression expr) - { - IElementType i = expr.getNode().getElementType(); - if(i == ASSIGNMENT_EXPRESSION) - { - return 0; - } - else if(i == CONDITIONAL_EXPRESSION) - { - return 1; - } - else if(i == BINARY_EXPRESSION) - { - { - IElementType opType = ((JSBinaryExpression) expr).getOperationSign(); - if(opType == OROR) - { - return 2; - } - else if(opType == ANDAND) - { - return 3; - } - else if(opType == OR) - { - return 4; - } - else if(opType == XOR) - { - return 5; - } - else if(opType == AND) - { - return 6; - } - else if(EQUALITY_OPERATIONS.contains(opType)) - { - return 7; - } - else if(RELATIONAL_OPERATIONS.contains(opType)) - { - return 8; - } - else if(SHIFT_OPERATIONS.contains(opType)) - { - return 9; - } - else if(ADDITIVE_OPERATIONS.contains(opType)) - { - return 10; - } - else if(MULTIPLICATIVE_OPERATIONS.contains(opType)) - { - return 11; - } - } - - return 8; - } - else if(i == PREFIX_EXPRESSION) - { - return 12; - } - else if(i == POSTFIX_EXPRESSION) - { - return 13; - } - - return 14; - } - - public static PsiElement findStatementAnchor(final JSReferenceExpression referenceExpression, final PsiFile file) - { - PsiElement anchor = PsiTreeUtil.getParentOfType(referenceExpression, JSStatement.class); - - if(file instanceof XmlFile) - { - final XmlAttributeValue attributeValue = PsiTreeUtil.getParentOfType(referenceExpression, XmlAttributeValue.class); - - if(attributeValue != null) - { - XmlFile root = ((XmlFile) file); - if(root.getViewProvider() instanceof TemplateLanguageFileViewProvider) - { - final TemplateLanguageFileViewProvider viewProvider = (TemplateLanguageFileViewProvider) root.getViewProvider(); - final PsiFile psi = viewProvider.getPsi(viewProvider.getTemplateDataLanguage()); - if(psi instanceof XmlFile) - { - root = (XmlFile) psi; - } - } - - final XmlTag tag = root.getDocument().getRootTag(); - - if(tag != null) - { - final XmlTag headTag = tag.findFirstSubTag("head"); - - if(headTag != null) - { - final XmlTag scriptTag = headTag.findFirstSubTag("script"); - - if(scriptTag != null) - { - PsiElement statementInScript = PsiTreeUtil.getChildOfType(scriptTag, JSStatement.class); - if(statementInScript != null) - { - anchor = statementInScript; - } - else - { - final XmlTagChild tagChild = PsiTreeUtil.getChildOfType(scriptTag, XmlTagChild.class); - if(tagChild != null) - { - anchor = tagChild; - } - } - } - } - } - } - } - return anchor; - } +public class JSUtils { + public static boolean isLHSExpression(JSExpression expr) { + if (expr instanceof JSDefinitionExpression definition) { + expr = definition.getExpression(); + } + + if (expr instanceof JSReferenceExpression) { + return true; + } + + if (expr instanceof JSParenthesizedExpression parenthesizedExpression) { + return isLHSExpression(parenthesizedExpression.getInnerExpression()); + } + + if (expr instanceof JSIndexedPropertyAccessExpression) { + return true; + } + + if (expr instanceof JSCallExpression) { + return true; + } + + if (expr instanceof JSNewExpression) { + return true; + } + + return false; + } + + public static boolean isNeedParenthesis(JSExpression oldExpr, JSExpression newExpr) { + int priority = getExpressionPrecedence(newExpr); + PsiElement parent = oldExpr.getParent(); + if (!(parent instanceof JSExpression)) { + return false; + } + int parentPriority = getExpressionPrecedence((JSExpression)parent); + if (priority < parentPriority) { + return true; + } + if (priority == parentPriority && parent instanceof JSBinaryExpression binaryExpression) { + IElementType operationSign = binaryExpression.getOperationSign(); + if (oldExpr != binaryExpression.getROperand()) { + return false; + } + if (!ASSOC_OPERATIONS.contains(operationSign)) { + return true; + } + + return (((JSBinaryExpression)newExpr).getOperationSign() != operationSign); + } + + return false; + } + + private static int getExpressionPrecedence(JSExpression expr) { + IElementType i = expr.getNode().getElementType(); + if (i == ASSIGNMENT_EXPRESSION) { + return 0; + } + else if (i == CONDITIONAL_EXPRESSION) { + return 1; + } + else if (i == BINARY_EXPRESSION) { + IElementType opType = ((JSBinaryExpression)expr).getOperationSign(); + if (opType == OROR) { + return 2; + } + else if (opType == ANDAND) { + return 3; + } + else if (opType == OR) { + return 4; + } + else if (opType == XOR) { + return 5; + } + else if (opType == AND) { + return 6; + } + else if (EQUALITY_OPERATIONS.contains(opType)) { + return 7; + } + else if (RELATIONAL_OPERATIONS.contains(opType)) { + return 8; + } + else if (SHIFT_OPERATIONS.contains(opType)) { + return 9; + } + else if (ADDITIVE_OPERATIONS.contains(opType)) { + return 10; + } + else if (MULTIPLICATIVE_OPERATIONS.contains(opType)) { + return 11; + } + + return 8; + } + else if (i == PREFIX_EXPRESSION) { + return 12; + } + else if (i == POSTFIX_EXPRESSION) { + return 13; + } + + return 14; + } + + public static PsiElement findStatementAnchor(JSReferenceExpression referenceExpression, PsiFile file) { + PsiElement anchor = PsiTreeUtil.getParentOfType(referenceExpression, JSStatement.class); + + if (file instanceof XmlFile root) { + XmlAttributeValue attributeValue = PsiTreeUtil.getParentOfType(referenceExpression, XmlAttributeValue.class); + + if (attributeValue != null) { + if (root.getViewProvider() instanceof TemplateLanguageFileViewProvider) { + TemplateLanguageFileViewProvider viewProvider = (TemplateLanguageFileViewProvider)root.getViewProvider(); + PsiFile psi = viewProvider.getPsi(viewProvider.getTemplateDataLanguage()); + if (psi instanceof XmlFile) { + root = (XmlFile)psi; + } + } + + XmlTag tag = root.getDocument().getRootTag(); + + if (tag != null) { + XmlTag headTag = tag.findFirstSubTag("head"); + + if (headTag != null) { + XmlTag scriptTag = headTag.findFirstSubTag("script"); + + if (scriptTag != null) { + PsiElement statementInScript = PsiTreeUtil.getChildOfType(scriptTag, JSStatement.class); + if (statementInScript != null) { + anchor = statementInScript; + } + else { + XmlTagChild tagChild = PsiTreeUtil.getChildOfType(scriptTag, XmlTagChild.class); + if (tagChild != null) { + anchor = tagChild; + } + } + } + } + } + } + } + return anchor; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/search/JSClassInheritorsProvider.java b/base-impl/src/main/java/com/intellij/lang/javascript/search/JSClassInheritorsProvider.java index 1f7cd240..7ab22286 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/search/JSClassInheritorsProvider.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/search/JSClassInheritorsProvider.java @@ -26,11 +26,10 @@ import java.util.Collection; @ExtensionAPI(ComponentScope.APPLICATION) -public interface JSClassInheritorsProvider -{ - ExtensionPointName EP_NAME = ExtensionPointName.create(JSClassInheritorsProvider.class); +public interface JSClassInheritorsProvider { + ExtensionPointName EP_NAME = ExtensionPointName.create(JSClassInheritorsProvider.class); - Collection getImplementingClasses(String parentName, Project project, GlobalSearchScope scope); + Collection getImplementingClasses(String parentName, Project project, GlobalSearchScope scope); - Collection getExtendingClasses(String parentName, Project project, GlobalSearchScope scope); + Collection getExtendingClasses(String parentName, Project project, GlobalSearchScope scope); } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/search/JSClassSearch.java b/base-impl/src/main/java/com/intellij/lang/javascript/search/JSClassSearch.java index 9554517d..f755a218 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/search/JSClassSearch.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/search/JSClassSearch.java @@ -18,250 +18,244 @@ import com.intellij.lang.javascript.psi.JSClass; import com.intellij.lang.javascript.psi.JSReferenceList; +import consulo.annotation.access.RequiredReadAction; import consulo.application.util.function.CommonProcessors; -import consulo.application.util.function.Processor; import consulo.application.util.query.Query; import consulo.application.util.query.QueryExecutor; import consulo.application.util.query.QueryFactory; -import consulo.component.extension.Extensions; import consulo.content.scope.SearchScope; import consulo.javascript.language.psi.stub.JavaScriptIndexKeys; import consulo.language.psi.scope.GlobalSearchScope; import consulo.language.psi.stub.StubIndex; import consulo.language.psi.stub.StubIndexKey; import consulo.project.Project; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; import java.util.Collection; import java.util.HashSet; import java.util.Set; - -public abstract class JSClassSearch implements QueryExecutor -{ - public static class SearchParameters - { - private final JSClass myClass; - private final boolean myCheckDeepInheritance; - private final GlobalSearchScope myScope; - - public SearchParameters(final JSClass anClass, final boolean checkDeepInheritance, GlobalSearchScope scope) - { - myClass = anClass; - myCheckDeepInheritance = checkDeepInheritance; - myScope = scope; - } - - public JSClass getTargetClass() - { - return myClass; - } - - public boolean isCheckDeepInheritance() - { - return myCheckDeepInheritance; - } - - public GlobalSearchScope getScope() - { - return myScope; - } - } - - public static Query searchClassInheritors(final JSClass superClass, final boolean checkDeepInheritance) - { - final SearchParameters parameters = new SearchParameters(superClass, checkDeepInheritance, getUseScope(superClass)); - return CLASS_INHERITORS_QUERY_FACTORY.createUniqueResultsQuery(parameters); - } - - private static GlobalSearchScope getUseScope(JSClass superClass) - { - SearchScope searchScope = superClass.getUseScope(); - return (GlobalSearchScope) searchScope; - } - - public static Query searchInterfaceImplementations(final JSClass superClass, final boolean checkDeepInheritance) - { - final SearchParameters parameters = new SearchParameters(superClass, checkDeepInheritance, getUseScope(superClass)); - return INTERFACE_IMPLEMENTATIONS_QUERY_FACTORY.createUniqueResultsQuery(parameters); - } - - // implementation - private static final QueryFactory INTERFACE_IMPLEMENTATIONS_QUERY_FACTORY = new QueryFactory(); - private static final QueryFactory CLASS_INHERITORS_QUERY_FACTORY = new QueryFactory(); - private static final JSClassSearch OUR_CLASS_SEARCH_EXECUTOR; - - static - { - INTERFACE_IMPLEMENTATIONS_QUERY_FACTORY.registerExecutor(new JSClassSearch() - { - @Override - protected StubIndexKey getIndexKey() - { - return JavaScriptIndexKeys.IMPLEMENTED_INDEX; - } - - @Override - protected JSClass[] getSupers(final JSClass candidate) - { - return candidate.getImplementedInterfaces(); - } - - @Override - public boolean execute(@Nonnull final SearchParameters queryParameters, @Nonnull Processor consumer) - { - final Set visited = new HashSet(); // no abstract classes in ActionScript ! - - if(queryParameters.isCheckDeepInheritance()) - { - final Processor consumerCopy = consumer; - consumer = new Processor() - { - @Override - public boolean process(JSClass jsClass) - { - return consumerCopy.process(jsClass) && OUR_CLASS_SEARCH_EXECUTOR.processDirectInheritors(jsClass, this, false, visited, - queryParameters.getScope()); - } - }; - } - - final Processor consumerToUse = consumer; - final boolean b = processDirectInheritors(queryParameters.getTargetClass(), consumerToUse, queryParameters.isCheckDeepInheritance(), visited, - queryParameters.getScope()); - if(b) - { - return searchClassInheritors(queryParameters.getTargetClass(), queryParameters.isCheckDeepInheritance()).forEach(new Processor() - { - @Override - public boolean process(final JSClass jsClass) - { - return processDirectInheritors(jsClass, consumerToUse, queryParameters.isCheckDeepInheritance(), visited, queryParameters.getScope()); - } - }); - } - return b; - } - - @Override - protected Collection getInheritors(JSClassInheritorsProvider provider, String parentName, Project project, GlobalSearchScope scope) - { - return provider.getImplementingClasses(parentName, project, scope); - } - }); - - CLASS_INHERITORS_QUERY_FACTORY.registerExecutor(OUR_CLASS_SEARCH_EXECUTOR = new JSClassSearch() - { - @Override - protected StubIndexKey getIndexKey() - { - return JavaScriptIndexKeys.EXTENDS_INDEX; - } - - @Override - protected JSClass[] getSupers(final JSClass candidate) - { - return candidate.getSuperClasses(); - } - - @Override - protected Collection getInheritors(JSClassInheritorsProvider provider, String parentName, Project project, GlobalSearchScope scope) - { - return provider.getExtendingClasses(parentName, project, scope); - } - - }); - } - - @Override - public boolean execute(@Nonnull final SearchParameters queryParameters, @Nonnull final Processor consumer) - { - return processDirectInheritors(queryParameters.getTargetClass(), consumer, queryParameters.isCheckDeepInheritance(), null, - queryParameters.getScope()); - } - - protected boolean processDirectInheritors(final JSClass superClass, final Processor consumer, final boolean checkDeep, Set processed, final GlobalSearchScope scope) - { - if(processed != null) - { - if(processed.contains(superClass)) - { - return true; - } - } - else - { - processed = new HashSet(); - } - - processed.add(superClass); - Project project = superClass.getProject(); - final String name = superClass.getName(); - if(name == null) - { - return true; - } - - final Set temp = processed; - final Processor processor = new Processor() - { - @Override - public boolean process(JSClass candidate) - { - final JSClass[] classes = getSupers(candidate); - if(classes != null) - { - for(JSClass superClassCandidate : classes) - { - if(superClassCandidate.isEquivalentTo(superClass)) - { - if(!consumer.process(candidate)) - { - return false; - } - if(checkDeep && !processDirectInheritors(candidate, consumer, checkDeep, temp, scope)) - { - return false; - } - } - } - } - - return true; - } - }; - - CommonProcessors.CollectProcessor collectProcessor = new CommonProcessors.CollectProcessor<>(); - - StubIndex.getInstance().processElements(getIndexKey(), name, project, scope, JSReferenceList.class, collectProcessor); - - for(JSReferenceList referenceList : collectProcessor.getResults()) - { - JSClass parent = (JSClass) referenceList.getParent(); - if(!processor.process(parent)) - { - return false; - } - } - - for(JSClassInheritorsProvider provider : Extensions.getExtensions(JSClassInheritorsProvider.EP_NAME)) - { - Collection inheritors = getInheritors(provider, name, project, scope); - for(JSClass inheritor : inheritors) - { - if(!processor.process(inheritor)) - { - return false; - } - } - } - return true; - } - - protected abstract Collection getInheritors(JSClassInheritorsProvider provider, String parentName, Project project, - GlobalSearchScope scope); - - protected abstract StubIndexKey getIndexKey(); - - protected abstract JSClass[] getSupers(final JSClass candidate); +import java.util.function.Predicate; + +public abstract class JSClassSearch implements QueryExecutor { + public static class SearchParameters { + private final JSClass myClass; + private final boolean myCheckDeepInheritance; + private final GlobalSearchScope myScope; + + public SearchParameters(JSClass anClass, boolean checkDeepInheritance, GlobalSearchScope scope) { + myClass = anClass; + myCheckDeepInheritance = checkDeepInheritance; + myScope = scope; + } + + public JSClass getTargetClass() { + return myClass; + } + + public boolean isCheckDeepInheritance() { + return myCheckDeepInheritance; + } + + public GlobalSearchScope getScope() { + return myScope; + } + } + + public static Query searchClassInheritors(JSClass superClass, boolean checkDeepInheritance) { + SearchParameters parameters = new SearchParameters(superClass, checkDeepInheritance, getUseScope(superClass)); + return CLASS_INHERITORS_QUERY_FACTORY.createUniqueResultsQuery(parameters); + } + + private static GlobalSearchScope getUseScope(JSClass superClass) { + SearchScope searchScope = superClass.getUseScope(); + return (GlobalSearchScope)searchScope; + } + + public static Query searchInterfaceImplementations(JSClass superClass, boolean checkDeepInheritance) { + SearchParameters parameters = new SearchParameters(superClass, checkDeepInheritance, getUseScope(superClass)); + return INTERFACE_IMPLEMENTATIONS_QUERY_FACTORY.createUniqueResultsQuery(parameters); + } + + // implementation + private static final QueryFactory INTERFACE_IMPLEMENTATIONS_QUERY_FACTORY = new QueryFactory<>(); + private static final QueryFactory CLASS_INHERITORS_QUERY_FACTORY = new QueryFactory<>(); + private static final JSClassSearch CLASS_SEARCH_EXECUTOR; + + static { + INTERFACE_IMPLEMENTATIONS_QUERY_FACTORY.registerExecutor(new JSClassSearch() { + @Override + protected StubIndexKey getIndexKey() { + return JavaScriptIndexKeys.IMPLEMENTED_INDEX; + } + + @Override + protected JSClass[] getSupers(JSClass candidate) { + return candidate.getImplementedInterfaces(); + } + + @Override + @RequiredReadAction + public boolean execute(@Nonnull SearchParameters queryParameters, @Nonnull Predicate consumer) { + Set visited = new HashSet<>(); // no abstract classes in ActionScript ! + + if (queryParameters.isCheckDeepInheritance()) { + Predicate consumerCopy = consumer; + consumer = new Predicate<>() { + @Override + @RequiredReadAction + public boolean test(JSClass jsClass) { + return consumerCopy.test(jsClass) && CLASS_SEARCH_EXECUTOR.processDirectInheritors( + jsClass, + this, + false, + visited, + queryParameters.getScope() + ); + } + }; + } + + Predicate consumerToUse = consumer; + boolean b = processDirectInheritors( + queryParameters.getTargetClass(), + consumerToUse, + queryParameters.isCheckDeepInheritance(), + visited, + queryParameters.getScope() + ); + if (b) { + return searchClassInheritors( + queryParameters.getTargetClass(), + queryParameters.isCheckDeepInheritance() + ).forEach((Predicate)jsClass -> processDirectInheritors( + jsClass, + consumerToUse, + queryParameters.isCheckDeepInheritance(), + visited, + queryParameters.getScope() + )); + } + return b; + } + + @Override + protected Collection getInheritors( + JSClassInheritorsProvider provider, + String parentName, + Project project, + GlobalSearchScope scope + ) { + return provider.getImplementingClasses(parentName, project, scope); + } + }); + + CLASS_INHERITORS_QUERY_FACTORY.registerExecutor(CLASS_SEARCH_EXECUTOR = new JSClassSearch() { + @Override + protected StubIndexKey getIndexKey() { + return JavaScriptIndexKeys.EXTENDS_INDEX; + } + + @Override + protected JSClass[] getSupers(JSClass candidate) { + return candidate.getSuperClasses(); + } + + @Override + protected Collection getInheritors( + JSClassInheritorsProvider provider, + String parentName, + Project project, + GlobalSearchScope scope + ) { + return provider.getExtendingClasses(parentName, project, scope); + } + + }); + } + + @Override + @RequiredReadAction + public boolean execute(@Nonnull SearchParameters queryParameters, @Nonnull Predicate consumer) { + return processDirectInheritors( + queryParameters.getTargetClass(), + consumer, + queryParameters.isCheckDeepInheritance(), + null, + queryParameters.getScope() + ); + } + + @RequiredReadAction + protected boolean processDirectInheritors( + JSClass superClass, + Predicate consumer, + boolean checkDeep, + Set processed, + GlobalSearchScope scope + ) { + if (processed != null) { + if (processed.contains(superClass)) { + return true; + } + } + else { + processed = new HashSet<>(); + } + + processed.add(superClass); + Project project = superClass.getProject(); + String name = superClass.getName(); + if (name == null) { + return true; + } + + Set temp = processed; + Predicate processor = candidate -> { + JSClass[] classes = getSupers(candidate); + if (classes != null) { + for (JSClass superClassCandidate : classes) { + if (superClassCandidate.isEquivalentTo(superClass)) { + if (!consumer.test(candidate) + || checkDeep && !processDirectInheritors(candidate, consumer, checkDeep, temp, scope)) { + return false; + } + } + } + } + + return true; + }; + + CommonProcessors.CollectProcessor collectProcessor = new CommonProcessors.CollectProcessor<>(); + + StubIndex.getInstance().processElements(getIndexKey(), name, project, scope, JSReferenceList.class, collectProcessor); + + for (JSReferenceList referenceList : collectProcessor.getResults()) { + JSClass parent = (JSClass)referenceList.getParent(); + if (!processor.test(parent)) { + return false; + } + } + + for (JSClassInheritorsProvider provider : JSClassInheritorsProvider.EP_NAME.getExtensionList()) { + Collection inheritors = getInheritors(provider, name, project, scope); + for (JSClass inheritor : inheritors) { + if (!processor.test(inheritor)) { + return false; + } + } + } + return true; + } + + protected abstract Collection getInheritors( + JSClassInheritorsProvider provider, + String parentName, + Project project, + GlobalSearchScope scope + ); + + protected abstract StubIndexKey getIndexKey(); + + protected abstract JSClass[] getSupers(JSClass candidate); } \ No newline at end of file diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSAttributeElementType.java b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSAttributeElementType.java index 5cac7445..ef2e5db0 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSAttributeElementType.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSAttributeElementType.java @@ -19,7 +19,7 @@ import java.io.IOException; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.ASTNode; @@ -36,47 +36,40 @@ /** * @author Maxim.Mossienko - * Date: Mar 25, 2008 - * Time: 10:30:20 PM + * Date: Mar 25, 2008 + * Time: 10:30:20 PM */ -public class JSAttributeElementType extends JSStubElementType -{ - public JSAttributeElementType() - { - super("ATTRIBUTE"); - } +public class JSAttributeElementType extends JSStubElementType { + public JSAttributeElementType() { + super("ATTRIBUTE"); + } - @Nonnull - @Override - public PsiElement createElement(@Nonnull ASTNode astNode) - { - return new JSAttributeImpl(astNode); - } + @Nonnull + @Override + public PsiElement createElement(@Nonnull ASTNode astNode) { + return new JSAttributeImpl(astNode); + } - @Override - public JSAttribute createPsi(@Nonnull JSAttributeStub stub) - { - return new JSAttributeImpl(stub); - } + @Override + public JSAttribute createPsi(@Nonnull JSAttributeStub stub) { + return new JSAttributeImpl(stub); + } - @RequiredReadAction - @Override - public JSAttributeStub createStub(@Nonnull JSAttribute psi, StubElement parentStub) - { - return new JSAttributeStubImpl(psi.getName(), 0, parentStub); - } + @RequiredReadAction + @Override + public JSAttributeStub createStub(@Nonnull JSAttribute psi, StubElement parentStub) { + return new JSAttributeStubImpl(psi.getName(), 0, parentStub); + } - @Override - public void serialize(@Nonnull JSAttributeStub stub, @Nonnull StubOutputStream dataStream) throws IOException - { - dataStream.writeName(stub.getName()); - } + @Override + public void serialize(@Nonnull JSAttributeStub stub, @Nonnull StubOutputStream dataStream) throws IOException { + dataStream.writeName(stub.getName()); + } - @Nonnull - @Override - public JSAttributeStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException - { - StringRef name = dataStream.readName(); - return new JSAttributeStubImpl(StringRef.toString(name), 0, parentStub); - } + @Nonnull + @Override + public JSAttributeStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException { + StringRef name = dataStream.readName(); + return new JSAttributeStubImpl(StringRef.toString(name), 0, parentStub); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSAttributeListElementType.java b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSAttributeListElementType.java index 72535cd1..211e5976 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSAttributeListElementType.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSAttributeListElementType.java @@ -30,56 +30,50 @@ import consulo.language.psi.stub.StubInputStream; import consulo.language.psi.stub.StubOutputStream; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; + import java.io.IOException; /** * @author Maxim.Mossienko - * Date: Mar 25, 2008 - * Time: 10:30:17 PM + * Date: Mar 25, 2008 + * Time: 10:30:17 PM */ -public class JSAttributeListElementType extends JSStubElementType -{ - public JSAttributeListElementType() - { - super("ATTRIBUTE_LIST"); - } +public class JSAttributeListElementType extends JSStubElementType { + public JSAttributeListElementType() { + super("ATTRIBUTE_LIST"); + } - @Nonnull - @Override - public PsiElement createElement(@Nonnull ASTNode astNode) - { - return new JSAttributeListImpl(astNode); - } + @Nonnull + @Override + public PsiElement createElement(@Nonnull ASTNode astNode) { + return new JSAttributeListImpl(astNode); + } - @Override - public JSAttributeList createPsi(@Nonnull JSAttributeListStub stub) - { - return new JSAttributeListImpl(stub); - } + @Override + public JSAttributeList createPsi(@Nonnull JSAttributeListStub stub) { + return new JSAttributeListImpl(stub); + } - @RequiredReadAction - @Override - public JSAttributeListStub createStub(@Nonnull JSAttributeList psi, StubElement parentStub) - { - String namespace = psi.getNamespace(); - int flags = JSAttributeListStubImpl.getFlags(psi); - return new JSAttributeListStubImpl(namespace, flags, parentStub, this); - } + @RequiredReadAction + @Override + public JSAttributeListStub createStub(@Nonnull JSAttributeList psi, StubElement parentStub) { + String namespace = psi.getNamespace(); + int flags = JSAttributeListStubImpl.getFlags(psi); + return new JSAttributeListStubImpl(namespace, flags, parentStub, this); + } - @Override - public void serialize(@Nonnull JSAttributeListStub stub, @Nonnull StubOutputStream dataStream) throws IOException - { - dataStream.writeName(stub.getNamespace()); - dataStream.writeInt(stub.getFlags()); - } + @Override + public void serialize(@Nonnull JSAttributeListStub stub, @Nonnull StubOutputStream dataStream) throws IOException { + dataStream.writeName(stub.getNamespace()); + dataStream.writeInt(stub.getFlags()); + } - @Nonnull - @Override - public JSAttributeListStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException - { - StringRef namespaceRef = dataStream.readName(); - int i = dataStream.readInt(); - return new JSAttributeListStubImpl(StringRef.toString(namespaceRef), i, parentStub, this); - } + @Nonnull + @Override + public JSAttributeListStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException { + StringRef namespaceRef = dataStream.readName(); + int i = dataStream.readInt(); + return new JSAttributeListStubImpl(StringRef.toString(namespaceRef), i, parentStub, this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSAttributeNameValuePairType.java b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSAttributeNameValuePairType.java index 683be6c4..8a7e8da8 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSAttributeNameValuePairType.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSAttributeNameValuePairType.java @@ -19,7 +19,7 @@ import java.io.IOException; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; import consulo.annotation.access.RequiredReadAction; import com.intellij.lang.javascript.psi.JSAttributeNameValuePair; @@ -36,51 +36,44 @@ /** * @author Maxim.Mossienko - * Date: Jun 8, 2008 - * Time: 6:20:05 PM + * Date: Jun 8, 2008 + * Time: 6:20:05 PM */ -public class JSAttributeNameValuePairType extends JSStubElementType -{ - public JSAttributeNameValuePairType() - { - super("ATTRIBUTE_NAME_VALUE_PAIR"); - } +public class JSAttributeNameValuePairType extends JSStubElementType { + public JSAttributeNameValuePairType() { + super("ATTRIBUTE_NAME_VALUE_PAIR"); + } - @Nonnull - @Override - public PsiElement createElement(@Nonnull ASTNode astNode) - { - return new JSAttributeNameValuePairImpl(astNode); - } + @Nonnull + @Override + public PsiElement createElement(@Nonnull ASTNode astNode) { + return new JSAttributeNameValuePairImpl(astNode); + } - @Override - public JSAttributeNameValuePair createPsi(@Nonnull JSAttributeNameValuePairStub stub) - { - return new JSAttributeNameValuePairImpl(stub); - } + @Override + public JSAttributeNameValuePair createPsi(@Nonnull JSAttributeNameValuePairStub stub) { + return new JSAttributeNameValuePairImpl(stub); + } - @RequiredReadAction - @Override - public JSAttributeNameValuePairStub createStub(@Nonnull JSAttributeNameValuePair psi, StubElement parentStub) - { - String name = psi.getName(); - String simpleValue = psi.getSimpleValue(); - return new JSAttributeNameValuePairStubImpl(name, simpleValue, parentStub); - } + @RequiredReadAction + @Override + public JSAttributeNameValuePairStub createStub(@Nonnull JSAttributeNameValuePair psi, StubElement parentStub) { + String name = psi.getName(); + String simpleValue = psi.getSimpleValue(); + return new JSAttributeNameValuePairStubImpl(name, simpleValue, parentStub); + } - @Override - public void serialize(@Nonnull JSAttributeNameValuePairStub stub, @Nonnull StubOutputStream dataStream) throws IOException - { - dataStream.writeName(stub.getName()); - dataStream.writeName(stub.getValue()); - } + @Override + public void serialize(@Nonnull JSAttributeNameValuePairStub stub, @Nonnull StubOutputStream dataStream) throws IOException { + dataStream.writeName(stub.getName()); + dataStream.writeName(stub.getValue()); + } - @Nonnull - @Override - public JSAttributeNameValuePairStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException - { - StringRef name = dataStream.readName(); - StringRef value = dataStream.readName(); - return new JSAttributeNameValuePairStubImpl(StringRef.toString(name), StringRef.toString(value), parentStub); - } + @Nonnull + @Override + public JSAttributeNameValuePairStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException { + StringRef name = dataStream.readName(); + StringRef value = dataStream.readName(); + return new JSAttributeNameValuePairStubImpl(StringRef.toString(name), StringRef.toString(value), parentStub); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSClassElementType.java b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSClassElementType.java index 78a1b51f..d67a589b 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSClassElementType.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSClassElementType.java @@ -32,71 +32,62 @@ import consulo.language.psi.stub.StubInputStream; import consulo.language.psi.stub.StubOutputStream; import consulo.util.lang.StringUtil; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; import java.io.IOException; /** * @author Maxim.Mossienko * @since 10:30:14 PM Mar 25, 2008 */ -public class JSClassElementType extends JSQualifiedStubElementType -{ - public JSClassElementType() - { - super("CLASS"); - } +public class JSClassElementType extends JSQualifiedStubElementType { + public JSClassElementType() { + super("CLASS"); + } - @Override - public void indexStub(@Nonnull JSClassStub stub, @Nonnull IndexSink sink) - { - super.indexStub(stub, sink); + @Override + public void indexStub(@Nonnull JSClassStub stub, @Nonnull IndexSink sink) { + super.indexStub(stub, sink); - String name = stub.getName(); - if(!StringUtil.isEmpty(name)) - { - sink.occurrence(JavaScriptIndexKeys.CLASSES_BY_NAME, name); - } - } + String name = stub.getName(); + if (!StringUtil.isEmpty(name)) { + sink.occurrence(JavaScriptIndexKeys.CLASSES_BY_NAME, name); + } + } - @Nonnull - @Override - public PsiElement createElement(@Nonnull ASTNode astNode) - { - return new JSClassImpl(astNode); - } + @Nonnull + @Override + public PsiElement createElement(@Nonnull ASTNode astNode) { + return new JSClassImpl(astNode); + } - @Override - public JSClass createPsi(@Nonnull JSClassStub stub) - { - return new JSClassImpl(stub, this); - } + @Override + public JSClass createPsi(@Nonnull JSClassStub stub) { + return new JSClassImpl(stub, this); + } - @RequiredReadAction - @Override - public JSClassStub createStub(@Nonnull JSClass psi, StubElement parentStub) - { - String name = psi.getName(); - int flags = JSClassStubImpl.getFlags(psi); - String qualifiedName = psi.getQualifiedName(); - return new JSClassStubImpl(name, flags, qualifiedName, parentStub, this); - } + @RequiredReadAction + @Override + public JSClassStub createStub(@Nonnull JSClass psi, StubElement parentStub) { + String name = psi.getName(); + int flags = JSClassStubImpl.getFlags(psi); + String qualifiedName = psi.getQualifiedName(); + return new JSClassStubImpl(name, flags, qualifiedName, parentStub, this); + } - @Override - public void serialize(@Nonnull JSClassStub stub, @Nonnull StubOutputStream dataStream) throws IOException - { - dataStream.writeName(stub.getName()); - dataStream.writeName(stub.getQualifiedName()); - dataStream.writeInt(stub.getFlags()); - } + @Override + public void serialize(@Nonnull JSClassStub stub, @Nonnull StubOutputStream dataStream) throws IOException { + dataStream.writeName(stub.getName()); + dataStream.writeName(stub.getQualifiedName()); + dataStream.writeInt(stub.getFlags()); + } - @Nonnull - @Override - public JSClassStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException - { - StringRef nameRef = dataStream.readName(); - StringRef qualifiedRef = dataStream.readName(); - int flags = dataStream.readInt(); - return new JSClassStubImpl(StringRef.toString(nameRef), flags, StringRef.toString(qualifiedRef), parentStub, this); - } + @Nonnull + @Override + public JSClassStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException { + StringRef nameRef = dataStream.readName(); + StringRef qualifiedRef = dataStream.readName(); + int flags = dataStream.readInt(); + return new JSClassStubImpl(StringRef.toString(nameRef), flags, StringRef.toString(qualifiedRef), parentStub, this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSFileElementType.java b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSFileElementType.java index a213b251..ab2a97e2 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSFileElementType.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSFileElementType.java @@ -17,6 +17,7 @@ package com.intellij.lang.javascript.types; import com.intellij.lang.javascript.psi.JSFile; +import consulo.annotation.access.RequiredReadAction; import consulo.index.io.StringRef; import consulo.language.psi.stub.*; import consulo.javascript.index.JavaScriptIndexer; @@ -25,75 +26,59 @@ import consulo.language.Language; import consulo.language.psi.PsiFile; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; + import java.io.IOException; /** * @author peter */ -public class JSFileElementType extends IStubFileElementType -{ - public JSFileElementType(final Language language) - { - super(language); - } +public class JSFileElementType extends IStubFileElementType { + public JSFileElementType(Language language) { + super(language); + } - @Override - public void indexStub(@Nonnull final JSFileStub stub, @Nonnull final IndexSink sink) - { - for(JavaScriptIndexer javaScriptIndexer : JavaScriptIndexer.EP_NAME.getExtensionList()) - { - javaScriptIndexer.indexFile(stub, sink); - } - } + @Override + public void indexStub(@Nonnull JSFileStub stub, @Nonnull IndexSink sink) { + JavaScriptIndexer.EP_NAME.forEachExtensionSafe(it -> it.indexFile(stub, sink)); + } - @Override - public StubBuilder getBuilder() - { - return new DefaultStubBuilder() - { - @Nonnull - @Override - protected StubElement createStubForFile(@Nonnull PsiFile file) - { - if(file instanceof JSFile) - { - return new JSFileStubImpl((JSFile) file, file.getName()); - } - return super.createStubForFile(file); - } - }; - } + @Override + public StubBuilder getBuilder() { + return new DefaultStubBuilder() { + @Nonnull + @Override + @RequiredReadAction + protected StubElement createStubForFile(@Nonnull PsiFile file) { + return file instanceof JSFile jsFile + ? new JSFileStubImpl(jsFile, file.getName()) + : super.createStubForFile(file); + } + }; + } - @Override - public void serialize(@Nonnull JSFileStub stub, @Nonnull StubOutputStream dataStream) throws IOException - { - dataStream.writeName(stub.getName()); - } + @Override + public void serialize(@Nonnull JSFileStub stub, @Nonnull StubOutputStream dataStream) throws IOException { + dataStream.writeName(stub.getName()); + } - @Nonnull - @Override - public JSFileStub deserialize(@Nonnull final StubInputStream dataStream, final StubElement parentStub) throws IOException - { - StringRef name = dataStream.readName(); - return new JSFileStubImpl(null, name); - } + @Nonnull + @Override + public JSFileStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException { + StringRef name = dataStream.readName(); + return new JSFileStubImpl(null, name); + } - @Nonnull - @Override - public String getExternalId() - { - return getLanguage() + ":" + toString(); - } + @Nonnull + @Override + public String getExternalId() { + return getLanguage() + ":" + toString(); + } - @Override - public int getStubVersion() - { - int version = 45; - for(JavaScriptIndexer javaScriptIndexer : JavaScriptIndexer.EP_NAME.getExtensionList()) - { - version += javaScriptIndexer.getVersion(); - } - return version; - } + @Override + public int getStubVersion() { + int[] version = new int[]{48}; + JavaScriptIndexer.EP_NAME.forEachExtensionSafe(javaScriptIndexer -> version[0]++); + return version[0]; + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSFunctionElementType.java b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSFunctionElementType.java index b39d92e0..71997c1c 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSFunctionElementType.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSFunctionElementType.java @@ -19,7 +19,7 @@ import java.io.IOException; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; import consulo.annotation.access.RequiredReadAction; import com.intellij.lang.javascript.psi.JSFunction; @@ -34,63 +34,58 @@ /** * @author Maxim.Mossienko - * Date: Mar 25, 2008 - * Time: 10:50:34 PM + * Date: Mar 25, 2008 + * Time: 10:50:34 PM */ -public abstract class JSFunctionElementType extends JSQualifiedStubElementType -{ - public JSFunctionElementType(@Nonnull String name) - { - super(name); - } +public abstract class JSFunctionElementType extends JSQualifiedStubElementType { + public JSFunctionElementType(@Nonnull String name) { + super(name); + } - @Override - protected boolean doIndexName(JSFunctionStub stub, final String name, final String fqn) - { - final IStubElementType stubType = stub.getParentStub().getStubType(); + @Override + protected boolean doIndexName(JSFunctionStub stub, String name, String fqn) { + IStubElementType stubType = stub.getParentStub().getStubType(); - if(stubType instanceof JSPackageStatementElementType || stubType == null) - { - return true; - } - return false; - } + return stubType instanceof JSPackageStatementElementType || stubType == null; + } - @Override - protected boolean doIndexQualifiedName(JSFunctionStub stub, String name, String fqn) - { - return doIndexName(stub, name, fqn); - } + @Override + protected boolean doIndexQualifiedName(JSFunctionStub stub, String name, String fqn) { + return doIndexName(stub, name, fqn); + } - @RequiredReadAction - @Override - public JSFunctionStub createStub(@Nonnull JSFunction psi, StubElement parentStub) - { - String name = psi.getName(); - String qualifiedName = psi.getQualifiedName(); - String returnTypeString = psi.getReturnTypeString(); - int flags = JSFunctionStubImpl.buildFlags(psi); - return new JSFunctionStubImpl(name, flags, qualifiedName, returnTypeString, parentStub, this); - } + @RequiredReadAction + @Override + public JSFunctionStub createStub(@Nonnull JSFunction psi, StubElement parentStub) { + String name = psi.getName(); + String qualifiedName = psi.getQualifiedName(); + String returnTypeString = psi.getReturnTypeString(); + int flags = JSFunctionStubImpl.buildFlags(psi); + return new JSFunctionStubImpl(name, flags, qualifiedName, returnTypeString, parentStub, this); + } - @Override - public void serialize(@Nonnull JSFunctionStub stub, @Nonnull StubOutputStream dataStream) throws IOException - { - dataStream.writeName(stub.getName()); - dataStream.writeName(stub.getQualifiedName()); - dataStream.writeName(stub.getReturnTypeString()); - dataStream.writeVarInt(stub.getFlags()); - } + @Override + public void serialize(@Nonnull JSFunctionStub stub, @Nonnull StubOutputStream dataStream) throws IOException { + dataStream.writeName(stub.getName()); + dataStream.writeName(stub.getQualifiedName()); + dataStream.writeName(stub.getReturnTypeString()); + dataStream.writeVarInt(stub.getFlags()); + } - @Nonnull - @Override - public JSFunctionStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException - { - StringRef nameRef = dataStream.readName(); - StringRef qualifiedRef = dataStream.readName(); - StringRef returnTypeRef = dataStream.readName(); - int flags = dataStream.readVarInt(); - return new JSFunctionStubImpl(StringRef.toString(nameRef), flags, StringRef.toString(qualifiedRef), StringRef.toString(returnTypeRef), - parentStub, this); - } + @Nonnull + @Override + public JSFunctionStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException { + StringRef nameRef = dataStream.readName(); + StringRef qualifiedRef = dataStream.readName(); + StringRef returnTypeRef = dataStream.readName(); + int flags = dataStream.readVarInt(); + return new JSFunctionStubImpl( + StringRef.toString(nameRef), + flags, + StringRef.toString(qualifiedRef), + StringRef.toString(returnTypeRef), + parentStub, + this + ); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSImportStatementElementType.java b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSImportStatementElementType.java index 56af7669..4b1e5ab8 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSImportStatementElementType.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSImportStatementElementType.java @@ -19,7 +19,7 @@ import java.io.IOException; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; import consulo.annotation.access.RequiredReadAction; import com.intellij.lang.javascript.psi.JSImportStatement; @@ -36,48 +36,41 @@ /** * @author Maxim.Mossienko - * Date: Jun 6, 2008 - * Time: 7:49:18 PM + * Date: Jun 6, 2008 + * Time: 7:49:18 PM */ -public class JSImportStatementElementType extends JSStubElementType -{ - public JSImportStatementElementType() - { - super("IMPORT_STATEMENT"); - } +public class JSImportStatementElementType extends JSStubElementType { + public JSImportStatementElementType() { + super("IMPORT_STATEMENT"); + } - @Nonnull - @Override - public PsiElement createElement(@Nonnull ASTNode astNode) - { - return new JSImportStatementImpl(astNode); - } + @Nonnull + @Override + public PsiElement createElement(@Nonnull ASTNode astNode) { + return new JSImportStatementImpl(astNode); + } - @Override - public JSImportStatement createPsi(@Nonnull JSImportStatementStub stub) - { - return new JSImportStatementImpl(stub); - } + @Override + public JSImportStatement createPsi(@Nonnull JSImportStatementStub stub) { + return new JSImportStatementImpl(stub); + } - @RequiredReadAction - @Override - public JSImportStatementStub createStub(@Nonnull JSImportStatement psi, StubElement parentStub) - { - String importText = psi.getImportText(); - return new JSImportStatementStubImpl(importText, parentStub, this); - } + @RequiredReadAction + @Override + public JSImportStatementStub createStub(@Nonnull JSImportStatement psi, StubElement parentStub) { + String importText = psi.getImportText(); + return new JSImportStatementStubImpl(importText, parentStub, this); + } - @Override - public void serialize(@Nonnull JSImportStatementStub stub, @Nonnull StubOutputStream dataStream) throws IOException - { - dataStream.writeName(stub.getImportText()); - } + @Override + public void serialize(@Nonnull JSImportStatementStub stub, @Nonnull StubOutputStream dataStream) throws IOException { + dataStream.writeName(stub.getImportText()); + } - @Nonnull - @Override - public JSImportStatementStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException - { - StringRef importText = dataStream.readName(); - return new JSImportStatementStubImpl(StringRef.toString(importText), parentStub, this); - } + @Nonnull + @Override + public JSImportStatementStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException { + StringRef importText = dataStream.readName(); + return new JSImportStatementStubImpl(StringRef.toString(importText), parentStub, this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSIncludeDirectiveElementType.java b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSIncludeDirectiveElementType.java index 25e9bd7f..2fada8f3 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSIncludeDirectiveElementType.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSIncludeDirectiveElementType.java @@ -19,7 +19,7 @@ import java.io.IOException; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; import consulo.annotation.access.RequiredReadAction; import consulo.index.io.StringRef; @@ -36,48 +36,41 @@ /** * @author Maxim.Mossienko - * Date: Jun 7, 2008 - * Time: 9:23:54 PM + * Date: Jun 7, 2008 + * Time: 9:23:54 PM */ -public class JSIncludeDirectiveElementType extends JSStubElementType -{ - public JSIncludeDirectiveElementType() - { - super("INCLUDE_DIRECTIVE"); - } +public class JSIncludeDirectiveElementType extends JSStubElementType { + public JSIncludeDirectiveElementType() { + super("INCLUDE_DIRECTIVE"); + } - @Override - public void serialize(@Nonnull JSIncludeDirectiveStub stub, @Nonnull StubOutputStream dataStream) throws IOException - { - dataStream.writeName(stub.getIncludeText()); - } + @Override + public void serialize(@Nonnull JSIncludeDirectiveStub stub, @Nonnull StubOutputStream dataStream) throws IOException { + dataStream.writeName(stub.getIncludeText()); + } - @Nonnull - @Override - public JSIncludeDirectiveStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException - { - StringRef includeText = dataStream.readName(); - return new JSIncludeDirectiveStubImpl(StringRef.toString(includeText), parentStub, this); - } + @Nonnull + @Override + public JSIncludeDirectiveStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException { + StringRef includeText = dataStream.readName(); + return new JSIncludeDirectiveStubImpl(StringRef.toString(includeText), parentStub, this); + } - @RequiredReadAction - @Override - public JSIncludeDirectiveStub createStub(@Nonnull JSIncludeDirective psi, StubElement parentStub) - { - String includeText = psi.getIncludeText(); - return new JSIncludeDirectiveStubImpl(includeText, parentStub, this); - } + @RequiredReadAction + @Override + public JSIncludeDirectiveStub createStub(@Nonnull JSIncludeDirective psi, StubElement parentStub) { + String includeText = psi.getIncludeText(); + return new JSIncludeDirectiveStubImpl(includeText, parentStub, this); + } - @Nonnull - @Override - public PsiElement createElement(@Nonnull ASTNode astNode) - { - return new JSIncludeDirectiveImpl(astNode); - } + @Nonnull + @Override + public PsiElement createElement(@Nonnull ASTNode astNode) { + return new JSIncludeDirectiveImpl(astNode); + } - @Override - public JSIncludeDirective createPsi(@Nonnull JSIncludeDirectiveStub stub) - { - return new JSIncludeDirectiveImpl(stub); - } + @Override + public JSIncludeDirective createPsi(@Nonnull JSIncludeDirectiveStub stub) { + return new JSIncludeDirectiveImpl(stub); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSNamespaceDeclarationElementType.java b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSNamespaceDeclarationElementType.java index 50208692..f8b105a7 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSNamespaceDeclarationElementType.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSNamespaceDeclarationElementType.java @@ -19,8 +19,6 @@ import java.io.IOException; -import javax.annotation.Nonnull; - import consulo.annotation.access.RequiredReadAction; import com.intellij.lang.javascript.psi.JSNamespaceDeclaration; import com.intellij.lang.javascript.psi.impl.JSNamespaceDeclarationImpl; @@ -33,58 +31,57 @@ import consulo.language.psi.stub.StubElement; import consulo.language.psi.stub.StubInputStream; import consulo.language.psi.stub.StubOutputStream; +import jakarta.annotation.Nonnull; /** * @author Maxim.Mossienko - * Date: Jun 6, 2008 - * Time: 7:49:06 PM + * Date: Jun 6, 2008 + * Time: 7:49:06 PM */ -public class JSNamespaceDeclarationElementType extends JSQualifiedStubElementType -{ - public JSNamespaceDeclarationElementType() - { - super("NAMESPACE_DECLARATION"); - } +public class JSNamespaceDeclarationElementType extends JSQualifiedStubElementType { + public JSNamespaceDeclarationElementType() { + super("NAMESPACE_DECLARATION"); + } - @Nonnull - @Override - public PsiElement createElement(@Nonnull ASTNode astNode) - { - return new JSNamespaceDeclarationImpl(astNode); - } + @Nonnull + @Override + public PsiElement createElement(@Nonnull ASTNode astNode) { + return new JSNamespaceDeclarationImpl(astNode); + } - @Override - public JSNamespaceDeclaration createPsi(@Nonnull JSNamespaceDeclarationStub stub) - { - return new JSNamespaceDeclarationImpl(stub); - } + @Override + public JSNamespaceDeclaration createPsi(@Nonnull JSNamespaceDeclarationStub stub) { + return new JSNamespaceDeclarationImpl(stub); + } - @RequiredReadAction - @Override - public JSNamespaceDeclarationStub createStub(@Nonnull JSNamespaceDeclaration psi, StubElement parentStub) - { - String name = psi.getName(); - String qualifiedName = psi.getQualifiedName(); - String initialValueString = psi.getInitialValueString(); - return new JSNamespaceDeclarationStubImpl(name, qualifiedName, initialValueString, parentStub, this); - } + @RequiredReadAction + @Override + public JSNamespaceDeclarationStub createStub(@Nonnull JSNamespaceDeclaration psi, StubElement parentStub) { + String name = psi.getName(); + String qualifiedName = psi.getQualifiedName(); + String initialValueString = psi.getInitialValueString(); + return new JSNamespaceDeclarationStubImpl(name, qualifiedName, initialValueString, parentStub, this); + } - @Override - public void serialize(@Nonnull JSNamespaceDeclarationStub stub, @Nonnull StubOutputStream dataStream) throws IOException - { - dataStream.writeName(stub.getName()); - dataStream.writeName(stub.getQualifiedName()); - dataStream.writeName(stub.getInitialValueString()); - } + @Override + public void serialize(@Nonnull JSNamespaceDeclarationStub stub, @Nonnull StubOutputStream dataStream) throws IOException { + dataStream.writeName(stub.getName()); + dataStream.writeName(stub.getQualifiedName()); + dataStream.writeName(stub.getInitialValueString()); + } - @Nonnull - @Override - public JSNamespaceDeclarationStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException - { - StringRef nameRef = dataStream.readName(); - StringRef qualifiedRef = dataStream.readName(); - StringRef initialValueRef = dataStream.readName(); - return new JSNamespaceDeclarationStubImpl(StringRef.toString(nameRef), StringRef.toString(qualifiedRef), - StringRef.toString(initialValueRef), parentStub, this); - } + @Nonnull + @Override + public JSNamespaceDeclarationStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException { + StringRef nameRef = dataStream.readName(); + StringRef qualifiedRef = dataStream.readName(); + StringRef initialValueRef = dataStream.readName(); + return new JSNamespaceDeclarationStubImpl( + StringRef.toString(nameRef), + StringRef.toString(qualifiedRef), + StringRef.toString(initialValueRef), + parentStub, + this + ); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSPackageStatementElementType.java b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSPackageStatementElementType.java index 63a378c1..0307170b 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSPackageStatementElementType.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSPackageStatementElementType.java @@ -19,7 +19,7 @@ import java.io.IOException; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; import consulo.annotation.access.RequiredReadAction; import com.intellij.lang.javascript.psi.JSPackageStatement; @@ -36,51 +36,44 @@ /** * @author Maxim.Mossienko - * Date: Jun 6, 2008 - * Time: 7:49:25 PM + * Date: Jun 6, 2008 + * Time: 7:49:25 PM */ -public class JSPackageStatementElementType extends JSStubElementType -{ - public JSPackageStatementElementType() - { - super("PACKAGE_STATEMENT"); - } +public class JSPackageStatementElementType extends JSStubElementType { + public JSPackageStatementElementType() { + super("PACKAGE_STATEMENT"); + } - @Nonnull - @Override - public PsiElement createElement(@Nonnull ASTNode astNode) - { - return new JSPackageStatementImpl(astNode); - } + @Nonnull + @Override + public PsiElement createElement(@Nonnull ASTNode astNode) { + return new JSPackageStatementImpl(astNode); + } - @Override - public JSPackageStatement createPsi(@Nonnull JSPackageStatementStub stub) - { - return new JSPackageStatementImpl(stub); - } + @Override + public JSPackageStatement createPsi(@Nonnull JSPackageStatementStub stub) { + return new JSPackageStatementImpl(stub); + } - @RequiredReadAction - @Override - public JSPackageStatementStub createStub(@Nonnull JSPackageStatement psi, StubElement parentStub) - { - String name = psi.getName(); - String qualifiedName = psi.getQualifiedName(); - return new JSPackageStatementStubImpl(name, qualifiedName, parentStub, this); - } + @RequiredReadAction + @Override + public JSPackageStatementStub createStub(@Nonnull JSPackageStatement psi, StubElement parentStub) { + String name = psi.getName(); + String qualifiedName = psi.getQualifiedName(); + return new JSPackageStatementStubImpl(name, qualifiedName, parentStub, this); + } - @Override - public void serialize(@Nonnull JSPackageStatementStub stub, @Nonnull StubOutputStream dataStream) throws IOException - { - dataStream.writeName(stub.getName()); - dataStream.writeName(stub.getQualifiedName()); - } + @Override + public void serialize(@Nonnull JSPackageStatementStub stub, @Nonnull StubOutputStream dataStream) throws IOException { + dataStream.writeName(stub.getName()); + dataStream.writeName(stub.getQualifiedName()); + } - @Nonnull - @Override - public JSPackageStatementStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException - { - StringRef nameRef = dataStream.readName(); - StringRef qualifiedRef = dataStream.readName(); - return new JSPackageStatementStubImpl(StringRef.toString(nameRef), StringRef.toString(qualifiedRef), parentStub, this); - } + @Nonnull + @Override + public JSPackageStatementStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException { + StringRef nameRef = dataStream.readName(); + StringRef qualifiedRef = dataStream.readName(); + return new JSPackageStatementStubImpl(StringRef.toString(nameRef), StringRef.toString(qualifiedRef), parentStub, this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSParameterElementType.java b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSParameterElementType.java index d9289741..04ff5e0b 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSParameterElementType.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSParameterElementType.java @@ -19,7 +19,7 @@ import java.io.IOException; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; import consulo.annotation.access.RequiredReadAction; import com.intellij.lang.javascript.psi.JSParameter; import consulo.javascript.impl.language.psi.JSStubElementType; @@ -35,61 +35,61 @@ /** * @author Maxim.Mossienko - * Date: Mar 25, 2008 - * Time: 10:30:07 PM + * Date: Mar 25, 2008 + * Time: 10:30:07 PM */ -public class JSParameterElementType extends JSStubElementType -{ - public JSParameterElementType() - { - super("FORMAL_PARAMETER"); - } +public class JSParameterElementType extends JSStubElementType { + public JSParameterElementType() { + super("FORMAL_PARAMETER"); + } - @Nonnull - @Override - public PsiElement createElement(@Nonnull ASTNode astNode) - { - return new JSParameterImpl(astNode); - } + @Nonnull + @Override + public PsiElement createElement(@Nonnull ASTNode astNode) { + return new JSParameterImpl(astNode); + } - @Override - public JSParameter createPsi(@Nonnull JSParameterStub stub) - { - return new JSParameterImpl(stub); - } + @Override + public JSParameter createPsi(@Nonnull JSParameterStub stub) { + return new JSParameterImpl(stub); + } - @RequiredReadAction - @Override - public JSParameterStub createStub(@Nonnull JSParameter psi, StubElement parentStub) - { - String name = psi.getName(); - int flags = JSParameterStubImpl.buildFlags(psi); - String typeString = psi.getTypeString(); - String initializerText = psi.getInitializerText(); - String qualifiedName = psi.getQualifiedName(); - return new JSParameterStubImpl(name, flags, typeString, initializerText, qualifiedName, parentStub, this); - } + @RequiredReadAction + @Override + public JSParameterStub createStub(@Nonnull JSParameter psi, StubElement parentStub) { + String name = psi.getName(); + int flags = JSParameterStubImpl.buildFlags(psi); + String typeString = psi.getTypeString(); + String initializerText = psi.getInitializerText(); + String qualifiedName = psi.getQualifiedName(); + return new JSParameterStubImpl(name, flags, typeString, initializerText, qualifiedName, parentStub, this); + } - @Override - public void serialize(@Nonnull JSParameterStub stub, @Nonnull StubOutputStream dataStream) throws IOException - { - dataStream.writeName(stub.getName()); - dataStream.writeVarInt(stub.getFlags()); - dataStream.writeName(stub.getTypeString()); - dataStream.writeName(stub.getInitializerText()); - dataStream.writeName(stub.getQualifiedName()); - } + @Override + public void serialize(@Nonnull JSParameterStub stub, @Nonnull StubOutputStream dataStream) throws IOException { + dataStream.writeName(stub.getName()); + dataStream.writeVarInt(stub.getFlags()); + dataStream.writeName(stub.getTypeString()); + dataStream.writeName(stub.getInitializerText()); + dataStream.writeName(stub.getQualifiedName()); + } - @Nonnull - @Override - public JSParameterStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException - { - StringRef nameRef = dataStream.readName(); - int flags = dataStream.readVarInt(); - StringRef typeRef = dataStream.readName(); - StringRef initializerRef = dataStream.readName(); - StringRef qualifiedRef = dataStream.readName(); - return new JSParameterStubImpl(StringRef.toString(nameRef), flags, StringRef.toString(typeRef), StringRef.toString(initializerRef), - StringRef.toString(qualifiedRef), parentStub, this); - } + @Nonnull + @Override + public JSParameterStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException { + StringRef nameRef = dataStream.readName(); + int flags = dataStream.readVarInt(); + StringRef typeRef = dataStream.readName(); + StringRef initializerRef = dataStream.readName(); + StringRef qualifiedRef = dataStream.readName(); + return new JSParameterStubImpl( + StringRef.toString(nameRef), + flags, + StringRef.toString(typeRef), + StringRef.toString(initializerRef), + StringRef.toString(qualifiedRef), + parentStub, + this + ); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSParameterListElementType.java b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSParameterListElementType.java index 81e178ca..58b6d2b3 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSParameterListElementType.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSParameterListElementType.java @@ -29,51 +29,45 @@ import consulo.language.psi.stub.StubInputStream; import consulo.language.psi.stub.StubOutputStream; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; + import java.io.IOException; /** * @author Maxim.Mossienko - * Date: Mar 25, 2008 - * Time: 10:30:00 PM + * Date: Mar 25, 2008 + * Time: 10:30:00 PM */ -public class JSParameterListElementType extends JSStubElementType -{ - public JSParameterListElementType() - { - super("PARAMETER_LIST"); - } +public class JSParameterListElementType extends JSStubElementType { + public JSParameterListElementType() { + super("PARAMETER_LIST"); + } - @Nonnull - @Override - public PsiElement createElement(@Nonnull ASTNode astNode) - { - return new JSParameterListImpl(astNode); - } + @Nonnull + @Override + public PsiElement createElement(@Nonnull ASTNode astNode) { + return new JSParameterListImpl(astNode); + } - @Override - public JSParameterList createPsi(@Nonnull JSParameterListStub stub) - { - return new JSParameterListImpl(stub); - } + @Override + public JSParameterList createPsi(@Nonnull JSParameterListStub stub) { + return new JSParameterListImpl(stub); + } - @RequiredReadAction - @Override - public JSParameterListStub createStub(@Nonnull JSParameterList psi, StubElement parentStub) - { - return new JSParameterListStubImpl(parentStub, this); - } + @RequiredReadAction + @Override + public JSParameterListStub createStub(@Nonnull JSParameterList psi, StubElement parentStub) { + return new JSParameterListStubImpl(parentStub, this); + } - @Override - public void serialize(@Nonnull JSParameterListStub stub, @Nonnull StubOutputStream dataStream) throws IOException - { + @Override + public void serialize(@Nonnull JSParameterListStub stub, @Nonnull StubOutputStream dataStream) throws IOException { - } + } - @Nonnull - @Override - public JSParameterListStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException - { - return new JSParameterListStubImpl(parentStub, this); - } + @Nonnull + @Override + public JSParameterListStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException { + return new JSParameterListStubImpl(parentStub, this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSReferenceListElementType.java b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSReferenceListElementType.java index 9987de92..72c13075 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSReferenceListElementType.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSReferenceListElementType.java @@ -19,7 +19,7 @@ import java.io.IOException; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; import consulo.language.psi.PsiElement; import consulo.language.psi.stub.*; @@ -39,82 +39,67 @@ /** * @author Maxim.Mossienko - * Date: Jun 6, 2008 - * Time: 7:51:24 PM + * Date: Jun 6, 2008 + * Time: 7:51:24 PM */ -public class JSReferenceListElementType extends JSStubElementType -{ - public JSReferenceListElementType(@NonNls String name) - { - super(name); - } +public class JSReferenceListElementType extends JSStubElementType { + public JSReferenceListElementType(@NonNls String name) { + super(name); + } - @Override - public void indexStub(@Nonnull JSReferenceListStub stub, @Nonnull IndexSink sink) - { - if(this == JSElementTypes.EXTENDS_LIST) - { - doIndex(sink, stub, JavaScriptIndexKeys.EXTENDS_INDEX); - } - else if(this == JSElementTypes.IMPLEMENTS_LIST) - { - doIndex(sink, stub, JavaScriptIndexKeys.IMPLEMENTED_INDEX); - } - } + @Override + public void indexStub(@Nonnull JSReferenceListStub stub, @Nonnull IndexSink sink) { + if (this == JSElementTypes.EXTENDS_LIST) { + doIndex(sink, stub, JavaScriptIndexKeys.EXTENDS_INDEX); + } + else if (this == JSElementTypes.IMPLEMENTS_LIST) { + doIndex(sink, stub, JavaScriptIndexKeys.IMPLEMENTED_INDEX); + } + } - private static void doIndex(IndexSink sink, JSReferenceListStub stub, StubIndexKey indexKey) - { - for(String s : stub.getReferenceTexts()) - { - if(s != null) - { - sink.occurrence(indexKey, StringUtil.getShortName(s)); - } - } - } + private static void doIndex(IndexSink sink, JSReferenceListStub stub, StubIndexKey indexKey) { + for (String s : stub.getReferenceTexts()) { + if (s != null) { + sink.occurrence(indexKey, StringUtil.getShortName(s)); + } + } + } - @Nonnull - @Override - public PsiElement createElement(@Nonnull ASTNode astNode) - { - return new JSReferenceListImpl(astNode); - } + @Nonnull + @Override + public PsiElement createElement(@Nonnull ASTNode astNode) { + return new JSReferenceListImpl(astNode); + } - @Override - public JSReferenceList createPsi(@Nonnull JSReferenceListStub stub) - { - return new JSReferenceListImpl(stub, this); - } + @Override + public JSReferenceList createPsi(@Nonnull JSReferenceListStub stub) { + return new JSReferenceListImpl(stub, this); + } - @RequiredReadAction - @Override - public JSReferenceListStub createStub(@Nonnull JSReferenceList psi, StubElement parentStub) - { - String[] referenceTexts = psi.getReferenceTexts(); - return new JSReferenceListStubImpl(referenceTexts, parentStub, this); - } + @RequiredReadAction + @Override + public JSReferenceListStub createStub(@Nonnull JSReferenceList psi, StubElement parentStub) { + String[] referenceTexts = psi.getReferenceTexts(); + return new JSReferenceListStubImpl(referenceTexts, parentStub, this); + } - @Override - public void serialize(@Nonnull JSReferenceListStub stub, @Nonnull StubOutputStream dataStream) throws IOException - { - String[] referenceTexts = stub.getReferenceTexts(); - dataStream.writeVarInt(referenceTexts.length); - for(String referenceText : referenceTexts) - { - dataStream.writeName(referenceText); - } - } + @Override + public void serialize(@Nonnull JSReferenceListStub stub, @Nonnull StubOutputStream dataStream) throws IOException { + String[] referenceTexts = stub.getReferenceTexts(); + dataStream.writeVarInt(referenceTexts.length); + for (String referenceText : referenceTexts) { + dataStream.writeName(referenceText); + } + } - @Nonnull - @Override - public JSReferenceListStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException - { - int count = dataStream.readVarInt(); - String[] refs = ArrayUtil.newStringArray(count); - for(int i = 0; i < count; i++) - { - refs[i] = StringRef.toString(dataStream.readName()); - } - return new JSReferenceListStubImpl(refs, parentStub, this); - } + @Nonnull + @Override + public JSReferenceListStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException { + int count = dataStream.readVarInt(); + String[] refs = ArrayUtil.newStringArray(count); + for (int i = 0; i < count; i++) { + refs[i] = StringRef.toString(dataStream.readName()); + } + return new JSReferenceListStubImpl(refs, parentStub, this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSUseNamespaceDirectiveType.java b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSUseNamespaceDirectiveType.java index be953d24..c2a325de 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSUseNamespaceDirectiveType.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSUseNamespaceDirectiveType.java @@ -19,7 +19,7 @@ import java.io.IOException; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; import consulo.annotation.access.RequiredReadAction; import consulo.index.io.StringRef; @@ -36,47 +36,40 @@ /** * @author Maxim.Mossienko - * Date: Oct 3, 2008 - * Time: 9:13:01 PM + * Date: Oct 3, 2008 + * Time: 9:13:01 PM */ -public class JSUseNamespaceDirectiveType extends JSStubElementType -{ - public JSUseNamespaceDirectiveType() - { - super("USE_NAMESPACE_DIRECTIVE"); - } +public class JSUseNamespaceDirectiveType extends JSStubElementType { + public JSUseNamespaceDirectiveType() { + super("USE_NAMESPACE_DIRECTIVE"); + } - @Nonnull - @Override - public PsiElement createElement(@Nonnull ASTNode astNode) - { - return new JSUseNamespaceDirectiveImpl(astNode); - } + @Nonnull + @Override + public PsiElement createElement(@Nonnull ASTNode astNode) { + return new JSUseNamespaceDirectiveImpl(astNode); + } - @Override - public JSUseNamespaceDirective createPsi(@Nonnull JSUseNamespaceDirectiveStub stub) - { - return new JSUseNamespaceDirectiveImpl(stub); - } + @Override + public JSUseNamespaceDirective createPsi(@Nonnull JSUseNamespaceDirectiveStub stub) { + return new JSUseNamespaceDirectiveImpl(stub); + } - @RequiredReadAction - @Override - public JSUseNamespaceDirectiveStub createStub(@Nonnull JSUseNamespaceDirective psi, StubElement parentStub) - { - return new JSUseNamespaceDirectiveStubImpl(psi.getNamespaceToBeUsed(), parentStub, this); - } + @RequiredReadAction + @Override + public JSUseNamespaceDirectiveStub createStub(@Nonnull JSUseNamespaceDirective psi, StubElement parentStub) { + return new JSUseNamespaceDirectiveStubImpl(psi.getNamespaceToBeUsed(), parentStub, this); + } - @Override - public void serialize(@Nonnull JSUseNamespaceDirectiveStub stub, @Nonnull StubOutputStream dataStream) throws IOException - { - dataStream.writeName(stub.getNamespaceToUse()); - } + @Override + public void serialize(@Nonnull JSUseNamespaceDirectiveStub stub, @Nonnull StubOutputStream dataStream) throws IOException { + dataStream.writeName(stub.getNamespaceToUse()); + } - @Nonnull - @Override - public JSUseNamespaceDirectiveStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException - { - StringRef nameRef = dataStream.readName(); - return new JSUseNamespaceDirectiveStubImpl(StringRef.toString(nameRef), parentStub, this); - } + @Nonnull + @Override + public JSUseNamespaceDirectiveStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException { + StringRef nameRef = dataStream.readName(); + return new JSUseNamespaceDirectiveStubImpl(StringRef.toString(nameRef), parentStub, this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSVarStatementElementType.java b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSVarStatementElementType.java index 13d7987e..e280a7f5 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSVarStatementElementType.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSVarStatementElementType.java @@ -19,7 +19,7 @@ import java.io.IOException; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.ASTNode; @@ -38,53 +38,45 @@ /** * @author Maxim.Mossienko - * Date: Jun 8, 2008 - * Time: 1:50:59 PM + * Date: Jun 8, 2008 + * Time: 1:50:59 PM */ -public class JSVarStatementElementType extends JSStubElementType -{ - public JSVarStatementElementType() - { - super("VAR_STATEMENT"); - } +public class JSVarStatementElementType extends JSStubElementType { + public JSVarStatementElementType() { + super("VAR_STATEMENT"); + } - @Override - public boolean shouldCreateStub(ASTNode node) - { - final PsiElement element = node.getTreeParent().getPsi(); - return element instanceof JSClass || element instanceof JSPackageStatement || element instanceof JSFile; - } + @Override + public boolean shouldCreateStub(ASTNode node) { + PsiElement element = node.getTreeParent().getPsi(); + return element instanceof JSClass || element instanceof JSPackageStatement || element instanceof JSFile; + } - @Nonnull - @Override - public PsiElement createElement(@Nonnull ASTNode astNode) - { - return new JSVarStatementImpl(astNode); - } + @Nonnull + @Override + public PsiElement createElement(@Nonnull ASTNode astNode) { + return new JSVarStatementImpl(astNode); + } - @Override - public JSVarStatement createPsi(@Nonnull JSVarStatementStub stub) - { - return new JSVarStatementImpl(stub); - } + @Override + public JSVarStatement createPsi(@Nonnull JSVarStatementStub stub) { + return new JSVarStatementImpl(stub); + } - @RequiredReadAction - @Override - public JSVarStatementStub createStub(@Nonnull JSVarStatement psi, StubElement parentStub) - { - return new JSVarStatementStubImpl(parentStub, this); - } + @RequiredReadAction + @Override + public JSVarStatementStub createStub(@Nonnull JSVarStatement psi, StubElement parentStub) { + return new JSVarStatementStubImpl(parentStub, this); + } - @Override - public void serialize(@Nonnull JSVarStatementStub stub, @Nonnull StubOutputStream dataStream) throws IOException - { + @Override + public void serialize(@Nonnull JSVarStatementStub stub, @Nonnull StubOutputStream dataStream) throws IOException { - } + } - @Nonnull - @Override - public JSVarStatementStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException - { - return new JSVarStatementStubImpl(parentStub, this); - } + @Nonnull + @Override + public JSVarStatementStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException { + return new JSVarStatementStubImpl(parentStub, this); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSVariableElementType.java b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSVariableElementType.java index f9fc22c5..9b81468e 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/types/JSVariableElementType.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/types/JSVariableElementType.java @@ -19,7 +19,7 @@ import java.io.IOException; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; import consulo.annotation.access.RequiredReadAction; import com.intellij.lang.javascript.JSElementTypes; @@ -39,88 +39,81 @@ /** * @author Maxim.Mossienko - * Date: Mar 25, 2008 - * Time: 10:30:10 PM + * Date: Mar 25, 2008 + * Time: 10:30:10 PM */ -public class JSVariableElementType extends JSQualifiedStubElementType -{ - public JSVariableElementType() - { - super("VARIABLE"); - } +public class JSVariableElementType extends JSQualifiedStubElementType { + public JSVariableElementType() { + super("VARIABLE"); + } - @Override - protected boolean doIndexName(JSVariableStub stub, String name, String fqn) - { - final IStubElementType stubType = stub.getParentStub().getParentStub().getStubType(); + @Override + protected boolean doIndexName(JSVariableStub stub, String name, String fqn) { + IStubElementType stubType = stub.getParentStub().getParentStub().getStubType(); - if(stubType instanceof JSPackageStatementElementType || stubType == null) - { - return true; - } - return false; - } + return stubType instanceof JSPackageStatementElementType || stubType == null; + } - @Override - protected boolean doIndexQualifiedName(JSVariableStub stub, String name, String fqn) - { - return doIndexName(stub, name, fqn); - } + @Override + protected boolean doIndexQualifiedName(JSVariableStub stub, String name, String fqn) { + return doIndexName(stub, name, fqn); + } - @Override - public boolean shouldCreateStub(final ASTNode node) - { - final IElementType discriminatingParentType = node.getTreeParent().getTreeParent().getElementType(); - return discriminatingParentType == JSElementTypes.PACKAGE_STATEMENT || - discriminatingParentType == JSElementTypes.CLASS || - discriminatingParentType instanceof JSFileElementType; - } + @Override + public boolean shouldCreateStub(ASTNode node) { + IElementType discriminatingParentType = node.getTreeParent().getTreeParent().getElementType(); + return discriminatingParentType == JSElementTypes.PACKAGE_STATEMENT + || discriminatingParentType == JSElementTypes.CLASS + || discriminatingParentType instanceof JSFileElementType; + } - @Nonnull - @Override - public PsiElement createElement(@Nonnull ASTNode astNode) - { - return new JSVariableImpl(astNode); - } + @Nonnull + @Override + public PsiElement createElement(@Nonnull ASTNode astNode) { + return new JSVariableImpl(astNode); + } - @Override - public JSVariable createPsi(@Nonnull JSVariableStub stub) - { - return new JSVariableImpl(stub); - } + @Override + public JSVariable createPsi(@Nonnull JSVariableStub stub) { + return new JSVariableImpl(stub); + } - @RequiredReadAction - @Override - public JSVariableStub createStub(@Nonnull JSVariable psi, StubElement parentStub) - { - String name = psi.getName(); - int flags = JSVariableStubImpl.buildFlags(psi); - String typeString = psi.getTypeString(); - String initializerText = psi.getInitializerText(); - String qualifiedName = psi.getQualifiedName(); - return new JSVariableStubImpl(name, flags, typeString, initializerText, qualifiedName, parentStub, this); - } + @RequiredReadAction + @Override + public JSVariableStub createStub(@Nonnull JSVariable psi, StubElement parentStub) { + String name = psi.getName(); + int flags = JSVariableStubImpl.buildFlags(psi); + String typeString = psi.getTypeString(); + String initializerText = psi.getInitializerText(); + String qualifiedName = psi.getQualifiedName(); + return new JSVariableStubImpl(name, flags, typeString, initializerText, qualifiedName, parentStub, this); + } - @Override - public void serialize(@Nonnull JSVariableStub stub, @Nonnull StubOutputStream dataStream) throws IOException - { - dataStream.writeName(stub.getName()); - dataStream.writeVarInt(stub.getFlags()); - dataStream.writeName(stub.getTypeString()); - dataStream.writeName(stub.getInitializerText()); - dataStream.writeName(stub.getQualifiedName()); - } + @Override + public void serialize(@Nonnull JSVariableStub stub, @Nonnull StubOutputStream dataStream) throws IOException { + dataStream.writeName(stub.getName()); + dataStream.writeVarInt(stub.getFlags()); + dataStream.writeName(stub.getTypeString()); + dataStream.writeName(stub.getInitializerText()); + dataStream.writeName(stub.getQualifiedName()); + } - @Nonnull - @Override - public JSVariableStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException - { - StringRef nameRef = dataStream.readName(); - int flags = dataStream.readVarInt(); - StringRef typeRef = dataStream.readName(); - StringRef initializerRef = dataStream.readName(); - StringRef qualifiedRef = dataStream.readName(); - return new JSVariableStubImpl(StringRef.toString(nameRef), flags, StringRef.toString(typeRef), StringRef.toString(initializerRef), - StringRef.toString(qualifiedRef), parentStub, this); - } + @Nonnull + @Override + public JSVariableStub deserialize(@Nonnull StubInputStream dataStream, StubElement parentStub) throws IOException { + StringRef nameRef = dataStream.readName(); + int flags = dataStream.readVarInt(); + StringRef typeRef = dataStream.readName(); + StringRef initializerRef = dataStream.readName(); + StringRef qualifiedRef = dataStream.readName(); + return new JSVariableStubImpl( + StringRef.toString(nameRef), + flags, + StringRef.toString(typeRef), + StringRef.toString(initializerRef), + StringRef.toString(qualifiedRef), + parentStub, + this + ); + } } diff --git a/base-impl/src/main/java/com/intellij/lang/javascript/validation/JSUnusedImportsHelper.java b/base-impl/src/main/java/com/intellij/lang/javascript/validation/JSUnusedImportsHelper.java index 90b1edb1..5ee4f4c8 100644 --- a/base-impl/src/main/java/com/intellij/lang/javascript/validation/JSUnusedImportsHelper.java +++ b/base-impl/src/main/java/com/intellij/lang/javascript/validation/JSUnusedImportsHelper.java @@ -38,342 +38,276 @@ import consulo.xml.psi.xml.XmlFile; import consulo.xml.psi.xml.XmlTag; import consulo.xml.psi.xml.XmlText; +import jakarta.annotation.Nullable; -import javax.annotation.Nullable; import java.util.*; -public class JSUnusedImportsHelper -{ - private final Collection myElements; - - public static class Results - { - public final Collection unusedImports; - public final Collection allImports; - public final Map fqnsToReplaceWithImport; - - public Results(Map fqnsToReplaceWithImport, Collection unusedImports, - Collection allImports) - { - this.fqnsToReplaceWithImport = fqnsToReplaceWithImport; - this.unusedImports = unusedImports; - this.allImports = allImports; - } - } - - private static final Collection> REFERENCED_ELEMENTS_CLASSES = Arrays.asList(JSClass.class, - JSNamespaceDeclaration.class, JSFunction.class, JSVariable.class); - - // in Flex 3 for some reason fqn reference to function or variable does not reqiure explicit import statement - private static final Collection> QUALIFIED_REFERENCE_NEEDS_IMPORT = Arrays.asList(JSClass.class, - JSNamespaceDeclaration.class); - - private static final Key> ourUnusedImportsKey = Key.create("js.unused.imports"); - - private final Set unusedImports = new HashSet(); - private final Collection allImports = new HashSet(); - private final Set importsUsedAheadOfDefinition = new HashSet(); - private final Map fqnsToReplaceWithImport = new HashMap(); - private final PsiFile myContainingFile; - - private JSUnusedImportsHelper(PsiFile containingFile, Collection elements) - { - myContainingFile = containingFile; - myElements = elements; - } - - private void registerUnused(final JSImportStatement importStatement) - { - allImports.add(importStatement); - - final String importText = importStatement.getImportText(); - if(importText == null) - { - return; - } - - if(importsUsedAheadOfDefinition.contains(importStatement)) - { - return; - } - - unusedImports.add(importStatement); - } - - private static boolean isInstance(PsiElement element, Collection> classes) - { - for(Class clazz : classes) - { - if(clazz.isInstance(element)) - { - return true; - } - } - return false; - } - - private void process(JSReferenceExpression node) - { - if(node.getQualifier() == null) - { - String thisPackage = JSResolveUtil.findPackageStatementQualifier(node); - registerUsedImportsFromResolveResults(node, thisPackage); - } - else - { - registerUsedImportsFromResolveResults(node, null); - - Pair replaceStatus = getReplaceStatus(node); - - if(replaceStatus.second) - { - if(sameContainingFile(node.getContainingFile(), myContainingFile)) - { - fqnsToReplaceWithImport.put(node, node.getText()); - } - } - } - } - - private void registerUsedImportsFromResolveResults(JSReferenceExpression node, String thisPackage) - { - for(ResolveResult r : node.multiResolve(false)) - { - // TODO can we get different import statements here? - if(r instanceof JSResolveUtil.MyResolveResult) - { - JavaScriptImportStatementBase importStatement = ((JSResolveUtil.MyResolveResult) r).getImportUsed(); - - if(importStatement instanceof JSImportStatement && isInstance(r.getElement(), REFERENCED_ELEMENTS_CLASSES)) - { - String importString = ((JSImportStatement) importStatement).getImportText(); - String importedPackage = importString.substring(0, importString.lastIndexOf('.')); - if(thisPackage == null || !thisPackage.equals(importedPackage)) - { - registerUsed((JSImportStatement) importStatement); - } - } - } - } - } - - private static boolean sameContainingFile(PsiFile containingFile, PsiFile subjectFile) - { - return subjectFile instanceof XmlFile ? getContainingFile(containingFile) == subjectFile : containingFile == subjectFile; - } - - public static boolean isSomeNodeThatShouldNotHaveImportsWhenQualified(JSReferenceExpression expression, PsiElement element) - { - Pair pair = getReplaceStatus(expression, element); - return !pair.first; - } - - private static Pair getReplaceStatus(JSReferenceExpression node) - { - return getReplaceStatus(node, null); - } - - /** - * @return Pair(needs import statement, can be replaced) - */ - private static Pair getReplaceStatus(JSReferenceExpression node, PsiElement resolve) - { - if(resolve == null) - { - resolve = JSResolveUtil.findClassByQName(node.getText(), node); - } - PsiElement parent = node.getParent(); - if(parent instanceof JavaScriptImportStatementBase) - { - return Pair.create(false, false); - } - - if(parent instanceof JSExpressionStatement && !(resolve instanceof JSNamespaceDeclaration)) - { - return Pair.create(false, false); - } - - // implicit parameter of anonymous event listener - if(parent instanceof JSParameter) - { - JSFunction parentFunctionExpression = PsiTreeUtil.getParentOfType(node, JSFunction.class); - if(parentFunctionExpression instanceof JSFunctionExpression) - { - if(node.getContainingFile().getContext() instanceof XmlAttributeValue || node.getContainingFile().getContext() instanceof XmlText) - { - return Pair.create(false, false); - } - } - } - - if(parent.getNode().getElementType() == JSElementTypes.EXTENDS_LIST) - { - if(parent.getParent() instanceof JSClass) - { - String className = ((JSClass) parent.getParent()).getName(); - if(StringUtil.isNotEmpty(className) && className.equals(node.getReferencedName())) - { - return Pair.create(true, false); - } - } - } - - // part of implements list of mxml component - if(parent.getNode().getElementType() == JSElementTypes.IMPLEMENTS_LIST) - { - if(node.getContainingFile().getContext() instanceof XmlAttributeValue) - { - return Pair.create(false, false); - } - } - - PsiElement element = resolve; - if(element == null || !isInstance(element, REFERENCED_ELEMENTS_CLASSES)) - { - return Pair.create(false, false); - } - - return Pair.create(isInstance(element, QUALIFIED_REFERENCE_NEEDS_IMPORT), true); - } - - private void registerUsed(JSImportStatement importStatement) - { - allImports.add(importStatement); - if(importStatement.getImportText() == null) - { - return; - } - - if(!unusedImports.remove(importStatement)) - { - importsUsedAheadOfDefinition.add(importStatement); - } - } - - private Collection filter(Collection original) - { - Collection result = new ArrayList(); - for(JSImportStatement importStatement : original) - { - if(importStatement.isValid() && sameContainingFile(importStatement.getContainingFile(), myContainingFile)) - { - result.add(importStatement); - } - } - return result; - } - - - public static Results getUnusedImports(PsiFile file) - { - PsiFile containingFile = getContainingFile(file); - - CachedValue data = containingFile.getUserData(ourUnusedImportsKey); - if(data == null) - { - final PsiFile containingFile1 = containingFile; - data = CachedValuesManager.getManager(file.getProject()).createCachedValue(new CachedValueProvider() - { - @Override - public Result compute() - { - final Map> allElements = new HashMap>(); - Collection processedFiles = new HashSet(); - collectElements(null, containingFile1, allElements, processedFiles); - - Results allResults = new Results(new HashMap(), new ArrayList(), - new ArrayList()); - for(Collection elements : allElements.values()) - { - Results results = new JSUnusedImportsHelper(containingFile1, elements).getUnusedImports(); - allResults.fqnsToReplaceWithImport.putAll(results.fqnsToReplaceWithImport); - allResults.unusedImports.addAll(results.unusedImports); - allResults.allImports.addAll(results.allImports); - } - - // TODO explicit depencencies - return new Result(allResults, PsiModificationTracker.MODIFICATION_COUNT); - } - }, false); - containingFile1.putUserData(ourUnusedImportsKey, data); - } - return data.getValue(); - } - - private static PsiFile getContainingFile(PsiFile file) - { - return file.getContext() != null ? file.getContext().getContainingFile() : file; - } - - private Results getUnusedImports() - { - for(PsiElement e : myElements) - { - if(e instanceof JSImportStatement) - { - JSImportStatement importStatement = (JSImportStatement) e; - registerUnused(importStatement); - } - else if(e instanceof JSReferenceExpression) - { - process((JSReferenceExpression) e); - } - } - - return new Results(fqnsToReplaceWithImport, filter(unusedImports), filter(allImports)); - } - - private static void collectElements(@Nullable final XmlTag rootTag, final PsiFile file, final Map> result, - final Collection processedFiles) - { - if(processedFiles.contains(file)) - { - return; - } - if(file instanceof JSFile) - { - processedFiles.add((JSFile) file); - - PsiTreeUtil.processElements(file, new PsiElementProcessor() - { - @Override - public boolean execute(PsiElement element) - { - if(element instanceof JSIncludeDirective) - { - PsiFile includedFile = ((JSIncludeDirective) element).resolveFile(); - // we check processed files before since we may include this file to self and setting context will make cycle - if(includedFile instanceof JSFile && !processedFiles.contains((JSFile) includedFile)) - { - includedFile.putUserData(JSResolveUtil.contextKey, element); - collectElements(rootTag, includedFile, result, processedFiles); - } - } - else if(element instanceof JSElement && !(element instanceof JSFile)) - { - Collection elements = result.get(rootTag); - if(elements == null) - { - elements = new ArrayList(); - result.put(rootTag, elements); - } - elements.add(element); - } - return true; - } - }); - } - else if(JavaScriptSupportLoader.isFlexMxmFile(file)) - { - XmlBackedJSClassImpl.visitInjectedFiles((XmlFile) file, new XmlBackedJSClassImpl.InjectedFileVisitor() - { - @Override - public void visit(XmlTag rootTag, JSFile jsFile) - { - collectElements(rootTag, jsFile, result, processedFiles); - } - }); - } - } - +public class JSUnusedImportsHelper { + private final Collection myElements; + + public static class Results { + public final Collection unusedImports; + public final Collection allImports; + public final Map fqnsToReplaceWithImport; + + public Results( + Map fqnsToReplaceWithImport, + Collection unusedImports, + Collection allImports + ) { + this.fqnsToReplaceWithImport = fqnsToReplaceWithImport; + this.unusedImports = unusedImports; + this.allImports = allImports; + } + } + + private static final Collection> REFERENCED_ELEMENTS_CLASSES = + Arrays.asList(JSClass.class, JSNamespaceDeclaration.class, JSFunction.class, JSVariable.class); + + // in Flex 3 for some reason fqn reference to function or variable does not reqiure explicit import statement + private static final Collection> QUALIFIED_REFERENCE_NEEDS_IMPORT = + Arrays.asList(JSClass.class, JSNamespaceDeclaration.class); + + private static final Key> ourUnusedImportsKey = Key.create("js.unused.imports"); + + private final Set unusedImports = new HashSet<>(); + private final Collection allImports = new HashSet<>(); + private final Set importsUsedAheadOfDefinition = new HashSet<>(); + private final Map fqnsToReplaceWithImport = new HashMap<>(); + private final PsiFile myContainingFile; + + private JSUnusedImportsHelper(PsiFile containingFile, Collection elements) { + myContainingFile = containingFile; + myElements = elements; + } + + private void registerUnused(JSImportStatement importStatement) { + allImports.add(importStatement); + + String importText = importStatement.getImportText(); + if (importText == null) { + return; + } + + if (importsUsedAheadOfDefinition.contains(importStatement)) { + return; + } + + unusedImports.add(importStatement); + } + + private static boolean isInstance(PsiElement element, Collection> classes) { + for (Class clazz : classes) { + if (clazz.isInstance(element)) { + return true; + } + } + return false; + } + + private void process(JSReferenceExpression node) { + if (node.getQualifier() == null) { + String thisPackage = JSResolveUtil.findPackageStatementQualifier(node); + registerUsedImportsFromResolveResults(node, thisPackage); + } + else { + registerUsedImportsFromResolveResults(node, null); + + Pair replaceStatus = getReplaceStatus(node); + + if (replaceStatus.second) { + if (sameContainingFile(node.getContainingFile(), myContainingFile)) { + fqnsToReplaceWithImport.put(node, node.getText()); + } + } + } + } + + private void registerUsedImportsFromResolveResults(JSReferenceExpression node, String thisPackage) { + for (ResolveResult r : node.multiResolve(false)) { + // TODO can we get different import statements here? + if (r instanceof JSResolveUtil.MyResolveResult resolveResult + && resolveResult.getImportUsed() instanceof JSImportStatement jsImportStatement + && isInstance(r.getElement(), REFERENCED_ELEMENTS_CLASSES)) { + String importString = jsImportStatement.getImportText(); + String importedPackage = importString.substring(0, importString.lastIndexOf('.')); + if (thisPackage == null || !thisPackage.equals(importedPackage)) { + registerUsed(jsImportStatement); + } + } + } + } + + private static boolean sameContainingFile(PsiFile containingFile, PsiFile subjectFile) { + return subjectFile instanceof XmlFile ? getContainingFile(containingFile) == subjectFile : containingFile == subjectFile; + } + + public static boolean isSomeNodeThatShouldNotHaveImportsWhenQualified(JSReferenceExpression expression, PsiElement element) { + Pair pair = getReplaceStatus(expression, element); + return !pair.first; + } + + private static Pair getReplaceStatus(JSReferenceExpression node) { + return getReplaceStatus(node, null); + } + + /** + * @return Pair(needs import statement, can be replaced) + */ + private static Pair getReplaceStatus(JSReferenceExpression node, PsiElement resolve) { + if (resolve == null) { + resolve = JSResolveUtil.findClassByQName(node.getText(), node); + } + PsiElement parent = node.getParent(); + if (parent instanceof JavaScriptImportStatementBase) { + return Pair.create(false, false); + } + + if (parent instanceof JSExpressionStatement && !(resolve instanceof JSNamespaceDeclaration)) { + return Pair.create(false, false); + } + + // implicit parameter of anonymous event listener + if (parent instanceof JSParameter) { + JSFunction parentFunctionExpression = PsiTreeUtil.getParentOfType(node, JSFunction.class); + if (parentFunctionExpression instanceof JSFunctionExpression) { + if (node.getContainingFile().getContext() instanceof XmlAttributeValue + || node.getContainingFile().getContext() instanceof XmlText) { + return Pair.create(false, false); + } + } + } + + if (parent.getNode().getElementType() == JSElementTypes.EXTENDS_LIST && parent.getParent() instanceof JSClass jsClass) { + String className = jsClass.getName(); + if (StringUtil.isNotEmpty(className) && className.equals(node.getReferencedName())) { + return Pair.create(true, false); + } + } + + // part of implements list of mxml component + if (parent.getNode().getElementType() == JSElementTypes.IMPLEMENTS_LIST + && node.getContainingFile().getContext() instanceof XmlAttributeValue) { + return Pair.create(false, false); + } + + PsiElement element = resolve; + if (element == null || !isInstance(element, REFERENCED_ELEMENTS_CLASSES)) { + return Pair.create(false, false); + } + + return Pair.create(isInstance(element, QUALIFIED_REFERENCE_NEEDS_IMPORT), true); + } + + private void registerUsed(JSImportStatement importStatement) { + allImports.add(importStatement); + if (importStatement.getImportText() == null) { + return; + } + + if (!unusedImports.remove(importStatement)) { + importsUsedAheadOfDefinition.add(importStatement); + } + } + + private Collection filter(Collection original) { + Collection result = new ArrayList<>(); + for (JSImportStatement importStatement : original) { + if (importStatement.isValid() && sameContainingFile(importStatement.getContainingFile(), myContainingFile)) { + result.add(importStatement); + } + } + return result; + } + + public static Results getUnusedImports(PsiFile file) { + PsiFile containingFile = getContainingFile(file); + + CachedValue data = containingFile.getUserData(ourUnusedImportsKey); + if (data == null) { + PsiFile containingFile1 = containingFile; + data = CachedValuesManager.getManager(file.getProject()).createCachedValue( + () -> { + Map> allElements = new HashMap<>(); + Collection processedFiles = new HashSet<>(); + collectElements(null, containingFile1, allElements, processedFiles); + + Results allResults = new Results(new HashMap<>(), new ArrayList<>(), new ArrayList<>()); + for (Collection elements : allElements.values()) { + Results results = new JSUnusedImportsHelper(containingFile1, elements).getUnusedImports(); + allResults.fqnsToReplaceWithImport.putAll(results.fqnsToReplaceWithImport); + allResults.unusedImports.addAll(results.unusedImports); + allResults.allImports.addAll(results.allImports); + } + + // TODO explicit depencencies + return new CachedValueProvider.Result<>(allResults, PsiModificationTracker.MODIFICATION_COUNT); + }, + false + ); + containingFile1.putUserData(ourUnusedImportsKey, data); + } + return data.getValue(); + } + + private static PsiFile getContainingFile(PsiFile file) { + return file.getContext() != null ? file.getContext().getContainingFile() : file; + } + + private Results getUnusedImports() { + for (PsiElement e : myElements) { + if (e instanceof JSImportStatement) { + JSImportStatement importStatement = (JSImportStatement)e; + registerUnused(importStatement); + } + else if (e instanceof JSReferenceExpression) { + process((JSReferenceExpression)e); + } + } + + return new Results(fqnsToReplaceWithImport, filter(unusedImports), filter(allImports)); + } + + private static void collectElements( + @Nullable XmlTag rootTag, + PsiFile file, + Map> result, + Collection processedFiles + ) { + if (processedFiles.contains(file)) { + return; + } + if (file instanceof JSFile jsFile) { + processedFiles.add(jsFile); + + PsiTreeUtil.processElements( + file, + element -> { + if (element instanceof JSIncludeDirective includeDirective) { + PsiFile includedFile = includeDirective.resolveFile(); + // we check processed files before since we may include this file to self and setting context will make cycle + if (includedFile instanceof JSFile includedJsFile && !processedFiles.contains(includedJsFile)) { + includedFile.putUserData(JSResolveUtil.contextKey, element); + collectElements(rootTag, includedFile, result, processedFiles); + } + } + else if (element instanceof JSElement && !(element instanceof JSFile)) { + Collection elements = result.get(rootTag); + if (elements == null) { + elements = new ArrayList<>(); + result.put(rootTag, elements); + } + elements.add(element); + } + return true; + } + ); + } + else if (JavaScriptSupportLoader.isFlexMxmFile(file)) { + XmlBackedJSClassImpl.visitInjectedFiles( + (XmlFile)file, + (rootTag1, jsFile) -> collectElements(rootTag1, jsFile, result, processedFiles) + ); + } + } } diff --git a/base-impl/src/main/java/consulo/javascript/ecmascript4/psi/impl/EcmaScript4ElementTypes.java b/base-impl/src/main/java/consulo/javascript/ecmascript4/psi/impl/EcmaScript4ElementTypes.java index 36c939fd..ee996cda 100644 --- a/base-impl/src/main/java/consulo/javascript/ecmascript4/psi/impl/EcmaScript4ElementTypes.java +++ b/base-impl/src/main/java/consulo/javascript/ecmascript4/psi/impl/EcmaScript4ElementTypes.java @@ -9,7 +9,6 @@ * @author VISTALL * @since 2019-12-14 */ -public interface EcmaScript4ElementTypes -{ - JSStubElementType IMPORT_STATEMENT = new JSImportStatementElementType(); +public interface EcmaScript4ElementTypes { + JSStubElementType IMPORT_STATEMENT = new JSImportStatementElementType(); } diff --git a/base-impl/src/main/java/consulo/javascript/ide/codeInsight/JavaScriptQuickFixFactory.java b/base-impl/src/main/java/consulo/javascript/ide/codeInsight/JavaScriptQuickFixFactory.java index b1cb00cb..fbf95279 100644 --- a/base-impl/src/main/java/consulo/javascript/ide/codeInsight/JavaScriptQuickFixFactory.java +++ b/base-impl/src/main/java/consulo/javascript/ide/codeInsight/JavaScriptQuickFixFactory.java @@ -24,45 +24,42 @@ import consulo.language.psi.PsiElement; import consulo.language.version.LanguageVersion; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; + +import java.util.List; /** * @author VISTALL * @since 23.02.2016 */ @ExtensionAPI(ComponentScope.APPLICATION) -public abstract class JavaScriptQuickFixFactory -{ - private static final JavaScriptQuickFixFactory ourDefaultImpl = new JavaScriptQuickFixFactory() - { - @Override - public boolean isMyVersion(@Nonnull JavaScriptLanguageVersion version) - { - return true; - } - }; +public abstract class JavaScriptQuickFixFactory { + private static final JavaScriptQuickFixFactory ourDefaultImpl = new JavaScriptQuickFixFactory() { + @Override + public boolean isMyVersion(@Nonnull JavaScriptLanguageVersion version) { + return true; + } + }; - @Nonnull - public static JavaScriptQuickFixFactory byElement(PsiElement element) - { - LanguageVersion languageVersion = element.getLanguageVersion(); - if(languageVersion instanceof BaseJavaScriptLanguageVersion jsVersion) - { - for(JavaScriptQuickFixFactory factory : element.getProject().getApplication().getExtensionList(JavaScriptQuickFixFactory.class)) - { - if(factory.isMyVersion(jsVersion)) - { - return factory; - } - } - } - return ourDefaultImpl; - } + @Nonnull + public static JavaScriptQuickFixFactory byElement(PsiElement element) { + LanguageVersion languageVersion = element.getLanguageVersion(); + if (languageVersion instanceof BaseJavaScriptLanguageVersion jsVersion) { + List extensionList = element.getProject() + .getApplication() + .getExtensionList(JavaScriptQuickFixFactory.class); + for (JavaScriptQuickFixFactory factory : extensionList) { + if (factory.isMyVersion(jsVersion)) { + return factory; + } + } + } + return ourDefaultImpl; + } - public CreateJSFunctionOrMethodFix createFunctionOrMethodFix(String referenceName, boolean isMethod) - { - return new CreateJSFunctionOrMethodFix(referenceName, isMethod); - } + public CreateJSFunctionOrMethodFix createFunctionOrMethodFix(String referenceName, boolean isMethod) { + return new CreateJSFunctionOrMethodFix(referenceName, isMethod); + } - public abstract boolean isMyVersion(@Nonnull JavaScriptLanguageVersion version); + public abstract boolean isMyVersion(@Nonnull JavaScriptLanguageVersion version); } diff --git a/base-impl/src/main/java/consulo/javascript/ide/hightlight/JavaScriptHighlighter.java b/base-impl/src/main/java/consulo/javascript/ide/hightlight/JavaScriptHighlighter.java index 5670f88c..b76d25e0 100644 --- a/base-impl/src/main/java/consulo/javascript/ide/hightlight/JavaScriptHighlighter.java +++ b/base-impl/src/main/java/consulo/javascript/ide/hightlight/JavaScriptHighlighter.java @@ -20,124 +20,108 @@ import com.intellij.lang.javascript.JSDocTokenTypes; import com.intellij.lang.javascript.JSTokenTypes; import com.intellij.lang.javascript.highlighting.JavaScriptHighlightingLexer; -import consulo.application.util.function.Processor; import consulo.colorScheme.TextAttributesKey; import consulo.language.ast.IElementType; import consulo.language.ast.StringEscapesTokenTypes; import consulo.language.ast.TokenSet; import consulo.language.editor.highlight.SyntaxHighlighterBase; -import consulo.language.impl.ast.Factory; import consulo.language.lexer.Lexer; +import consulo.util.collection.MultiMap; import consulo.xml.editor.XmlHighlighterColors; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; -import java.util.HashMap; -import java.util.Map; import java.util.function.Supplier; /** * @author VISTALL * @since 12.12.2015 */ -public class JavaScriptHighlighter extends SyntaxHighlighterBase -{ - private static Map keys1; - private static Map keys2; - - static - { - keys1 = new HashMap(); - keys2 = new HashMap(); - - TokenSet operations = TokenSet.andNot(JSTokenTypes.OPERATIONS, TokenSet.create(JSTokenTypes.AS_KEYWORD, JSTokenTypes.IS_KEYWORD)); - - SyntaxHighlighterBase.safeMap(keys1, operations, JavaScriptSyntaxHighlightKeys.JS_OPERATION_SIGN); - - safeMap(keys1, JSTokenTypes.KEYWORDS, JavaScriptSyntaxHighlightKeys.JS_KEYWORD); - - keys1.put(StringEscapesTokenTypes.VALID_STRING_ESCAPE_TOKEN, JavaScriptSyntaxHighlightKeys.JS_VALID_STRING_ESCAPE); - keys1.put(StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN, JavaScriptSyntaxHighlightKeys.JS_INVALID_STRING_ESCAPE); - keys1.put(StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN, JavaScriptSyntaxHighlightKeys.JS_INVALID_STRING_ESCAPE); - - keys1.put(JSTokenTypes.NUMERIC_LITERAL, JavaScriptSyntaxHighlightKeys.JS_NUMBER); - keys1.put(JSTokenTypes.STRING_LITERAL, JavaScriptSyntaxHighlightKeys.JS_STRING); - keys1.put(JSTokenTypes.SINGLE_QUOTE_STRING_LITERAL, JavaScriptSyntaxHighlightKeys.JS_STRING); - keys1.put(JSTokenTypes.INTERPOLATION_STRING_LITERAL, JavaScriptSyntaxHighlightKeys.JS_STRING); - keys1.put(JSTokenTypes.REGEXP_LITERAL, JavaScriptSyntaxHighlightKeys.JS_REGEXP); - - keys1.put(JSTokenTypes.LPAR, JavaScriptSyntaxHighlightKeys.JS_PARENTHS); - keys1.put(JSTokenTypes.RPAR, JavaScriptSyntaxHighlightKeys.JS_PARENTHS); - - keys1.put(JSTokenTypes.LBRACE, JavaScriptSyntaxHighlightKeys.JS_BRACES); - keys1.put(JSTokenTypes.RBRACE, JavaScriptSyntaxHighlightKeys.JS_BRACES); - - keys1.put(JSTokenTypes.LBRACKET, JavaScriptSyntaxHighlightKeys.JS_BRACKETS); - keys1.put(JSTokenTypes.RBRACKET, JavaScriptSyntaxHighlightKeys.JS_BRACKETS); - - keys1.put(JSTokenTypes.COMMA, JavaScriptSyntaxHighlightKeys.JS_COMMA); - keys1.put(JSTokenTypes.DOT, JavaScriptSyntaxHighlightKeys.JS_DOT); - keys1.put(JSTokenTypes.SEMICOLON, JavaScriptSyntaxHighlightKeys.JS_SEMICOLON); - - keys1.put(JSTokenTypes.C_STYLE_COMMENT, JavaScriptSyntaxHighlightKeys.JS_BLOCK_COMMENT); - keys1.put(JSTokenTypes.XML_STYLE_COMMENT, JavaScriptSyntaxHighlightKeys.JS_BLOCK_COMMENT); - keys1.put(JSTokenTypes.DOC_COMMENT, JavaScriptSyntaxHighlightKeys.JS_DOC_COMMENT); - keys1.put(JSTokenTypes.END_OF_LINE_COMMENT, JavaScriptSyntaxHighlightKeys.JS_LINE_COMMENT); - keys1.put(JSTokenTypes.BAD_CHARACTER, JavaScriptSyntaxHighlightKeys.JS_BAD_CHARACTER); - - keys1.put(JSDocTokenTypes.DOC_TAG_NAME, JavaScriptSyntaxHighlightKeys.JS_DOC_COMMENT); - keys2.put(JSDocTokenTypes.DOC_TAG_NAME, JavaScriptSyntaxHighlightKeys.JS_DOC_TAG); - - IElementType[] javadoc = IElementType.enumerate(new Processor() - { - @Override - public boolean process(IElementType type) - { - return type instanceof JSDocElementType; - } - }); - - for(IElementType type : javadoc) - { - keys1.put(type, JavaScriptSyntaxHighlightKeys.JS_DOC_COMMENT); - } - - keys1.put(JSTokenTypes.JSDOC_TAG_DATA, JavaScriptSyntaxHighlightKeys.JS_DOC_COMMENT); - - for(IElementType type : JSTokenTypes.XML_TOKENS.getTypes()) - { - keys1.put(type, XmlHighlighterColors.XML_TAG); - } - - keys2.put(JSTokenTypes.XML_TAG_NAME, XmlHighlighterColors.XML_TAG_NAME); - keys2.put(JSTokenTypes.XML_NAME, XmlHighlighterColors.XML_ATTRIBUTE_NAME); - keys2.put(JSTokenTypes.XML_ATTR_VALUE, XmlHighlighterColors.XML_ATTRIBUTE_VALUE); - keys2.put(JSTokenTypes.XML_ATTR_VALUE_END, XmlHighlighterColors.XML_ATTRIBUTE_VALUE); - keys2.put(JSTokenTypes.XML_ATTR_VALUE_START, XmlHighlighterColors.XML_ATTRIBUTE_VALUE); - keys2.put(JSTokenTypes.XML_ATTR_EQUAL, XmlHighlighterColors.XML_ATTRIBUTE_VALUE); - keys2.put(JSTokenTypes.XML_ENTITY_REF, XmlHighlighterColors.XML_ENTITY_REFERENCE); - - keys1.put(JSTokenTypes.XML_STYLE_COMMENT, XmlHighlighterColors.XML_COMMENT); - keys1.put(JSTokenTypes.XML_TAG_CONTENT, XmlHighlighterColors.XML_TAG_DATA); - } - - private Supplier myFactory; - - public JavaScriptHighlighter(@Nonnull Supplier factory) - { - myFactory = factory; - } - - @Nonnull - @Override - public Lexer getHighlightingLexer() - { - return new JavaScriptHighlightingLexer(myFactory); - } - - @Override - @Nonnull - public TextAttributesKey[] getTokenHighlights(IElementType tokenType) - { - return pack(keys1.get(tokenType), keys2.get(tokenType)); - } +public class JavaScriptHighlighter extends SyntaxHighlighterBase { + public static void storeDefaults(MultiMap keys) { + TokenSet operations = TokenSet.andNot(JSTokenTypes.OPERATIONS, TokenSet.create(JSTokenTypes.AS_KEYWORD, JSTokenTypes.IS_KEYWORD)); + + for (IElementType type : operations.getTypes()) { + keys.putValue(type, JavaScriptSyntaxHighlightKeys.JS_OPERATION_SIGN); + } + + for (IElementType type : JSTokenTypes.KEYWORDS.getTypes()) { + keys.putValue(type, JavaScriptSyntaxHighlightKeys.JS_KEYWORD); + } + + keys.putValue(StringEscapesTokenTypes.VALID_STRING_ESCAPE_TOKEN, JavaScriptSyntaxHighlightKeys.JS_VALID_STRING_ESCAPE); + keys.putValue(StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN, JavaScriptSyntaxHighlightKeys.JS_INVALID_STRING_ESCAPE); + keys.putValue(StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN, JavaScriptSyntaxHighlightKeys.JS_INVALID_STRING_ESCAPE); + + keys.putValue(JSTokenTypes.NUMERIC_LITERAL, JavaScriptSyntaxHighlightKeys.JS_NUMBER); + keys.putValue(JSTokenTypes.STRING_LITERAL, JavaScriptSyntaxHighlightKeys.JS_STRING); + keys.putValue(JSTokenTypes.SINGLE_QUOTE_STRING_LITERAL, JavaScriptSyntaxHighlightKeys.JS_STRING); + keys.putValue(JSTokenTypes.INTERPOLATION_STRING_LITERAL, JavaScriptSyntaxHighlightKeys.JS_STRING); + keys.putValue(JSTokenTypes.REGEXP_LITERAL, JavaScriptSyntaxHighlightKeys.JS_REGEXP); + + keys.putValue(JSTokenTypes.LPAR, JavaScriptSyntaxHighlightKeys.JS_PARENTHS); + keys.putValue(JSTokenTypes.RPAR, JavaScriptSyntaxHighlightKeys.JS_PARENTHS); + + keys.putValue(JSTokenTypes.LBRACE, JavaScriptSyntaxHighlightKeys.JS_BRACES); + keys.putValue(JSTokenTypes.RBRACE, JavaScriptSyntaxHighlightKeys.JS_BRACES); + + keys.putValue(JSTokenTypes.LBRACKET, JavaScriptSyntaxHighlightKeys.JS_BRACKETS); + keys.putValue(JSTokenTypes.RBRACKET, JavaScriptSyntaxHighlightKeys.JS_BRACKETS); + + keys.putValue(JSTokenTypes.COMMA, JavaScriptSyntaxHighlightKeys.JS_COMMA); + keys.putValue(JSTokenTypes.DOT, JavaScriptSyntaxHighlightKeys.JS_DOT); + keys.putValue(JSTokenTypes.SEMICOLON, JavaScriptSyntaxHighlightKeys.JS_SEMICOLON); + + keys.putValue(JSTokenTypes.C_STYLE_COMMENT, JavaScriptSyntaxHighlightKeys.JS_BLOCK_COMMENT); + keys.putValue(JSTokenTypes.XML_STYLE_COMMENT, JavaScriptSyntaxHighlightKeys.JS_BLOCK_COMMENT); + keys.putValue(JSTokenTypes.DOC_COMMENT, JavaScriptSyntaxHighlightKeys.JS_DOC_COMMENT); + keys.putValue(JSTokenTypes.END_OF_LINE_COMMENT, JavaScriptSyntaxHighlightKeys.JS_LINE_COMMENT); + keys.putValue(JSTokenTypes.BAD_CHARACTER, JavaScriptSyntaxHighlightKeys.JS_BAD_CHARACTER); + + keys.putValue(JSDocTokenTypes.DOC_TAG_NAME, JavaScriptSyntaxHighlightKeys.JS_DOC_COMMENT); + keys.putValue(JSDocTokenTypes.DOC_TAG_NAME, JavaScriptSyntaxHighlightKeys.JS_DOC_TAG); + + IElementType[] javadoc = IElementType.enumerate(type -> type instanceof JSDocElementType); + + for (IElementType type : javadoc) { + keys.putValue(type, JavaScriptSyntaxHighlightKeys.JS_DOC_COMMENT); + } + + keys.putValue(JSTokenTypes.JSDOC_TAG_DATA, JavaScriptSyntaxHighlightKeys.JS_DOC_COMMENT); + + for (IElementType type : JSTokenTypes.XML_TOKENS.getTypes()) { + keys.putValue(type, XmlHighlighterColors.XML_TAG); + } + + keys.putValue(JSTokenTypes.XML_TAG_NAME, XmlHighlighterColors.XML_TAG_NAME); + keys.putValue(JSTokenTypes.XML_NAME, XmlHighlighterColors.XML_ATTRIBUTE_NAME); + keys.putValue(JSTokenTypes.XML_ATTR_VALUE, XmlHighlighterColors.XML_ATTRIBUTE_VALUE); + keys.putValue(JSTokenTypes.XML_ATTR_VALUE_END, XmlHighlighterColors.XML_ATTRIBUTE_VALUE); + keys.putValue(JSTokenTypes.XML_ATTR_VALUE_START, XmlHighlighterColors.XML_ATTRIBUTE_VALUE); + keys.putValue(JSTokenTypes.XML_ATTR_EQUAL, XmlHighlighterColors.XML_ATTRIBUTE_VALUE); + keys.putValue(JSTokenTypes.XML_ENTITY_REF, XmlHighlighterColors.XML_ENTITY_REFERENCE); + + keys.putValue(JSTokenTypes.XML_STYLE_COMMENT, XmlHighlighterColors.XML_COMMENT); + keys.putValue(JSTokenTypes.XML_TAG_CONTENT, XmlHighlighterColors.XML_TAG_DATA); + } + + private final Supplier myFactory; + private final MultiMap keys = MultiMap.createLinked(); + + public JavaScriptHighlighter(@Nonnull Supplier factory) { + myFactory = factory; + + storeDefaults(keys); + } + + @Nonnull + @Override + public Lexer getHighlightingLexer() { + return new JavaScriptHighlightingLexer(myFactory); + } + + @Override + @Nonnull + public TextAttributesKey[] getTokenHighlights(IElementType tokenType) { + return keys.get(tokenType).toArray(new TextAttributesKey[0]); + } } diff --git a/base-impl/src/main/java/consulo/javascript/ide/hightlight/JavaScriptSyntaxHighlightFactory.java b/base-impl/src/main/java/consulo/javascript/ide/hightlight/JavaScriptSyntaxHighlightFactory.java index 7f49d869..817306e6 100644 --- a/base-impl/src/main/java/consulo/javascript/ide/hightlight/JavaScriptSyntaxHighlightFactory.java +++ b/base-impl/src/main/java/consulo/javascript/ide/hightlight/JavaScriptSyntaxHighlightFactory.java @@ -8,34 +8,29 @@ import consulo.language.editor.highlight.SyntaxHighlighter; import consulo.language.version.LanguageVersion; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 05.03.2015 */ @ExtensionImpl -public class JavaScriptSyntaxHighlightFactory extends LanguageVersionableSyntaxHighlighterFactory -{ - public JavaScriptSyntaxHighlightFactory() - { - } +public class JavaScriptSyntaxHighlightFactory extends LanguageVersionableSyntaxHighlighterFactory { + public JavaScriptSyntaxHighlightFactory() { + } - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } - @Nonnull - @Override - public SyntaxHighlighter getSyntaxHighlighter(@Nonnull LanguageVersion languageVersion) - { - if(languageVersion instanceof BaseJavaScriptLanguageVersion) - { - return ((BaseJavaScriptLanguageVersion) languageVersion).getSyntaxHighlighter(); - } - throw new IllegalArgumentException(languageVersion.toString()); - } + @Nonnull + @Override + public SyntaxHighlighter getSyntaxHighlighter(@Nonnull LanguageVersion languageVersion) { + if (languageVersion instanceof BaseJavaScriptLanguageVersion baseJavaScriptLanguageVersion) { + return baseJavaScriptLanguageVersion.getSyntaxHighlighter(); + } + throw new IllegalArgumentException(languageVersion.toString()); + } } diff --git a/base-impl/src/main/java/consulo/javascript/ide/hightlight/JavaScriptSyntaxHighlightKeys.java b/base-impl/src/main/java/consulo/javascript/ide/hightlight/JavaScriptSyntaxHighlightKeys.java index 7a70f997..f4a395f3 100644 --- a/base-impl/src/main/java/consulo/javascript/ide/hightlight/JavaScriptSyntaxHighlightKeys.java +++ b/base-impl/src/main/java/consulo/javascript/ide/hightlight/JavaScriptSyntaxHighlightKeys.java @@ -27,49 +27,64 @@ * @author VISTALL * @since 12.12.2015 */ -public interface JavaScriptSyntaxHighlightKeys -{ - TextAttributesKey JS_KEYWORD = TextAttributesKey.createTextAttributesKey("JS.KEYWORD", DefaultLanguageHighlighterColors.KEYWORD); +public interface JavaScriptSyntaxHighlightKeys { + TextAttributesKey JS_KEYWORD = TextAttributesKey.of("JS.KEYWORD", DefaultLanguageHighlighterColors.KEYWORD); - TextAttributesKey JS_STRING = TextAttributesKey.createTextAttributesKey("JS.STRING", DefaultLanguageHighlighterColors.STRING); + TextAttributesKey JS_STRING = TextAttributesKey.of("JS.STRING", DefaultLanguageHighlighterColors.STRING); - TextAttributesKey JS_NUMBER = TextAttributesKey.createTextAttributesKey("JS.NUMBER", DefaultLanguageHighlighterColors.NUMBER); + TextAttributesKey JS_NUMBER = TextAttributesKey.of("JS.NUMBER", DefaultLanguageHighlighterColors.NUMBER); - TextAttributesKey JS_REGEXP = TextAttributesKey.createTextAttributesKey("JS.REGEXP", DefaultLanguageHighlighterColors.NUMBER); + TextAttributesKey JS_REGEXP = TextAttributesKey.of("JS.REGEXP", DefaultLanguageHighlighterColors.NUMBER); - TextAttributesKey JS_LINE_COMMENT = TextAttributesKey.createTextAttributesKey("JS.LINE_COMMENT", DefaultLanguageHighlighterColors.LINE_COMMENT); + TextAttributesKey JS_LINE_COMMENT = TextAttributesKey.of("JS.LINE_COMMENT", DefaultLanguageHighlighterColors.LINE_COMMENT); - TextAttributesKey JS_BLOCK_COMMENT = TextAttributesKey.createTextAttributesKey("JS.BLOCK_COMMENT", DefaultLanguageHighlighterColors.BLOCK_COMMENT); + TextAttributesKey JS_BLOCK_COMMENT = + TextAttributesKey.of("JS.BLOCK_COMMENT", DefaultLanguageHighlighterColors.BLOCK_COMMENT); - TextAttributesKey JS_DOC_COMMENT = TextAttributesKey.createTextAttributesKey("JS.DOC_COMMENT", DefaultLanguageHighlighterColors.DOC_COMMENT); + TextAttributesKey JS_DOC_COMMENT = TextAttributesKey.of("JS.DOC_COMMENT", DefaultLanguageHighlighterColors.DOC_COMMENT); - TextAttributesKey JS_OPERATION_SIGN = TextAttributesKey.createTextAttributesKey("JS.OPERATION_SIGN", DefaultLanguageHighlighterColors.OPERATION_SIGN); + TextAttributesKey JS_OPERATION_SIGN = + TextAttributesKey.of("JS.OPERATION_SIGN", DefaultLanguageHighlighterColors.OPERATION_SIGN); - TextAttributesKey JS_PARENTHS = TextAttributesKey.createTextAttributesKey("JS.PARENTHS", DefaultLanguageHighlighterColors.PARENTHESES); + TextAttributesKey JS_PARENTHS = TextAttributesKey.of("JS.PARENTHS", DefaultLanguageHighlighterColors.PARENTHESES); - TextAttributesKey JS_BRACKETS = TextAttributesKey.createTextAttributesKey("JS.BRACKETS", DefaultLanguageHighlighterColors.BRACKETS); + TextAttributesKey JS_BRACKETS = TextAttributesKey.of("JS.BRACKETS", DefaultLanguageHighlighterColors.BRACKETS); - TextAttributesKey JS_BRACES = TextAttributesKey.createTextAttributesKey("JS.BRACES", DefaultLanguageHighlighterColors.BRACES); + TextAttributesKey JS_BRACES = TextAttributesKey.of("JS.BRACES", DefaultLanguageHighlighterColors.BRACES); - TextAttributesKey JS_COMMA = TextAttributesKey.createTextAttributesKey("JS.COMMA", DefaultLanguageHighlighterColors.COMMA); + TextAttributesKey JS_COMMA = TextAttributesKey.of("JS.COMMA", DefaultLanguageHighlighterColors.COMMA); - TextAttributesKey JS_DOT = TextAttributesKey.createTextAttributesKey("JS.DOT", DefaultLanguageHighlighterColors.DOT); + TextAttributesKey JS_DOT = TextAttributesKey.of("JS.DOT", DefaultLanguageHighlighterColors.DOT); - TextAttributesKey JS_SEMICOLON = TextAttributesKey.createTextAttributesKey("JS.SEMICOLON", DefaultLanguageHighlighterColors.SEMICOLON); + TextAttributesKey JS_SEMICOLON = TextAttributesKey.of("JS.SEMICOLON", DefaultLanguageHighlighterColors.SEMICOLON); - TextAttributesKey JS_BAD_CHARACTER = TextAttributesKey.createTextAttributesKey("JS.BADCHARACTER", HighlighterColors.BAD_CHARACTER); - TextAttributesKey JS_DOC_TAG = TextAttributesKey.createTextAttributesKey("JS.DOC_TAG", DefaultLanguageHighlighterColors.DOC_COMMENT_TAG); - TextAttributesKey JS_DOC_MARKUP = TextAttributesKey.createTextAttributesKey("JS.DOC_MARKUP", DefaultLanguageHighlighterColors.DOC_COMMENT_MARKUP); - TextAttributesKey JS_VALID_STRING_ESCAPE = TextAttributesKey.createTextAttributesKey("JS.VALID_STRING_ESCAPE",DefaultLanguageHighlighterColors.VALID_STRING_ESCAPE); - TextAttributesKey JS_INVALID_STRING_ESCAPE = TextAttributesKey.createTextAttributesKey("JS.INVALID_STRING_ESCAPE", DefaultLanguageHighlighterColors.INVALID_STRING_ESCAPE); - TextAttributesKey JS_LOCAL_VARIABLE = TextAttributesKey.createTextAttributesKey("JS.LOCAL_VARIABLE", DefaultLanguageHighlighterColors.LOCAL_VARIABLE); - TextAttributesKey JS_PARAMETER = TextAttributesKey.createTextAttributesKey("JS.PARAMETER", DefaultLanguageHighlighterColors.PARAMETER); - TextAttributesKey JS_INSTANCE_MEMBER_VARIABLE = TextAttributesKey.createTextAttributesKey("JS.INSTANCE_MEMBER_VARIABLE", DefaultLanguageHighlighterColors.INSTANCE_FIELD); - TextAttributesKey JS_STATIC_MEMBER_VARIABLE = TextAttributesKey.createTextAttributesKey("JS.STATIC_MEMBER_VARIABLE",DefaultLanguageHighlighterColors.STATIC_FIELD); - TextAttributesKey JS_GLOBAL_VARIABLE = TextAttributesKey.createTextAttributesKey("JS.GLOBAL_VARIABLE", DefaultLanguageHighlighterColors.STATIC_FIELD); - TextAttributesKey JS_GLOBAL_FUNCTION = TextAttributesKey.createTextAttributesKey("JS.GLOBAL_FUNCTION", DefaultLanguageHighlighterColors.STATIC_METHOD); - TextAttributesKey JS_STATIC_MEMBER_FUNCTION = TextAttributesKey.createTextAttributesKey("JS.STATIC_MEMBER_FUNCTION", DefaultLanguageHighlighterColors.STATIC_METHOD); - TextAttributesKey JS_INSTANCE_MEMBER_FUNCTION = TextAttributesKey.createTextAttributesKey("JS.INSTANCE_MEMBER_FUNCTION", new TextAttributes(new RGBColor(0x7a, 0x7a, 43), StandardColors.WHITE, null, null,0)); + TextAttributesKey JS_BAD_CHARACTER = TextAttributesKey.of("JS.BADCHARACTER", HighlighterColors.BAD_CHARACTER); + TextAttributesKey JS_DOC_TAG = TextAttributesKey.of("JS.DOC_TAG", DefaultLanguageHighlighterColors.DOC_COMMENT_TAG); + TextAttributesKey JS_DOC_MARKUP = TextAttributesKey.of("JS.DOC_MARKUP", DefaultLanguageHighlighterColors.DOC_COMMENT_MARKUP); + TextAttributesKey JS_VALID_STRING_ESCAPE = + TextAttributesKey.of("JS.VALID_STRING_ESCAPE", DefaultLanguageHighlighterColors.VALID_STRING_ESCAPE); + TextAttributesKey JS_INVALID_STRING_ESCAPE = + TextAttributesKey.of("JS.INVALID_STRING_ESCAPE", DefaultLanguageHighlighterColors.INVALID_STRING_ESCAPE); + TextAttributesKey JS_LOCAL_VARIABLE = + TextAttributesKey.of("JS.LOCAL_VARIABLE", DefaultLanguageHighlighterColors.LOCAL_VARIABLE); + TextAttributesKey JS_PARAMETER = TextAttributesKey.of("JS.PARAMETER", DefaultLanguageHighlighterColors.PARAMETER); + TextAttributesKey JS_INSTANCE_MEMBER_VARIABLE = + TextAttributesKey.of("JS.INSTANCE_MEMBER_VARIABLE", DefaultLanguageHighlighterColors.INSTANCE_FIELD); + TextAttributesKey JS_STATIC_MEMBER_VARIABLE = + TextAttributesKey.of("JS.STATIC_MEMBER_VARIABLE", DefaultLanguageHighlighterColors.STATIC_FIELD); + TextAttributesKey JS_GLOBAL_VARIABLE = + TextAttributesKey.of("JS.GLOBAL_VARIABLE", DefaultLanguageHighlighterColors.STATIC_FIELD); + TextAttributesKey JS_GLOBAL_FUNCTION = + TextAttributesKey.of("JS.GLOBAL_FUNCTION", DefaultLanguageHighlighterColors.STATIC_METHOD); + TextAttributesKey JS_STATIC_MEMBER_FUNCTION = + TextAttributesKey.of("JS.STATIC_MEMBER_FUNCTION", DefaultLanguageHighlighterColors.STATIC_METHOD); + TextAttributesKey JS_INSTANCE_MEMBER_FUNCTION = TextAttributesKey.createTextAttributesKey( + "JS.INSTANCE_MEMBER_FUNCTION", + new TextAttributes(new RGBColor(0x7a, 0x7a, 43), StandardColors.WHITE, null, null, 0) + ); - TextAttributesKey JS_METADATA = TextAttributesKey.createTextAttributesKey("JS.ATTRIBUTE", new TextAttributes(null, new RGBColor(0xf7, 0xe9, 0xe9), null, null, 0)); + TextAttributesKey JS_METADATA = TextAttributesKey.createTextAttributesKey( + "JS.ATTRIBUTE", + new TextAttributes(null, new RGBColor(0xf7, 0xe9, 0xe9), null, null, 0) + ); } diff --git a/base-impl/src/main/java/consulo/javascript/impl/language/JavaScriptQuoteHandler.java b/base-impl/src/main/java/consulo/javascript/impl/language/JavaScriptQuoteHandler.java index 0a049df1..68f444f7 100644 --- a/base-impl/src/main/java/consulo/javascript/impl/language/JavaScriptQuoteHandler.java +++ b/base-impl/src/main/java/consulo/javascript/impl/language/JavaScriptQuoteHandler.java @@ -27,63 +27,54 @@ import consulo.language.editor.action.SimpleTokenSetQuoteHandler; import consulo.language.psi.PsiElement; import consulo.virtualFileSystem.fileType.FileType; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 09.12.2015 */ @ExtensionImpl -public class JavaScriptQuoteHandler extends SimpleTokenSetQuoteHandler implements JavaLikeQuoteHandler, FileQuoteHandler -{ - public JavaScriptQuoteHandler() - { - super(JavaScriptTokenSets.STRING_LITERALS); - } +public class JavaScriptQuoteHandler extends SimpleTokenSetQuoteHandler implements JavaLikeQuoteHandler, FileQuoteHandler { + public JavaScriptQuoteHandler() { + super(JavaScriptTokenSets.STRING_LITERALS); + } - @Override - public TokenSet getConcatenatableStringTokenTypes() - { - return TokenSet.EMPTY; - } + @Override + public TokenSet getConcatenatableStringTokenTypes() { + return TokenSet.EMPTY; + } - @Override - public String getStringConcatenationOperatorRepresentation() - { - return ""; - } + @Override + public String getStringConcatenationOperatorRepresentation() { + return ""; + } - @Override - public TokenSet getStringTokenTypes() - { - return myLiteralTokenSet; - } + @Override + public TokenSet getStringTokenTypes() { + return myLiteralTokenSet; + } - @Override - public boolean isAppropriateElementTypeForLiteral(@Nonnull IElementType tokenType) - { - return JavaScriptTokenSets.COMMENTS.contains(tokenType) || - tokenType == JSTokenTypes.WHITE_SPACE || - tokenType == JSTokenTypes.SEMICOLON || - tokenType == JSTokenTypes.COMMA || - tokenType == JSTokenTypes.RPAR || - tokenType == JSTokenTypes.RBRACKET || - tokenType == JSTokenTypes.RBRACE || - tokenType == JSTokenTypes.SINGLE_QUOTE_STRING_LITERAL || - tokenType == JSTokenTypes.STRING_LITERAL; - } + @Override + public boolean isAppropriateElementTypeForLiteral(@Nonnull IElementType tokenType) { + return JavaScriptTokenSets.COMMENTS.contains(tokenType) + || tokenType == JSTokenTypes.WHITE_SPACE + || tokenType == JSTokenTypes.SEMICOLON + || tokenType == JSTokenTypes.COMMA + || tokenType == JSTokenTypes.RPAR + || tokenType == JSTokenTypes.RBRACKET + || tokenType == JSTokenTypes.RBRACE + || tokenType == JSTokenTypes.SINGLE_QUOTE_STRING_LITERAL + || tokenType == JSTokenTypes.STRING_LITERAL; + } - @Override - public boolean needParenthesesAroundConcatenation(PsiElement element) - { - return false; - } + @Override + public boolean needParenthesesAroundConcatenation(PsiElement element) { + return false; + } - @Nonnull - @Override - public FileType getFileType() - { - return JavaScriptFileType.INSTANCE; - } + @Nonnull + @Override + public FileType getFileType() { + return JavaScriptFileType.INSTANCE; + } } diff --git a/base-impl/src/main/java/consulo/javascript/impl/language/psi/JSComputedNameImpl.java b/base-impl/src/main/java/consulo/javascript/impl/language/psi/JSComputedNameImpl.java index 2ab51448..c4ffeca9 100644 --- a/base-impl/src/main/java/consulo/javascript/impl/language/psi/JSComputedNameImpl.java +++ b/base-impl/src/main/java/consulo/javascript/impl/language/psi/JSComputedNameImpl.java @@ -22,30 +22,26 @@ import consulo.javascript.psi.JSComputedName; import consulo.language.ast.ASTNode; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL * @since 03.03.2016 */ -public class JSComputedNameImpl extends JSElementImpl implements JSComputedName -{ - public JSComputedNameImpl(ASTNode node) - { - super(node); - } +public class JSComputedNameImpl extends JSElementImpl implements JSComputedName { + public JSComputedNameImpl(ASTNode node) { + super(node); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSElement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSElement(this); + } - @Nullable - @Override - public JSExpression getExpression() - { - return findChildByClass(JSExpression.class); - } + @Nullable + @Override + public JSExpression getExpression() { + return findChildByClass(JSExpression.class); + } } diff --git a/base-impl/src/main/java/consulo/javascript/impl/language/psi/JSElementFactory.java b/base-impl/src/main/java/consulo/javascript/impl/language/psi/JSElementFactory.java index f2aaa804..caf081d8 100644 --- a/base-impl/src/main/java/consulo/javascript/impl/language/psi/JSElementFactory.java +++ b/base-impl/src/main/java/consulo/javascript/impl/language/psi/JSElementFactory.java @@ -20,23 +20,19 @@ import com.intellij.lang.javascript.psi.impl.JSExpressionCodeFragmentImpl; import consulo.language.psi.PsiElement; import consulo.project.Project; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author nik */ -public class JSElementFactory -{ - private JSElementFactory() - { - } +public class JSElementFactory { + private JSElementFactory() { + } - @Nonnull - public static JSFile createExpressionCodeFragment(@Nonnull Project project, CharSequence text, PsiElement context, boolean isPhysical) - { - JSExpressionCodeFragmentImpl codeFragment = new JSExpressionCodeFragmentImpl(project, "fragment.js", text, isPhysical); - codeFragment.setContext(context); - return codeFragment; - } + @Nonnull + public static JSFile createExpressionCodeFragment(@Nonnull Project project, CharSequence text, PsiElement context, boolean isPhysical) { + JSExpressionCodeFragmentImpl codeFragment = new JSExpressionCodeFragmentImpl(project, "fragment.js", text, isPhysical); + codeFragment.setContext(context); + return codeFragment; + } } diff --git a/base-impl/src/main/java/consulo/javascript/impl/language/psi/JSStubElementType.java b/base-impl/src/main/java/consulo/javascript/impl/language/psi/JSStubElementType.java index 70ce3c05..0c282b79 100644 --- a/base-impl/src/main/java/consulo/javascript/impl/language/psi/JSStubElementType.java +++ b/base-impl/src/main/java/consulo/javascript/impl/language/psi/JSStubElementType.java @@ -26,30 +26,26 @@ import consulo.language.psi.stub.IStubElementType; import consulo.language.psi.stub.IndexSink; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; -public abstract class JSStubElementType, PsiT extends JSElement> extends IStubElementType implements IElementTypeAsPsiFactory -{ - public JSStubElementType(String debugName) - { - super(debugName, JavaScriptLanguage.INSTANCE); - } +public abstract class JSStubElementType, PsiT extends JSElement> extends IStubElementType + implements IElementTypeAsPsiFactory { + public JSStubElementType(String debugName) { + super(debugName, JavaScriptLanguage.INSTANCE); + } - @Override - public String toString() - { - return "js." + super.toString(); - } + @Override + public String toString() { + return "js." + super.toString(); + } - @Override - public void indexStub(@Nonnull final StubT stub, @Nonnull final IndexSink sink) - { - } + @Override + public void indexStub(@Nonnull StubT stub, @Nonnull IndexSink sink) { + } - @Nonnull - @Override - public String getExternalId() - { - return toString(); - } + @Nonnull + @Override + public String getExternalId() { + return toString(); + } } \ No newline at end of file diff --git a/base-impl/src/main/java/consulo/javascript/impl/language/psi/JavaScriptLambdaExpressionImpl.java b/base-impl/src/main/java/consulo/javascript/impl/language/psi/JavaScriptLambdaExpressionImpl.java index bb0a63b1..6096157e 100644 --- a/base-impl/src/main/java/consulo/javascript/impl/language/psi/JavaScriptLambdaExpressionImpl.java +++ b/base-impl/src/main/java/consulo/javascript/impl/language/psi/JavaScriptLambdaExpressionImpl.java @@ -30,129 +30,114 @@ import consulo.language.psi.resolve.PsiScopeProcessor; import consulo.language.psi.resolve.ResolveState; import consulo.language.util.IncorrectOperationException; -import org.jetbrains.annotations.NonNls; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL * @since 03.03.2016 */ -public class JavaScriptLambdaExpressionImpl extends JSExpressionImpl implements JavaScriptLambdaExpression -{ - public JavaScriptLambdaExpressionImpl(ASTNode node) - { - super(node); - } - - @Override - @RequiredReadAction - public boolean processDeclarations(@Nonnull PsiScopeProcessor processor, @Nonnull ResolveState state, PsiElement lastParent, @Nonnull PsiElement place) - { - if(lastParent != null && lastParent.getParent() == this) - { - final JSParameter[] params = getParameterList().getParameters(); - for(JSParameter param : params) - { - if(!processor.execute(param, state)) - { - return false; - } - } - - boolean b = JSResolveUtil.processDeclarationsInScope(this, processor, state, lastParent, place); - if(b) - { - processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, this); - } - return b; - } - - return processor.execute(this, state); - } - - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitLambdaExpression(this); - } - - @RequiredReadAction - @Nonnull - @Override - public JSParameterList getParameterList() - { - return findNotNullChildByClass(JSParameterList.class); - } - - @Override - public JSSourceElement[] getBody() - { - final ASTNode[] children = getNode().getChildren(JSElementTypes.SOURCE_ELEMENTS); - if(children.length == 0) - { - return JSSourceElement.EMPTY_ARRAY; - } - JSSourceElement[] result = new JSSourceElement[children.length]; - for(int i = 0; i < children.length; i++) - { - result[i] = (JSSourceElement) children[i].getPsi(); - } - return result; - } - - @Nonnull - @Override - public JavaScriptType getReturnType() - { - return JavaScriptType.UNKNOWN; - } - - @Override - public String getReturnTypeString() - { - return null; - } - - @Nullable - @Override - public JavaScriptTypeElement getReturnTypeElement() - { - return null; - } - - @Override - public boolean isDeprecated() - { - return false; - } - - @Nullable - @Override - public JSAttributeList getAttributeList() - { - return null; - } - - @Override - public String getQualifiedName() - { - return null; - } - - @RequiredReadAction - @Nullable - @Override - public PsiElement getNameIdentifier() - { - return null; - } - - @RequiredWriteAction - @Override - public PsiElement setName(@Nonnull @NonNls String name) throws IncorrectOperationException - { - return null; - } +public class JavaScriptLambdaExpressionImpl extends JSExpressionImpl implements JavaScriptLambdaExpression { + public JavaScriptLambdaExpressionImpl(ASTNode node) { + super(node); + } + + @Override + @RequiredReadAction + public boolean processDeclarations( + @Nonnull PsiScopeProcessor processor, + @Nonnull ResolveState state, + PsiElement lastParent, + @Nonnull PsiElement place + ) { + if (lastParent != null && lastParent.getParent() == this) { + JSParameter[] params = getParameterList().getParameters(); + for (JSParameter param : params) { + if (!processor.execute(param, state)) { + return false; + } + } + + boolean b = JSResolveUtil.processDeclarationsInScope(this, processor, state, lastParent, place); + if (b) { + processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, this); + } + return b; + } + + return processor.execute(this, state); + } + + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitLambdaExpression(this); + } + + @RequiredReadAction + @Nonnull + @Override + public JSParameterList getParameterList() { + return findNotNullChildByClass(JSParameterList.class); + } + + @Override + @RequiredReadAction + public JSSourceElement[] getBody() { + ASTNode[] children = getNode().getChildren(JSElementTypes.SOURCE_ELEMENTS); + if (children.length == 0) { + return JSSourceElement.EMPTY_ARRAY; + } + JSSourceElement[] result = new JSSourceElement[children.length]; + for (int i = 0; i < children.length; i++) { + result[i] = (JSSourceElement)children[i].getPsi(); + } + return result; + } + + @Nonnull + @Override + public JavaScriptType getReturnType() { + return JavaScriptType.UNKNOWN; + } + + @Override + public String getReturnTypeString() { + return null; + } + + @Nullable + @Override + public JavaScriptTypeElement getReturnTypeElement() { + return null; + } + + @Override + public boolean isDeprecated() { + return false; + } + + @Nullable + @Override + public JSAttributeList getAttributeList() { + return null; + } + + @Override + @RequiredReadAction + public String getQualifiedName() { + return null; + } + + @RequiredReadAction + @Nullable + @Override + public PsiElement getNameIdentifier() { + return null; + } + + @RequiredWriteAction + @Override + public PsiElement setName(@Nonnull String name) throws IncorrectOperationException { + return null; + } } diff --git a/base-impl/src/main/java/consulo/javascript/impl/language/psi/JavaScriptSpreadExpressionImpl.java b/base-impl/src/main/java/consulo/javascript/impl/language/psi/JavaScriptSpreadExpressionImpl.java index 4001d56f..899eb54f 100644 --- a/base-impl/src/main/java/consulo/javascript/impl/language/psi/JavaScriptSpreadExpressionImpl.java +++ b/base-impl/src/main/java/consulo/javascript/impl/language/psi/JavaScriptSpreadExpressionImpl.java @@ -8,43 +8,37 @@ import consulo.javascript.language.psi.JavaScriptType; import consulo.language.ast.ASTNode; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 2020-01-01 */ -public class JavaScriptSpreadExpressionImpl extends JSElementImpl implements JSSpreadExpression -{ - public JavaScriptSpreadExpressionImpl(ASTNode node) - { - super(node); - } +public class JavaScriptSpreadExpressionImpl extends JSElementImpl implements JSSpreadExpression { + public JavaScriptSpreadExpressionImpl(ASTNode node) { + super(node); + } - @Override - public JSExpression getInnerExpression() - { - return findNotNullChildByClass(JSExpression.class); - } + @Override + public JSExpression getInnerExpression() { + return findNotNullChildByClass(JSExpression.class); + } - @Nonnull - @Override - public JSExpression replace(JSExpression other) - { - return this; - } + @Nonnull + @Override + public JSExpression replace(JSExpression other) { + return this; + } - @RequiredReadAction - @Nonnull - @Override - public JavaScriptType getType() - { - return JavaScriptType.UNKNOWN; - } + @RequiredReadAction + @Nonnull + @Override + public JavaScriptType getType() { + return JavaScriptType.UNKNOWN; + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSElement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSElement(this); + } } diff --git a/base-impl/src/main/java/consulo/javascript/impl/language/psi/stub/JSFileStubImpl.java b/base-impl/src/main/java/consulo/javascript/impl/language/psi/stub/JSFileStubImpl.java index 7100e0eb..6b07f129 100644 --- a/base-impl/src/main/java/consulo/javascript/impl/language/psi/stub/JSFileStubImpl.java +++ b/base-impl/src/main/java/consulo/javascript/impl/language/psi/stub/JSFileStubImpl.java @@ -7,39 +7,34 @@ import consulo.language.psi.stub.IStubFileElementType; import consulo.language.psi.stub.PsiFileStubImpl; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL * @since 19.07.2015 */ -public class JSFileStubImpl extends PsiFileStubImpl implements JSFileStub -{ - private StringRef myName; +public class JSFileStubImpl extends PsiFileStubImpl implements JSFileStub { + private StringRef myName; - public JSFileStubImpl(@Nullable JSFile file, @Nonnull String name) - { - super(file); - myName = StringRef.fromString(name); - } + public JSFileStubImpl(@Nullable JSFile file, @Nonnull String name) { + super(file); + myName = StringRef.fromString(name); + } - public JSFileStubImpl(@Nullable JSFile file, @Nonnull StringRef name) - { - super(file); - myName = name; - } + public JSFileStubImpl(@Nullable JSFile file, @Nonnull StringRef name) { + super(file); + myName = name; + } - @Override - public IStubFileElementType getType() - { - return JSElementTypes.FILE; - } + @Override + public IStubFileElementType getType() { + return JSElementTypes.FILE; + } - @Nonnull - @Override - public String getName() - { - return StringRef.toString(myName); - } + @Nonnull + @Override + public String getName() { + return StringRef.toString(myName); + } } diff --git a/base-impl/src/main/java/consulo/javascript/impl/language/psi/stub/JavaScriptClassNameIndex.java b/base-impl/src/main/java/consulo/javascript/impl/language/psi/stub/JavaScriptClassNameIndex.java index 241ee73e..fcbe10c6 100644 --- a/base-impl/src/main/java/consulo/javascript/impl/language/psi/stub/JavaScriptClassNameIndex.java +++ b/base-impl/src/main/java/consulo/javascript/impl/language/psi/stub/JavaScriptClassNameIndex.java @@ -25,18 +25,16 @@ import consulo.language.psi.stub.StringStubIndexExtension; import consulo.language.psi.stub.StubIndexKey; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL */ @ExtensionImpl -public class JavaScriptClassNameIndex extends StringStubIndexExtension -{ - @Nonnull - @Override - public StubIndexKey getKey() - { - return JavaScriptIndexKeys.CLASSES_BY_NAME; - } +public class JavaScriptClassNameIndex extends StringStubIndexExtension { + @Nonnull + @Override + public StubIndexKey getKey() { + return JavaScriptIndexKeys.CLASSES_BY_NAME; + } } \ No newline at end of file diff --git a/base-impl/src/main/java/consulo/javascript/inspections/qucikFixes/CreateJSFunctionFixBase.java b/base-impl/src/main/java/consulo/javascript/inspections/qucikFixes/CreateJSFunctionFixBase.java index 30741b9d..72c482d4 100644 --- a/base-impl/src/main/java/consulo/javascript/inspections/qucikFixes/CreateJSFunctionFixBase.java +++ b/base-impl/src/main/java/consulo/javascript/inspections/qucikFixes/CreateJSFunctionFixBase.java @@ -14,10 +14,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package consulo.javascript.inspections.qucikFixes; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.inspections.qucikFixes.BaseCreateFix; import com.intellij.lang.javascript.psi.JSClass; import com.intellij.lang.javascript.psi.JSReferenceExpression; @@ -26,84 +24,77 @@ import consulo.language.editor.template.Template; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiFile; -import org.jetbrains.annotations.PropertyKey; +import consulo.localize.LocalizeValue; + +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; import java.util.Set; /** -* @author VISTALL -* @since 24.02.2016 -*/ -public abstract class CreateJSFunctionFixBase extends BaseCreateFix -{ - private final String myName; - private final String myIntentionNameKey; - - public CreateJSFunctionFixBase(String name, @PropertyKey(resourceBundle = JavaScriptBundle.BUNDLE) String nameKey) - { - myName = name; - myIntentionNameKey = nameKey; - } - - @Override - @Nonnull - public String getName() - { - return JavaScriptBundle.message(myIntentionNameKey, myName); - } - - @Override - @Nonnull - public String getFamilyName() - { - return JavaScriptBundle.message("javascript.create.function.intention.family"); - } - - @RequiredReadAction - @Override - protected void buildTemplate(Template template, JSReferenceExpression referenceExpression, Set features, boolean staticContext, PsiFile file, - PsiElement anchorParent) - { - boolean classFeature = features.contains(JavaScriptFeature.CLASS); - String referencedName = classFeature ? referenceExpression.getReferencedName() : referenceExpression.getText(); - BaseCreateFix.addAccessModifier(template, referenceExpression, classFeature, staticContext); - writeFunctionAndName(template, referencedName, features); - template.addTextSegment("("); - - addParameters(template, referenceExpression, file, features); - - template.addTextSegment(")"); - - if(classFeature) - { - template.addTextSegment(":"); - addReturnType(template, referenceExpression, file); - } - - JSClass clazz = BaseCreateFix.findClass(file, anchorParent); - if(clazz == null || !clazz.isInterface()) - { - template.addTextSegment(" {"); - addBody(template, referenceExpression, file); - template.addTextSegment("}"); - } - else - { - addSemicolonSegment(template, file); - template.addEndVariable(); - } - } - - protected void writeFunctionAndName(Template template, String referencedName, Set features) - { - template.addTextSegment("function "); - template.addTextSegment(referencedName); - } - - protected abstract void addParameters(Template template, JSReferenceExpression refExpr, PsiFile file, Set features); - - protected abstract void addReturnType(Template template, JSReferenceExpression referenceExpression, PsiFile psifile); - - protected abstract void addBody(Template template, JSReferenceExpression refExpr, PsiFile file); + * @author VISTALL + * @since 2016-02-24 + */ +public abstract class CreateJSFunctionFixBase extends BaseCreateFix { + @Nonnull + private final LocalizeValue myMessage; + + public CreateJSFunctionFixBase(@Nonnull LocalizeValue message) { + myMessage = message; + } + + @Override + @Nonnull + public LocalizeValue getName() { + return myMessage; + } + + @RequiredReadAction + @Override + protected void buildTemplate( + Template template, + JSReferenceExpression referenceExpression, + Set features, + boolean staticContext, + PsiFile file, + PsiElement anchorParent + ) { + boolean classFeature = features.contains(JavaScriptFeature.CLASS); + String referencedName = classFeature ? referenceExpression.getReferencedName() : referenceExpression.getText(); + BaseCreateFix.addAccessModifier(template, referenceExpression, classFeature, staticContext); + writeFunctionAndName(template, referencedName, features); + template.addTextSegment("("); + + addParameters(template, referenceExpression, file, features); + + template.addTextSegment(")"); + + if (classFeature) { + template.addTextSegment(":"); + addReturnType(template, referenceExpression, file); + } + + JSClass clazz = BaseCreateFix.findClass(file, anchorParent); + if (clazz == null || !clazz.isInterface()) { + template.addTextSegment(" {"); + addBody(template, referenceExpression, file); + template.addTextSegment("}"); + } + else { + addSemicolonSegment(template, file); + template.addEndVariable(); + } + } + + protected void writeFunctionAndName(Template template, String referencedName, Set features) { + template.addTextSegment("function "); + template.addTextSegment(referencedName); + } + + @RequiredReadAction + protected abstract void addParameters(Template template, JSReferenceExpression refExpr, PsiFile file, Set features); + + @RequiredReadAction + protected abstract void addReturnType(Template template, JSReferenceExpression referenceExpression, PsiFile psifile); + + protected abstract void addBody(Template template, JSReferenceExpression refExpr, PsiFile file); } diff --git a/base-impl/src/main/java/consulo/javascript/lang/BaseJavaScriptLanguageVersion.java b/base-impl/src/main/java/consulo/javascript/lang/BaseJavaScriptLanguageVersion.java index fb890b73..d5d79e22 100644 --- a/base-impl/src/main/java/consulo/javascript/lang/BaseJavaScriptLanguageVersion.java +++ b/base-impl/src/main/java/consulo/javascript/lang/BaseJavaScriptLanguageVersion.java @@ -9,7 +9,8 @@ import consulo.language.editor.highlight.SyntaxHighlighter; import consulo.language.parser.PsiParser; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; + import java.util.LinkedHashSet; import java.util.Set; @@ -17,56 +18,49 @@ * @author VISTALL * @since 24.08.14 */ -public abstract class BaseJavaScriptLanguageVersion extends JavaScriptLanguageVersion -{ - private static TokenSet ourLiterals = TokenSet.orSet(JavaScriptTokenSets.STRING_LITERALS, TokenSet.create(JSTokenTypes.NUMERIC_LITERAL)); +public abstract class BaseJavaScriptLanguageVersion extends JavaScriptLanguageVersion { + private static TokenSet ourLiterals = + TokenSet.orSet(JavaScriptTokenSets.STRING_LITERALS, TokenSet.create(JSTokenTypes.NUMERIC_LITERAL)); - private Set myFeatures = new LinkedHashSet<>(); + private Set myFeatures = new LinkedHashSet<>(); - public BaseJavaScriptLanguageVersion(String name, String... mimeTypes) - { - super(name, name, JavaScriptLanguage.INSTANCE, mimeTypes); - } + public BaseJavaScriptLanguageVersion(String name, String... mimeTypes) { + super(name, name, JavaScriptLanguage.INSTANCE, mimeTypes); + } - protected void addFeature(@Nonnull JavaScriptFeature feature) - { - myFeatures.add(feature); - } + protected void addFeature(@Nonnull JavaScriptFeature feature) { + myFeatures.add(feature); + } - @Nonnull - public Set getFeatures() - { - return myFeatures; - } + @Nonnull + public Set getFeatures() { + return myFeatures; + } - @Nonnull - public abstract SyntaxHighlighter getSyntaxHighlighter(); + @Nonnull + public abstract SyntaxHighlighter getSyntaxHighlighter(); - @Nonnull - @Override - public PsiParser createParser() - { - return new JavaScriptParser(); - } + @Nonnull + @Override + public PsiParser createParser() { + return new JavaScriptParser(); + } - @Nonnull - @Override - public TokenSet getWhitespaceTokens() - { - return JavaScriptTokenSets.WHITE_SPACES; - } + @Nonnull + @Override + public TokenSet getWhitespaceTokens() { + return JavaScriptTokenSets.WHITE_SPACES; + } - @Nonnull - @Override - public TokenSet getCommentTokens() - { - return JSTokenTypes.COMMENTS; - } + @Nonnull + @Override + public TokenSet getCommentTokens() { + return JSTokenTypes.COMMENTS; + } - @Nonnull - @Override - public TokenSet getStringLiteralElements() - { - return ourLiterals; - } + @Nonnull + @Override + public TokenSet getStringLiteralElements() { + return ourLiterals; + } } diff --git a/base-impl/src/main/java/consulo/javascript/lang/JavaScript15LanguageVersion.java b/base-impl/src/main/java/consulo/javascript/lang/JavaScript15LanguageVersion.java index a525c6f5..79efc92b 100644 --- a/base-impl/src/main/java/consulo/javascript/lang/JavaScript15LanguageVersion.java +++ b/base-impl/src/main/java/consulo/javascript/lang/JavaScript15LanguageVersion.java @@ -4,11 +4,12 @@ import consulo.javascript.ide.hightlight.JavaScriptHighlighter; import consulo.javascript.lang.lexer.JavaScript15Lexer; import consulo.javascript.language.JavaScriptLanguage; -import consulo.javascript.language.StandardJavaScriptVersions; +import consulo.javascript.language.StandardJavaScriptVersion; import consulo.language.editor.highlight.SyntaxHighlighter; import consulo.language.lexer.Lexer; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; + import java.util.function.Supplier; /** @@ -16,44 +17,38 @@ * @since 05.03.2015 */ @ExtensionImpl -public class JavaScript15LanguageVersion extends BaseJavaScriptLanguageVersion implements StandardJavaScriptVersions.Marker -{ - private static final Supplier ourLexerFactory = () -> new JavaScript15Lexer(); - - @Nonnull - public static JavaScript15LanguageVersion getInstance() - { - return JavaScriptLanguage.INSTANCE.findVersionByClass(JavaScript15LanguageVersion.class); - } - - public JavaScript15LanguageVersion() - { - super("JAVASCRIPT_1_5"); - } - - @Nonnull - @Override - public String getPresentableName() - { - return "JavaScript 1.5"; - } - @Nonnull - @Override - public Lexer createLexer() - { - return ourLexerFactory.get(); - } - - @Nonnull - @Override - public SyntaxHighlighter getSyntaxHighlighter() - { - return new JavaScriptHighlighter(ourLexerFactory); - } - - @Override - public int getWeight() - { - return 0; - } +public class JavaScript15LanguageVersion extends BaseJavaScriptLanguageVersion implements StandardJavaScriptVersion { + private static final Supplier ourLexerFactory = () -> new JavaScript15Lexer(); + + @Nonnull + public static JavaScript15LanguageVersion getInstance() { + return JavaScriptLanguage.INSTANCE.findVersionByClass(JavaScript15LanguageVersion.class); + } + + public JavaScript15LanguageVersion() { + super("JAVASCRIPT_1_5"); + } + + @Nonnull + @Override + public String getPresentableName() { + return "JavaScript 1.5"; + } + + @Nonnull + @Override + public Lexer createLexer() { + return ourLexerFactory.get(); + } + + @Nonnull + @Override + public SyntaxHighlighter getSyntaxHighlighter() { + return new JavaScriptHighlighter(ourLexerFactory); + } + + @Override + public int getWeight() { + return 0; + } } diff --git a/base-impl/src/main/java/consulo/javascript/lang/JavaScriptContextKeywordElementType.java b/base-impl/src/main/java/consulo/javascript/lang/JavaScriptContextKeywordElementType.java index 77510a67..e0e18729 100644 --- a/base-impl/src/main/java/consulo/javascript/lang/JavaScriptContextKeywordElementType.java +++ b/base-impl/src/main/java/consulo/javascript/lang/JavaScriptContextKeywordElementType.java @@ -5,32 +5,28 @@ import com.intellij.lang.javascript.JSElementType; import consulo.language.ast.IElementType; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL * @since 2019-12-14 */ -public class JavaScriptContextKeywordElementType extends JSElementType -{ - private static final BiMap ourCache = HashBiMap.create(); +public class JavaScriptContextKeywordElementType extends JSElementType { + private static final BiMap ourCache = HashBiMap.create(); - @Nullable - public static IElementType getKeywordByText(String text) - { - return ourCache.get(text); - } + @Nullable + public static IElementType getKeywordByText(String text) { + return ourCache.get(text); + } - public static boolean containsKeyword(@Nonnull IElementType e) - { - return ourCache.inverse().containsKey(e); - } + public static boolean containsKeyword(@Nonnull IElementType e) { + return ourCache.inverse().containsKey(e); + } - public JavaScriptContextKeywordElementType(@Nonnull String id, @Nonnull String keyword) - { - super(id); + public JavaScriptContextKeywordElementType(@Nonnull String id, @Nonnull String keyword) { + super(id); - ourCache.put(keyword, this); - } + ourCache.put(keyword, this); + } } diff --git a/base-impl/src/main/java/consulo/javascript/lang/JavaScriptTokenSets.java b/base-impl/src/main/java/consulo/javascript/lang/JavaScriptTokenSets.java index 295c376b..498b8c96 100644 --- a/base-impl/src/main/java/consulo/javascript/lang/JavaScriptTokenSets.java +++ b/base-impl/src/main/java/consulo/javascript/lang/JavaScriptTokenSets.java @@ -24,11 +24,11 @@ * @author VISTALL * @since 24.08.14 */ -public interface JavaScriptTokenSets extends JSTokenTypes -{ - TokenSet STRING_LITERALS = TokenSet.create(JSTokenTypes.STRING_LITERAL, JSTokenTypes.SINGLE_QUOTE_STRING_LITERAL, JSTokenTypes.INTERPOLATION_STRING_LITERAL); +public interface JavaScriptTokenSets extends JSTokenTypes { + TokenSet STRING_LITERALS = + TokenSet.create(JSTokenTypes.STRING_LITERAL, JSTokenTypes.SINGLE_QUOTE_STRING_LITERAL, JSTokenTypes.INTERPOLATION_STRING_LITERAL); - TokenSet WHITE_SPACES = TokenSet.create(JSTokenTypes.WHITE_SPACE); + TokenSet WHITE_SPACES = TokenSet.create(JSTokenTypes.WHITE_SPACE); - TokenSet NAME_TOKEN_TYPES = TokenSet.create(JSElementTypes.REFERENCE_EXPRESSION, JSTokenTypes.IDENTIFIER); + TokenSet NAME_TOKEN_TYPES = TokenSet.create(JSElementTypes.REFERENCE_EXPRESSION, JSTokenTypes.IDENTIFIER); } diff --git a/base-impl/src/main/java/consulo/javascript/lang/StandardJavaScriptVersionsImpl.java b/base-impl/src/main/java/consulo/javascript/lang/StandardJavaScriptVersionsImpl.java index 124aaa3a..c136a5df 100644 --- a/base-impl/src/main/java/consulo/javascript/lang/StandardJavaScriptVersionsImpl.java +++ b/base-impl/src/main/java/consulo/javascript/lang/StandardJavaScriptVersionsImpl.java @@ -1,15 +1,17 @@ package consulo.javascript.lang; import consulo.annotation.component.ServiceImpl; +import consulo.javascript.internal.DefaultJavaScriptVersion; import consulo.javascript.language.JavaScriptLanguage; import consulo.javascript.language.JavaScriptLanguageVersion; +import consulo.javascript.language.StandardJavaScriptVersion; import consulo.javascript.language.StandardJavaScriptVersions; import consulo.language.version.LanguageVersion; import consulo.util.lang.StringUtil; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; import jakarta.inject.Singleton; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; @@ -19,47 +21,44 @@ */ @Singleton @ServiceImpl -public class StandardJavaScriptVersionsImpl extends StandardJavaScriptVersions -{ - @Nonnull - public BaseJavaScriptLanguageVersion getDefaultVersion() - { - return JavaScript15LanguageVersion.getInstance(); - } +public class StandardJavaScriptVersionsImpl extends StandardJavaScriptVersions { + @Nonnull + public JavaScriptLanguageVersion getDefaultVersion() { + LanguageVersion[] versions = JavaScriptLanguage.INSTANCE.getVersions(); + for (LanguageVersion version : versions) { + if (version instanceof DefaultJavaScriptVersion) { + return (JavaScriptLanguageVersion)version; + } + } + return JavaScript15LanguageVersion.getInstance(); + } - @Nonnull - public List getValidLanguageVersions() - { - List list = new ArrayList<>(); - LanguageVersion[] versions = JavaScriptLanguage.INSTANCE.getVersions(); - for(LanguageVersion version : versions) - { - if(version instanceof StandardJavaScriptVersions.Marker) - { - list.add((BaseJavaScriptLanguageVersion) version); - } - } + @Nonnull + public List getValidLanguageVersions() { + List list = new ArrayList<>(); + LanguageVersion[] versions = JavaScriptLanguage.INSTANCE.getVersions(); + for (LanguageVersion version : versions) { + if (version instanceof StandardJavaScriptVersion) { + list.add((BaseJavaScriptLanguageVersion)version); + } + } - list.sort((o1, o2) -> StringUtil.naturalCompare(o1.getPresentableName(), o2.getPresentableName())); - return list; - } + list.sort((o1, o2) -> StringUtil.naturalCompare(o1.getPresentableName(), o2.getPresentableName())); + return list; + } - @Nonnull - public BaseJavaScriptLanguageVersion findVersionById(@Nullable String id) - { - if(StringUtil.isEmpty(id)) - { - return getDefaultVersion(); - } + @Nonnull + public JavaScriptLanguageVersion findVersionById(@Nullable String id) { + if (StringUtil.isEmpty(id)) { + return getDefaultVersion(); + } - LanguageVersion[] versions = JavaScriptLanguage.INSTANCE.getVersions(); - for(LanguageVersion version : versions) - { - if(version instanceof StandardJavaScriptVersions.Marker && id.equals(version.getId())) - { - return (BaseJavaScriptLanguageVersion) version; - } - } - return getDefaultVersion(); - } + LanguageVersion[] versions = JavaScriptLanguage.INSTANCE.getVersions(); + for (LanguageVersion version : versions) { + if (version instanceof StandardJavaScriptVersion && id.equals(version.getId())) { + return (BaseJavaScriptLanguageVersion)version; + } + } + return getDefaultVersion(); + } } diff --git a/base-impl/src/main/java/consulo/javascript/lang/lexer/JavaScriptFlexAdapter.java b/base-impl/src/main/java/consulo/javascript/lang/lexer/JavaScriptFlexAdapter.java index 8aa2278a..4a0056f7 100644 --- a/base-impl/src/main/java/consulo/javascript/lang/lexer/JavaScriptFlexAdapter.java +++ b/base-impl/src/main/java/consulo/javascript/lang/lexer/JavaScriptFlexAdapter.java @@ -22,31 +22,26 @@ /** * @author Maxim.Mossienko */ -public class JavaScriptFlexAdapter extends FlexAdapter -{ - private static final int BASE_STATE_MASK = 0xF; - private static final int TAG_COUNT_SHIFT = 4; +public class JavaScriptFlexAdapter extends FlexAdapter { + private static final int BASE_STATE_MASK = 0xF; + private static final int TAG_COUNT_SHIFT = 4; - public JavaScriptFlexAdapter(FlexLexer lexer) - { - super(lexer); - } + public JavaScriptFlexAdapter(FlexLexer lexer) { + super(lexer); + } - @Override - public void start(final CharSequence buffer, final int startOffset, final int endOffset, final int initialState) - { - super.start(buffer, startOffset, endOffset, initialState & BASE_STATE_MASK); - ((JavaScriptFlexLexer) getFlex()).setTagCount(initialState >> TAG_COUNT_SHIFT); - } + @Override + public void start(CharSequence buffer, int startOffset, int endOffset, int initialState) { + super.start(buffer, startOffset, endOffset, initialState & BASE_STATE_MASK); + ((JavaScriptFlexLexer)getFlex()).setTagCount(initialState >> TAG_COUNT_SHIFT); + } - @Override - public int getState() - { - return getStateInternal() + (((JavaScriptFlexLexer) getFlex()).getTagCount() << TAG_COUNT_SHIFT); - } + @Override + public int getState() { + return getStateInternal() + (((JavaScriptFlexLexer)getFlex()).getTagCount() << TAG_COUNT_SHIFT); + } - protected int getStateInternal() - { - return super.getState(); - } + protected int getStateInternal() { + return super.getState(); + } } \ No newline at end of file diff --git a/base-impl/src/main/java/consulo/javascript/lang/lexer/JavaScriptFlexLexer.java b/base-impl/src/main/java/consulo/javascript/lang/lexer/JavaScriptFlexLexer.java index 3539ceff..8491d090 100644 --- a/base-impl/src/main/java/consulo/javascript/lang/lexer/JavaScriptFlexLexer.java +++ b/base-impl/src/main/java/consulo/javascript/lang/lexer/JavaScriptFlexLexer.java @@ -6,9 +6,8 @@ * @author VISTALL * @since 2019-12-05 */ -public interface JavaScriptFlexLexer extends FlexLexer -{ - void setTagCount(int count); +public interface JavaScriptFlexLexer extends FlexLexer { + void setTagCount(int count); - int getTagCount(); + int getTagCount(); } diff --git a/base-impl/src/main/java/consulo/javascript/lang/parsing/ExpressionParsing.java b/base-impl/src/main/java/consulo/javascript/lang/parsing/ExpressionParsing.java index b7a18f0b..bae3e641 100644 --- a/base-impl/src/main/java/consulo/javascript/lang/parsing/ExpressionParsing.java +++ b/base-impl/src/main/java/consulo/javascript/lang/parsing/ExpressionParsing.java @@ -19,1020 +19,852 @@ import com.intellij.javascript.documentation.JSDocumentationUtils; import com.intellij.lang.javascript.JSElementTypes; import com.intellij.lang.javascript.JSTokenTypes; -import consulo.javascript.language.JavaScriptBundle; import consulo.javascript.lang.JavaScriptTokenSets; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.ast.IElementType; import consulo.language.ast.TokenSet; import consulo.language.parser.PsiBuilder; +import consulo.localize.LocalizeValue; import consulo.logging.Logger; import consulo.util.dataholder.Key; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; /** - * User: max - * Date: Jan 28, 2005 - * Time: 1:18:22 PM + * @author max + * @since 2005-01-28 */ -public class ExpressionParsing extends Parsing -{ - private static final Logger LOG = Logger.getInstance(ExpressionParsing.class); - - public static final Key WITHIN_ARRAY_LITERAL_EXPRESSION = Key.create("within.array.literal.expression"); - public static final Key WITHIN_OBJECT_LITERAL_EXPRESSION = Key.create("within.object.literal.expression"); - - private static final TokenSet DOT_SET = TokenSet.create(JSTokenTypes.DOT); - private static final TokenSet MEMBER_OPERATOR_SET = TokenSet.create(JSTokenTypes.DOT, JSTokenTypes.COLON_COLON, JSTokenTypes.DOT_DOT, JSTokenTypes.QUEST_DOT); - - private final JSXParser myJSXParser = new JSXParser(); - - public ExpressionParsing(C context) - { - super(context); - } - - protected boolean parsePrimaryExpression(PsiBuilder builder) - { - final IElementType firstToken = builder.getTokenType(); - if(firstToken == JSTokenTypes.THIS_KEYWORD) - { - Parsing.buildTokenElement(JSElementTypes.THIS_EXPRESSION, builder); - return true; - } - else if(firstToken == JSTokenTypes.SUPER_KEYWORD) - { - Parsing.buildTokenElement(JSElementTypes.SUPER_EXPRESSION, builder); - return true; - } - else if(isIdentifierName(builder, firstToken) || firstToken == JSTokenTypes.ANY_IDENTIFIER) - { - Parsing.buildTokenElement(JSElementTypes.REFERENCE_EXPRESSION, builder); - return true; - } - else if(firstToken == JSTokenTypes.REGEXP_LITERAL) - { - String errorMessage = validateLiteral(builder); - Parsing.buildTokenElement(JSElementTypes.REGEXP_LITERAL_EXPRESSION, builder); - if(errorMessage != null) - { - builder.error(errorMessage); - } - return true; - } - else if(firstToken == JSTokenTypes.NUMERIC_LITERAL || - firstToken == JSTokenTypes.STRING_LITERAL || - firstToken == JSTokenTypes.SINGLE_QUOTE_STRING_LITERAL || - firstToken == JSTokenTypes.INTERPOLATION_STRING_LITERAL || - firstToken == JSTokenTypes.NULL_KEYWORD || - firstToken == JSTokenTypes.UNDEFINED_KEYWORD || - firstToken == JSTokenTypes.FALSE_KEYWORD || - firstToken == JSTokenTypes.TRUE_KEYWORD) - { - String errorMessage = validateLiteral(builder); - Parsing.buildTokenElement(JSElementTypes.LITERAL_EXPRESSION, builder); - if(errorMessage != null) - { - builder.error(errorMessage); - } - return true; - } - else if(firstToken == JSTokenTypes.LPAR) - { - parseParenthesizedExpression(builder); - return true; - } - else if(firstToken == JSTokenTypes.LBRACKET) - { - parseArrayLiteralExpression(builder); - return true; - } - else if(firstToken == JSTokenTypes.LBRACE) - { - parseObjectLiteralExpression(builder); - return true; - } - else if(firstToken == JSTokenTypes.LET_KEYWORD) - { - parseLetExpression(builder); - return true; - } - else if(firstToken == JSTokenTypes.FUNCTION_KEYWORD) - { - getFunctionParsing().parseFunctionExpression(builder); - return true; - } - else if(firstToken == JSTokenTypes.XML_START_TAG_START || firstToken == JSTokenTypes.XML_START_TAG_LIST) - { - parseTag(builder); - return true; - } - else if(firstToken == JSTokenTypes.AT) - { - PsiBuilder.Marker marker = builder.mark(); - builder.advanceLexer(); - - if(!builder.eof()) - { - IElementType tokenType = builder.getTokenType(); - if(tokenType == JSTokenTypes.ANY_IDENTIFIER || isIdentifierToken(builder, tokenType)) - { - builder.advanceLexer(); - } - else if(tokenType == JSTokenTypes.LBRACKET) - { - builder.advanceLexer(); - parseExpression(builder); - Parsing.checkMatches(builder, JSTokenTypes.RBRACKET, JavaScriptBundle.message("javascript.parser.message.expected.rbracket")); - } - else - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.identifier")); - } - } - - marker.done(JSElementTypes.REFERENCE_EXPRESSION); - - return true; - } - else - { - return false; - } - } - - private void parseLetExpression(final PsiBuilder builder) - { - final PsiBuilder.Marker marker = getStatementParsing().parseLetExpressionStart(builder); - parseExpression(builder); - marker.done(JSElementTypes.LET_EXPRESSION); - } - - private void parseTag(final PsiBuilder builder) - { - myJSXParser.setBuilder(builder); - - myJSXParser.parseTag(false); - } - - @Nullable - public static String validateLiteral(final PsiBuilder builder) - { - final IElementType ttype = builder.getTokenType(); - if(ttype == JSTokenTypes.STRING_LITERAL || ttype == JSTokenTypes.SINGLE_QUOTE_STRING_LITERAL) - { - final String ttext = builder.getTokenText(); - assert ttext != null; - - if(lastSymbolEscaped(ttext) || - ttext.startsWith("\"") && (!ttext.endsWith("\"") || ttext.length() == 1) || - ttext.startsWith("\'") && (!ttext.endsWith("\'") || ttext.length() == 1)) - { - return JavaScriptBundle.message("javascript.parser.message.unclosed.string.literal"); - } - } - - return null; - } - - private static boolean lastSymbolEscaped(String text) - { - boolean escapes = false; - boolean escaped = true; - for(int i = 0; i < text.length(); i++) - { - char c = text.charAt(i); - if(escapes) - { - escapes = false; - escaped = true; - continue; - } - if(c == '\\') - { - escapes = true; - } - escaped = false; - } - return escapes || escaped; - } - - public void parseObjectLiteralExpression(final PsiBuilder builder) - { - ExpressionParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.LBRACE); - final PsiBuilder.Marker expr = builder.mark(); - builder.advanceLexer(); - - IElementType elementType = builder.getTokenType(); - - while(elementType != JSTokenTypes.RBRACE && elementType != null) - { - parseProperty(builder); - - elementType = builder.getTokenType(); - if(elementType == JSTokenTypes.RBRACE) - { - break; - } - else if(elementType == JSTokenTypes.COMMA) - { - builder.advanceLexer(); - - if(builder.getTokenType() == JSTokenTypes.RBRACE) - { - break; - } - } - else - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.comma")); - } - - elementType = builder.getTokenType(); - if(elementType == JSTokenTypes.RBRACE) - { - builder.error(JavaScriptBundle.message("javascript.parser.property.expected")); - } - else if(isNotPropertyStart(builder, elementType)) - { - break; - } - } - - Parsing.checkMatches(builder, JSTokenTypes.RBRACE, JavaScriptBundle.message("javascript.parser.message.expected.rbrace")); - expr.done(JSElementTypes.OBJECT_LITERAL_EXPRESSION); - } - - public boolean isNotPropertyStart(PsiBuilder builder, IElementType elementType) - { - return !isIdentifierToken(builder, elementType) && !JavaScriptTokenSets.STRING_LITERALS.contains(elementType) && elementType != JSTokenTypes.NUMERIC_LITERAL; - } - - protected void parseProperty(final PsiBuilder builder) - { - final IElementType nameToken = builder.getTokenType(); - final PsiBuilder.Marker property = builder.mark(); - - if(isNotPropertyStart(builder, nameToken)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.identifier.string.literal.or.numeric.literal")); - } - builder.advanceLexer(); - - Parsing.checkMatches(builder, JSTokenTypes.COLON, JavaScriptBundle.message("javascript.parser.message.expected.colon")); - - builder.putUserData(WITHIN_OBJECT_LITERAL_EXPRESSION, Boolean.TRUE); - if(!parseAssignmentExpression(builder)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - builder.putUserData(WITHIN_OBJECT_LITERAL_EXPRESSION, null); - - property.done(JSElementTypes.PROPERTY); - } - - public void parseArrayLiteralExpression(final PsiBuilder builder) - { - ExpressionParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.LBRACKET); - final PsiBuilder.Marker expr = builder.mark(); - builder.advanceLexer(); - boolean commaExpected = false; - - Boolean save = null; - - try - { - save = builder.getUserData(WITHIN_ARRAY_LITERAL_EXPRESSION); - builder.putUserData(WITHIN_ARRAY_LITERAL_EXPRESSION, Boolean.TRUE); - - while(builder.getTokenType() != JSTokenTypes.RBRACKET) - { - if(commaExpected) - { - final boolean b = Parsing.checkMatches(builder, JSTokenTypes.COMMA, JavaScriptBundle.message("javascript.parser.message.expected.comma")); - if(!b) - { - break; - } - } - - while(builder.getTokenType() == JSTokenTypes.COMMA) - { - builder.advanceLexer(); - } - - commaExpected = false; - if(builder.getTokenType() != JSTokenTypes.RBRACKET) - { - if(!parseAssignmentExpression(builder)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - break; - } - else - { - commaExpected = true; - } - } - } - Parsing.checkMatches(builder, JSTokenTypes.RBRACKET, JavaScriptBundle.message("javascript.parser.message.expected.rbracket")); - expr.done(JSElementTypes.ARRAY_LITERAL_EXPRESSION); - } - finally - { - builder.putUserData(WITHIN_ARRAY_LITERAL_EXPRESSION, save); - } - } - - private void parseParenthesizedExpression(final PsiBuilder builder) - { - ExpressionParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.LPAR); - final PsiBuilder.Marker expr = builder.mark(); - builder.advanceLexer(); - parseExpression(builder); - Parsing.checkMatches(builder, JSTokenTypes.RPAR, JavaScriptBundle.message("javascript.parser.message.expected.rparen")); - expr.done(JSElementTypes.PARENTHESIZED_EXPRESSION); - } - - protected boolean parseMemberExpression(PsiBuilder builder, boolean allowCallSyntax) - { - return parseMemberExpression(builder, allowCallSyntax, MEMBER_OPERATOR_SET); - } - - protected boolean parseMemberExpression(PsiBuilder builder, boolean allowCallSyntax, TokenSet membersOperatorSet) - { - PsiBuilder.Marker expr = builder.mark(); - boolean isNew; - - final IElementType type = builder.getTokenType(); - - if(type == JSTokenTypes.NEW_KEYWORD) - { - isNew = true; - final boolean isfunction = parseNewExpression(builder); - - if(isfunction) - { - expr.done(JSElementTypes.NEW_EXPRESSION); - if(builder.getTokenType() != JSTokenTypes.LPAR) - { - return true; - } - expr = expr.precede(); - isNew = false; - } - } - else - { - isNew = false; - if(!parsePrimaryExpression(builder)) - { - expr.drop(); - return false; - } - } - - boolean currentlyAllowCallSyntax = allowCallSyntax && (type != JSTokenTypes.LBRACE && type != JSTokenTypes.LBRACKET); - - while(true) - { - IElementType tokenType = builder.getTokenType(); - if(membersOperatorSet.contains(tokenType)) - { - currentlyAllowCallSyntax = allowCallSyntax; - builder.advanceLexer(); - - if(builder.getTokenType() == JSTokenTypes.AT) - { - builder.advanceLexer(); - } - - tokenType = builder.getTokenType(); - - if(tokenType == JSTokenTypes.LBRACKET || tokenType == JSTokenTypes.LPAR) - { - continue; - } - - if(tokenType == JSTokenTypes.ANY_IDENTIFIER || isIdentifierToken(builder, tokenType)) - { - builder.advanceLexer(); - } - else - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.name")); - } - - expr.done(JSElementTypes.REFERENCE_EXPRESSION); - expr = expr.precede(); - } - else if(tokenType == JSTokenTypes.LBRACKET) - { - builder.advanceLexer(); - parseExpression(builder); - Parsing.checkMatches(builder, JSTokenTypes.RBRACKET, JavaScriptBundle.message("javascript.parser.message.expected.rbracket")); - expr.done(JSElementTypes.INDEXED_PROPERTY_ACCESS_EXPRESSION); - expr = expr.precede(); - } - else if(currentlyAllowCallSyntax && tokenType == JSTokenTypes.LPAR) - { - parseArgumentList(builder); - expr.done(isNew ? JSElementTypes.NEW_EXPRESSION : JSElementTypes.CALL_EXPRESSION); - expr = expr.precede(); - isNew = false; - } - else - { - if(isNew) - { - expr.done(JSElementTypes.NEW_EXPRESSION); - } - else - { - expr.drop(); - } - break; - } - } - - return true; - } - - public boolean parseQualifiedTypeName(PsiBuilder builder) - { - return parseQualifiedTypeName(builder, false); - } - - public boolean parseQualifiedTypeName(PsiBuilder builder, boolean allowStar) - { - return parseQualifiedTypeName(builder, allowStar, DOT_SET); - } - - public boolean parseQualifiedTypeName(PsiBuilder builder, boolean allowStar, TokenSet separatorsSet) - { - if(!JSTokenTypes.IDENTIFIER_TOKENS_SET.contains(builder.getTokenType())) - { - return false; - } - PsiBuilder.Marker expr = builder.mark(); - Parsing.buildTokenElement(JSElementTypes.REFERENCE_EXPRESSION, builder); - - while(separatorsSet.contains(builder.getTokenType())) - { - boolean stop = false; - builder.advanceLexer(); - - final IElementType tokenType = builder.getTokenType(); - if(tokenType == JSTokenTypes.ANY_IDENTIFIER && allowStar) - { - builder.advanceLexer(); - stop = true; - } - else if(tokenType == JSTokenTypes.DEFAULT_KEYWORD || (tokenType != JSTokenTypes.IDENTIFIER && JSTokenTypes.IDENTIFIER_TOKENS_SET - .contains(tokenType))) - { - builder.advanceLexer(); // TODO: allow any keyword - } - else - { - Parsing.checkMatches(builder, JSTokenTypes.IDENTIFIER, JavaScriptBundle.message("javascript.parser.message.expected.name")); - } - expr.done(JSElementTypes.REFERENCE_EXPRESSION); - expr = expr.precede(); - - if(stop) - { - break; - } - } - - expr.drop(); - return true; - } - - protected boolean parseNewExpression(PsiBuilder builder) - { - ExpressionParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.NEW_KEYWORD); - builder.advanceLexer(); - - if(builder.getTokenType() == JSTokenTypes.FUNCTION_KEYWORD) - { - getFunctionParsing().parseFunctionExpression(builder); - return true; - } - - if(!parseMemberExpression(builder, false)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - return false; - } - - protected void parseArgumentList(final PsiBuilder builder) - { - ExpressionParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.LPAR); - final PsiBuilder.Marker arglist = builder.mark(); - builder.advanceLexer(); - boolean first = true; - while(builder.getTokenType() != JSTokenTypes.RPAR) - { - if(first) - { - first = false; - } - else - { - if(builder.getTokenType() == JSTokenTypes.COMMA) - { - builder.advanceLexer(); - } - else - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.comma.or.rparen")); - break; - } - } - if(!parseAssignmentExpression(builder)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - } - - Parsing.checkMatches(builder, JSTokenTypes.RPAR, JavaScriptBundle.message("javascript.parser.message.expected.rparen")); - arglist.done(JSElementTypes.ARGUMENT_LIST); - } - - public void parseExpression(PsiBuilder builder) - { - if(!parseExpressionOptional(builder)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - } - - public boolean parseAssignmentExpressionNoIn(final PsiBuilder builder) - { - return parseAssignmentExpression(builder, false); - } - - public boolean parseAssignmentExpression(final PsiBuilder builder) - { - return parseAssignmentExpression(builder, true); - } - - private boolean parseAssignmentExpression(final PsiBuilder builder, boolean allowIn) - { - final PsiBuilder.Marker expr = builder.mark(); - - if(JSTokenTypes.ASSIGNMENT_OPERATIONS.contains(builder.getTokenType()) && builder.getUserData(WITHIN_OBJECT_LITERAL_EXPRESSION) == null) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - builder.advanceLexer(); - if(!parseAssignmentExpression(builder, allowIn)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - expr.done(JSElementTypes.ASSIGNMENT_EXPRESSION); - return true; - } - - final PsiBuilder.Marker definitionExpr = builder.mark(); - if(!parseConditionalExpression(builder, allowIn)) - { - definitionExpr.drop(); - expr.drop(); - return false; - } - - if(JSTokenTypes.ASSIGNMENT_OPERATIONS.contains(builder.getTokenType())) - { - definitionExpr.done(JSElementTypes.DEFINITION_EXPRESSION); - builder.advanceLexer(); - if(!parseAssignmentExpression(builder, allowIn)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - expr.done(JSElementTypes.ASSIGNMENT_EXPRESSION); - } - else - { - definitionExpr.drop(); - expr.drop(); - } - return true; - } - - private boolean parseConditionalExpression(final PsiBuilder builder, final boolean allowIn) - { - final PsiBuilder.Marker expr = builder.mark(); - if(!parseORExpression(builder, allowIn)) - { - expr.drop(); - return false; - } - - final IElementType nextTokenType = builder.getTokenType(); - - if(nextTokenType == JSTokenTypes.QUEST) - { - builder.advanceLexer(); - if(!parseAssignmentExpression(builder, allowIn)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - Parsing.checkMatches(builder, JSTokenTypes.COLON, JavaScriptBundle.message("javascript.parser.message.expected.colon")); - if(!parseAssignmentExpression(builder, allowIn)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - expr.done(JSElementTypes.CONDITIONAL_EXPRESSION); - } - else if(nextTokenType == JSTokenTypes.FOR_KEYWORD && builder.getUserData(WITHIN_ARRAY_LITERAL_EXPRESSION) != null) - { - getStatementParsing().parseForLoopHeader(builder); // TODO: make it more clear - expr.done(JSElementTypes.CONDITIONAL_EXPRESSION); - } - else - { - expr.drop(); - } - return true; - } - - private boolean parseORExpression(final PsiBuilder builder, final boolean allowIn) - { - PsiBuilder.Marker expr = builder.mark(); - if(!parseANDExpression(builder, allowIn)) - { - expr.drop(); - return false; - } - - while(builder.getTokenType() == JSTokenTypes.OROR) - { - builder.advanceLexer(); - if(!parseANDExpression(builder, allowIn)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - expr.done(JSElementTypes.BINARY_EXPRESSION); - expr = expr.precede(); - } - - expr.drop(); - return true; - } - - private boolean parseANDExpression(final PsiBuilder builder, final boolean allowIn) - { - PsiBuilder.Marker expr = builder.mark(); - if(!parseBitwiseORExpression(builder, allowIn)) - { - expr.drop(); - return false; - } - - while(builder.getTokenType() == JSTokenTypes.ANDAND) - { - builder.advanceLexer(); - if(!parseBitwiseORExpression(builder, allowIn)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - expr.done(JSElementTypes.BINARY_EXPRESSION); - expr = expr.precede(); - } - - expr.drop(); - return true; - } - - private boolean parseBitwiseORExpression(final PsiBuilder builder, final boolean allowIn) - { - PsiBuilder.Marker expr = builder.mark(); - if(!parseBitwiseXORExpression(builder, allowIn)) - { - expr.drop(); - return false; - } - - while(builder.getTokenType() == JSTokenTypes.OR) - { - builder.advanceLexer(); - if(!parseBitwiseXORExpression(builder, allowIn)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - expr.done(JSElementTypes.BINARY_EXPRESSION); - expr = expr.precede(); - } - - expr.drop(); - return true; - } - - private boolean parseBitwiseXORExpression(final PsiBuilder builder, final boolean allowIn) - { - PsiBuilder.Marker expr = builder.mark(); - if(!parseBitwiseANDExpression(builder, allowIn)) - { - expr.drop(); - return false; - } - - while(builder.getTokenType() == JSTokenTypes.XOR) - { - builder.advanceLexer(); - if(!parseBitwiseANDExpression(builder, allowIn)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - expr.done(JSElementTypes.BINARY_EXPRESSION); - expr = expr.precede(); - } - - expr.drop(); - return true; - } - - private boolean parseBitwiseANDExpression(final PsiBuilder builder, final boolean allowIn) - { - PsiBuilder.Marker expr = builder.mark(); - if(!parseEqualityExpression(builder, allowIn)) - { - expr.drop(); - return false; - } - - while(builder.getTokenType() == JSTokenTypes.AND) - { - builder.advanceLexer(); - if(!parseEqualityExpression(builder, allowIn)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - expr.done(JSElementTypes.BINARY_EXPRESSION); - expr = expr.precede(); - } - - expr.drop(); - return true; - } - - private boolean parseEqualityExpression(final PsiBuilder builder, final boolean allowIn) - { - PsiBuilder.Marker expr = builder.mark(); - if(!parseRelationalExpression(builder, allowIn)) - { - expr.drop(); - return false; - } - - while(JSTokenTypes.EQUALITY_OPERATIONS.contains(builder.getTokenType())) - { - builder.advanceLexer(); - if(!parseRelationalExpression(builder, allowIn)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - expr.done(JSElementTypes.BINARY_EXPRESSION); - expr = expr.precede(); - } - - expr.drop(); - return true; - } - - private boolean parseRelationalExpression(final PsiBuilder builder, final boolean allowIn) - { - PsiBuilder.Marker expr = builder.mark(); - if(!parseShiftExpression(builder)) - { - expr.drop(); - return false; - } - while(JSTokenTypes.RELATIONAL_OPERATIONS.contains(builder.getTokenType()) && (allowIn || builder.getTokenType() != JSTokenTypes.IN_KEYWORD)) - { - builder.advanceLexer(); - if(!parseShiftExpression(builder)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - expr.done(JSElementTypes.BINARY_EXPRESSION); - expr = expr.precede(); - } - - expr.drop(); - return true; - } - - private boolean parseShiftExpression(final PsiBuilder builder) - { - PsiBuilder.Marker expr = builder.mark(); - if(!parseAdditiveExpression(builder)) - { - expr.drop(); - return false; - } - while(JSTokenTypes.SHIFT_OPERATIONS.contains(builder.getTokenType())) - { - builder.advanceLexer(); - if(!parseAdditiveExpression(builder)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - expr.done(JSElementTypes.BINARY_EXPRESSION); - expr = expr.precede(); - } - - expr.drop(); - return true; - } - - private boolean parseAdditiveExpression(final PsiBuilder builder) - { - PsiBuilder.Marker expr = builder.mark(); - if(!parseMultiplicativeExpression(builder)) - { - expr.drop(); - return false; - } - while(JSTokenTypes.ADDITIVE_OPERATIONS.contains(builder.getTokenType())) - { - builder.advanceLexer(); - if(!parseMultiplicativeExpression(builder)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - expr.done(JSElementTypes.BINARY_EXPRESSION); - expr = expr.precede(); - } - - expr.drop(); - return true; - } - - private boolean parseIsAsExpression(final PsiBuilder builder) - { - PsiBuilder.Marker expr = builder.mark(); - if(!parseUnaryExpression(builder)) - { - expr.drop(); - return false; - } - - while(builder.getTokenType() == JSTokenTypes.AS_KEYWORD || builder.getTokenType() == JSTokenTypes.IS_KEYWORD) - { - builder.advanceLexer(); - if(!parseUnaryExpression(builder)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - expr.done(JSElementTypes.BINARY_EXPRESSION); - expr = expr.precede(); - } - - expr.drop(); - return true; - } - - protected boolean parseMultiplicativeExpression(final PsiBuilder builder) - { - return parseMultiplicativeExpression(builder, JSTokenTypes.MULTIPLICATIVE_OPERATIONS); - } - - protected boolean parseMultiplicativeExpression(final PsiBuilder builder, TokenSet operatorSet) - { - PsiBuilder.Marker expr = builder.mark(); - if(!parseIsAsExpression(builder)) - { - expr.drop(); - return false; - } - - while(operatorSet.contains(builder.getTokenType())) - { - builder.advanceLexer(); - if(!parseUnaryExpression(builder)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - expr.done(JSElementTypes.BINARY_EXPRESSION); - expr = expr.precede(); - } - - expr.drop(); - return true; - } - - private boolean parseUnaryExpression(final PsiBuilder builder) - { - final IElementType tokenType = builder.getTokenType(); - if(JSTokenTypes.UNARY_OPERATIONS.contains(tokenType)) - { - final PsiBuilder.Marker expr = builder.mark(); - builder.advanceLexer(); - if(!parseUnaryExpression(builder)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - expr.done(JSElementTypes.PREFIX_EXPRESSION); - return true; - } - else - { - return parsePostfixExpression(builder); - } - } - - private boolean parsePostfixExpression(PsiBuilder builder) - { - final PsiBuilder.Marker expr = builder.mark(); - if(!parseMemberExpression(builder, true)) - { - expr.drop(); - return false; - } - - final IElementType tokenType = builder.getTokenType(); - if(tokenType == JSTokenTypes.PLUSPLUS || tokenType == JSTokenTypes.MINUSMINUS) - { - builder.advanceLexer(); - expr.done(JSElementTypes.POSTFIX_EXPRESSION); - } - else - { - expr.drop(); - } - return true; - } - - public boolean parseExpressionOptional(final PsiBuilder builder) - { - return parseExpressionOptional(builder, true); - } - - public boolean parseExpressionOptionalNoIn(final PsiBuilder builder) - { - return parseExpressionOptional(builder, false); - } - - public boolean parseExpressionOptional(final PsiBuilder builder, final boolean allowIn) - { - PsiBuilder.Marker expr = builder.mark(); - if(!parseAssignmentExpression(builder, allowIn)) - { - expr.drop(); - return false; - } - - if(builder.getTokenType() == JSTokenTypes.IN_KEYWORD) - { - expr.done(JSElementTypes.DEFINITION_EXPRESSION); - return true; - } - - while(builder.getTokenType() == JSTokenTypes.COMMA) - { - builder.advanceLexer(); - if(!parseAssignmentExpression(builder, allowIn)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - - expr.done(JSElementTypes.COMMA_EXPRESSION); - expr = expr.precede(); - } - - expr.drop(); - - return true; - } - - public boolean tryParseType(final PsiBuilder builder) - { - return false; - } - - public boolean parseType(final PsiBuilder builder) - { - final IElementType tokenType = builder.getTokenType(); - if(JSDocumentationUtils.ourPrimitiveTypeFilter.contains(tokenType)) - { - builder.advanceLexer(); - } - else if(!parseQualifiedTypeName(builder)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.typename")); - } - return true; - } - - public void parseSimpleExpression(final PsiBuilder builder) - { - if(!parseUnaryExpression(builder)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - } +public class ExpressionParsing extends Parsing { + private static final Logger LOG = Logger.getInstance(ExpressionParsing.class); + + public static final Key WITHIN_ARRAY_LITERAL_EXPRESSION = Key.create("within.array.literal.expression"); + public static final Key WITHIN_OBJECT_LITERAL_EXPRESSION = Key.create("within.object.literal.expression"); + + private static final TokenSet DOT_SET = TokenSet.create(JSTokenTypes.DOT); + private static final TokenSet MEMBER_OPERATOR_SET = + TokenSet.create(JSTokenTypes.DOT, JSTokenTypes.COLON_COLON, JSTokenTypes.DOT_DOT, JSTokenTypes.QUEST_DOT); + private static final TokenSet LITERAL_SET = TokenSet.create( + JSTokenTypes.NUMERIC_LITERAL, + JSTokenTypes.STRING_LITERAL, + JSTokenTypes.SINGLE_QUOTE_STRING_LITERAL, + JSTokenTypes.INTERPOLATION_STRING_LITERAL, + JSTokenTypes.NULL_KEYWORD, + JSTokenTypes.UNDEFINED_KEYWORD, + JSTokenTypes.FALSE_KEYWORD, + JSTokenTypes.TRUE_KEYWORD + ); + + private final JSXParser myJSXParser = new JSXParser(); + + public ExpressionParsing(C context) { + super(context); + } + + protected boolean parsePrimaryExpression(PsiBuilder builder) { + IElementType firstToken = builder.getTokenType(); + if (firstToken == JSTokenTypes.THIS_KEYWORD) { + Parsing.buildTokenElement(JSElementTypes.THIS_EXPRESSION, builder); + return true; + } + else if (firstToken == JSTokenTypes.SUPER_KEYWORD) { + Parsing.buildTokenElement(JSElementTypes.SUPER_EXPRESSION, builder); + return true; + } + else if (isIdentifierName(builder, firstToken) || firstToken == JSTokenTypes.ANY_IDENTIFIER) { + Parsing.buildTokenElement(JSElementTypes.REFERENCE_EXPRESSION, builder); + return true; + } + else if (firstToken == JSTokenTypes.REGEXP_LITERAL) { + LocalizeValue errorMessage = validateLiteral(builder); + Parsing.buildTokenElement(JSElementTypes.REGEXP_LITERAL_EXPRESSION, builder); + if (errorMessage != null) { + builder.error(errorMessage); + } + return true; + } + else if (LITERAL_SET.contains(firstToken)) { + LocalizeValue errorMessage = validateLiteral(builder); + Parsing.buildTokenElement(JSElementTypes.LITERAL_EXPRESSION, builder); + if (errorMessage != null) { + builder.error(errorMessage); + } + return true; + } + else if (firstToken == JSTokenTypes.LPAR) { + parseParenthesizedExpression(builder); + return true; + } + else if (firstToken == JSTokenTypes.LBRACKET) { + parseArrayLiteralExpression(builder); + return true; + } + else if (firstToken == JSTokenTypes.LBRACE) { + parseObjectLiteralExpression(builder); + return true; + } + else if (firstToken == JSTokenTypes.LET_KEYWORD) { + parseLetExpression(builder); + return true; + } + else if (firstToken == JSTokenTypes.FUNCTION_KEYWORD) { + getFunctionParsing().parseFunctionExpression(builder); + return true; + } + else if (firstToken == JSTokenTypes.XML_START_TAG_START || firstToken == JSTokenTypes.XML_START_TAG_LIST) { + parseTag(builder); + return true; + } + else if (firstToken == JSTokenTypes.AT) { + PsiBuilder.Marker marker = builder.mark(); + builder.advanceLexer(); + + if (!builder.eof()) { + IElementType tokenType = builder.getTokenType(); + if (tokenType == JSTokenTypes.ANY_IDENTIFIER || isIdentifierToken(builder, tokenType)) { + builder.advanceLexer(); + } + else if (tokenType == JSTokenTypes.LBRACKET) { + builder.advanceLexer(); + parseExpression(builder); + Parsing.checkMatches(builder, JSTokenTypes.RBRACKET, JavaScriptLocalize.javascriptParserMessageExpectedRbracket()); + } + else { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedIdentifier()); + } + } + + marker.done(JSElementTypes.REFERENCE_EXPRESSION); + + return true; + } + else { + return false; + } + } + + private void parseLetExpression(PsiBuilder builder) { + PsiBuilder.Marker marker = getStatementParsing().parseLetExpressionStart(builder); + parseExpression(builder); + marker.done(JSElementTypes.LET_EXPRESSION); + } + + private void parseTag(PsiBuilder builder) { + myJSXParser.setBuilder(builder); + + myJSXParser.parseTag(false); + } + + @Nullable + public static LocalizeValue validateLiteral(PsiBuilder builder) { + IElementType ttype = builder.getTokenType(); + if (ttype == JSTokenTypes.STRING_LITERAL || ttype == JSTokenTypes.SINGLE_QUOTE_STRING_LITERAL) { + String ttext = builder.getTokenText(); + assert ttext != null; + + if (lastSymbolEscaped(ttext) || + ttext.startsWith("\"") && (!ttext.endsWith("\"") || ttext.length() == 1) || + ttext.startsWith("\'") && (!ttext.endsWith("\'") || ttext.length() == 1)) { + return JavaScriptLocalize.javascriptParserMessageUnclosedStringLiteral(); + } + } + + return null; + } + + private static boolean lastSymbolEscaped(String text) { + boolean escapes = false; + boolean escaped = true; + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + if (escapes) { + escapes = false; + escaped = true; + continue; + } + if (c == '\\') { + escapes = true; + } + escaped = false; + } + return escapes || escaped; + } + + public void parseObjectLiteralExpression(PsiBuilder builder) { + ExpressionParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.LBRACE); + PsiBuilder.Marker expr = builder.mark(); + builder.advanceLexer(); + + IElementType elementType = builder.getTokenType(); + + while (elementType != JSTokenTypes.RBRACE && elementType != null) { + parseProperty(builder); + + elementType = builder.getTokenType(); + if (elementType == JSTokenTypes.RBRACE) { + break; + } + else if (elementType == JSTokenTypes.COMMA) { + builder.advanceLexer(); + + if (builder.getTokenType() == JSTokenTypes.RBRACE) { + break; + } + } + else { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedComma()); + } + + elementType = builder.getTokenType(); + if (elementType == JSTokenTypes.RBRACE) { + builder.error(JavaScriptLocalize.javascriptParserPropertyExpected()); + } + else if (isNotPropertyStart(builder, elementType)) { + break; + } + } + + Parsing.checkMatches(builder, JSTokenTypes.RBRACE, JavaScriptLocalize.javascriptParserMessageExpectedRbrace()); + expr.done(JSElementTypes.OBJECT_LITERAL_EXPRESSION); + } + + public boolean isNotPropertyStart(PsiBuilder builder, IElementType elementType) { + return !isIdentifierToken(builder, elementType) + && !JavaScriptTokenSets.STRING_LITERALS.contains(elementType) + && elementType != JSTokenTypes.NUMERIC_LITERAL; + } + + protected void parseProperty(PsiBuilder builder) { + IElementType nameToken = builder.getTokenType(); + PsiBuilder.Marker property = builder.mark(); + + if (isNotPropertyStart(builder, nameToken)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedIdentifierStringLiteralOrNumericLiteral()); + } + builder.advanceLexer(); + + Parsing.checkMatches(builder, JSTokenTypes.COLON, JavaScriptLocalize.javascriptParserMessageExpectedColon()); + + builder.putUserData(WITHIN_OBJECT_LITERAL_EXPRESSION, Boolean.TRUE); + if (!parseAssignmentExpression(builder)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + builder.putUserData(WITHIN_OBJECT_LITERAL_EXPRESSION, null); + + property.done(JSElementTypes.PROPERTY); + } + + public void parseArrayLiteralExpression(PsiBuilder builder) { + ExpressionParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.LBRACKET); + PsiBuilder.Marker expr = builder.mark(); + builder.advanceLexer(); + boolean commaExpected = false; + + Boolean save = null; + + try { + save = builder.getUserData(WITHIN_ARRAY_LITERAL_EXPRESSION); + builder.putUserData(WITHIN_ARRAY_LITERAL_EXPRESSION, Boolean.TRUE); + + while (builder.getTokenType() != JSTokenTypes.RBRACKET) { + if (commaExpected) { + boolean b = + Parsing.checkMatches(builder, JSTokenTypes.COMMA, JavaScriptLocalize.javascriptParserMessageExpectedComma()); + if (!b) { + break; + } + } + + while (builder.getTokenType() == JSTokenTypes.COMMA) { + builder.advanceLexer(); + } + + commaExpected = false; + if (builder.getTokenType() != JSTokenTypes.RBRACKET) { + if (!parseAssignmentExpression(builder)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + break; + } + else { + commaExpected = true; + } + } + } + Parsing.checkMatches(builder, JSTokenTypes.RBRACKET, JavaScriptLocalize.javascriptParserMessageExpectedRbracket()); + expr.done(JSElementTypes.ARRAY_LITERAL_EXPRESSION); + } + finally { + builder.putUserData(WITHIN_ARRAY_LITERAL_EXPRESSION, save); + } + } + + private void parseParenthesizedExpression(PsiBuilder builder) { + ExpressionParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.LPAR); + PsiBuilder.Marker expr = builder.mark(); + builder.advanceLexer(); + parseExpression(builder); + Parsing.checkMatches(builder, JSTokenTypes.RPAR, JavaScriptLocalize.javascriptParserMessageExpectedRparen()); + expr.done(JSElementTypes.PARENTHESIZED_EXPRESSION); + } + + protected boolean parseMemberExpression(PsiBuilder builder, boolean allowCallSyntax) { + return parseMemberExpression(builder, allowCallSyntax, MEMBER_OPERATOR_SET); + } + + protected boolean parseMemberExpression(PsiBuilder builder, boolean allowCallSyntax, TokenSet membersOperatorSet) { + PsiBuilder.Marker expr = builder.mark(); + boolean isNew; + + IElementType type = builder.getTokenType(); + + if (type == JSTokenTypes.NEW_KEYWORD) { + isNew = true; + boolean isfunction = parseNewExpression(builder); + + if (isfunction) { + expr.done(JSElementTypes.NEW_EXPRESSION); + if (builder.getTokenType() != JSTokenTypes.LPAR) { + return true; + } + expr = expr.precede(); + isNew = false; + } + } + else { + isNew = false; + if (!parsePrimaryExpression(builder)) { + expr.drop(); + return false; + } + } + + boolean currentlyAllowCallSyntax = allowCallSyntax && (type != JSTokenTypes.LBRACE && type != JSTokenTypes.LBRACKET); + + while (true) { + IElementType tokenType = builder.getTokenType(); + if (membersOperatorSet.contains(tokenType)) { + currentlyAllowCallSyntax = allowCallSyntax; + builder.advanceLexer(); + + if (builder.getTokenType() == JSTokenTypes.AT) { + builder.advanceLexer(); + } + + tokenType = builder.getTokenType(); + + if (tokenType == JSTokenTypes.LBRACKET || tokenType == JSTokenTypes.LPAR) { + continue; + } + + if (tokenType == JSTokenTypes.ANY_IDENTIFIER || isIdentifierToken(builder, tokenType)) { + builder.advanceLexer(); + } + else { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedName()); + } + + expr.done(JSElementTypes.REFERENCE_EXPRESSION); + expr = expr.precede(); + } + else if (tokenType == JSTokenTypes.LBRACKET) { + builder.advanceLexer(); + parseExpression(builder); + Parsing.checkMatches(builder, JSTokenTypes.RBRACKET, JavaScriptLocalize.javascriptParserMessageExpectedRbracket()); + expr.done(JSElementTypes.INDEXED_PROPERTY_ACCESS_EXPRESSION); + expr = expr.precede(); + } + else if (currentlyAllowCallSyntax && tokenType == JSTokenTypes.LPAR) { + parseArgumentList(builder); + expr.done(isNew ? JSElementTypes.NEW_EXPRESSION : JSElementTypes.CALL_EXPRESSION); + expr = expr.precede(); + isNew = false; + } + else { + if (isNew) { + expr.done(JSElementTypes.NEW_EXPRESSION); + } + else { + expr.drop(); + } + break; + } + } + + return true; + } + + public boolean parseQualifiedTypeName(PsiBuilder builder) { + return parseQualifiedTypeName(builder, false); + } + + public boolean parseQualifiedTypeName(PsiBuilder builder, boolean allowStar) { + return parseQualifiedTypeName(builder, allowStar, DOT_SET); + } + + public boolean parseQualifiedTypeName(PsiBuilder builder, boolean allowStar, TokenSet separatorsSet) { + if (JSTokenTypes.IDENTIFIER != builder.getTokenType()) { + return false; + } + PsiBuilder.Marker expr = builder.mark(); + Parsing.buildTokenElement(JSElementTypes.REFERENCE_EXPRESSION, builder); + + while (separatorsSet.contains(builder.getTokenType())) { + boolean stop = false; + builder.advanceLexer(); + + IElementType tokenType = builder.getTokenType(); + if (tokenType == JSTokenTypes.ANY_IDENTIFIER && allowStar) { + builder.advanceLexer(); + stop = true; + } + else if (tokenType == JSTokenTypes.DEFAULT_KEYWORD) { + builder.advanceLexer(); // TODO: allow any keyword + } + else { + Parsing.checkMatches(builder, JSTokenTypes.IDENTIFIER, JavaScriptLocalize.javascriptParserMessageExpectedName()); + } + expr.done(JSElementTypes.REFERENCE_EXPRESSION); + expr = expr.precede(); + + if (stop) { + break; + } + } + + expr.drop(); + return true; + } + + protected boolean parseNewExpression(PsiBuilder builder) { + ExpressionParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.NEW_KEYWORD); + builder.advanceLexer(); + + if (builder.getTokenType() == JSTokenTypes.FUNCTION_KEYWORD) { + getFunctionParsing().parseFunctionExpression(builder); + return true; + } + + if (!parseMemberExpression(builder, false)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + return false; + } + + protected void parseArgumentList(PsiBuilder builder) { + ExpressionParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.LPAR); + PsiBuilder.Marker arglist = builder.mark(); + builder.advanceLexer(); + boolean first = true; + while (builder.getTokenType() != JSTokenTypes.RPAR) { + if (first) { + first = false; + } + else if (builder.getTokenType() == JSTokenTypes.COMMA) { + builder.advanceLexer(); + } + else { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedCommaOrRparen()); + break; + } + if (!parseAssignmentExpression(builder)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + } + + Parsing.checkMatches(builder, JSTokenTypes.RPAR, JavaScriptLocalize.javascriptParserMessageExpectedRparen()); + arglist.done(JSElementTypes.ARGUMENT_LIST); + } + + public void parseExpression(PsiBuilder builder) { + if (!parseExpressionOptional(builder)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + } + + public boolean parseAssignmentExpressionNoIn(PsiBuilder builder) { + return parseAssignmentExpression(builder, false); + } + + public boolean parseAssignmentExpression(PsiBuilder builder) { + return parseAssignmentExpression(builder, true); + } + + private boolean parseAssignmentExpression(PsiBuilder builder, boolean allowIn) { + PsiBuilder.Marker expr = builder.mark(); + + if (JSTokenTypes.ASSIGNMENT_OPERATIONS.contains(builder.getTokenType()) && builder.getUserData(WITHIN_OBJECT_LITERAL_EXPRESSION) == null) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + builder.advanceLexer(); + if (!parseAssignmentExpression(builder, allowIn)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + expr.done(JSElementTypes.ASSIGNMENT_EXPRESSION); + return true; + } + + PsiBuilder.Marker definitionExpr = builder.mark(); + if (!parseConditionalExpression(builder, allowIn)) { + definitionExpr.drop(); + expr.drop(); + return false; + } + + if (JSTokenTypes.ASSIGNMENT_OPERATIONS.contains(builder.getTokenType())) { + definitionExpr.done(JSElementTypes.DEFINITION_EXPRESSION); + builder.advanceLexer(); + if (!parseAssignmentExpression(builder, allowIn)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + expr.done(JSElementTypes.ASSIGNMENT_EXPRESSION); + } + else { + definitionExpr.drop(); + expr.drop(); + } + return true; + } + + private boolean parseConditionalExpression(PsiBuilder builder, boolean allowIn) { + PsiBuilder.Marker expr = builder.mark(); + if (!parseORExpression(builder, allowIn)) { + expr.drop(); + return false; + } + + IElementType nextTokenType = builder.getTokenType(); + + if (nextTokenType == JSTokenTypes.QUEST) { + builder.advanceLexer(); + if (!parseAssignmentExpression(builder, allowIn)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + Parsing.checkMatches(builder, JSTokenTypes.COLON, JavaScriptLocalize.javascriptParserMessageExpectedColon()); + if (!parseAssignmentExpression(builder, allowIn)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + expr.done(JSElementTypes.CONDITIONAL_EXPRESSION); + } + else if (nextTokenType == JSTokenTypes.FOR_KEYWORD && builder.getUserData(WITHIN_ARRAY_LITERAL_EXPRESSION) != null) { + getStatementParsing().parseForLoopHeader(builder); // TODO: make it more clear + expr.done(JSElementTypes.CONDITIONAL_EXPRESSION); + } + else { + expr.drop(); + } + return true; + } + + private boolean parseORExpression(PsiBuilder builder, boolean allowIn) { + PsiBuilder.Marker expr = builder.mark(); + if (!parseANDExpression(builder, allowIn)) { + expr.drop(); + return false; + } + + while (builder.getTokenType() == JSTokenTypes.OROR) { + builder.advanceLexer(); + if (!parseANDExpression(builder, allowIn)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + expr.done(JSElementTypes.BINARY_EXPRESSION); + expr = expr.precede(); + } + + expr.drop(); + return true; + } + + private boolean parseANDExpression(PsiBuilder builder, boolean allowIn) { + PsiBuilder.Marker expr = builder.mark(); + if (!parseBitwiseORExpression(builder, allowIn)) { + expr.drop(); + return false; + } + + while (builder.getTokenType() == JSTokenTypes.ANDAND) { + builder.advanceLexer(); + if (!parseBitwiseORExpression(builder, allowIn)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + expr.done(JSElementTypes.BINARY_EXPRESSION); + expr = expr.precede(); + } + + expr.drop(); + return true; + } + + private boolean parseBitwiseORExpression(PsiBuilder builder, boolean allowIn) { + PsiBuilder.Marker expr = builder.mark(); + if (!parseBitwiseXORExpression(builder, allowIn)) { + expr.drop(); + return false; + } + + while (builder.getTokenType() == JSTokenTypes.OR) { + builder.advanceLexer(); + if (!parseBitwiseXORExpression(builder, allowIn)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + expr.done(JSElementTypes.BINARY_EXPRESSION); + expr = expr.precede(); + } + + expr.drop(); + return true; + } + + private boolean parseBitwiseXORExpression(PsiBuilder builder, boolean allowIn) { + PsiBuilder.Marker expr = builder.mark(); + if (!parseBitwiseANDExpression(builder, allowIn)) { + expr.drop(); + return false; + } + + while (builder.getTokenType() == JSTokenTypes.XOR) { + builder.advanceLexer(); + if (!parseBitwiseANDExpression(builder, allowIn)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + expr.done(JSElementTypes.BINARY_EXPRESSION); + expr = expr.precede(); + } + + expr.drop(); + return true; + } + + private boolean parseBitwiseANDExpression(PsiBuilder builder, boolean allowIn) { + PsiBuilder.Marker expr = builder.mark(); + if (!parseEqualityExpression(builder, allowIn)) { + expr.drop(); + return false; + } + + while (builder.getTokenType() == JSTokenTypes.AND) { + builder.advanceLexer(); + if (!parseEqualityExpression(builder, allowIn)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + expr.done(JSElementTypes.BINARY_EXPRESSION); + expr = expr.precede(); + } + + expr.drop(); + return true; + } + + private boolean parseEqualityExpression(PsiBuilder builder, boolean allowIn) { + PsiBuilder.Marker expr = builder.mark(); + if (!parseRelationalExpression(builder, allowIn)) { + expr.drop(); + return false; + } + + while (JSTokenTypes.EQUALITY_OPERATIONS.contains(builder.getTokenType())) { + builder.advanceLexer(); + if (!parseRelationalExpression(builder, allowIn)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + expr.done(JSElementTypes.BINARY_EXPRESSION); + expr = expr.precede(); + } + + expr.drop(); + return true; + } + + private boolean parseRelationalExpression(PsiBuilder builder, boolean allowIn) { + PsiBuilder.Marker expr = builder.mark(); + if (!parseShiftExpression(builder)) { + expr.drop(); + return false; + } + while (JSTokenTypes.RELATIONAL_OPERATIONS.contains(builder.getTokenType()) + && (allowIn || builder.getTokenType() != JSTokenTypes.IN_KEYWORD)) { + builder.advanceLexer(); + if (!parseShiftExpression(builder)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + expr.done(JSElementTypes.BINARY_EXPRESSION); + expr = expr.precede(); + } + + expr.drop(); + return true; + } + + private boolean parseShiftExpression(PsiBuilder builder) { + PsiBuilder.Marker expr = builder.mark(); + if (!parseAdditiveExpression(builder)) { + expr.drop(); + return false; + } + while (JSTokenTypes.SHIFT_OPERATIONS.contains(builder.getTokenType())) { + builder.advanceLexer(); + if (!parseAdditiveExpression(builder)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + expr.done(JSElementTypes.BINARY_EXPRESSION); + expr = expr.precede(); + } + + expr.drop(); + return true; + } + + private boolean parseAdditiveExpression(PsiBuilder builder) { + PsiBuilder.Marker expr = builder.mark(); + if (!parseMultiplicativeExpression(builder)) { + expr.drop(); + return false; + } + while (JSTokenTypes.ADDITIVE_OPERATIONS.contains(builder.getTokenType())) { + builder.advanceLexer(); + if (!parseMultiplicativeExpression(builder)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + expr.done(JSElementTypes.BINARY_EXPRESSION); + expr = expr.precede(); + } + + expr.drop(); + return true; + } + + private boolean parseIsAsExpression(PsiBuilder builder) { + PsiBuilder.Marker expr = builder.mark(); + if (!parseUnaryExpression(builder)) { + expr.drop(); + return false; + } + + while (builder.getTokenType() == JSTokenTypes.AS_KEYWORD || builder.getTokenType() == JSTokenTypes.IS_KEYWORD) { + builder.advanceLexer(); + if (!parseUnaryExpression(builder)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + expr.done(JSElementTypes.BINARY_EXPRESSION); + expr = expr.precede(); + } + + expr.drop(); + return true; + } + + protected boolean parseMultiplicativeExpression(PsiBuilder builder) { + return parseMultiplicativeExpression(builder, JSTokenTypes.MULTIPLICATIVE_OPERATIONS); + } + + protected boolean parseMultiplicativeExpression(PsiBuilder builder, TokenSet operatorSet) { + PsiBuilder.Marker expr = builder.mark(); + if (!parseIsAsExpression(builder)) { + expr.drop(); + return false; + } + + while (operatorSet.contains(builder.getTokenType())) { + builder.advanceLexer(); + if (!parseUnaryExpression(builder)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + expr.done(JSElementTypes.BINARY_EXPRESSION); + expr = expr.precede(); + } + + expr.drop(); + return true; + } + + private boolean parseUnaryExpression(PsiBuilder builder) { + IElementType tokenType = builder.getTokenType(); + if (JSTokenTypes.UNARY_OPERATIONS.contains(tokenType)) { + PsiBuilder.Marker expr = builder.mark(); + builder.advanceLexer(); + if (!parseUnaryExpression(builder)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + expr.done(JSElementTypes.PREFIX_EXPRESSION); + return true; + } + else { + return parsePostfixExpression(builder); + } + } + + private boolean parsePostfixExpression(PsiBuilder builder) { + PsiBuilder.Marker expr = builder.mark(); + if (!parseMemberExpression(builder, true)) { + expr.drop(); + return false; + } + + IElementType tokenType = builder.getTokenType(); + if (tokenType == JSTokenTypes.PLUSPLUS || tokenType == JSTokenTypes.MINUSMINUS) { + builder.advanceLexer(); + expr.done(JSElementTypes.POSTFIX_EXPRESSION); + } + else { + expr.drop(); + } + return true; + } + + public boolean parseExpressionOptional(PsiBuilder builder) { + return parseExpressionOptional(builder, true); + } + + public boolean parseExpressionOptionalNoIn(PsiBuilder builder) { + return parseExpressionOptional(builder, false); + } + + public boolean parseExpressionOptional(PsiBuilder builder, boolean allowIn) { + PsiBuilder.Marker expr = builder.mark(); + if (!parseAssignmentExpression(builder, allowIn)) { + expr.drop(); + return false; + } + + if (builder.getTokenType() == JSTokenTypes.IN_KEYWORD) { + expr.done(JSElementTypes.DEFINITION_EXPRESSION); + return true; + } + + while (builder.getTokenType() == JSTokenTypes.COMMA) { + builder.advanceLexer(); + if (!parseAssignmentExpression(builder, allowIn)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + + expr.done(JSElementTypes.COMMA_EXPRESSION); + expr = expr.precede(); + } + + expr.drop(); + + return true; + } + + public boolean tryParseType(PsiBuilder builder) { + return false; + } + + public boolean parseType(PsiBuilder builder) { + IElementType tokenType = builder.getTokenType(); + if (JSDocumentationUtils.PRIMITIVE_TYPE_FILTER.contains(tokenType)) { + builder.advanceLexer(); + } + else if (!parseQualifiedTypeName(builder)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedTypename()); + } + return true; + } + + public boolean parseSimpleExpression(PsiBuilder builder) { + if (!parseUnaryExpression(builder)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + return false; + } + return true; + } } diff --git a/base-impl/src/main/java/consulo/javascript/lang/parsing/FunctionParsing.java b/base-impl/src/main/java/consulo/javascript/lang/parsing/FunctionParsing.java index 9e111f13..c62641f2 100644 --- a/base-impl/src/main/java/consulo/javascript/lang/parsing/FunctionParsing.java +++ b/base-impl/src/main/java/consulo/javascript/lang/parsing/FunctionParsing.java @@ -18,208 +18,170 @@ import com.intellij.lang.javascript.JSElementTypes; import com.intellij.lang.javascript.JSTokenTypes; -import consulo.javascript.language.JavaScriptBundle; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.parser.PsiBuilder; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author max */ -public class FunctionParsing extends Parsing -{ - public FunctionParsing(JavaScriptParsingContext context) - { - super(context); - } - - public void parseFunctionExpression(PsiBuilder builder) - { - parseFunction(builder, true); - } - - public void parseFunctionDeclaration(PsiBuilder builder) - { - parseFunction(builder, false); - } - - private void parseFunction(PsiBuilder builder, boolean expressionContext) - { - parseFunctionNoMarker(builder, expressionContext, builder.mark()); - } - - public void parseFunctionNoMarker(final PsiBuilder builder, final boolean expressionContext, final @Nonnull PsiBuilder.Marker functionMarker) - { - if(builder.getTokenType() == JSTokenTypes.FUNCTION_KEYWORD) - { - // function keyword may be ommited in context of get/set property definition - builder.advanceLexer(); - } - - // Function name - - if(!expressionContext) - { - if(isContextKeyword(builder, JSTokenTypes.GET_KEYWORD)) - { - advanceContextKeyword(builder, JSTokenTypes.GET_KEYWORD); - } - else if(isContextKeyword(builder, JSTokenTypes.SET_KEYWORD)) - { - advanceContextKeyword(builder, JSTokenTypes.SET_KEYWORD); - } - } - - if(isIdentifierName(builder, builder.getTokenType())) - { - getExpressionParsing().parseQualifiedTypeName(builder, false); - } - else - { - if(!expressionContext && builder.getTokenType() != JSTokenTypes.LPAR /*get/set as name*/) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.function.name")); - } - } - - parseParameterList(builder); - - getExpressionParsing().tryParseType(builder); - - if(builder.getTokenType() == JSTokenTypes.SEMICOLON) - { - builder.advanceLexer(); - } - else - { - getStatementParsing().parseFunctionBody(builder); - } - - functionMarker.done(expressionContext ? JSElementTypes.FUNCTION_EXPRESSION : JSElementTypes.FUNCTION_DECLARATION); - } - - public void parseParameterList(final PsiBuilder builder) - { - final PsiBuilder.Marker parameterList; - if(builder.getTokenType() != JSTokenTypes.LPAR) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.lparen")); - parameterList = builder.mark(); // To have non-empty parameters list at all the time. - parameterList.done(JSElementTypes.PARAMETER_LIST); - return; - } - else - { - parameterList = builder.mark(); - builder.advanceLexer(); - } - - boolean first = true; - while(builder.getTokenType() != JSTokenTypes.RPAR) - { - if(first) - { - first = false; - } - else - { - if(builder.getTokenType() == JSTokenTypes.COMMA) - { - builder.advanceLexer(); - } - else - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.comma.or.rparen")); - break; - } - } - - parseParameter(builder, null); - } - - if(builder.getTokenType() == JSTokenTypes.RPAR) - { - builder.advanceLexer(); - } - - parameterList.done(JSElementTypes.PARAMETER_LIST); - } - - public void parseParameter(@Nonnull PsiBuilder builder, @Nullable PsiBuilder.Marker parameterMarker) - { - if(parameterMarker == null) - { - parameterMarker = builder.mark(); - } - - if(builder.getTokenType() == JSTokenTypes.DOT_DOT_DOT) - { - builder.advanceLexer(); - } - - if(builder.getTokenType() == JSTokenTypes.IDENTIFIER) - { - builder.advanceLexer(); - getExpressionParsing().tryParseType(builder); - if(builder.getTokenType() == JSTokenTypes.EQ) - { - builder.advanceLexer(); - getExpressionParsing().parseSimpleExpression(builder); - } - parameterMarker.done(JSElementTypes.FORMAL_PARAMETER); - } - else if(builder.getTokenType() == JSTokenTypes.LBRACE) - { - parseDeconstructionParameter(builder, parameterMarker); - } - else - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.formal.parameter.name")); - parameterMarker.drop(); - } - } - - protected void parseDeconstructionParameter(PsiBuilder builder, PsiBuilder.Marker mark) - { - PsiBuilder.Marker desctructionObjectMarker = builder.mark(); - builder.advanceLexer(); - - boolean first = true; - while(!builder.eof()) - { - if(builder.getTokenType() == JSTokenTypes.RBRACE) - { - break; - } - - if(!first) - { - Parsing.checkMatches(builder, JSTokenTypes.COMMA, "Comma expected"); - } - - first = false; - - if(isIdentifierToken(builder)) - { - PsiBuilder.Marker propertyMarker = builder.mark(); - PsiBuilder.Marker varMarker = builder.mark(); - builder.advanceLexer(); - varMarker.done(JSElementTypes.FORMAL_PARAMETER); - propertyMarker.done(JSElementTypes.DESTRUCTURING_SHORTHANDED_PROPERTY); - } - else - { - PsiBuilder.Marker err = builder.mark(); - builder.advanceLexer(); - err.error("Expected identifier"); - } - } - - Parsing.checkMatches(builder, JSTokenTypes.RBRACE, "'}' expected"); - - desctructionObjectMarker.done(JSElementTypes.DESTRUCTURING_OBJECT); - - mark.done(JSElementTypes.DESTRUCTURING_PARAMETER); - } +public class FunctionParsing extends Parsing { + public FunctionParsing(JavaScriptParsingContext context) { + super(context); + } + + public void parseFunctionExpression(PsiBuilder builder) { + parseFunction(builder, true); + } + + public void parseFunctionDeclaration(PsiBuilder builder) { + parseFunction(builder, false); + } + + private void parseFunction(PsiBuilder builder, boolean expressionContext) { + parseFunctionNoMarker(builder, expressionContext, builder.mark()); + } + + public void parseFunctionNoMarker( + PsiBuilder builder, + boolean expressionContext, + @Nonnull PsiBuilder.Marker functionMarker + ) { + if (builder.getTokenType() == JSTokenTypes.FUNCTION_KEYWORD) { + // function keyword may be ommited in context of get/set property definition + builder.advanceLexer(); + } + + // Function name + + if (!expressionContext) { + if (isContextKeyword(builder, JSTokenTypes.GET_KEYWORD)) { + advanceContextKeyword(builder, JSTokenTypes.GET_KEYWORD); + } + else if (isContextKeyword(builder, JSTokenTypes.SET_KEYWORD)) { + advanceContextKeyword(builder, JSTokenTypes.SET_KEYWORD); + } + } + + if (isIdentifierName(builder, builder.getTokenType())) { + getExpressionParsing().parseQualifiedTypeName(builder, false); + } + else if (!expressionContext && builder.getTokenType() != JSTokenTypes.LPAR /*get/set as name*/) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedFunctionName()); + } + + parseParameterList(builder); + + getExpressionParsing().tryParseType(builder); + + if (builder.getTokenType() == JSTokenTypes.SEMICOLON) { + builder.advanceLexer(); + } + else { + getStatementParsing().parseFunctionBody(builder); + } + + functionMarker.done(expressionContext ? JSElementTypes.FUNCTION_EXPRESSION : JSElementTypes.FUNCTION_DECLARATION); + } + + public void parseParameterList(PsiBuilder builder) { + PsiBuilder.Marker parameterList; + if (builder.getTokenType() != JSTokenTypes.LPAR) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedLparen()); + parameterList = builder.mark(); // To have non-empty parameters list at all the time. + parameterList.done(JSElementTypes.PARAMETER_LIST); + return; + } + else { + parameterList = builder.mark(); + builder.advanceLexer(); + } + + boolean first = true; + while (builder.getTokenType() != JSTokenTypes.RPAR) { + if (first) { + first = false; + } + else if (builder.getTokenType() == JSTokenTypes.COMMA) { + builder.advanceLexer(); + } + else { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedCommaOrRparen()); + break; + } + + parseParameter(builder, null); + } + + if (builder.getTokenType() == JSTokenTypes.RPAR) { + builder.advanceLexer(); + } + + parameterList.done(JSElementTypes.PARAMETER_LIST); + } + + public void parseParameter(@Nonnull PsiBuilder builder, @Nullable PsiBuilder.Marker parameterMarker) { + if (parameterMarker == null) { + parameterMarker = builder.mark(); + } + + if (builder.getTokenType() == JSTokenTypes.DOT_DOT_DOT) { + builder.advanceLexer(); + } + + if (builder.getTokenType() == JSTokenTypes.IDENTIFIER) { + builder.advanceLexer(); + getExpressionParsing().tryParseType(builder); + if (builder.getTokenType() == JSTokenTypes.EQ) { + builder.advanceLexer(); + getExpressionParsing().parseSimpleExpression(builder); + } + parameterMarker.done(JSElementTypes.FORMAL_PARAMETER); + } + else if (builder.getTokenType() == JSTokenTypes.LBRACE) { + parseDeconstructionParameter(builder, parameterMarker); + } + else { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedFormalParameterName()); + parameterMarker.drop(); + } + } + + protected void parseDeconstructionParameter(PsiBuilder builder, PsiBuilder.Marker mark) { + PsiBuilder.Marker desctructionObjectMarker = builder.mark(); + builder.advanceLexer(); + + boolean first = true; + while (!builder.eof()) { + if (builder.getTokenType() == JSTokenTypes.RBRACE) { + break; + } + + if (!first) { + Parsing.checkMatches(builder, JSTokenTypes.COMMA, JavaScriptLocalize.javascriptParserMessageExpectedComma()); + } + + first = false; + + if (isIdentifierToken(builder)) { + PsiBuilder.Marker propertyMarker = builder.mark(); + PsiBuilder.Marker varMarker = builder.mark(); + builder.advanceLexer(); + varMarker.done(JSElementTypes.FORMAL_PARAMETER); + propertyMarker.done(JSElementTypes.DESTRUCTURING_SHORTHANDED_PROPERTY); + } + else { + PsiBuilder.Marker err = builder.mark(); + builder.advanceLexer(); + err.error(JavaScriptLocalize.javascriptParserMessageExpectedIdentifier()); + } + } + + Parsing.checkMatches(builder, JSTokenTypes.RBRACE, JavaScriptLocalize.javascriptParserMessageExpectedRbrace()); + + desctructionObjectMarker.done(JSElementTypes.DESTRUCTURING_OBJECT); + + mark.done(JSElementTypes.DESTRUCTURING_PARAMETER); + } } diff --git a/base-impl/src/main/java/consulo/javascript/lang/parsing/JSXParser.java b/base-impl/src/main/java/consulo/javascript/lang/parsing/JSXParser.java index a504887a..dccdf96c 100644 --- a/base-impl/src/main/java/consulo/javascript/lang/parsing/JSXParser.java +++ b/base-impl/src/main/java/consulo/javascript/lang/parsing/JSXParser.java @@ -7,312 +7,263 @@ import consulo.language.ast.ILazyParseableElementType; import consulo.language.ast.TokenType; import consulo.language.parser.PsiBuilder; -import consulo.xml.codeInsight.daemon.XmlErrorMessages; +import consulo.localize.LocalizeValue; +import consulo.xml.impl.localize.XmlErrorLocalize; import consulo.xml.psi.xml.XmlElementType; import consulo.xml.psi.xml.XmlTokenType; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.Stack; /** * @author VISTALL - * @see XmlParsing - * @see HtmlParsing + * @see consulo.xml.psi.impl.source.parsing.xml.XmlParsing + * @see consulo.xml.lang.html.HtmlParsing * @since 2019-12-17 */ -public class JSXParser -{ - private final Stack myTagNamesStack = new Stack<>(); - private static final int BALANCING_DEPTH_THRESHOLD = 1000; - - private PsiBuilder myBuilder; - - public void setBuilder(PsiBuilder builder) - { - myBuilder = builder; - } - - private PsiBuilder.Marker mark() - { - return myBuilder.mark(); - } - - private void advance() - { - myBuilder.advanceLexer(); - } - - private IElementType token() - { - return myBuilder.getTokenType(); - } - - private void error(String error) - { - myBuilder.error(error); - } - - private boolean eof() - { - return myBuilder.eof(); - } - - @Nullable - private String parseTagHeader(final boolean multipleRootTagError, final PsiBuilder.Marker tag) - { - if(multipleRootTagError) - { - final PsiBuilder.Marker error = mark(); - advance(); - error.error(XmlErrorMessages.message("xml.parsing.multiple.root.tags")); - } - else - { - advance(); - } - - final String tagName; - if(token() != JSTokenTypes.XML_NAME || myBuilder.rawLookup(-1) == TokenType.WHITE_SPACE) - { - error(XmlErrorMessages.message("xml.parsing.tag.name.expected")); - tagName = ""; - } - else - { - tagName = myBuilder.getTokenText(); - assert tagName != null; - advance(); - } - myTagNamesStack.push(tagName); - - do - { - final IElementType tt = token(); - if(tt == JSTokenTypes.XML_NAME) - { - parseAttribute(); - } - else if(tt == JSTokenTypes.XML_JS_SCRIPT) - { - advance(); - } - else - { - break; - } - } - while(true); - - if(token() == XmlTokenType.XML_EMPTY_ELEMENT_END) - { - advance(); - myTagNamesStack.pop(); - tag.done(JSElementTypes.XML_LITERAL_EXPRESSION); - return null; - } - - if(token() == JSTokenTypes.XML_TAG_END) - { - advance(); - } - else - { - error(XmlErrorMessages.message("tag.start.is.not.closed")); - myTagNamesStack.pop(); - tag.done(JSElementTypes.XML_LITERAL_EXPRESSION); - return null; - } - - if(myTagNamesStack.size() > BALANCING_DEPTH_THRESHOLD) - { - error(XmlErrorMessages.message("way.too.unbalanced")); - tag.done(JSElementTypes.XML_LITERAL_EXPRESSION); - return null; - } - - return tagName; - } - - - private void parseAttribute() - { - assert token() == XmlTokenType.XML_NAME; - final PsiBuilder.Marker att = mark(); - advance(); - if(token() == XmlTokenType.XML_EQ) - { - advance(); - parseAttributeValue(); - } - att.done(XmlElementType.XML_ATTRIBUTE); - } - - private void parseAttributeValue() - { - final PsiBuilder.Marker attValue = mark(); - if(token() == XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER) - { - while(true) - { - final IElementType tt = token(); - if(tt == null || tt == XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER || tt == XmlTokenType.XML_END_TAG_START || tt == XmlTokenType.XML_EMPTY_ELEMENT_END || - tt == JSTokenTypes.XML_START_TAG_START) - { - break; - } - - if(tt == JSTokenTypes.BAD_CHARACTER) - { - final PsiBuilder.Marker error = mark(); - advance(); - error.error(XmlErrorMessages.message("unescaped.ampersand.or.nonterminated.character.entity.reference")); - } - else - { - advance(); - } - } - - if(token() == XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER) - { - advance(); - } - else - { - error(XmlErrorMessages.message("xml.parsing.unclosed.attribute.value")); - } - } - else if(token() == JSTokenTypes.XML_JS_SCRIPT) - { - advance(); - } - else - { - if(token() != XmlTokenType.XML_TAG_END && token() != XmlTokenType.XML_EMPTY_ELEMENT_END) - { - advance(); // Single token att value - } - } - - attValue.done(XmlElementType.XML_ATTRIBUTE_VALUE); - } - - public void parseTagContent() - { - PsiBuilder.Marker xmlText = null; - while(true) - { - final IElementType tt = token(); - if(tt == null || tt == XmlTokenType.XML_END_TAG_START) - { - break; - } - - if(tt == JSTokenTypes.XML_START_TAG_START) - { - xmlText = terminateText(xmlText); - parseTag(false); - } - else if(tt == JSTokenTypes.BAD_CHARACTER) - { - xmlText = startText(xmlText); - final PsiBuilder.Marker error = mark(); - advance(); - error.error(XmlErrorMessages.message("unescaped.ampersand.or.nonterminated.character.entity.reference")); - } - else if(tt instanceof ICustomParsingType || tt instanceof ILazyParseableElementType) - { - xmlText = terminateText(xmlText); - advance(); - } - else - { - xmlText = startText(xmlText); - advance(); - } - } - - terminateText(xmlText); - } - - @Nullable - private static PsiBuilder.Marker terminateText(@Nullable PsiBuilder.Marker xmlText) - { - if(xmlText != null) - { - xmlText.done(XmlElementType.XML_TEXT); - } - return null; - } - - @Nonnull - private PsiBuilder.Marker startText(@Nullable PsiBuilder.Marker xmlText) - { - if(xmlText == null) - { - xmlText = mark(); - } - return xmlText; - } - - protected void parseTag(boolean multipleRootTagError) - { - assert token() == JSTokenTypes.XML_START_TAG_START : "Tag start expected"; - final PsiBuilder.Marker tag = mark(); - - final String tagName = parseTagHeader(multipleRootTagError, tag); - if(tagName == null) - { - return; - } - - final PsiBuilder.Marker content = mark(); - parseTagContent(); - - if(token() == JSTokenTypes.XML_END_TAG_START) - { - final PsiBuilder.Marker footer = mark(); - advance(); - - if(token() == JSTokenTypes.XML_NAME) - { - String endName = myBuilder.getTokenText(); - if(!tagName.equals(endName) && myTagNamesStack.contains(endName)) - { - footer.rollbackTo(); - myTagNamesStack.pop(); - tag.doneBefore(JSElementTypes.XML_LITERAL_EXPRESSION, content, XmlErrorMessages.message("named.element.is.not.closed", tagName)); - content.drop(); - return; - } - - advance(); - } - footer.drop(); - - while(token() != XmlTokenType.XML_TAG_END && token() != XmlTokenType.XML_START_TAG_START && token() != XmlTokenType.XML_END_TAG_START && !eof()) - { - error(XmlErrorMessages.message("xml.parsing.unexpected.token")); - advance(); - } - - if(token() == JSTokenTypes.XML_TAG_END) - { - advance(); - } - else - { - error(XmlErrorMessages.message("xml.parsing.closing.tag.is.not.done")); - } - } - else - { - error(XmlErrorMessages.message("xml.parsing.unexpected.end.of.file")); - } - - content.drop(); - myTagNamesStack.pop(); - tag.done(JSElementTypes.XML_LITERAL_EXPRESSION); - } +public class JSXParser { + public static final String FRAGMENT_TAG = "<<>>"; + + private final Stack myTagNamesStack = new Stack<>(); + private static final int BALANCING_DEPTH_THRESHOLD = 1000; + + private PsiBuilder myBuilder; + + public void setBuilder(PsiBuilder builder) { + myBuilder = builder; + } + + private PsiBuilder.Marker mark() { + return myBuilder.mark(); + } + + private void advance() { + myBuilder.advanceLexer(); + } + + private IElementType token() { + return myBuilder.getTokenType(); + } + + private void error(LocalizeValue error) { + myBuilder.error(error); + } + + private boolean eof() { + return myBuilder.eof(); + } + + @Nullable + private String parseTagHeader(boolean multipleRootTagError, PsiBuilder.Marker tag) { + if (token() == JSTokenTypes.XML_START_TAG_LIST) { + myTagNamesStack.push(FRAGMENT_TAG); + advance(); + return FRAGMENT_TAG; + } + + if (multipleRootTagError) { + PsiBuilder.Marker error = mark(); + advance(); + error.error(XmlErrorLocalize.xmlParsingMultipleRootTags()); + } + else { + advance(); + } + + String tagName; + if (token() != JSTokenTypes.XML_NAME || myBuilder.rawLookup(-1) == TokenType.WHITE_SPACE) { + error(XmlErrorLocalize.xmlParsingTagNameExpected()); + tagName = ""; + } + else { + tagName = myBuilder.getTokenText(); + advance(); + } + myTagNamesStack.push(tagName); + + do { + IElementType tt = token(); + if (tt == JSTokenTypes.XML_NAME) { + parseAttribute(); + } + else if (tt == JSTokenTypes.XML_JS_SCRIPT) { + advance(); + } + else { + break; + } + } + while (true); + + if (token() == XmlTokenType.XML_EMPTY_ELEMENT_END) { + advance(); + myTagNamesStack.pop(); + tag.done(JSElementTypes.XML_LITERAL_EXPRESSION); + return null; + } + + if (token() == JSTokenTypes.XML_TAG_END) { + advance(); + } + else { + error(XmlErrorLocalize.tagStartIsNotClosed()); + myTagNamesStack.pop(); + tag.done(JSElementTypes.XML_LITERAL_EXPRESSION); + return null; + } + + if (myTagNamesStack.size() > BALANCING_DEPTH_THRESHOLD) { + error(XmlErrorLocalize.wayTooUnbalanced()); + tag.done(JSElementTypes.XML_LITERAL_EXPRESSION); + return null; + } + + return tagName; + } + + private void parseAttribute() { + PsiBuilder.Marker att = mark(); + advance(); + if (token() == XmlTokenType.XML_EQ) { + advance(); + parseAttributeValue(); + } + att.done(XmlElementType.XML_ATTRIBUTE); + } + + private void parseAttributeValue() { + PsiBuilder.Marker attValue = mark(); + if (token() == XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER) { + while (true) { + IElementType tt = token(); + if (tt == null || tt == XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER || tt == XmlTokenType.XML_END_TAG_START + || tt == XmlTokenType.XML_EMPTY_ELEMENT_END || tt == JSTokenTypes.XML_START_TAG_START) { + break; + } + + if (tt == JSTokenTypes.BAD_CHARACTER) { + PsiBuilder.Marker error = mark(); + advance(); + error.error(XmlErrorLocalize.unescapedAmpersandOrNonterminatedCharacterEntityReference()); + } + else { + advance(); + } + } + + if (token() == XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER) { + advance(); + } + else { + error(XmlErrorLocalize.xmlParsingUnclosedAttributeValue()); + } + } + else if (token() == JSTokenTypes.XML_JS_SCRIPT) { + advance(); + } + else if (token() != XmlTokenType.XML_TAG_END && token() != XmlTokenType.XML_EMPTY_ELEMENT_END) { + advance(); // Single token att value + } + + attValue.done(XmlElementType.XML_ATTRIBUTE_VALUE); + } + + public void parseTagContent() { + PsiBuilder.Marker xmlText = null; + while (true) { + IElementType tt = token(); + if (tt == null || tt == XmlTokenType.XML_END_TAG_START) { + break; + } + + if (tt == JSTokenTypes.XML_START_TAG_START) { + xmlText = terminateText(xmlText); + parseTag(false); + } + else if (tt == JSTokenTypes.BAD_CHARACTER) { + xmlText = startText(xmlText); + PsiBuilder.Marker error = mark(); + advance(); + error.error(XmlErrorLocalize.unescapedAmpersandOrNonterminatedCharacterEntityReference()); + } + else if (tt instanceof ICustomParsingType || tt instanceof ILazyParseableElementType) { + xmlText = terminateText(xmlText); + advance(); + } + else { + xmlText = startText(xmlText); + advance(); + } + } + + terminateText(xmlText); + } + + @Nullable + private static PsiBuilder.Marker terminateText(@Nullable PsiBuilder.Marker xmlText) { + if (xmlText != null) { + xmlText.done(XmlElementType.XML_TEXT); + } + return null; + } + + @Nonnull + private PsiBuilder.Marker startText(@Nullable PsiBuilder.Marker xmlText) { + if (xmlText == null) { + xmlText = mark(); + } + return xmlText; + } + + protected void parseTag(boolean multipleRootTagError) { + PsiBuilder.Marker tag = mark(); + + String tagName = parseTagHeader(multipleRootTagError, tag); + if (tagName == null) { + return; + } + + PsiBuilder.Marker content = mark(); + parseTagContent(); + + if (token() == JSTokenTypes.XML_END_TAG_START) { + PsiBuilder.Marker footer = mark(); + advance(); + + if (token() == JSTokenTypes.XML_NAME) { + String endName = myBuilder.getTokenText(); + if (!tagName.equals(endName) && myTagNamesStack.contains(endName)) { + footer.rollbackTo(); + myTagNamesStack.pop(); + tag.doneBefore(JSElementTypes.XML_LITERAL_EXPRESSION, content, XmlErrorLocalize.namedElementIsNotClosed(tagName)); + content.drop(); + return; + } + + advance(); + } + footer.drop(); + + while (token() != XmlTokenType.XML_TAG_END && token() != XmlTokenType.XML_START_TAG_START + && token() != XmlTokenType.XML_END_TAG_START && !eof()) { + error(XmlErrorLocalize.xmlParsingUnexpectedToken()); + advance(); + } + + if (token() == JSTokenTypes.XML_TAG_END) { + advance(); + } + else { + error(XmlErrorLocalize.xmlParsingClosingTagIsNotDone()); + } + } + else { + error(XmlErrorLocalize.xmlParsingUnexpectedEndOfFile()); + } + + content.drop(); + myTagNamesStack.pop(); + tag.done(JSElementTypes.XML_LITERAL_EXPRESSION); + } } diff --git a/base-impl/src/main/java/consulo/javascript/lang/parsing/JavaScriptParser.java b/base-impl/src/main/java/consulo/javascript/lang/parsing/JavaScriptParser.java index c2f3d4d5..e3478429 100644 --- a/base-impl/src/main/java/consulo/javascript/lang/parsing/JavaScriptParser.java +++ b/base-impl/src/main/java/consulo/javascript/lang/parsing/JavaScriptParser.java @@ -6,40 +6,35 @@ import consulo.language.parser.PsiParser; import consulo.language.version.LanguageVersion; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 24.08.14 */ -public class JavaScriptParser implements PsiParser -{ - @Nonnull - @Override - public ASTNode parse(@Nonnull IElementType root, @Nonnull PsiBuilder originalBuilder, @Nonnull LanguageVersion languageVersion) - { - JavaScriptParsingContext parsingContext = createParsingContext(); +public class JavaScriptParser implements PsiParser { + @Nonnull + @Override + public ASTNode parse(@Nonnull IElementType root, @Nonnull PsiBuilder originalBuilder, @Nonnull LanguageVersion languageVersion) { + JavaScriptParsingContext parsingContext = createParsingContext(); - JavaScriptParserBuilder builder = createBuilder(originalBuilder); + JavaScriptParserBuilder builder = createBuilder(originalBuilder); - final PsiBuilder.Marker rootMarker = builder.mark(); - while(!builder.eof()) - { - parsingContext.getStatementParsing().parseSourceElement(builder); - } - rootMarker.done(root); - return builder.getTreeBuilt(); - } + PsiBuilder.Marker rootMarker = builder.mark(); + while (!builder.eof()) { + parsingContext.getStatementParsing().parseSourceElement(builder); + } + rootMarker.done(root); + return builder.getTreeBuilt(); + } - @Nonnull - public JavaScriptParserBuilder createBuilder(PsiBuilder builder) - { - return new JavaScriptParserBuilder(builder); - } + @Nonnull + public JavaScriptParserBuilder createBuilder(PsiBuilder builder) { + return new JavaScriptParserBuilder(builder); + } - @Nonnull - public JavaScriptParsingContext createParsingContext() - { - return new JavaScriptParsingContext(); - } + @Nonnull + public JavaScriptParsingContext createParsingContext() { + return new JavaScriptParsingContext(); + } } diff --git a/base-impl/src/main/java/consulo/javascript/lang/parsing/JavaScriptParserBuilder.java b/base-impl/src/main/java/consulo/javascript/lang/parsing/JavaScriptParserBuilder.java index 9dce2832..8d95f0fc 100644 --- a/base-impl/src/main/java/consulo/javascript/lang/parsing/JavaScriptParserBuilder.java +++ b/base-impl/src/main/java/consulo/javascript/lang/parsing/JavaScriptParserBuilder.java @@ -7,10 +7,8 @@ * @author VISTALL * @since 15.02.2016 */ -public class JavaScriptParserBuilder extends PsiBuilderAdapter -{ - public JavaScriptParserBuilder(PsiBuilder delegate) - { - super(delegate); - } +public class JavaScriptParserBuilder extends PsiBuilderAdapter { + public JavaScriptParserBuilder(PsiBuilder delegate) { + super(delegate); + } } diff --git a/base-impl/src/main/java/consulo/javascript/lang/parsing/JavaScriptParsingContext.java b/base-impl/src/main/java/consulo/javascript/lang/parsing/JavaScriptParsingContext.java index ff4fd901..1a726ad2 100644 --- a/base-impl/src/main/java/consulo/javascript/lang/parsing/JavaScriptParsingContext.java +++ b/base-impl/src/main/java/consulo/javascript/lang/parsing/JavaScriptParsingContext.java @@ -3,79 +3,66 @@ import com.intellij.lang.javascript.JSTokenTypes; import consulo.language.ast.IElementType; import consulo.language.parser.PsiBuilder; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 29.08.13. */ -public class JavaScriptParsingContext -{ - private final ExpressionParsing myExpressionParsing; - private final StatementParsing myStatementParsing; - private final FunctionParsing myFunctionParsing; +public class JavaScriptParsingContext { + private final ExpressionParsing myExpressionParsing; + private final StatementParsing myStatementParsing; + private final FunctionParsing myFunctionParsing; - public JavaScriptParsingContext() - { - myExpressionParsing = createExpressionParsing(); - myStatementParsing = createStatementParsing(); - myFunctionParsing = createFunctionParsing(); - } + public JavaScriptParsingContext() { + myExpressionParsing = createExpressionParsing(); + myStatementParsing = createStatementParsing(); + myFunctionParsing = createFunctionParsing(); + } - public boolean isIdentifierToken(PsiBuilder builder, IElementType tokenType) - { - if(isIdentifierName(builder, tokenType)) - { - return true; - } + public boolean isIdentifierToken(PsiBuilder builder, IElementType tokenType) { + if (isIdentifierName(builder, tokenType)) { + return true; + } - if(JSTokenTypes.KEYWORDS.contains(tokenType)) - { - builder.remapCurrentToken(JSTokenTypes.IDENTIFIER); - return true; - } - return false; - } + if (JSTokenTypes.KEYWORDS.contains(tokenType)) { + builder.remapCurrentToken(JSTokenTypes.IDENTIFIER); + return true; + } + return false; + } - public boolean isIdentifierName(PsiBuilder builder, IElementType tokenType) - { - return JSTokenTypes.IDENTIFIER_TOKENS_SET.contains(tokenType); - } + public boolean isIdentifierName(PsiBuilder builder, IElementType tokenType) { + return JSTokenTypes.IDENTIFIER_TOKENS_SET.contains(tokenType); + } - @Nonnull - protected FunctionParsing createFunctionParsing() - { - return new FunctionParsing(this); - } + @Nonnull + protected FunctionParsing createFunctionParsing() { + return new FunctionParsing(this); + } - @Nonnull - protected StatementParsing createStatementParsing() - { - return new StatementParsing(this); - } + @Nonnull + protected StatementParsing createStatementParsing() { + return new StatementParsing(this); + } - @Nonnull - protected ExpressionParsing createExpressionParsing() - { - return new ExpressionParsing(this); - } + @Nonnull + protected ExpressionParsing createExpressionParsing() { + return new ExpressionParsing(this); + } - @Nonnull - public FunctionParsing getFunctionParsing() - { - return myFunctionParsing; - } + @Nonnull + public FunctionParsing getFunctionParsing() { + return myFunctionParsing; + } - @Nonnull - public ExpressionParsing getExpressionParsing() - { - return myExpressionParsing; - } + @Nonnull + public ExpressionParsing getExpressionParsing() { + return myExpressionParsing; + } - @Nonnull - public StatementParsing getStatementParsing() - { - return myStatementParsing; - } + @Nonnull + public StatementParsing getStatementParsing() { + return myStatementParsing; + } } \ No newline at end of file diff --git a/base-impl/src/main/java/consulo/javascript/lang/parsing/Parsing.java b/base-impl/src/main/java/consulo/javascript/lang/parsing/Parsing.java index 378d513a..d66d8c16 100644 --- a/base-impl/src/main/java/consulo/javascript/lang/parsing/Parsing.java +++ b/base-impl/src/main/java/consulo/javascript/lang/parsing/Parsing.java @@ -24,148 +24,107 @@ import consulo.language.parser.PsiBuilder; import consulo.localize.LocalizeValue; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * User: max * Date: Jan 28, 2005 * Time: 7:03:42 PM */ -public class Parsing -{ - private C myContext; - - public Parsing(C context) - { - myContext = context; - } - - public boolean isContextKeyword(@Nonnull PsiBuilder builder, @Nonnull IElementType elementType) - { - if(builder.getTokenType() == JSTokenTypes.IDENTIFIER) - { - IElementType contextKeywordElementType = JavaScriptContextKeywordElementType.getKeywordByText(builder.getTokenText()); - if(contextKeywordElementType == null) - { - return false; - } - if(elementType == contextKeywordElementType) - { - return true; - } - } - return false; - } - - @Nullable - public IElementType isContextKeyword(@Nonnull PsiBuilder builder, @Nonnull TokenSet tokenSet) - { - if(builder.getTokenType() == JSTokenTypes.IDENTIFIER) - { - IElementType contextKeywordElementType = JavaScriptContextKeywordElementType.getKeywordByText(builder.getTokenText()); - if(contextKeywordElementType == null) - { - return null; - } - if(tokenSet.contains(contextKeywordElementType)) - { - return contextKeywordElementType; - } - } - return null; - } - - public void advanceContextKeyword(@Nonnull PsiBuilder builder, @Nonnull IElementType elementType) - { - if(isContextKeyword(builder, elementType)) - { - if(builder instanceof JavaScriptStrictParserBuilder) - { - ((JavaScriptStrictParserBuilder) builder).disableNonStrictRemap(builder.getCurrentOffset()); - } - builder.remapCurrentToken(elementType); - builder.advanceLexer(); - } - } - - public void advanceContextKeyword(@Nonnull PsiBuilder builder, @Nonnull TokenSet tokenSet) - { - IElementType elementType = isContextKeyword(builder, tokenSet); - if(elementType != null) - { - if(builder instanceof JavaScriptStrictParserBuilder) - { - ((JavaScriptStrictParserBuilder) builder).disableNonStrictRemap(builder.getCurrentOffset()); - } - builder.remapCurrentToken(elementType); - builder.advanceLexer(); - } - } - - public FunctionParsing getFunctionParsing() - { - return myContext.getFunctionParsing(); - } - - public StatementParsing getStatementParsing() - { - return myContext.getStatementParsing(); - } - - public ExpressionParsing getExpressionParsing() - { - return myContext.getExpressionParsing(); - } - - public static void buildTokenElement(IElementType type, PsiBuilder builder) - { - final PsiBuilder.Marker marker = builder.mark(); - builder.advanceLexer(); - marker.done(type); - } - - @Deprecated - public static boolean checkMatches(final PsiBuilder builder, final IElementType token, final String message) - { - if(builder.getTokenType() == token) - { - builder.advanceLexer(); - return true; - } - else - { - builder.error(message); - return false; - } - } - - public static boolean checkMatches(final PsiBuilder builder, final IElementType token, final LocalizeValue message) - { - if(builder.getTokenType() == token) - { - builder.advanceLexer(); - return true; - } - else - { - builder.error(message); - return false; - } - } - - public boolean isIdentifierToken(PsiBuilder builder, IElementType tokenType) - { - return myContext.isIdentifierToken(builder, tokenType); - } - - public boolean isIdentifierToken(PsiBuilder builder) - { - return myContext.isIdentifierName(builder, builder.getTokenType()); - } - - public boolean isIdentifierName(PsiBuilder builder, IElementType tokenType) - { - return myContext.isIdentifierName(builder, tokenType); - } +public class Parsing { + private C myContext; + + public Parsing(C context) { + myContext = context; + } + + public boolean isContextKeyword(@Nonnull PsiBuilder builder, @Nonnull IElementType elementType) { + if (builder.getTokenType() == JSTokenTypes.IDENTIFIER) { + IElementType contextKeywordElementType = JavaScriptContextKeywordElementType.getKeywordByText(builder.getTokenText()); + if (contextKeywordElementType == null) { + return false; + } + if (elementType == contextKeywordElementType) { + return true; + } + } + return false; + } + + @Nullable + public IElementType isContextKeyword(@Nonnull PsiBuilder builder, @Nonnull TokenSet tokenSet) { + if (builder.getTokenType() == JSTokenTypes.IDENTIFIER) { + IElementType contextKeywordElementType = JavaScriptContextKeywordElementType.getKeywordByText(builder.getTokenText()); + if (contextKeywordElementType == null) { + return null; + } + if (tokenSet.contains(contextKeywordElementType)) { + return contextKeywordElementType; + } + } + return null; + } + + public void advanceContextKeyword(@Nonnull PsiBuilder builder, @Nonnull IElementType elementType) { + if (isContextKeyword(builder, elementType)) { + if (builder instanceof JavaScriptStrictParserBuilder parserBuilder) { + parserBuilder.disableNonStrictRemap(builder.getCurrentOffset()); + } + builder.remapCurrentToken(elementType); + builder.advanceLexer(); + } + } + + public void advanceContextKeyword(@Nonnull PsiBuilder builder, @Nonnull TokenSet tokenSet) { + IElementType elementType = isContextKeyword(builder, tokenSet); + if (elementType != null) { + if (builder instanceof JavaScriptStrictParserBuilder strictParserBuilder) { + strictParserBuilder.disableNonStrictRemap(builder.getCurrentOffset()); + } + builder.remapCurrentToken(elementType); + builder.advanceLexer(); + } + } + + public FunctionParsing getFunctionParsing() { + return myContext.getFunctionParsing(); + } + + public StatementParsing getStatementParsing() { + return myContext.getStatementParsing(); + } + + public ExpressionParsing getExpressionParsing() { + return myContext.getExpressionParsing(); + } + + public static void buildTokenElement(IElementType type, PsiBuilder builder) { + PsiBuilder.Marker marker = builder.mark(); + builder.advanceLexer(); + marker.done(type); + } + + public static boolean checkMatches(PsiBuilder builder, IElementType token, LocalizeValue message) { + if (builder.getTokenType() == token) { + builder.advanceLexer(); + return true; + } + else { + builder.error(message); + return false; + } + } + + public boolean isIdentifierToken(PsiBuilder builder, IElementType tokenType) { + return myContext.isIdentifierToken(builder, tokenType); + } + + public boolean isIdentifierToken(PsiBuilder builder) { + return myContext.isIdentifierName(builder, builder.getTokenType()); + } + + public boolean isIdentifierName(PsiBuilder builder, IElementType tokenType) { + return myContext.isIdentifierName(builder, tokenType); + } } diff --git a/base-impl/src/main/java/consulo/javascript/lang/parsing/StatementParsing.java b/base-impl/src/main/java/consulo/javascript/lang/parsing/StatementParsing.java index 28b1bdb5..9a8f6079 100644 --- a/base-impl/src/main/java/consulo/javascript/lang/parsing/StatementParsing.java +++ b/base-impl/src/main/java/consulo/javascript/lang/parsing/StatementParsing.java @@ -18,863 +18,732 @@ import com.intellij.lang.javascript.JSElementTypes; import com.intellij.lang.javascript.JSTokenTypes; -import consulo.javascript.language.JavaScriptBundle; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.ast.IElementType; import consulo.language.parser.PsiBuilder; import consulo.logging.Logger; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author max */ -public class StatementParsing extends Parsing -{ - private static final Logger LOG = Logger.getInstance(StatementParsing.class); - - public StatementParsing(JavaScriptParsingContext context) - { - super(context); - } - - public void parseSourceElement(PsiBuilder builder) - { - final IElementType tokenType = builder.getTokenType(); - if(tokenType == JSTokenTypes.FUNCTION_KEYWORD) - { - getFunctionParsing().parseFunctionDeclaration(builder); - } - else - { - parseStatement(builder); - } - } - - private void parsePackageBodyStatement(PsiBuilder builder) - { - doParseStatement(builder, true); - } - - public void parseStatement(PsiBuilder builder) - { - doParseStatement(builder, false); - } - - protected void doParseStatement(final PsiBuilder builder, boolean canHaveClasses) - { - final IElementType firstToken = builder.getTokenType(); - - if(firstToken == null) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.statement")); - return; - } - - if(firstToken == JSTokenTypes.LBRACE) - { - parseBlock(builder); - return; - } - - if(firstToken == JSTokenTypes.VAR_KEYWORD || - firstToken == JSTokenTypes.CONST_KEYWORD || - firstToken == JSTokenTypes.LET_KEYWORD) - { - parseVarStatement(builder, false); - return; - } - - if(firstToken == JSTokenTypes.SEMICOLON) - { - parseEmptyStatement(builder); - return; - } - - if(firstToken == JSTokenTypes.IF_KEYWORD) - { - parseIfStatement(builder); - return; - } - - if(firstToken == JSTokenTypes.DO_KEYWORD || - firstToken == JSTokenTypes.WHILE_KEYWORD || - firstToken == JSTokenTypes.FOR_KEYWORD) - { - parseIterationStatement(builder); - return; - } - - if(firstToken == JSTokenTypes.CONTINUE_KEYWORD) - { - parseContinueStatement(builder); - return; - } - - if(firstToken == JSTokenTypes.BREAK_KEYWORD) - { - parseBreakStatement(builder); - return; - } - - if(firstToken == JSTokenTypes.RETURN_KEYWORD) - { - parseReturnStatement(builder); - return; - } - - if(firstToken == JSTokenTypes.WITH_KEYWORD) - { - parseWithStatement(builder); - return; - } - - if(firstToken == JSTokenTypes.YIELD_KEYWORD) - { - parseYieldStatement(builder); - return; - } - - if(firstToken == JSTokenTypes.LET_KEYWORD) - { - parseLetStatement(builder); - return; - } - - if(firstToken == JSTokenTypes.SWITCH_KEYWORD) - { - parseSwitchStatement(builder); - return; - } - - if(firstToken == JSTokenTypes.THROW_KEYWORD) - { - parseThrowStatement(builder); - return; - } - - if(firstToken == JSTokenTypes.TRY_KEYWORD) - { - parseTryStatement(builder); - return; - } - - if(firstToken == JSTokenTypes.FUNCTION_KEYWORD) - { - getFunctionParsing().parseFunctionDeclaration(builder); - return; - } - - if(doParseStatementSub(builder, canHaveClasses)) - { - return; - } - - if(firstToken == JSTokenTypes.IDENTIFIER) - { - // Try labeled statement: - final PsiBuilder.Marker labeledStatement = builder.mark(); - builder.advanceLexer(); - if(builder.getTokenType() == JSTokenTypes.COLON) - { - builder.advanceLexer(); - parseStatement(builder); - labeledStatement.done(JSElementTypes.LABELED_STATEMENT); - return; - } - else - { - labeledStatement.rollbackTo(); - } - } - - if(firstToken != JSTokenTypes.LBRACE && firstToken != JSTokenTypes.FUNCTION_KEYWORD) - { - if(parseExpressionStatement(builder)) - { - return; - } - } - - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.statement")); - builder.advanceLexer(); - } - - protected boolean doParseStatementSub(PsiBuilder builder, boolean canHaveClasses) - { - return false; - } - - protected boolean parseExpressionStatement(PsiBuilder builder) - { - // Try expression statement - final PsiBuilder.Marker exprStatement = builder.mark(); - if(getExpressionParsing().parseExpressionOptional(builder)) - { - checkForSemicolon(builder); - exprStatement.done(JSElementTypes.EXPRESSION_STATEMENT); - return true; - } - else - { - exprStatement.drop(); - } - return false; - } - - protected void parseYieldStatement(final PsiBuilder builder) - { - StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.YIELD_KEYWORD); - final PsiBuilder.Marker marker = builder.mark(); - builder.advanceLexer(); - - getExpressionParsing().parseExpressionOptional(builder); - checkForSemicolon(builder); - marker.done(JSElementTypes.YIELD_STATEMENT); - } - - protected void parseLetStatement(final PsiBuilder builder) - { - final PsiBuilder.Marker marker = parseLetExpressionStart(builder); - - parseBlock(builder); - marker.done(JSElementTypes.LET_STATEMENT); - } - - PsiBuilder.Marker parseLetExpressionStart(final PsiBuilder builder) - { - StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.LET_KEYWORD); - final PsiBuilder.Marker marker = builder.mark(); - builder.advanceLexer(); - - if(builder.getTokenType() == JSTokenTypes.LPAR) - { - builder.advanceLexer(); - - if(getExpressionParsing().parseAssignmentExpression(builder)) - { - while(builder.getTokenType() == JSTokenTypes.COMMA) - { - builder.advanceLexer(); - if(!getExpressionParsing().parseAssignmentExpression(builder)) - { - break; - } - } - } - Parsing.checkMatches(builder, JSTokenTypes.RPAR, JavaScriptBundle.message("javascript.parser.message.expected.rparen")); - } - return marker; - } - - - public void parseIncludeDirective(final PsiBuilder builder) - { - StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.INCLUDE_KEYWORD); - final PsiBuilder.Marker useNSStatement = builder.mark(); - builder.advanceLexer(); - Parsing.checkMatches(builder, JSTokenTypes.STRING_LITERAL, JavaScriptBundle.message("javascript.parser.message.expected.string.literal")); - checkForSemicolon(builder); - - useNSStatement.done(JSElementTypes.INCLUDE_DIRECTIVE); - } - - protected void parseTryStatement(final PsiBuilder builder) - { - StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.TRY_KEYWORD); - final PsiBuilder.Marker statement = builder.mark(); - builder.advanceLexer(); - parseBlock(builder); - - while(builder.getTokenType() == JSTokenTypes.CATCH_KEYWORD) - { - parseCatchBlock(builder); - } - - if(builder.getTokenType() == JSTokenTypes.FINALLY_KEYWORD) - { - builder.advanceLexer(); - parseBlock(builder); - } - - statement.done(JSElementTypes.TRY_STATEMENT); - } - - private void parseCatchBlock(final PsiBuilder builder) - { - StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.CATCH_KEYWORD); - final PsiBuilder.Marker block = builder.mark(); - builder.advanceLexer(); - Parsing.checkMatches(builder, JSTokenTypes.LPAR, JavaScriptBundle.message("javascript.parser.message.expected.lparen")); - - final IElementType identifierType = builder.getTokenType(); - - if(JSTokenTypes.IDENTIFIER_TOKENS_SET.contains(identifierType)) - { - final PsiBuilder.Marker param = builder.mark(); - builder.advanceLexer(); - - if(!getExpressionParsing().tryParseType(builder)) - { - if(builder.getTokenType() == JSTokenTypes.IF_KEYWORD) - { - builder.advanceLexer(); - Parsing.checkMatches(builder, identifierType, JavaScriptBundle.message("javascript.parser.message.expected.identifier")); - Parsing.checkMatches(builder, JSTokenTypes.INSTANCEOF_KEYWORD, JavaScriptBundle.message("javascript.parser.message.expected.instanceof")); - Parsing.checkMatches(builder, JSTokenTypes.IDENTIFIER, JavaScriptBundle.message("javascript.parser.message.expected.identifier")); - } - } - param.done(JSElementTypes.FORMAL_PARAMETER); - } - else - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.parameter.name")); - } - - Parsing.checkMatches(builder, JSTokenTypes.RPAR, JavaScriptBundle.message("javascript.parser.message.expected.rparen")); - - parseBlock(builder); - - block.done(JSElementTypes.CATCH_BLOCK); - } - - protected void parseThrowStatement(final PsiBuilder builder) - { - StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.THROW_KEYWORD); - final PsiBuilder.Marker statement = builder.mark(); - builder.advanceLexer(); - - getExpressionParsing().parseExpressionOptional(builder); - - checkForSemicolon(builder); - statement.done(JSElementTypes.THROW_STATEMENT); - } - - protected void parseSwitchStatement(final PsiBuilder builder) - { - StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.SWITCH_KEYWORD); - final PsiBuilder.Marker statement = builder.mark(); - builder.advanceLexer(); - - Parsing.checkMatches(builder, JSTokenTypes.LPAR, JavaScriptBundle.message("javascript.parser.message.expected.lparen")); - getExpressionParsing().parseExpression(builder); - Parsing.checkMatches(builder, JSTokenTypes.RPAR, JavaScriptBundle.message("javascript.parser.message.expected.rparen")); - - Parsing.checkMatches(builder, JSTokenTypes.LBRACE, JavaScriptBundle.message("javascript.parser.message.expected.lbrace")); - while(builder.getTokenType() != JSTokenTypes.RBRACE) - { - if(builder.eof()) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.unexpected.end.of.file")); - statement.done(JSElementTypes.SWITCH_STATEMENT); - return; - } - parseCaseOrDefaultClause(builder); - } - - builder.advanceLexer(); - statement.done(JSElementTypes.SWITCH_STATEMENT); - } - - private void parseCaseOrDefaultClause(final PsiBuilder builder) - { - final IElementType firstToken = builder.getTokenType(); - final PsiBuilder.Marker clause = builder.mark(); - if(firstToken != JSTokenTypes.CASE_KEYWORD && firstToken != JSTokenTypes.DEFAULT_KEYWORD) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.catch.or.default")); - } - builder.advanceLexer(); - if(firstToken == JSTokenTypes.CASE_KEYWORD) - { - getExpressionParsing().parseExpression(builder); - } - Parsing.checkMatches(builder, JSTokenTypes.COLON, JavaScriptBundle.message("javascript.parser.message.expected.colon")); - while(true) - { - IElementType token = builder.getTokenType(); - if(token == null || token == JSTokenTypes.CASE_KEYWORD || token == JSTokenTypes.DEFAULT_KEYWORD || token == JSTokenTypes.RBRACE) - { - break; - } - parseStatement(builder); - } - clause.done(JSElementTypes.CASE_CLAUSE); - } - - protected void parseWithStatement(final PsiBuilder builder) - { - StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.WITH_KEYWORD); - final PsiBuilder.Marker statement = builder.mark(); - builder.advanceLexer(); - - Parsing.checkMatches(builder, JSTokenTypes.LPAR, JavaScriptBundle.message("javascript.parser.message.expected.lparen")); - getExpressionParsing().parseExpression(builder); - Parsing.checkMatches(builder, JSTokenTypes.RPAR, JavaScriptBundle.message("javascript.parser.message.expected.rparen")); - - parseStatement(builder); - - statement.done(JSElementTypes.WITH_STATEMENT); - } - - protected void parseReturnStatement(final PsiBuilder builder) - { - StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.RETURN_KEYWORD); - final PsiBuilder.Marker statement = builder.mark(); - boolean hasNewLine = hasSemanticLineBeforeNextToken(builder); - builder.advanceLexer(); - if(!hasNewLine) - { - getExpressionParsing().parseExpressionOptional(builder); - - checkForSemicolon(builder); - } - statement.done(JSElementTypes.RETURN_STATEMENT); - } - - protected void parseBreakStatement(final PsiBuilder builder) - { - StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.BREAK_KEYWORD); - final PsiBuilder.Marker statement = builder.mark(); - - boolean hasSemanticLineBeforeNextToken = hasSemanticLineBeforeNextToken(builder); - builder.advanceLexer(); - - if(!hasSemanticLineBeforeNextToken && builder.getTokenType() == JSTokenTypes.IDENTIFIER) - { - builder.advanceLexer(); - } - - if(builder.getTokenType() == JSTokenTypes.SEMICOLON) - { - builder.advanceLexer(); - } - - statement.done(JSElementTypes.BREAK_STATEMENT); - } - - protected void parseContinueStatement(final PsiBuilder builder) - { - StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.CONTINUE_KEYWORD); - final PsiBuilder.Marker statement = builder.mark(); - boolean hasSemanticLineBeforeNextToken = hasSemanticLineBeforeNextToken(builder); - builder.advanceLexer(); - - if(!hasSemanticLineBeforeNextToken && builder.getTokenType() == JSTokenTypes.IDENTIFIER) - { - builder.advanceLexer(); - } - - if(builder.getTokenType() == JSTokenTypes.SEMICOLON) - { - builder.advanceLexer(); - } - - statement.done(JSElementTypes.CONTINUE_STATEMENT); - } - - protected boolean hasSemanticLineBeforeNextToken(final PsiBuilder builder) - { - IElementType tokenType = builder.getTokenType(); - if(tokenType == null) - { - return true; - } - // force end - if(tokenType == JSTokenTypes.RBRACE) - { - return true; - } - - int step = 1; - IElementType rawElementType; - while((rawElementType = builder.rawLookup(step)) != null) - { - if(rawElementType == JSTokenTypes.WHITE_SPACE) - { - int tokenStart = builder.rawTokenTypeStart(step); - CharSequence originalText = builder.getOriginalText(); - for(int i = tokenStart; i < originalText.length(); i++) - { - char c = originalText.charAt(i); - if(c == '\n') - { - return true; - } - else if(!Character.isWhitespace(c)) - { - return false; - } - else - { - step ++; - } - } - } - else - { - break; - } - } - return false; - } - - protected void parseIterationStatement(final PsiBuilder builder) - { - final IElementType tokenType = builder.getTokenType(); - if(tokenType == JSTokenTypes.DO_KEYWORD) - { - parseDoWhileStatement(builder); - } - else if(tokenType == JSTokenTypes.WHILE_KEYWORD) - { - parseWhileStatement(builder); - } - else if(tokenType == JSTokenTypes.FOR_KEYWORD) - { - parseForStatement(builder); - } - else - { - StatementParsing.LOG.error("Unknown iteration statement"); - } - } - - private void parseForStatement(final PsiBuilder builder) - { - StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.FOR_KEYWORD); - final PsiBuilder.Marker statement = builder.mark(); - final boolean forin = parseForLoopHeader(builder); - - parseStatement(builder); - statement.done(forin ? JSElementTypes.FOR_IN_STATEMENT : JSElementTypes.FOR_STATEMENT); - } - - protected boolean parseForLoopHeader(final PsiBuilder builder) - { - builder.advanceLexer(); - if(builder.getTokenType() == JSTokenTypes.EACH_KEYWORD) - { - builder.advanceLexer(); - } - - Parsing.checkMatches(builder, JSTokenTypes.LPAR, JavaScriptBundle.message("javascript.parser.message.expected.lparen")); - final boolean empty; - if(builder.getTokenType() == JSTokenTypes.VAR_KEYWORD || builder.getTokenType() == JSTokenTypes.LET_KEYWORD) - { - parseVarStatement(builder, true); - empty = false; - } - else - { - empty = !getExpressionParsing().parseExpressionOptional(builder, false); - } - - boolean forin = false; - if(builder.getTokenType() == JSTokenTypes.SEMICOLON) - { - builder.advanceLexer(); - getExpressionParsing().parseExpressionOptional(builder); - - if(builder.getTokenType() == JSTokenTypes.SEMICOLON) - { - builder.advanceLexer(); - } - else - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.semicolon")); - } - getExpressionParsing().parseExpressionOptional(builder); - } - else if(builder.getTokenType() == JSTokenTypes.IN_KEYWORD) - { - forin = true; - if(empty) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.forloop.left.hand.side.expression.or.variable.declaration")); - } - builder.advanceLexer(); - getExpressionParsing().parseExpression(builder); - } - else - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.forloop.in.or.semicolon")); - } - - Parsing.checkMatches(builder, JSTokenTypes.RPAR, JavaScriptBundle.message("javascript.parser.message.expected.rparen")); - return forin; - } - - private void parseWhileStatement(final PsiBuilder builder) - { - StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.WHILE_KEYWORD); - final PsiBuilder.Marker statement = builder.mark(); - builder.advanceLexer(); - - Parsing.checkMatches(builder, JSTokenTypes.LPAR, JavaScriptBundle.message("javascript.parser.message.expected.lparen")); - getExpressionParsing().parseExpression(builder); - Parsing.checkMatches(builder, JSTokenTypes.RPAR, JavaScriptBundle.message("javascript.parser.message.expected.rparen")); - - parseStatement(builder); - statement.done(JSElementTypes.WHILE_STATEMENT); - } - - private void parseDoWhileStatement(final PsiBuilder builder) - { - StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.DO_KEYWORD); - final PsiBuilder.Marker statement = builder.mark(); - builder.advanceLexer(); - - parseStatement(builder); - Parsing.checkMatches(builder, JSTokenTypes.WHILE_KEYWORD, JavaScriptBundle.message("javascript.parser.message.expected.while.keyword")); - Parsing.checkMatches(builder, JSTokenTypes.LPAR, JavaScriptBundle.message("javascript.parser.message.expected.lparen")); - getExpressionParsing().parseExpression(builder); - Parsing.checkMatches(builder, JSTokenTypes.RPAR, JavaScriptBundle.message("javascript.parser.message.expected.rparen")); - checkForSemicolon(builder); - - statement.done(JSElementTypes.DOWHILE_STATEMENT); - } - - protected void parseIfStatement(final PsiBuilder builder) - { - StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.IF_KEYWORD); - final PsiBuilder.Marker ifStatement = builder.mark(); - builder.advanceLexer(); - - Parsing.checkMatches(builder, JSTokenTypes.LPAR, JavaScriptBundle.message("javascript.parser.message.expected.lparen")); - getExpressionParsing().parseExpression(builder); - - // handle empty expressions inside - while(builder.getTokenType() == JSTokenTypes.OROR || builder.getTokenType() == JSTokenTypes.EQEQ) - { - builder.advanceLexer(); - } - - Parsing.checkMatches(builder, JSTokenTypes.RPAR, JavaScriptBundle.message("javascript.parser.message.expected.rparen")); - - parseStatement(builder); - - if(builder.getTokenType() == JSTokenTypes.ELSE_KEYWORD) - { - builder.advanceLexer(); - parseStatement(builder); - } - - ifStatement.done(JSElementTypes.IF_STATEMENT); - } - - protected void parseEmptyStatement(final PsiBuilder builder) - { - StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.SEMICOLON); - final PsiBuilder.Marker statement = builder.mark(); - builder.advanceLexer(); - statement.done(JSElementTypes.EMPTY_STATEMENT); - } - - protected void parseVarStatement(final PsiBuilder builder, final boolean inForInitializationContext) - { - parseVarStatementWithMarker(builder, inForInitializationContext, builder.mark()); - } - - protected void parseVarStatementWithMarker(final PsiBuilder builder, final boolean inForInitializationContext, final @Nonnull PsiBuilder.Marker var) - { - final IElementType declType = builder.getTokenType(); - LOG.assertTrue(declType == JSTokenTypes.VAR_KEYWORD || - declType == JSTokenTypes.CONST_KEYWORD || - declType == JSTokenTypes.LET_KEYWORD); - - builder.advanceLexer(); - - if(builder.getTokenType() == JSTokenTypes.LBRACE) - { - parseDeconstructionElement(builder); - } - else - { - boolean first = true; - while(true) - { - if(first) - { - first = false; - } - else - { - Parsing.checkMatches(builder, JSTokenTypes.COMMA, JavaScriptBundle.message("javascript.parser.message.expected.comma")); - } - - parseVarDeclaration(builder, !inForInitializationContext); - - if(builder.getTokenType() != JSTokenTypes.COMMA) - { - break; - } - } - } - - if(!inForInitializationContext) - { - checkForSemicolon(builder); - } - - var.done(JSElementTypes.VAR_STATEMENT); - } - - protected void parseDeconstructionElement(PsiBuilder builder) - { - PsiBuilder.Marker mark = builder.mark(); - - PsiBuilder.Marker desctructionObjectMarker = builder.mark(); - builder.advanceLexer(); - - boolean first = true; - while(!builder.eof()) - { - if(builder.getTokenType() == JSTokenTypes.RBRACE) - { - break; - } - - if(!first) - { - Parsing.checkMatches(builder, JSTokenTypes.COMMA, "Comma expected"); - } - - first = false; - - if(isIdentifierToken(builder)) - { - PsiBuilder.Marker propertyMarker = builder.mark(); - PsiBuilder.Marker varMarker = builder.mark(); - builder.advanceLexer(); - varMarker.done(JSElementTypes.VARIABLE); - propertyMarker.done(JSElementTypes.DESTRUCTURING_SHORTHANDED_PROPERTY); - } - else - { - PsiBuilder.Marker err = builder.mark(); - builder.advanceLexer(); - err.error("Expected identifier"); - } - } - - Parsing.checkMatches(builder, JSTokenTypes.RBRACE, "'}' expected"); - - desctructionObjectMarker.done(JSElementTypes.DESTRUCTURING_OBJECT); - - parseVarInitializer(builder, false); - - mark.done(JSElementTypes.DESTRUCTURING_ELEMENT); - } - - protected void checkForSemicolon(final PsiBuilder builder) - { - if(builder.getTokenType() == JSTokenTypes.SEMICOLON) - { - builder.advanceLexer(); - } - } - - protected void parseVarDeclaration(final PsiBuilder builder, boolean allowIn) - { - if(!JSTokenTypes.IDENTIFIER_TOKENS_SET.contains(builder.getTokenType())) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.variable.name")); - builder.advanceLexer(); - return; - } - - PsiBuilder.Marker var = builder.mark(); - - builder.advanceLexer(); - - getExpressionParsing().tryParseType(builder); - - parseVarInitializer(builder, allowIn); - - var.done(JSElementTypes.VARIABLE); - } - - protected void parseVarInitializer(PsiBuilder builder, boolean allowIn) - { - if(builder.getTokenType() == JSTokenTypes.EQ) - { - builder.advanceLexer(); - if(allowIn) - { - if(!getExpressionParsing().parseAssignmentExpression(builder)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - } - else - { - if(!getExpressionParsing().parseAssignmentExpressionNoIn(builder)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - } - } - } - - public void parseBlock(final PsiBuilder builder) - { - parseBlockOrFunctionBody(builder, BlockType.BLOCK); - } - - public void parseFunctionBody(final PsiBuilder builder) - { - parseBlockOrFunctionBody(builder, BlockType.FUNCTION_BODY); - } - - public enum BlockType - { - FUNCTION_BODY, BLOCK, PACKAGE_OR_CLASS_BODY - } - - protected void parseBlockOrFunctionBody(final PsiBuilder builder, BlockType type) - { - final PsiBuilder.Marker block = type != BlockType.PACKAGE_OR_CLASS_BODY ? builder.mark() : null; - if(builder.getTokenType() != JSTokenTypes.LBRACE) - { - if(block != null) - { - block.rollbackTo(); - } - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.lbrace")); - return; - } - - builder.advanceLexer(); - while(builder.getTokenType() != JSTokenTypes.RBRACE) - { - if(builder.eof()) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.missing.rbrace")); - if(block != null) - { - block.done(JSElementTypes.BLOCK_STATEMENT); - } - return; - } - - if(type == BlockType.FUNCTION_BODY) - { - parseSourceElement(builder); - } - else if(type == BlockType.BLOCK) - { - parseStatement(builder); - } - else - { - parsePackageBodyStatement(builder); - } - } - - builder.advanceLexer(); - if(block != null) - { - block.done(JSElementTypes.BLOCK_STATEMENT); - } - } +public class StatementParsing extends Parsing { + private static final Logger LOG = Logger.getInstance(StatementParsing.class); + + public StatementParsing(JavaScriptParsingContext context) { + super(context); + } + + public void parseSourceElement(PsiBuilder builder) { + IElementType tokenType = builder.getTokenType(); + if (tokenType == JSTokenTypes.FUNCTION_KEYWORD) { + getFunctionParsing().parseFunctionDeclaration(builder); + } + else { + parseStatement(builder); + } + } + + private void parsePackageBodyStatement(PsiBuilder builder) { + doParseStatement(builder, true); + } + + public void parseStatement(PsiBuilder builder) { + doParseStatement(builder, false); + } + + protected void doParseStatement(PsiBuilder builder, boolean canHaveClasses) { + IElementType firstToken = builder.getTokenType(); + + if (firstToken == null) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedStatement()); + return; + } + + if (firstToken == JSTokenTypes.LBRACE) { + parseBlock(builder); + return; + } + + if (firstToken == JSTokenTypes.VAR_KEYWORD + || firstToken == JSTokenTypes.CONST_KEYWORD + || firstToken == JSTokenTypes.LET_KEYWORD) { + parseVarStatement(builder, false); + return; + } + + if (firstToken == JSTokenTypes.SEMICOLON) { + parseEmptyStatement(builder); + return; + } + + if (firstToken == JSTokenTypes.IF_KEYWORD) { + parseIfStatement(builder); + return; + } + + if (firstToken == JSTokenTypes.DO_KEYWORD + || firstToken == JSTokenTypes.WHILE_KEYWORD + || firstToken == JSTokenTypes.FOR_KEYWORD) { + parseIterationStatement(builder); + return; + } + + if (firstToken == JSTokenTypes.CONTINUE_KEYWORD) { + parseContinueStatement(builder); + return; + } + + if (firstToken == JSTokenTypes.BREAK_KEYWORD) { + parseBreakStatement(builder); + return; + } + + if (firstToken == JSTokenTypes.RETURN_KEYWORD) { + parseReturnStatement(builder); + return; + } + + if (firstToken == JSTokenTypes.WITH_KEYWORD) { + parseWithStatement(builder); + return; + } + + if (firstToken == JSTokenTypes.YIELD_KEYWORD) { + parseYieldStatement(builder); + return; + } + + if (firstToken == JSTokenTypes.LET_KEYWORD) { + parseLetStatement(builder); + return; + } + + if (firstToken == JSTokenTypes.SWITCH_KEYWORD) { + parseSwitchStatement(builder); + return; + } + + if (firstToken == JSTokenTypes.THROW_KEYWORD) { + parseThrowStatement(builder); + return; + } + + if (firstToken == JSTokenTypes.TRY_KEYWORD) { + parseTryStatement(builder); + return; + } + + if (firstToken == JSTokenTypes.FUNCTION_KEYWORD) { + getFunctionParsing().parseFunctionDeclaration(builder); + return; + } + + if (doParseStatementSub(builder, canHaveClasses)) { + return; + } + + if (firstToken == JSTokenTypes.IDENTIFIER) { + // Try labeled statement: + PsiBuilder.Marker labeledStatement = builder.mark(); + builder.advanceLexer(); + if (builder.getTokenType() == JSTokenTypes.COLON) { + builder.advanceLexer(); + parseStatement(builder); + labeledStatement.done(JSElementTypes.LABELED_STATEMENT); + return; + } + else { + labeledStatement.rollbackTo(); + } + } + + if (firstToken != JSTokenTypes.LBRACE && firstToken != JSTokenTypes.FUNCTION_KEYWORD && parseExpressionStatement(builder)) { + return; + } + + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedStatement()); + builder.advanceLexer(); + } + + protected boolean doParseStatementSub(PsiBuilder builder, boolean canHaveClasses) { + return false; + } + + protected boolean parseExpressionStatement(PsiBuilder builder) { + // Try expression statement + PsiBuilder.Marker exprStatement = builder.mark(); + if (getExpressionParsing().parseExpressionOptional(builder)) { + checkForSemicolon(builder); + exprStatement.done(JSElementTypes.EXPRESSION_STATEMENT); + return true; + } + else { + exprStatement.drop(); + } + return false; + } + + protected void parseYieldStatement(PsiBuilder builder) { + StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.YIELD_KEYWORD); + PsiBuilder.Marker marker = builder.mark(); + builder.advanceLexer(); + + getExpressionParsing().parseExpressionOptional(builder); + checkForSemicolon(builder); + marker.done(JSElementTypes.YIELD_STATEMENT); + } + + protected void parseLetStatement(PsiBuilder builder) { + PsiBuilder.Marker marker = parseLetExpressionStart(builder); + + parseBlock(builder); + marker.done(JSElementTypes.LET_STATEMENT); + } + + PsiBuilder.Marker parseLetExpressionStart(PsiBuilder builder) { + StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.LET_KEYWORD); + PsiBuilder.Marker marker = builder.mark(); + builder.advanceLexer(); + + if (builder.getTokenType() == JSTokenTypes.LPAR) { + builder.advanceLexer(); + + if (getExpressionParsing().parseAssignmentExpression(builder)) { + while (builder.getTokenType() == JSTokenTypes.COMMA) { + builder.advanceLexer(); + if (!getExpressionParsing().parseAssignmentExpression(builder)) { + break; + } + } + } + Parsing.checkMatches(builder, JSTokenTypes.RPAR, JavaScriptLocalize.javascriptParserMessageExpectedRparen()); + } + return marker; + } + + + public void parseIncludeDirective(PsiBuilder builder) { + StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.INCLUDE_KEYWORD); + PsiBuilder.Marker useNSStatement = builder.mark(); + builder.advanceLexer(); + Parsing.checkMatches(builder, JSTokenTypes.STRING_LITERAL, JavaScriptLocalize.javascriptParserMessageExpectedStringLiteral()); + checkForSemicolon(builder); + + useNSStatement.done(JSElementTypes.INCLUDE_DIRECTIVE); + } + + protected void parseTryStatement(PsiBuilder builder) { + StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.TRY_KEYWORD); + PsiBuilder.Marker statement = builder.mark(); + builder.advanceLexer(); + parseBlock(builder); + + while (builder.getTokenType() == JSTokenTypes.CATCH_KEYWORD) { + parseCatchBlock(builder); + } + + if (builder.getTokenType() == JSTokenTypes.FINALLY_KEYWORD) { + builder.advanceLexer(); + parseBlock(builder); + } + + statement.done(JSElementTypes.TRY_STATEMENT); + } + + private void parseCatchBlock(PsiBuilder builder) { + StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.CATCH_KEYWORD); + PsiBuilder.Marker block = builder.mark(); + builder.advanceLexer(); + Parsing.checkMatches(builder, JSTokenTypes.LPAR, JavaScriptLocalize.javascriptParserMessageExpectedLparen()); + + IElementType identifierType = builder.getTokenType(); + + if (JSTokenTypes.IDENTIFIER_TOKENS_SET.contains(identifierType)) { + PsiBuilder.Marker param = builder.mark(); + builder.advanceLexer(); + + if (!getExpressionParsing().tryParseType(builder) && builder.getTokenType() == JSTokenTypes.IF_KEYWORD) { + builder.advanceLexer(); + Parsing.checkMatches(builder, identifierType, JavaScriptLocalize.javascriptParserMessageExpectedIdentifier()); + Parsing.checkMatches( + builder, + JSTokenTypes.INSTANCEOF_KEYWORD, + JavaScriptLocalize.javascriptParserMessageExpectedInstanceof() + ); + Parsing.checkMatches(builder, JSTokenTypes.IDENTIFIER, JavaScriptLocalize.javascriptParserMessageExpectedIdentifier()); + } + param.done(JSElementTypes.FORMAL_PARAMETER); + } + else { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedParameterName()); + } + + Parsing.checkMatches(builder, JSTokenTypes.RPAR, JavaScriptLocalize.javascriptParserMessageExpectedRparen()); + + parseBlock(builder); + + block.done(JSElementTypes.CATCH_BLOCK); + } + + protected void parseThrowStatement(PsiBuilder builder) { + StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.THROW_KEYWORD); + PsiBuilder.Marker statement = builder.mark(); + builder.advanceLexer(); + + getExpressionParsing().parseExpressionOptional(builder); + + checkForSemicolon(builder); + statement.done(JSElementTypes.THROW_STATEMENT); + } + + protected void parseSwitchStatement(PsiBuilder builder) { + StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.SWITCH_KEYWORD); + PsiBuilder.Marker statement = builder.mark(); + builder.advanceLexer(); + + Parsing.checkMatches(builder, JSTokenTypes.LPAR, JavaScriptLocalize.javascriptParserMessageExpectedLparen()); + getExpressionParsing().parseExpression(builder); + Parsing.checkMatches(builder, JSTokenTypes.RPAR, JavaScriptLocalize.javascriptParserMessageExpectedRparen()); + + Parsing.checkMatches(builder, JSTokenTypes.LBRACE, JavaScriptLocalize.javascriptParserMessageExpectedLbrace()); + while (builder.getTokenType() != JSTokenTypes.RBRACE) { + if (builder.eof()) { + builder.error(JavaScriptLocalize.javascriptParserMessageUnexpectedEndOfFile()); + statement.done(JSElementTypes.SWITCH_STATEMENT); + return; + } + parseCaseOrDefaultClause(builder); + } + + builder.advanceLexer(); + statement.done(JSElementTypes.SWITCH_STATEMENT); + } + + private void parseCaseOrDefaultClause(PsiBuilder builder) { + IElementType firstToken = builder.getTokenType(); + PsiBuilder.Marker clause = builder.mark(); + if (firstToken != JSTokenTypes.CASE_KEYWORD && firstToken != JSTokenTypes.DEFAULT_KEYWORD) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedCatchOrDefault()); + } + builder.advanceLexer(); + if (firstToken == JSTokenTypes.CASE_KEYWORD) { + getExpressionParsing().parseExpression(builder); + } + Parsing.checkMatches(builder, JSTokenTypes.COLON, JavaScriptLocalize.javascriptParserMessageExpectedColon()); + while (true) { + IElementType token = builder.getTokenType(); + if (token == null || token == JSTokenTypes.CASE_KEYWORD || token == JSTokenTypes.DEFAULT_KEYWORD + || token == JSTokenTypes.RBRACE) { + break; + } + parseStatement(builder); + } + clause.done(JSElementTypes.CASE_CLAUSE); + } + + protected void parseWithStatement(PsiBuilder builder) { + StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.WITH_KEYWORD); + PsiBuilder.Marker statement = builder.mark(); + builder.advanceLexer(); + + Parsing.checkMatches(builder, JSTokenTypes.LPAR, JavaScriptLocalize.javascriptParserMessageExpectedLparen()); + getExpressionParsing().parseExpression(builder); + Parsing.checkMatches(builder, JSTokenTypes.RPAR, JavaScriptLocalize.javascriptParserMessageExpectedRparen()); + + parseStatement(builder); + + statement.done(JSElementTypes.WITH_STATEMENT); + } + + protected void parseReturnStatement(PsiBuilder builder) { + StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.RETURN_KEYWORD); + PsiBuilder.Marker statement = builder.mark(); + boolean hasNewLine = hasSemanticLineBeforeNextToken(builder); + builder.advanceLexer(); + if (!hasNewLine) { + getExpressionParsing().parseExpressionOptional(builder); + + checkForSemicolon(builder); + } + statement.done(JSElementTypes.RETURN_STATEMENT); + } + + protected void parseBreakStatement(PsiBuilder builder) { + StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.BREAK_KEYWORD); + PsiBuilder.Marker statement = builder.mark(); + + boolean hasSemanticLineBeforeNextToken = hasSemanticLineBeforeNextToken(builder); + builder.advanceLexer(); + + if (!hasSemanticLineBeforeNextToken && builder.getTokenType() == JSTokenTypes.IDENTIFIER) { + builder.advanceLexer(); + } + + if (builder.getTokenType() == JSTokenTypes.SEMICOLON) { + builder.advanceLexer(); + } + + statement.done(JSElementTypes.BREAK_STATEMENT); + } + + protected void parseContinueStatement(PsiBuilder builder) { + StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.CONTINUE_KEYWORD); + PsiBuilder.Marker statement = builder.mark(); + boolean hasSemanticLineBeforeNextToken = hasSemanticLineBeforeNextToken(builder); + builder.advanceLexer(); + + if (!hasSemanticLineBeforeNextToken && builder.getTokenType() == JSTokenTypes.IDENTIFIER) { + builder.advanceLexer(); + } + + if (builder.getTokenType() == JSTokenTypes.SEMICOLON) { + builder.advanceLexer(); + } + + statement.done(JSElementTypes.CONTINUE_STATEMENT); + } + + protected boolean hasSemanticLineBeforeNextToken(PsiBuilder builder) { + IElementType tokenType = builder.getTokenType(); + if (tokenType == null) { + return true; + } + // force end + if (tokenType == JSTokenTypes.RBRACE) { + return true; + } + + int step = 1; + IElementType rawElementType; + while ((rawElementType = builder.rawLookup(step)) != null) { + if (rawElementType == JSTokenTypes.WHITE_SPACE) { + int tokenStart = builder.rawTokenTypeStart(step); + CharSequence originalText = builder.getOriginalText(); + for (int i = tokenStart; i < originalText.length(); i++) { + char c = originalText.charAt(i); + if (c == '\n') { + return true; + } + else if (!Character.isWhitespace(c)) { + return false; + } + else { + step++; + } + } + } + else { + break; + } + } + return false; + } + + protected void parseIterationStatement(PsiBuilder builder) { + IElementType tokenType = builder.getTokenType(); + if (tokenType == JSTokenTypes.DO_KEYWORD) { + parseDoWhileStatement(builder); + } + else if (tokenType == JSTokenTypes.WHILE_KEYWORD) { + parseWhileStatement(builder); + } + else if (tokenType == JSTokenTypes.FOR_KEYWORD) { + parseForStatement(builder); + } + else { + StatementParsing.LOG.error("Unknown iteration statement"); + } + } + + private void parseForStatement(PsiBuilder builder) { + StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.FOR_KEYWORD); + PsiBuilder.Marker statement = builder.mark(); + boolean forin = parseForLoopHeader(builder); + + parseStatement(builder); + statement.done(forin ? JSElementTypes.FOR_IN_STATEMENT : JSElementTypes.FOR_STATEMENT); + } + + protected boolean parseForLoopHeader(PsiBuilder builder) { + builder.advanceLexer(); + if (builder.getTokenType() == JSTokenTypes.EACH_KEYWORD) { + builder.advanceLexer(); + } + + Parsing.checkMatches(builder, JSTokenTypes.LPAR, JavaScriptLocalize.javascriptParserMessageExpectedLparen()); + boolean empty; + if (builder.getTokenType() == JSTokenTypes.VAR_KEYWORD || builder.getTokenType() == JSTokenTypes.LET_KEYWORD) { + parseVarStatement(builder, true); + empty = false; + } + else { + empty = !getExpressionParsing().parseExpressionOptional(builder, false); + } + + boolean forin = false; + if (builder.getTokenType() == JSTokenTypes.SEMICOLON) { + builder.advanceLexer(); + getExpressionParsing().parseExpressionOptional(builder); + + if (builder.getTokenType() == JSTokenTypes.SEMICOLON) { + builder.advanceLexer(); + } + else { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedSemicolon()); + } + getExpressionParsing().parseExpressionOptional(builder); + } + else if (builder.getTokenType() == JSTokenTypes.IN_KEYWORD) { + forin = true; + if (empty) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedForloopLeftHandSideExpressionOrVariableDeclaration()); + } + builder.advanceLexer(); + getExpressionParsing().parseExpression(builder); + } + else { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedForloopInOrSemicolon()); + } + + Parsing.checkMatches(builder, JSTokenTypes.RPAR, JavaScriptLocalize.javascriptParserMessageExpectedRparen()); + return forin; + } + + private void parseWhileStatement(PsiBuilder builder) { + StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.WHILE_KEYWORD); + PsiBuilder.Marker statement = builder.mark(); + builder.advanceLexer(); + + Parsing.checkMatches(builder, JSTokenTypes.LPAR, JavaScriptLocalize.javascriptParserMessageExpectedLparen()); + getExpressionParsing().parseExpression(builder); + Parsing.checkMatches(builder, JSTokenTypes.RPAR, JavaScriptLocalize.javascriptParserMessageExpectedRparen()); + + parseStatement(builder); + statement.done(JSElementTypes.WHILE_STATEMENT); + } + + private void parseDoWhileStatement(PsiBuilder builder) { + StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.DO_KEYWORD); + PsiBuilder.Marker statement = builder.mark(); + builder.advanceLexer(); + + parseStatement(builder); + Parsing.checkMatches(builder, JSTokenTypes.WHILE_KEYWORD, JavaScriptLocalize.javascriptParserMessageExpectedWhileKeyword()); + Parsing.checkMatches(builder, JSTokenTypes.LPAR, JavaScriptLocalize.javascriptParserMessageExpectedLparen()); + getExpressionParsing().parseExpression(builder); + Parsing.checkMatches(builder, JSTokenTypes.RPAR, JavaScriptLocalize.javascriptParserMessageExpectedRparen()); + checkForSemicolon(builder); + + statement.done(JSElementTypes.DOWHILE_STATEMENT); + } + + protected void parseIfStatement(PsiBuilder builder) { + StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.IF_KEYWORD); + PsiBuilder.Marker ifStatement = builder.mark(); + builder.advanceLexer(); + + Parsing.checkMatches(builder, JSTokenTypes.LPAR, JavaScriptLocalize.javascriptParserMessageExpectedLparen()); + getExpressionParsing().parseExpression(builder); + + // handle empty expressions inside + while (builder.getTokenType() == JSTokenTypes.OROR || builder.getTokenType() == JSTokenTypes.EQEQ) { + builder.advanceLexer(); + } + + Parsing.checkMatches(builder, JSTokenTypes.RPAR, JavaScriptLocalize.javascriptParserMessageExpectedRparen()); + + parseStatement(builder); + + if (builder.getTokenType() == JSTokenTypes.ELSE_KEYWORD) { + builder.advanceLexer(); + parseStatement(builder); + } + + ifStatement.done(JSElementTypes.IF_STATEMENT); + } + + protected void parseEmptyStatement(PsiBuilder builder) { + StatementParsing.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.SEMICOLON); + PsiBuilder.Marker statement = builder.mark(); + builder.advanceLexer(); + statement.done(JSElementTypes.EMPTY_STATEMENT); + } + + protected void parseVarStatement(PsiBuilder builder, boolean inForInitializationContext) { + parseVarStatementWithMarker(builder, inForInitializationContext, builder.mark()); + } + + protected void parseVarStatementWithMarker( + PsiBuilder builder, + boolean inForInitializationContext, + @Nonnull PsiBuilder.Marker var + ) { + IElementType declType = builder.getTokenType(); + LOG.assertTrue(declType == JSTokenTypes.VAR_KEYWORD || + declType == JSTokenTypes.CONST_KEYWORD || + declType == JSTokenTypes.LET_KEYWORD); + + builder.advanceLexer(); + + if (builder.getTokenType() == JSTokenTypes.LBRACE) { + parseDeconstructionElement(builder); + } + else { + boolean first = true; + while (true) { + if (first) { + first = false; + } + else { + Parsing.checkMatches(builder, JSTokenTypes.COMMA, JavaScriptLocalize.javascriptParserMessageExpectedComma()); + } + + parseVarDeclaration(builder, !inForInitializationContext); + + if (builder.getTokenType() != JSTokenTypes.COMMA) { + break; + } + } + } + + if (!inForInitializationContext) { + checkForSemicolon(builder); + } + + var.done(JSElementTypes.VAR_STATEMENT); + } + + protected void parseDeconstructionElement(PsiBuilder builder) { + PsiBuilder.Marker mark = builder.mark(); + + PsiBuilder.Marker desctructionObjectMarker = builder.mark(); + builder.advanceLexer(); + + boolean first = true; + while (!builder.eof()) { + if (builder.getTokenType() == JSTokenTypes.RBRACE) { + break; + } + + if (!first) { + Parsing.checkMatches(builder, JSTokenTypes.COMMA, JavaScriptLocalize.javascriptParserMessageExpectedComma()); + } + + first = false; + + if (isIdentifierToken(builder)) { + PsiBuilder.Marker propertyMarker = builder.mark(); + PsiBuilder.Marker varMarker = builder.mark(); + builder.advanceLexer(); + varMarker.done(JSElementTypes.VARIABLE); + propertyMarker.done(JSElementTypes.DESTRUCTURING_SHORTHANDED_PROPERTY); + } + else { + PsiBuilder.Marker err = builder.mark(); + builder.advanceLexer(); + err.error(JavaScriptLocalize.javascriptParserMessageExpectedIdentifier()); + } + } + + Parsing.checkMatches(builder, JSTokenTypes.RBRACE, JavaScriptLocalize.javascriptParserMessageExpectedRbrace()); + + desctructionObjectMarker.done(JSElementTypes.DESTRUCTURING_OBJECT); + + parseVarInitializer(builder, false); + + mark.done(JSElementTypes.DESTRUCTURING_ELEMENT); + } + + protected void checkForSemicolon(PsiBuilder builder) { + if (builder.getTokenType() == JSTokenTypes.SEMICOLON) { + builder.advanceLexer(); + } + } + + protected void parseVarDeclaration(PsiBuilder builder, boolean allowIn) { + if (!JSTokenTypes.IDENTIFIER_TOKENS_SET.contains(builder.getTokenType())) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedVariableName()); + builder.advanceLexer(); + return; + } + + PsiBuilder.Marker var = builder.mark(); + + builder.advanceLexer(); + + getExpressionParsing().tryParseType(builder); + + parseVarInitializer(builder, allowIn); + + var.done(JSElementTypes.VARIABLE); + } + + protected void parseVarInitializer(PsiBuilder builder, boolean allowIn) { + if (builder.getTokenType() == JSTokenTypes.EQ) { + builder.advanceLexer(); + if (allowIn) { + if (!getExpressionParsing().parseAssignmentExpression(builder)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + } + else { + if (!getExpressionParsing().parseAssignmentExpressionNoIn(builder)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + } + } + } + + public void parseBlock(PsiBuilder builder) { + parseBlockOrFunctionBody(builder, BlockType.BLOCK); + } + + public void parseFunctionBody(PsiBuilder builder) { + parseBlockOrFunctionBody(builder, BlockType.FUNCTION_BODY); + } + + public enum BlockType { + FUNCTION_BODY, + BLOCK, + PACKAGE_OR_CLASS_BODY + } + + protected void parseBlockOrFunctionBody(PsiBuilder builder, BlockType type) { + PsiBuilder.Marker block = type != BlockType.PACKAGE_OR_CLASS_BODY ? builder.mark() : null; + if (builder.getTokenType() != JSTokenTypes.LBRACE) { + if (block != null) { + block.rollbackTo(); + } + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedLbrace()); + return; + } + + builder.advanceLexer(); + while (builder.getTokenType() != JSTokenTypes.RBRACE) { + if (builder.eof()) { + builder.error(JavaScriptLocalize.javascriptParserMessageMissingRbrace()); + if (block != null) { + block.done(JSElementTypes.BLOCK_STATEMENT); + } + return; + } + + if (type == BlockType.FUNCTION_BODY) { + parseSourceElement(builder); + } + else if (type == BlockType.BLOCK) { + parseStatement(builder); + } + else { + parsePackageBodyStatement(builder); + } + } + + builder.advanceLexer(); + if (block != null) { + block.done(JSElementTypes.BLOCK_STATEMENT); + } + } } diff --git a/base-impl/src/main/java/consulo/javascript/lang/parsing/impl/JavaSciptDestructuringElementImpl.java b/base-impl/src/main/java/consulo/javascript/lang/parsing/impl/JavaSciptDestructuringElementImpl.java index c510669f..6d5d5b92 100644 --- a/base-impl/src/main/java/consulo/javascript/lang/parsing/impl/JavaSciptDestructuringElementImpl.java +++ b/base-impl/src/main/java/consulo/javascript/lang/parsing/impl/JavaSciptDestructuringElementImpl.java @@ -6,32 +6,28 @@ import com.intellij.lang.javascript.psi.JSElementVisitor; import com.intellij.lang.javascript.psi.impl.JSElementImpl; import consulo.annotation.access.RequiredReadAction; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; /** * @author VISTALL * @since 2019-12-14 */ -public class JavaSciptDestructuringElementImpl extends JSElementImpl implements JSDestructuringElement -{ - public JavaSciptDestructuringElementImpl(ASTNode node) - { - super(node); - } +public class JavaSciptDestructuringElementImpl extends JSElementImpl implements JSDestructuringElement { + public JavaSciptDestructuringElementImpl(ASTNode node) { + super(node); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSElement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSElement(this); + } - @RequiredReadAction - @Nullable - @Override - public JSDestructuringObject getDestructuringObject() - { - return findChildByClass(JSDestructuringObject.class); - } + @RequiredReadAction + @Nullable + @Override + public JSDestructuringObject getDestructuringObject() { + return findChildByClass(JSDestructuringObject.class); + } } diff --git a/base-impl/src/main/java/consulo/javascript/lang/parsing/impl/JavaSciptDestructuringObjectImpl.java b/base-impl/src/main/java/consulo/javascript/lang/parsing/impl/JavaSciptDestructuringObjectImpl.java index 7230a7cb..40e4bf4a 100644 --- a/base-impl/src/main/java/consulo/javascript/lang/parsing/impl/JavaSciptDestructuringObjectImpl.java +++ b/base-impl/src/main/java/consulo/javascript/lang/parsing/impl/JavaSciptDestructuringObjectImpl.java @@ -8,42 +8,37 @@ import consulo.annotation.access.RequiredReadAction; import consulo.language.ast.ASTNode; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; + import java.util.Arrays; /** * @author VISTALL * @since 2019-12-14 */ -public class JavaSciptDestructuringObjectImpl extends JSElementImpl implements JSDestructuringObject -{ - public JavaSciptDestructuringObjectImpl(ASTNode node) - { - super(node); - } +public class JavaSciptDestructuringObjectImpl extends JSElementImpl implements JSDestructuringObject { + public JavaSciptDestructuringObjectImpl(ASTNode node) { + super(node); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSElement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSElement(this); + } - @RequiredReadAction - @Nonnull - @Override - public JSVariable[] getVariables() - { - JSDestructuringShorthandedProperty[] properties = getProperties(); - if(properties.length == 0) - { - return JSVariable.EMPTY_ARRAY; - } - return Arrays.stream(properties).map(JSDestructuringShorthandedProperty::getVarialbe).toArray(JSVariable[]::new); - } + @Nonnull + @Override + @RequiredReadAction + public JSVariable[] getVariables() { + JSDestructuringShorthandedProperty[] properties = getProperties(); + if (properties.length == 0) { + return JSVariable.EMPTY_ARRAY; + } + return Arrays.stream(properties).map(JSDestructuringShorthandedProperty::getVariable).toArray(JSVariable[]::new); + } - @Override - public JSDestructuringShorthandedProperty[] getProperties() - { - return findChildrenByClass(JSDestructuringShorthandedProperty.class); - } + @Override + public JSDestructuringShorthandedProperty[] getProperties() { + return findChildrenByClass(JSDestructuringShorthandedProperty.class); + } } diff --git a/base-impl/src/main/java/consulo/javascript/lang/parsing/impl/JavaScriptDestructuringParameterImpl.java b/base-impl/src/main/java/consulo/javascript/lang/parsing/impl/JavaScriptDestructuringParameterImpl.java index fd91cdb8..09e6ec25 100644 --- a/base-impl/src/main/java/consulo/javascript/lang/parsing/impl/JavaScriptDestructuringParameterImpl.java +++ b/base-impl/src/main/java/consulo/javascript/lang/parsing/impl/JavaScriptDestructuringParameterImpl.java @@ -14,178 +14,157 @@ import consulo.language.util.IncorrectOperationException; import org.jetbrains.annotations.NonNls; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL * @since 2019-12-17 */ -public class JavaScriptDestructuringParameterImpl extends JSElementImpl implements JSDestructuringParameter -{ - public JavaScriptDestructuringParameterImpl(ASTNode node) - { - super(node); - } - - @Override - @RequiredReadAction - public boolean processDeclarations(@Nonnull PsiScopeProcessor processor, @Nonnull ResolveState state, PsiElement lastParent, @Nonnull PsiElement place) - { - JSDestructuringObject destructuringObject = getDestructuringObject(); - if(destructuringObject == null) - { - return true; - } - for(JSVariable variable : destructuringObject.getVariables()) - { - if(!processor.execute(variable, state)) - { - return false; - } - } - return super.processDeclarations(processor, state, lastParent, place); - } - - @Nullable - @Override - public JSVariableStubBase getStub() - { - return null; - } - - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSElement(this); - } - - @RequiredReadAction - @Nullable - @Override - public JSDestructuringObject getDestructuringObject() - { - return findChildByClass(JSDestructuringObject.class); - } - - @Override - public JSFunction getDeclaringFunction() - { - return getStubOrPsiParentOfType(JSFunction.class); - } - - @RequiredReadAction - @Override - public boolean isRest() - { - return false; - } - - @RequiredReadAction - @Nullable - @Override - public PsiElement getRestElement() - { - return null; - } - - @Override - public boolean isOptional() - { - return false; - } - - @Override - public boolean hasInitializer() - { - return false; - } - - @RequiredReadAction - @Nullable - @Override - public JSExpression getInitializer() - { - return null; - } - - @Override - public String getInitializerText() - { - return null; - } - - @Override - public void setInitializer(JSExpression expr) throws IncorrectOperationException - { - - } - - @Nonnull - @Override - public JavaScriptType getType() - { - return JavaScriptType.UNKNOWN; - } - - @Nullable - @Override - public String getTypeString() - { - return null; - } - - @RequiredReadAction - @Nullable - @Override - public JavaScriptTypeElement getTypeElement() - { - return null; - } - - @Override - public boolean isConst() - { - return false; - } - - @Override - public boolean isLocal() - { - return false; - } - - @Override - public boolean isDeprecated() - { - return false; - } - - @Nullable - @Override - public JSAttributeList getAttributeList() - { - return null; - } - - @Override - public String getQualifiedName() - { - return null; - } - - @RequiredReadAction - @Nullable - @Override - public PsiElement getNameIdentifier() - { - return null; - } - - @RequiredWriteAction - @Override - public PsiElement setName(@Nonnull @NonNls String name) throws IncorrectOperationException - { - return null; - } +public class JavaScriptDestructuringParameterImpl extends JSElementImpl implements JSDestructuringParameter { + public JavaScriptDestructuringParameterImpl(ASTNode node) { + super(node); + } + + @Override + @RequiredReadAction + public boolean processDeclarations( + @Nonnull PsiScopeProcessor processor, + @Nonnull ResolveState state, + PsiElement lastParent, + @Nonnull PsiElement place + ) { + JSDestructuringObject destructuringObject = getDestructuringObject(); + if (destructuringObject == null) { + return true; + } + for (JSVariable variable : destructuringObject.getVariables()) { + if (!processor.execute(variable, state)) { + return false; + } + } + return super.processDeclarations(processor, state, lastParent, place); + } + + @Nullable + @Override + public JSVariableStubBase getStub() { + return null; + } + + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSElement(this); + } + + @RequiredReadAction + @Nullable + @Override + public JSDestructuringObject getDestructuringObject() { + return findChildByClass(JSDestructuringObject.class); + } + + @Override + public JSFunction getDeclaringFunction() { + return getStubOrPsiParentOfType(JSFunction.class); + } + + @RequiredReadAction + @Override + public boolean isRest() { + return false; + } + + @RequiredReadAction + @Nullable + @Override + public PsiElement getRestElement() { + return null; + } + + @Override + public boolean isOptional() { + return false; + } + + @Override + public boolean hasInitializer() { + return false; + } + + @RequiredReadAction + @Nullable + @Override + public JSExpression getInitializer() { + return null; + } + + @Override + public String getInitializerText() { + return null; + } + + @Override + public void setInitializer(JSExpression expr) throws IncorrectOperationException { + + } + + @Nonnull + @Override + public JavaScriptType getType() { + return JavaScriptType.UNKNOWN; + } + + @Nullable + @Override + public String getTypeString() { + return null; + } + + @RequiredReadAction + @Nullable + @Override + public JavaScriptTypeElement getTypeElement() { + return null; + } + + @Override + public boolean isConst() { + return false; + } + + @Override + public boolean isLocal() { + return false; + } + + @Override + public boolean isDeprecated() { + return false; + } + + @Nullable + @Override + public JSAttributeList getAttributeList() { + return null; + } + + @Override + @RequiredReadAction + public String getQualifiedName() { + return null; + } + + @RequiredReadAction + @Nullable + @Override + public PsiElement getNameIdentifier() { + return null; + } + + @RequiredWriteAction + @Override + public PsiElement setName(@Nonnull @NonNls String name) throws IncorrectOperationException { + return null; + } } diff --git a/base-impl/src/main/java/consulo/javascript/lang/parsing/impl/JavaScriptDestructuringShorthandedPropertyImpl.java b/base-impl/src/main/java/consulo/javascript/lang/parsing/impl/JavaScriptDestructuringShorthandedPropertyImpl.java index c5d358b6..84df1b61 100644 --- a/base-impl/src/main/java/consulo/javascript/lang/parsing/impl/JavaScriptDestructuringShorthandedPropertyImpl.java +++ b/base-impl/src/main/java/consulo/javascript/lang/parsing/impl/JavaScriptDestructuringShorthandedPropertyImpl.java @@ -7,30 +7,26 @@ import com.intellij.lang.javascript.psi.impl.JSElementImpl; import consulo.annotation.access.RequiredReadAction; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 2019-12-14 */ -public class JavaScriptDestructuringShorthandedPropertyImpl extends JSElementImpl implements JSDestructuringShorthandedProperty -{ - public JavaScriptDestructuringShorthandedPropertyImpl(ASTNode node) - { - super(node); - } +public class JavaScriptDestructuringShorthandedPropertyImpl extends JSElementImpl implements JSDestructuringShorthandedProperty { + public JavaScriptDestructuringShorthandedPropertyImpl(ASTNode node) { + super(node); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSElement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSElement(this); + } - @Nonnull - @RequiredReadAction - @Override - public JSVariable getVarialbe() - { - return findNotNullChildByClass(JSVariable.class); - } + @Nonnull + @Override + @RequiredReadAction + public JSVariable getVariable() { + return findNotNullChildByClass(JSVariable.class); + } } diff --git a/base-impl/src/main/java/consulo/javascript/lang/parsing/impl/JavaScriptStrictParserBuilder.java b/base-impl/src/main/java/consulo/javascript/lang/parsing/impl/JavaScriptStrictParserBuilder.java index 8f4f0021..23d27f2f 100644 --- a/base-impl/src/main/java/consulo/javascript/lang/parsing/impl/JavaScriptStrictParserBuilder.java +++ b/base-impl/src/main/java/consulo/javascript/lang/parsing/impl/JavaScriptStrictParserBuilder.java @@ -10,7 +10,8 @@ import consulo.util.lang.StringUtil; import consulo.util.lang.ThreeState; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; + import java.util.HashMap; import java.util.Map; @@ -18,105 +19,87 @@ * @author VISTALL * @since 15.02.2016 */ -public class JavaScriptStrictParserBuilder extends JavaScriptParserBuilder -{ - private static final int ourExpectedStringSize = JavaScriptConstants.USE_STRICT.length() + 2; // '' or "" - - private ThreeState myStrictState = ThreeState.UNSURE; - - private Map myStrictKeywords = new HashMap(); - - private int[] myDisableNonStrictRemap = ArrayUtil.EMPTY_INT_ARRAY; - - public JavaScriptStrictParserBuilder(PsiBuilder delegate) - { - super(delegate); - } - - public void onlyInStrictMode(IElementType elementType) - { - myStrictKeywords.put(elementType, ThreeState.YES); - } - - public void disableNonStrictRemap(int offset) - { - myDisableNonStrictRemap = ArrayUtil.append(myDisableNonStrictRemap, offset); - } - - @Nullable - @Override - public IElementType getTokenType() - { - checkStrictMode(); - IElementType tokenType = super.getTokenType(); - ThreeState threeState = myStrictKeywords.get(tokenType); - if(threeState != null) - { - if(threeState == myStrictState) - { - return tokenType; - } - else - { - int currentOffset = getCurrentOffset(); - if(ArrayUtil.indexOf(myDisableNonStrictRemap, currentOffset) != -1) - { - return tokenType; - } - - return JSTokenTypes.IDENTIFIER; - } - } - return tokenType; - } - - @Override - public void advanceLexer() - { - IElementType tokenType = getTokenType(); - - IElementType originalTokenType = super.getTokenType(); - - if(tokenType != originalTokenType) - { - remapCurrentToken(tokenType); - } - - super.advanceLexer(); - } - - public boolean isStrictMode() - { - return myStrictState == ThreeState.YES; - } - - private void checkStrictMode() - { - if(myStrictState != ThreeState.UNSURE) - { - return; - } - - IElementType tokenType = super.getTokenType(); - if(JavaScriptTokenSets.STRING_LITERALS.contains(tokenType)) - { - String tokenText = getTokenText(); - if(tokenText == null) - { - return; - } - - int length = tokenText.length(); - if(ourExpectedStringSize == length) - { - String stringContent = StringUtil.unquoteString(tokenText); - if(JavaScriptConstants.USE_STRICT.equals(stringContent)) - { - myStrictState = ThreeState.YES; - return; - } - } - } - myStrictState = ThreeState.NO; - } +public class JavaScriptStrictParserBuilder extends JavaScriptParserBuilder { + private static final int ourExpectedStringSize = JavaScriptConstants.USE_STRICT.length() + 2; // '' or "" + + private ThreeState myStrictState = ThreeState.UNSURE; + + private Map myStrictKeywords = new HashMap<>(); + + private int[] myDisableNonStrictRemap = ArrayUtil.EMPTY_INT_ARRAY; + + public JavaScriptStrictParserBuilder(PsiBuilder delegate) { + super(delegate); + } + + public void onlyInStrictMode(IElementType elementType) { + myStrictKeywords.put(elementType, ThreeState.YES); + } + + public void disableNonStrictRemap(int offset) { + myDisableNonStrictRemap = ArrayUtil.append(myDisableNonStrictRemap, offset); + } + + @Nullable + @Override + public IElementType getTokenType() { + checkStrictMode(); + IElementType tokenType = super.getTokenType(); + ThreeState threeState = myStrictKeywords.get(tokenType); + if (threeState != null) { + if (threeState == myStrictState) { + return tokenType; + } + else { + int currentOffset = getCurrentOffset(); + if (ArrayUtil.indexOf(myDisableNonStrictRemap, currentOffset) != -1) { + return tokenType; + } + + return JSTokenTypes.IDENTIFIER; + } + } + return tokenType; + } + + @Override + public void advanceLexer() { + IElementType tokenType = getTokenType(); + + IElementType originalTokenType = super.getTokenType(); + + if (tokenType != originalTokenType) { + remapCurrentToken(tokenType); + } + + super.advanceLexer(); + } + + public boolean isStrictMode() { + return myStrictState == ThreeState.YES; + } + + private void checkStrictMode() { + if (myStrictState != ThreeState.UNSURE) { + return; + } + + IElementType tokenType = super.getTokenType(); + if (JavaScriptTokenSets.STRING_LITERALS.contains(tokenType)) { + String tokenText = getTokenText(); + if (tokenText == null) { + return; + } + + int length = tokenText.length(); + if (ourExpectedStringSize == length) { + String stringContent = StringUtil.unquoteString(tokenText); + if (JavaScriptConstants.USE_STRICT.equals(stringContent)) { + myStrictState = ThreeState.YES; + return; + } + } + } + myStrictState = ThreeState.NO; + } } diff --git a/base-impl/src/main/java/consulo/javascript/lang/psi/impl/JSRegExpLiteralExpressionImpl.java b/base-impl/src/main/java/consulo/javascript/lang/psi/impl/JSRegExpLiteralExpressionImpl.java index f31d1b72..d532d8b0 100644 --- a/base-impl/src/main/java/consulo/javascript/lang/psi/impl/JSRegExpLiteralExpressionImpl.java +++ b/base-impl/src/main/java/consulo/javascript/lang/psi/impl/JSRegExpLiteralExpressionImpl.java @@ -5,16 +5,14 @@ /** * Own implementation for RegExp literal for correct registration RegExpLanguageHost. - * + *

* String literal with regexp will have own RegExp host * * @author VISTALL * @since 21/12/2021 */ -public class JSRegExpLiteralExpressionImpl extends JSLiteralExpressionImpl -{ - public JSRegExpLiteralExpressionImpl(ASTNode node) - { - super(node); - } +public class JSRegExpLiteralExpressionImpl extends JSLiteralExpressionImpl { + public JSRegExpLiteralExpressionImpl(ASTNode node) { + super(node); + } } diff --git a/base-impl/src/main/java/consulo/javascript/lang/psi/impl/JavaScriptClassType.java b/base-impl/src/main/java/consulo/javascript/lang/psi/impl/JavaScriptClassType.java index 4506aa5c..b8d2fc05 100644 --- a/base-impl/src/main/java/consulo/javascript/lang/psi/impl/JavaScriptClassType.java +++ b/base-impl/src/main/java/consulo/javascript/lang/psi/impl/JavaScriptClassType.java @@ -21,39 +21,31 @@ import consulo.javascript.language.psi.JavaScriptType; import consulo.language.psi.PsiElement; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL * @since 23.02.2016 */ -public class JavaScriptClassType implements JavaScriptType -{ - private JSClass myClass; +public class JavaScriptClassType implements JavaScriptType { + private JSClass myClass; - public JavaScriptClassType(JSClass aClass) - { - myClass = aClass; - } + public JavaScriptClassType(JSClass aClass) { + myClass = aClass; + } - @RequiredReadAction - @Nonnull - @Override - public String getPresentableText() - { - String name = myClass.getName(); - if(name == null) - { - return ""; - } - return name; - } + @RequiredReadAction + @Nonnull + @Override + public String getPresentableText() { + String name = myClass.getName(); + return name == null ? "" : name; + } - @Nullable - @Override - public PsiElement getTargetElement() - { - return myClass; - } + @Nullable + @Override + public PsiElement getTargetElement() { + return myClass; + } } diff --git a/base-impl/src/main/java/consulo/javascript/lang/psi/impl/elementType/BaseJavaScriptElementType.java b/base-impl/src/main/java/consulo/javascript/lang/psi/impl/elementType/BaseJavaScriptElementType.java index f6129e71..7b2fcb06 100644 --- a/base-impl/src/main/java/consulo/javascript/lang/psi/impl/elementType/BaseJavaScriptElementType.java +++ b/base-impl/src/main/java/consulo/javascript/lang/psi/impl/elementType/BaseJavaScriptElementType.java @@ -25,10 +25,9 @@ * @author VISTALL * @since 01.03.2016 */ -public abstract class BaseJavaScriptElementType, P extends JavaScriptTypeElement> extends JSStubElementType -{ - public BaseJavaScriptElementType(@NonNls String debugName) - { - super(debugName); - } +public abstract class BaseJavaScriptElementType, P extends JavaScriptTypeElement> + extends JSStubElementType { + public BaseJavaScriptElementType(@NonNls String debugName) { + super(debugName); + } } diff --git a/base-impl/src/main/java/consulo/javascript/lang/psi/impl/resolve/JavaScriptVersionWithHelper.java b/base-impl/src/main/java/consulo/javascript/lang/psi/impl/resolve/JavaScriptVersionWithHelper.java index 5df55969..2611c0be 100644 --- a/base-impl/src/main/java/consulo/javascript/lang/psi/impl/resolve/JavaScriptVersionWithHelper.java +++ b/base-impl/src/main/java/consulo/javascript/lang/psi/impl/resolve/JavaScriptVersionWithHelper.java @@ -1,13 +1,12 @@ package consulo.javascript.lang.psi.impl.resolve; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 2019-12-14 */ -public interface JavaScriptVersionWithHelper -{ - @Nonnull - ResolveHelper getHelper(); +public interface JavaScriptVersionWithHelper { + @Nonnull + ResolveHelper getHelper(); } diff --git a/base-impl/src/main/java/consulo/javascript/lang/psi/impl/resolve/ResolveHelper.java b/base-impl/src/main/java/consulo/javascript/lang/psi/impl/resolve/ResolveHelper.java index 9b9a2296..d8c7ad4c 100644 --- a/base-impl/src/main/java/consulo/javascript/lang/psi/impl/resolve/ResolveHelper.java +++ b/base-impl/src/main/java/consulo/javascript/lang/psi/impl/resolve/ResolveHelper.java @@ -8,45 +8,36 @@ import consulo.language.psi.PsiNamedElement; import consulo.language.psi.resolve.ResolveState; import consulo.language.version.LanguageVersion; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; /** * @author VISTALL * @since 2019-12-14 */ -public abstract class ResolveHelper -{ - private static final ResolveHelper DEFAULT = new ResolveHelper() - { - }; - - public static ResolveHelper find(PsiElement element) - { - LanguageVersion languageVersion = element.getLanguageVersion(); - if(languageVersion instanceof JavaScriptVersionWithHelper) - { - return ((JavaScriptVersionWithHelper) languageVersion).getHelper(); - } - - return DEFAULT; - } - - @Nullable - public JSImportedElementResolveResult resolveTypeNameUsingImports(final @Nonnull String referencedName, PsiNamedElement parent) - { - return null; - } - - public boolean execute(ResolveProcessor resolveProcessor, PsiElement element, ResolveState state) - { - return false; - } - - @RequiredReadAction - public boolean isResolveTo(JSReferenceExpressionImpl expression, PsiElement element) - { - return false; - } +public abstract class ResolveHelper { + private static final ResolveHelper DEFAULT = new ResolveHelper() { + }; + + public static ResolveHelper find(PsiElement element) { + LanguageVersion languageVersion = element.getLanguageVersion(); + return languageVersion instanceof JavaScriptVersionWithHelper javaScriptVersionWithHelper + ? javaScriptVersionWithHelper.getHelper() + : DEFAULT; + } + + @Nullable + public JSImportedElementResolveResult resolveTypeNameUsingImports(@Nonnull String referencedName, PsiNamedElement parent) { + return null; + } + + public boolean execute(ResolveProcessor resolveProcessor, PsiElement element, ResolveState state) { + return false; + } + + @RequiredReadAction + public boolean isResolveTo(JSReferenceExpressionImpl expression, PsiElement element) { + return false; + } } diff --git a/base-impl/src/main/java/consulo/javascript/lang/viewProvider/JSFileViewProviderFactory.java b/base-impl/src/main/java/consulo/javascript/lang/viewProvider/JSFileViewProviderFactory.java index 2a6b3d23..aab1014a 100644 --- a/base-impl/src/main/java/consulo/javascript/lang/viewProvider/JSFileViewProviderFactory.java +++ b/base-impl/src/main/java/consulo/javascript/lang/viewProvider/JSFileViewProviderFactory.java @@ -12,45 +12,48 @@ import consulo.util.lang.reflect.ReflectionUtil; import consulo.virtualFileSystem.VirtualFile; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 2019-12-17 */ @ExtensionImpl -public class JSFileViewProviderFactory implements LanguageFileViewProviderFactory -{ - private static class JSFileViewProvider extends SingleRootFileViewProvider - { - private JSFileViewProvider(@Nonnull PsiManager manager, @Nonnull VirtualFile virtualFile, boolean eventSystemEnabled, @Nonnull Language language) - { - super(manager, virtualFile, eventSystemEnabled, language); - } +public class JSFileViewProviderFactory implements LanguageFileViewProviderFactory { + private static class JSFileViewProvider extends SingleRootFileViewProvider { + private JSFileViewProvider( + @Nonnull PsiManager manager, + @Nonnull VirtualFile virtualFile, + boolean eventSystemEnabled, + @Nonnull Language language + ) { + super(manager, virtualFile, eventSystemEnabled, language); + } - @Override - @RequiredReadAction - public PsiElement findElementAt(int offset, @Nonnull Class lang) - { - PsiElement elementAt = findElementAt(offset); - if(elementAt != null && ReflectionUtil.isAssignable(lang, elementAt.getLanguage().getClass())) - { - return elementAt; - } - return null; - } - } + @Override + @RequiredReadAction + public PsiElement findElementAt(int offset, @Nonnull Class lang) { + PsiElement elementAt = findElementAt(offset); + if (elementAt != null && ReflectionUtil.isAssignable(lang, elementAt.getLanguage().getClass())) { + return elementAt; + } + return null; + } + } - @Override - public FileViewProvider createFileViewProvider(@Nonnull VirtualFile virtualFile, Language language, @Nonnull PsiManager psiManager, boolean eventSystemEnabled) - { - return new JSFileViewProvider(psiManager, virtualFile, eventSystemEnabled, language); - } + @Override + public FileViewProvider createFileViewProvider( + @Nonnull VirtualFile virtualFile, + Language language, + @Nonnull PsiManager psiManager, + boolean eventSystemEnabled + ) { + return new JSFileViewProvider(psiManager, virtualFile, eventSystemEnabled, language); + } - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } } diff --git a/base-impl/src/main/java/consulo/javascript/types/JSQualifiedStubElementType.java b/base-impl/src/main/java/consulo/javascript/types/JSQualifiedStubElementType.java index 732e831e..0f900285 100644 --- a/base-impl/src/main/java/consulo/javascript/types/JSQualifiedStubElementType.java +++ b/base-impl/src/main/java/consulo/javascript/types/JSQualifiedStubElementType.java @@ -22,45 +22,38 @@ import com.intellij.lang.javascript.psi.stubs.JSQualifiedStub; import consulo.javascript.language.psi.stub.JavaScriptIndexKeys; import consulo.language.psi.stub.IndexSink; +import jakarta.annotation.Nonnull; import org.jetbrains.annotations.NonNls; -import javax.annotation.Nonnull; - /** * @author VISTALL * @since 03.05.2015 */ -public abstract class JSQualifiedStubElementType, PsiT extends JSQualifiedNamedElement> extends JSStubElementType -{ - public JSQualifiedStubElementType(@NonNls String debugName) - { - super(debugName); - } - - @Override - public void indexStub(@Nonnull StubT stub, @Nonnull IndexSink sink) - { - final String name = stub.getName(); - final String fqn = stub.getQualifiedName(); - - if(name != null && doIndexName(stub, name, fqn)) - { - sink.occurrence(JavaScriptIndexKeys.ELEMENTS_BY_NAME, name); - } - - if(fqn != null && doIndexQualifiedName(stub, name, fqn)) - { - sink.occurrence(JavaScriptIndexKeys.ELEMENTS_BY_QNAME, fqn); - } - } - - protected boolean doIndexQualifiedName(StubT stub, final String name, final String fqn) - { - return true; - } - - protected boolean doIndexName(StubT stub, final String name, final String fqn) - { - return true; - } +public abstract class JSQualifiedStubElementType, PsiT extends JSQualifiedNamedElement> + extends JSStubElementType { + public JSQualifiedStubElementType(@NonNls String debugName) { + super(debugName); + } + + @Override + public void indexStub(@Nonnull StubT stub, @Nonnull IndexSink sink) { + String name = stub.getName(); + String fqn = stub.getQualifiedName(); + + if (name != null && doIndexName(stub, name, fqn)) { + sink.occurrence(JavaScriptIndexKeys.ELEMENTS_BY_NAME, name); + } + + if (fqn != null && doIndexQualifiedName(stub, name, fqn)) { + sink.occurrence(JavaScriptIndexKeys.ELEMENTS_BY_QNAME, fqn); + } + } + + protected boolean doIndexQualifiedName(StubT stub, String name, String fqn) { + return true; + } + + protected boolean doIndexName(StubT stub, String name, String fqn) { + return true; + } } diff --git a/base-impl/src/main/java/module-info.java b/base-impl/src/main/java/module-info.java index 4d9ef8fc..dc987e32 100644 --- a/base-impl/src/main/java/module-info.java +++ b/base-impl/src/main/java/module-info.java @@ -2,42 +2,41 @@ * @author VISTALL * @since 23-Aug-22 */ -open module consulo.javascript.base.impl -{ - requires transitive consulo.javascript.base.api; +open module consulo.javascript.base.impl { + requires transitive consulo.javascript.base.api; - requires com.google.common; - requires com.intellij.xml; + requires com.google.common; + requires com.intellij.xml; - exports com.intellij.javascript.documentation; - exports com.intellij.lang.javascript; - exports com.intellij.lang.javascript.flex; - exports com.intellij.lang.javascript.highlighting; - exports com.intellij.lang.javascript.index; - exports com.intellij.lang.javascript.inspections.qucikFixes; - exports com.intellij.lang.javascript.parsing; - exports com.intellij.lang.javascript.psi.impl; - exports com.intellij.lang.javascript.psi.impl.reference; - exports com.intellij.lang.javascript.psi.resolve; - exports com.intellij.lang.javascript.psi.stubs.impl; - exports com.intellij.lang.javascript.psi.util; - exports com.intellij.lang.javascript.search; - exports com.intellij.lang.javascript.types; - exports com.intellij.lang.javascript.validation; - exports consulo.javascript.ecmascript4.psi.impl; - exports consulo.javascript.ide.codeInsight; - exports consulo.javascript.ide.hightlight; - exports consulo.javascript.inspections.qucikFixes; - exports consulo.javascript.lang; - exports consulo.javascript.lang.lexer; - exports consulo.javascript.lang.parsing; - exports consulo.javascript.lang.parsing.impl; - exports consulo.javascript.lang.psi.impl; - exports consulo.javascript.lang.psi.impl.elementType; - exports consulo.javascript.lang.psi.impl.resolve; - exports consulo.javascript.lang.viewProvider; - exports consulo.javascript.impl.language.psi; - exports consulo.javascript.impl.language.psi.stub; - exports consulo.javascript.impl.language; - exports consulo.javascript.types; + exports com.intellij.javascript.documentation; + exports com.intellij.lang.javascript; + exports com.intellij.lang.javascript.flex; + exports com.intellij.lang.javascript.highlighting; + exports com.intellij.lang.javascript.index; + exports com.intellij.lang.javascript.inspections.qucikFixes; + exports com.intellij.lang.javascript.parsing; + exports com.intellij.lang.javascript.psi.impl; + exports com.intellij.lang.javascript.psi.impl.reference; + exports com.intellij.lang.javascript.psi.resolve; + exports com.intellij.lang.javascript.psi.stubs.impl; + exports com.intellij.lang.javascript.psi.util; + exports com.intellij.lang.javascript.search; + exports com.intellij.lang.javascript.types; + exports com.intellij.lang.javascript.validation; + exports consulo.javascript.ecmascript4.psi.impl; + exports consulo.javascript.ide.codeInsight; + exports consulo.javascript.ide.hightlight; + exports consulo.javascript.impl.language.psi; + exports consulo.javascript.impl.language.psi.stub; + exports consulo.javascript.impl.language; + exports consulo.javascript.inspections.qucikFixes; + exports consulo.javascript.lang; + exports consulo.javascript.lang.lexer; + exports consulo.javascript.lang.parsing; + exports consulo.javascript.lang.parsing.impl; + exports consulo.javascript.lang.psi.impl; + exports consulo.javascript.lang.psi.impl.elementType; + exports consulo.javascript.lang.psi.impl.resolve; + exports consulo.javascript.lang.viewProvider; + exports consulo.javascript.types; } \ No newline at end of file diff --git a/debugger/browser-debugger-impl/pom.xml b/debugger/browser-debugger-impl/pom.xml new file mode 100644 index 00000000..5ebf640d --- /dev/null +++ b/debugger/browser-debugger-impl/pom.xml @@ -0,0 +1,75 @@ + + + + 4.0.0 + + consulo + arch.ide-api-provided + 3-SNAPSHOT + + + + consulo.plugin + consulo.javascript-browser.debugger.impl + 3-SNAPSHOT + jar + + + + consulo + https://maven.consulo.dev/repository/snapshots/ + + true + interval:60 + + + + + + + ${project.groupId} + consulo.javascript-base.impl + ${project.version} + + + + ${project.groupId} + consulo.javascript-debugger.impl + ${project.version} + + + + ${project.groupId} + consulo.javascript-cdt.debugger.impl + ${project.version} + + + + ${project.groupId} + com.intellij.xml + ${project.version} + provided + + + + com.google.code.gson + gson + provided + + + \ No newline at end of file diff --git a/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/BrowserCDTDebugProcess.java b/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/BrowserCDTDebugProcess.java new file mode 100644 index 00000000..e0865745 --- /dev/null +++ b/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/BrowserCDTDebugProcess.java @@ -0,0 +1,22 @@ +package consulo.javascript.debugger.browser; + +import consulo.execution.ExecutionResult; +import consulo.execution.debug.XDebugSession; +import consulo.javascript.debugger.cdt.CDTProcessBase; +import consulo.javascript.debugger.cdt.ChromeDevToolsFactory; +import consulo.process.ExecutionException; +import jakarta.annotation.Nonnull; + +/** + * @author VISTALL + * @since 2026-02-15 + */ +public class BrowserCDTDebugProcess extends CDTProcessBase { + public BrowserCDTDebugProcess(@Nonnull XDebugSession session, ExecutionResult result) throws ExecutionException { + super(session, result); + } + + public void init(SessionHolder.BrowserSession session) { + initTools(ChromeDevToolsFactory.create(new ProxyWebSocketService(session))); + } +} diff --git a/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/BrowserDebuggerProcess.java b/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/BrowserDebuggerProcess.java new file mode 100644 index 00000000..9e7e8048 --- /dev/null +++ b/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/BrowserDebuggerProcess.java @@ -0,0 +1,35 @@ +package consulo.javascript.debugger.browser; + +import consulo.builtinWebServer.webSocket.WebSocketConnection; +import consulo.execution.debug.DefaultDebugProcessHandler; +import consulo.javascript.debugger.browser.transport.DetachDebuggerRequest; +import consulo.javascript.debugger.browser.transport.ExtensionWebSocketAccepter; +import jakarta.annotation.Nonnull; + +/** + * @author VISTALL + * @since 2026-02-15 + */ +public class BrowserDebuggerProcess extends DefaultDebugProcessHandler { + private final SessionHolder.BrowserSession myBrowserSession; + + public BrowserDebuggerProcess(@Nonnull SessionHolder.BrowserSession browserSession) { + myBrowserSession = browserSession; + } + + public void setDebugProcess(BrowserCDTDebugProcess cdtProcess) { + myBrowserSession.setDebugProcess(cdtProcess); + } + + @Override + protected void destroyProcessImpl() { + super.destroyProcessImpl(); + + WebSocketConnection connection = myBrowserSession.getWebSocketConnection(); + if (connection != null) { + connection.send(ExtensionWebSocketAccepter.GSON.toJson(new DetachDebuggerRequest(myBrowserSession.getTabId()))); + } + + myBrowserSession.close(); + } +} diff --git a/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/JavaScriptBrowserConfiguration.java b/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/JavaScriptBrowserConfiguration.java new file mode 100644 index 00000000..154737be --- /dev/null +++ b/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/JavaScriptBrowserConfiguration.java @@ -0,0 +1,104 @@ +package consulo.javascript.debugger.browser; + +import consulo.annotation.access.RequiredReadAction; +import consulo.application.Application; +import consulo.compiler.execution.CompileStepBeforeRun; +import consulo.execution.DefaultExecutionResult; +import consulo.execution.ExecutionResult; +import consulo.execution.configuration.*; +import consulo.execution.configuration.ui.SettingsEditor; +import consulo.execution.executor.Executor; +import consulo.execution.runner.ExecutionEnvironment; +import consulo.execution.runner.ProgramRunner; +import consulo.execution.ui.console.ConsoleView; +import consulo.execution.ui.console.TextConsoleBuilder; +import consulo.execution.ui.console.TextConsoleBuilderFactory; +import consulo.module.Module; +import consulo.module.ModuleManager; +import consulo.process.ExecutionException; +import consulo.util.lang.StringUtil; +import consulo.util.xml.serializer.InvalidDataException; +import consulo.util.xml.serializer.WriteExternalException; +import consulo.util.xml.serializer.XmlSerializer; +import consulo.webBrowser.BrowserLauncher; +import consulo.webBrowser.WebBrowser; +import consulo.webBrowser.WebBrowserManager; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; +import org.jdom.Element; + +import java.util.Arrays; +import java.util.Collection; + +/** + * @author VISTALL + * @since 2020-06-15 + */ +public class JavaScriptBrowserConfiguration extends ModuleBasedConfiguration implements RunConfigurationWithSuppressedDefaultRunAction, CompileStepBeforeRun.Suppressor { + public String URL = "http://localhost"; + + public JavaScriptBrowserConfiguration(String name, RunConfigurationModule configurationModule, ConfigurationFactory factory) { + super(name, configurationModule, factory); + } + + public JavaScriptBrowserConfiguration(RunConfigurationModule configurationModule, ConfigurationFactory factory) { + super(configurationModule, factory); + } + + @Override + public void readExternal(Element element) throws InvalidDataException { + super.readExternal(element); + XmlSerializer.deserializeInto(this, element); + } + + @Override + public void writeExternal(Element element) throws WriteExternalException { + super.writeExternal(element); + XmlSerializer.serializeInto(this, element); + } + + @Override + @RequiredReadAction + public Collection getValidModules() { + ModuleManager manager = ModuleManager.getInstance(getProject()); + return Arrays.asList(manager.getModules()); + } + + @Nonnull + @Override + public SettingsEditor getConfigurationEditor() { + return new JavaScriptBrowserConfigurationEditor(); + } + + @Nullable + @Override + public RunProfileState getState(@Nonnull Executor executor, @Nonnull ExecutionEnvironment environment) throws ExecutionException { + return new RunProfileState() { + @Override + public ExecutionResult execute(Executor executor, @Nonnull ProgramRunner programRunner) throws ExecutionException { + TextConsoleBuilder builder = TextConsoleBuilderFactory.getInstance().createBuilder(environment.getProject()); + + ConsoleView console = builder.getConsole(); + + WebBrowserManager manager = WebBrowserManager.getInstance(); + WebBrowser webBrowser = manager.getFirstActiveBrowser(); + + if (webBrowser == null) { + throw new ExecutionException("Can't find Chrome browser"); + } + + if (StringUtil.isEmpty(URL)) { + throw new ExecutionException("URL is empty"); + } + + BrowserLauncher.getInstance().browse(URL, webBrowser, environment.getProject()); + + SessionHolder holder = Application.get().getInstance(SessionHolder.class); + + SessionHolder.BrowserSession browserSession = holder.prepareSession(URL); + + return new DefaultExecutionResult(console, new BrowserDebuggerProcess(browserSession)); + } + }; + } +} diff --git a/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/JavaScriptBrowserConfigurationEditor.java b/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/JavaScriptBrowserConfigurationEditor.java new file mode 100644 index 00000000..2e4f9779 --- /dev/null +++ b/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/JavaScriptBrowserConfigurationEditor.java @@ -0,0 +1,49 @@ +package consulo.javascript.debugger.browser; + +import consulo.configurable.ConfigurationException; +import consulo.execution.configuration.ui.SettingsEditor; +import consulo.localize.LocalizeValue; +import consulo.ui.Component; +import consulo.ui.TextBox; +import consulo.ui.annotation.RequiredUIAccess; +import consulo.ui.util.FormBuilder; +import jakarta.annotation.Nullable; + +import java.util.Objects; + +/** + * @author VISTALL + * @since 2020-06-15 + */ +public class JavaScriptBrowserConfigurationEditor extends SettingsEditor { + private TextBox myUrlBox; + + private FormBuilder myFormBuilder = FormBuilder.create(); + + private Component myRoot; + + public JavaScriptBrowserConfigurationEditor() { + myUrlBox = TextBox.create(); + + myFormBuilder.addLabeled(LocalizeValue.localizeTODO("URL:"), myUrlBox); + + myRoot = myFormBuilder.build(); + } + + @Nullable + @Override + @RequiredUIAccess + protected Component createUIComponent() { + return myRoot; + } + + @Override + protected void resetEditorFrom(JavaScriptBrowserConfiguration javaScriptBrowserConfiguration) { + myUrlBox.setValue(Objects.requireNonNullElse(javaScriptBrowserConfiguration.URL, "")); + } + + @Override + protected void applyEditorTo(JavaScriptBrowserConfiguration javaScriptBrowserConfiguration) throws ConfigurationException { + javaScriptBrowserConfiguration.URL = myUrlBox.getValue(); + } +} diff --git a/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/JavaScriptBrowserConfigurationType.java b/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/JavaScriptBrowserConfigurationType.java new file mode 100644 index 00000000..fb726895 --- /dev/null +++ b/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/JavaScriptBrowserConfigurationType.java @@ -0,0 +1,36 @@ +package consulo.javascript.debugger.browser; + +import consulo.annotation.component.ExtensionImpl; +import consulo.application.AllIcons; +import consulo.execution.configuration.ConfigurationFactory; +import consulo.execution.configuration.ConfigurationTypeBase; +import consulo.execution.configuration.RunConfiguration; +import consulo.execution.configuration.RunConfigurationModule; +import consulo.javascript.module.extension.JavaScriptModuleExtension; +import consulo.localize.LocalizeValue; +import consulo.module.extension.ModuleExtensionHelper; +import consulo.project.Project; +import jakarta.annotation.Nonnull; + +/** + * @author VISTALL + * @since 2020-06-15 + */ +@ExtensionImpl +public class JavaScriptBrowserConfigurationType extends ConfigurationTypeBase { + public JavaScriptBrowserConfigurationType() { + super("JavaScriptBrowserConfigurationType", LocalizeValue.localizeTODO("JavaScript Debug"), AllIcons.RunConfigurations.Web_app); + + addFactory(new ConfigurationFactory(this) { + @Override + public RunConfiguration createTemplateConfiguration(Project project) { + return new JavaScriptBrowserConfiguration(new RunConfigurationModule(project), this); + } + + @Override + public boolean isApplicable(@Nonnull Project project) { + return ModuleExtensionHelper.getInstance(project).hasModuleExtension(JavaScriptModuleExtension.class); + } + }); + } +} diff --git a/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/JavaScriptBrowserDebugRunner.java b/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/JavaScriptBrowserDebugRunner.java new file mode 100644 index 00000000..bcc582f0 --- /dev/null +++ b/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/JavaScriptBrowserDebugRunner.java @@ -0,0 +1,49 @@ +package consulo.javascript.debugger.browser; + +import consulo.annotation.component.ExtensionImpl; +import consulo.execution.ExecutionResult; +import consulo.execution.configuration.RunProfile; +import consulo.execution.configuration.RunProfileState; +import consulo.execution.debug.DefaultDebugExecutor; +import consulo.execution.debug.XDebuggerManager; +import consulo.execution.runner.DefaultProgramRunner; +import consulo.execution.runner.ExecutionEnvironment; +import consulo.execution.ui.RunContentDescriptor; +import consulo.javascript.debugger.cdt.CDTProcessBase; +import consulo.process.ExecutionException; +import jakarta.annotation.Nonnull; + +import java.util.Objects; + +/** + * @author VISTALL + * @since 2020-06-15 + */ +@ExtensionImpl +public class JavaScriptBrowserDebugRunner extends DefaultProgramRunner { + @Nonnull + @Override + public String getRunnerId() { + return "browser-javascript-debug"; + } + + @Override + protected RunContentDescriptor doExecute(@Nonnull RunProfileState state, @Nonnull ExecutionEnvironment env) throws ExecutionException { + return XDebuggerManager.getInstance(env.getProject()).startSession(env, xDebugSession -> { + ExecutionResult result = Objects.requireNonNull(state.execute(env.getExecutor(), env.getRunner())); + + BrowserDebuggerProcess processHandler = (BrowserDebuggerProcess) result.getProcessHandler(); + + BrowserCDTDebugProcess process = new BrowserCDTDebugProcess(xDebugSession, result); + + processHandler.setDebugProcess(process); + + return process; + }).getRunContentDescriptor(); + } + + @Override + public boolean canRun(@Nonnull String executorId, @Nonnull RunProfile runProfile) { + return executorId.equals(DefaultDebugExecutor.EXECUTOR_ID) && runProfile instanceof JavaScriptBrowserConfiguration; + } +} diff --git a/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/ProxyWebSocketService.java b/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/ProxyWebSocketService.java new file mode 100644 index 00000000..90b0b17f --- /dev/null +++ b/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/ProxyWebSocketService.java @@ -0,0 +1,54 @@ +package consulo.javascript.debugger.browser; + +import com.github.kklisura.cdt.services.WebSocketService; +import com.github.kklisura.cdt.services.exceptions.WebSocketServiceException; +import consulo.builtinWebServer.webSocket.WebSocketConnection; +import consulo.javascript.debugger.browser.transport.DebuggerCommandRequest; +import consulo.javascript.debugger.browser.transport.ExtensionWebSocketAccepter; + +import java.net.URI; +import java.util.function.Consumer; + +/** + * @author VISTALL + * @since 2026-02-15 + */ +public class ProxyWebSocketService implements WebSocketService { + private final SessionHolder.BrowserSession myBrowserSession; + + public ProxyWebSocketService(SessionHolder.BrowserSession browserSession) { + myBrowserSession = browserSession; + } + + @Override + public void connect(URI uri) throws WebSocketServiceException { + throw new UnsupportedOperationException(); + } + + @Override + public void send(String message) throws WebSocketServiceException { + WebSocketConnection connection = myBrowserSession.getWebSocketConnection(); + + DebuggerCommandRequest request = new DebuggerCommandRequest(); + request.tabId = myBrowserSession.getTabId(); + request.command = ExtensionWebSocketAccepter.GSON.fromJson(message, Object.class); + + String json = ExtensionWebSocketAccepter.GSON.toJson(request); + + connection.send(json); + } + + @Override + public void addMessageHandler(Consumer consumer) throws WebSocketServiceException { + myBrowserSession.addHandler(consumer); + } + + @Override + public void close() { + } + + @Override + public boolean closed() { + return false; + } +} diff --git a/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/SessionHolder.java b/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/SessionHolder.java new file mode 100644 index 00000000..186e9f37 --- /dev/null +++ b/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/SessionHolder.java @@ -0,0 +1,102 @@ +package consulo.javascript.debugger.browser; + +import consulo.annotation.component.ComponentScope; +import consulo.annotation.component.ServiceAPI; +import consulo.annotation.component.ServiceImpl; +import consulo.builtinWebServer.webSocket.WebSocketConnection; +import consulo.util.collection.Lists; +import consulo.util.collection.SmartList; +import jakarta.inject.Singleton; + +import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; + +/** + * @author VISTALL + * @since 2026-02-15 + */ +@Singleton +@ServiceAPI(ComponentScope.APPLICATION) +@ServiceImpl +public class SessionHolder { + public class BrowserSession { + private final String myUrl; + + private int myTabId; + + private WebSocketConnection myWebSocketConnection; + + private BrowserCDTDebugProcess myDebugProcess; + + private List> myHandlers = new SmartList<>(); + + public BrowserSession(String url) { + myUrl = url; + } + + public int getTabId() { + return myTabId; + } + + public void addHandler(Consumer consumer) { + myHandlers.add(consumer); + } + + public void fireHandlers(String message) { + for (Consumer handler : myHandlers) { + handler.accept(message); + } + } + + public void close() { + myBrowserSessions.remove(this); + } + + public void setDebugProcess(BrowserCDTDebugProcess debugProcess) { + myDebugProcess = debugProcess; + } + + public WebSocketConnection getWebSocketConnection() { + return myWebSocketConnection; + } + + public BrowserCDTDebugProcess getDebugProcess() { + return myDebugProcess; + } + } + + private List myBrowserSessions = Lists.newLockFreeCopyOnWriteList(); + + public BrowserSession prepareSession(String url) { + BrowserSession session = new BrowserSession(url); + myBrowserSessions.add(session); + return session; + } + + public BrowserSession find(int tabId) { + for (BrowserSession browserSession : myBrowserSessions) { + if (browserSession.myTabId == tabId) { + return browserSession; + } + } + + return null; + } + + public BrowserSession initNew(String url, int tabId, WebSocketConnection connection) { + for (BrowserSession session : myBrowserSessions.reversed()) { + if (session.myTabId != 0) { + continue; + } + + if (Objects.equals(session.myUrl, url)) { + session.myTabId = tabId; + session. myWebSocketConnection = connection; + return session; + } + } + + return null; + } +} diff --git a/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/transport/AttachDebuggerResponse.java b/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/transport/AttachDebuggerResponse.java new file mode 100644 index 00000000..0bbc3072 --- /dev/null +++ b/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/transport/AttachDebuggerResponse.java @@ -0,0 +1,14 @@ +package consulo.javascript.debugger.browser.transport; + +/** + * @author VISTALL + * @since 2026-02-15 + */ +public class AttachDebuggerResponse { + public String message = "attach_debugger"; + public int tabId; + + public AttachDebuggerResponse(int tabId) { + this.tabId = tabId; + } +} diff --git a/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/transport/DebuggerCommandRequest.java b/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/transport/DebuggerCommandRequest.java new file mode 100644 index 00000000..ccee75bc --- /dev/null +++ b/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/transport/DebuggerCommandRequest.java @@ -0,0 +1,13 @@ +package consulo.javascript.debugger.browser.transport; + +/** + * @author VISTALL + * @since 2026-02-15 + */ +public class DebuggerCommandRequest { + public String message = "debugger_command"; + + public int tabId; + + public Object command; +} diff --git a/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/transport/DetachDebuggerRequest.java b/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/transport/DetachDebuggerRequest.java new file mode 100644 index 00000000..13deb032 --- /dev/null +++ b/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/transport/DetachDebuggerRequest.java @@ -0,0 +1,14 @@ +package consulo.javascript.debugger.browser.transport; + +/** + * @author VISTALL + * @since 2026-02-15 + */ +public class DetachDebuggerRequest { + public String message = "detach_debugger"; + public final int tabId; + + public DetachDebuggerRequest(int tabId) { + this.tabId = tabId; + } +} diff --git a/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/transport/ExtensionWebSocketAccepter.java b/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/transport/ExtensionWebSocketAccepter.java new file mode 100644 index 00000000..98a87253 --- /dev/null +++ b/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/transport/ExtensionWebSocketAccepter.java @@ -0,0 +1,127 @@ +package consulo.javascript.debugger.browser.transport; + +import com.google.gson.Gson; +import consulo.annotation.component.ExtensionImpl; +import consulo.builtinWebServer.webSocket.WebSocketAccepter; +import consulo.builtinWebServer.webSocket.WebSocketConnection; +import consulo.execution.debug.XDebugSession; +import consulo.execution.ui.console.ConsoleViewContentType; +import consulo.javascript.debugger.browser.BrowserCDTDebugProcess; +import consulo.javascript.debugger.browser.SessionHolder; +import consulo.javascript.debugger.cdt.CDTProcessBase; +import jakarta.annotation.Nonnull; +import jakarta.inject.Inject; + +import java.nio.charset.StandardCharsets; +import java.util.Map; + +/** + * @author VISTALL + * @since 2020-06-15 + */ +@ExtensionImpl +public class ExtensionWebSocketAccepter implements WebSocketAccepter { + public static final Gson GSON = new Gson(); + + private final SessionHolder mySessionHolder; + + @Inject + public ExtensionWebSocketAccepter(SessionHolder sessionHolder) { + mySessionHolder = sessionHolder; + } + + @Override + public void accept(@Nonnull WebSocketConnection webSocketConnection, @Nonnull byte[] bytes) { + accept(webSocketConnection, new String(bytes, StandardCharsets.UTF_8)); + } + + @Override + public void accept(@Nonnull WebSocketConnection conn, @Nonnull String text) { + try { + SessionHolder.BrowserSession session = null; + + Object jsonObject = GSON.fromJson(text, Object.class); + if (jsonObject instanceof Map map) { + Object message = map.get("message"); + + if (message instanceof String messageStr) { + switch (messageStr) { + case "init": { + String url = (String) map.get("url"); + int tabId = getInt(map.get("tabId")); + + session = mySessionHolder.initNew(url, tabId, conn); + + conn.send(GSON.toJson(new InitResponse(tabId, session != null))); + if (session != null) { + conn.send(GSON.toJson(new AttachDebuggerResponse(tabId))); + } + break; + } + case "debugger_detached": { + int tabId = getInt(map.get("tabId")); + + session = mySessionHolder.find(tabId); + + if (session != null) { + CDTProcessBase debugProcess = session.getDebugProcess(); + + XDebugSession xDebugSession = debugProcess.getSession(); + + xDebugSession.getConsoleView().print("Browser disconnected\n", ConsoleViewContentType.LOG_INFO_OUTPUT); + + debugProcess.getProcessHandler().destroyProcess(); + } + break; + } + case "debugger_command_response": { + int tabId = getInt(map.get("tabId")); + + session = mySessionHolder.find(tabId); + + if (session != null) { + Object response = map.get("response"); + + String responseJson = GSON.toJson(response); + + session.fireHandlers(responseJson); + } + break; + } + case "debugger_attached": { + int tabId = getInt(map.get("tabId")); + + session = mySessionHolder.find(tabId); + + if (session != null) { + BrowserCDTDebugProcess debugProcess = session.getDebugProcess(); + + XDebugSession xDebugSession = debugProcess.getSession(); + + debugProcess.init(session); + + xDebugSession.getConsoleView().print("Browser connected\n", ConsoleViewContentType.LOG_INFO_OUTPUT); + } + + break; + } + } + } + } + } + catch (Exception ignored) { + } + } + + private static int getInt(Object value) { + if (value instanceof Number number) { + return number.intValue(); + } + + if (value instanceof String str) { + return Integer.parseInt(str); + } + + throw new UnsupportedOperationException(value + " is not number"); + } +} diff --git a/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/transport/InitResponse.java b/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/transport/InitResponse.java new file mode 100644 index 00000000..49f2b5ab --- /dev/null +++ b/debugger/browser-debugger-impl/src/main/java/consulo/javascript/debugger/browser/transport/InitResponse.java @@ -0,0 +1,17 @@ +package consulo.javascript.debugger.browser.transport; + +/** + * @author VISTALL + * @since 2026-02-15 + */ +public class InitResponse { + public String message = "init"; + public int tabId; + public String status = "accepted"; + public String version = "7.4"; + + public InitResponse(int tabId, boolean accepted) { + this.tabId = tabId; + this.status = accepted ? "accepted" : ""; + } +} diff --git a/debugger/browser-debugger-impl/src/main/java/module-info.java b/debugger/browser-debugger-impl/src/main/java/module-info.java new file mode 100644 index 00000000..2aed0f0e --- /dev/null +++ b/debugger/browser-debugger-impl/src/main/java/module-info.java @@ -0,0 +1,15 @@ +/** + * @author VISTALL + * @since 2026-02-15 + */ +module consulo.javascript.browser.debugger.impl { + requires consulo.javascript.debugger.impl; + + requires com.google.gson; + + requires cdt.java.client; + + requires consulo.javascript.cdt.debugger.impl; + + opens consulo.javascript.debugger.browser to consulo.util.xml.serializer; +} \ No newline at end of file diff --git a/debugger/cdt-debugger-impl/pom.xml b/debugger/cdt-debugger-impl/pom.xml new file mode 100644 index 00000000..56c8ba66 --- /dev/null +++ b/debugger/cdt-debugger-impl/pom.xml @@ -0,0 +1,81 @@ + + + + 4.0.0 + + consulo + arch.ide-api-provided + 3-SNAPSHOT + + + + consulo.plugin + consulo.javascript-cdt.debugger.impl + 3-SNAPSHOT + jar + + + + consulo + https://maven.consulo.dev/repository/snapshots/ + + true + interval:60 + + + + + + + ${project.groupId} + consulo.javascript-base.impl + ${project.version} + + + + ${project.groupId} + consulo.javascript-debugger.impl + ${project.version} + + + + ${project.groupId} + com.intellij.xml + ${project.version} + provided + + + + consulo.internal.com.github.kklisura.cdt + cdt-java-client + 4.0.2 + + + org.javassist + javassist + + + + + + com.google.code.gson + gson + provided + + + \ No newline at end of file diff --git a/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTBreakpointInfo.java b/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTBreakpointInfo.java new file mode 100644 index 00000000..99759ad1 --- /dev/null +++ b/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTBreakpointInfo.java @@ -0,0 +1,36 @@ +package consulo.javascript.debugger.cdt; + +import com.github.kklisura.cdt.protocol.types.debugger.Location; +import consulo.execution.debug.breakpoint.XBreakpoint; + +import java.util.List; + +/** + * @author VISTALL + * @since 2026-02-15 + */ +public class CDTBreakpointInfo { + private List myLocations; + private XBreakpoint myBreakpoint; + + public CDTBreakpointInfo(List locations, XBreakpoint breakpoint) { + myLocations = locations; + myBreakpoint = breakpoint; + } + + public List getLocations() { + return myLocations; + } + + public void setLocations(List locations) { + myLocations = locations; + } + + public XBreakpoint getBreakpoint() { + return myBreakpoint; + } + + public void setBreakpoint(XBreakpoint breakpoint) { + myBreakpoint = breakpoint; + } +} diff --git a/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTExecutionStack.java b/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTExecutionStack.java new file mode 100644 index 00000000..1be641d2 --- /dev/null +++ b/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTExecutionStack.java @@ -0,0 +1,39 @@ +package consulo.javascript.debugger.cdt; + +import com.github.kklisura.cdt.protocol.types.debugger.CallFrame; +import consulo.execution.debug.frame.XExecutionStack; +import consulo.execution.debug.frame.XStackFrame; +import jakarta.annotation.Nullable; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author VISTALL + * @since 2026-02-15 + */ +public class CDTExecutionStack extends XExecutionStack { + private final List myFrames; + + public CDTExecutionStack(String displayName, + List callFrames, + CDTProcessBase process) { + super(displayName); + + myFrames = new ArrayList<>(callFrames.size()); + for (CallFrame callFrame : callFrames) { + myFrames.add(new CDTStackFrame(callFrame, process)); + } + } + + @Nullable + @Override + public XStackFrame getTopFrame() { + return myFrames.isEmpty() ? null : myFrames.getFirst(); + } + + @Override + public void computeStackFrames(XStackFrameContainer container) { + container.addStackFrames(myFrames, true); + } +} diff --git a/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTProcessBase.java b/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTProcessBase.java new file mode 100644 index 00000000..2c3dbf61 --- /dev/null +++ b/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTProcessBase.java @@ -0,0 +1,298 @@ +package consulo.javascript.debugger.cdt; + +import com.github.kklisura.cdt.protocol.ChromeDevTools; +import com.github.kklisura.cdt.protocol.commands.Debugger; +import com.github.kklisura.cdt.protocol.events.debugger.Paused; +import com.github.kklisura.cdt.protocol.types.debugger.Location; +import com.github.kklisura.cdt.protocol.types.debugger.SetBreakpointByUrl; +import consulo.application.Application; +import consulo.application.ReadAction; +import consulo.application.concurrent.ApplicationConcurrency; +import consulo.execution.ExecutionResult; +import consulo.execution.debug.*; +import consulo.execution.debug.breakpoint.*; +import consulo.execution.debug.evaluation.XDebuggerEditorsProvider; +import consulo.execution.debug.frame.XSuspendContext; +import consulo.execution.debug.icon.ExecutionDebugIconGroup; +import consulo.execution.debug.localize.XDebuggerLocalize; +import consulo.execution.debug.ui.XDebugTabLayouter; +import consulo.execution.ui.ExecutionConsole; +import consulo.execution.ui.layout.RunnerLayoutUi; +import consulo.javascript.debugger.JavaScriptEditorsProvider; +import consulo.javascript.debugger.JavaScriptLineBreakpointType; +import consulo.javascript.debugger.JavaScriptListPanel; +import consulo.javascript.icon.JavaScriptIconGroup; +import consulo.localize.LocalizeValue; +import consulo.process.ExecutionException; +import consulo.process.ProcessHandler; +import consulo.ui.ex.content.Content; +import consulo.util.io.Url; +import consulo.util.io.Urls; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; + +import java.net.SocketException; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.function.Consumer; + +/** + * @author VISTALL + * @since 2026-02-15 + */ +public abstract class CDTProcessBase extends XDebugProcess { + private final ExecutionResult myResult; + + private CDTScriptHolder myScripts = new CDTScriptHolder(); + + private JavaScriptListPanel myScriptListPanel; + + private final XBreakpointManager myXBreakpointManager; + + private ChromeDevTools myChromeDevTools; + + private ExecutorService myExecutor; + + private Map myBreakpoints = new HashMap<>(); + + public CDTProcessBase(@Nonnull XDebugSession session, ExecutionResult result) throws ExecutionException { + super(session); + myScriptListPanel = new JavaScriptListPanel<>(); + + myExecutor = Application.get().getInstance(ApplicationConcurrency.class).createBoundedScheduledExecutorService("CDTProcess", 1); + + myResult = result; + myXBreakpointManager = XDebuggerManager.getInstance(getSession().getProject()).getBreakpointManager(); + getSession().setPauseActionSupported(true); + } + + public void initTools(ChromeDevTools devTools) { + myChromeDevTools = devTools; + + Debugger debugger = myChromeDevTools.getDebugger(); + + debugger.onScriptParsed(event -> { + CDTScript cdtScript = new CDTScript(getSession().getProject(), event); + + myScripts.add(cdtScript); + + getSession().getProject().getUIAccess().execute(() -> myScriptListPanel.add(cdtScript)); + }); + + debugger.onPaused(this::onPause); + + devTools.getRuntime().onExecutionContextDestroyed(executionContextDestroyed -> { + getProcessHandler().destroyProcess(); + }); + + initOthers(); + } + + protected void initOthers() { + invoke(devTools -> { + ReadAction.run(() -> getSession().initBreakpoints()); + + devTools.getRuntime().runIfWaitingForDebugger(); + }); + } + + public CDTScriptHolder getScripts() { + return myScripts; + } + + public void invoke(Consumer runnable) { + if (myChromeDevTools == null) { + return; + } + + myExecutor.execute(() -> { + try { + runnable.accept(myChromeDevTools); + } + catch (Exception e) { + e.printStackTrace(); + } + }); + } + + protected void onPause(Paused event) { + XBreakpoint breakpoint = null; + List hitBreakpoints = event.getHitBreakpoints(); + if (hitBreakpoints != null) { + for (String hitBreakpoint : hitBreakpoints) { + CDTBreakpointInfo info = myBreakpoints.get(hitBreakpoint); + if (info != null) { + breakpoint = info.getBreakpoint(); + break; + } + } + } + + XDebugSession debugSession = getSession(); + if (breakpoint != null) { + debugSession.breakpointReached(breakpoint, null, new CDTSuspendContext(event, this)); + } + else { + debugSession.positionReached(new CDTSuspendContext(event, this)); + } + } + + @Nullable + @Override + protected ProcessHandler doGetProcessHandler() { + return myResult.getProcessHandler(); + } + + @Override + public boolean checkCanPerformCommands() { + return myChromeDevTools != null; + } + + @Nonnull + @Override + public XDebuggerEditorsProvider getEditorsProvider() { + return JavaScriptEditorsProvider.INSTANCE; + } + + @Nonnull + @Override + public ExecutionConsole createConsole() { + return myResult.getExecutionConsole(); + } + + @Override + public boolean checkCanInitBreakpoints() { + return false; + } + + @Nonnull + @Override + public XBreakpointHandler[] getBreakpointHandlers() { + return new XBreakpointHandler[]{ + new XBreakpointHandler<>(JavaScriptLineBreakpointType.class) { + @Override + public void registerBreakpoint(@Nonnull final XLineBreakpoint lineBreakpoint) { + int line = lineBreakpoint.getLine(); + XExpression conditionExpression = lineBreakpoint.getConditionExpression(); + String expression = conditionExpression == null ? null : conditionExpression.getExpression(); + + invoke((devTools) -> { + Url url = Urls.newFromIdea(lineBreakpoint.getFileUrl()); + + String externalForm = url.toExternalForm(); + + SetBreakpointByUrl setBreakpointByUrl = devTools.getDebugger().setBreakpointByUrl(line, externalForm, null, null, null, expression); + + List locations = setBreakpointByUrl.getLocations(); + + myBreakpoints.put(setBreakpointByUrl.getBreakpointId(), new CDTBreakpointInfo(locations, lineBreakpoint)); + + if (!locations.isEmpty()) { + myXBreakpointManager.updateBreakpointPresentation(lineBreakpoint, ExecutionDebugIconGroup.breakpointBreakpointvalid(), null); + } + + // TODO error handler + }); + } + + @Override + public void unregisterBreakpoint(@Nonnull XLineBreakpoint breakpoint, boolean b) { + String presentableFilePath = breakpoint.getPresentableFilePath(); + // myVm.setBreakpoint(new Breakpoint.Target.ScriptName(presentableFilePath), breakpoint.getLine(), Breakpoint.EMPTY_VALUE, false, null, null, null); + } + } + }; + } + + @Override + public void startPausing() { + ChromeDevTools chromeDevTools = myChromeDevTools; + + if (chromeDevTools != null) { + invoke((devTools) -> devTools.getDebugger().pause()); + } + } + + @Override + public void startStepOver(@Nullable XSuspendContext context) { + invoke((chromeDevTools) -> chromeDevTools.getDebugger().stepOver()); + } + + @Override + public void startStepInto(@Nullable XSuspendContext context) { + invoke((chromeDevTools) -> chromeDevTools.getDebugger().stepInto()); + } + + @Override + public void startStepOut(@Nullable XSuspendContext context) { + invoke((chromeDevTools) -> chromeDevTools.getDebugger().stepOut()); + } + + @Override + public void stop() { + if (myChromeDevTools instanceof AutoCloseable closeable) { + try { + closeable.close(); + } + catch (Exception ignored) { + } + } + + myExecutor.shutdown(); + + myBreakpoints.clear(); + + Application.get().runReadAction(new Runnable() { + @Override + public void run() { + Collection> breakpoints = myXBreakpointManager.getBreakpoints(JavaScriptLineBreakpointType + .class); + for (XLineBreakpoint breakpoint : breakpoints) { + myXBreakpointManager.updateBreakpointPresentation(breakpoint, null, null); + } + } + }); + } + + @Override + public void resume(@Nullable XSuspendContext context) { + invoke((chromeDevTools) -> chromeDevTools.getDebugger().resume()); + } + + @Override + public void runToPosition(@Nonnull XSourcePosition position, @Nullable XSuspendContext context) { + } + + @Nonnull + @Override + public XDebugTabLayouter createTabLayouter() { + return new XDebugTabLayouter() { + @Override + public void registerAdditionalContent(@Nonnull RunnerLayoutUi ui) { + Content content = ui.createContent("ScriptListView", myScriptListPanel, "Scripts", JavaScriptIconGroup.javascript(), null); + content.setCloseable(false); + + ui.addContent(content); + } + }; + } + + @Nonnull + @Override + public LocalizeValue getCurrentStateMessage() { + if (myChromeDevTools == null) { + return XDebuggerLocalize.debuggerStateMessageDisconnected(); + } + else { + return LocalizeValue.localizeTODO("Attached"); + } + } + +// @Nullable +// public XLineBreakpoint getXBreakpointByVmBreakpoint(Breakpoint breakpoint) { +// return myBreakpoints.get(breakpoint); +// } +} diff --git a/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTRemoteObjectValue.java b/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTRemoteObjectValue.java new file mode 100644 index 00000000..e3256c6a --- /dev/null +++ b/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTRemoteObjectValue.java @@ -0,0 +1,101 @@ +package consulo.javascript.debugger.cdt; + +import com.github.kklisura.cdt.protocol.types.runtime.Properties; +import com.github.kklisura.cdt.protocol.types.runtime.PropertyDescriptor; +import com.github.kklisura.cdt.protocol.types.runtime.RemoteObject; +import com.github.kklisura.cdt.protocol.types.runtime.RemoteObjectType; +import consulo.execution.debug.frame.*; +import consulo.execution.debug.frame.presentation.XValuePresentation; +import consulo.execution.debug.icon.ExecutionDebugIconGroup; +import consulo.ui.image.Image; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; + +import java.util.List; + +/** + * @author VISTALL + * @since 2026-02-15 + */ +public class CDTRemoteObjectValue extends XNamedValue { + @Nullable + private final RemoteObject myRemoteObject; + + private final CDTProcessBase myProcess; + + public CDTRemoteObjectValue(@Nonnull String name, @Nullable RemoteObject remoteObject, CDTProcessBase process) { + super(name); + myRemoteObject = remoteObject; + myProcess = process; + } + + @Override + public void computeChildren(@Nonnull XCompositeNode node) { + fill(myRemoteObject, node, myProcess); + } + + public static void fill(RemoteObject remoteObject, XCompositeNode node, CDTProcessBase process) { + if (remoteObject == null) { + return; + } + + if (remoteObject.getType() != RemoteObjectType.OBJECT) { + node.addChildren(XValueChildrenList.EMPTY, true); + return; + } + + process.invoke(devTools -> { + String objectId = remoteObject.getObjectId(); + + Properties properties = devTools.getRuntime().getProperties(objectId); + + List result = properties.getResult(); + + XValueChildrenList list = new XValueChildrenList(); + + for (PropertyDescriptor propertyDescriptor : result) { + RemoteObject value = propertyDescriptor.getValue(); + + list.add(new CDTRemoteObjectValue(propertyDescriptor.getName(), value, process)); + } + + node.addChildren(list, true); + }); + } + + @Nonnull + protected Image getObjectIcon() { + return ExecutionDebugIconGroup.nodeValue(); + } + + @Override + public void computePresentation(@Nonnull XValueNode node, @Nonnull XValuePlace place) { + if (myRemoteObject == null) { + node.setPresentation(getObjectIcon(), null, "null", false); + return; + } + + if (myRemoteObject.getType() == RemoteObjectType.OBJECT) { + node.setPresentation(getObjectIcon(), "", "", true); + } + else { + node.setPresentation(ExecutionDebugIconGroup.nodePrimitive(), new XValuePresentation() { + @Override + public void renderValue(@Nonnull XValueTextRenderer renderer) { + switch (myRemoteObject.getType()) { + case STRING: + renderer.renderStringValue(String.valueOf(myRemoteObject.getValue())); + break; + case NUMBER: + case BIGINT: + renderer.renderNumericValue(String.valueOf(myRemoteObject.getValue())); + break; + case BOOLEAN: + renderer.renderKeywordValue(String.valueOf(myRemoteObject.getValue())); + break; + } + } + }, myRemoteObject.getType() == RemoteObjectType.OBJECT); + } + } +} diff --git a/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTScopeValue.java b/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTScopeValue.java new file mode 100644 index 00000000..788f0658 --- /dev/null +++ b/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTScopeValue.java @@ -0,0 +1,42 @@ +package consulo.javascript.debugger.cdt; + +import com.github.kklisura.cdt.protocol.types.debugger.Scope; +import com.github.kklisura.cdt.protocol.types.debugger.ScopeType; +import com.github.kklisura.cdt.protocol.types.runtime.RemoteObject; +import consulo.execution.debug.frame.XCompositeNode; +import consulo.execution.debug.frame.XValueGroup; +import consulo.util.lang.StringUtil; +import jakarta.annotation.Nonnull; + +import java.util.Locale; + +/** + * @author VISTALL + * @since 2026-02-15 + */ +public class CDTScopeValue extends XValueGroup { + @Nonnull + private final Scope myScope; + @Nonnull + private final RemoteObject myRemoteObject; + private final CDTProcessBase myProcess; + + public CDTScopeValue(@Nonnull Scope scope, + @Nonnull RemoteObject remoteObject, + CDTProcessBase process) { + super(StringUtil.capitalize(scope.getType().name().toLowerCase(Locale.ROOT))); + myScope = scope; + myRemoteObject = remoteObject; + myProcess = process; + } + + @Override + public void computeChildren(@Nonnull XCompositeNode node) { + CDTRemoteObjectValue.fill(myRemoteObject, node, myProcess); + } + + @Override + public boolean isAutoExpand() { + return myScope.getType() == ScopeType.LOCAL; + } +} diff --git a/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTScript.java b/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTScript.java new file mode 100644 index 00000000..c4c0510e --- /dev/null +++ b/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTScript.java @@ -0,0 +1,77 @@ +package consulo.javascript.debugger.cdt; + +import com.github.kklisura.cdt.protocol.events.debugger.ScriptParsed; +import com.github.kklisura.cdt.protocol.types.debugger.ScriptLanguage; +import consulo.javascript.debugger.JavaScriptFileInfo; +import consulo.javascript.icon.JavaScriptIconGroup; +import consulo.language.editor.FileColorManager; +import consulo.navigation.OpenFileDescriptorFactory; +import consulo.project.Project; +import consulo.ui.color.ColorValue; +import consulo.ui.image.Image; +import consulo.virtualFileSystem.VirtualFile; +import consulo.virtualFileSystem.VirtualFileManager; +import consulo.virtualFileSystem.util.VirtualFileUtil; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; + +/** + * @author VISTALL + * @since 2026-02-15 + */ +public class CDTScript implements JavaScriptFileInfo { + private final String myId; + private final String myUrl; + private final Project myProject; + private final ScriptLanguage myScriptLanguage; + + public CDTScript(Project project, ScriptParsed scriptParsed) { + myProject = project; + myId = scriptParsed.getScriptId(); + myUrl = scriptParsed.getUrl(); + myScriptLanguage = scriptParsed.getScriptLanguage(); + } + + public String getId() { + return myId; + } + + public VirtualFile toVirtualFile() { + return VirtualFileManager.getInstance().findFileByUrl(myUrl); + } + + @Nonnull + @Override + public String getPath() { + return/* myId + ":" +*/ VirtualFileUtil.urlToPath(myUrl); + } + + @Nonnull + @Override + public Image getIcon() { + return switch (myScriptLanguage) { + case JAVA_SCRIPT -> JavaScriptIconGroup.javascript(); + case WEB_ASSEMBLY -> + // TODO web assembly icon + JavaScriptIconGroup.javascript(); + }; + } + + @Nullable + @Override + public ColorValue getFileStatusColor() { + VirtualFile virtualFile = toVirtualFile(); + if (virtualFile != null) { + return FileColorManager.getInstance(myProject).getFileColorValue(virtualFile); + } + return null; + } + + @Override + public void navigate(boolean focus) { + VirtualFile file = toVirtualFile(); + if (file != null) { + OpenFileDescriptorFactory.getInstance(myProject).newBuilder(file).build().navigate(focus); + } + } +} diff --git a/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTScriptHolder.java b/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTScriptHolder.java new file mode 100644 index 00000000..2dbe5154 --- /dev/null +++ b/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTScriptHolder.java @@ -0,0 +1,28 @@ +package consulo.javascript.debugger.cdt; + +import consulo.util.collection.Lists; + +import java.util.List; +import java.util.Objects; + +/** + * @author VISTALL + * @since 2026-02-15 + */ +public class CDTScriptHolder { + private final List myScripts = Lists.newLockFreeCopyOnWriteList(); + + public void add(CDTScript script) { + myScripts.add(script); + } + + public CDTScript find(String scriptId) { + for (CDTScript script : myScripts) { + if (Objects.equals(scriptId, script.getId())) { + return script; + } + } + + return null; + } +} diff --git a/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTStackFrame.java b/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTStackFrame.java new file mode 100644 index 00000000..fef896b3 --- /dev/null +++ b/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTStackFrame.java @@ -0,0 +1,109 @@ +package consulo.javascript.debugger.cdt; + +import com.github.kklisura.cdt.protocol.types.debugger.CallFrame; +import com.github.kklisura.cdt.protocol.types.debugger.Location; +import com.github.kklisura.cdt.protocol.types.debugger.Scope; +import com.github.kklisura.cdt.protocol.types.runtime.RemoteObject; +import com.github.kklisura.cdt.protocol.types.runtime.RemoteObjectType; +import consulo.application.Application; +import consulo.execution.debug.XSourcePosition; +import consulo.execution.debug.XSourcePositionFactory; +import consulo.execution.debug.frame.XCompositeNode; +import consulo.execution.debug.frame.XStackFrame; +import consulo.execution.debug.frame.XValueChildrenList; +import consulo.ui.ex.ColoredTextContainer; +import consulo.ui.ex.SimpleTextAttributes; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; + +import java.util.List; + +/** + * @author VISTALL + * @since 2026-02-15 + */ +public class CDTStackFrame extends XStackFrame { + private final CallFrame myCallFrame; + private final CDTProcessBase myProcess; + + private XSourcePosition mySourcePosition; + + private final Location myLocation; + private final CDTScript myScript; + private final String myScriptId; + + public CDTStackFrame(CallFrame callFrame, CDTProcessBase process) { + myCallFrame = callFrame; + myProcess = process; + + myLocation = callFrame.getLocation(); + + if (myLocation != null) { + myScriptId = myLocation.getScriptId(); + myScript = process.getScripts().find(myScriptId); + + if (myScript != null) { + mySourcePosition = Application.get().getInstance(XSourcePositionFactory.class).createPosition( + myScript.toVirtualFile(), + myLocation.getLineNumber(), + myLocation.getColumnNumber() + ); + } + } + else { + myScript = null; + myScriptId = null; + } + } + + @Nullable + @Override + public XSourcePosition getSourcePosition() { + return mySourcePosition; + } + + @Nullable + @Override + public Object getEqualityObject() { + return myCallFrame.getCallFrameId(); + } + + @Override + public void customizePresentation(ColoredTextContainer component) { + XSourcePosition position = getSourcePosition(); + if (position != null) { + component.append(position.getFile().getName(), SimpleTextAttributes.REGULAR_ATTRIBUTES); + component.append(":" + (position.getLine() + 1), SimpleTextAttributes.REGULAR_ATTRIBUTES); + } + else if (myScript != null) { + component.append(myScript.getPath(), SimpleTextAttributes.REGULAR_ATTRIBUTES); + component.append(":" + (myLocation.getLineNumber() + 1), SimpleTextAttributes.REGULAR_ATTRIBUTES); + } + else { + component.append(myScriptId, SimpleTextAttributes.REGULAR_ATTRIBUTES); + } + } + + @Override + public void computeChildren(@Nonnull XCompositeNode node) { + myProcess.invoke(devTools -> { + List scopeChain = myCallFrame.getScopeChain(); + + XValueChildrenList list = new XValueChildrenList(); + for (Scope scope : scopeChain) { + RemoteObject object = scope.getObject(); + if (object == null) { + continue; + } + + if (object.getType() != RemoteObjectType.OBJECT) { + continue; + } + + list.addTopGroup(new CDTScopeValue(scope, object, myProcess)); + } + + node.addChildren(list, true); + }); + } +} diff --git a/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTSuspendContext.java b/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTSuspendContext.java new file mode 100644 index 00000000..e5068a90 --- /dev/null +++ b/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/CDTSuspendContext.java @@ -0,0 +1,29 @@ +package consulo.javascript.debugger.cdt; + +import com.github.kklisura.cdt.protocol.events.debugger.Paused; +import consulo.execution.debug.frame.XExecutionStack; +import consulo.execution.debug.frame.XSuspendContext; +import jakarta.annotation.Nullable; + +/** + * @author VISTALL + * @since 2026-02-15 + */ +public class CDTSuspendContext extends XSuspendContext { + private CDTExecutionStack myStack; + + public CDTSuspendContext(Paused event, CDTProcessBase process) { + myStack = new CDTExecutionStack("", event.getCallFrames(), process); + } + + @Nullable + @Override + public XExecutionStack getActiveExecutionStack() { + return myStack; + } + + @Override + public XExecutionStack[] getExecutionStacks() { + return new XExecutionStack[] {myStack}; + } +} diff --git a/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/ChromeDevToolsFactory.java b/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/ChromeDevToolsFactory.java new file mode 100644 index 00000000..3a21046a --- /dev/null +++ b/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/ChromeDevToolsFactory.java @@ -0,0 +1,60 @@ +package consulo.javascript.debugger.cdt; + +import com.github.kklisura.cdt.services.WebSocketService; +import com.github.kklisura.cdt.services.config.ChromeDevToolsServiceConfiguration; +import com.github.kklisura.cdt.services.executors.EventExecutorService; +import com.github.kklisura.cdt.services.impl.ChromeDevToolsServiceImpl; +import com.github.kklisura.cdt.services.invocation.CommandInvocationHandler; +import com.github.kklisura.cdt.services.utils.ProxyUtils; +import consulo.proxy.advanced.AdvancedProxyBuilder; + +import java.lang.reflect.Method; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author VISTALL + * @since 2026-02-15 + */ +public class ChromeDevToolsFactory { + public static ChromeDevToolsServiceImpl create(WebSocketService webSocketService) { + ChromeDevToolsServiceConfiguration conf = new ChromeDevToolsServiceConfiguration(); + conf.setEventExecutorService(new EventExecutorService() { + @Override + public void execute(Runnable runnable) { + runnable.run(); + } + + @Override + public void shutdown() { + + } + }); + + if (Boolean.FALSE) { + webSocketService = new LoggingWebSocketService(webSocketService); + } + + // Create invocation handler + CommandInvocationHandler commandInvocationHandler = new CommandInvocationHandler(); + + // Setup command cache for this session + Map commandsCache = new ConcurrentHashMap<>(); + + ChromeDevToolsServiceImpl service = AdvancedProxyBuilder.create(ChromeDevToolsServiceImpl.class) + .withSuperConstructorArguments(webSocketService, conf) + .withInvocationHandler((proxy, method, args) -> { + return commandsCache.computeIfAbsent( + method, + key -> { + Class returnType = method.getReturnType(); + return ProxyUtils.createProxy(returnType, commandInvocationHandler); + }); + }) + .build(); + + commandInvocationHandler.setChromeDevToolsService(service); + + return service; + } +} diff --git a/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/LoggingWebSocketService.java b/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/LoggingWebSocketService.java new file mode 100644 index 00000000..c6786585 --- /dev/null +++ b/debugger/cdt-debugger-impl/src/main/java/consulo/javascript/debugger/cdt/LoggingWebSocketService.java @@ -0,0 +1,48 @@ +package consulo.javascript.debugger.cdt; + +import com.github.kklisura.cdt.services.WebSocketService; +import com.github.kklisura.cdt.services.exceptions.WebSocketServiceException; + +import java.net.URI; +import java.util.function.Consumer; + +/** + * @author VISTALL + * @since 2026-02-16 + */ +public class LoggingWebSocketService implements WebSocketService { + private final WebSocketService myDelegate; + + public LoggingWebSocketService(WebSocketService delegate) { + myDelegate = delegate; + } + + @Override + public void connect(URI uri) throws WebSocketServiceException { + myDelegate.connect(uri); + } + + @Override + public void send(String s) throws WebSocketServiceException { + System.out.println("send " + s); + myDelegate.send(s); + } + + @Override + public void addMessageHandler(Consumer consumer) throws WebSocketServiceException { + myDelegate.addMessageHandler(s -> { + System.out.println("rec: " + s); + consumer.accept(s); + }); + } + + @Override + public void close() { + myDelegate.close(); + } + + @Override + public boolean closed() { + return myDelegate.closed(); + } +} diff --git a/debugger/cdt-debugger-impl/src/main/java/module-info.java b/debugger/cdt-debugger-impl/src/main/java/module-info.java new file mode 100644 index 00000000..bcb862d6 --- /dev/null +++ b/debugger/cdt-debugger-impl/src/main/java/module-info.java @@ -0,0 +1,13 @@ +/** + * @author VISTALL + * @since 2026-02-15 + */ +module consulo.javascript.cdt.debugger.impl { + requires consulo.javascript.debugger.impl; + + requires com.google.gson; + + requires cdt.java.client; + + exports consulo.javascript.debugger.cdt; +} \ No newline at end of file diff --git a/debugger/debugger-impl/pom.xml b/debugger/debugger-impl/pom.xml index d61b7628..bfe4827d 100644 --- a/debugger/debugger-impl/pom.xml +++ b/debugger/debugger-impl/pom.xml @@ -32,7 +32,7 @@ consulo - https://maven.consulo.io/repository/snapshots/ + https://maven.consulo.dev/repository/snapshots/ true interval:60 diff --git a/debugger/debugger-impl/src/main/java/consulo/javascript/debugger/JSDebuggerSupportUtils.java b/debugger/debugger-impl/src/main/java/consulo/javascript/debugger/JSDebuggerSupportUtils.java index c4a87c6f..9b822207 100644 --- a/debugger/debugger-impl/src/main/java/consulo/javascript/debugger/JSDebuggerSupportUtils.java +++ b/debugger/debugger-impl/src/main/java/consulo/javascript/debugger/JSDebuggerSupportUtils.java @@ -30,9 +30,9 @@ import consulo.util.lang.ref.Ref; import consulo.virtualFileSystem.VirtualFile; import consulo.xml.lang.xml.XMLLanguage; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import java.util.List; /** @@ -56,7 +56,7 @@ public static TextRange getExpressionAtOffset(@Nonnull Project project, @Nonnull if(ref == null) { - final PsiElement at = file.findElementAt(offset); + PsiElement at = file.findElementAt(offset); TextRange rangeForNamedElement = getRangeForNamedElement(at, 0); if(rangeForNamedElement != null) @@ -64,7 +64,7 @@ public static TextRange getExpressionAtOffset(@Nonnull Project project, @Nonnull return rangeForNamedElement; } - final PsiLanguageInjectionHost psiLanguageInjectionHost = PsiTreeUtil.getParentOfType(at, PsiLanguageInjectionHost.class); + PsiLanguageInjectionHost psiLanguageInjectionHost = PsiTreeUtil.getParentOfType(at, PsiLanguageInjectionHost.class); if(psiLanguageInjectionHost != null) { @@ -75,11 +75,11 @@ public static TextRange getExpressionAtOffset(@Nonnull Project project, @Nonnull InjectedLanguageManager.getInstance(project).enumerate(psiLanguageInjectionHost, new PsiLanguageInjectionHost.InjectedPsiVisitor() { @Override - public void visit(@Nonnull final PsiFile injectedPsi, @Nonnull final List places) + public void visit(@Nonnull PsiFile injectedPsi, @Nonnull List places) { - final PsiLanguageInjectionHost.Shred shred = places.get(0); - final int injectedStart = shred.getRangeInsideHost().getStartOffset() + shred.getHost().getTextOffset(); - final int offsetInInjected = offset - injectedStart; + PsiLanguageInjectionHost.Shred shred = places.get(0); + int injectedStart = shred.getRangeInsideHost().getStartOffset() + shred.getHost().getTextOffset(); + int offsetInInjected = offset - injectedStart; result.set(injectedPsi.findReferenceAt(offsetInInjected)); eltInInjected.set(injectedPsi.findElementAt(offsetInInjected)); @@ -109,7 +109,7 @@ public void visit(@Nonnull final PsiFile injectedPsi, @Nonnull final List places) + public void visit(@Nonnull PsiFile injectedPsi, @Nonnull List places) { - final PsiLanguageInjectionHost.Shred shred = places.get(0); - final int injectedStart = shred.getRangeInsideHost().getStartOffset() + shred.getHost().getTextOffset(); - final int offsetInInjected = finalOffset - injectedStart; + PsiLanguageInjectionHost.Shred shred = places.get(0); + int injectedStart = shred.getRangeInsideHost().getStartOffset() + shred.getHost().getTextOffset(); + int offsetInInjected = finalOffset - injectedStart; resultInInjected.set(injectedPsi.findElementAt(offsetInInjected)); } diff --git a/debugger/debugger-impl/src/main/java/consulo/javascript/debugger/JavaScriptEditorsProvider.java b/debugger/debugger-impl/src/main/java/consulo/javascript/debugger/JavaScriptEditorsProvider.java index 30deec9e..174b2797 100644 --- a/debugger/debugger-impl/src/main/java/consulo/javascript/debugger/JavaScriptEditorsProvider.java +++ b/debugger/debugger-impl/src/main/java/consulo/javascript/debugger/JavaScriptEditorsProvider.java @@ -16,8 +16,7 @@ package consulo.javascript.debugger; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; import consulo.javascript.language.JavaScriptFileType; import consulo.javascript.impl.language.psi.JSElementFactory; import consulo.execution.debug.evaluation.XDebuggerEditorsProviderBase; @@ -25,6 +24,7 @@ import consulo.project.Project; import consulo.language.psi.PsiFile; import consulo.virtualFileSystem.fileType.FileType; +import jakarta.annotation.Nullable; /** * @author VISTALL diff --git a/debugger/debugger-impl/src/main/java/consulo/javascript/debugger/JavaScriptFileInfo.java b/debugger/debugger-impl/src/main/java/consulo/javascript/debugger/JavaScriptFileInfo.java new file mode 100644 index 00000000..beb65238 --- /dev/null +++ b/debugger/debugger-impl/src/main/java/consulo/javascript/debugger/JavaScriptFileInfo.java @@ -0,0 +1,22 @@ +package consulo.javascript.debugger; + +import consulo.navigation.Navigatable; +import consulo.ui.color.ColorValue; +import consulo.ui.image.Image; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; + +/** + * @author VISTALL + * @since 2026-02-16 + */ +public interface JavaScriptFileInfo extends Navigatable { + @Nonnull + String getPath(); + + @Nonnull + Image getIcon(); + + @Nullable + ColorValue getFileStatusColor(); +} diff --git a/debugger/debugger-impl/src/main/java/consulo/javascript/debugger/JavaScriptLineBreakpointType.java b/debugger/debugger-impl/src/main/java/consulo/javascript/debugger/JavaScriptLineBreakpointType.java index 315e4ec2..1754d81c 100644 --- a/debugger/debugger-impl/src/main/java/consulo/javascript/debugger/JavaScriptLineBreakpointType.java +++ b/debugger/debugger-impl/src/main/java/consulo/javascript/debugger/JavaScriptLineBreakpointType.java @@ -26,8 +26,8 @@ import consulo.project.Project; import consulo.virtualFileSystem.fileType.FileType; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL diff --git a/debugger/debugger-impl/src/main/java/consulo/javascript/debugger/JavaScriptLineBreakpointTypeResolver.java b/debugger/debugger-impl/src/main/java/consulo/javascript/debugger/JavaScriptLineBreakpointTypeResolver.java index fb78b35a..e4911172 100644 --- a/debugger/debugger-impl/src/main/java/consulo/javascript/debugger/JavaScriptLineBreakpointTypeResolver.java +++ b/debugger/debugger-impl/src/main/java/consulo/javascript/debugger/JavaScriptLineBreakpointTypeResolver.java @@ -24,9 +24,9 @@ import consulo.project.Project; import consulo.virtualFileSystem.VirtualFile; import consulo.virtualFileSystem.fileType.FileType; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; /** * @author VISTALL diff --git a/debugger/debugger-impl/src/main/java/consulo/javascript/debugger/JavaScriptListPanel.java b/debugger/debugger-impl/src/main/java/consulo/javascript/debugger/JavaScriptListPanel.java index f5fa3627..7ce337f2 100644 --- a/debugger/debugger-impl/src/main/java/consulo/javascript/debugger/JavaScriptListPanel.java +++ b/debugger/debugger-impl/src/main/java/consulo/javascript/debugger/JavaScriptListPanel.java @@ -16,18 +16,16 @@ package consulo.javascript.debugger; -import consulo.language.editor.FileColorManager; -import consulo.navigation.OpenFileDescriptorFactory; -import consulo.project.Project; +import consulo.ui.annotation.RequiredUIAccess; +import consulo.ui.color.ColorValue; import consulo.ui.ex.awt.ColoredListCellRenderer; import consulo.ui.ex.awt.JBList; import consulo.ui.ex.awt.JBScrollPane; import consulo.ui.ex.awt.SortedListModel; +import consulo.ui.ex.awtUnsafe.TargetAWT; import consulo.util.io.FileUtil; -import consulo.virtualFileSystem.VirtualFile; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import javax.swing.*; import java.awt.*; import java.awt.event.MouseAdapter; @@ -38,84 +36,53 @@ * @author VISTALL * @since 21.03.14 */ -public abstract class JavaScriptListPanel extends JPanel -{ - @Nonnull - private final Project myProject; - private SortedListModel myModel = SortedListModel.create(new Comparator() - { - @Override - public int compare(T o1, T o2) - { - VirtualFile v1 = toVirtualFile(o1, false); - VirtualFile v2 = toVirtualFile(o2, false); - if(v1 == null || v2 == null) - { - return -1; - } - return FileUtil.comparePaths(v1.getPath(), v2.getPath()); - } - }); +public class JavaScriptListPanel extends JPanel { + private SortedListModel myModel = SortedListModel.create((Comparator) (o1, o2) -> FileUtil.comparePaths(o1.getPath(), o2.getPath())); - public JavaScriptListPanel(@Nonnull Project project) - { - super(new BorderLayout()); - init(); - myProject = project; - } + public JavaScriptListPanel() { + super(new BorderLayout()); + init(); + } - private void init() - { - final JBList jbList = new JBList<>(myModel); - jbList.setCellRenderer(new ColoredListCellRenderer() - { - @Override - protected void customizeCellRenderer(@Nonnull JList jList, T t, int i, boolean b, boolean b1) - { - VirtualFile virtualFile = toVirtualFile(t, false); - if(virtualFile == null) - { - append(""); - } - else - { - setBackground(FileColorManager.getInstance(myProject).getFileColor(virtualFile)); - append(virtualFile.getPath()); - setIcon(virtualFile.getFileType().getIcon()); - } - } - }); - jbList.addMouseListener(new MouseAdapter() - { - @Override - public void mouseClicked(MouseEvent e) - { - if(e.getClickCount() == 2 && e.getButton() == MouseEvent.BUTTON1) - { - T selectedValue = jbList.getSelectedValue(); - if(selectedValue == null) - { - return; - } + private void init() { + final JBList list = new JBList<>(myModel); + list.setCellRenderer(new ColoredListCellRenderer() { + @Override + protected void customizeCellRenderer(@Nonnull JList list, T value, int index, boolean selected, boolean hasFocus) { + append(value.getPath()); - VirtualFile virtualFile = toVirtualFile(selectedValue, true); + setIcon(value.getIcon()); - if(virtualFile != null) - { - OpenFileDescriptorFactory.getInstance(myProject).builder(virtualFile).build().navigate(true); - } - } - } - }); + if (!selected) { + ColorValue fileStatusColor = value.getFileStatusColor(); + if (fileStatusColor != null) { + setBackground(TargetAWT.to(fileStatusColor)); + } + } + } + }); - add(new JBScrollPane(jbList), BorderLayout.CENTER); - } + list.addMouseListener(new MouseAdapter() { + @Override + @RequiredUIAccess + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2 && e.getButton() == MouseEvent.BUTTON1) { + T selectedValue = list.getSelectedValue(); + if (selectedValue == null) { + return; + } - @Nullable - public abstract VirtualFile toVirtualFile(@Nonnull T value, boolean toOpen); + if (selectedValue.canNavigate()) { + selectedValue.navigate(true); + } + } + } + }); - public void add(T value) - { - myModel.add(value); - } + add(new JBScrollPane(list), BorderLayout.CENTER); + } + + public void add(T value) { + myModel.add(value); + } } diff --git a/debugger/v8-debugger-impl/pom.xml b/debugger/v8-debugger-impl/pom.xml index 219d1689..5cca4523 100644 --- a/debugger/v8-debugger-impl/pom.xml +++ b/debugger/v8-debugger-impl/pom.xml @@ -32,7 +32,7 @@ consulo - https://maven.consulo.io/repository/snapshots/ + https://maven.consulo.dev/repository/snapshots/ true interval:60 diff --git a/debugger/v8-debugger-impl/src/main/java/consulo/javascript/run/debug/v8/V8BaseDebugProcess.java b/debugger/v8-debugger-impl/src/main/java/consulo/javascript/run/debug/v8/V8BaseDebugProcess.java index 99054a12..c1edc2dc 100644 --- a/debugger/v8-debugger-impl/src/main/java/consulo/javascript/run/debug/v8/V8BaseDebugProcess.java +++ b/debugger/v8-debugger-impl/src/main/java/consulo/javascript/run/debug/v8/V8BaseDebugProcess.java @@ -16,7 +16,6 @@ package consulo.javascript.run.debug.v8; -import consulo.application.AllIcons; import consulo.application.Application; import consulo.execution.ExecutionResult; import consulo.execution.debug.*; @@ -26,6 +25,8 @@ import consulo.execution.debug.breakpoint.XLineBreakpoint; import consulo.execution.debug.evaluation.XDebuggerEditorsProvider; import consulo.execution.debug.frame.XSuspendContext; +import consulo.execution.debug.icon.ExecutionDebugIconGroup; +import consulo.execution.debug.localize.XDebuggerLocalize; import consulo.execution.debug.ui.XDebugTabLayouter; import consulo.execution.ui.ExecutionConsole; import consulo.execution.ui.layout.RunnerLayoutUi; @@ -33,18 +34,19 @@ import consulo.javascript.debugger.JavaScriptLineBreakpointType; import consulo.javascript.debugger.JavaScriptListPanel; import consulo.javascript.icon.JavaScriptIconGroup; +import consulo.localize.LocalizeValue; import consulo.process.ExecutionException; import consulo.process.ProcessHandler; import consulo.ui.ex.awt.UIUtil; import consulo.ui.ex.content.Content; import consulo.virtualFileSystem.VirtualFile; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; import org.chromium.sdk.Breakpoint; import org.chromium.sdk.DebugContext; import org.chromium.sdk.JavascriptVm; import org.chromium.sdk.Script; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.Collection; import java.util.HashMap; import java.util.Map; @@ -53,242 +55,199 @@ * @author VISTALL * @since 2020-06-16 */ -public abstract class V8BaseDebugProcess extends XDebugProcess -{ - protected V myVm; - - private final ExecutionResult myResult; - private DebugContext myCurrentDebugContext; - private JavaScriptListPanel"; - @NonNls - private static final String HTML_TAG_END = ">"; - - final XmlFile file; - final String fileText; - int scriptStartIndex; - int scriptEndIndex; - JSElement next; - - public EmbeddedJSElementIterator(XmlFile file) - { - this.file = file; - this.fileText = file.getText(); - this.scriptEndIndex = -SCRIPT_END.length(); - - this.findNext(); - } - - @Override - public boolean hasNext() - { - return (this.next != null); - } - - @Override - public JSElement next() - { - if(this.next == null) - { - throw new NoSuchElementException(); - } - - JSElement next = this.next; - - this.findNext(); - return next; - } - - private void findNext() - { - if(!(this.next == null || this.next instanceof JSEmbeddedContentImpl)) - { - this.next = PsiTreeUtil.getNextSiblingOfType(this.next, JSElement.class); - - if(this.next != null) - { - return; - } - } - - PsiElement psiElement; - - do - { - if(this.scriptStartIndex >= 0) - { - this.scriptStartIndex = this.fileText.indexOf(SCRIPT_START, this.scriptEndIndex + SCRIPT_END.length()); - } - - if(this.scriptStartIndex < 0) - { - this.next = null; - return; - } - - int offset = ((this.scriptStartIndex >= 0) ? this.fileText.indexOf(HTML_TAG_END, this.scriptStartIndex + SCRIPT_START.length()) + 1 - : 0); - - this.scriptEndIndex = ((offset > 0) ? this.fileText.indexOf(SCRIPT_END, offset) : -1); - if(this.scriptEndIndex < 0) - { - this.scriptStartIndex = -1; - return; - } - - psiElement = this.file.findElementAt(offset); - - if(psiElement instanceof PsiWhiteSpace) - { - psiElement = PsiTreeUtil.getNextSiblingOfType(psiElement, JSElement.class); - } - - if(psiElement != null && psiElement instanceof JSElement) - { - this.next = FindReferenceUtil.getFarthestAncestor(psiElement, JSElement.class); - } - } - while(this.next == null); - } - - @Override - public void remove() - { - throw new UnsupportedOperationException(); - } - } +public class JSFunctionVisitor extends JSElementVisitor { + @Override + public void visitElement(PsiElement element) { + if (element instanceof JSFunction function) { + this.visitJSFunctionDeclaration(function); + } + else if (element instanceof JSReferenceExpression) { + if (element == element.getParent().getChildren()[0]) { + PsiElement firstChild = element.getParent().getFirstChild(); + + if (firstChild != null && firstChild.toString().indexOf(JSTokenTypes.NEW_KEYWORD.toString()) >= 0) { + this.visitJSNewExpression(new JSNewExpressionImpl(element.getParent().getNode())); + } + } + } + else if (element instanceof XmlFile xmlFile) { + processFile(xmlFile); + } + + super.visitElement(element); + + for (PsiElement childElement : element.getChildren()) { + childElement.accept(this); + } + } + + @Override + public void visitJSNewExpression(JSNewExpression newExpression) { + } + + private static final Logger logger = Logger.getInstance(JSFunctionVisitor.class.getName()); + + private void processFile(XmlFile file) { + int count = 0; + long start = System.currentTimeMillis(); + + for (JSElement element : getEmbeddedJSElements(file)) { + this.visitElement(element); + count++; + } + logger.info( + "Processed inspection " + this.getClass().getSimpleName() + " on file " + file.getName() + + " (" + count + " blocks) in " + (System.currentTimeMillis() - start) + " ms." + ); + } + + static Iterable getEmbeddedJSElements(XmlFile file) { + return () -> new EmbeddedJSElementIterator(file); + } + + /** + * This iterator makes a textual search for every SCRIPT sub-text and + * tries and finds JSElement instances within this SCRIPT, on which + * this.visitElement() can be called. + */ + private static class EmbeddedJSElementIterator implements Iterator { + @NonNls + private static final String SCRIPT_START = "= 0) { + this.scriptStartIndex = this.fileText.indexOf(SCRIPT_START, this.scriptEndIndex + SCRIPT_END.length()); + } + + if (this.scriptStartIndex < 0) { + this.next = null; + return; + } + + int offset = this.scriptStartIndex >= 0 + ? this.fileText.indexOf(HTML_TAG_END, this.scriptStartIndex + SCRIPT_START.length()) + 1 + : 0; + + this.scriptEndIndex = ((offset > 0) ? this.fileText.indexOf(SCRIPT_END, offset) : -1); + if (this.scriptEndIndex < 0) { + this.scriptStartIndex = -1; + return; + } + + psiElement = this.file.findElementAt(offset); + + if (psiElement instanceof PsiWhiteSpace) { + psiElement = PsiTreeUtil.getNextSiblingOfType(psiElement, JSElement.class); + } + + if (psiElement != null && psiElement instanceof JSElement) { + this.next = FindReferenceUtil.getFarthestAncestor(psiElement, JSElement.class); + } + } + while (this.next == null); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/JSIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/JSIntention.java index 4acc999a..05ad4b10 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/JSIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/JSIntention.java @@ -22,93 +22,67 @@ import consulo.language.psi.PsiElement; import consulo.language.psi.PsiFile; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; import consulo.project.Project; import consulo.xml.psi.xml.XmlElement; -import org.jetbrains.annotations.NonNls; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; public abstract class JSIntention extends PsiElementBaseIntentionAction { - private static final String INTENTION_SUFFIX = "Intention"; - private static final String DISPLAY_NAME = ".display-name"; - private static final String PACKAGE_NAME = JSIntention.class.getPackage().getName(); - - private final JSElementPredicate predicate; - - protected JSIntention() { - this.predicate = this.getElementPredicate(); - } + private final JSElementPredicate predicate; - @Override - public void invoke(@Nonnull Project project, Editor editor, @Nonnull PsiElement element) throws IncorrectOperationException { - PsiElement matchingElement = findMatchingElement(element); - if (matchingElement == null) { - return; + protected JSIntention() { + this.predicate = this.getElementPredicate(); } - processIntention(matchingElement); - } - protected abstract void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException; - - @Nonnull - protected abstract JSElementPredicate getElementPredicate(); - - @Nullable - protected PsiElement findMatchingElement(@Nullable PsiElement element) { - if (element == null || element instanceof PsiFile) { - return null; + @Override + public void invoke(@Nonnull Project project, Editor editor, @Nonnull PsiElement element) throws IncorrectOperationException { + PsiElement matchingElement = findMatchingElement(element); + if (matchingElement == null) { + return; + } + processIntention(matchingElement); } - final Language language = element.getLanguage(); - if (language != Language.ANY && language != JavaScriptLanguage.INSTANCE) { - return null; + protected abstract void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException; + + @Nonnull + protected abstract JSElementPredicate getElementPredicate(); + + @Nullable + protected PsiElement findMatchingElement(@Nullable PsiElement element) { + if (element == null || element instanceof PsiFile) { + return null; + } + + Language language = element.getLanguage(); + if (language != Language.ANY && language != JavaScriptLanguage.INSTANCE) { + return null; + } + + while (element != null) { + if (this.predicate.satisfiedBy(element)) { + return element; + } + element = element.getParent(); + if (element instanceof PsiFile || element instanceof XmlElement) { + break; + } + } + return null; } - while (element != null) { - if (this.predicate.satisfiedBy(element)) { - return element; - } - element = element.getParent(); - if (element instanceof PsiFile || element instanceof XmlElement) { - break; - } + @Override + public boolean isAvailable(@Nonnull Project project, Editor editor, @Nullable PsiElement element) { + return element != null && findMatchingElement(element) != null; } - return null; - } - - @Override - public boolean isAvailable(@Nonnull Project project, Editor editor, @Nullable PsiElement element) { - return element != null && findMatchingElement(element) != null; - } - - @Override - public boolean startInWriteAction() { - return true; - } - - protected String getTextKey(@NonNls Object... suffixes) { - return JSIntentionBundle.getKey(this.getClass().getName().substring(PACKAGE_NAME.length() + 1).replace("JS", ""), - INTENTION_SUFFIX, - null, - suffixes); - } - - @Override - @SuppressWarnings({"UnresolvedPropertyKey"}) - @Nonnull - public String getText() { - return JSIntentionBundle.message(this.getTextKey(DISPLAY_NAME)); - } - - @SuppressWarnings({"UnresolvedPropertyKey"}) - public String getText(@NonNls Object... arguments) { - return JSIntentionBundle.message(this.getTextKey(DISPLAY_NAME), arguments); - } + @Override + public boolean startInWriteAction() { + return true; + } - @SuppressWarnings({"UnresolvedPropertyKey"}) - protected String getSuffixedDisplayName(@NonNls String suffix, @NonNls Object... arguments) { - return JSIntentionBundle.message(this.getTextKey(DISPLAY_NAME, '.', suffix), arguments); - } + @Override + @Nonnull + public abstract LocalizeValue getText(); } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/JSIntentionBundle.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/JSIntentionBundle.java deleted file mode 100644 index 6cca6e24..00000000 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/JSIntentionBundle.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2005-2006 Olivier Descout - * - * 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 org.intellij.idea.lang.javascript.intention; - -import consulo.application.CommonBundle; -import org.intellij.idea.lang.javascript.JSAbstractBundle; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.PropertyKey; - -import java.util.ResourceBundle; - -public class JSIntentionBundle extends JSAbstractBundle -{ - - @NonNls - private static final String bundleClassName = "org.intellij.idea.lang.javascript.intention.JavaScriptIntentionBundle"; - private static final ResourceBundle ourBundle = ResourceBundle.getBundle(bundleClassName); - - private JSIntentionBundle() - { - } - - public static String message(@PropertyKey(resourceBundle = bundleClassName) String key, - Object... params) - { - return CommonBundle.message(ourBundle, key, params); - } -} diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/JSMutablyNamedIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/JSMutablyNamedIntention.java index 7b9e6c43..5b4bc7c4 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/JSMutablyNamedIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/JSMutablyNamedIntention.java @@ -17,40 +17,34 @@ import consulo.codeEditor.Editor; import consulo.language.psi.PsiElement; +import consulo.localize.LocalizeValue; import consulo.project.Project; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +public abstract class JSMutablyNamedIntention extends JSIntention { + private LocalizeValue myText = LocalizeValue.empty(); -public abstract class JSMutablyNamedIntention extends JSIntention -{ - private String myText; + protected abstract LocalizeValue getTextForElement(PsiElement element); - protected abstract String getTextForElement(PsiElement element); + @Override + @Nonnull + public LocalizeValue getText() { + return myText.orIfEmpty(getBasicText()); + } - @Override - @Nonnull - public String getText() - { - if(myText != null) - { - return myText; - } - return super.getText(); - } + @Nonnull + protected abstract LocalizeValue getBasicText(); - @Override - public boolean isAvailable(@Nonnull Project project, Editor editor, @Nullable PsiElement node) - { - final PsiElement element = findMatchingElement(node); - if(element != null) - { - myText = getTextForElement(element); - return true; - } - else - { - return false; - } - } + @Override + public boolean isAvailable(@Nonnull Project project, Editor editor, @Nullable PsiElement node) { + PsiElement element = findMatchingElement(node); + if (element != null) { + myText = getTextForElement(element); + return true; + } + else { + return false; + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/ComparisonPredicate.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/ComparisonPredicate.java index 3257f1dd..349c43b2 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/ComparisonPredicate.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/ComparisonPredicate.java @@ -22,27 +22,21 @@ import org.intellij.idea.lang.javascript.psiutil.ComparisonUtils; import org.intellij.idea.lang.javascript.psiutil.ErrorUtil; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; -class ComparisonPredicate implements JSElementPredicate -{ - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSBinaryExpression)) - { - return false; - } - if(ErrorUtil.containsError(element)) - { - return false; - } +class ComparisonPredicate implements JSElementPredicate { + @Override + public boolean satisfiedBy(@Nonnull PsiElement element) { + if (!(element instanceof JSBinaryExpression)) { + return false; + } + if (ErrorUtil.containsError(element)) { + return false; + } - final JSBinaryExpression expression = (JSBinaryExpression) element; - final JSExpression rhs = expression.getROperand(); + JSBinaryExpression expression = (JSBinaryExpression)element; + JSExpression rhs = expression.getROperand(); - return (rhs != null && - ComparisonUtils.isComparisonOperator((JSExpression) element)); - - } + return (rhs != null && ComparisonUtils.isComparisonOperator((JSExpression)element)); + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/ConjunctionPredicate.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/ConjunctionPredicate.java index 35b3f95c..76b3c996 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/ConjunctionPredicate.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/ConjunctionPredicate.java @@ -19,28 +19,23 @@ import com.intellij.lang.javascript.psi.JSBinaryExpression; import consulo.language.ast.IElementType; import consulo.language.psi.PsiElement; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.psiutil.ErrorUtil; -import javax.annotation.Nonnull; +class ConjunctionPredicate implements JSElementPredicate { + @Override + public boolean satisfiedBy(@Nonnull PsiElement element) { + if (!(element instanceof JSBinaryExpression)) { + return false; + } + if (ErrorUtil.containsError(element)) { + return false; + } -class ConjunctionPredicate implements JSElementPredicate -{ - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSBinaryExpression)) - { - return false; - } - if(ErrorUtil.containsError(element)) - { - return false; - } + JSBinaryExpression expression = (JSBinaryExpression)element; + IElementType sign = expression.getOperationSign(); - final JSBinaryExpression expression = (JSBinaryExpression) element; - final IElementType sign = expression.getOperationSign(); - - return (sign.equals(JSTokenTypes.ANDAND) || sign.equals(JSTokenTypes.OROR)); - } + return (JSTokenTypes.ANDAND.equals(sign) || JSTokenTypes.OROR.equals(sign)); + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/JSDeMorgansLawIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/JSDeMorgansLawIntention.java index ce99621d..39d43962 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/JSDeMorgansLawIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/JSDeMorgansLawIntention.java @@ -19,97 +19,85 @@ import com.intellij.lang.javascript.psi.JSBinaryExpression; import com.intellij.lang.javascript.psi.JSElement; import com.intellij.lang.javascript.psi.JSExpression; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.ast.IElementType; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSMutablyNamedIntention; import org.intellij.idea.lang.javascript.psiutil.BoolUtils; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; -import org.jetbrains.annotations.NonNls; - -import javax.annotation.Nonnull; @ExtensionImpl -@IntentionMetaData(ignoreId = "JSDeMorgansLawIntention", categories = { - "JavaScript", - "Boolean" -}, fileExtensions = "js") -public class JSDeMorgansLawIntention extends JSMutablyNamedIntention -{ - @NonNls - private static final String AND_OPERATOR = "&&"; - @NonNls - private static final String OR_OPERATOR = "||"; - @NonNls - private static final String AND_SUFFIX = "ANDAND"; - @NonNls - private static final String OR_SUFFIX = "OROR"; - - @Override - protected String getTextForElement(PsiElement element) - { - final IElementType tokenType = ((JSBinaryExpression) element).getOperationSign(); - - return this.getSuffixedDisplayName(tokenType.equals(JSTokenTypes.ANDAND) ? AND_SUFFIX : OR_SUFFIX); - } - - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new ConjunctionPredicate(); - } - - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - JSBinaryExpression exp = (JSBinaryExpression) element; - final IElementType tokenType = exp.getOperationSign(); - JSElement parent = (JSElement) exp.getParent(); - - while(isConjunctionExpression(parent, tokenType)) - { - exp = (JSBinaryExpression) parent; - assert (exp != null); - parent = (JSElement) exp.getParent(); - } - - final String newExpression = this.convertConjunctionExpression(exp, tokenType); - - JSElementFactory.replaceExpressionWithNegatedExpressionString(exp, newExpression); - } - - private String convertConjunctionExpression(JSBinaryExpression exp, - IElementType tokenType) - { - final String leftText = this.getOperandText(exp.getLOperand(), tokenType); - final String rightText = this.getOperandText(exp.getROperand(), tokenType); - final String flippedConjunction = (tokenType.equals(JSTokenTypes.ANDAND) ? OR_OPERATOR : AND_OPERATOR); - - return leftText + flippedConjunction + rightText; - } - - private String getOperandText(JSExpression operand, IElementType tokenType) - { - return (isConjunctionExpression(operand, tokenType) - ? this.convertConjunctionExpression((JSBinaryExpression) operand, tokenType) - : BoolUtils.getNegatedExpressionText(operand)); - } - - private static boolean isConjunctionExpression(JSElement exp, - IElementType conjunctionType) - { - if(!(exp instanceof JSBinaryExpression)) - { - return false; - } - - final JSBinaryExpression binaryExpression = (JSBinaryExpression) exp; - final IElementType tokenType = binaryExpression.getOperationSign(); - - return tokenType.equals(conjunctionType); - } +@IntentionMetaData( + ignoreId = "JSDeMorgansLawIntention", + categories = {"JavaScript", "Boolean"}, + fileExtensions = "js" +) +public class JSDeMorgansLawIntention extends JSMutablyNamedIntention { + @Override + @Nonnull + protected LocalizeValue getBasicText() { + return JSIntentionLocalize.boolDeMorgansLaw(); + } + + @Override + @RequiredReadAction + protected LocalizeValue getTextForElement(PsiElement element) { + IElementType tokenType = ((JSBinaryExpression)element).getOperationSign(); + + return JSTokenTypes.ANDAND.equals(tokenType) + ? JSIntentionLocalize.boolDeMorgansLawAndToOr() + : JSIntentionLocalize.boolDeMorgansLawOrToAnd(); + } + + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new ConjunctionPredicate(); + } + + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + JSBinaryExpression exp = (JSBinaryExpression)element; + IElementType tokenType = exp.getOperationSign(); + JSElement parent = (JSElement)exp.getParent(); + + while (isConjunctionExpression(parent, tokenType)) { + exp = (JSBinaryExpression)parent; + assert (exp != null); + parent = (JSElement)exp.getParent(); + } + + String newExpression = this.convertConjunctionExpression(exp, tokenType); + + JSElementFactory.replaceExpressionWithNegatedExpressionString(exp, newExpression); + } + + @RequiredReadAction + private String convertConjunctionExpression(JSBinaryExpression exp, IElementType tokenType) { + String leftText = this.getOperandText(exp.getLOperand(), tokenType); + String rightText = this.getOperandText(exp.getROperand(), tokenType); + String flippedConjunction = tokenType.equals(JSTokenTypes.ANDAND) ? "||" : "&&"; + + return leftText + flippedConjunction + rightText; + } + + @RequiredReadAction + private String getOperandText(JSExpression operand, IElementType tokenType) { + return isConjunctionExpression(operand, tokenType) + ? this.convertConjunctionExpression((JSBinaryExpression)operand, tokenType) + : BoolUtils.getNegatedExpressionText(operand); + } + + @RequiredReadAction + private static boolean isConjunctionExpression(JSElement exp, IElementType conjunctionType) { + return exp instanceof JSBinaryExpression binaryExpression && binaryExpression.getOperationSign().equals(conjunctionType); + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/JSFlipComparisonIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/JSFlipComparisonIntention.java index 252ec0e8..4f2a03ef 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/JSFlipComparisonIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/JSFlipComparisonIntention.java @@ -17,70 +17,73 @@ import com.intellij.lang.javascript.psi.JSBinaryExpression; import com.intellij.lang.javascript.psi.JSExpression; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.ast.IElementType; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSMutablyNamedIntention; import org.intellij.idea.lang.javascript.psiutil.ComparisonUtils; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; -import javax.annotation.Nonnull; - @ExtensionImpl -@IntentionMetaData(ignoreId = "JSFlipComparisonIntention", categories = { - "JavaScript", - "Boolean" -}, fileExtensions = "js") -public class JSFlipComparisonIntention extends JSMutablyNamedIntention -{ - @Override - public String getTextForElement(PsiElement element) - { - final JSBinaryExpression exp = (JSBinaryExpression) element; - String operatorText = null; - String flippedOperatorText = null; +@IntentionMetaData( + ignoreId = "JSFlipComparisonIntention", + categories = {"JavaScript", "Boolean"}, + fileExtensions = "js" +) +public class JSFlipComparisonIntention extends JSMutablyNamedIntention { + @Nonnull + @Override + protected LocalizeValue getBasicText() { + return JSIntentionLocalize.boolFlipComparison(); + } + + @Override + @RequiredReadAction + public LocalizeValue getTextForElement(PsiElement element) { + JSBinaryExpression exp = (JSBinaryExpression)element; + String operatorText = null; + String flippedOperatorText = null; - if(exp != null) - { - operatorText = ComparisonUtils.getOperatorText(exp.getOperationSign()); - flippedOperatorText = ComparisonUtils.getFlippedOperatorText(exp.getOperationSign()); - } + if (exp != null) { + operatorText = ComparisonUtils.getOperatorText(exp.getOperationSign()); + flippedOperatorText = ComparisonUtils.getFlippedOperatorText(exp.getOperationSign()); + } - if(exp == null) - { - return this.getSuffixedDisplayName("unknown"); - } - else if(operatorText.equals(flippedOperatorText)) - { - return this.getSuffixedDisplayName("equals", operatorText); - } - else - { - return this.getSuffixedDisplayName("not-equals", operatorText, flippedOperatorText); - } - } + if (exp == null) { + return JSIntentionLocalize.boolFlipComparisonUnknown(); + } + else if (operatorText.equals(flippedOperatorText)) { + return JSIntentionLocalize.boolFlipComparisonEquals(operatorText); + } + else { + return JSIntentionLocalize.boolFlipComparisonNotEquals(operatorText, flippedOperatorText); + } + } - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new ComparisonPredicate(); - } + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new ComparisonPredicate(); + } - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final JSBinaryExpression exp = (JSBinaryExpression) element; - final JSExpression lhs = exp.getLOperand(); - final JSExpression rhs = exp.getROperand(); - final IElementType sign = exp.getOperationSign(); + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + JSBinaryExpression exp = (JSBinaryExpression)element; + JSExpression lhs = exp.getLOperand(); + JSExpression rhs = exp.getROperand(); + IElementType sign = exp.getOperationSign(); - assert (rhs != null); + assert (rhs != null); - final String expString = rhs.getText() + ComparisonUtils.getFlippedOperatorText(sign) + lhs.getText(); - JSElementFactory.replaceExpression(exp, expString); - } + String expString = rhs.getText() + ComparisonUtils.getFlippedOperatorText(sign) + lhs.getText(); + JSElementFactory.replaceExpression(exp, expString); + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/JSFlipConjunctionIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/JSFlipConjunctionIntention.java index c62a79f9..7449f1dc 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/JSFlipConjunctionIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/JSFlipConjunctionIntention.java @@ -18,86 +18,81 @@ import com.intellij.lang.javascript.psi.JSBinaryExpression; import com.intellij.lang.javascript.psi.JSElement; import com.intellij.lang.javascript.psi.JSExpression; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.ast.IElementType; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSMutablyNamedIntention; import org.intellij.idea.lang.javascript.psiutil.BinaryOperatorUtils; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; -import javax.annotation.Nonnull; - @ExtensionImpl -@IntentionMetaData(ignoreId = "JSFlipConjunctionIntention", categories = { - "JavaScript", - "Boolean" -}, fileExtensions = "js") -public class JSFlipConjunctionIntention extends JSMutablyNamedIntention -{ - @Override - protected String getTextForElement(PsiElement element) - { - final JSBinaryExpression binaryExpression = (JSBinaryExpression) element; - final IElementType sign = binaryExpression.getOperationSign(); - - return this.getText(BinaryOperatorUtils.getOperatorText(sign)); - } +@IntentionMetaData( + ignoreId = "JSFlipConjunctionIntention", + categories = {"JavaScript", "Boolean"}, + fileExtensions = "js" +) +public class JSFlipConjunctionIntention extends JSMutablyNamedIntention { + @Nonnull + @Override + protected LocalizeValue getBasicText() { + return JSIntentionLocalize.boolFlipConjunction(); + } - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new ConjunctionPredicate(); - } + @Override + @RequiredReadAction + protected LocalizeValue getTextForElement(PsiElement element) { + JSBinaryExpression binaryExpression = (JSBinaryExpression)element; + IElementType sign = binaryExpression.getOperationSign(); - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final JSBinaryExpression binaryExpression = (JSBinaryExpression) element; - JSExpression exp = binaryExpression; + return JSIntentionLocalize.boolFlipConjunctionMessage(BinaryOperatorUtils.getOperatorText(sign)); + } - final IElementType sign = binaryExpression.getOperationSign(); - JSElement parent = (JSElement) exp.getParent(); + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new ConjunctionPredicate(); + } - while(isConjunctionExpression(parent, sign)) - { - exp = (JSExpression) parent; - assert (exp != null); - parent = (JSElement) exp.getParent(); - } - JSElementFactory.replaceExpression(exp, this.flipExpression(exp, sign)); - } + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + JSBinaryExpression binaryExpression = (JSBinaryExpression)element; + JSExpression exp = binaryExpression; - private String flipExpression(JSExpression exp, - IElementType conjunctionType) - { - if(isConjunctionExpression(exp, conjunctionType)) - { - final JSBinaryExpression andExpression = (JSBinaryExpression) exp; + IElementType sign = binaryExpression.getOperationSign(); + JSElement parent = (JSElement)exp.getParent(); - return this.flipExpression(andExpression.getROperand(), conjunctionType) + ' ' + - BinaryOperatorUtils.getOperatorText(conjunctionType) + ' ' + - this.flipExpression(andExpression.getLOperand(), conjunctionType); - } - else - { - return exp.getText(); - } - } + while (isConjunctionExpression(parent, sign)) { + exp = (JSExpression)parent; + assert (exp != null); + parent = (JSElement)exp.getParent(); + } + JSElementFactory.replaceExpression(exp, this.flipExpression(exp, sign)); + } - private static boolean isConjunctionExpression(JSElement expression, - IElementType conjunctionType) - { - if(!(expression instanceof JSBinaryExpression)) - { - return false; - } + @RequiredReadAction + private String flipExpression(JSExpression exp, IElementType conjunctionType) { + if (isConjunctionExpression(exp, conjunctionType)) { + JSBinaryExpression andExpression = (JSBinaryExpression)exp; - final JSBinaryExpression binaryExpression = (JSBinaryExpression) expression; + return this.flipExpression(andExpression.getROperand(), conjunctionType) + ' ' + + BinaryOperatorUtils.getOperatorText(conjunctionType) + ' ' + + this.flipExpression(andExpression.getLOperand(), conjunctionType); + } + else { + return exp.getText(); + } + } - return binaryExpression.getOperationSign().equals(conjunctionType); - } + @RequiredReadAction + private static boolean isConjunctionExpression(JSElement expression, IElementType conjunctionType) { + return expression instanceof JSBinaryExpression binaryExpression && binaryExpression.getOperationSign().equals(conjunctionType); + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/JSNegateComparisonIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/JSNegateComparisonIntention.java index 582ec90a..19f43d00 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/JSNegateComparisonIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/JSNegateComparisonIntention.java @@ -17,71 +17,70 @@ import com.intellij.lang.javascript.psi.JSBinaryExpression; import com.intellij.lang.javascript.psi.JSExpression; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.ast.IElementType; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSMutablyNamedIntention; import org.intellij.idea.lang.javascript.psiutil.ComparisonUtils; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; -import javax.annotation.Nonnull; - @ExtensionImpl -@IntentionMetaData(ignoreId = "JSNegateComparisonIntention", categories = { - "JavaScript", - "Boolean" -}, fileExtensions = "js") -public class JSNegateComparisonIntention extends JSMutablyNamedIntention -{ - @Override - public String getTextForElement(PsiElement element) - { - final JSBinaryExpression expression = (JSBinaryExpression) element; - String operatorText = ""; - String negatedOperatorText = ""; +@IntentionMetaData( + ignoreId = "JSNegateComparisonIntention", + categories = {"JavaScript", "Boolean"}, + fileExtensions = "js" +) +public class JSNegateComparisonIntention extends JSMutablyNamedIntention { + @Nonnull + @Override + protected LocalizeValue getBasicText() { + return JSIntentionLocalize.boolNegateComparison(); + } + + @Override + @RequiredReadAction + public LocalizeValue getTextForElement(PsiElement element) { + JSBinaryExpression expression = (JSBinaryExpression)element; + String operatorText = ""; + String negatedOperatorText = ""; - if(expression != null) - { - final IElementType sign = expression.getOperationSign(); + if (expression != null) { + IElementType sign = expression.getOperationSign(); - operatorText = ComparisonUtils.getOperatorText(sign); - negatedOperatorText = ComparisonUtils.getNegatedOperatorText(sign); - } + operatorText = ComparisonUtils.getOperatorText(sign); + negatedOperatorText = ComparisonUtils.getNegatedOperatorText(sign); + } - if(operatorText.equals(negatedOperatorText)) - { - return this.getSuffixedDisplayName("equals", operatorText); - } - else - { - return this.getSuffixedDisplayName("not-equals", operatorText, negatedOperatorText); - } - } + return operatorText.equals(negatedOperatorText) + ? JSIntentionLocalize.boolNegateComparisonEquals(operatorText) + : JSIntentionLocalize.boolNegateComparisonNotEquals(operatorText, negatedOperatorText); + } - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new ComparisonPredicate(); - } + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new ComparisonPredicate(); + } - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final JSBinaryExpression exp = (JSBinaryExpression) element; - final JSExpression lhs = exp.getLOperand(); - final JSExpression rhs = exp.getROperand(); - final IElementType sign = exp.getOperationSign(); - final String negatedOperator = ComparisonUtils.getNegatedOperatorText(sign); - final String lhsText = lhs.getText(); + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + JSBinaryExpression exp = (JSBinaryExpression)element; + JSExpression lhs = exp.getLOperand(); + JSExpression rhs = exp.getROperand(); + IElementType sign = exp.getOperationSign(); + String negatedOperator = ComparisonUtils.getNegatedOperatorText(sign); + String lhsText = lhs.getText(); - assert (rhs != null); + assert (rhs != null); - JSElementFactory.replaceExpressionWithNegatedExpressionString(exp, lhsText + - negatedOperator + - rhs.getText()); - } + JSElementFactory.replaceExpressionWithNegatedExpressionString(exp, lhsText + negatedOperator + rhs.getText()); + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/JSRemoveBooleanEqualityIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/JSRemoveBooleanEqualityIntention.java index 649f2bfd..37c00599 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/JSRemoveBooleanEqualityIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/bool/JSRemoveBooleanEqualityIntention.java @@ -18,11 +18,15 @@ import com.intellij.lang.javascript.JSTokenTypes; import com.intellij.lang.javascript.psi.JSBinaryExpression; import com.intellij.lang.javascript.psi.JSExpression; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.ast.IElementType; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSMutablyNamedIntention; import org.intellij.idea.lang.javascript.psiutil.BinaryOperatorUtils; @@ -30,118 +34,100 @@ import org.intellij.idea.lang.javascript.psiutil.ErrorUtil; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; -import javax.annotation.Nonnull; - @ExtensionImpl -@IntentionMetaData(ignoreId = "JSRemoveBooleanEqualityIntention", categories = { - "JavaScript", - "Boolean" -}, fileExtensions = "js") -public class JSRemoveBooleanEqualityIntention extends JSMutablyNamedIntention -{ - @Override - protected String getTextForElement(PsiElement element) - { - final JSBinaryExpression binaryExpression = (JSBinaryExpression) element; +@IntentionMetaData( + ignoreId = "JSRemoveBooleanEqualityIntention", + categories = {"JavaScript", "Boolean"}, + fileExtensions = "js" +) +public class JSRemoveBooleanEqualityIntention extends JSMutablyNamedIntention { + @Nonnull + @Override + protected LocalizeValue getBasicText() { + return JSIntentionLocalize.boolRemoveBooleanEquality(); + } + + @Override + @RequiredReadAction + protected LocalizeValue getTextForElement(PsiElement element) { + JSBinaryExpression binaryExpression = (JSBinaryExpression)element; - return this.getText(BinaryOperatorUtils.getOperatorText(binaryExpression.getOperationSign())); - } + return JSIntentionLocalize.boolRemoveBooleanEqualityMessage( + BinaryOperatorUtils.getOperatorText(binaryExpression.getOperationSign()) + ); + } - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new BooleanLiteralEqualityPredicate(); - } + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new BooleanLiteralEqualityPredicate(); + } - @Override - public void processIntention(@Nonnull PsiElement element) - throws IncorrectOperationException - { - final JSBinaryExpression exp = (JSBinaryExpression) element; - final boolean isEquals = exp.getOperationSign().equals(JSTokenTypes.EQEQ); - final JSExpression lhs = exp.getLOperand(); - final JSExpression rhs = exp.getROperand(); + @Override + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + JSBinaryExpression exp = (JSBinaryExpression)element; + boolean isEquals = exp.getOperationSign().equals(JSTokenTypes.EQEQ); + JSExpression lhs = exp.getLOperand(); + JSExpression rhs = exp.getROperand(); - assert (lhs != null); - assert (rhs != null); + assert (lhs != null); + assert (rhs != null); - final String lhsText = lhs.getText(); - final String rhsText = rhs.getText(); + String lhsText = lhs.getText(); + String rhsText = rhs.getText(); - if(BoolUtils.TRUE.equals(lhsText)) - { - if(isEquals) - { - JSElementFactory.replaceExpression(exp, rhsText); - } - else - { - JSElementFactory.replaceExpressionWithNegatedExpression(rhs, exp); - } - } - else if(BoolUtils.FALSE.equals(lhsText)) - { - if(isEquals) - { - JSElementFactory.replaceExpressionWithNegatedExpression(rhs, exp); - } - else - { - JSElementFactory.replaceExpression(exp, rhsText); - } - } - else if(BoolUtils.TRUE.equals(rhsText)) - { - if(isEquals) - { - JSElementFactory.replaceExpression(exp, lhsText); - } - else - { - JSElementFactory.replaceExpressionWithNegatedExpression(lhs, exp); - } - } - else - { - if(isEquals) - { - JSElementFactory.replaceExpressionWithNegatedExpression(lhs, exp); - } - else - { - JSElementFactory.replaceExpression(exp, lhsText); - } - } - } + if (BoolUtils.TRUE.equals(lhsText)) { + if (isEquals) { + JSElementFactory.replaceExpression(exp, rhsText); + } + else { + JSElementFactory.replaceExpressionWithNegatedExpression(rhs, exp); + } + } + else if (BoolUtils.FALSE.equals(lhsText)) { + if (isEquals) { + JSElementFactory.replaceExpressionWithNegatedExpression(rhs, exp); + } + else { + JSElementFactory.replaceExpression(exp, rhsText); + } + } + else if (BoolUtils.TRUE.equals(rhsText)) { + if (isEquals) { + JSElementFactory.replaceExpression(exp, lhsText); + } + else { + JSElementFactory.replaceExpressionWithNegatedExpression(lhs, exp); + } + } + else { + if (isEquals) { + JSElementFactory.replaceExpressionWithNegatedExpression(lhs, exp); + } + else { + JSElementFactory.replaceExpression(exp, lhsText); + } + } + } - private static class BooleanLiteralEqualityPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSBinaryExpression)) - { - return false; - } - if(ErrorUtil.containsError(element)) - { - return false; - } + private static class BooleanLiteralEqualityPredicate implements JSElementPredicate { + @Override + public boolean satisfiedBy(@Nonnull PsiElement element) { + if (!(element instanceof JSBinaryExpression) || ErrorUtil.containsError(element)) { + return false; + } - final JSBinaryExpression expression = (JSBinaryExpression) element; - final IElementType sign = expression.getOperationSign(); + JSBinaryExpression expression = (JSBinaryExpression)element; + IElementType sign = expression.getOperationSign(); - if(!(sign.equals(JSTokenTypes.EQEQ) || sign.equals(JSTokenTypes.NE))) - { - return false; - } + if (!(JSTokenTypes.EQEQ.equals(sign) || JSTokenTypes.NE.equals(sign))) { + return false; + } - final JSExpression lhs = expression.getLOperand(); - final JSExpression rhs = expression.getROperand(); + JSExpression lhs = expression.getLOperand(); + JSExpression rhs = expression.getROperand(); - return (lhs != null && rhs != null && - (BoolUtils.isBooleanLiteral(lhs) || BoolUtils.isBooleanLiteral(rhs))); - } - } + return lhs != null && rhs != null && (BoolUtils.isBooleanLiteral(lhs) || BoolUtils.isBooleanLiteral(rhs)); + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/braces/JSAddBracesIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/braces/JSAddBracesIntention.java index 8fe6085a..04e2948e 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/braces/JSAddBracesIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/braces/JSAddBracesIntention.java @@ -16,125 +16,93 @@ package org.intellij.idea.lang.javascript.intention.braces; import com.intellij.lang.javascript.psi.*; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiComment; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSMutablyNamedIntention; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; -import org.jetbrains.annotations.NonNls; - -import javax.annotation.Nonnull; @ExtensionImpl -@IntentionMetaData(ignoreId = "JSAddBracesIntention", categories = { - "JavaScript", - "Control Flow" -}, fileExtensions = "js") -public class JSAddBracesIntention extends JSMutablyNamedIntention -{ - - @NonNls - private static final String IF_KEYWORD = "if"; - @NonNls - private static final String ELSE_KEYWORD = "else"; - - @Override - @Nonnull - protected JSElementPredicate getElementPredicate() - { - return new AddBracesPredicate(); - } - - @Override - protected String getTextForElement(PsiElement element) - { - final JSElement parent = (JSElement) element.getParent(); - final String keyword; - - assert (parent != null); - - if(parent instanceof JSIfStatement) - { - final JSIfStatement ifStatement = (JSIfStatement) parent; - final JSStatement elseBranch = ifStatement.getElse(); - - keyword = (element.equals(elseBranch) ? ELSE_KEYWORD : IF_KEYWORD); - } - else - { - final PsiElement firstChild = parent.getFirstChild(); - - assert (firstChild != null); - keyword = firstChild.getText(); - } - - return this.getText(keyword); - } - - @Override - protected void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - if(!(element instanceof JSStatement)) - { - return; - } - final JSStatement statement = (JSStatement) element; - final JSElement parent = (JSElement) element.getParent(); - final String text = element.getText(); - String newText; - - if(parent.getLastChild() instanceof PsiComment) - { - newText = '{' + text + "\n}"; - } - else - { - newText = '{' + text + '}'; - } - JSElementFactory.replaceStatement(statement, newText); - } - - private static class AddBracesPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSStatement)) - { - return false; - } - if(element instanceof JSBlockStatement) - { - return false; - } - - final PsiElement parentElement = element.getParent(); - if(!(parentElement instanceof JSElement)) - { - return false; - } - final JSElement parent = (JSElement) parentElement; - - if(parent instanceof JSIfStatement) - { - final JSIfStatement ifStatement = (JSIfStatement) parent; - - return (!(element instanceof JSIfStatement && - element.equals(ifStatement.getElse()))); - } - - if(parent instanceof JSForStatement || - parent instanceof JSForInStatement - ) - { - return element.equals(((JSLoopStatement) parent).getBody()); - } - - return (parent instanceof JSWhileStatement || - parent instanceof JSDoWhileStatement); - } - } +@IntentionMetaData( + ignoreId = "JSAddBracesIntention", + categories = {"JavaScript", "Control Flow"}, + fileExtensions = "js" +) +public class JSAddBracesIntention extends JSMutablyNamedIntention { + @Override + @Nonnull + protected JSElementPredicate getElementPredicate() { + return new AddBracesPredicate(); + } + + @Nonnull + @Override + protected LocalizeValue getBasicText() { + return JSIntentionLocalize.bracesAdd(); + } + + @Override + @RequiredReadAction + protected LocalizeValue getTextForElement(PsiElement element) { + JSElement parent = (JSElement)element.getParent(); + String keyword; + + assert (parent != null); + + if (parent instanceof JSIfStatement ifStatement) { + JSStatement elseBranch = ifStatement.getElse(); + + keyword = (element.equals(elseBranch) ? "else" : "if"); + } + else { + PsiElement firstChild = parent.getFirstChild(); + + assert (firstChild != null); + keyword = firstChild.getText(); + } + + return JSIntentionLocalize.bracesAddMessage(keyword); + } + + @Override + @RequiredReadAction + protected void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + if (!(element instanceof JSStatement statement)) { + return; + } + JSElement parent = (JSElement)element.getParent(); + String text = element.getText(); + String newText = parent.getLastChild() instanceof PsiComment + ? '{' + text + "\n}" + : '{' + text + '}'; + JSElementFactory.replaceStatement(statement, newText); + } + + private static class AddBracesPredicate implements JSElementPredicate { + @Override + public boolean satisfiedBy(@Nonnull PsiElement element) { + if (!(element instanceof JSStatement) + || element instanceof JSBlockStatement + || !(element.getParent() instanceof JSElement parent)) { + return false; + } + + if (parent instanceof JSIfStatement ifStatement) { + return !(element instanceof JSIfStatement && element.equals(ifStatement.getElse())); + } + + if (parent instanceof JSForStatement || parent instanceof JSForInStatement) { + return element.equals(((JSLoopStatement)parent).getBody()); + } + + return parent instanceof JSWhileStatement || parent instanceof JSDoWhileStatement; + } + } } \ No newline at end of file diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/braces/JSRemoveBracesIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/braces/JSRemoveBracesIntention.java index d4c0ee81..ad0843f9 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/braces/JSRemoveBracesIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/braces/JSRemoveBracesIntention.java @@ -16,132 +16,117 @@ package org.intellij.idea.lang.javascript.intention.braces; import com.intellij.lang.javascript.psi.*; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiComment; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSMutablyNamedIntention; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; -import org.jetbrains.annotations.NonNls; - -import javax.annotation.Nonnull; @ExtensionImpl -@IntentionMetaData(ignoreId = "JSRemoveBracesIntention", categories = { - "JavaScript", - "Control Flow" -}, fileExtensions = "js") -public class JSRemoveBracesIntention extends JSMutablyNamedIntention -{ - @NonNls - private static final String IF_KEYWORD = "if"; - @NonNls - private static final String ELSE_KEYWORD = "else"; - - @Override - @Nonnull - protected JSElementPredicate getElementPredicate() - { - return new RemoveBracesPredicate(); - } - - @Override - protected String getTextForElement(PsiElement element) - { - final JSElement parent = (JSElement) element.getParent(); - final String keyword; - - assert (parent != null); - - if(parent instanceof JSIfStatement) - { - final JSIfStatement ifStatement = (JSIfStatement) parent; - final JSStatement elseBranch = ifStatement.getElse(); - - keyword = (element.equals(elseBranch) ? ELSE_KEYWORD : IF_KEYWORD); - } - else - { - final PsiElement keywordChild = parent.getFirstChild(); - - assert (keywordChild != null); - keyword = keywordChild.getText(); - } - - return this.getText(keyword); - } - - @Override - protected void processIntention(@Nonnull PsiElement element) - throws IncorrectOperationException - { - final JSBlockStatement blockStatement = (JSBlockStatement) element; - final JSStatement[] statements = blockStatement.getStatements(); - final JSStatement statement = statements[0]; - - // handle comments - final JSElement parent = (JSElement) blockStatement.getParent(); - - assert (parent != null); - - final JSElement grandParent = (JSElement) parent.getParent(); - - assert (grandParent != null); - - PsiElement sibling = statement.getFirstChild(); - - assert (sibling != null); - - sibling = sibling.getNextSibling(); - while(sibling != null && !sibling.equals(statement)) - { - if(sibling instanceof PsiComment) - { - grandParent.addBefore(sibling, parent); - } - sibling = sibling.getNextSibling(); - } - - final PsiElement lastChild = blockStatement.getLastChild(); - - if(lastChild instanceof PsiComment) - { - final JSElement nextSibling = (JSElement) parent.getNextSibling(); - - grandParent.addAfter(lastChild, nextSibling); - } - - String text = statement.getText(); - JSElementFactory.replaceStatement(blockStatement, text); - } - - public static class RemoveBracesPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSBlockStatement)) - { - return false; - } - - final JSBlockStatement blockStatement = (JSBlockStatement) element; - final PsiElement parent = blockStatement.getParent(); - - if(!(parent instanceof JSIfStatement || - parent instanceof JSWhileStatement || - parent instanceof JSDoWhileStatement || - parent instanceof JSForStatement || - parent instanceof JSForInStatement)) - { - return false; - } - - final JSStatement[] statements = blockStatement.getStatements(); - - return (statements.length == 1 && !(statements[0] instanceof JSVarStatement)); - } - } +@IntentionMetaData( + ignoreId = "JSRemoveBracesIntention", + categories = {"JavaScript", "Control Flow"}, + fileExtensions = "js" +) +public class JSRemoveBracesIntention extends JSMutablyNamedIntention { + @Nonnull + @Override + protected LocalizeValue getBasicText() { + return JSIntentionLocalize.bracesRemove(); + } + + @Override + @Nonnull + protected JSElementPredicate getElementPredicate() { + return new RemoveBracesPredicate(); + } + + @Override + @RequiredReadAction + protected LocalizeValue getTextForElement(PsiElement element) { + JSElement parent = (JSElement)element.getParent(); + String keyword; + + assert (parent != null); + + if (parent instanceof JSIfStatement ifStatement) { + JSStatement elseBranch = ifStatement.getElse(); + + keyword = element.equals(elseBranch) ? "else" : "if"; + } + else { + PsiElement keywordChild = parent.getFirstChild(); + + assert (keywordChild != null); + keyword = keywordChild.getText(); + } + + return JSIntentionLocalize.bracesRemoveMessage(keyword); + } + + @Override + @RequiredReadAction + protected void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + JSBlockStatement blockStatement = (JSBlockStatement)element; + JSStatement[] statements = blockStatement.getStatements(); + JSStatement statement = statements[0]; + + // handle comments + JSElement parent = (JSElement)blockStatement.getParent(); + + assert (parent != null); + + JSElement grandParent = (JSElement)parent.getParent(); + + assert (grandParent != null); + + PsiElement sibling = statement.getFirstChild(); + + assert (sibling != null); + + sibling = sibling.getNextSibling(); + while (sibling != null && !sibling.equals(statement)) { + if (sibling instanceof PsiComment) { + grandParent.addBefore(sibling, parent); + } + sibling = sibling.getNextSibling(); + } + + PsiElement lastChild = blockStatement.getLastChild(); + + if (lastChild instanceof PsiComment) { + JSElement nextSibling = (JSElement)parent.getNextSibling(); + + grandParent.addAfter(lastChild, nextSibling); + } + + String text = statement.getText(); + JSElementFactory.replaceStatement(blockStatement, text); + } + + public static class RemoveBracesPredicate implements JSElementPredicate { + @Override + public boolean satisfiedBy(@Nonnull PsiElement element) { + if (!(element instanceof JSBlockStatement blockStatement)) { + return false; + } + + PsiElement parent = blockStatement.getParent(); + + return (parent instanceof JSIfStatement || parent instanceof JSWhileStatement || parent instanceof JSDoWhileStatement + || parent instanceof JSForStatement || parent instanceof JSForInStatement) + && isSingleNonVarStatement(blockStatement.getStatements()); + } + + private boolean isSingleNonVarStatement(JSStatement[] statements) { + return statements.length == 1 && !(statements[0] instanceof JSVarStatement); + } + } } \ No newline at end of file diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/comment/JSChangeToCStyleCommentIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/comment/JSChangeToCStyleCommentIntention.java index 55ab6d6f..f81b34c9 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/comment/JSChangeToCStyleCommentIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/comment/JSChangeToCStyleCommentIntention.java @@ -16,128 +16,104 @@ package org.intellij.idea.lang.javascript.intention.comment; import com.intellij.lang.javascript.JSTokenTypes; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; -import consulo.language.ast.IElementType; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiComment; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; import consulo.util.lang.StringUtil; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; -import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.List; @ExtensionImpl -@IntentionMetaData(ignoreId = "JSChangeToCStyleCommentIntention", categories = { - "JavaScript", - "Comments" -}, fileExtensions = "js") -public class JSChangeToCStyleCommentIntention extends JSIntention -{ - - @Override - @Nonnull - protected JSElementPredicate getElementPredicate() - { - return new EndOfLineCommentPredicate(); - } - - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - PsiComment firstComment = (PsiComment) element; - - while(true) - { - final PsiElement prevComment = JSElementFactory.getNonWhiteSpaceSibling(firstComment, false); - - if(!isEndOfLineComment(prevComment)) - { - break; - } - assert (prevComment != null); - firstComment = (PsiComment) prevComment; - } - - final StringBuilder buffer = new StringBuilder(getCommentContents(firstComment)); - final List elementsToDelete = new ArrayList(); - PsiElement nextComment = firstComment; - - while(true) - { - elementsToDelete.add(nextComment); - - nextComment = JSElementFactory.getNonWhiteSpaceSibling(nextComment, true); - if(!isEndOfLineComment(nextComment)) - { - break; - } - assert (nextComment != null); - - final PsiElement prevSibling = nextComment.getPrevSibling(); - - assert (prevSibling != null); - elementsToDelete.add(prevSibling); - - buffer.append(prevSibling.getText()) // White space - .append(getCommentContents((PsiComment) nextComment)); - } - - final String text = StringUtil.replace(buffer.toString(), "*/", "* /"); - final String newCommentString; - - if(text.indexOf('\n') >= 0) - { - newCommentString = "/*\n" + text + "\n*/"; - } - else - { - newCommentString = "/*" + text + "*/"; - } - - JSElementFactory.addElementBefore(firstComment, newCommentString); - for(final PsiElement elementToDelete : elementsToDelete) - { - JSElementFactory.removeElement(elementToDelete); - } - } - - private static boolean isEndOfLineComment(PsiElement element) - { - if(!(element instanceof PsiComment)) - { - return false; - } - - final PsiComment comment = (PsiComment) element; - final IElementType tokenType = comment.getTokenType(); - - return JSTokenTypes.END_OF_LINE_COMMENT.equals(tokenType); - } - - private static String getCommentContents(PsiComment comment) - { - return comment.getText().substring(2); - } - - private static class EndOfLineCommentPredicate implements JSElementPredicate - { - - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof PsiComment)) - { - return false; - } - - final IElementType type = ((PsiComment) element).getTokenType(); - - return JSTokenTypes.END_OF_LINE_COMMENT.equals(type); - } - } +@IntentionMetaData( + ignoreId = "JSChangeToCStyleCommentIntention", + categories = {"JavaScript", "Comments"}, + fileExtensions = "js" +) +public class JSChangeToCStyleCommentIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.commentChangeToCstyleComment(); + } + + @Override + @Nonnull + protected JSElementPredicate getElementPredicate() { + return new EndOfLineCommentPredicate(); + } + + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + PsiComment firstComment = (PsiComment)element; + + while (true) { + PsiElement prevComment = JSElementFactory.getNonWhiteSpaceSibling(firstComment, false); + + if (!isEndOfLineComment(prevComment)) { + break; + } + assert (prevComment != null); + firstComment = (PsiComment)prevComment; + } + + StringBuilder buffer = new StringBuilder(getCommentContents(firstComment)); + List elementsToDelete = new ArrayList<>(); + PsiElement nextComment = firstComment; + + while (true) { + elementsToDelete.add(nextComment); + + nextComment = JSElementFactory.getNonWhiteSpaceSibling(nextComment, true); + if (!isEndOfLineComment(nextComment)) { + break; + } + assert (nextComment != null); + + PsiElement prevSibling = nextComment.getPrevSibling(); + + assert (prevSibling != null); + elementsToDelete.add(prevSibling); + + buffer.append(prevSibling.getText()) // White space + .append(getCommentContents((PsiComment)nextComment)); + } + + String text = StringUtil.replace(buffer.toString(), "*/", "* /"); + String newCommentString = text.indexOf('\n') >= 0 + ? "/*\n" + text + "\n*/" + : "/*" + text + "*/"; + + JSElementFactory.addElementBefore(firstComment, newCommentString); + for (PsiElement elementToDelete : elementsToDelete) { + JSElementFactory.removeElement(elementToDelete); + } + } + + private static boolean isEndOfLineComment(PsiElement element) { + return element instanceof PsiComment comment && JSTokenTypes.END_OF_LINE_COMMENT.equals(comment.getTokenType()); + } + + @RequiredReadAction + private static String getCommentContents(PsiComment comment) { + return comment.getText().substring(2); + } + + private static class EndOfLineCommentPredicate implements JSElementPredicate { + + @Override + public boolean satisfiedBy(@Nonnull PsiElement element) { + return element instanceof PsiComment comment && JSTokenTypes.END_OF_LINE_COMMENT.equals(comment.getTokenType()); + } + } } \ No newline at end of file diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/comment/JSChangeToEndOfLineCommentIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/comment/JSChangeToEndOfLineCommentIntention.java index 74cdce1d..d22df3f6 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/comment/JSChangeToEndOfLineCommentIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/comment/JSChangeToEndOfLineCommentIntention.java @@ -16,136 +16,125 @@ package org.intellij.idea.lang.javascript.intention.comment; import com.intellij.lang.javascript.JSTokenTypes; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.ast.IElementType; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiComment; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiWhiteSpace; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; import org.intellij.idea.lang.javascript.psiutil.TreeUtil; -import javax.annotation.Nonnull; - @ExtensionImpl -@IntentionMetaData(ignoreId = "JSChangeToEndOfLineCommentIntention", categories = { - "JavaScript", - "Comments" -}, fileExtensions = "js") -public class JSChangeToEndOfLineCommentIntention extends JSIntention -{ - @Override - @Nonnull - protected JSElementPredicate getElementPredicate() - { - return new CStyleCommentPredicate(); - } - - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final PsiElement parent = element.getParent(); - - assert (parent != null); - - final String commentText = element.getText(); - final PsiElement whitespace = element.getNextSibling(); - final String text = commentText.substring(2, commentText.length() - 2); - final String[] lines = text.split("\n"); - final String[] newComments = buildCommentStrings(lines); - PsiElement currentElement = element; - - for(int index = newComments.length; --index >= 0; ) - { - if(newComments[index].length() > 0) - { - currentElement = JSElementFactory.addElementBefore(currentElement, "\n"); - currentElement = JSElementFactory.addElementBefore(currentElement, newComments[index]); - } - } - if(whitespace != null) - { - JSElementFactory.removeElement(whitespace); - } - JSElementFactory.removeElement(element); - } - - private static String[] buildCommentStrings(String[] lines) - { - int lastNonEmtpyLine = -1; - - for(int i = lines.length - 1; i >= 0 && lastNonEmtpyLine == -1; i--) - { - final String line = lines[i].trim(); - if(line.length() != 0) - { - lastNonEmtpyLine = i; - } - } - if(lastNonEmtpyLine == -1) - { - return new String[]{"//"}; - } - - final StringBuilder buffer = new StringBuilder(); - final String[] commentStrings = new String[lastNonEmtpyLine + 1]; - - for(int i = 0; i <= lastNonEmtpyLine; i++) - { - final String line = lines[i]; - - if(line.trim().length() != 0) - { - buffer.replace(0, buffer.length(), "//"); - - if(line.startsWith(" *")) - { - buffer.append(line.substring(2)); - } - else if(line.startsWith("*")) - { - buffer.append(line.substring(1)); - } - else - { - buffer.append(line); - } - } - - commentStrings[i] = buffer.toString(); - } - return commentStrings; - } - - private static class CStyleCommentPredicate implements JSElementPredicate - { - - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof PsiComment)) - { - return false; - } - - final PsiComment comment = (PsiComment) element; - final IElementType type = comment.getTokenType(); - - if(!(JSTokenTypes.C_STYLE_COMMENT.equals(type) || JSTokenTypes.C_STYLE_COMMENT.equals(type))) - { - return false; - } - final PsiElement sibling = TreeUtil.getNextLeaf(comment); - if(!(sibling instanceof PsiWhiteSpace)) - { - return false; - } - final String whitespaceText = sibling.getText(); - return (whitespaceText.indexOf((int) '\n') >= 0 || - whitespaceText.indexOf((int) '\r') >= 0); - } - } +@IntentionMetaData( + ignoreId = "JSChangeToEndOfLineCommentIntention", + categories = {"JavaScript", "Comments"}, + fileExtensions = "js" +) +public class JSChangeToEndOfLineCommentIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.commentChangeToEndOfLineComment(); + } + + @Override + @Nonnull + protected JSElementPredicate getElementPredicate() { + return new CStyleCommentPredicate(); + } + + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + PsiElement parent = element.getParent(); + + assert (parent != null); + + String commentText = element.getText(); + PsiElement whitespace = element.getNextSibling(); + String text = commentText.substring(2, commentText.length() - 2); + String[] lines = text.split("\n"); + String[] newComments = buildCommentStrings(lines); + PsiElement currentElement = element; + + for (int index = newComments.length; --index >= 0; ) { + if (newComments[index].length() > 0) { + currentElement = JSElementFactory.addElementBefore(currentElement, "\n"); + currentElement = JSElementFactory.addElementBefore(currentElement, newComments[index]); + } + } + if (whitespace != null) { + JSElementFactory.removeElement(whitespace); + } + JSElementFactory.removeElement(element); + } + + private static String[] buildCommentStrings(String[] lines) { + int lastNonEmtpyLine = -1; + + for (int i = lines.length - 1; i >= 0 && lastNonEmtpyLine == -1; i--) { + String line = lines[i].trim(); + if (!line.isEmpty()) { + lastNonEmtpyLine = i; + } + } + if (lastNonEmtpyLine == -1) { + return new String[]{"//"}; + } + + StringBuilder buffer = new StringBuilder(); + String[] commentStrings = new String[lastNonEmtpyLine + 1]; + + for (int i = 0; i <= lastNonEmtpyLine; i++) { + String line = lines[i]; + + if (line.trim().length() != 0) { + buffer.replace(0, buffer.length(), "//"); + + if (line.startsWith(" *")) { + buffer.append(line.substring(2)); + } + else if (line.startsWith("*")) { + buffer.append(line.substring(1)); + } + else { + buffer.append(line); + } + } + + commentStrings[i] = buffer.toString(); + } + return commentStrings; + } + + private static class CStyleCommentPredicate implements JSElementPredicate { + @Override + @RequiredReadAction + public boolean satisfiedBy(@Nonnull PsiElement element) { + if (!(element instanceof PsiComment)) { + return false; + } + + PsiComment comment = (PsiComment)element; + IElementType type = comment.getTokenType(); + + if (!(JSTokenTypes.C_STYLE_COMMENT.equals(type) || JSTokenTypes.C_STYLE_COMMENT.equals(type))) { + return false; + } + PsiElement sibling = TreeUtil.getNextLeaf(comment); + if (!(sibling instanceof PsiWhiteSpace)) { + return false; + } + String whitespaceText = sibling.getText(); + return whitespaceText.indexOf((int)'\n') >= 0 || whitespaceText.indexOf((int)'\r') >= 0; + } + } } \ No newline at end of file diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/comment/JSMoveCommentToSeparateLineIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/comment/JSMoveCommentToSeparateLineIntention.java index cf989c13..12d0ebf8 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/comment/JSMoveCommentToSeparateLineIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/comment/JSMoveCommentToSeparateLineIntention.java @@ -16,111 +16,102 @@ package org.intellij.idea.lang.javascript.intention.comment; import com.intellij.lang.javascript.JSTokenTypes; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.ast.IElementType; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiComment; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiWhiteSpace; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; import org.intellij.idea.lang.javascript.psiutil.TreeUtil; -import javax.annotation.Nonnull; - @ExtensionImpl -@IntentionMetaData(ignoreId = "JSMoveCommentToSeparateLineIntention", categories = { - "JavaScript", - "Comments" -}, fileExtensions = "js") -public class JSMoveCommentToSeparateLineIntention extends JSIntention -{ - @Override - @Nonnull - protected JSElementPredicate getElementPredicate() - { - return new CommentOnLineWithSourcePredicate(); - } +@IntentionMetaData( + ignoreId = "JSMoveCommentToSeparateLineIntention", + categories = {"JavaScript", "Comments"}, + fileExtensions = "js" +) +public class JSMoveCommentToSeparateLineIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.commentMoveCommentToSeparateLine(); + } - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final PsiComment selectedComment = (PsiComment) element; - PsiElement elementToCheck = selectedComment; - final PsiWhiteSpace whiteSpace; + @Override + @Nonnull + protected JSElementPredicate getElementPredicate() { + return new CommentOnLineWithSourcePredicate(); + } - while(true) - { - elementToCheck = TreeUtil.getPrevLeaf(elementToCheck); - if(elementToCheck == null) - { - return; - } - if(isLineBreakWhiteSpace(elementToCheck)) - { - whiteSpace = (PsiWhiteSpace) elementToCheck; - break; - } - } + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + PsiComment selectedComment = (PsiComment)element; + PsiElement elementToCheck = selectedComment; + PsiWhiteSpace whiteSpace; - PsiElement commentElement = JSElementFactory.addElementBefore(whiteSpace, selectedComment.getText()); - JSElementFactory.addElementBefore(commentElement, "\n"); + while (true) { + elementToCheck = TreeUtil.getPrevLeaf(elementToCheck); + if (elementToCheck == null) { + return; + } + if (isLineBreakWhiteSpace(elementToCheck)) { + whiteSpace = (PsiWhiteSpace)elementToCheck; + break; + } + } - JSElementFactory.removeElement(selectedComment); - } + PsiElement commentElement = JSElementFactory.addElementBefore(whiteSpace, selectedComment.getText()); + JSElementFactory.addElementBefore(commentElement, "\n"); - private static boolean isLineBreakWhiteSpace(PsiElement element) - { - return (element instanceof PsiWhiteSpace && - containsLineBreak(element.getText())); - } + JSElementFactory.removeElement(selectedComment); + } - private static boolean containsLineBreak(String text) - { - return (text.indexOf((int) '\n') >= 0 || - text.indexOf((int) '\r') >= 0); - } + @RequiredReadAction + private static boolean isLineBreakWhiteSpace(PsiElement element) { + return (element instanceof PsiWhiteSpace && containsLineBreak(element.getText())); + } - private static class CommentOnLineWithSourcePredicate implements JSElementPredicate - { + private static boolean containsLineBreak(String text) { + return (text.indexOf((int)'\n') >= 0 || text.indexOf((int)'\r') >= 0); + } - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof PsiComment)) - { - return false; - } - final PsiComment comment = (PsiComment) element; - final IElementType type = comment.getTokenType(); + private static class CommentOnLineWithSourcePredicate implements JSElementPredicate { + @Override + @RequiredReadAction + public boolean satisfiedBy(@Nonnull PsiElement element) { + if (!(element instanceof PsiComment)) { + return false; + } + PsiComment comment = (PsiComment)element; + IElementType type = comment.getTokenType(); - if(!(JSTokenTypes.C_STYLE_COMMENT.equals(type) || - JSTokenTypes.END_OF_LINE_COMMENT.equals(type))) - { - return false; // can't move JSP comments - } + if (!(JSTokenTypes.C_STYLE_COMMENT.equals(type) || JSTokenTypes.END_OF_LINE_COMMENT.equals(type))) { + return false; // can't move JSP comments + } - final PsiElement prevSibling = TreeUtil.getPrevLeaf(element); - if(!(prevSibling instanceof PsiWhiteSpace)) - { - return true; - } - final String prevSiblingText = prevSibling.getText(); - if(prevSiblingText.indexOf('\n') < 0 && - prevSiblingText.indexOf('\r') < 0) - { - return true; - } - final PsiElement nextSibling = TreeUtil.getNextLeaf(element); - if(!(nextSibling instanceof PsiWhiteSpace)) - { - return true; - } - final String nextSiblingText = nextSibling.getText(); - return (nextSiblingText.indexOf('\n') < 0 && - nextSiblingText.indexOf('\r') < 0); - } - } + PsiElement prevSibling = TreeUtil.getPrevLeaf(element); + if (!(prevSibling instanceof PsiWhiteSpace)) { + return true; + } + String prevSiblingText = prevSibling.getText(); + if (prevSiblingText.indexOf('\n') < 0 && prevSiblingText.indexOf('\r') < 0) { + return true; + } + PsiElement nextSibling = TreeUtil.getNextLeaf(element); + if (!(nextSibling instanceof PsiWhiteSpace)) { + return true; + } + String nextSiblingText = nextSibling.getText(); + return (nextSiblingText.indexOf('\n') < 0 && nextSiblingText.indexOf('\r') < 0); + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/conditional/JSFlipConditionalIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/conditional/JSFlipConditionalIntention.java index 1f469c50..0b1b6af9 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/conditional/JSFlipConditionalIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/conditional/JSFlipConditionalIntention.java @@ -18,68 +18,66 @@ import com.intellij.lang.javascript.psi.JSConditionalExpression; import com.intellij.lang.javascript.psi.JSExpression; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.BoolUtils; import org.intellij.idea.lang.javascript.psiutil.ErrorUtil; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; -import javax.annotation.Nonnull; - @ExtensionImpl -@IntentionMetaData(ignoreId = "JSFlipConditionalIntention", categories = { - "JavaScript", - "Conditional" -}, fileExtensions = "js") -public class JSFlipConditionalIntention extends JSIntention -{ - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new FlipConditionalPredicate(); - } +@IntentionMetaData( + ignoreId = "JSFlipConditionalIntention", + categories = {"JavaScript", "Conditional"}, + fileExtensions = "js" +) +public class JSFlipConditionalIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.conditionalFlipConditional(); + } + + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new FlipConditionalPredicate(); + } - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final JSConditionalExpression exp = (JSConditionalExpression) element; - final JSExpression condition = exp.getCondition(); - final JSExpression elseExpression = exp.getElse(); - final JSExpression thenExpression = exp.getThen(); + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + JSConditionalExpression exp = (JSConditionalExpression)element; + JSExpression condition = exp.getCondition(); + JSExpression elseExpression = exp.getElse(); + JSExpression thenExpression = exp.getThen(); - assert (elseExpression != null); - assert (thenExpression != null); + assert (elseExpression != null); + assert (thenExpression != null); - final String newExpression = BoolUtils.getNegatedExpressionText(condition) + '?' + - elseExpression.getText() + ':' + thenExpression.getText(); + String newExpression = BoolUtils.getNegatedExpressionText(condition) + '?' + + elseExpression.getText() + ':' + thenExpression.getText(); - JSElementFactory.replaceExpression(exp, newExpression); - } + JSElementFactory.replaceExpression(exp, newExpression); + } - private static class FlipConditionalPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSConditionalExpression)) - { - return false; - } - if(ErrorUtil.containsError(element)) - { - return false; - } + private static class FlipConditionalPredicate implements JSElementPredicate { + @Override + public boolean satisfiedBy(@Nonnull PsiElement element) { + if (!(element instanceof JSConditionalExpression) || ErrorUtil.containsError(element)) { + return false; + } - final JSConditionalExpression condition = (JSConditionalExpression) element; + JSConditionalExpression condition = (JSConditionalExpression)element; - return (condition.getCondition() != null && - condition.getThen() != null && - condition.getElse() != null); - } - } + return condition.getCondition() != null && condition.getThen() != null && condition.getElse() != null; + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/conditional/JSFlipIfIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/conditional/JSFlipIfIntention.java index f5328854..52f78d4c 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/conditional/JSFlipIfIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/conditional/JSFlipIfIntention.java @@ -19,72 +19,63 @@ import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.JSIfStatement; import com.intellij.lang.javascript.psi.JSStatement; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.BoolUtils; import org.intellij.idea.lang.javascript.psiutil.ErrorUtil; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; -import org.jetbrains.annotations.NonNls; - -import javax.annotation.Nonnull; @ExtensionImpl -@IntentionMetaData(ignoreId = "JSFlipIfIntention", categories = { - "JavaScript", - "Conditional" -}, fileExtensions = "js") -public class JSFlipIfIntention extends JSIntention -{ - - @NonNls - private static final String IF_PREFIX = "if ("; - @NonNls - private static final String ELSE_KEYWORD = "else "; - - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new FlipIfPredicate(); - } - - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final JSIfStatement exp = (JSIfStatement) element; - final JSExpression condition = exp.getCondition(); - final JSStatement thenBranch = exp.getThen(); - final JSStatement elseBranch = exp.getElse(); - final String negatedText = BoolUtils.getNegatedExpressionText(condition); - final boolean emptyThenBranch = (thenBranch == null || - (thenBranch instanceof JSBlockStatement && - ((JSBlockStatement) thenBranch).getStatements().length == 0)); - final String thenText = (emptyThenBranch ? "" : ELSE_KEYWORD + thenBranch.getText()); - final String elseText = ((elseBranch == null) ? "{}" : elseBranch.getText()); +@IntentionMetaData( + ignoreId = "JSFlipIfIntention", + categories = {"JavaScript", "Conditional"}, + fileExtensions = "js" +) +public class JSFlipIfIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.conditionalFlipIf(); + } - final String newStatement = IF_PREFIX + negatedText + ')' + elseText + thenText; + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new FlipIfPredicate(); + } - JSElementFactory.replaceStatement(exp, newStatement); - } + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + JSIfStatement exp = (JSIfStatement)element; + JSExpression condition = exp.getCondition(); + JSStatement thenBranch = exp.getThen(); + JSStatement elseBranch = exp.getElse(); + String negatedText = BoolUtils.getNegatedExpressionText(condition); + boolean emptyThenBranch = + (thenBranch == null || (thenBranch instanceof JSBlockStatement blockStatement && blockStatement.getStatements().length == 0)); + String thenText = emptyThenBranch ? "" : "else " + thenBranch.getText(); + String elseText = elseBranch == null ? "{}" : elseBranch.getText(); - private static class FlipIfPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSIfStatement) || - ErrorUtil.containsError(element)) - { - return false; - } + String newStatement = "if (" + negatedText + ')' + elseText + thenText; - final JSIfStatement condition = (JSIfStatement) element; + JSElementFactory.replaceStatement(exp, newStatement); + } - return (condition.getCondition() != null); - } - } + private static class FlipIfPredicate implements JSElementPredicate { + @Override + public boolean satisfiedBy(@Nonnull PsiElement element) { + return element instanceof JSIfStatement ifStatement + && !ErrorUtil.containsError(ifStatement) + && ifStatement.getCondition() != null; + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/conditional/JSRemoveConditionalIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/conditional/JSRemoveConditionalIntention.java index adc1c69d..9d925cb5 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/conditional/JSRemoveConditionalIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/conditional/JSRemoveConditionalIntention.java @@ -17,10 +17,14 @@ import com.intellij.lang.javascript.psi.JSConditionalExpression; import com.intellij.lang.javascript.psi.JSExpression; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.BoolUtils; @@ -28,70 +32,62 @@ import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; import org.intellij.idea.lang.javascript.psiutil.ParenthesesUtils; -import javax.annotation.Nonnull; - @ExtensionImpl -@IntentionMetaData(ignoreId = "JSRemoveConditionalIntention", categories = { - "JavaScript", - "Conditional" -}, fileExtensions = "js") -public class JSRemoveConditionalIntention extends JSIntention -{ - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new RemoveConditionalPredicate(); - } +@IntentionMetaData( + ignoreId = "JSRemoveConditionalIntention", + categories = {"JavaScript", "Conditional"}, + fileExtensions = "js" +) +public class JSRemoveConditionalIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.conditionalRemoveConditional(); + } - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final JSConditionalExpression exp = (JSConditionalExpression) element; - final JSExpression condition = exp.getCondition(); - final JSExpression thenExpression = exp.getThen(); + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new RemoveConditionalPredicate(); + } - assert (thenExpression != null); + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + JSConditionalExpression exp = (JSConditionalExpression)element; + JSExpression condition = exp.getCondition(); + JSExpression thenExpression = exp.getThen(); - final String thenExpressionText = thenExpression.getText(); - final String newExpression; + assert (thenExpression != null); - newExpression = (thenExpressionText.equals(BoolUtils.TRUE) - ? condition.getText() - : BoolUtils.getNegatedExpressionText(condition)); - JSElementFactory.replaceExpression(exp, newExpression); - } + String thenExpressionText = thenExpression.getText(); + String newExpression; - private static class RemoveConditionalPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSConditionalExpression)) - { - return false; - } - if(ErrorUtil.containsError(element)) - { - return false; - } + newExpression = thenExpressionText.equals(BoolUtils.TRUE) + ? condition.getText() + : BoolUtils.getNegatedExpressionText(condition); + JSElementFactory.replaceExpression(exp, newExpression); + } - final JSConditionalExpression condition = (JSConditionalExpression) element; - final JSExpression thenExpression = ParenthesesUtils.stripParentheses(condition.getThen()); - final JSExpression elseExpression = ParenthesesUtils.stripParentheses(condition.getElse()); + private static class RemoveConditionalPredicate implements JSElementPredicate { + @Override + @RequiredReadAction + public boolean satisfiedBy(@Nonnull PsiElement element) { + if (element instanceof JSConditionalExpression condition && !ErrorUtil.containsError(element)) { + JSExpression thenExpression = ParenthesesUtils.stripParentheses(condition.getThen()); + JSExpression elseExpression = ParenthesesUtils.stripParentheses(condition.getElse()); - if(condition.getCondition() == null || - thenExpression == null || - elseExpression == null) - { - return false; - } + if (condition.getCondition() == null || thenExpression == null || elseExpression == null) { + return false; + } - final String thenText = thenExpression.getText(); - final String elseText = elseExpression.getText(); + String thenText = thenExpression.getText(); + String elseText = elseExpression.getText(); - return ((BoolUtils.TRUE.equals(elseText) && BoolUtils.FALSE.equals(thenText)) || - (BoolUtils.TRUE.equals(thenText) && BoolUtils.FALSE.equals(elseText))); - } - } + return (BoolUtils.TRUE.equals(elseText) && BoolUtils.FALSE.equals(thenText)) + || (BoolUtils.TRUE.equals(thenText) && BoolUtils.FALSE.equals(elseText)); + } + return false; + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/conditional/JSReplaceConditionalWithIfIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/conditional/JSReplaceConditionalWithIfIntention.java index 791f8e95..531ce789 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/conditional/JSReplaceConditionalWithIfIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/conditional/JSReplaceConditionalWithIfIntention.java @@ -17,42 +17,45 @@ import com.intellij.lang.javascript.psi.JSConditionalExpression; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.ConditionalUtils; -import javax.annotation.Nonnull; - @ExtensionImpl -@IntentionMetaData(ignoreId = "JSReplaceConditionalWithIfIntention", categories = { - "JavaScript", - "Conditional" -}, fileExtensions = "js") -public class JSReplaceConditionalWithIfIntention extends JSIntention -{ - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new ReplaceConditionalWithIfPredicate(); - } +@IntentionMetaData( + ignoreId = "JSReplaceConditionalWithIfIntention", + categories = {"JavaScript", "Conditional"}, + fileExtensions = "js" +) +public class JSReplaceConditionalWithIfIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.conditionalReplaceConditionalWithIf(); + } + + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new ReplaceConditionalWithIfPredicate(); + } - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - assert (element instanceof JSConditionalExpression); - ConditionalUtils.replaceConditionalWithIf((JSConditionalExpression) element); - } + @Override + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + assert (element instanceof JSConditionalExpression); + ConditionalUtils.replaceConditionalWithIf((JSConditionalExpression)element); + } - private static class ReplaceConditionalWithIfPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - return (element instanceof JSConditionalExpression); - } - } + private static class ReplaceConditionalWithIfPredicate implements JSElementPredicate { + @Override + public boolean satisfiedBy(@Nonnull PsiElement element) { + return (element instanceof JSConditionalExpression); + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/constant/JSConstantExpressionIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/constant/JSConstantExpressionIntention.java index fd9b4594..4a3f7540 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/constant/JSConstantExpressionIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/constant/JSConstantExpressionIntention.java @@ -20,91 +20,67 @@ import com.intellij.lang.javascript.psi.JSLiteralExpression; import com.intellij.lang.javascript.psi.JSReferenceExpression; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; import consulo.util.lang.StringUtil; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.ErrorUtil; import org.intellij.idea.lang.javascript.psiutil.ExpressionUtil; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; -import javax.annotation.Nonnull; - @ExtensionImpl -@IntentionMetaData(ignoreId = "JSConstantExpressionIntention", categories = { - "JavaScript", - "Other" -}, fileExtensions = "js") -public class JSConstantExpressionIntention extends JSIntention -{ - @Override - @Nonnull - protected JSElementPredicate getElementPredicate() - { - return new ConstantExpressionPredicate(); - } - - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final JSExpression expression = (JSExpression) element; - final Object value = ExpressionUtil.computeConstantExpression(expression); - final String newExpression; +@IntentionMetaData( + ignoreId = "JSConstantExpressionIntention", + categories = {"JavaScript", "Other"}, + fileExtensions = "js" +) +public class JSConstantExpressionIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.constantComputeExpression(); + } - if(value instanceof String) - { - newExpression = '"' + StringUtil.escapeStringCharacters((String) value) + '"'; - } - else - { - newExpression = String.valueOf(value); - } - JSElementFactory.replaceExpression(expression, newExpression); - } + @Override + @Nonnull + protected JSElementPredicate getElementPredicate() { + return new ConstantExpressionPredicate(); + } - private static class ConstantExpressionPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSExpression)) - { - return false; - } - if(ErrorUtil.containsError(element)) - { - return false; - } - final JSExpression expression = (JSExpression) element; + @Override + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + JSExpression expression = (JSExpression)element; + Object value = ExpressionUtil.computeConstantExpression(expression); + String newExpression = value instanceof String strValue + ? '"' + StringUtil.escapeStringCharacters(strValue) + '"' + : String.valueOf(value); + JSElementFactory.replaceExpression(expression, newExpression); + } - if(element instanceof JSLiteralExpression || - (element instanceof JSReferenceExpression && - ((JSReferenceExpression) element).getQualifier() != null - ) || - expression instanceof JSCallExpression - ) - { - return false; - } - if(!ExpressionUtil.isConstantExpression(expression)) - { - return false; - } + private static class ConstantExpressionPredicate implements JSElementPredicate { + @Override + public boolean satisfiedBy(@Nonnull PsiElement element) { + if (!(element instanceof JSExpression) || ErrorUtil.containsError(element)) { + return false; + } + JSExpression expression = (JSExpression)element; - if(ExpressionUtil.computeConstantExpression(expression) == null) - { - return false; - } + if (element instanceof JSLiteralExpression + || (element instanceof JSReferenceExpression referenceExpression && referenceExpression.getQualifier() != null) + || expression instanceof JSCallExpression + || !ExpressionUtil.isConstantExpression(expression) + || ExpressionUtil.computeConstantExpression(expression) == null) { + return false; + } - final PsiElement parent = element.getParent(); + PsiElement parent = element.getParent(); - if(!(parent instanceof JSExpression)) - { - return true; - } - return (!ExpressionUtil.isConstantExpression((JSExpression) parent)); - } - } + return !(parent instanceof JSExpression parentExpression && ExpressionUtil.isConstantExpression(parentExpression)); + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/constant/JSConstantSubexpressionIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/constant/JSConstantSubexpressionIntention.java index 5ff7d4ea..c98c59ea 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/constant/JSConstantSubexpressionIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/constant/JSConstantSubexpressionIntention.java @@ -19,12 +19,17 @@ import com.intellij.lang.javascript.psi.JSElement; import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.impl.JSChangeUtil; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.ast.IElementType; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; import consulo.util.lang.StringUtil; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSMutablyNamedIntention; import org.intellij.idea.lang.javascript.psiutil.BinaryOperatorUtils; @@ -32,202 +37,161 @@ import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; import org.intellij.idea.lang.javascript.psiutil.ParenthesesUtils; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - @ExtensionImpl -@IntentionMetaData(ignoreId = "JSConstantSubexpressionIntention", categories = { - "JavaScript", - "Other" -}, fileExtensions = "js") -public class JSConstantSubexpressionIntention extends JSMutablyNamedIntention -{ - @Override - @Nonnull - protected JSElementPredicate getElementPredicate() - { - return new ConstantSubexpressionPredicate(); - } - - @Override - protected String getTextForElement(PsiElement element) - { - final PsiElement parent = element.getParent(); - final JSBinaryExpression binaryExpression = (JSBinaryExpression) (parent instanceof JSBinaryExpression ? parent : element); - final JSExpression lhs = binaryExpression.getLOperand(); - final JSExpression leftSide; - - if(lhs instanceof JSBinaryExpression) - { - leftSide = ((JSBinaryExpression) lhs).getROperand(); - } - else - { - leftSide = lhs; - } - final IElementType operationSign = binaryExpression.getOperationSign(); - final JSExpression rhs = binaryExpression.getROperand(); - - assert (rhs != null); - assert (leftSide != null); - - return this.getText(leftSide.getText(), BinaryOperatorUtils.getOperatorText(operationSign), rhs.getText()); - } - - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final PsiElement parent = element.getParent(); - final JSExpression expression = (JSExpression) (parent instanceof JSBinaryExpression ? parent : element); - String newExpression = ""; - final Object constantValue; - - if(expression instanceof JSBinaryExpression) - { - final JSBinaryExpression binaryExpression = (JSBinaryExpression) expression; - final JSExpression lhs = binaryExpression.getLOperand(); - - if(lhs instanceof JSBinaryExpression) - { - final JSBinaryExpression lhsBinaryExpression = (JSBinaryExpression) lhs; - final JSExpression rightSide = lhsBinaryExpression.getROperand(); - - newExpression += getLeftSideText(lhsBinaryExpression); - - assert (rightSide != null); - } - constantValue = ExpressionUtil.computeConstantExpression(getSubexpression(binaryExpression)); - } - else - { - constantValue = ExpressionUtil.computeConstantExpression(expression); - } - - if(constantValue instanceof String) - { - newExpression += '"' + StringUtil.escapeStringCharacters(constantValue.toString()) + '"'; - } - else - { - newExpression += String.valueOf(constantValue); - } - JSElementFactory.replaceExpression(expression, newExpression); - } - - private static String getLeftSideText(JSBinaryExpression binaryExpression) - { - return binaryExpression.getLOperand().getText() + - BinaryOperatorUtils.getOperatorText(binaryExpression.getOperationSign()); - } - - /** - * Returns the smallest subexpression (if precendence allows it). For instance: - * variable + 2 + 3 normally gets evaluated left to right -> (variable + 2) - * + 3 this method returns the right most legal subexpression -> 2 + 3 - * - * @param expression the expression to analyse - * @return the found common sub-expression if found, or null otherwise. - */ - @Nullable - private static JSBinaryExpression getSubexpression(JSBinaryExpression expression) - { - final JSExpression rhs = expression.getROperand(); - final IElementType sign = expression.getOperationSign(); - final int parentPrecendence = ParenthesesUtils.getPrecendence(expression); - - if(rhs == null) - { - return null; - } - - final JSExpression lhs = expression.getLOperand(); - - if(!(lhs instanceof JSBinaryExpression)) - { - return expression; - } - - final JSBinaryExpression lhsBinaryExpression = (JSBinaryExpression) lhs; - final int childPrecendence = ParenthesesUtils.getPrecendence(lhsBinaryExpression); - final JSExpression leftSide = lhsBinaryExpression.getROperand(); - - if(leftSide == null) - { - return null; - } - - if(parentPrecendence > childPrecendence) - { - return null; - } - - try - { - final String subExpressionText = leftSide.getText() + BinaryOperatorUtils.getOperatorText(sign) + - rhs.getText(); - final JSExpression subExpression = JSChangeUtil.createExpressionFromText(expression.getProject(), - subExpressionText); - - return (JSBinaryExpression) subExpression; - } - catch(Throwable ignore) - { - return null; - } - } - - private static class ConstantSubexpressionPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSElement || - element.getPrevSibling() instanceof JSElement)) - { - return false; - } - - PsiElement parent = element.getParent(); - - if(!(parent instanceof JSBinaryExpression)) - { - if(element instanceof JSBinaryExpression && - ((JSBinaryExpression) element).getLOperand() instanceof JSBinaryExpression) - { - parent = element; - } - else - { - return false; - } - } - final JSBinaryExpression binaryExpression = (JSBinaryExpression) parent; - - final JSBinaryExpression subexpression = getSubexpression(binaryExpression); - if(subexpression == null) - { - return false; - } - if(binaryExpression.equals(subexpression) && - !isPartOfConstantExpression(binaryExpression)) - { - // handled by JSConstantExpressionIntention - return false; - } - if(!ExpressionUtil.isConstantExpression(subexpression)) - { - return false; - } - - return (ExpressionUtil.computeConstantExpression(subexpression) != null); - } - - private static boolean isPartOfConstantExpression(JSBinaryExpression binaryExpression) - { - final PsiElement containingElement = binaryExpression.getParent(); - - return (containingElement instanceof JSExpression && - ExpressionUtil.isConstantExpression((JSExpression) containingElement)); - } - } +@IntentionMetaData( + ignoreId = "JSConstantSubexpressionIntention", + categories = {"JavaScript", "Other"}, + fileExtensions = "js" +) +public class JSConstantSubexpressionIntention extends JSMutablyNamedIntention { + @Override + @Nonnull + protected JSElementPredicate getElementPredicate() { + return new ConstantSubexpressionPredicate(); + } + + @Nonnull + @Override + protected LocalizeValue getBasicText() { + return JSIntentionLocalize.constantComputeSubexpression(); + } + + @Override + @RequiredReadAction + protected LocalizeValue getTextForElement(PsiElement element) { + PsiElement parent = element.getParent(); + JSBinaryExpression binaryExpression = (JSBinaryExpression)(parent instanceof JSBinaryExpression ? parent : element); + JSExpression lhs = binaryExpression.getLOperand(); + JSExpression leftSide = lhs instanceof JSBinaryExpression lhsBinaryExpression ? lhsBinaryExpression.getROperand() : lhs; + IElementType operationSign = binaryExpression.getOperationSign(); + JSExpression rhs = binaryExpression.getROperand(); + + assert (rhs != null); + assert (leftSide != null); + + return JSIntentionLocalize.constantComputeSubexpressionMessage( + leftSide.getText(), + BinaryOperatorUtils.getOperatorText(operationSign), + rhs.getText() + ); + } + + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + PsiElement parent = element.getParent(); + JSExpression expression = (JSExpression)(parent instanceof JSBinaryExpression ? parent : element); + String newExpression = ""; + Object constantValue; + + if (expression instanceof JSBinaryExpression) { + JSBinaryExpression binaryExpression = (JSBinaryExpression)expression; + JSExpression lhs = binaryExpression.getLOperand(); + + if (lhs instanceof JSBinaryExpression lhsBinaryExpression) { + JSExpression rightSide = lhsBinaryExpression.getROperand(); + + newExpression += getLeftSideText(lhsBinaryExpression); + + assert (rightSide != null); + } + constantValue = ExpressionUtil.computeConstantExpression(getSubexpression(binaryExpression)); + } + else { + constantValue = ExpressionUtil.computeConstantExpression(expression); + } + + newExpression += constantValue instanceof String strValue + ? '"' + StringUtil.escapeStringCharacters(strValue) + '"' + : String.valueOf(constantValue); + JSElementFactory.replaceExpression(expression, newExpression); + } + + @RequiredReadAction + private static String getLeftSideText(JSBinaryExpression binaryExpression) { + return binaryExpression.getLOperand().getText() + + BinaryOperatorUtils.getOperatorText(binaryExpression.getOperationSign()); + } + + /** + * Returns the smallest subexpression (if precendence allows it). For instance: + * variable + 2 + 3 normally gets evaluated left to right -> (variable + 2) + * + 3 this method returns the right most legal subexpression -> 2 + 3 + * + * @param expression the expression to analyse + * @return the found common sub-expression if found, or null otherwise. + */ + @Nullable + @RequiredReadAction + private static JSBinaryExpression getSubexpression(JSBinaryExpression expression) { + JSExpression rhs = expression.getROperand(); + IElementType sign = expression.getOperationSign(); + int parentPrecendence = ParenthesesUtils.getPrecendence(expression); + + if (rhs == null) { + return null; + } + + JSExpression lhs = expression.getLOperand(); + + if (!(lhs instanceof JSBinaryExpression)) { + return expression; + } + + JSBinaryExpression lhsBinaryExpression = (JSBinaryExpression)lhs; + int childPrecendence = ParenthesesUtils.getPrecendence(lhsBinaryExpression); + JSExpression leftSide = lhsBinaryExpression.getROperand(); + + if (leftSide == null || parentPrecendence > childPrecendence) { + return null; + } + + try { + String subExpressionText = leftSide.getText() + BinaryOperatorUtils.getOperatorText(sign) + rhs.getText(); + return (JSBinaryExpression)JSChangeUtil.createExpressionFromText(expression.getProject(), subExpressionText); + } + catch (Throwable ignore) { + return null; + } + } + + private static class ConstantSubexpressionPredicate implements JSElementPredicate { + @Override + @RequiredReadAction + public boolean satisfiedBy(@Nonnull PsiElement element) { + if (!(element instanceof JSElement || element.getPrevSibling() instanceof JSElement)) { + return false; + } + + PsiElement parent = element.getParent(); + + if (!(parent instanceof JSBinaryExpression)) { + if (element instanceof JSBinaryExpression binaryExpression + && binaryExpression.getLOperand() instanceof JSBinaryExpression) { + parent = element; + } + else { + return false; + } + } + JSBinaryExpression binaryExpression = (JSBinaryExpression)parent; + + JSBinaryExpression subexpression = getSubexpression(binaryExpression); + if (subexpression == null) { + return false; + } + if (binaryExpression.equals(subexpression) && !isPartOfConstantExpression(binaryExpression)) { + // handled by JSConstantExpressionIntention + return false; + } + return ExpressionUtil.isConstantExpression(subexpression) + && ExpressionUtil.computeConstantExpression(subexpression) != null; + } + + private static boolean isPartOfConstantExpression(JSBinaryExpression binaryExpression) { + PsiElement containingElement = binaryExpression.getParent(); + + return containingElement instanceof JSExpression expression && ExpressionUtil.isConstantExpression(expression); + } + } } \ No newline at end of file diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/increment/JSExtractIncrementIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/increment/JSExtractIncrementIntention.java index 14ee6f5e..73faa4da 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/increment/JSExtractIncrementIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/increment/JSExtractIncrementIntention.java @@ -16,95 +16,87 @@ package org.intellij.idea.lang.javascript.intention.increment; import com.intellij.lang.javascript.psi.*; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.ast.IElementType; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSMutablyNamedIntention; import org.intellij.idea.lang.javascript.psiutil.*; -import javax.annotation.Nonnull; - @ExtensionImpl -@IntentionMetaData(ignoreId = "JSExtractIncrementIntention", categories = { - "JavaScript", - "Other" -}, fileExtensions = "js") -public class JSExtractIncrementIntention extends JSMutablyNamedIntention -{ - @Override - public String getTextForElement(PsiElement element) - { - return this.getText(BinaryOperatorUtils.getOperatorText(getOperationSign(element))); - } - - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new ExtractIncrementPredicate(); - } +@IntentionMetaData( + ignoreId = "JSExtractIncrementIntention", + categories = {"JavaScript", "Other"}, + fileExtensions = "js" +) +public class JSExtractIncrementIntention extends JSMutablyNamedIntention { + @Override + @Nonnull + protected LocalizeValue getBasicText() { + return JSIntentionLocalize.incrementExtract(); + } - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final boolean isPostfix = (element instanceof JSPostfixExpression); - final JSExpression operand = (isPostfix ? ((JSPostfixExpression) element).getExpression() - : ((JSPrefixExpression) element).getExpression()); - final JSStatement statement = TreeUtil.getParentOfType(element, JSStatement.class); + @Override + @RequiredReadAction + public LocalizeValue getTextForElement(PsiElement element) { + return JSIntentionLocalize.incrementExtractMessage(BinaryOperatorUtils.getOperatorText(getOperationSign(element))); + } - assert (statement != null); + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new ExtractIncrementPredicate(); + } - if(isPostfix) - { - JSElementFactory.addStatementAfter(statement, element.getText() + ';'); - } - else - { - JSElementFactory.addStatementBefore(statement, element.getText() + ';'); - } - JSElementFactory.replaceExpression((JSExpression) element, operand.getText()); - } + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + boolean isPostfix = (element instanceof JSPostfixExpression); + JSExpression operand = isPostfix + ? ((JSPostfixExpression)element).getExpression() + : ((JSPrefixExpression)element).getExpression(); + JSStatement statement = TreeUtil.getParentOfType(element, JSStatement.class); - private static IElementType getOperationSign(PsiElement element) - { - return ((element instanceof JSPostfixExpression) - ? ((JSPostfixExpression) element).getOperationSign() - : ((JSPrefixExpression) element).getOperationSign()); - } + assert (statement != null); - private static class ExtractIncrementPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!ExpressionUtil.isIncrementDecrementExpression(element)) - { - return false; - } - if(ErrorUtil.containsError(element)) - { - return false; - } + if (isPostfix) { + JSElementFactory.addStatementAfter(statement, element.getText() + ';'); + } + else { + JSElementFactory.addStatementBefore(statement, element.getText() + ';'); + } + JSElementFactory.replaceExpression((JSExpression)element, operand.getText()); + } - final PsiElement parent = element.getParent(); + @RequiredReadAction + private static IElementType getOperationSign(PsiElement element) { + return element instanceof JSPostfixExpression postfixExpression + ? postfixExpression.getOperationSign() + : ((JSPrefixExpression)element).getOperationSign(); + } - if(parent instanceof JSExpressionStatement) - { - return false; - } + private static class ExtractIncrementPredicate implements JSElementPredicate { + @Override + public boolean satisfiedBy(@Nonnull PsiElement element) { + if (!ExpressionUtil.isIncrementDecrementExpression(element) + || ErrorUtil.containsError(element) + || element.getParent() instanceof JSExpressionStatement) { + return false; + } - final JSStatement containingStatement = TreeUtil.getParentOfType(element, JSStatement.class); + JSStatement containingStatement = TreeUtil.getParentOfType(element, JSStatement.class); - if(element instanceof JSPostfixExpression && - (containingStatement instanceof JSReturnStatement || - containingStatement instanceof JSThrowStatement)) - { - return false; - } - return (containingStatement != null); - } - } + if (element instanceof JSPostfixExpression + && (containingStatement instanceof JSReturnStatement || containingStatement instanceof JSThrowStatement)) { + return false; + } + return (containingStatement != null); + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/initialization/JSMergeDeclarationAndInitializationIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/initialization/JSMergeDeclarationAndInitializationIntention.java index 1fdd0063..405df98c 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/initialization/JSMergeDeclarationAndInitializationIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/initialization/JSMergeDeclarationAndInitializationIntention.java @@ -16,120 +16,108 @@ package org.intellij.idea.lang.javascript.intention.initialization; import com.intellij.lang.javascript.psi.*; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.ErrorUtil; import org.intellij.idea.lang.javascript.psiutil.FindReferenceUtil; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; -import org.jetbrains.annotations.NonNls; -import javax.annotation.Nonnull; import java.util.Iterator; @ExtensionImpl -@IntentionMetaData(ignoreId = "JSMergeDeclarationAndInitializationIntention", categories = { - "JavaScript", - "Declaration" -}, fileExtensions = "js") -public class JSMergeDeclarationAndInitializationIntention extends JSIntention -{ - @NonNls - private static final String JS_VAR_PREFIX = "var "; +@IntentionMetaData( + ignoreId = "JSMergeDeclarationAndInitializationIntention", + categories = {"JavaScript", "Declaration"}, + fileExtensions = "js" +) +public class JSMergeDeclarationAndInitializationIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.initializationMergeDeclarationAndInitialization(); + } - @Override - @Nonnull - protected JSElementPredicate getElementPredicate() - { - return new Predicate(); - } + @Override + @Nonnull + protected JSElementPredicate getElementPredicate() { + return new Predicate(); + } - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - assert (element instanceof JSVarStatement); + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + assert (element instanceof JSVarStatement); - final JSVarStatement varStatement = (JSVarStatement) element; - StringBuilder declarationBuffer = new StringBuilder(); + JSVarStatement varStatement = (JSVarStatement)element; + StringBuilder declarationBuffer = new StringBuilder(); - for(final JSVariable variable : varStatement.getVariables()) - { - if(variable.hasInitializer()) - { - declarationBuffer.append((declarationBuffer.length() == 0) ? JS_VAR_PREFIX : ", ") - .append(variable.getName()) - .append(" = ") - .append(variable.getInitializer().getText()); - } - else - { - final Iterator referenceIterator = FindReferenceUtil.getReferencesAfter(variable, variable.getTextRange().getEndOffset()).iterator(); - final JSReferenceExpression firstReference = (JSReferenceExpression) (referenceIterator.hasNext() ? referenceIterator.next() : null); - // final JSReferenceExpression firstReference = FindReferenceUtil.findFirstReference(variable); + for (JSVariable variable : varStatement.getVariables()) { + if (variable.hasInitializer()) { + declarationBuffer.append(declarationBuffer.isEmpty() ? "var " : ", ") + .append(variable.getName()).append(" = ").append(variable.getInitializer().getText()); + } + else { + Iterator referenceIterator = + FindReferenceUtil.getReferencesAfter(variable, variable.getTextRange().getEndOffset()).iterator(); + JSReferenceExpression firstReference = + (JSReferenceExpression)(referenceIterator.hasNext() ? referenceIterator.next() : null); + //final JSReferenceExpression firstReference = FindReferenceUtil.findFirstReference(variable); - if(firstReference != null && - firstReference.getParent() instanceof JSDefinitionExpression) - { - final JSExpressionStatement assignmentStatement = (JSExpressionStatement) firstReference.getParent().getParent().getParent(); + if (firstReference != null && firstReference.getParent() instanceof JSDefinitionExpression definitionExpression) { + JSExpressionStatement assignmentStatement = (JSExpressionStatement)definitionExpression.getParent().getParent(); - // Replace assignment statement by var statement. - JSElementFactory.replaceStatement(assignmentStatement, JS_VAR_PREFIX + assignmentStatement.getText()); - } - else - { - declarationBuffer.append((declarationBuffer.length() == 0) ? JS_VAR_PREFIX : ", ") - .append(variable.getName()); - } - } - } + // Replace assignment statement by var statement. + JSElementFactory.replaceStatement(assignmentStatement, "var " + assignmentStatement.getText()); + } + else { + declarationBuffer.append((declarationBuffer.length() == 0) ? "var " : ", ") + .append(variable.getName()); + } + } + } - // Do replacement. - if(declarationBuffer.length() == 0) - { - JSElementFactory.removeElement(varStatement); - } - else - { - declarationBuffer.append(';'); - JSElementFactory.replaceStatement(varStatement, declarationBuffer.toString()); - } - } + // Do replacement. + if (declarationBuffer.length() == 0) { + JSElementFactory.removeElement(varStatement); + } + else { + declarationBuffer.append(';'); + JSElementFactory.replaceStatement(varStatement, declarationBuffer.toString()); + } + } - private static class Predicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSVarStatement)) - { - return false; - } - final JSVarStatement varStatement = (JSVarStatement) element; - if(ErrorUtil.containsError(varStatement)) - { - return false; - } + private static class Predicate implements JSElementPredicate { + @Override + @RequiredReadAction + public boolean satisfiedBy(@Nonnull PsiElement element) { + if (element instanceof JSVarStatement varStatement && !ErrorUtil.containsError(varStatement)) { + for (JSVariable variable : varStatement.getVariables()) { + if (variable.hasInitializer()) { + continue; + } - for(JSVariable variable : varStatement.getVariables()) - { - if(!variable.hasInitializer()) - { - final Iterator referenceIterator = FindReferenceUtil.getReferencesAfter(variable, variable.getTextRange().getEndOffset()).iterator(); - final JSReferenceExpression firstReference = (JSReferenceExpression) (referenceIterator.hasNext() ? referenceIterator.next() : null); + Iterator referenceIterator = + FindReferenceUtil.getReferencesAfter(variable, variable.getTextRange().getEndOffset()).iterator(); + JSReferenceExpression firstReference = + (JSReferenceExpression)(referenceIterator.hasNext() ? referenceIterator.next() : null); - if(firstReference != null && - firstReference.getParent() instanceof JSDefinitionExpression && - firstReference.getParent().getParent() instanceof JSAssignmentExpression && - firstReference.getParent().getParent().getParent() instanceof JSExpressionStatement) - { - return true; - } - } - } - return false; - } - } + if (firstReference != null + && firstReference.getParent() instanceof JSDefinitionExpression definitionExpression + && definitionExpression.getParent() instanceof JSAssignmentExpression assignmentExpression + && assignmentExpression.getParent() instanceof JSExpressionStatement) { + return true; + } + } + } + return false; + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/initialization/JSSplitDeclarationAndInitializationIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/initialization/JSSplitDeclarationAndInitializationIntention.java index 69c311cd..a6094183 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/initialization/JSSplitDeclarationAndInitializationIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/initialization/JSSplitDeclarationAndInitializationIntention.java @@ -19,109 +19,106 @@ import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.impl.JSPsiImplUtils; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiFile; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.ErrorUtil; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; import org.jetbrains.annotations.NonNls; -import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.List; @ExtensionImpl -@IntentionMetaData(ignoreId = "JSSplitDeclarationAndInitializationIntention", categories = { - "JavaScript", - "Declaration" -}, fileExtensions = "js") -public class JSSplitDeclarationAndInitializationIntention extends JSIntention -{ - @NonNls - private static final String VAR_KEYWORD = "var "; - - @Override - @Nonnull - protected JSElementPredicate getElementPredicate() - { - return new Predicate(); - } - - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - assert (element instanceof JSVarStatement); - - final JSVarStatement varStatement = (JSVarStatement) element; - StringBuilder declarationBuffer = new StringBuilder(); - List initializations = new ArrayList(); - - for(JSVariable variable : varStatement.getVariables()) - { - declarationBuffer.append((declarationBuffer.length() == 0) ? VAR_KEYWORD : ",") - .append(variable.getName()); - - String s = JSPsiImplUtils.getTypeFromDeclaration(variable); - final PsiFile containingFile = element.getContainingFile(); - - if(s == null && containingFile.getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4) - { - s = JSResolveUtil.getExpressionType(variable.getInitializer(), containingFile); - } - - if(s != null) - { - declarationBuffer.append(":").append(s); - } - if(variable.hasInitializer()) - { - initializations.add(variable.getName() + '=' + variable.getInitializer().getText() + ';'); - } - } - declarationBuffer.append(';'); - - // Do replacement. - JSStatement newStatement = JSElementFactory.replaceStatement(varStatement, declarationBuffer.toString()); - - for(final String initialization : initializations) - { - newStatement = JSElementFactory.addStatementAfter(newStatement, initialization); - } - } - - private static class Predicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - PsiElement elementParent; - - if(!(element instanceof JSVarStatement) || - (elementParent = element.getParent()) instanceof JSForStatement || - elementParent instanceof JSClass - ) - { - return false; - } - - final JSVarStatement varStatement = (JSVarStatement) element; - if(ErrorUtil.containsError(varStatement)) - { - return false; - } - - for(JSVariable variable : varStatement.getVariables()) - { - if(variable.hasInitializer()) - { - return true; - } - } - return false; - } - } +@IntentionMetaData( + ignoreId = "JSSplitDeclarationAndInitializationIntention", + categories = {"JavaScript", "Declaration"}, + fileExtensions = "js" +) +public class JSSplitDeclarationAndInitializationIntention extends JSIntention { + @NonNls + private static final String VAR_KEYWORD = "var "; + + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.initializationSplitDeclarationAndInitialization(); + } + + @Override + @Nonnull + protected JSElementPredicate getElementPredicate() { + return new Predicate(); + } + + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + assert (element instanceof JSVarStatement); + + JSVarStatement varStatement = (JSVarStatement)element; + StringBuilder declarationBuffer = new StringBuilder(); + List initializations = new ArrayList<>(); + + for (JSVariable variable : varStatement.getVariables()) { + declarationBuffer.append(declarationBuffer.isEmpty() ? VAR_KEYWORD : ",") + .append(variable.getName()); + + String s = JSPsiImplUtils.getTypeFromDeclaration(variable); + PsiFile containingFile = element.getContainingFile(); + + if (s == null && containingFile.getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4) { + s = JSResolveUtil.getExpressionType(variable.getInitializer(), containingFile); + } + + if (s != null) { + declarationBuffer.append(":").append(s); + } + if (variable.hasInitializer()) { + initializations.add(variable.getName() + '=' + variable.getInitializer().getText() + ';'); + } + } + declarationBuffer.append(';'); + + // Do replacement. + JSStatement newStatement = JSElementFactory.replaceStatement(varStatement, declarationBuffer.toString()); + + for (String initialization : initializations) { + newStatement = JSElementFactory.addStatementAfter(newStatement, initialization); + } + } + + private static class Predicate implements JSElementPredicate { + @Override + public boolean satisfiedBy(@Nonnull PsiElement element) { + PsiElement elementParent; + + if (!(element instanceof JSVarStatement) + || (elementParent = element.getParent()) instanceof JSForStatement || + elementParent instanceof JSClass + ) { + return false; + } + + JSVarStatement varStatement = (JSVarStatement)element; + if (ErrorUtil.containsError(varStatement)) { + return false; + } + + for (JSVariable variable : varStatement.getVariables()) { + if (variable.hasInitializer()) { + return true; + } + } + return false; + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/loop/JSMergeParallelForInLoopsIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/loop/JSMergeParallelForInLoopsIntention.java index 4100a103..bb50ad48 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/loop/JSMergeParallelForInLoopsIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/loop/JSMergeParallelForInLoopsIntention.java @@ -20,190 +20,153 @@ import com.intellij.lang.javascript.psi.JSForInStatement; import com.intellij.lang.javascript.psi.JSStatement; import com.intellij.lang.javascript.psi.JSVarStatement; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.ast.ASTNode; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.ControlFlowUtils; import org.intellij.idea.lang.javascript.psiutil.EquivalenceChecker; import org.intellij.idea.lang.javascript.psiutil.ErrorUtil; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; -import org.jetbrains.annotations.NonNls; - -import javax.annotation.Nonnull; @ExtensionImpl -@IntentionMetaData(ignoreId = "JSMergeParallelForInLoopsIntention", categories = { - "JavaScript", - "Control Flow" -}, fileExtensions = "js") -public class JSMergeParallelForInLoopsIntention extends JSIntention -{ - - @NonNls - private static final String FOR_IN_PREFIX = "for ("; - @NonNls - private static final String FOR_IN_COLLECTION_PREFIX = " in "; - - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new MergeParallelForInLoopsPredicate(); - } - - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final PsiElement nextElement = JSElementFactory.getNonWhiteSpaceSibling(element, true); - - assert (nextElement != null); - - final JSForInStatement firstStatement = (JSForInStatement) element; - final JSForInStatement secondStatement = (JSForInStatement) nextElement; - final StringBuilder statementBuffer = new StringBuilder(); - - this.mergeForInStatements(statementBuffer, firstStatement, secondStatement); - JSElementFactory.replaceStatement(firstStatement, statementBuffer.toString()); - JSElementFactory.removeElement(secondStatement); - } - - private void mergeForInStatements(StringBuilder statementBuffer, - JSForInStatement firstStatement, - JSForInStatement secondStatement) - { - final JSExpression variableExpression = getVariableExpression(firstStatement); - final JSVarStatement declaration = firstStatement.getDeclarationStatement(); - final JSExpression collectionExpression = getCollectionExpression(firstStatement); - final JSStatement firstBody = firstStatement.getBody(); - final JSStatement secondBody = secondStatement.getBody(); - - statementBuffer.append(FOR_IN_PREFIX) - .append((declaration == null) ? variableExpression.getText() : declaration.getText()) - .append(FOR_IN_COLLECTION_PREFIX) - .append(collectionExpression.getText()) - .append(')'); - ControlFlowUtils.appendStatementsInSequence(statementBuffer, firstBody, secondBody); - } - - private static class MergeParallelForInLoopsPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSForInStatement) || ErrorUtil.containsError(element)) - { - return false; - } - - final PsiElement nextStatement = JSElementFactory.getNonWhiteSpaceSibling(element, true); - - if(!(nextStatement instanceof JSForInStatement) || - ErrorUtil.containsError(nextStatement)) - { - return false; - } - - return forInStatementsCanBeMerged((JSForInStatement) element, - (JSForInStatement) nextStatement); - } - - public static boolean forInStatementsCanBeMerged(JSForInStatement statement1, - JSForInStatement statement2) - { - - // final JSExpression firstVarExpression = statement1.getVariableExpression(); - // final JSExpression secondVarExpression = statement2.getVariableExpression(); - final JSExpression firstVarExpression = getVariableExpression(statement1); - final JSExpression secondVarExpression = getVariableExpression(statement2); - if(!EquivalenceChecker.expressionsAreEquivalent(firstVarExpression, - secondVarExpression)) - { - return false; - } - - final JSVarStatement firstDeclaration = statement1.getDeclarationStatement(); - final JSVarStatement secondDeclaration = statement2.getDeclarationStatement(); - if(!EquivalenceChecker.statementsAreEquivalent(firstDeclaration, - secondDeclaration)) - { - return false; - } - - // final JSExpression firstCollection = statement1.getCollectionExpression(); - // final JSExpression secondCollection = statement2.getCollectionExpression(); - final JSExpression firstCollection = getCollectionExpression(statement1); - final JSExpression secondCollection = getCollectionExpression(statement2); - if(!EquivalenceChecker.expressionsAreEquivalent(firstCollection, - secondCollection)) - { - return false; - } - - final JSStatement firstBody = statement1.getBody(); - final JSStatement secondBody = statement2.getBody(); - return (firstBody == null || secondBody == null || - ControlFlowUtils.canBeMerged(firstBody, secondBody)); - } - } - - /** - * Method provided as a workaround of a bug in the JavaScript language IDEA plugin. - * - * @param forInStatement the for-in statement - * @return the for-in statement collection expression - */ - private static JSExpression getCollectionExpression(JSForInStatement forInStatement) - { - final ASTNode statementNode = forInStatement.getNode(); - ASTNode child = ((statementNode == null) ? null : statementNode.getFirstChildNode()); - boolean inPassed = false; - - while(child != null) - { - if(child.getElementType() == JSTokenTypes.IN_KEYWORD) - { - inPassed = true; - } - if(inPassed && child.getPsi() instanceof JSExpression) - { - return (JSExpression) child.getPsi(); - } - child = child.getTreeNext(); - } - - return null; - } - - /** - * Method provided as a workaround of a bug in the JavaScript language IDEA plugin. - * - * @param forInStatement the for-in statement - * @return the for-in statement collection expression - */ - private static JSExpression getVariableExpression(JSForInStatement forInStatement) - { - final ASTNode statementNode = forInStatement.getNode(); - ASTNode child = ((statementNode == null) ? null : statementNode.getFirstChildNode()); - - while(child != null) - { - if(child.getElementType() == JSTokenTypes.IN_KEYWORD) - { - return null; - } - - if(child.getPsi() instanceof JSExpression) - { - return (JSExpression) child.getPsi(); - } - child = child.getTreeNext(); - } - - return null; - } - +@IntentionMetaData( + ignoreId = "JSMergeParallelForInLoopsIntention", + categories = {"JavaScript", "Control Flow"}, + fileExtensions = "js" +) +public class JSMergeParallelForInLoopsIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.loopMergeParallelForInLoops(); + } + + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new MergeParallelForInLoopsPredicate(); + } + + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + PsiElement nextElement = JSElementFactory.getNonWhiteSpaceSibling(element, true); + + assert (nextElement != null); + + JSForInStatement firstStatement = (JSForInStatement)element; + JSForInStatement secondStatement = (JSForInStatement)nextElement; + StringBuilder statementBuffer = new StringBuilder(); + + this.mergeForInStatements(statementBuffer, firstStatement, secondStatement); + JSElementFactory.replaceStatement(firstStatement, statementBuffer.toString()); + JSElementFactory.removeElement(secondStatement); + } + + @RequiredReadAction + private void mergeForInStatements(StringBuilder statementBuffer, JSForInStatement firstStatement, JSForInStatement secondStatement) { + JSExpression variableExpression = getVariableExpression(firstStatement); + JSVarStatement declaration = firstStatement.getDeclarationStatement(); + JSExpression collectionExpression = getCollectionExpression(firstStatement); + JSStatement firstBody = firstStatement.getBody(); + JSStatement secondBody = secondStatement.getBody(); + + statementBuffer.append("for (") + .append((declaration == null) ? variableExpression.getText() : declaration.getText()) + .append(" in ") + .append(collectionExpression.getText()) + .append(')'); + ControlFlowUtils.appendStatementsInSequence(statementBuffer, firstBody, secondBody); + } + + private static class MergeParallelForInLoopsPredicate implements JSElementPredicate { + @Override + public boolean satisfiedBy(@Nonnull PsiElement element) { + return element instanceof JSForInStatement forInStatement + && !ErrorUtil.containsError(element) + && JSElementFactory.getNonWhiteSpaceSibling(element, true) instanceof JSForInStatement nextForInStatement + && !ErrorUtil.containsError(nextForInStatement) + && forInStatementsCanBeMerged(forInStatement, nextForInStatement); + } + + public static boolean forInStatementsCanBeMerged(JSForInStatement statement1, JSForInStatement statement2) { + JSExpression firstVarExpression = getVariableExpression(statement1); + JSExpression secondVarExpression = getVariableExpression(statement2); + if (!EquivalenceChecker.expressionsAreEquivalent(firstVarExpression, secondVarExpression)) { + return false; + } + + JSVarStatement firstDeclaration = statement1.getDeclarationStatement(); + JSVarStatement secondDeclaration = statement2.getDeclarationStatement(); + if (!EquivalenceChecker.statementsAreEquivalent(firstDeclaration, secondDeclaration)) { + return false; + } + + JSExpression firstCollection = getCollectionExpression(statement1); + JSExpression secondCollection = getCollectionExpression(statement2); + if (!EquivalenceChecker.expressionsAreEquivalent(firstCollection, secondCollection)) { + return false; + } + + JSStatement firstBody = statement1.getBody(); + JSStatement secondBody = statement2.getBody(); + return firstBody == null || secondBody == null || ControlFlowUtils.canBeMerged(firstBody, secondBody); + } + } + + /** + * Method provided as a workaround of a bug in the JavaScript language IDEA plugin. + * + * @param forInStatement the for-in statement + * @return the for-in statement collection expression + */ + private static JSExpression getCollectionExpression(JSForInStatement forInStatement) { + ASTNode statementNode = forInStatement.getNode(); + ASTNode child = (statementNode == null) ? null : statementNode.getFirstChildNode(); + boolean inPassed = false; + + while (child != null) { + if (child.getElementType() == JSTokenTypes.IN_KEYWORD) { + inPassed = true; + } + if (inPassed && child.getPsi() instanceof JSExpression childExpression) { + return childExpression; + } + child = child.getTreeNext(); + } + + return null; + } + + /** + * Method provided as a workaround of a bug in the JavaScript language IDEA plugin. + * + * @param forInStatement the for-in statement + * @return the for-in statement collection expression + */ + private static JSExpression getVariableExpression(JSForInStatement forInStatement) { + ASTNode statementNode = forInStatement.getNode(); + ASTNode child = (statementNode == null) ? null : statementNode.getFirstChildNode(); + + while (child != null) { + if (child.getElementType() == JSTokenTypes.IN_KEYWORD) { + return null; + } + + if (child.getPsi() instanceof JSExpression childExpression) { + return childExpression; + } + child = child.getTreeNext(); + } + + return null; + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/loop/JSMergeParallelForLoopsIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/loop/JSMergeParallelForLoopsIntention.java index 3c43e8a7..4289c261 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/loop/JSMergeParallelForLoopsIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/loop/JSMergeParallelForLoopsIntention.java @@ -19,134 +19,113 @@ import com.intellij.lang.javascript.psi.JSForStatement; import com.intellij.lang.javascript.psi.JSStatement; import com.intellij.lang.javascript.psi.JSVarStatement; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.ControlFlowUtils; import org.intellij.idea.lang.javascript.psiutil.EquivalenceChecker; import org.intellij.idea.lang.javascript.psiutil.ErrorUtil; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; -import org.jetbrains.annotations.NonNls; - -import javax.annotation.Nonnull; @ExtensionImpl -@IntentionMetaData(ignoreId = "JSMergeParallelForLoopsIntention", categories = { - "JavaScript", - "Control Flow" -}, fileExtensions = "js") -public class JSMergeParallelForLoopsIntention extends JSIntention -{ - @NonNls - private static final String FOR_STATEMENT_PREFIX = "for ("; - - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new MergeParallelForLoopsPredicate(); - } - - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final PsiElement nextElement = JSElementFactory.getNonWhiteSpaceSibling(element, true); - - assert (nextElement != null); - - final JSForStatement firstStatement = (JSForStatement) element; - final JSForStatement secondStatement = (JSForStatement) nextElement; - final StringBuilder statementBuffer = new StringBuilder(); - - this.mergeForStatements(statementBuffer, firstStatement, secondStatement); - JSElementFactory.replaceStatement(firstStatement, statementBuffer.toString()); - JSElementFactory.removeElement(secondStatement); - } - - private void mergeForStatements(StringBuilder statementBuffer, - JSForStatement firstStatement, - JSForStatement secondStatement) - { - final JSExpression initialization = firstStatement.getInitialization(); - final JSVarStatement varStatement = firstStatement.getVarDeclaration(); - final JSExpression condition = firstStatement.getCondition(); - final JSExpression update = firstStatement.getUpdate(); - final JSStatement firstBody = firstStatement.getBody(); - final JSStatement secondBody = secondStatement.getBody(); - - statementBuffer.append(FOR_STATEMENT_PREFIX) - .append((initialization == null) ? varStatement.getText() : initialization.getText()) - .append(';') - .append(condition.getText()) - .append(';') - .append(update.getText()) - .append(')'); - ControlFlowUtils.appendStatementsInSequence(statementBuffer, firstBody, secondBody); - } - - private static class MergeParallelForLoopsPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSForStatement) || ErrorUtil.containsError(element)) - { - return false; - } - - final PsiElement nextStatement = JSElementFactory.getNonWhiteSpaceSibling(element, true); - - if(!(nextStatement instanceof JSForStatement) || ErrorUtil.containsError(nextStatement)) - { - return false; - } - - return forStatementsCanBeMerged((JSForStatement) element, - (JSForStatement) nextStatement); - } - - public static boolean forStatementsCanBeMerged(JSForStatement statement1, - JSForStatement statement2) - { - final JSExpression firstInitialization = statement1.getInitialization(); - final JSExpression secondInitialization = statement2.getInitialization(); - if(!EquivalenceChecker.expressionsAreEquivalent(firstInitialization, - secondInitialization)) - { - return false; - } - - final JSVarStatement firstVarStatement = statement1.getVarDeclaration(); - final JSVarStatement secondVarStatement = statement2.getVarDeclaration(); - if(!EquivalenceChecker.statementsAreEquivalent(firstVarStatement, - secondVarStatement)) - { - return false; - } - - final JSExpression firstCondition = statement1.getCondition(); - final JSExpression secondCondition = statement2.getCondition(); - if(!EquivalenceChecker.expressionsAreEquivalent(firstCondition, - secondCondition)) - { - return false; - } - - final JSExpression firstUpdate = statement1.getUpdate(); - final JSExpression secondUpdate = statement2.getUpdate(); - if(!EquivalenceChecker.expressionsAreEquivalent(firstUpdate, - secondUpdate)) - { - return false; - } - - final JSStatement firstBody = statement1.getBody(); - final JSStatement secondBody = statement2.getBody(); - return (firstBody == null || secondBody == null || - ControlFlowUtils.canBeMerged(firstBody, secondBody)); - } - } +@IntentionMetaData( + ignoreId = "JSMergeParallelForLoopsIntention", + categories = {"JavaScript", "Control Flow"}, + fileExtensions = "js" +) +public class JSMergeParallelForLoopsIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.loopMergeParallelForLoops(); + } + + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new MergeParallelForLoopsPredicate(); + } + + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + PsiElement nextElement = JSElementFactory.getNonWhiteSpaceSibling(element, true); + + assert (nextElement != null); + + JSForStatement firstStatement = (JSForStatement)element; + JSForStatement secondStatement = (JSForStatement)nextElement; + StringBuilder statementBuffer = new StringBuilder(); + + this.mergeForStatements(statementBuffer, firstStatement, secondStatement); + JSElementFactory.replaceStatement(firstStatement, statementBuffer.toString()); + JSElementFactory.removeElement(secondStatement); + } + + @RequiredReadAction + private void mergeForStatements(StringBuilder statementBuffer, JSForStatement firstStatement, JSForStatement secondStatement) { + JSExpression initialization = firstStatement.getInitialization(); + JSVarStatement varStatement = firstStatement.getVarDeclaration(); + JSExpression condition = firstStatement.getCondition(); + JSExpression update = firstStatement.getUpdate(); + JSStatement firstBody = firstStatement.getBody(); + JSStatement secondBody = secondStatement.getBody(); + + statementBuffer.append("for (") + .append((initialization == null) ? varStatement.getText() : initialization.getText()) + .append(';') + .append(condition.getText()) + .append(';') + .append(update.getText()) + .append(')'); + ControlFlowUtils.appendStatementsInSequence(statementBuffer, firstBody, secondBody); + } + + private static class MergeParallelForLoopsPredicate implements JSElementPredicate { + @Override + public boolean satisfiedBy(@Nonnull PsiElement element) { + return element instanceof JSForStatement forStatement + && !ErrorUtil.containsError(forStatement) + && JSElementFactory.getNonWhiteSpaceSibling(element, true) instanceof JSForStatement nextForStatement + && !ErrorUtil.containsError(nextForStatement) + && forStatementsCanBeMerged(forStatement, nextForStatement); + } + + public static boolean forStatementsCanBeMerged(JSForStatement statement1, JSForStatement statement2) { + JSExpression firstInitialization = statement1.getInitialization(); + JSExpression secondInitialization = statement2.getInitialization(); + if (!EquivalenceChecker.expressionsAreEquivalent(firstInitialization, secondInitialization)) { + return false; + } + + JSVarStatement firstVarStatement = statement1.getVarDeclaration(); + JSVarStatement secondVarStatement = statement2.getVarDeclaration(); + if (!EquivalenceChecker.statementsAreEquivalent(firstVarStatement, secondVarStatement)) { + return false; + } + + JSExpression firstCondition = statement1.getCondition(); + JSExpression secondCondition = statement2.getCondition(); + if (!EquivalenceChecker.expressionsAreEquivalent(firstCondition, secondCondition)) { + return false; + } + + JSExpression firstUpdate = statement1.getUpdate(); + JSExpression secondUpdate = statement2.getUpdate(); + if (!EquivalenceChecker.expressionsAreEquivalent(firstUpdate, secondUpdate)) { + return false; + } + + JSStatement firstBody = statement1.getBody(); + JSStatement secondBody = statement2.getBody(); + return (firstBody == null || secondBody == null || ControlFlowUtils.canBeMerged(firstBody, secondBody)); + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/number/JSConvertIntegerToDecimalIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/number/JSConvertIntegerToDecimalIntention.java index ebdcf618..6d0abc25 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/number/JSConvertIntegerToDecimalIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/number/JSConvertIntegerToDecimalIntention.java @@ -16,53 +16,56 @@ package org.intellij.idea.lang.javascript.intention.number; import com.intellij.lang.javascript.psi.JSLiteralExpression; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; import org.intellij.idea.lang.javascript.psiutil.NumberUtil; -import javax.annotation.Nonnull; - @ExtensionImpl -@IntentionMetaData(ignoreId = "JSConvertIntegerToDecimalIntention", categories = { - "JavaScript", - "Numbers" -}, fileExtensions = "js") -public class JSConvertIntegerToDecimalIntention extends JSIntention -{ - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new ConvertIntegerToDecimalPredicate(); - } +@IntentionMetaData( + ignoreId = "JSConvertIntegerToDecimalIntention", + categories = {"JavaScript", "Numbers"}, + fileExtensions = "js" +) +public class JSConvertIntegerToDecimalIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.numberConvertIntegerToDecimal(); + } + + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new ConvertIntegerToDecimalPredicate(); + } - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final JSLiteralExpression exp = (JSLiteralExpression) element; + @Override + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + JSLiteralExpression exp = (JSLiteralExpression)element; - JSElementFactory.replaceExpression(exp, NumberUtil.getLiteralNumber(exp).toString()); - } + JSElementFactory.replaceExpression(exp, NumberUtil.getLiteralNumber(exp).toString()); + } - private static class ConvertIntegerToDecimalPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSLiteralExpression)) - { - return false; - } + private static class ConvertIntegerToDecimalPredicate implements JSElementPredicate { + @Override + @RequiredReadAction + public boolean satisfiedBy(@Nonnull PsiElement element) { + if (!(element instanceof JSLiteralExpression)) { + return false; + } - final String elementText = element.getText(); + String elementText = element.getText(); - return (NumberUtil.isHex(elementText) || - NumberUtil.isOctal(elementText)); - } - } + return NumberUtil.isHex(elementText) || NumberUtil.isOctal(elementText); + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/number/JSConvertIntegerToHexIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/number/JSConvertIntegerToHexIntention.java index 6e39e25d..b039d78c 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/number/JSConvertIntegerToHexIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/number/JSConvertIntegerToHexIntention.java @@ -16,50 +16,50 @@ package org.intellij.idea.lang.javascript.intention.number; import com.intellij.lang.javascript.psi.JSLiteralExpression; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; import org.intellij.idea.lang.javascript.psiutil.NumberUtil; -import javax.annotation.Nonnull; - @ExtensionImpl -@IntentionMetaData(ignoreId = "JSConvertIntegerToHexIntention", categories = { - "JavaScript", - "Numbers" -}, fileExtensions = "js") -public class JSConvertIntegerToHexIntention extends JSIntention -{ - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new ConvertIntegerToHexPredicate(); - } +@IntentionMetaData( + ignoreId = "JSConvertIntegerToHexIntention", + categories = {"JavaScript", "Numbers"}, + fileExtensions = "js" +) +public class JSConvertIntegerToHexIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.numberConvertIntegerToHex(); + } - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final JSLiteralExpression exp = (JSLiteralExpression) element; + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new ConvertIntegerToHexPredicate(); + } - JSElementFactory.replaceExpression(exp, "0x" + NumberUtil.getLiteralNumber(exp).toString(16)); - } + @Override + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + JSLiteralExpression exp = (JSLiteralExpression)element; - private static class ConvertIntegerToHexPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSLiteralExpression)) - { - return false; - } + JSElementFactory.replaceExpression(exp, "0x" + NumberUtil.getLiteralNumber(exp).toString(16)); + } - return NumberUtil.isDecimal(element.getText()); - } - } + private static class ConvertIntegerToHexPredicate implements JSElementPredicate { + @Override + @RequiredReadAction + public boolean satisfiedBy(@Nonnull PsiElement element) { + return element instanceof JSLiteralExpression && NumberUtil.isDecimal(element.getText()); + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/number/JSConvertIntegerToOctalIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/number/JSConvertIntegerToOctalIntention.java index 3343bbc1..00ab0b65 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/number/JSConvertIntegerToOctalIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/number/JSConvertIntegerToOctalIntention.java @@ -16,55 +16,56 @@ package org.intellij.idea.lang.javascript.intention.number; import com.intellij.lang.javascript.psi.JSLiteralExpression; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; import org.intellij.idea.lang.javascript.psiutil.NumberUtil; -import javax.annotation.Nonnull; - @ExtensionImpl -@IntentionMetaData(ignoreId = "JSConvertIntegerToOctalIntention", categories = { - "JavaScript", - "Numbers" -}, fileExtensions = "js") -public class JSConvertIntegerToOctalIntention extends JSIntention -{ - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new ConvertIntegerToOctalPredicate(); - } +@IntentionMetaData( + ignoreId = "JSConvertIntegerToOctalIntention", + categories = {"JavaScript", "Numbers"}, + fileExtensions = "js" +) +public class JSConvertIntegerToOctalIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.numberConvertIntegerToOctal(); + } - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final JSLiteralExpression exp = (JSLiteralExpression) element; + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new ConvertIntegerToOctalPredicate(); + } - JSElementFactory.replaceExpression(exp, '0' + NumberUtil.getLiteralNumber(exp).toString(8)); - } + @Override + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + JSLiteralExpression exp = (JSLiteralExpression)element; - private static class ConvertIntegerToOctalPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSLiteralExpression)) - { - return false; - } + JSElementFactory.replaceExpression(exp, '0' + NumberUtil.getLiteralNumber(exp).toString(8)); + } - final String elementText = element.getText(); + private static class ConvertIntegerToOctalPredicate implements JSElementPredicate { + @Override + @RequiredReadAction + public boolean satisfiedBy(@Nonnull PsiElement element) { + if (!(element instanceof JSLiteralExpression)) { + return false; + } - return (NumberUtil.isHex(elementText) || - (NumberUtil.isDecimal(elementText) && - !NumberUtil.isOctal(elementText))); - } - } + String elementText = element.getText(); + return NumberUtil.isHex(elementText) || (NumberUtil.isDecimal(elementText) && !NumberUtil.isOctal(elementText)); + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/number/JSReplaceMultiplyWithShiftIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/number/JSReplaceMultiplyWithShiftIntention.java index add28157..2a41a99b 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/number/JSReplaceMultiplyWithShiftIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/number/JSReplaceMultiplyWithShiftIntention.java @@ -17,164 +17,138 @@ import com.intellij.lang.javascript.JSTokenTypes; import com.intellij.lang.javascript.psi.*; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.ast.IElementType; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSMutablyNamedIntention; import org.intellij.idea.lang.javascript.psiutil.BinaryOperatorUtils; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; import org.intellij.idea.lang.javascript.psiutil.ParenthesesUtils; -import javax.annotation.Nonnull; - @ExtensionImpl -@IntentionMetaData(ignoreId = "JSReplaceMultiplyWithShiftIntention", categories = { - "JavaScript", - "Shift" -}, fileExtensions = "js") -public class JSReplaceMultiplyWithShiftIntention extends JSMutablyNamedIntention -{ - @Override - protected String getTextForElement(PsiElement element) - { - final IElementType tokenType = ((JSBinaryExpression) element).getOperationSign(); - final String operatorString; - - if(element instanceof JSAssignmentExpression) - { - operatorString = (tokenType.equals(JSTokenTypes.MULTEQ) ? "<<=" : ">>="); - } - else - { - operatorString = (tokenType.equals(JSTokenTypes.MULT) ? "<<" : ">>"); - } - - return this.getText(BinaryOperatorUtils.getOperatorText(tokenType), operatorString); - } - - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new MultiplyByPowerOfTwoPredicate(); - } - - @Override - public void processIntention(@Nonnull PsiElement element) - throws IncorrectOperationException - { - if(element instanceof JSAssignmentExpression) - { - this.replaceMultiplyOrDivideAssignWithShiftAssign((JSAssignmentExpression) element); - } - else - { - this.replaceMultiplyOrDivideWithShift((JSBinaryExpression) element); - } - } - - private void replaceMultiplyOrDivideAssignWithShiftAssign(JSAssignmentExpression exp) - throws IncorrectOperationException - { - final JSExpression lhs = exp.getLOperand(); - final JSExpression rhs = exp.getROperand(); - final IElementType tokenType = exp.getOperationSign(); - final String assignString = (tokenType.equals(JSTokenTypes.MULTEQ) ? "<<=" : ">>="); - final String expString = lhs.getText() + assignString + - ShiftUtils.getLogBase2(rhs); - - JSElementFactory.replaceExpression(exp, expString); - } - - private void replaceMultiplyOrDivideWithShift(JSBinaryExpression exp) - throws IncorrectOperationException - { - JSExpression lhs = exp.getLOperand(); - JSExpression rhs = exp.getROperand(); - final IElementType tokenType = exp.getOperationSign(); - final String operatorString = (tokenType.equals(JSTokenTypes.MULT) ? "<<" : ">>"); - - if(ShiftUtils.isPowerOfTwo(lhs) && tokenType.equals(JSTokenTypes.MULT)) - { - JSExpression swap = lhs; - - lhs = rhs; - rhs = swap; - } - - final String lhsText = ParenthesesUtils.getParenthesized(lhs, ParenthesesUtils.SHIFT_PRECENDENCE); - String expString = lhsText + operatorString + ShiftUtils.getLogBase2(rhs); - final JSElement parent = (JSElement) exp.getParent(); - - if(parent != null && parent instanceof JSExpression) - { - if(!(parent instanceof JSParenthesizedExpression) && - ParenthesesUtils.getPrecendence((JSExpression) parent) < ParenthesesUtils.SHIFT_PRECENDENCE) - { - expString = '(' + expString + ')'; - } - } - JSElementFactory.replaceExpression(exp, expString); - } - - private static class MultiplyByPowerOfTwoPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(element instanceof JSAssignmentExpression) - { - return isMultiplyByPowerOfTwo((JSAssignmentExpression) element); - } - else if(element instanceof JSBinaryExpression) - { - return isMultiplyByPowerOfTwo((JSBinaryExpression) element); - } - else - { - return false; - } - } - - private static boolean isMultiplyByPowerOfTwo(JSAssignmentExpression expression) - { - final IElementType operator = expression.getOperationSign(); - - if(operator == null || !(operator.equals(JSTokenTypes.MULTEQ) || operator.equals(JSTokenTypes.DIVEQ))) - { - return false; - } - - final JSExpression rightExpression = expression.getROperand(); - - if(rightExpression == null) - { - return false; - } - - return ShiftUtils.isPowerOfTwo(rightExpression); - } - - private static boolean isMultiplyByPowerOfTwo(JSBinaryExpression expression) - { - final IElementType operator = expression.getOperationSign(); - - if(operator == null || !(operator.equals(JSTokenTypes.MULT) || operator.equals(JSTokenTypes.DIV))) - { - return false; - } - - final JSExpression leftOperand = expression.getLOperand(); - final JSExpression rightOperand = expression.getROperand(); - - if(leftOperand == null || rightOperand == null) - { - return false; - } - return (ShiftUtils.isPowerOfTwo(leftOperand) || ShiftUtils.isPowerOfTwo(rightOperand)); - } - } +@IntentionMetaData( + ignoreId = "JSReplaceMultiplyWithShiftIntention", + categories = {"JavaScript", "Shift"}, + fileExtensions = "js" +) +public class JSReplaceMultiplyWithShiftIntention extends JSMutablyNamedIntention { + @Nonnull + @Override + protected LocalizeValue getBasicText() { + return JSIntentionLocalize.numberReplaceMultiplyWithShift(); + } + + @Override + @RequiredReadAction + protected LocalizeValue getTextForElement(PsiElement element) { + IElementType tokenType = ((JSBinaryExpression)element).getOperationSign(); + String operatorString; + + if (element instanceof JSAssignmentExpression) { + operatorString = JSTokenTypes.MULTEQ.equals(tokenType) ? "<<=" : ">>="; + } + else { + operatorString = JSTokenTypes.MULT.equals(tokenType) ? "<<" : ">>"; + } + + return JSIntentionLocalize.numberReplaceMultiplyWithShiftMessage(BinaryOperatorUtils.getOperatorText(tokenType), operatorString); + } + + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new MultiplyByPowerOfTwoPredicate(); + } + + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + if (element instanceof JSAssignmentExpression assignmentExpression) { + this.replaceMultiplyOrDivideAssignWithShiftAssign(assignmentExpression); + } + else { + this.replaceMultiplyOrDivideWithShift((JSBinaryExpression)element); + } + } + + @RequiredReadAction + private void replaceMultiplyOrDivideAssignWithShiftAssign(JSAssignmentExpression exp) throws IncorrectOperationException { + JSExpression lhs = exp.getLOperand(); + JSExpression rhs = exp.getROperand(); + IElementType tokenType = exp.getOperationSign(); + String assignString = JSTokenTypes.MULTEQ.equals(tokenType) ? "<<=" : ">>="; + String expString = lhs.getText() + assignString + ShiftUtils.getLogBase2(rhs); + + JSElementFactory.replaceExpression(exp, expString); + } + + @RequiredReadAction + private void replaceMultiplyOrDivideWithShift(JSBinaryExpression exp) throws IncorrectOperationException { + JSExpression lhs = exp.getLOperand(); + JSExpression rhs = exp.getROperand(); + IElementType tokenType = exp.getOperationSign(); + String operatorString = JSTokenTypes.MULT.equals(tokenType) ? "<<" : ">>"; + + if (ShiftUtils.isPowerOfTwo(lhs) && JSTokenTypes.MULT.equals(tokenType)) { + JSExpression swap = lhs; + + lhs = rhs; + rhs = swap; + } + + String lhsText = ParenthesesUtils.getParenthesized(lhs, ParenthesesUtils.SHIFT_PRECENDENCE); + String expString = lhsText + operatorString + ShiftUtils.getLogBase2(rhs); + JSElement parent = (JSElement)exp.getParent(); + + if (parent != null && parent instanceof JSExpression parentExpression && !(parent instanceof JSParenthesizedExpression) + && ParenthesesUtils.getPrecendence(parentExpression) < ParenthesesUtils.SHIFT_PRECENDENCE) { + expString = '(' + expString + ')'; + } + JSElementFactory.replaceExpression(exp, expString); + } + + private static class MultiplyByPowerOfTwoPredicate implements JSElementPredicate { + @Override + @RequiredReadAction + public boolean satisfiedBy(@Nonnull PsiElement element) { + return element instanceof JSAssignmentExpression assignmentExpression + ? isMultiplyByPowerOfTwo(assignmentExpression) + : element instanceof JSBinaryExpression binaryExpression && isMultiplyByPowerOfTwo(binaryExpression); + } + + @RequiredReadAction + private static boolean isMultiplyByPowerOfTwo(JSAssignmentExpression expression) { + IElementType operator = expression.getOperationSign(); + + if (operator == null || !(operator.equals(JSTokenTypes.MULTEQ) || operator.equals(JSTokenTypes.DIVEQ))) { + return false; + } + + JSExpression rightExpression = expression.getROperand(); + + return rightExpression != null && ShiftUtils.isPowerOfTwo(rightExpression); + } + + @RequiredReadAction + private static boolean isMultiplyByPowerOfTwo(JSBinaryExpression expression) { + IElementType operator = expression.getOperationSign(); + + if (operator == null || !(JSTokenTypes.MULT.equals(operator) || JSTokenTypes.DIV.equals(operator))) { + return false; + } + + JSExpression leftOperand = expression.getLOperand(); + JSExpression rightOperand = expression.getROperand(); + + return leftOperand != null && rightOperand != null + && (ShiftUtils.isPowerOfTwo(leftOperand) || ShiftUtils.isPowerOfTwo(rightOperand)); + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/number/JSReplaceShiftWithMultiplyIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/number/JSReplaceShiftWithMultiplyIntention.java index 9f2fd03d..ea0e3401 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/number/JSReplaceShiftWithMultiplyIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/number/JSReplaceShiftWithMultiplyIntention.java @@ -17,152 +17,125 @@ import com.intellij.lang.javascript.JSTokenTypes; import com.intellij.lang.javascript.psi.*; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.ast.IElementType; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSMutablyNamedIntention; import org.intellij.idea.lang.javascript.psiutil.BinaryOperatorUtils; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; import org.intellij.idea.lang.javascript.psiutil.ParenthesesUtils; -import javax.annotation.Nonnull; - @ExtensionImpl -@IntentionMetaData(ignoreId = "JSReplaceShiftWithMultiplyIntention", categories = { - "JavaScript", - "Shift" -}, fileExtensions = "js") -public class JSReplaceShiftWithMultiplyIntention extends JSMutablyNamedIntention -{ - @Override - protected String getTextForElement(PsiElement element) - { - final IElementType tokenType = ((JSBinaryExpression) element).getOperationSign(); - final String operatorString; - - if(element instanceof JSAssignmentExpression) - { - operatorString = (tokenType.equals(JSTokenTypes.LTLTEQ) ? "*=" : "/="); - } - else - { - operatorString = (tokenType.equals(JSTokenTypes.LTLT) ? "*" : "/"); - } - - return this.getText(BinaryOperatorUtils.getOperatorText(tokenType), operatorString); - } - - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new ShiftByLiteralPredicate(); - } - - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - if(element instanceof JSAssignmentExpression) - { - this.replaceShiftAssignWithMultiplyOrDivideAssign((JSAssignmentExpression) element); - } - else - { - assert (element instanceof JSBinaryExpression); - this.replaceShiftWithMultiplyOrDivide((JSBinaryExpression) element); - } - } - - private void replaceShiftAssignWithMultiplyOrDivideAssign(JSAssignmentExpression exp) - throws IncorrectOperationException - { - final JSExpression lhs = exp.getLOperand(); - final JSExpression rhs = exp.getROperand(); - final IElementType tokenType = exp.getOperationSign(); - final String assignString = ((tokenType.equals(JSTokenTypes.LTLTEQ)) ? "*=" : "/="); - - final String expString = lhs.getText() + assignString + ShiftUtils.getExpBase2(rhs); - - JSElementFactory.replaceExpression(exp, expString); - } - - private void replaceShiftWithMultiplyOrDivide(JSBinaryExpression exp) - throws IncorrectOperationException - { - final JSExpression lhs = exp.getLOperand(); - final JSExpression rhs = exp.getROperand(); - final IElementType tokenType = exp.getOperationSign(); - final String operatorString = ((tokenType.equals(JSTokenTypes.LTLT)) ? "*" : "/"); - final String lhsText = ParenthesesUtils.getParenthesized(lhs, ParenthesesUtils.MULTIPLICATIVE_PRECENDENCE); - String expString = lhsText + operatorString + ShiftUtils.getExpBase2(rhs); - final JSElement parent = (JSElement) exp.getParent(); - - if(parent != null && parent instanceof JSExpression) - { - if(!(parent instanceof JSParenthesizedExpression) && - ParenthesesUtils.getPrecendence((JSExpression) parent) < ParenthesesUtils.MULTIPLICATIVE_PRECENDENCE) - { - expString = '(' + expString + ')'; - } - } - JSElementFactory.replaceExpression(exp, expString); - } - - private static class ShiftByLiteralPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(element instanceof JSAssignmentExpression) - { - return this.isAssignmentShiftByLiteral((JSAssignmentExpression) element); - } - else if(element instanceof JSBinaryExpression) - { - return this.isBinaryShiftByLiteral((JSBinaryExpression) element); - } - else - { - return false; - } - } - - private boolean isAssignmentShiftByLiteral(JSAssignmentExpression expression) - { - final IElementType tokenType = expression.getOperationSign(); - - if(tokenType == null || - !(tokenType.equals(JSTokenTypes.LTLTEQ) || - tokenType.equals(JSTokenTypes.GTGTEQ) - ) - ) - { - return false; - } - - final JSExpression rhs = expression.getROperand(); - - if(rhs == null) - { - return false; - } - return ShiftUtils.isIntLiteral(rhs); - } - - private boolean isBinaryShiftByLiteral(JSBinaryExpression expression) - { - final IElementType tokenType = expression.getOperationSign(); - - if(!(tokenType.equals(JSTokenTypes.LTLT) || - tokenType.equals(JSTokenTypes.GTGT))) - { - return false; - } - - return ShiftUtils.isIntLiteral(expression.getROperand()); - } - } +@IntentionMetaData( + ignoreId = "JSReplaceShiftWithMultiplyIntention", + categories = {"JavaScript", "Shift"}, + fileExtensions = "js" +) +public class JSReplaceShiftWithMultiplyIntention extends JSMutablyNamedIntention { + @Nonnull + @Override + protected LocalizeValue getBasicText() { + return JSIntentionLocalize.numberReplaceShiftWithMultiply(); + } + + @Override + @RequiredReadAction + protected LocalizeValue getTextForElement(PsiElement element) { + IElementType tokenType = ((JSBinaryExpression)element).getOperationSign(); + String operatorString; + + if (element instanceof JSAssignmentExpression) { + operatorString = JSTokenTypes.LTLTEQ.equals(tokenType) ? "*=" : "/="; + } + else { + operatorString = JSTokenTypes.LTLT.equals(tokenType) ? "*" : "/"; + } + + return JSIntentionLocalize.numberReplaceShiftWithMultiplyMessage(BinaryOperatorUtils.getOperatorText(tokenType), operatorString); + } + + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new ShiftByLiteralPredicate(); + } + + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + if (element instanceof JSAssignmentExpression assignmentExpression) { + this.replaceShiftAssignWithMultiplyOrDivideAssign(assignmentExpression); + } + else { + assert (element instanceof JSBinaryExpression); + this.replaceShiftWithMultiplyOrDivide((JSBinaryExpression)element); + } + } + + @RequiredReadAction + private void replaceShiftAssignWithMultiplyOrDivideAssign(JSAssignmentExpression exp) throws IncorrectOperationException { + JSExpression lhs = exp.getLOperand(); + JSExpression rhs = exp.getROperand(); + IElementType tokenType = exp.getOperationSign(); + String assignString = JSTokenTypes.LTLTEQ.equals(tokenType) ? "*=" : "/="; + + String expString = lhs.getText() + assignString + ShiftUtils.getExpBase2(rhs); + + JSElementFactory.replaceExpression(exp, expString); + } + + @RequiredReadAction + private void replaceShiftWithMultiplyOrDivide(JSBinaryExpression exp) throws IncorrectOperationException { + JSExpression lhs = exp.getLOperand(); + JSExpression rhs = exp.getROperand(); + IElementType tokenType = exp.getOperationSign(); + String operatorString = JSTokenTypes.LTLT.equals(tokenType) ? "*" : "/"; + String lhsText = ParenthesesUtils.getParenthesized(lhs, ParenthesesUtils.MULTIPLICATIVE_PRECENDENCE); + String expString = lhsText + operatorString + ShiftUtils.getExpBase2(rhs); + JSElement parent = (JSElement)exp.getParent(); + + if (parent != null && parent instanceof JSExpression parentExpression && !(parent instanceof JSParenthesizedExpression) + && ParenthesesUtils.getPrecendence(parentExpression) < ParenthesesUtils.MULTIPLICATIVE_PRECENDENCE) { + expString = '(' + expString + ')'; + } + JSElementFactory.replaceExpression(exp, expString); + } + + private static class ShiftByLiteralPredicate implements JSElementPredicate { + @Override + @RequiredReadAction + public boolean satisfiedBy(@Nonnull PsiElement element) { + return element instanceof JSAssignmentExpression assignmentExpression + ? this.isAssignmentShiftByLiteral(assignmentExpression) + : element instanceof JSBinaryExpression binaryExpression && this.isBinaryShiftByLiteral(binaryExpression); + } + + @RequiredReadAction + private boolean isAssignmentShiftByLiteral(JSAssignmentExpression expression) { + IElementType tokenType = expression.getOperationSign(); + + if (tokenType == null || !(JSTokenTypes.LTLTEQ.equals(tokenType) || JSTokenTypes.GTGTEQ.equals(tokenType))) { + return false; + } + + JSExpression rhs = expression.getROperand(); + + return rhs != null && ShiftUtils.isIntLiteral(rhs); + } + + @RequiredReadAction + private boolean isBinaryShiftByLiteral(JSBinaryExpression expression) { + IElementType tokenType = expression.getOperationSign(); + + return (JSTokenTypes.LTLT.equals(tokenType) || JSTokenTypes.GTGT.equals(tokenType)) + && ShiftUtils.isIntLiteral(expression.getROperand()); + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/number/ShiftUtils.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/number/ShiftUtils.java index 8e979d46..67dc1b84 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/number/ShiftUtils.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/number/ShiftUtils.java @@ -18,109 +18,85 @@ import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.JSLiteralExpression; -class ShiftUtils -{ - private ShiftUtils() - { - } +class ShiftUtils { + private ShiftUtils() { + } - public static boolean isPowerOfTwo(JSExpression expression) - { - if(!(expression instanceof JSLiteralExpression)) - { - return false; - } - final String value = expression.getText(); - long intValue; + public static boolean isPowerOfTwo(JSExpression expression) { + if (!(expression instanceof JSLiteralExpression)) { + return false; + } + String value = expression.getText(); + long intValue; - try - { - intValue = Integer.decode(value).longValue(); - } - catch(NumberFormatException e) - { - return false; - } + try { + intValue = Integer.decode(value).longValue(); + } + catch (NumberFormatException e) { + return false; + } - if(intValue <= 0) - { - return false; - } - while((intValue & 1) == 0) - { - intValue >>= 1; - } - return (intValue == 1); - } + if (intValue <= 0) { + return false; + } + while ((intValue & 1) == 0) { + intValue >>= 1; + } + return (intValue == 1); + } - public static int getLogBase2(JSExpression rhs) - { - final String value = rhs.getText(); - long intValue; + public static int getLogBase2(JSExpression rhs) { + String value = rhs.getText(); + long intValue; - try - { - intValue = Integer.decode(value).longValue(); - } - catch(NumberFormatException e) - { - assert (false); - return 0; - } + try { + intValue = Integer.decode(value).longValue(); + } + catch (NumberFormatException e) { + assert (false); + return 0; + } - int log = 0; - while((intValue & 1) == 0) - { - intValue >>= 1; - log++; - } - return log; - } + int log = 0; + while ((intValue & 1) == 0) { + intValue >>= 1; + log++; + } + return log; + } - public static int getExpBase2(JSExpression rhs) - { - final String value = rhs.getText(); - final long intValue; + public static int getExpBase2(JSExpression rhs) { + String value = rhs.getText(); + long intValue; - try - { - intValue = Integer.decode(value).longValue(); - } - catch(NumberFormatException e) - { - assert (false); - return 0; - } + try { + intValue = Integer.decode(value).longValue(); + } + catch (NumberFormatException e) { + assert (false); + return 0; + } - int exp = 1; - for(int i = 0; i < intValue; i++) - { - exp <<= 1; - } - return exp; - } + int exp = 1; + for (int i = 0; i < intValue; i++) { + exp <<= 1; + } + return exp; + } - public static boolean isIntLiteral(JSExpression expression) - { - if(!(expression instanceof JSLiteralExpression)) - { - return false; - } + public static boolean isIntLiteral(JSExpression expression) { + if (!(expression instanceof JSLiteralExpression)) { + return false; + } - if(!(expression instanceof JSLiteralExpression)) - { - return false; - } - final String value = expression.getText(); + String value = expression.getText(); - try - { - Integer.decode(value); - return true; - } - catch(NumberFormatException e) - { - return false; - } - } + try { + Integer.decode(value); + return true; + } + catch (NumberFormatException e) { + return false; + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/opassign/JSReplaceWithOperatorAssignmentIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/opassign/JSReplaceWithOperatorAssignmentIntention.java index 4c45d8e7..21480878 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/opassign/JSReplaceWithOperatorAssignmentIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/opassign/JSReplaceWithOperatorAssignmentIntention.java @@ -20,115 +20,102 @@ import com.intellij.lang.javascript.psi.JSBinaryExpression; import com.intellij.lang.javascript.psi.JSDefinitionExpression; import com.intellij.lang.javascript.psi.JSExpression; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.ast.IElementType; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSMutablyNamedIntention; import org.intellij.idea.lang.javascript.psiutil.*; -import javax.annotation.Nonnull; - @ExtensionImpl -@IntentionMetaData(ignoreId = "JSReplaceWithOperatorAssignmentIntention", categories = { - "JavaScript", - "Other" -}, fileExtensions = "js") -public class JSReplaceWithOperatorAssignmentIntention extends JSMutablyNamedIntention -{ - @Override - public String getTextForElement(PsiElement element) - { - final JSAssignmentExpression exp = (JSAssignmentExpression) element; - final JSBinaryExpression rhs = (JSBinaryExpression) exp.getROperand(); - assert (rhs != null); - final IElementType sign = rhs.getOperationSign(); +@IntentionMetaData( + ignoreId = "JSReplaceWithOperatorAssignmentIntention", + categories = {"JavaScript", "Other"}, + fileExtensions = "js" +) +public class JSReplaceWithOperatorAssignmentIntention extends JSMutablyNamedIntention { + @Nonnull + @Override + protected LocalizeValue getBasicText() { + return JSIntentionLocalize.opassignReplaceWithOperatorAssignment(); + } + + @Override + @RequiredReadAction + public LocalizeValue getTextForElement(PsiElement element) { + JSAssignmentExpression exp = (JSAssignmentExpression)element; + JSBinaryExpression rhs = (JSBinaryExpression)exp.getROperand(); + assert (rhs != null); + IElementType sign = rhs.getOperationSign(); - return this.getText(BinaryOperatorUtils.getOperatorText(sign)); - } + return JSIntentionLocalize.opassignReplaceWithOperatorAssignmentMessage(BinaryOperatorUtils.getOperatorText(sign)); + } - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new Predicate(); - } + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new Predicate(); + } - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final JSAssignmentExpression exp = (JSAssignmentExpression) element; - final JSBinaryExpression rhs = (JSBinaryExpression) exp.getROperand(); - final JSExpression lhs = exp.getLOperand(); + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + JSAssignmentExpression exp = (JSAssignmentExpression)element; + JSBinaryExpression rhs = (JSBinaryExpression)exp.getROperand(); + JSExpression lhs = exp.getLOperand(); - assert (rhs != null); + assert (rhs != null); - final IElementType sign = rhs.getOperationSign(); - final String operand = BinaryOperatorUtils.getOperatorText(sign); - final JSExpression rhsrhs = rhs.getROperand(); + IElementType sign = rhs.getOperationSign(); + String operand = BinaryOperatorUtils.getOperatorText(sign); + JSExpression rhsrhs = rhs.getROperand(); - assert (rhsrhs != null); + assert (rhsrhs != null); - JSElementFactory.replaceExpression(exp, lhs.getText() + operand + '=' + rhsrhs.getText()); - } + JSElementFactory.replaceExpression(exp, lhs.getText() + operand + '=' + rhsrhs.getText()); + } - private static class Predicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSAssignmentExpression)) - { - return false; - } - if(ErrorUtil.containsError(element)) - { - return false; - } - final JSAssignmentExpression assignment = (JSAssignmentExpression) element; - final IElementType tokenType = assignment.getOperationSign(); - if(!JSTokenTypes.EQ.equals(tokenType)) - { - return false; - } - JSExpression lhs = assignment.getLOperand(); - final JSExpression rhs = assignment.getROperand(); + private static class Predicate implements JSElementPredicate { + @Override + @RequiredReadAction + public boolean satisfiedBy(@Nonnull PsiElement element) { + if (!(element instanceof JSAssignmentExpression) || ErrorUtil.containsError(element)) { + return false; + } + JSAssignmentExpression assignment = (JSAssignmentExpression)element; + IElementType tokenType = assignment.getOperationSign(); + if (!JSTokenTypes.EQ.equals(tokenType)) { + return false; + } + JSExpression lhs = assignment.getLOperand(); + JSExpression rhs = assignment.getROperand(); - if(lhs instanceof JSDefinitionExpression) - { - lhs = ((JSDefinitionExpression) lhs).getExpression(); - } - if(lhs == null || rhs == null) - { - return false; - } - if(!(rhs instanceof JSBinaryExpression)) - { - return false; - } - final JSBinaryExpression binaryRhs = (JSBinaryExpression) rhs; - final JSExpression rhsRhs = binaryRhs.getROperand(); - final JSExpression rhsLhs = binaryRhs.getLOperand(); + if (lhs instanceof JSDefinitionExpression definitionExpression) { + lhs = definitionExpression.getExpression(); + } + if (lhs == null || !(rhs instanceof JSBinaryExpression)) { + return false; + } + JSBinaryExpression binaryRhs = (JSBinaryExpression)rhs; + JSExpression rhsRhs = binaryRhs.getROperand(); + JSExpression rhsLhs = binaryRhs.getLOperand(); - if(rhsRhs == null) - { - return false; - } + if (rhsRhs == null) { + return false; + } - final IElementType rhsTokenType = binaryRhs.getOperationSign(); + IElementType rhsTokenType = binaryRhs.getOperationSign(); - if(JSTokenTypes.OROR.equals(rhsTokenType) || - JSTokenTypes.ANDAND.equals(rhsTokenType)) - { - return false; - } - if(SideEffectChecker.mayHaveSideEffects(lhs)) - { - return false; - } - return EquivalenceChecker.expressionsAreEquivalent(lhs, rhsLhs); - } - } + return !JSTokenTypes.OROR.equals(rhsTokenType) + && !JSTokenTypes.ANDAND.equals(rhsTokenType) + && !SideEffectChecker.mayHaveSideEffects(lhs) + && EquivalenceChecker.expressionsAreEquivalent(lhs, rhsLhs); + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/parenthesis/JSRemoveUnnecessaryParenthesesIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/parenthesis/JSRemoveUnnecessaryParenthesesIntention.java index 852e4e32..7e8d7506 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/parenthesis/JSRemoveUnnecessaryParenthesesIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/parenthesis/JSRemoveUnnecessaryParenthesesIntention.java @@ -15,111 +15,89 @@ */ package org.intellij.idea.lang.javascript.intention.parenthesis; -import com.intellij.lang.javascript.psi.*; +import com.intellij.lang.javascript.psi.JSBinaryExpression; +import com.intellij.lang.javascript.psi.JSExpression; +import com.intellij.lang.javascript.psi.JSFunctionExpression; +import com.intellij.lang.javascript.psi.JSParenthesizedExpression; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.ast.IElementType; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.ErrorUtil; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; import org.intellij.idea.lang.javascript.psiutil.ParenthesesUtils; -import javax.annotation.Nonnull; - @ExtensionImpl -@IntentionMetaData(ignoreId = "JSRemoveUnnecessaryParenthesesIntention", categories = { - "JavaScript", - "Other" -}, fileExtensions = "js") -public class JSRemoveUnnecessaryParenthesesIntention extends JSIntention -{ - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new UnnecessaryParenthesesPredicate(); - } - - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - JSExpression exp = (JSExpression) element; +@IntentionMetaData( + ignoreId = "JSRemoveUnnecessaryParenthesesIntention", + categories = {"JavaScript", "Other"}, + fileExtensions = "js" +) +public class JSRemoveUnnecessaryParenthesesIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.parenthesisRemoveUnnecessaryParentheses(); + } - while(exp.getParent() instanceof JSExpression) - { - exp = (JSExpression) exp.getParent(); - assert exp != null; - } + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new UnnecessaryParenthesesPredicate(); + } - final String newExpression = ParenthesesUtils.removeParentheses(exp); + @Override + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + JSExpression exp = (JSExpression)element; - JSElementFactory.replaceExpression(exp, newExpression); - } + while (exp.getParent() instanceof JSExpression parentExp) { + exp = parentExp; + } - private static class UnnecessaryParenthesesPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSParenthesizedExpression)) - { - return false; - } - if(ErrorUtil.containsError(element)) - { - return false; - } + String newExpression = ParenthesesUtils.removeParentheses(exp); - final JSParenthesizedExpression expression = (JSParenthesizedExpression) element; - final JSElement parent = (JSElement) expression.getParent(); + JSElementFactory.replaceExpression(exp, newExpression); + } - if(!(parent instanceof JSExpression)) - { - return true; - } + private static class UnnecessaryParenthesesPredicate implements JSElementPredicate { + @Override + @RequiredReadAction + public boolean satisfiedBy(@Nonnull PsiElement element) { + if (element instanceof JSParenthesizedExpression expression && !ErrorUtil.containsError(element)) { + if (!(expression.getParent() instanceof JSExpression parentExpression)) { + return true; + } - final JSExpression body = expression.getInnerExpression(); + JSExpression body = expression.getInnerExpression(); - if(body instanceof JSParenthesizedExpression) - { - return true; - } + if (body instanceof JSParenthesizedExpression) { + return true; + } - final int parentPrecendence = ParenthesesUtils.getPrecendence((JSExpression) parent); - final int childPrecendence = ParenthesesUtils.getPrecendence(body); + int parentPrecendence = ParenthesesUtils.getPrecendence(parentExpression); + int childPrecendence = ParenthesesUtils.getPrecendence(body); - if(parentPrecendence > childPrecendence) - { - if(body instanceof JSFunctionExpression) - { - return false; - } - return true; - } - else if(parentPrecendence == childPrecendence) - { - if(parent instanceof JSBinaryExpression && - body instanceof JSBinaryExpression) - { - final IElementType parentOperator = ((JSBinaryExpression) parent).getOperationSign(); - final IElementType childOperator = ((JSBinaryExpression) body).getOperationSign(); - final JSBinaryExpression binaryExpression = (JSBinaryExpression) parent; - final JSExpression lhs = binaryExpression.getLOperand(); + if (parentPrecendence > childPrecendence) { + return !(body instanceof JSFunctionExpression); + } + else if (parentPrecendence == childPrecendence + && parentExpression instanceof JSBinaryExpression parentBinaryExpression + && body instanceof JSBinaryExpression bodyBinaryExpression) { + IElementType parentOperator = parentBinaryExpression.getOperationSign(); + IElementType childOperator = bodyBinaryExpression.getOperationSign(); + JSExpression lhs = parentBinaryExpression.getLOperand(); - return (lhs.equals(expression) && parentOperator.equals(childOperator)); - } - else - { - return false; - } - } - else - { - return false; - } - } - } + return lhs.equals(expression) && parentOperator.equals(childOperator); + } + } + return false; + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/string/JSDoubleToSingleQuotedStringIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/string/JSDoubleToSingleQuotedStringIntention.java index d7076630..49877e27 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/string/JSDoubleToSingleQuotedStringIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/string/JSDoubleToSingleQuotedStringIntention.java @@ -16,80 +16,74 @@ package org.intellij.idea.lang.javascript.intention.string; import com.intellij.lang.javascript.psi.JSLiteralExpression; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; -import javax.annotation.Nonnull; - @ExtensionImpl -@IntentionMetaData(ignoreId = "JSDoubleToSingleQuotedStringIntention", categories = { - "JavaScript", - "Other" -}, fileExtensions = "js") -public class JSDoubleToSingleQuotedStringIntention extends JSIntention -{ - @Override - @Nonnull - protected JSElementPredicate getElementPredicate() - { - return new DoubleToSingleQuotedStringPredicate(); - } +@IntentionMetaData( + ignoreId = "JSDoubleToSingleQuotedStringIntention", + categories = {"JavaScript", "Other"}, + fileExtensions = "js" +) +public class JSDoubleToSingleQuotedStringIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.stringDoubleQuotedToSingleQuoted(); + } - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final JSLiteralExpression stringLiteral = (JSLiteralExpression) element; + @Override + @Nonnull + protected JSElementPredicate getElementPredicate() { + return new DoubleToSingleQuotedStringPredicate(); + } - JSElementFactory.replaceExpression(stringLiteral, changeQuotes(stringLiteral.getText())); - } + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + JSLiteralExpression stringLiteral = (JSLiteralExpression)element; - static String changeQuotes(String stringLiteral) - { - StringBuilder buffer = new StringBuilder(stringLiteral); - int simpleIndex = stringLiteral.lastIndexOf(StringUtil.SIMPLE_QUOTE); - int doubleIndex = stringLiteral.lastIndexOf(StringUtil.DOUBLE_QUOTE, stringLiteral.length() - 2); + JSElementFactory.replaceExpression(stringLiteral, changeQuotes(stringLiteral.getText())); + } - while(simpleIndex >= 0 || doubleIndex > 0) - { - if(simpleIndex > doubleIndex) - { - if(stringLiteral.charAt(simpleIndex - 1) != StringUtil.BACKSLASH) - { - buffer.insert(simpleIndex, StringUtil.BACKSLASH); - } - simpleIndex = stringLiteral.lastIndexOf(StringUtil.SIMPLE_QUOTE, simpleIndex - 1); - } - else - { - if(stringLiteral.charAt(doubleIndex - 1) == StringUtil.BACKSLASH) - { - buffer.deleteCharAt(doubleIndex - 1); - } - doubleIndex = stringLiteral.lastIndexOf(StringUtil.DOUBLE_QUOTE, doubleIndex - 2); - } - } - buffer.setCharAt(0, StringUtil.SIMPLE_QUOTE); - buffer.setCharAt(buffer.length() - 1, StringUtil.SIMPLE_QUOTE); + static String changeQuotes(String stringLiteral) { + StringBuilder buffer = new StringBuilder(stringLiteral); + int simpleIndex = stringLiteral.lastIndexOf(StringUtil.SIMPLE_QUOTE); + int doubleIndex = stringLiteral.lastIndexOf(StringUtil.DOUBLE_QUOTE, stringLiteral.length() - 2); - return buffer.toString(); - } + while (simpleIndex >= 0 || doubleIndex > 0) { + if (simpleIndex > doubleIndex) { + if (stringLiteral.charAt(simpleIndex - 1) != StringUtil.BACKSLASH) { + buffer.insert(simpleIndex, StringUtil.BACKSLASH); + } + simpleIndex = stringLiteral.lastIndexOf(StringUtil.SIMPLE_QUOTE, simpleIndex - 1); + } + else { + if (stringLiteral.charAt(doubleIndex - 1) == StringUtil.BACKSLASH) { + buffer.deleteCharAt(doubleIndex - 1); + } + doubleIndex = stringLiteral.lastIndexOf(StringUtil.DOUBLE_QUOTE, doubleIndex - 2); + } + } + buffer.setCharAt(0, StringUtil.SIMPLE_QUOTE); + buffer.setCharAt(buffer.length() - 1, StringUtil.SIMPLE_QUOTE); - private static class DoubleToSingleQuotedStringPredicate implements JSElementPredicate - { + return buffer.toString(); + } - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSLiteralExpression)) - { - return false; - } - return StringUtil.isDoubleQuoteStringLiteral((JSLiteralExpression) element); - } - } + private static class DoubleToSingleQuotedStringPredicate implements JSElementPredicate { + @Override + public boolean satisfiedBy(@Nonnull PsiElement element) { + return element instanceof JSLiteralExpression literalExpression && StringUtil.isDoubleQuoteStringLiteral(literalExpression); + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/string/JSJoinConcatenatedStringLiteralsIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/string/JSJoinConcatenatedStringLiteralsIntention.java index e2458f2a..c603fcc6 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/string/JSJoinConcatenatedStringLiteralsIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/string/JSJoinConcatenatedStringLiteralsIntention.java @@ -21,101 +21,80 @@ import com.intellij.lang.javascript.psi.JSLiteralExpression; import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.javascript.lang.JavaScriptTokenSets; import consulo.javascript.psi.JSSimpleLiteralExpression; -import consulo.language.ast.IElementType; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; -import javax.annotation.Nonnull; - @ExtensionImpl -@IntentionMetaData(ignoreId = "JSJoinConcatenatedStringLiteralsIntention", categories = { - "JavaScript", - "Other" -}, fileExtensions = "js") -public class JSJoinConcatenatedStringLiteralsIntention extends JSIntention -{ - @Override - @Nonnull - protected JSElementPredicate getElementPredicate() - { - return new StringConcatPredicate(); - } - - @Override - public void processIntention(@Nonnull PsiElement element) - throws IncorrectOperationException - { - final JSBinaryExpression expression = (JSBinaryExpression) element; - final JSExpression lhs = expression.getLOperand(); - final JSExpression rhs = expression.getROperand(); - - assert (lhs instanceof JSLiteralExpression && rhs instanceof JSLiteralExpression); - - final JSLiteralExpression leftLiteral = (JSLiteralExpression) lhs; - final JSLiteralExpression rightLiteral = (JSLiteralExpression) rhs; - String lhsText = lhs.getText(); - String rhsText = rhs.getText(); - final String newExpression; +@IntentionMetaData( + ignoreId = "JSJoinConcatenatedStringLiteralsIntention", + categories = {"JavaScript", "Other"}, + fileExtensions = "js" +) +public class JSJoinConcatenatedStringLiteralsIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.stringJoinConcatenatedStringLiterals(); + } - if(StringUtil.isSimpleQuoteStringLiteral(leftLiteral) && - StringUtil.isDoubleQuoteStringLiteral(rightLiteral)) - { - rhsText = JSDoubleToSingleQuotedStringIntention.changeQuotes(rhsText); - } - else if(StringUtil.isDoubleQuoteStringLiteral(leftLiteral) && - StringUtil.isSimpleQuoteStringLiteral(rightLiteral)) - { - rhsText = JSSingleToDoubleQuotedStringIntention.changeQuotes(rhsText); - } + @Override + @Nonnull + protected JSElementPredicate getElementPredicate() { + return new StringConcatPredicate(); + } - newExpression = lhsText.substring(0, lhsText.length() - 1) + rhsText.substring(1); - JSElementFactory.replaceExpression(expression, newExpression); - } + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + JSBinaryExpression expression = (JSBinaryExpression)element; + JSExpression lhs = expression.getLOperand(); + JSExpression rhs = expression.getROperand(); - private static class StringConcatPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSBinaryExpression)) - { - return false; - } + assert (lhs instanceof JSLiteralExpression && rhs instanceof JSLiteralExpression); - final JSBinaryExpression expression = (JSBinaryExpression) element; - final IElementType sign = expression.getOperationSign(); + JSLiteralExpression leftLiteral = (JSLiteralExpression)lhs; + JSLiteralExpression rightLiteral = (JSLiteralExpression)rhs; + String lhsText = lhs.getText(); + String rhsText = rhs.getText(); + String newExpression; - if(!sign.equals(JSTokenTypes.PLUS)) - { - return false; - } - final JSExpression lhs = expression.getLOperand(); - final JSExpression rhs = expression.getROperand(); + if (StringUtil.isSimpleQuoteStringLiteral(leftLiteral) + && StringUtil.isDoubleQuoteStringLiteral(rightLiteral)) { + rhsText = JSDoubleToSingleQuotedStringIntention.changeQuotes(rhsText); + } + else if (StringUtil.isDoubleQuoteStringLiteral(leftLiteral) + && StringUtil.isSimpleQuoteStringLiteral(rightLiteral)) { + rhsText = JSSingleToDoubleQuotedStringIntention.changeQuotes(rhsText); + } - if(!isApplicableLiteral(lhs)) - { - return false; - } - if(!isApplicableLiteral(rhs)) - { - return false; - } + newExpression = lhsText.substring(0, lhsText.length() - 1) + rhsText.substring(1); + JSElementFactory.replaceExpression(expression, newExpression); + } - return true; - } + private static class StringConcatPredicate implements JSElementPredicate { + @Override + @RequiredReadAction + public boolean satisfiedBy(@Nonnull PsiElement element) { + return element instanceof JSBinaryExpression expression + && JSTokenTypes.PLUS.equals(expression.getOperationSign()) + && isApplicableLiteral(expression.getLOperand()) + && isApplicableLiteral(expression.getROperand()); + } - @RequiredReadAction - private static boolean isApplicableLiteral(JSExpression lhs) - { - return lhs != null && - lhs instanceof JSSimpleLiteralExpression && - JavaScriptTokenSets.STRING_LITERALS.contains(((JSSimpleLiteralExpression) lhs).getLiteralElementType()); - } - } + @RequiredReadAction + private static boolean isApplicableLiteral(JSExpression lhs) { + return lhs != null + && lhs instanceof JSSimpleLiteralExpression simpleLiteralExpression + && JavaScriptTokenSets.STRING_LITERALS.contains(simpleLiteralExpression.getLiteralElementType()); + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/string/JSSingleToDoubleQuotedStringIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/string/JSSingleToDoubleQuotedStringIntention.java index e3aaba47..b8b7a940 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/string/JSSingleToDoubleQuotedStringIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/string/JSSingleToDoubleQuotedStringIntention.java @@ -16,82 +16,74 @@ package org.intellij.idea.lang.javascript.intention.string; import com.intellij.lang.javascript.psi.JSLiteralExpression; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; -import javax.annotation.Nonnull; - @ExtensionImpl -@IntentionMetaData(ignoreId = "JSSingleToDoubleQuotedStringIntention", categories = { - "JavaScript", - "Other" -}, fileExtensions = "js") -public class JSSingleToDoubleQuotedStringIntention extends JSIntention -{ - @Override - @Nonnull - protected JSElementPredicate getElementPredicate() - { - return new SingleToDoubleQuotedStringPredicate(); - } - - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final JSLiteralExpression charLiteral = (JSLiteralExpression) element; +@IntentionMetaData( + ignoreId = "JSSingleToDoubleQuotedStringIntention", + categories = {"JavaScript", "Other"}, + fileExtensions = "js" +) +public class JSSingleToDoubleQuotedStringIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.stringSingleToDoubleQuotedString(); + } - JSElementFactory.replaceExpression(charLiteral, changeQuotes(charLiteral.getText())); - } + @Override + @Nonnull + protected JSElementPredicate getElementPredicate() { + return new SingleToDoubleQuotedStringPredicate(); + } - static String changeQuotes(String charLiteral) - { - StringBuilder buffer = new StringBuilder(charLiteral); - int simpleIndex = charLiteral.lastIndexOf(StringUtil.SIMPLE_QUOTE, charLiteral.length() - 2); - int doubleIndex = charLiteral.lastIndexOf(StringUtil.DOUBLE_QUOTE); + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + JSLiteralExpression charLiteral = (JSLiteralExpression)element; - while(simpleIndex > 0 || doubleIndex >= 0) - { - if(simpleIndex > doubleIndex) - { - if(charLiteral.charAt(simpleIndex - 1) == StringUtil.BACKSLASH) - { - buffer.deleteCharAt(simpleIndex - 1); - } - simpleIndex = charLiteral.lastIndexOf(StringUtil.SIMPLE_QUOTE, simpleIndex - 2); - } - else - { - if(charLiteral.charAt(doubleIndex - 1) != StringUtil.BACKSLASH) - { - buffer.insert(doubleIndex, StringUtil.BACKSLASH); - } - doubleIndex = charLiteral.lastIndexOf(StringUtil.DOUBLE_QUOTE, doubleIndex - 1); - } - } - buffer.setCharAt(0, StringUtil.DOUBLE_QUOTE); - buffer.setCharAt(buffer.length() - 1, StringUtil.DOUBLE_QUOTE); + JSElementFactory.replaceExpression(charLiteral, changeQuotes(charLiteral.getText())); + } - return buffer.toString(); - } + static String changeQuotes(String charLiteral) { + StringBuilder buffer = new StringBuilder(charLiteral); + int simpleIndex = charLiteral.lastIndexOf(StringUtil.SIMPLE_QUOTE, charLiteral.length() - 2); + int doubleIndex = charLiteral.lastIndexOf(StringUtil.DOUBLE_QUOTE); - private static class SingleToDoubleQuotedStringPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSLiteralExpression)) - { - return false; - } + while (simpleIndex > 0 || doubleIndex >= 0) { + if (simpleIndex > doubleIndex) { + if (charLiteral.charAt(simpleIndex - 1) == StringUtil.BACKSLASH) { + buffer.deleteCharAt(simpleIndex - 1); + } + simpleIndex = charLiteral.lastIndexOf(StringUtil.SIMPLE_QUOTE, simpleIndex - 2); + } + else { + if (charLiteral.charAt(doubleIndex - 1) != StringUtil.BACKSLASH) { + buffer.insert(doubleIndex, StringUtil.BACKSLASH); + } + doubleIndex = charLiteral.lastIndexOf(StringUtil.DOUBLE_QUOTE, doubleIndex - 1); + } + } + buffer.setCharAt(0, StringUtil.DOUBLE_QUOTE); + buffer.setCharAt(buffer.length() - 1, StringUtil.DOUBLE_QUOTE); - final JSLiteralExpression expression = (JSLiteralExpression) element; + return buffer.toString(); + } - return StringUtil.isSimpleQuoteStringLiteral(expression); - } - } + private static class SingleToDoubleQuotedStringPredicate implements JSElementPredicate { + @Override + public boolean satisfiedBy(@Nonnull PsiElement element) { + return element instanceof JSLiteralExpression expression && StringUtil.isSimpleQuoteStringLiteral(expression); + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/string/StringUtil.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/string/StringUtil.java index d014e24a..383431ab 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/string/StringUtil.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/string/StringUtil.java @@ -17,32 +17,28 @@ import com.intellij.lang.javascript.psi.JSLiteralExpression; -class StringUtil -{ - public static final char SIMPLE_QUOTE = '\''; - public static final char DOUBLE_QUOTE = '"'; - public static final char BACKSLASH = '\\'; - - private StringUtil() - { - } - - public static boolean isSimpleQuoteStringLiteral(JSLiteralExpression expression) - { - final String value = expression.getText(); - - return (value != null && - value.charAt(0) == SIMPLE_QUOTE && - value.charAt(value.length() - 1) == SIMPLE_QUOTE); - } - - public static boolean isDoubleQuoteStringLiteral(JSLiteralExpression expression) - { - final String value = expression.getText(); - - return (value != null && - value.charAt(0) == DOUBLE_QUOTE && - value.charAt(value.length() - 1) == DOUBLE_QUOTE); - } +class StringUtil { + public static final char SIMPLE_QUOTE = '\''; + public static final char DOUBLE_QUOTE = '"'; + public static final char BACKSLASH = '\\'; + + private StringUtil() { + } + + public static boolean isSimpleQuoteStringLiteral(JSLiteralExpression expression) { + String value = expression.getText(); + + return (value != null && + value.charAt(0) == SIMPLE_QUOTE && + value.charAt(value.length() - 1) == SIMPLE_QUOTE); + } + + public static boolean isDoubleQuoteStringLiteral(JSLiteralExpression expression) { + String value = expression.getText(); + + return (value != null && + value.charAt(0) == DOUBLE_QUOTE && + value.charAt(value.length() - 1) == DOUBLE_QUOTE); + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/switchtoif/CaseUtil.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/switchtoif/CaseUtil.java index 5db0821d..ada6aebc 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/switchtoif/CaseUtil.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/switchtoif/CaseUtil.java @@ -28,238 +28,175 @@ import java.util.ArrayList; import java.util.List; -class CaseUtil -{ - - private CaseUtil() - { - } - - private static boolean canBeCaseLabel(JSExpression expression) - { - if(expression == null) - { - return false; - } - return ExpressionUtil.isConstantExpression(expression); - } - - public static boolean containsHiddenBreak(JSCaseClause caseClause) - { - for(JSStatement statement : caseClause.getStatements()) - { - if(CaseUtil.containsHiddenBreak(statement, true)) - { - return true; - } - } - return false; - } - - public static boolean containsHiddenBreak(List elements) - { - for(final PsiElement element : elements) - { - if(element instanceof JSStatement && - containsHiddenBreak((JSStatement) element, true)) - { - return true; - } - } - return false; - } - - public static boolean containsHiddenBreak(JSStatement statement) - { - return containsHiddenBreak(statement, true); - } - - private static boolean containsHiddenBreak(JSStatement statement, - boolean isTopLevel) - { - if(statement instanceof JSBlockStatement) - { - final JSStatement[] statements = ((JSBlockStatement) statement).getStatements(); - for(final JSStatement childStatement : statements) - { - if(containsHiddenBreak(childStatement, false)) - { - return true; - } - } - } - else if(statement instanceof JSIfStatement) - { - final JSIfStatement ifStatement = (JSIfStatement) statement; - - return (containsHiddenBreak(ifStatement.getThen(), false) || - containsHiddenBreak(ifStatement.getElse(), false)); - } - else if(statement instanceof JSBreakStatement) - { - if(isTopLevel) - { - return false; - } - - final String identifier = ((JSBreakStatement) statement).getLabel(); - - return (identifier == null || identifier.length() == 0); - } - - return false; - } - - public static boolean isUsedByStatementList(JSVariable var, - List elements) - { - for(PsiElement element : elements) - { - if(element instanceof JSElement && - isUsedByStatement(var, (JSElement) element)) - { - return true; - } - } - return false; - } - - private static boolean isUsedByStatement(JSVariable var, - JSElement statement) - { - final LocalVariableUsageVisitor visitor = new LocalVariableUsageVisitor(var); - statement.accept(visitor); - return visitor.isUsed(); - } - - public static String findUniqueLabel(JSStatement statement, - String baseName) - { - JSElement ancestor = statement; - - while(ancestor.getParent() != null) - { - if(ancestor instanceof PsiFile) - { - break; - } - ancestor = (JSElement) ancestor.getParent(); - } - - if(!checkForLabel(baseName, ancestor)) - { - return baseName; - } - - int val = 1; - - while(true) - { - final String name = baseName + val; - - if(!checkForLabel(name, ancestor)) - { - return name; - } - val++; - } - } - - private static boolean checkForLabel(String name, JSElement ancestor) - { - final LabelSearchVisitor visitor = new LabelSearchVisitor(name); - ancestor.accept(visitor); - return visitor.isUsed(); - } - - public static JSExpression getCaseExpression(JSIfStatement statement) - { - final JSExpression condition = statement.getCondition(); - final List possibleCaseExpressions = determinePossibleCaseExpressions(condition); - - if(possibleCaseExpressions != null) - { - for(final JSExpression caseExpression : possibleCaseExpressions) - { - if(!SideEffectChecker.mayHaveSideEffects(caseExpression)) - { - JSIfStatement statementToCheck = statement; - - while(canBeMadeIntoCase(statementToCheck.getCondition(), caseExpression)) - { - final JSStatement elseBranch = statementToCheck.getElse(); - - if(elseBranch == null || !(elseBranch instanceof JSIfStatement)) - { - return caseExpression; - } - statementToCheck = (JSIfStatement) elseBranch; - } - } - } - } - return null; - } - - private static List determinePossibleCaseExpressions(JSExpression exp) - { - final JSExpression expToCheck = ParenthesesUtils.stripParentheses(exp); - final List out = new ArrayList(10); - - if(expToCheck instanceof JSBinaryExpression) - { - final JSBinaryExpression binaryExp = (JSBinaryExpression) expToCheck; - final IElementType operation = binaryExp.getOperationSign(); - final JSExpression lhs = binaryExp.getLOperand(); - final JSExpression rhs = binaryExp.getROperand(); - - if(operation.equals(JSTokenTypes.OROR)) - { - return determinePossibleCaseExpressions(lhs); - } - else if(operation.equals(JSTokenTypes.EQEQ)) - { - if(canBeCaseLabel(lhs) && rhs != null) - { - out.add(rhs); - } - if(canBeCaseLabel(rhs)) - { - out.add(lhs); - } - } - } - return out; - } - - private static boolean canBeMadeIntoCase(JSExpression exp, - JSExpression caseExpression) - { - final JSExpression expToCheck = ParenthesesUtils.stripParentheses(exp); - - if(!(expToCheck instanceof JSBinaryExpression)) - { - return false; - } - - final JSBinaryExpression binaryExp = (JSBinaryExpression) expToCheck; - final IElementType operation = binaryExp.getOperationSign(); - final JSExpression leftOperand = binaryExp.getLOperand(); - final JSExpression rightOperand = binaryExp.getROperand(); - - if(operation.equals(JSTokenTypes.OROR)) - { - return (canBeMadeIntoCase(leftOperand, caseExpression) && - canBeMadeIntoCase(rightOperand, caseExpression)); - } - else if(operation.equals(JSTokenTypes.EQEQ)) - { - return ((canBeCaseLabel(leftOperand) && EquivalenceChecker.expressionsAreEquivalent(caseExpression, rightOperand)) || - (canBeCaseLabel(rightOperand) && EquivalenceChecker.expressionsAreEquivalent(caseExpression, leftOperand))); - } - else - { - return false; - } - } +class CaseUtil { + private CaseUtil() { + } + + private static boolean canBeCaseLabel(JSExpression expression) { + return expression != null && ExpressionUtil.isConstantExpression(expression); + } + + public static boolean containsHiddenBreak(JSCaseClause caseClause) { + for (JSStatement statement : caseClause.getStatements()) { + if (CaseUtil.containsHiddenBreak(statement, true)) { + return true; + } + } + return false; + } + + public static boolean containsHiddenBreak(List elements) { + for (PsiElement element : elements) { + if (element instanceof JSStatement statement && containsHiddenBreak(statement, true)) { + return true; + } + } + return false; + } + + public static boolean containsHiddenBreak(JSStatement statement) { + return containsHiddenBreak(statement, true); + } + + private static boolean containsHiddenBreak(JSStatement statement, boolean isTopLevel) { + if (statement instanceof JSBlockStatement blockStatement) { + for (JSStatement childStatement : blockStatement.getStatements()) { + if (containsHiddenBreak(childStatement, false)) { + return true; + } + } + } + else if (statement instanceof JSIfStatement ifStatement) { + return containsHiddenBreak(ifStatement.getThen(), false) || containsHiddenBreak(ifStatement.getElse(), false); + } + else if (statement instanceof JSBreakStatement breakStatement) { + if (isTopLevel) { + return false; + } + + String identifier = breakStatement.getLabel(); + + return (identifier == null || identifier.length() == 0); + } + + return false; + } + + public static boolean isUsedByStatementList(JSVariable var, List elements) { + for (PsiElement element : elements) { + if (element instanceof JSElement jsElement && isUsedByStatement(var, jsElement)) { + return true; + } + } + return false; + } + + private static boolean isUsedByStatement(JSVariable var, JSElement statement) { + LocalVariableUsageVisitor visitor = new LocalVariableUsageVisitor(var); + statement.accept(visitor); + return visitor.isUsed(); + } + + public static String findUniqueLabel(JSStatement statement, String baseName) { + JSElement ancestor = statement; + + while (ancestor.getParent() != null) { + if (ancestor instanceof PsiFile) { + break; + } + ancestor = (JSElement)ancestor.getParent(); + } + + if (!checkForLabel(baseName, ancestor)) { + return baseName; + } + + int val = 1; + + while (true) { + String name = baseName + val; + + if (!checkForLabel(name, ancestor)) { + return name; + } + val++; + } + } + + private static boolean checkForLabel(String name, JSElement ancestor) { + LabelSearchVisitor visitor = new LabelSearchVisitor(name); + ancestor.accept(visitor); + return visitor.isUsed(); + } + + public static JSExpression getCaseExpression(JSIfStatement statement) { + JSExpression condition = statement.getCondition(); + List possibleCaseExpressions = determinePossibleCaseExpressions(condition); + + if (possibleCaseExpressions != null) { + for (JSExpression caseExpression : possibleCaseExpressions) { + if (!SideEffectChecker.mayHaveSideEffects(caseExpression)) { + JSIfStatement statementToCheck = statement; + + while (canBeMadeIntoCase(statementToCheck.getCondition(), caseExpression)) { + JSStatement elseBranch = statementToCheck.getElse(); + + if (elseBranch == null || !(elseBranch instanceof JSIfStatement)) { + return caseExpression; + } + statementToCheck = (JSIfStatement)elseBranch; + } + } + } + } + return null; + } + + private static List determinePossibleCaseExpressions(JSExpression exp) { + JSExpression expToCheck = ParenthesesUtils.stripParentheses(exp); + List out = new ArrayList<>(10); + + if (expToCheck instanceof JSBinaryExpression binaryExp) { + IElementType operation = binaryExp.getOperationSign(); + JSExpression lhs = binaryExp.getLOperand(); + JSExpression rhs = binaryExp.getROperand(); + + if (JSTokenTypes.OROR.equals(operation)) { + return determinePossibleCaseExpressions(lhs); + } + else if (JSTokenTypes.EQEQ.equals(operation)) { + if (canBeCaseLabel(lhs) && rhs != null) { + out.add(rhs); + } + if (canBeCaseLabel(rhs)) { + out.add(lhs); + } + } + } + return out; + } + + private static boolean canBeMadeIntoCase(JSExpression exp, JSExpression caseExpression) { + JSExpression expToCheck = ParenthesesUtils.stripParentheses(exp); + + if (!(expToCheck instanceof JSBinaryExpression)) { + return false; + } + + JSBinaryExpression binaryExp = (JSBinaryExpression)expToCheck; + IElementType operation = binaryExp.getOperationSign(); + JSExpression leftOperand = binaryExp.getLOperand(); + JSExpression rightOperand = binaryExp.getROperand(); + + if (JSTokenTypes.OROR.equals(operation)) { + return canBeMadeIntoCase(leftOperand, caseExpression) && canBeMadeIntoCase(rightOperand, caseExpression); + } + else if (JSTokenTypes.EQEQ.equals(operation)) { + return (canBeCaseLabel(leftOperand) && EquivalenceChecker.expressionsAreEquivalent(caseExpression, rightOperand) + || (canBeCaseLabel(rightOperand) && EquivalenceChecker.expressionsAreEquivalent(caseExpression, leftOperand))); + } + else { + return false; + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/switchtoif/JSReplaceIfWithSwitchIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/switchtoif/JSReplaceIfWithSwitchIntention.java index 95fa8662..84819e80 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/switchtoif/JSReplaceIfWithSwitchIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/switchtoif/JSReplaceIfWithSwitchIntention.java @@ -17,485 +17,397 @@ import com.intellij.lang.javascript.JSTokenTypes; import com.intellij.lang.javascript.psi.*; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.ast.IElementType; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.*; import org.jetbrains.annotations.NonNls; -import javax.annotation.Nonnull; import java.util.*; @ExtensionImpl -@IntentionMetaData(ignoreId = "JSReplaceIfWithSwitchIntention", categories = { - "JavaScript", - "Control Flow" -}, fileExtensions = "js") -public class JSReplaceIfWithSwitchIntention extends JSIntention -{ - @NonNls - private static final String IF_KEYWORD = "if"; - @NonNls - private static final String DEFAULT_LABEL_NAME = "Label"; - @NonNls - private static final String SWITCH_STATEMENT_PREFIX = "switch("; - @NonNls - private static final String DEFAULT_CASE_CLAUSE_EXPRESSION = "default: "; - @NonNls - private static final String CASE_EXPRESSION_PREFIX = "\ncase "; - @NonNls - private static final String LABELED_BREAK_STATEMENT_PREFIX = "break "; - @NonNls - private static final String BREAK_STATEMENT = "\nbreak;"; - - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new IfToSwitchPredicate(); - } - - @Override - public void processIntention(@Nonnull PsiElement element) - throws IncorrectOperationException - { - JSIfStatement ifStatement = (JSIfStatement) element.getParent(); - - assert (ifStatement != null); - - boolean breaksNeedRelabeled = false; - JSStatement breakTarget = null; - String labelString = ""; - - if(ControlFlowUtils.statementContainsExitingBreak(ifStatement)) - { - JSElement ancestor = (JSElement) ifStatement.getParent(); - while(ancestor != null) - { - if(ancestor instanceof JSForStatement || - ancestor instanceof JSForInStatement || - ancestor instanceof JSDoWhileStatement || - ancestor instanceof JSWhileStatement || - ancestor instanceof JSSwitchStatement) - { - breakTarget = (JSStatement) ancestor; - break; - } - ancestor = (JSElement) ancestor.getParent(); - } - if(breakTarget != null) - { - labelString = CaseUtil.findUniqueLabel(ifStatement, DEFAULT_LABEL_NAME); - breaksNeedRelabeled = true; - } - } - final JSIfStatement statementToReplace = ifStatement; - final JSExpression caseExpression = CaseUtil.getCaseExpression(ifStatement); - - assert (caseExpression != null); - - final StringBuilder switchStatementBuffer = new StringBuilder(1024); - - switchStatementBuffer.append(SWITCH_STATEMENT_PREFIX) - .append(caseExpression.getText()) - .append(')') - .append('{'); - - final List branches = new ArrayList(20); - - while(true) - { - final Set topLevelVariables = new HashSet(5); - final Set innerVariables = new HashSet(5); - final JSExpression condition = ifStatement.getCondition(); - final JSExpression[] labels = getValuesFromCondition(condition, caseExpression); - final JSStatement thenBranch = ifStatement.getThen(); - - DeclarationUtils.calculateVariablesDeclared(thenBranch, - topLevelVariables, - innerVariables, - true); - - final IfStatementBranch ifBranch = new IfStatementBranch(); - - ifBranch.setInnerVariables(innerVariables); - ifBranch.setTopLevelVariables(topLevelVariables); - ifBranch.setStatement(thenBranch); - for(final JSExpression label : labels) - { - ifBranch.addCondition(label.getText()); - } - branches.add(ifBranch); - - final JSStatement elseBranch = ifStatement.getElse(); - - if(elseBranch instanceof JSIfStatement) - { - ifStatement = (JSIfStatement) elseBranch; - } - else if(elseBranch == null) - { - break; - } - else - { - final Set elseTopLevelVariables = new HashSet(5); - final Set elseInnerVariables = new HashSet(5); - - DeclarationUtils.calculateVariablesDeclared(elseBranch, elseTopLevelVariables, - elseInnerVariables, true); - - final IfStatementBranch elseIfBranch = new IfStatementBranch(); - - elseIfBranch.setInnerVariables(elseInnerVariables); - elseIfBranch.setTopLevelVariables(elseTopLevelVariables); - elseIfBranch.setElse(); - elseIfBranch.setStatement(elseBranch); - branches.add(elseIfBranch); - break; - } - } - - for(IfStatementBranch branch : branches) - { - boolean hasConflicts = false; - for(IfStatementBranch testBranch : branches) - { - if(branch.topLevelDeclarationsConfictWith(testBranch)) - { - hasConflicts = true; - } - } - - final JSStatement branchStatement = (JSStatement) branch.getStatement(); - - if(branch.isElse()) - { - dumpDefaultBranch(switchStatementBuffer, branchStatement, - hasConflicts, breaksNeedRelabeled, labelString); - } - else - { - final List conditions = branch.getConditions(); - - dumpBranch(switchStatementBuffer, conditions, branchStatement, - hasConflicts, breaksNeedRelabeled, labelString); - } - } - - switchStatementBuffer.append('}'); - - final String switchStatementString = switchStatementBuffer.toString(); - - if(breaksNeedRelabeled) - { - final int length = switchStatementBuffer.length(); - final StringBuilder out = new StringBuilder(length); - - out.append(labelString) - .append(':'); - termReplace(out, breakTarget, statementToReplace, switchStatementString); - JSElementFactory.replaceStatement(breakTarget, out.toString()); - } - else - { - JSElementFactory.replaceStatement(statementToReplace, switchStatementString); - } - } - - private static void termReplace(StringBuilder out, - JSElement target, - JSElement replace, - String stringToReplaceWith) - { - if(target.equals(replace)) - { - out.append(stringToReplaceWith); - } - else if(target.getChildren().length != 0) - { - final JSElement[] children = (JSElement[]) target.getChildren(); - for(final JSElement child : children) - { - termReplace(out, child, replace, stringToReplaceWith); - } - } - else - { - final String text = target.getText(); - out.append(text); - } - } - - private static JSExpression[] getValuesFromCondition(JSExpression condition, - JSExpression caseExpression) - { - final List values = new ArrayList(10); - - getValuesFromExpression(condition, caseExpression, values); - return values.toArray(new JSExpression[values.size()]); - } - - private static void getValuesFromExpression(JSExpression expression, - JSExpression caseExpression, - List values) - { - if(expression instanceof JSBinaryExpression) - { - final JSBinaryExpression binaryExpression = - (JSBinaryExpression) expression; - final JSExpression lhs = binaryExpression.getLOperand(); - final JSExpression rhs = binaryExpression.getROperand(); - final IElementType tokenType = binaryExpression.getOperationSign(); - - if(JSTokenTypes.OROR.equals(tokenType)) - { - getValuesFromExpression(lhs, caseExpression, values); - getValuesFromExpression(rhs, caseExpression, values); - } - else - { - if(EquivalenceChecker.expressionsAreEquivalent(caseExpression, rhs)) - { - values.add(lhs); - } - else - { - values.add(rhs); - } - } - } - else if(expression instanceof JSParenthesizedExpression) - { - final JSParenthesizedExpression parenExpression = (JSParenthesizedExpression) expression; - final JSExpression contents = parenExpression.getInnerExpression(); - - getValuesFromExpression(contents, caseExpression, values); - } - } - - private static void dumpBranch(StringBuilder switchStatementString, - List labels, - JSStatement body, - boolean wrap, - boolean renameBreaks, - String breakLabelName) - { - dumpLabels(switchStatementString, labels); - dumpBody(switchStatementString, body, wrap, renameBreaks, breakLabelName); - } - - private static void dumpDefaultBranch(StringBuilder switchStatementString, - JSStatement body, - boolean wrap, - boolean renameBreaks, - String breakLabelName) - { - switchStatementString.append(DEFAULT_CASE_CLAUSE_EXPRESSION); - dumpBody(switchStatementString, body, wrap, renameBreaks, breakLabelName); - } - - private static void dumpLabels(StringBuilder switchStatementString, - List labels) - { - for(String label : labels) - { - switchStatementString.append(CASE_EXPRESSION_PREFIX); - switchStatementString.append(label); - switchStatementString.append(": "); - } - } - - private static void dumpBody(StringBuilder switchStatementString, - JSStatement bodyStatement, - boolean wrap, - boolean renameBreaks, - String breakLabelName) - { - if(bodyStatement instanceof JSBlockStatement) - { - if(wrap) - { - appendElement(switchStatementString, bodyStatement, - renameBreaks, breakLabelName); - } - else - { - // Skip the first and last characters to unwrap the block - final String bodyText = bodyStatement.getText(); - switchStatementString.append(bodyText.substring(1, bodyText.length() - 1)); - } - } - else - { - if(wrap) - { - switchStatementString.append('{'); - appendElement(switchStatementString, bodyStatement, - renameBreaks, breakLabelName); - switchStatementString.append('}'); - } - else - { - appendElement(switchStatementString, bodyStatement, - renameBreaks, breakLabelName); - } - } - if(ControlFlowUtils.statementMayCompleteNormally(bodyStatement)) - { - switchStatementString.append(BREAK_STATEMENT); - } - switchStatementString.append('\n'); - } - - private static void appendElement(StringBuilder switchStatementString, - JSElement element, - boolean renameBreakElements, - String breakLabelString) - { - final String text = element.getText(); - - if(!renameBreakElements) - { - switchStatementString.append(text); - } - else if(element instanceof JSBreakStatement) - { - final String identifier = ((JSBreakStatement) element).getLabel(); - if(identifier == null || identifier.length() == 0) - { - switchStatementString.append(LABELED_BREAK_STATEMENT_PREFIX); - switchStatementString.append(breakLabelString); - switchStatementString.append(';'); - } - else - { - switchStatementString.append(text); - } - } - else if(element instanceof JSBlockStatement || - element instanceof JSIfStatement) - { - final JSElement[] children = (JSElement[]) element.getChildren(); - for(final JSElement child : children) - { - appendElement(switchStatementString, child, renameBreakElements, - breakLabelString); - } - } - else - { - switchStatementString.append(text); - } - } - - private static class IfToSwitchPredicate implements JSElementPredicate - { - - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - final PsiElement parent = element.getParent(); - if(!(parent instanceof JSIfStatement)) - { - return false; - } - final String text = element.getText(); - if(!IF_KEYWORD.equals(text)) - { - return false; - } - final JSIfStatement statement = (JSIfStatement) parent; - if(ErrorUtil.containsError(statement)) - { - return false; - } - return (CaseUtil.getCaseExpression(statement) != null); - } - } - - private static class IfStatementBranch - { - private final List conditions = new ArrayList(3); - private Set topLevelVariables = new HashSet(3); - private Set innerVariables = new HashSet(3); - private JSStatement statement; - private boolean isElse; - - public void addCondition(String conditionString) - { - this.conditions.add(conditionString); - } - - public void setStatement(JSStatement statement) - { - this.statement = statement; - } - - public JSStatement getStatement() - { - return this.statement; - } - - public List getConditions() - { - return Collections.unmodifiableList(this.conditions); - } - - public boolean isElse() - { - return this.isElse; - } - - public void setElse() - { - this.isElse = true; - } - - public void setTopLevelVariables(Set topLevelVariables) - { - this.topLevelVariables = new HashSet(topLevelVariables); - } - - public void setInnerVariables(Set innerVariables) - { - this.innerVariables = new HashSet(innerVariables); - } - - private Set getTopLevelVariables() - { - return Collections.unmodifiableSet(this.topLevelVariables); - } - - private Set getInnerVariables() - { - return Collections.unmodifiableSet(this.innerVariables); - } - - public boolean topLevelDeclarationsConfictWith(IfStatementBranch testBranch) - { - final Set innerVariables = testBranch.getInnerVariables(); - final Set topLevel = testBranch.getTopLevelVariables(); - - return (hasNonEmptyIntersection(this.topLevelVariables, topLevel) || - hasNonEmptyIntersection(this.topLevelVariables, innerVariables)); - } - - private static boolean hasNonEmptyIntersection(Set set1, - Set set2) - { - for(final String set1Element : set1) - { - if(set2.contains(set1Element)) - { - return true; - } - } - return false; - } - } +@IntentionMetaData( + ignoreId = "JSReplaceIfWithSwitchIntention", + categories = {"JavaScript", "Control Flow"}, + fileExtensions = "js" +) +public class JSReplaceIfWithSwitchIntention extends JSIntention { + @NonNls + private static final String IF_KEYWORD = "if"; + @NonNls + private static final String DEFAULT_LABEL_NAME = "Label"; + @NonNls + private static final String DEFAULT_CASE_CLAUSE_EXPRESSION = "default: "; + @NonNls + private static final String LABELED_BREAK_STATEMENT_PREFIX = "break "; + @NonNls + private static final String BREAK_STATEMENT = "\nbreak;"; + + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.switchtoifReplaceIfWithSwitch(); + } + + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new IfToSwitchPredicate(); + } + + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + JSIfStatement ifStatement = (JSIfStatement)element.getParent(); + + assert (ifStatement != null); + + boolean breaksNeedRelabeled = false; + JSStatement breakTarget = null; + String labelString = ""; + + if (ControlFlowUtils.statementContainsExitingBreak(ifStatement)) { + JSElement ancestor = (JSElement)ifStatement.getParent(); + while (ancestor != null) { + if (ancestor instanceof JSForStatement + || ancestor instanceof JSForInStatement + || ancestor instanceof JSDoWhileStatement + || ancestor instanceof JSWhileStatement + || ancestor instanceof JSSwitchStatement) { + breakTarget = (JSStatement)ancestor; + break; + } + ancestor = (JSElement)ancestor.getParent(); + } + + if (breakTarget != null) { + labelString = CaseUtil.findUniqueLabel(ifStatement, DEFAULT_LABEL_NAME); + breaksNeedRelabeled = true; + } + } + JSIfStatement statementToReplace = ifStatement; + JSExpression caseExpression = CaseUtil.getCaseExpression(ifStatement); + + assert (caseExpression != null); + + StringBuilder switchStatementBuffer = new StringBuilder(1024); + + switchStatementBuffer.append("switch(").append(caseExpression.getText()).append(')') + .append('{'); + + List branches = new ArrayList<>(20); + + while (true) { + Set topLevelVariables = new HashSet<>(5); + Set innerVariables = new HashSet<>(5); + JSExpression condition = ifStatement.getCondition(); + JSExpression[] labels = getValuesFromCondition(condition, caseExpression); + JSStatement thenBranch = ifStatement.getThen(); + + DeclarationUtils.calculateVariablesDeclared(thenBranch, topLevelVariables, innerVariables, true); + + IfStatementBranch ifBranch = new IfStatementBranch(); + + ifBranch.setInnerVariables(innerVariables); + ifBranch.setTopLevelVariables(topLevelVariables); + ifBranch.setStatement(thenBranch); + for (JSExpression label : labels) { + ifBranch.addCondition(label.getText()); + } + branches.add(ifBranch); + + JSStatement elseBranch = ifStatement.getElse(); + + if (elseBranch instanceof JSIfStatement elseIfStatement) { + ifStatement = elseIfStatement; + } + else if (elseBranch == null) { + break; + } + else { + Set elseTopLevelVariables = new HashSet<>(5); + Set elseInnerVariables = new HashSet<>(5); + + DeclarationUtils.calculateVariablesDeclared(elseBranch, elseTopLevelVariables, elseInnerVariables, true); + + IfStatementBranch elseIfBranch = new IfStatementBranch(); + + elseIfBranch.setInnerVariables(elseInnerVariables); + elseIfBranch.setTopLevelVariables(elseTopLevelVariables); + elseIfBranch.setElse(); + elseIfBranch.setStatement(elseBranch); + branches.add(elseIfBranch); + break; + } + } + + for (IfStatementBranch branch : branches) { + boolean hasConflicts = false; + for (IfStatementBranch testBranch : branches) { + if (branch.topLevelDeclarationsConfictWith(testBranch)) { + hasConflicts = true; + } + } + + JSStatement branchStatement = branch.getStatement(); + + if (branch.isElse()) { + dumpDefaultBranch(switchStatementBuffer, branchStatement, hasConflicts, breaksNeedRelabeled, labelString); + } + else { + List conditions = branch.getConditions(); + + dumpBranch(switchStatementBuffer, conditions, branchStatement, hasConflicts, breaksNeedRelabeled, labelString); + } + } + + switchStatementBuffer.append('}'); + + String switchStatementString = switchStatementBuffer.toString(); + + if (breaksNeedRelabeled) { + int length = switchStatementBuffer.length(); + StringBuilder out = new StringBuilder(length); + + out.append(labelString).append(':'); + termReplace(out, breakTarget, statementToReplace, switchStatementString); + JSElementFactory.replaceStatement(breakTarget, out.toString()); + } + else { + JSElementFactory.replaceStatement(statementToReplace, switchStatementString); + } + } + + @RequiredReadAction + private static void termReplace(StringBuilder out, JSElement target, JSElement replace, String stringToReplaceWith) { + if (target.equals(replace)) { + out.append(stringToReplaceWith); + } + else if (target.getChildren().length != 0) { + JSElement[] children = (JSElement[])target.getChildren(); + for (JSElement child : children) { + termReplace(out, child, replace, stringToReplaceWith); + } + } + else { + String text = target.getText(); + out.append(text); + } + } + + @RequiredReadAction + private static JSExpression[] getValuesFromCondition(JSExpression condition, JSExpression caseExpression) { + List values = new ArrayList<>(10); + + getValuesFromExpression(condition, caseExpression, values); + return values.toArray(new JSExpression[values.size()]); + } + + @RequiredReadAction + private static void getValuesFromExpression(JSExpression expression, JSExpression caseExpression, List values) { + if (expression instanceof JSBinaryExpression binaryExpression) { + JSExpression lhs = binaryExpression.getLOperand(); + JSExpression rhs = binaryExpression.getROperand(); + IElementType tokenType = binaryExpression.getOperationSign(); + + if (JSTokenTypes.OROR.equals(tokenType)) { + getValuesFromExpression(lhs, caseExpression, values); + getValuesFromExpression(rhs, caseExpression, values); + } + else if (EquivalenceChecker.expressionsAreEquivalent(caseExpression, rhs)) { + values.add(lhs); + } + else { + values.add(rhs); + } + } + else if (expression instanceof JSParenthesizedExpression parenExpression) { + JSExpression contents = parenExpression.getInnerExpression(); + + getValuesFromExpression(contents, caseExpression, values); + } + } + + @RequiredReadAction + private static void dumpBranch( + StringBuilder switchStatementString, + List labels, + JSStatement body, + boolean wrap, + boolean renameBreaks, + String breakLabelName + ) { + dumpLabels(switchStatementString, labels); + dumpBody(switchStatementString, body, wrap, renameBreaks, breakLabelName); + } + + @RequiredReadAction + private static void dumpDefaultBranch( + StringBuilder switchStatementString, + JSStatement body, + boolean wrap, + boolean renameBreaks, + String breakLabelName + ) { + switchStatementString.append(DEFAULT_CASE_CLAUSE_EXPRESSION); + dumpBody(switchStatementString, body, wrap, renameBreaks, breakLabelName); + } + + private static void dumpLabels(StringBuilder switchStatementString, List labels) { + for (String label : labels) { + switchStatementString.append("\ncase ").append(label).append(": "); + } + } + + @RequiredReadAction + private static void dumpBody( + StringBuilder switchStatementString, + JSStatement bodyStatement, + boolean wrap, + boolean renameBreaks, + String breakLabelName + ) { + if (bodyStatement instanceof JSBlockStatement) { + if (wrap) { + appendElement(switchStatementString, bodyStatement, renameBreaks, breakLabelName); + } + else { + // Skip the first and last characters to unwrap the block + String bodyText = bodyStatement.getText(); + switchStatementString.append(bodyText.substring(1, bodyText.length() - 1)); + } + } + else { + if (wrap) { + switchStatementString.append('{'); + appendElement(switchStatementString, bodyStatement, renameBreaks, breakLabelName); + switchStatementString.append('}'); + } + else { + appendElement(switchStatementString, bodyStatement, renameBreaks, breakLabelName); + } + } + if (ControlFlowUtils.statementMayCompleteNormally(bodyStatement)) { + switchStatementString.append(BREAK_STATEMENT); + } + switchStatementString.append('\n'); + } + + @RequiredReadAction + private static void appendElement( + StringBuilder switchStatementString, + JSElement element, + boolean renameBreakElements, + String breakLabelString + ) { + String text = element.getText(); + + if (!renameBreakElements) { + switchStatementString.append(text); + } + else if (element instanceof JSBreakStatement breakStatement) { + String identifier = breakStatement.getLabel(); + if (identifier == null || identifier.isEmpty()) { + switchStatementString.append(LABELED_BREAK_STATEMENT_PREFIX); + switchStatementString.append(breakLabelString); + switchStatementString.append(';'); + } + else { + switchStatementString.append(text); + } + } + else if (element instanceof JSBlockStatement || element instanceof JSIfStatement) { + JSElement[] children = (JSElement[])element.getChildren(); + for (JSElement child : children) { + appendElement(switchStatementString, child, renameBreakElements, breakLabelString); + } + } + else { + switchStatementString.append(text); + } + } + + private static class IfToSwitchPredicate implements JSElementPredicate { + @Override + @RequiredReadAction + public boolean satisfiedBy(@Nonnull PsiElement element) { + return element.getParent() instanceof JSIfStatement statement + && IF_KEYWORD.equals(element.getText()) + && !ErrorUtil.containsError(statement) + && CaseUtil.getCaseExpression(statement) != null; + } + } + + private static class IfStatementBranch { + private final List conditions = new ArrayList<>(3); + private Set topLevelVariables = new HashSet<>(3); + private Set innerVariables = new HashSet<>(3); + private JSStatement statement; + private boolean isElse; + + public void addCondition(String conditionString) { + this.conditions.add(conditionString); + } + + public void setStatement(JSStatement statement) { + this.statement = statement; + } + + public JSStatement getStatement() { + return this.statement; + } + + public List getConditions() { + return Collections.unmodifiableList(this.conditions); + } + + public boolean isElse() { + return this.isElse; + } + + public void setElse() { + this.isElse = true; + } + + public void setTopLevelVariables(Set topLevelVariables) { + this.topLevelVariables = new HashSet<>(topLevelVariables); + } + + public void setInnerVariables(Set innerVariables) { + this.innerVariables = new HashSet<>(innerVariables); + } + + private Set getTopLevelVariables() { + return Collections.unmodifiableSet(this.topLevelVariables); + } + + private Set getInnerVariables() { + return Collections.unmodifiableSet(this.innerVariables); + } + + public boolean topLevelDeclarationsConfictWith(IfStatementBranch testBranch) { + Set innerVariables = testBranch.getInnerVariables(); + Set topLevel = testBranch.getTopLevelVariables(); + + return hasNonEmptyIntersection(this.topLevelVariables, topLevel) + || hasNonEmptyIntersection(this.topLevelVariables, innerVariables); + } + + private static boolean hasNonEmptyIntersection(Set set1, Set set2) { + for (String set1Element : set1) { + if (set2.contains(set1Element)) { + return true; + } + } + return false; + } + } } \ No newline at end of file diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/switchtoif/JSReplaceSwitchWithIfIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/switchtoif/JSReplaceSwitchWithIfIntention.java index b0b1821d..c8e3d184 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/switchtoif/JSReplaceSwitchWithIfIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/switchtoif/JSReplaceSwitchWithIfIntention.java @@ -17,497 +17,445 @@ import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.impl.JSChangeUtil; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.codeStyle.CodeStyleManager; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiManager; import consulo.language.psi.PsiWhiteSpace; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.*; import org.jetbrains.annotations.NonNls; -import javax.annotation.Nonnull; import java.util.*; @ExtensionImpl -@IntentionMetaData(ignoreId = "JSReplaceSwitchWithIfIntention", categories = { - "JavaScript", - "Control Flow" -}, fileExtensions = "js") -public class JSReplaceSwitchWithIfIntention extends JSIntention -{ - - @NonNls - private static final String IF_PREFIX = "if ("; - @NonNls - private static final String IF_SUFFIX = ") {"; - @NonNls - private static final String ELSE = "} else {"; - @NonNls - private static final String ELSE_KEYWORD = "else "; - @NonNls - private static final String VAR_PREFIX = "var "; - @NonNls - private static final String BREAK_KEYWORD = "break "; - @NonNls - private static final String DEFAULT_LABEL_NAME = "Label"; - - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new SwitchPredicate(); - } - - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final JSSwitchStatement switchStatement = (JSSwitchStatement) element.getParent(); - - assert (switchStatement != null); - - final PsiManager mgr = switchStatement.getManager(); - final JSExpression switchExpression = switchStatement.getSwitchExpression(); - final CodeStyleManager codeStyleMgr = CodeStyleManager.getInstance(element.getProject()); - final boolean hadSideEffects = SideEffectChecker.mayHaveSideEffects(switchExpression); - final String declarationString; - final String expressionText; - - if(hadSideEffects) - { - final String variableName = "i"; // TODO JavaCodeStyleManager.getInstance(switchExpression.getProject()).suggestUniqueVariableName("i", switchExpression, true); - - expressionText = variableName; - declarationString = VAR_PREFIX + variableName + " = " + switchExpression.getText() + ';'; - } - else - { - declarationString = null; - expressionText = switchExpression.getText(); - } - - boolean renameBreaks = false; - - for(JSCaseClause caseClause : switchStatement.getCaseClauses()) - { - if(CaseUtil.containsHiddenBreak(caseClause)) - { - renameBreaks = true; - break; - } - } - - final StringBuilder ifStatementBuffer = new StringBuilder(1024); - String breakLabel = null; - - if(renameBreaks) - { - breakLabel = CaseUtil.findUniqueLabel(switchStatement, DEFAULT_LABEL_NAME); - ifStatementBuffer.append(breakLabel) - .append(':'); - } - - final List openBranches = new ArrayList(); - final Set declaredVars = new HashSet(5); - final List allBranches = new ArrayList(); - SwitchStatementBranch currentBranch = null; - - for(JSCaseClause caseClause : switchStatement.getCaseClauses()) - { - final PsiElement[] caseClauseChildren = caseClause.getChildren(); - - for(PsiElement child : caseClauseChildren) - { - if(child == caseClauseChildren[0]) - { - if(currentBranch == null) - { - openBranches.clear(); - currentBranch = new SwitchStatementBranch(); - currentBranch.addPendingVariableDeclarations(declaredVars); - allBranches.add(currentBranch); - openBranches.add(currentBranch); - } - else if(currentBranch.hasStatements()) - { - currentBranch = new SwitchStatementBranch(); - allBranches.add(currentBranch); - openBranches.add(currentBranch); - } - - if(caseClause.isDefault()) - { - currentBranch.setDefault(); - } - } - - if(child instanceof JSExpression) - { - // Processes case clause expression - final JSExpression value = ParenthesesUtils.stripParentheses(caseClause.getCaseExpression()); - - assert (currentBranch != null); - currentBranch.addLabel(value.getText()); - } - else if(child instanceof JSStatement) - { - // Processes case clause statements - final JSStatement statement = (JSStatement) child; - - if(statement instanceof JSVarStatement) - { - for(JSVariable variable : ((JSVarStatement) statement).getVariables()) - { - declaredVars.add(variable); - } - } - else if(statement instanceof JSBlockStatement) - { - for(PsiElement blockElement : statement.getChildren()) - { - final boolean isJsElement = (blockElement instanceof JSElement); - final boolean isWhiteSpace = (blockElement instanceof PsiWhiteSpace); - - for(SwitchStatementBranch branch : openBranches) - { - if(isJsElement) - { - branch.addStatement((JSElement) blockElement); - } - else if(isWhiteSpace) - { - branch.addWhiteSpace(blockElement); - } - else - { - branch.addComment(blockElement); - } - } - } - } - else - { - for(SwitchStatementBranch branch : openBranches) - { - branch.addStatement(statement); - } - } - - if(!ControlFlowUtils.statementMayCompleteNormally(statement)) - { - currentBranch = null; - } - } - else - { - final boolean isWhiteSpace = (child instanceof PsiWhiteSpace); - - for(SwitchStatementBranch openBranch : openBranches) - { - if(isWhiteSpace) - { - openBranch.addWhiteSpace(child); - } - else - { - openBranch.addComment(child); - } - } - } - } - } - - boolean firstBranch = true; - SwitchStatementBranch defaultBranch = null; - - for(SwitchStatementBranch branch : allBranches) - { - if(branch.isDefault()) - { - defaultBranch = branch; - } - else - { - final List labels = branch.getLabels(); - final List bodyElements = branch.getBodyElements(); - final Set pendingVariableDeclarations = branch.getPendingVariableDeclarations(); - - dumpBranch(ifStatementBuffer, expressionText, - labels, bodyElements, firstBranch, - renameBreaks && CaseUtil.containsHiddenBreak(bodyElements), breakLabel, - pendingVariableDeclarations); - firstBranch = false; - } - } - if(defaultBranch != null) - { - final List bodyElements = defaultBranch.getBodyElements(); - final Set pendingVariableDeclarations = defaultBranch.getPendingVariableDeclarations(); - - dumpDefaultBranch(ifStatementBuffer, bodyElements, - firstBranch, renameBreaks, breakLabel, - pendingVariableDeclarations); - } - - if(hadSideEffects) - { - final String ifStatementString = ifStatementBuffer.toString(); - final JSStatement declarationStatement = (JSStatement) JSChangeUtil.createStatementFromText(element.getProject(), declarationString).getPsi(); - final JSStatement ifStatement = (JSStatement) JSChangeUtil.createStatementFromText(element.getProject(), ifStatementString).getPsi(); - - codeStyleMgr.reformat(declarationStatement); - codeStyleMgr.reformat(ifStatement); - JSElementFactory.replaceStatement(switchStatement, declarationStatement.getText() + '\n' + ifStatement.getText()); - } - else - { - final String ifStatementString = ifStatementBuffer.toString(); - final JSStatement newStatement = (JSStatement) JSChangeUtil.createStatementFromText(element.getProject(), ifStatementString).getPsi(); - - codeStyleMgr.reformat(newStatement); - JSElementFactory.replaceStatement(switchStatement, newStatement.getText()); - } - } - - private static void dumpBranch(StringBuilder ifStatementString, - String expressionText, - List labels, - List bodyStatements, - boolean firstBranch, - boolean renameBreaks, - String breakLabel, - Set variableDecls) - { - if(!firstBranch) - { - ifStatementString.append(ELSE_KEYWORD); - } - dumpLabels(ifStatementString, expressionText, labels); - dumpBody(ifStatementString, bodyStatements, renameBreaks, breakLabel, - variableDecls); - } - - private static void dumpDefaultBranch(StringBuilder ifStatementString, - List bodyStatements, - boolean firstBranch, - boolean renameBreaks, - String breakLabel, - Set variableDecls) - { - if(!firstBranch) - { - ifStatementString.append(ELSE_KEYWORD); - } - dumpBody(ifStatementString, bodyStatements, renameBreaks, breakLabel, - variableDecls); - } - - private static void dumpLabels(StringBuilder ifStatementString, - String expressionText, - List labels) - { - boolean firstLabel = true; - - ifStatementString.append(IF_PREFIX); - for(String label : labels) - { - if(!firstLabel) - { - ifStatementString.append("||"); - } - firstLabel = false; - - ifStatementString.append(expressionText) - .append("==") - .append(label); - } - ifStatementString.append(')'); - } - - private static void dumpBody(StringBuilder ifStatementString, - List bodyStatements, - boolean renameBreaks, - String breakLabel, - Set variableDecls) - { - - ifStatementString.append('{'); - for(final JSVariable var : variableDecls) - { - if(CaseUtil.isUsedByStatementList(var, bodyStatements)) - { - ifStatementString.append(VAR_PREFIX) - .append(var.getName()) - .append(';'); - } - } - - for(final PsiElement bodyStatement : bodyStatements) - { - if(!(bodyStatement instanceof JSBreakStatement)) - { - appendElement(ifStatementString, bodyStatement, renameBreaks, - breakLabel); - } - } - ifStatementString.append('}'); - } - - private static void appendElement(StringBuilder ifStatementString, - PsiElement element, - boolean renameBreakElements, - String breakLabelString) - { - if(!renameBreakElements) - { - final String text = element.getText(); - - ifStatementString.append(text); - } - else if(element instanceof JSBreakStatement) - { - final String identifier = ((JSBreakStatement) element).getLabel(); - - if(identifier == null || identifier.length() == 0) - { - ifStatementString.append(BREAK_KEYWORD) - .append(breakLabelString) - .append(';'); - } - else - { - final String text = element.getText(); - ifStatementString.append(text); - } - } - else if(element instanceof JSBlockStatement) - { - for(final PsiElement child : element.getChildren()) - { - appendElement(ifStatementString, child, renameBreakElements, breakLabelString); - } - } - else if(element instanceof JSIfStatement) - { - JSIfStatement ifStatement = (JSIfStatement) element; - JSStatement elseBranch = ifStatement.getElse(); - - ifStatementString.append(IF_PREFIX) - .append(ifStatement.getCondition().getText()) - .append(IF_SUFFIX); - appendElement(ifStatementString, ifStatement.getThen(), renameBreakElements, breakLabelString); - if(elseBranch != null) - { - ifStatementString.append(ELSE); - appendElement(ifStatementString, elseBranch, renameBreakElements, breakLabelString); - } - ifStatementString.append('}'); - } - else - { - ifStatementString.append(element.getText()); - } - } - - private static class SwitchPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - final PsiElement parent = element.getParent(); - - if(!(parent instanceof JSSwitchStatement)) - { - return false; - } - final JSSwitchStatement switchStatement = (JSSwitchStatement) parent; - if(ErrorUtil.containsError(switchStatement)) - { - return false; - } - - final JSExpression expression = switchStatement.getSwitchExpression(); - - return (expression != null && expression.isValid()); - } - } - - private static class SwitchStatementBranch - { - private final Set pendingVariableDeclarations = new HashSet(5); - private final List labels = new ArrayList(2); - private final List bodyElements = new ArrayList(5); - private final List pendingWhiteSpace = new ArrayList(2); - private boolean isDefault; - private boolean hasStatements; - - public void addLabel(String labelString) - { - this.labels.add(labelString); - } - - public void addStatement(JSElement statement) - { - this.hasStatements = true; - this.addElement(statement); - } - - public void addComment(PsiElement comment) - { - this.addElement(comment); - } - - private void addElement(PsiElement element) - { - this.bodyElements.addAll(this.pendingWhiteSpace); - this.pendingWhiteSpace.clear(); - this.bodyElements.add(element); - } - - public void addWhiteSpace(PsiElement whiteSpace) - { - if(this.bodyElements.size() > 0) - { - this.pendingWhiteSpace.add(whiteSpace); - } - } - - public List getLabels() - { - return Collections.unmodifiableList(this.labels); - } - - public List getBodyElements() - { - return Collections.unmodifiableList(this.bodyElements); - } - - public boolean isDefault() - { - return this.isDefault; - } - - public void setDefault() - { - this.isDefault = true; - } - - public boolean hasStatements() - { - return this.hasStatements; - } - - public void addPendingVariableDeclarations(Set vars) - { - this.pendingVariableDeclarations.addAll(vars); - } - - public Set getPendingVariableDeclarations() - { - return Collections.unmodifiableSet(this.pendingVariableDeclarations); - } - } +@IntentionMetaData( + ignoreId = "JSReplaceSwitchWithIfIntention", + categories = {"JavaScript", "Control Flow"}, + fileExtensions = "js" +) +public class JSReplaceSwitchWithIfIntention extends JSIntention { + @NonNls + private static final String IF_PREFIX = "if ("; + @NonNls + private static final String IF_SUFFIX = ") {"; + @NonNls + private static final String ELSE = "} else {"; + @NonNls + private static final String ELSE_KEYWORD = "else "; + @NonNls + private static final String VAR_PREFIX = "var "; + @NonNls + private static final String BREAK_KEYWORD = "break "; + @NonNls + private static final String DEFAULT_LABEL_NAME = "Label"; + + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.switchtoifReplaceSwitchWithIf(); + } + + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new SwitchPredicate(); + } + + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + JSSwitchStatement switchStatement = (JSSwitchStatement)element.getParent(); + + assert (switchStatement != null); + + PsiManager mgr = switchStatement.getManager(); + JSExpression switchExpression = switchStatement.getSwitchExpression(); + CodeStyleManager codeStyleMgr = CodeStyleManager.getInstance(element.getProject()); + boolean hadSideEffects = SideEffectChecker.mayHaveSideEffects(switchExpression); + String declarationString; + String expressionText; + + if (hadSideEffects) { + String variableName = + "i"; // TODO JavaCodeStyleManager.getInstance(switchExpression.getProject()).suggestUniqueVariableName("i", switchExpression, true); + + expressionText = variableName; + declarationString = VAR_PREFIX + variableName + " = " + switchExpression.getText() + ';'; + } + else { + declarationString = null; + expressionText = switchExpression.getText(); + } + + boolean renameBreaks = false; + + for (JSCaseClause caseClause : switchStatement.getCaseClauses()) { + if (CaseUtil.containsHiddenBreak(caseClause)) { + renameBreaks = true; + break; + } + } + + StringBuilder ifStatementBuffer = new StringBuilder(1024); + String breakLabel = null; + + if (renameBreaks) { + breakLabel = CaseUtil.findUniqueLabel(switchStatement, DEFAULT_LABEL_NAME); + ifStatementBuffer.append(breakLabel).append(':'); + } + + List openBranches = new ArrayList<>(); + Set declaredVars = new HashSet<>(5); + List allBranches = new ArrayList<>(); + SwitchStatementBranch currentBranch = null; + + for (JSCaseClause caseClause : switchStatement.getCaseClauses()) { + PsiElement[] caseClauseChildren = caseClause.getChildren(); + + for (PsiElement child : caseClauseChildren) { + if (child == caseClauseChildren[0]) { + if (currentBranch == null) { + openBranches.clear(); + currentBranch = new SwitchStatementBranch(); + currentBranch.addPendingVariableDeclarations(declaredVars); + allBranches.add(currentBranch); + openBranches.add(currentBranch); + } + else if (currentBranch.hasStatements()) { + currentBranch = new SwitchStatementBranch(); + allBranches.add(currentBranch); + openBranches.add(currentBranch); + } + + if (caseClause.isDefault()) { + currentBranch.setDefault(); + } + } + + if (child instanceof JSExpression) { + // Processes case clause expression + JSExpression value = ParenthesesUtils.stripParentheses(caseClause.getCaseExpression()); + + assert (currentBranch != null); + currentBranch.addLabel(value.getText()); + } + else if (child instanceof JSStatement) { + // Processes case clause statements + JSStatement statement = (JSStatement)child; + + if (statement instanceof JSVarStatement) { + Collections.addAll(declaredVars, ((JSVarStatement)statement).getVariables()); + } + else if (statement instanceof JSBlockStatement) { + for (PsiElement blockElement : statement.getChildren()) { + boolean isJsElement = (blockElement instanceof JSElement); + boolean isWhiteSpace = (blockElement instanceof PsiWhiteSpace); + + for (SwitchStatementBranch branch : openBranches) { + if (isJsElement) { + branch.addStatement((JSElement)blockElement); + } + else if (isWhiteSpace) { + branch.addWhiteSpace(blockElement); + } + else { + branch.addComment(blockElement); + } + } + } + } + else { + for (SwitchStatementBranch branch : openBranches) { + branch.addStatement(statement); + } + } + + if (!ControlFlowUtils.statementMayCompleteNormally(statement)) { + currentBranch = null; + } + } + else { + boolean isWhiteSpace = (child instanceof PsiWhiteSpace); + + for (SwitchStatementBranch openBranch : openBranches) { + if (isWhiteSpace) { + openBranch.addWhiteSpace(child); + } + else { + openBranch.addComment(child); + } + } + } + } + } + + boolean firstBranch = true; + SwitchStatementBranch defaultBranch = null; + + for (SwitchStatementBranch branch : allBranches) { + if (branch.isDefault()) { + defaultBranch = branch; + } + else { + List labels = branch.getLabels(); + List bodyElements = branch.getBodyElements(); + Set pendingVariableDeclarations = branch.getPendingVariableDeclarations(); + + dumpBranch( + ifStatementBuffer, + expressionText, + labels, + bodyElements, + firstBranch, + renameBreaks && CaseUtil.containsHiddenBreak(bodyElements), + breakLabel, + pendingVariableDeclarations + ); + firstBranch = false; + } + } + if (defaultBranch != null) { + List bodyElements = defaultBranch.getBodyElements(); + Set pendingVariableDeclarations = defaultBranch.getPendingVariableDeclarations(); + + dumpDefaultBranch( + ifStatementBuffer, + bodyElements, + firstBranch, + renameBreaks, + breakLabel, + pendingVariableDeclarations + ); + } + + if (hadSideEffects) { + String ifStatementString = ifStatementBuffer.toString(); + JSStatement declarationStatement = + (JSStatement)JSChangeUtil.createStatementFromText(element.getProject(), declarationString).getPsi(); + JSStatement ifStatement = + (JSStatement)JSChangeUtil.createStatementFromText(element.getProject(), ifStatementString).getPsi(); + + codeStyleMgr.reformat(declarationStatement); + codeStyleMgr.reformat(ifStatement); + JSElementFactory.replaceStatement(switchStatement, declarationStatement.getText() + '\n' + ifStatement.getText()); + } + else { + String ifStatementString = ifStatementBuffer.toString(); + JSStatement newStatement = + (JSStatement)JSChangeUtil.createStatementFromText(element.getProject(), ifStatementString).getPsi(); + + codeStyleMgr.reformat(newStatement); + JSElementFactory.replaceStatement(switchStatement, newStatement.getText()); + } + } + + @RequiredReadAction + private static void dumpBranch( + StringBuilder ifStatementString, + String expressionText, + List labels, + List bodyStatements, + boolean firstBranch, + boolean renameBreaks, + String breakLabel, + Set variableDecls + ) { + if (!firstBranch) { + ifStatementString.append(ELSE_KEYWORD); + } + dumpLabels(ifStatementString, expressionText, labels); + dumpBody(ifStatementString, bodyStatements, renameBreaks, breakLabel, variableDecls); + } + + @RequiredReadAction + private static void dumpDefaultBranch( + StringBuilder ifStatementString, + List bodyStatements, + boolean firstBranch, + boolean renameBreaks, + String breakLabel, + Set variableDecls + ) { + if (!firstBranch) { + ifStatementString.append(ELSE_KEYWORD); + } + dumpBody(ifStatementString, bodyStatements, renameBreaks, breakLabel, variableDecls); + } + + private static void dumpLabels(StringBuilder ifStatementString, String expressionText, List labels) { + boolean firstLabel = true; + + ifStatementString.append(IF_PREFIX); + for (String label : labels) { + if (!firstLabel) { + ifStatementString.append("||"); + } + firstLabel = false; + + ifStatementString.append(expressionText).append("==").append(label); + } + ifStatementString.append(')'); + } + + @RequiredReadAction + private static void dumpBody( + StringBuilder ifStatementString, + List bodyStatements, + boolean renameBreaks, + String breakLabel, + Set variableDecls + ) { + ifStatementString.append('{'); + for (JSVariable var : variableDecls) { + if (CaseUtil.isUsedByStatementList(var, bodyStatements)) { + ifStatementString.append(VAR_PREFIX) + .append(var.getName()) + .append(';'); + } + } + + for (PsiElement bodyStatement : bodyStatements) { + if (!(bodyStatement instanceof JSBreakStatement)) { + appendElement(ifStatementString, bodyStatement, renameBreaks, + breakLabel + ); + } + } + ifStatementString.append('}'); + } + + @RequiredReadAction + private static void appendElement( + StringBuilder ifStatementString, + PsiElement element, + boolean renameBreakElements, + String breakLabelString + ) { + if (!renameBreakElements) { + String text = element.getText(); + + ifStatementString.append(text); + } + else if (element instanceof JSBreakStatement breakStatement) { + String identifier = breakStatement.getLabel(); + + if (identifier == null || identifier.isEmpty()) { + ifStatementString.append(BREAK_KEYWORD).append(breakLabelString).append(';'); + } + else { + ifStatementString.append(element.getText()); + } + } + else if (element instanceof JSBlockStatement) { + for (PsiElement child : element.getChildren()) { + appendElement(ifStatementString, child, renameBreakElements, breakLabelString); + } + } + else if (element instanceof JSIfStatement ifStatement) { + JSStatement elseBranch = ifStatement.getElse(); + + ifStatementString.append(IF_PREFIX) + .append(ifStatement.getCondition().getText()) + .append(IF_SUFFIX); + appendElement(ifStatementString, ifStatement.getThen(), renameBreakElements, breakLabelString); + if (elseBranch != null) { + ifStatementString.append(ELSE); + appendElement(ifStatementString, elseBranch, renameBreakElements, breakLabelString); + } + ifStatementString.append('}'); + } + else { + ifStatementString.append(element.getText()); + } + } + + private static class SwitchPredicate implements JSElementPredicate { + @Override + public boolean satisfiedBy(@Nonnull PsiElement element) { + PsiElement parent = element.getParent(); + + if (parent instanceof JSSwitchStatement switchStatement) { + if (ErrorUtil.containsError(switchStatement)) { + return false; + } + + JSExpression expression = switchStatement.getSwitchExpression(); + + return expression != null && expression.isValid(); + } + else { + return false; + } + } + } + + private static class SwitchStatementBranch { + private final Set pendingVariableDeclarations = new HashSet<>(5); + private final List labels = new ArrayList<>(2); + private final List bodyElements = new ArrayList<>(5); + private final List pendingWhiteSpace = new ArrayList<>(2); + private boolean isDefault; + private boolean hasStatements; + + public void addLabel(String labelString) { + this.labels.add(labelString); + } + + public void addStatement(JSElement statement) { + this.hasStatements = true; + this.addElement(statement); + } + + public void addComment(PsiElement comment) { + this.addElement(comment); + } + + private void addElement(PsiElement element) { + this.bodyElements.addAll(this.pendingWhiteSpace); + this.pendingWhiteSpace.clear(); + this.bodyElements.add(element); + } + + public void addWhiteSpace(PsiElement whiteSpace) { + if (this.bodyElements.size() > 0) { + this.pendingWhiteSpace.add(whiteSpace); + } + } + + public List getLabels() { + return Collections.unmodifiableList(this.labels); + } + + public List getBodyElements() { + return Collections.unmodifiableList(this.bodyElements); + } + + public boolean isDefault() { + return this.isDefault; + } + + public void setDefault() { + this.isDefault = true; + } + + public boolean hasStatements() { + return this.hasStatements; + } + + public void addPendingVariableDeclarations(Set vars) { + this.pendingVariableDeclarations.addAll(vars); + } + + public Set getPendingVariableDeclarations() { + return Collections.unmodifiableSet(this.pendingVariableDeclarations); + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/switchtoif/LabelSearchVisitor.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/switchtoif/LabelSearchVisitor.java index 4c057810..d73122df 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/switchtoif/LabelSearchVisitor.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/switchtoif/LabelSearchVisitor.java @@ -19,31 +19,26 @@ import com.intellij.lang.javascript.psi.JSReferenceExpression; import org.intellij.idea.lang.javascript.psiutil.JSRecursiveElementVisitor; -class LabelSearchVisitor extends JSRecursiveElementVisitor -{ - private final String labelName; - private boolean used; +class LabelSearchVisitor extends JSRecursiveElementVisitor { + private final String labelName; + private boolean used; - LabelSearchVisitor(String name) - { - this.labelName = name; - } + LabelSearchVisitor(String name) { + this.labelName = name; + } - @Override - public void visitJSReferenceExpression(JSReferenceExpression expression) - { - } + @Override + public void visitJSReferenceExpression(JSReferenceExpression expression) { + } - @Override - public void visitJSLabeledStatement(JSLabeledStatement statement) - { - final String labelText = statement.getLabel(); + @Override + public void visitJSLabeledStatement(JSLabeledStatement statement) { + String labelText = statement.getLabel(); - this.used = (labelText != null && labelText.equals(this.labelName)); - } + this.used = labelText != null && labelText.equals(this.labelName); + } - public boolean isUsed() - { - return this.used; - } + public boolean isUsed() { + return this.used; + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/switchtoif/LocalVariableUsageVisitor.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/switchtoif/LocalVariableUsageVisitor.java index 212abb00..aa13b4b8 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/switchtoif/LocalVariableUsageVisitor.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/switchtoif/LocalVariableUsageVisitor.java @@ -20,30 +20,24 @@ import com.intellij.lang.javascript.psi.JSVariable; import org.intellij.idea.lang.javascript.psiutil.JSRecursiveElementVisitor; +class LocalVariableUsageVisitor extends JSRecursiveElementVisitor { + private final JSVariable variable; + private boolean used; -class LocalVariableUsageVisitor extends JSRecursiveElementVisitor -{ - private final JSVariable variable; - private boolean used; + LocalVariableUsageVisitor(JSVariable name) { + this.variable = name; + } - LocalVariableUsageVisitor(JSVariable name) - { - this.variable = name; - } + @Override + public void visitJSReferenceExpression(JSReferenceExpression expression) { + JSElement reference = (JSElement)expression.resolve(); + if (this.variable.equals(reference)) { + this.used = true; + } + super.visitJSReferenceExpression(expression); + } - @Override - public void visitJSReferenceExpression(JSReferenceExpression expression) - { - final JSElement reference = (JSElement) expression.resolve(); - if(this.variable.equals(reference)) - { - this.used = true; - } - super.visitJSReferenceExpression(expression); - } - - public boolean isUsed() - { - return this.used; - } + public boolean isUsed() { + return this.used; + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSMergeElseIfIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSMergeElseIfIntention.java index 3e74ca63..954207da 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSMergeElseIfIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSMergeElseIfIntention.java @@ -20,90 +20,61 @@ import com.intellij.lang.javascript.psi.JSIfStatement; import com.intellij.lang.javascript.psi.JSStatement; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.ErrorUtil; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; -import javax.annotation.Nonnull; - @ExtensionImpl -@IntentionMetaData(ignoreId = "JSMergeElseIfIntention", categories = { - "JavaScript", - "Control Flow" -}, fileExtensions = "js") -public class JSMergeElseIfIntention extends JSIntention -{ - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new MergeElseIfPredicate(); - } - - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final JSIfStatement parentStatement = (JSIfStatement) element.getParent(); - - assert (parentStatement != null); - - final JSBlockStatement elseBranch = (JSBlockStatement) parentStatement.getElse(); - final JSStatement elseBranchContents = elseBranch.getStatements()[0]; - - JSElementFactory.replaceStatement(elseBranch, elseBranchContents.getText()); - } - - private static class MergeElseIfPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSElement)) - { - return false; - } - - final PsiElement parent = element.getParent(); - - if(!(parent instanceof JSIfStatement)) - { - return false; - } - - final JSIfStatement ifStatement = (JSIfStatement) parent; - - if(ErrorUtil.containsError(ifStatement)) - { - return false; - } - - final JSStatement thenBranch = ifStatement.getThen(); - final JSStatement elseBranch = ifStatement.getElse(); - - if(thenBranch == null) - { - return false; - } - if(elseBranch == null) - { - return false; - } - if(!(elseBranch instanceof JSBlockStatement)) - { - return false; - } - - final JSStatement[] statements = ((JSBlockStatement) elseBranch).getStatements(); - - if(statements.length != 1) - { - return false; - } - return (statements[0] != null && statements[0] instanceof JSIfStatement); - } - } +@IntentionMetaData( + ignoreId = "JSMergeElseIfIntention", + categories = {"JavaScript", "Control Flow"}, + fileExtensions = "js" +) +public class JSMergeElseIfIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.trivialifMergeElseIf(); + } + + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new MergeElseIfPredicate(); + } + + @Override + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + JSIfStatement parentStatement = (JSIfStatement)element.getParent(); + + assert (parentStatement != null); + + JSBlockStatement elseBranch = (JSBlockStatement)parentStatement.getElse(); + JSStatement elseBranchContents = elseBranch.getStatements()[0]; + + JSElementFactory.replaceStatement(elseBranch, elseBranchContents.getText()); + } + + private static class MergeElseIfPredicate implements JSElementPredicate { + @Override + public boolean satisfiedBy(@Nonnull PsiElement element) { + return element instanceof JSElement + && element.getParent() instanceof JSIfStatement ifStatement + && !ErrorUtil.containsError(ifStatement) + && ifStatement.getThen() != null + && ifStatement.getElse() instanceof JSBlockStatement elseBlock + && isSingleIfStatement(elseBlock.getStatements()); + } + + private boolean isSingleIfStatement(JSStatement[] statements) { + return statements.length == 1 && statements[0] instanceof JSIfStatement; + } + } } \ No newline at end of file diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSMergeIfAndIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSMergeIfAndIntention.java index f6699073..931d4ec3 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSMergeIfAndIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSMergeIfAndIntention.java @@ -19,103 +19,87 @@ import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.JSIfStatement; import com.intellij.lang.javascript.psi.JSStatement; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.ConditionalUtils; import org.intellij.idea.lang.javascript.psiutil.ErrorUtil; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; import org.intellij.idea.lang.javascript.psiutil.ParenthesesUtils; -import org.jetbrains.annotations.NonNls; - -import javax.annotation.Nonnull; @ExtensionImpl -@IntentionMetaData(ignoreId = "JSMergeIfAndIntention", categories = { - "JavaScript", - "Control Flow" -}, fileExtensions = "js") -public class JSMergeIfAndIntention extends JSIntention -{ - @NonNls - private static final String IF_STATEMENT_PREFIX = "if ("; - - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new MergeIfAndPredicate(); - } - - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - assert (element.getParent() != null); - assert (element.getParent() instanceof JSIfStatement || element instanceof JSIfStatement); - - final JSIfStatement parentStatement = (JSIfStatement) (element.getParent() instanceof JSIfStatement ? element.getParent() : element); - final JSIfStatement childStatement = (JSIfStatement) ConditionalUtils.stripBraces(parentStatement.getThen()); - final JSExpression childCondition = childStatement.getCondition(); - final JSExpression parentCondition = parentStatement.getCondition(); - final String childConditionText = ParenthesesUtils.getParenthesized(childCondition, ParenthesesUtils.AND_PRECENDENCE); - final String parentConditionText = ParenthesesUtils.getParenthesized(parentCondition, ParenthesesUtils.AND_PRECENDENCE); - final JSStatement childThenBranch = childStatement.getThen(); - final String statement = IF_STATEMENT_PREFIX + parentConditionText + " && " + childConditionText + ')' + - childThenBranch.getText(); - - JSElementFactory.replaceStatement(parentStatement, statement); - } - - private static class MergeIfAndPredicate implements JSElementPredicate - { - - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSElement)) - { - return false; - } - - PsiElement parent = element.getParent(); - - if(!(parent instanceof JSIfStatement)) - { - if(element instanceof JSIfStatement) - { - parent = element; - } - else - { - return false; - } - } - - final JSIfStatement ifStatement = (JSIfStatement) parent; - - if(ErrorUtil.containsError(ifStatement)) - { - return false; - } - - final JSStatement thenBranch = ConditionalUtils.stripBraces(ifStatement.getThen()); - final JSStatement elseBranch = ConditionalUtils.stripBraces(ifStatement.getElse()); - - if(thenBranch == null || elseBranch != null) - { - return false; - } - if(!(thenBranch instanceof JSIfStatement)) - { - return false; - } - - final JSIfStatement childIfStatement = (JSIfStatement) thenBranch; - - return (childIfStatement.getElse() == null); - } - } +@IntentionMetaData( + ignoreId = "JSMergeIfAndIntention", + categories = {"JavaScript", "Control Flow"}, + fileExtensions = "js" +) +public class JSMergeIfAndIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.trivialifMergeIfAnd(); + } + + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new MergeIfAndPredicate(); + } + + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + assert (element.getParent() != null); + assert (element.getParent() instanceof JSIfStatement || element instanceof JSIfStatement); + + JSIfStatement parentStatement = (JSIfStatement)(element.getParent() instanceof JSIfStatement ? element.getParent() : element); + JSIfStatement childStatement = (JSIfStatement)ConditionalUtils.stripBraces(parentStatement.getThen()); + JSExpression childCondition = childStatement.getCondition(); + JSExpression parentCondition = parentStatement.getCondition(); + String childConditionText = ParenthesesUtils.getParenthesized(childCondition, ParenthesesUtils.AND_PRECENDENCE); + String parentConditionText = ParenthesesUtils.getParenthesized(parentCondition, ParenthesesUtils.AND_PRECENDENCE); + JSStatement childThenBranch = childStatement.getThen(); + String statement = "if (" + parentConditionText + " && " + childConditionText + ')' + childThenBranch.getText(); + + JSElementFactory.replaceStatement(parentStatement, statement); + } + + private static class MergeIfAndPredicate implements JSElementPredicate { + + @Override + public boolean satisfiedBy(@Nonnull PsiElement element) { + if (!(element instanceof JSElement)) { + return false; + } + + PsiElement parent = element.getParent(); + + if (!(parent instanceof JSIfStatement)) { + if (element instanceof JSIfStatement) { + parent = element; + } + else { + return false; + } + } + + JSIfStatement ifStatement = (JSIfStatement)parent; + + if (ErrorUtil.containsError(ifStatement)) { + return false; + } + + JSStatement thenBranch = ConditionalUtils.stripBraces(ifStatement.getThen()); + JSStatement elseBranch = ConditionalUtils.stripBraces(ifStatement.getElse()); + + return elseBranch == null && thenBranch instanceof JSIfStatement childIfStatement && childIfStatement.getElse() == null; + } + } } \ No newline at end of file diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSMergeIfOrIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSMergeIfOrIntention.java index 8125af55..a82725e7 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSMergeIfOrIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSMergeIfOrIntention.java @@ -19,211 +19,161 @@ import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.JSIfStatement; import com.intellij.lang.javascript.psi.JSStatement; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.*; -import org.jetbrains.annotations.NonNls; - -import javax.annotation.Nonnull; @ExtensionImpl -@IntentionMetaData(ignoreId = "JSMergeIfOrIntention", categories = { - "JavaScript", - "Control Flow" -}, fileExtensions = "js") -public class JSMergeIfOrIntention extends JSIntention -{ - @NonNls - private static final String IF_STATEMENT_PREFIX = "if ("; - @NonNls - private static final String ELSE_KEYWORD = "else "; - - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new MergeIfOrPredicate(); - } - - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - assert (element instanceof JSElement); - JSElement jsElement = (JSElement) element; - if(MergeIfOrPredicate.isMergableExplicitIf(jsElement)) - { - replaceMergeableExplicitIf(jsElement); - } - else - { - replaceMergeableImplicitIf(jsElement); - } - } - - private static void replaceMergeableExplicitIf(JSElement token) throws IncorrectOperationException - { - final JSIfStatement parentStatement = (JSIfStatement) (token.getParent() instanceof JSIfStatement ? token.getParent() : token); - - assert (parentStatement != null); - - final JSIfStatement childStatement = (JSIfStatement) parentStatement.getElse(); - final JSExpression childCondition = childStatement.getCondition(); - final JSExpression condition = parentStatement.getCondition(); - final String childConditionText = ParenthesesUtils.getParenthesized(childCondition, ParenthesesUtils.OR_PRECENDENCE); - final String parentConditionText = ParenthesesUtils.getParenthesized(condition, ParenthesesUtils.OR_PRECENDENCE); - final JSStatement parentThenBranch = parentStatement.getThen(); - final String parentThenBranchText = parentThenBranch.getText(); - final StringBuilder statement = new StringBuilder(IF_STATEMENT_PREFIX) - .append(parentConditionText) - .append(" || ") - .append(childConditionText) - .append(')') - .append(parentThenBranchText); - final JSStatement childElseBranch = childStatement.getElse(); - - if(childElseBranch != null) - { - final String childElseBranchText = childElseBranch.getText(); - - statement.append(ELSE_KEYWORD) - .append(childElseBranchText); - } - - JSElementFactory.replaceStatement(parentStatement, statement.toString()); - } - - private static void replaceMergeableImplicitIf(JSElement token) throws IncorrectOperationException - { - final JSIfStatement parentStatement = (JSIfStatement) (token.getParent() instanceof JSIfStatement ? token.getParent() : token); - final JSIfStatement childStatement = (JSIfStatement) JSElementFactory.getNonWhiteSpaceSibling(parentStatement, true); - - assert (childStatement != null); - assert (parentStatement != null); - - final JSExpression childCondition = childStatement.getCondition(); - final JSExpression condition = parentStatement.getCondition(); - final String childConditionText = ParenthesesUtils.getParenthesized(childCondition, ParenthesesUtils.OR_PRECENDENCE); - final String parentConditionText = ParenthesesUtils.getParenthesized(condition, ParenthesesUtils.OR_PRECENDENCE); - final JSStatement parentThenBranch = parentStatement.getThen(); - final JSStatement childElseBranch = childStatement.getElse(); - StringBuilder statement = new StringBuilder(IF_STATEMENT_PREFIX) - .append(parentConditionText) - .append(" || ") - .append(childConditionText) - .append(')') - .append(parentThenBranch.getText()); - - if(childElseBranch != null) - { - statement.append(ELSE_KEYWORD) - .append(childElseBranch.getText()); - } - - JSElementFactory.replaceStatement(parentStatement, statement.toString()); - JSElementFactory.removeElement(childStatement); - } - - private static class MergeIfOrPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSElement)) - { - return false; - } - - final JSElement jsElement = (JSElement) element; - - return (isMergableExplicitIf(jsElement) || isMergableImplicitIf(jsElement)); - } - - public static boolean isMergableExplicitIf(JSElement element) - { - PsiElement parent = element.getParent(); - - if(!(parent instanceof JSIfStatement)) - { - if(element instanceof JSIfStatement) - { - parent = element; - } - else - { - return false; - } - } - - final JSIfStatement ifStatement = (JSIfStatement) parent; - - if(ErrorUtil.containsError(ifStatement)) - { - return false; - } - - final JSStatement thenBranch = ifStatement.getThen(); - final JSStatement elseBranch = ifStatement.getElse(); - - if(thenBranch == null || elseBranch == null) - { - return false; - } - if(!(elseBranch instanceof JSIfStatement)) - { - return false; - } - - final JSIfStatement childIfStatement = (JSIfStatement) elseBranch; - final JSStatement childThenBranch = childIfStatement.getThen(); - - return EquivalenceChecker.statementsAreEquivalent(thenBranch, childThenBranch); - } - - private static boolean isMergableImplicitIf(JSElement element) - { - PsiElement parent = element.getParent(); - - if(!(parent instanceof JSIfStatement)) - { - if(element instanceof JSIfStatement) - { - parent = element; - } - else - { - return false; - } - } - - final JSIfStatement ifStatement = (JSIfStatement) parent; - final JSStatement thenBranch = ifStatement.getThen(); - final JSStatement elseBranch = ifStatement.getElse(); - - if(thenBranch == null || elseBranch != null) - { - return false; - } - - if(ControlFlowUtils.statementMayCompleteNormally(thenBranch)) - { - return false; - } - - final PsiElement nextStatement = JSElementFactory.getNonWhiteSpaceSibling(ifStatement, true); - - if(!(nextStatement instanceof JSIfStatement)) - { - return false; - } - - final JSIfStatement childIfStatement = (JSIfStatement) nextStatement; - final JSStatement childThenBranch = childIfStatement.getThen(); - - return EquivalenceChecker.statementsAreEquivalent(thenBranch, childThenBranch); - } - } +@IntentionMetaData( + ignoreId = "JSMergeIfOrIntention", + categories = {"JavaScript", "Control Flow"}, + fileExtensions = "js" +) +public class JSMergeIfOrIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.trivialifMergeIfOr(); + } + + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new MergeIfOrPredicate(); + } + + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + assert (element instanceof JSElement); + JSElement jsElement = (JSElement)element; + if (MergeIfOrPredicate.isMergableExplicitIf(jsElement)) { + replaceMergeableExplicitIf(jsElement); + } + else { + replaceMergeableImplicitIf(jsElement); + } + } + + @RequiredReadAction + private static void replaceMergeableExplicitIf(JSElement token) throws IncorrectOperationException { + JSIfStatement parentStatement = (JSIfStatement)(token.getParent() instanceof JSIfStatement ? token.getParent() : token); + + assert (parentStatement != null); + + JSIfStatement childStatement = (JSIfStatement)parentStatement.getElse(); + JSExpression childCondition = childStatement.getCondition(); + JSExpression condition = parentStatement.getCondition(); + String childConditionText = ParenthesesUtils.getParenthesized(childCondition, ParenthesesUtils.OR_PRECENDENCE); + String parentConditionText = ParenthesesUtils.getParenthesized(condition, ParenthesesUtils.OR_PRECENDENCE); + JSStatement parentThenBranch = parentStatement.getThen(); + StringBuilder statement = new StringBuilder("if (") + .append(parentConditionText) + .append(" || ") + .append(childConditionText) + .append(')') + .append(parentThenBranch.getText()); + JSStatement childElseBranch = childStatement.getElse(); + + if (childElseBranch != null) { + statement.append("else ").append(childElseBranch.getText()); + } + + JSElementFactory.replaceStatement(parentStatement, statement.toString()); + } + + @RequiredReadAction + private static void replaceMergeableImplicitIf(JSElement token) throws IncorrectOperationException { + JSIfStatement parentStatement = (JSIfStatement)(token.getParent() instanceof JSIfStatement ? token.getParent() : token); + JSIfStatement childStatement = (JSIfStatement)JSElementFactory.getNonWhiteSpaceSibling(parentStatement, true); + + assert (childStatement != null); + assert (parentStatement != null); + + JSExpression childCondition = childStatement.getCondition(); + JSExpression condition = parentStatement.getCondition(); + String childConditionText = ParenthesesUtils.getParenthesized(childCondition, ParenthesesUtils.OR_PRECENDENCE); + String parentConditionText = ParenthesesUtils.getParenthesized(condition, ParenthesesUtils.OR_PRECENDENCE); + JSStatement parentThenBranch = parentStatement.getThen(); + JSStatement childElseBranch = childStatement.getElse(); + StringBuilder statement = new StringBuilder("if (") + .append(parentConditionText) + .append(" || ") + .append(childConditionText) + .append(')') + .append(parentThenBranch.getText()); + + if (childElseBranch != null) { + statement.append("else ").append(childElseBranch.getText()); + } + + JSElementFactory.replaceStatement(parentStatement, statement.toString()); + JSElementFactory.removeElement(childStatement); + } + + private static class MergeIfOrPredicate implements JSElementPredicate { + @Override + public boolean satisfiedBy(@Nonnull PsiElement element) { + return element instanceof JSElement jsElement + && (isMergableExplicitIf(jsElement) || isMergableImplicitIf(jsElement)); + } + + public static boolean isMergableExplicitIf(JSElement element) { + PsiElement parent = element.getParent(); + + if (!(parent instanceof JSIfStatement)) { + if (element instanceof JSIfStatement) { + parent = element; + } + else { + return false; + } + } + + JSIfStatement ifStatement = (JSIfStatement)parent; + + if (ErrorUtil.containsError(ifStatement)) { + return false; + } + + JSStatement thenBranch = ifStatement.getThen(), elseBranch = ifStatement.getElse(); + + return thenBranch != null + && elseBranch instanceof JSIfStatement childIfStatement + && EquivalenceChecker.statementsAreEquivalent(thenBranch, childIfStatement.getThen()); + } + + private static boolean isMergableImplicitIf(JSElement element) { + PsiElement parent = element.getParent(); + + if (!(parent instanceof JSIfStatement)) { + if (element instanceof JSIfStatement) { + parent = element; + } + else { + return false; + } + } + + JSIfStatement ifStatement = (JSIfStatement)parent; + JSStatement thenBranch = ifStatement.getThen(), elseBranch = ifStatement.getElse(); + + if (thenBranch == null || elseBranch != null || ControlFlowUtils.statementMayCompleteNormally(thenBranch)) { + return false; + } + + PsiElement nextStatement = JSElementFactory.getNonWhiteSpaceSibling(ifStatement, true); + + return nextStatement instanceof JSIfStatement childIfStatement + && EquivalenceChecker.statementsAreEquivalent(thenBranch, childIfStatement.getThen()); + } + } } \ No newline at end of file diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSMergeParallelIfsIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSMergeParallelIfsIntention.java index d5a0e93a..bbca23e4 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSMergeParallelIfsIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSMergeParallelIfsIntention.java @@ -18,134 +18,109 @@ import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.JSIfStatement; import com.intellij.lang.javascript.psi.JSStatement; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.ControlFlowUtils; import org.intellij.idea.lang.javascript.psiutil.EquivalenceChecker; import org.intellij.idea.lang.javascript.psiutil.ErrorUtil; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; -import org.jetbrains.annotations.NonNls; - -import javax.annotation.Nonnull; @ExtensionImpl -@IntentionMetaData(ignoreId = "JSMergeParallelIfsIntention", categories = { - "JavaScript", - "Control Flow" -}, fileExtensions = "js") -public class JSMergeParallelIfsIntention extends JSIntention -{ - @NonNls - private static final String IF_STATEMENT_PREFIX = "if ("; - @NonNls - private static final String ELSE_KEYWORD = "else "; - - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new MergeParallelIfsPredicate(); - } - - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final PsiElement nextElement = JSElementFactory.getNonWhiteSpaceSibling(element, true); - - assert (nextElement != null); - - final JSIfStatement firstStatement = (JSIfStatement) element; - final JSIfStatement secondStatement = (JSIfStatement) nextElement; - final StringBuilder statementBuffer = new StringBuilder(); - - this.mergeIfStatements(statementBuffer, firstStatement, secondStatement); - JSElementFactory.replaceStatement(firstStatement, statementBuffer.toString()); - JSElementFactory.removeElement(secondStatement); - } - - private void mergeIfStatements(StringBuilder statementBuffer, - JSIfStatement firstStatement, - JSIfStatement secondStatement) - { - final JSExpression condition = firstStatement.getCondition(); - final JSStatement firstThenBranch = firstStatement.getThen(); - final JSStatement secondThenBranch = secondStatement.getThen(); - final JSStatement firstElseBranch = firstStatement.getElse(); - final JSStatement secondElseBranch = secondStatement.getElse(); - - statementBuffer.append(IF_STATEMENT_PREFIX) - .append(condition.getText()) - .append(')'); - ControlFlowUtils.appendStatementsInSequence(statementBuffer, firstThenBranch, secondThenBranch); - - if(firstElseBranch != null || secondElseBranch != null) - { - statementBuffer.append(ELSE_KEYWORD); - if(firstElseBranch instanceof JSIfStatement && - secondElseBranch instanceof JSIfStatement && - MergeParallelIfsPredicate.ifStatementsCanBeMerged((JSIfStatement) firstElseBranch, - (JSIfStatement) secondElseBranch)) - { - this.mergeIfStatements(statementBuffer, - (JSIfStatement) firstElseBranch, - (JSIfStatement) secondElseBranch); - } - else - { - ControlFlowUtils.appendStatementsInSequence(statementBuffer, firstElseBranch, secondElseBranch); - } - } - } - - private static class MergeParallelIfsPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSIfStatement) || ErrorUtil.containsError(element)) - { - return false; - } - - final PsiElement nextStatement = JSElementFactory.getNonWhiteSpaceSibling(element, true); - - if(!(nextStatement instanceof JSIfStatement) || ErrorUtil.containsError(nextStatement)) - { - return false; - } - - return ifStatementsCanBeMerged((JSIfStatement) element, - (JSIfStatement) nextStatement); - } - - public static boolean ifStatementsCanBeMerged(JSIfStatement statement1, - JSIfStatement statement2) - { - final JSStatement thenBranch = statement1.getThen(); - final JSStatement elseBranch = statement1.getElse(); - if(thenBranch == null) - { - return false; - } - final JSExpression firstCondition = statement1.getCondition(); - final JSExpression secondCondition = statement2.getCondition(); - if(!EquivalenceChecker.expressionsAreEquivalent(firstCondition, - secondCondition)) - { - return false; - } - final JSStatement nextThenBranch = statement2.getThen(); - if(!ControlFlowUtils.canBeMerged(thenBranch, nextThenBranch)) - { - return false; - } - final JSStatement nextElseBranch = statement2.getElse(); - return (elseBranch == null || nextElseBranch == null || - ControlFlowUtils.canBeMerged(elseBranch, nextElseBranch)); - } - } +@IntentionMetaData( + ignoreId = "JSMergeParallelIfsIntention", + categories = {"JavaScript", "Control Flow"}, + fileExtensions = "js" +) +public class JSMergeParallelIfsIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.trivialifMergeParallelIfs(); + } + + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new MergeParallelIfsPredicate(); + } + + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + PsiElement nextElement = JSElementFactory.getNonWhiteSpaceSibling(element, true); + + assert (nextElement != null); + + JSIfStatement firstStatement = (JSIfStatement)element; + JSIfStatement secondStatement = (JSIfStatement)nextElement; + StringBuilder statementBuffer = new StringBuilder(); + + this.mergeIfStatements(statementBuffer, firstStatement, secondStatement); + JSElementFactory.replaceStatement(firstStatement, statementBuffer.toString()); + JSElementFactory.removeElement(secondStatement); + } + + @RequiredReadAction + private void mergeIfStatements(StringBuilder statementBuffer, JSIfStatement firstStatement, JSIfStatement secondStatement) { + JSExpression condition = firstStatement.getCondition(); + JSStatement firstThenBranch = firstStatement.getThen(); + JSStatement secondThenBranch = secondStatement.getThen(); + JSStatement firstElseBranch = firstStatement.getElse(); + JSStatement secondElseBranch = secondStatement.getElse(); + + statementBuffer.append("if (").append(condition.getText()).append(')'); + ControlFlowUtils.appendStatementsInSequence(statementBuffer, firstThenBranch, secondThenBranch); + + if (firstElseBranch != null || secondElseBranch != null) { + statementBuffer.append("else "); + if (firstElseBranch instanceof JSIfStatement firstIfStatement + && secondElseBranch instanceof JSIfStatement secondIfStatement + && MergeParallelIfsPredicate.ifStatementsCanBeMerged(firstIfStatement, secondIfStatement)) { + this.mergeIfStatements(statementBuffer, firstIfStatement, secondIfStatement); + } + else { + ControlFlowUtils.appendStatementsInSequence(statementBuffer, firstElseBranch, secondElseBranch); + } + } + } + + private static class MergeParallelIfsPredicate implements JSElementPredicate { + @Override + public boolean satisfiedBy(@Nonnull PsiElement element) { + return element instanceof JSIfStatement ifStatement + && !ErrorUtil.containsError(element) + && JSElementFactory.getNonWhiteSpaceSibling(element, true) instanceof JSIfStatement nextIfStatement + && !ErrorUtil.containsError(nextIfStatement) + && ifStatementsCanBeMerged(ifStatement, nextIfStatement); + } + + public static boolean ifStatementsCanBeMerged(JSIfStatement statement1, JSIfStatement statement2) { + JSStatement thenBranch = statement1.getThen(); + JSStatement elseBranch = statement1.getElse(); + if (thenBranch == null) { + return false; + } + JSExpression firstCondition = statement1.getCondition(); + JSExpression secondCondition = statement2.getCondition(); + if (!EquivalenceChecker.expressionsAreEquivalent(firstCondition, secondCondition)) { + return false; + } + + JSStatement nextThenBranch = statement2.getThen(); + if (!ControlFlowUtils.canBeMerged(thenBranch, nextThenBranch)) { + return false; + } + + JSStatement nextElseBranch = statement2.getElse(); + return (elseBranch == null || nextElseBranch == null || ControlFlowUtils.canBeMerged(elseBranch, nextElseBranch)); + } + } } \ No newline at end of file diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSRemoveRedundantElseIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSRemoveRedundantElseIntention.java index 6c01a689..b50242d3 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSRemoveRedundantElseIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSRemoveRedundantElseIntention.java @@ -19,96 +19,78 @@ import com.intellij.lang.javascript.psi.JSIfStatement; import com.intellij.lang.javascript.psi.JSReturnStatement; import com.intellij.lang.javascript.psi.JSStatement; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.ErrorUtil; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; -import org.jetbrains.annotations.NonNls; - -import javax.annotation.Nonnull; @ExtensionImpl -@IntentionMetaData(ignoreId = "JSRemoveRedundantElseIntention", categories = { - "JavaScript", - "Control Flow" -}, fileExtensions = "js") -public class JSRemoveRedundantElseIntention extends JSIntention -{ - @NonNls - private static final String IF_STATEMENT_PREFIX = "if ("; - - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new RemoveRedundantElsePredicate(); - } - - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final JSIfStatement ifStatement = (JSIfStatement) element; - final JSStatement thenBranch = ifStatement.getThen(); - final JSStatement elseBranch = ifStatement.getElse(); - - assert (thenBranch != null); - assert (elseBranch != null); - - final String newIfText = IF_STATEMENT_PREFIX + ifStatement.getCondition().getText() + ')' + thenBranch.getText(); - final String elseText = elseBranch.getText(); - final String newStatement = (elseBranch instanceof JSBlockStatement - ? elseText.substring(elseText.indexOf('{') + 1, elseText.lastIndexOf('}') - 1).trim() - : elseText); - - JSElementFactory.addStatementAfter(ifStatement, newStatement); - JSElementFactory.replaceStatement(ifStatement, newIfText); - } - - private static class RemoveRedundantElsePredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSIfStatement)) - { - return false; - } - - final JSIfStatement ifStatement = (JSIfStatement) element; - - if(ErrorUtil.containsError(ifStatement)) - { - return false; - } - - final JSStatement elseBranch = ifStatement.getElse(); - JSStatement thenBranch = ifStatement.getThen(); - - if(elseBranch == null) - { - return false; - } - - while(thenBranch != null && thenBranch instanceof JSBlockStatement) - { - JSStatement[] thenStatements = ((JSBlockStatement) thenBranch).getStatements(); - - if(thenStatements.length == 0) - { - return true; - } - else if(thenStatements.length > 1) - { - return false; - } - thenBranch = thenStatements[0]; - } - - return (thenBranch != null && thenBranch instanceof JSReturnStatement); - } - } +@IntentionMetaData( + ignoreId = "JSRemoveRedundantElseIntention", + categories = {"JavaScript", "Control Flow"}, + fileExtensions = "js" +) +public class JSRemoveRedundantElseIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.trivialifRemoveRedundantElse(); + } + + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new RemoveRedundantElsePredicate(); + } + + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + JSIfStatement ifStatement = (JSIfStatement)element; + JSStatement thenBranch = ifStatement.getThen(); + JSStatement elseBranch = ifStatement.getElse(); + + assert (thenBranch != null); + assert (elseBranch != null); + + String newIfText = "if (" + ifStatement.getCondition().getText() + ')' + thenBranch.getText(); + String elseText = elseBranch.getText(); + String newStatement = elseBranch instanceof JSBlockStatement + ? elseText.substring(elseText.indexOf('{') + 1, elseText.lastIndexOf('}') - 1).trim() + : elseText; + + JSElementFactory.addStatementAfter(ifStatement, newStatement); + JSElementFactory.replaceStatement(ifStatement, newIfText); + } + + private static class RemoveRedundantElsePredicate implements JSElementPredicate { + @Override + public boolean satisfiedBy(@Nonnull PsiElement element) { + if (element instanceof JSIfStatement ifStatement && !ErrorUtil.containsError(ifStatement) && ifStatement.getElse() != null) { + JSStatement thenBranch = ifStatement.getThen(); + while (thenBranch instanceof JSBlockStatement thenBlockStatement) { + JSStatement[] thenStatements = thenBlockStatement.getStatements(); + + if (thenStatements.length == 0) { + return true; + } + else if (thenStatements.length > 1) { + return false; + } + thenBranch = thenStatements[0]; + } + + return thenBranch instanceof JSReturnStatement; + } + return false; + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSReplaceIfWithConditionalIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSReplaceIfWithConditionalIntention.java index 2b6cfc05..c7538b0b 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSReplaceIfWithConditionalIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSReplaceIfWithConditionalIntention.java @@ -16,300 +16,253 @@ package org.intellij.idea.lang.javascript.intention.trivialif; import com.intellij.lang.javascript.psi.*; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.ast.IElementType; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.psi.util.PsiTreeUtil; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.*; -import org.jetbrains.annotations.NonNls; - -import javax.annotation.Nonnull; @ExtensionImpl -@IntentionMetaData(ignoreId = "JSReplaceIfWithConditionalIntention", categories = { - "JavaScript", - "Conditional" -}, fileExtensions = "js") -public class JSReplaceIfWithConditionalIntention extends JSIntention -{ - private static final char TERNARY_QUESTION = '?'; - private static final char TERNARY_SEMICOLON = ':'; - @NonNls - private static final String RETURN_KEYWORD = "return "; - - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new ReplaceIfWithConditionalPredicate(); - } - - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final JSIfStatement ifStatement = (JSIfStatement) (element.getParent() instanceof JSIfStatement ? element.getParent() : element); - - assert (ifStatement != null); - - if(ReplaceIfWithConditionalPredicate.isReplaceableAssignment(ifStatement)) - { - final StringBuilder newStatement = new StringBuilder(); - - getAssignmentReplacement(newStatement, ifStatement); - newStatement.append(';'); - JSElementFactory.replaceStatement(ifStatement, newStatement.toString()); - } - else if(ReplaceIfWithConditionalPredicate.isReplaceableReturn(ifStatement)) - { - final StringBuilder newStatement = new StringBuilder(RETURN_KEYWORD); - - getReturnReplacement(newStatement, ifStatement); - newStatement.append(';'); - JSElementFactory.replaceStatement(ifStatement, newStatement.toString()); - } - else if(ReplaceIfWithConditionalPredicate.isReplaceableImplicitReturn(ifStatement)) - { - final JSExpression condition = ifStatement.getCondition(); - final JSReturnStatement thenBranch = (JSReturnStatement) ConditionalUtils.stripBraces(ifStatement.getThen()); - final JSReturnStatement elseBranch = PsiTreeUtil.getNextSiblingOfType(ifStatement, JSReturnStatement.class); - final String newStatement = getImplicitReturnReplacement(condition, thenBranch, elseBranch); - - JSElementFactory.replaceStatement(ifStatement, newStatement); - if(elseBranch != null) - { - JSElementFactory.removeElement(elseBranch); - } - } - } - - private static void getAssignmentReplacement(StringBuilder buffer, JSIfStatement ifStatement) - { - final JSExpression condition = ifStatement.getCondition(); - final JSExpressionStatement thenBranch = (JSExpressionStatement) ConditionalUtils.stripBraces(ifStatement.getThen()); - final JSAssignmentExpression thenAssign = (JSAssignmentExpression) thenBranch.getExpression(); - final JSExpression thenRhs = thenAssign.getROperand(); - final String operator = BinaryOperatorUtils.getOperatorText(thenAssign.getOperationSign()); - final JSStatement elseBranch = ifStatement.getElse(); - - assert (thenRhs != null); - - buffer.append(thenAssign.getLOperand().getText()) - .append(operator) - .append(ParenthesesUtils.getParenthesized(condition, ParenthesesUtils.CONDITIONAL_PRECENDENCE)) - .append(TERNARY_QUESTION) - .append(ParenthesesUtils.getParenthesized(thenRhs, ParenthesesUtils.CONDITIONAL_PRECENDENCE)) - .append(TERNARY_SEMICOLON); - - if(elseBranch instanceof JSIfStatement) - { - getAssignmentReplacement(buffer, (JSIfStatement) elseBranch); - return; - } - - final JSExpressionStatement strippedElseBranch = (JSExpressionStatement) ConditionalUtils.stripBraces(elseBranch); - final JSAssignmentExpression elseAssign = (JSAssignmentExpression) strippedElseBranch.getExpression(); - final JSExpression elseRhs = elseAssign.getROperand(); - - assert (elseRhs != null); - - buffer.append(ParenthesesUtils.getParenthesized(elseRhs, ParenthesesUtils.CONDITIONAL_PRECENDENCE)); - } - - private static void getReturnReplacement(StringBuilder buffer, JSIfStatement ifStatement) - { - final JSStatement thenBranch = ifStatement.getThen(); - final JSReturnStatement thenReturn = (JSReturnStatement) ConditionalUtils.stripBraces(thenBranch); - final JSStatement elseBranch = ifStatement.getElse(); - - buffer.append(ParenthesesUtils.getParenthesized(ifStatement.getCondition(), - ParenthesesUtils.CONDITIONAL_PRECENDENCE)) - .append(TERNARY_QUESTION) - .append(ParenthesesUtils.getParenthesized(thenReturn.getExpression(), - ParenthesesUtils.CONDITIONAL_PRECENDENCE)) - .append(TERNARY_SEMICOLON); - - if(elseBranch instanceof JSIfStatement) - { - getReturnReplacement(buffer, (JSIfStatement) elseBranch); - return; - } - - final JSReturnStatement elseReturn = (JSReturnStatement) ConditionalUtils.stripBraces(elseBranch); - - buffer.append(ParenthesesUtils.getParenthesized(elseReturn.getExpression(), - ParenthesesUtils.CONDITIONAL_PRECENDENCE)); - } - - private static String getImplicitReturnReplacement(JSExpression condition, JSReturnStatement thenBranch, JSReturnStatement elseBranch) - { - assert (thenBranch != null); - assert (elseBranch != null); - - final JSExpression thenReturnValue = thenBranch.getExpression(); - final JSExpression elseReturnValue = elseBranch.getExpression(); - - final String thenValue = ParenthesesUtils.getParenthesized(thenReturnValue, ParenthesesUtils.CONDITIONAL_PRECENDENCE); - final String elseValue = ParenthesesUtils.getParenthesized(elseReturnValue, ParenthesesUtils.CONDITIONAL_PRECENDENCE); - final String conditionText = ParenthesesUtils.getParenthesized(condition, ParenthesesUtils.CONDITIONAL_PRECENDENCE); - - return RETURN_KEYWORD + conditionText + TERNARY_QUESTION + thenValue + TERNARY_SEMICOLON + elseValue + ';'; - } - - private static class ReplaceIfWithConditionalPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSElement)) - { - return false; - } - - PsiElement parent = element.getParent(); - - if(!(parent instanceof JSIfStatement)) - { - if(element instanceof JSIfStatement) - { - parent = element; - } - else - { - return false; - } - } - - if(ErrorUtil.containsError(parent)) - { - return false; - } - - final JSIfStatement ifStatement = (JSIfStatement) parent; - final JSExpression condition = ifStatement.getCondition(); - - if(condition == null || !condition.isValid()) - { - return false; - } - if(isReplaceableAssignment(ifStatement)) - { - return true; - } - if(isReplaceableReturn(ifStatement)) - { - return true; - } - return isReplaceableImplicitReturn(ifStatement); - } - - public static boolean isReplaceableImplicitReturn(JSIfStatement ifStatement) - { - final PsiElement nextStatement = JSElementFactory.getNonWhiteSpaceSibling(ifStatement, true); - - if(!(nextStatement instanceof JSReturnStatement)) - { - return false; - } - - final JSStatement thenBranch = ConditionalUtils.stripBraces(ifStatement.getThen()); - - if(!(thenBranch instanceof JSReturnStatement)) - { - return false; - } - - return (((JSReturnStatement) thenBranch).getExpression() != null && - ((JSReturnStatement) nextStatement).getExpression() != null); - } - - public static boolean isReplaceableReturn(JSIfStatement ifStatement) - { - final JSStatement thenBranch = ConditionalUtils.stripBraces(ifStatement.getThen()); - final JSStatement elseBranch = ConditionalUtils.stripBraces(ifStatement.getElse()); - - if(!(thenBranch instanceof JSReturnStatement)) - { - return false; - } - - if(elseBranch instanceof JSIfStatement) - { - return isReplaceableReturn((JSIfStatement) elseBranch); - } - if(!(elseBranch instanceof JSReturnStatement)) - { - return false; - } - - return (((JSReturnStatement) thenBranch).getExpression() != null && - ((JSReturnStatement) elseBranch).getExpression() != null); - - } - - public static boolean isReplaceableAssignment(JSIfStatement ifStatement) - { - final JSStatement thenBranch = ConditionalUtils.stripBraces(ifStatement.getThen()); - if(thenBranch == null) - { - return false; - } - - if(!ConditionalUtils.isAssignment(thenBranch)) - { - return false; - } - final JSStatement elseBranch = ConditionalUtils.stripBraces(ifStatement.getElse()); - - if(elseBranch == null) - { - return false; - } - if(elseBranch instanceof JSIfStatement) - { - return isReplaceableAssignment((JSIfStatement) elseBranch); - } - - if(!ConditionalUtils.isAssignment(elseBranch)) - { - return false; - } - - final JSAssignmentExpression thenExpression = (JSAssignmentExpression) ((JSExpressionStatement) thenBranch).getExpression(); - final JSAssignmentExpression elseExpression = (JSAssignmentExpression) ((JSExpressionStatement) elseBranch).getExpression(); - final IElementType thenSign = thenExpression.getOperationSign(); - final IElementType elseSign = elseExpression.getOperationSign(); - - if(!thenSign.equals(elseSign)) - { - return false; - } - - final JSExpression thenLhs = thenExpression.getLOperand(); - - if(thenExpression.getROperand() == null) - { - return false; - } - if(elseExpression.getROperand() == null || - elseExpression.getLOperand() == null) - { - return false; - } - final JSExpression thenRhs = thenExpression.getROperand(); - assert thenRhs != null; - - final JSExpression elseRhs = elseExpression.getROperand(); - if(elseRhs == null) - { - return false; - } - - final JSExpression elseLhs = elseExpression.getLOperand(); - return EquivalenceChecker.expressionsAreEquivalent(thenLhs, elseLhs); - } - } +@IntentionMetaData( + ignoreId = "JSReplaceIfWithConditionalIntention", + categories = {"JavaScript", "Conditional"}, + fileExtensions = "js" +) +public class JSReplaceIfWithConditionalIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.trivialifReplaceIfWithConditional(); + } + + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new ReplaceIfWithConditionalPredicate(); + } + + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + JSIfStatement ifStatement = (JSIfStatement)(element.getParent() instanceof JSIfStatement ? element.getParent() : element); + + assert (ifStatement != null); + + if (ReplaceIfWithConditionalPredicate.isReplaceableAssignment(ifStatement)) { + StringBuilder newStatement = new StringBuilder(); + + getAssignmentReplacement(newStatement, ifStatement); + newStatement.append(';'); + JSElementFactory.replaceStatement(ifStatement, newStatement.toString()); + } + else if (ReplaceIfWithConditionalPredicate.isReplaceableReturn(ifStatement)) { + StringBuilder newStatement = new StringBuilder("return "); + + getReturnReplacement(newStatement, ifStatement); + newStatement.append(';'); + JSElementFactory.replaceStatement(ifStatement, newStatement.toString()); + } + else if (ReplaceIfWithConditionalPredicate.isReplaceableImplicitReturn(ifStatement)) { + JSExpression condition = ifStatement.getCondition(); + JSReturnStatement thenBranch = (JSReturnStatement)ConditionalUtils.stripBraces(ifStatement.getThen()); + JSReturnStatement elseBranch = PsiTreeUtil.getNextSiblingOfType(ifStatement, JSReturnStatement.class); + String newStatement = getImplicitReturnReplacement(condition, thenBranch, elseBranch); + + JSElementFactory.replaceStatement(ifStatement, newStatement); + if (elseBranch != null) { + JSElementFactory.removeElement(elseBranch); + } + } + } + + @RequiredReadAction + private static void getAssignmentReplacement(StringBuilder buffer, JSIfStatement ifStatement) { + JSExpression condition = ifStatement.getCondition(); + JSExpressionStatement thenBranch = (JSExpressionStatement)ConditionalUtils.stripBraces(ifStatement.getThen()); + JSAssignmentExpression thenAssign = (JSAssignmentExpression)thenBranch.getExpression(); + JSExpression thenRhs = thenAssign.getROperand(); + String operator = BinaryOperatorUtils.getOperatorText(thenAssign.getOperationSign()); + JSStatement elseBranch = ifStatement.getElse(); + + assert (thenRhs != null); + + buffer.append(thenAssign.getLOperand().getText()) + .append(operator) + .append(ParenthesesUtils.getParenthesized(condition, ParenthesesUtils.CONDITIONAL_PRECENDENCE)) + .append('?') + .append(ParenthesesUtils.getParenthesized(thenRhs, ParenthesesUtils.CONDITIONAL_PRECENDENCE)) + .append(':'); + + if (elseBranch instanceof JSIfStatement) { + getAssignmentReplacement(buffer, (JSIfStatement)elseBranch); + return; + } + + JSExpressionStatement strippedElseBranch = (JSExpressionStatement)ConditionalUtils.stripBraces(elseBranch); + JSAssignmentExpression elseAssign = (JSAssignmentExpression)strippedElseBranch.getExpression(); + JSExpression elseRhs = elseAssign.getROperand(); + + assert (elseRhs != null); + + buffer.append(ParenthesesUtils.getParenthesized(elseRhs, ParenthesesUtils.CONDITIONAL_PRECENDENCE)); + } + + private static void getReturnReplacement(StringBuilder buffer, JSIfStatement ifStatement) { + JSStatement thenBranch = ifStatement.getThen(); + JSReturnStatement thenReturn = (JSReturnStatement)ConditionalUtils.stripBraces(thenBranch); + JSStatement elseBranch = ifStatement.getElse(); + + buffer.append(ParenthesesUtils.getParenthesized(ifStatement.getCondition(), ParenthesesUtils.CONDITIONAL_PRECENDENCE)) + .append('?') + .append(ParenthesesUtils.getParenthesized(thenReturn.getExpression(), ParenthesesUtils.CONDITIONAL_PRECENDENCE)) + .append(':'); + + if (elseBranch instanceof JSIfStatement elseIfStatement) { + getReturnReplacement(buffer, elseIfStatement); + return; + } + + JSReturnStatement elseReturn = (JSReturnStatement)ConditionalUtils.stripBraces(elseBranch); + + buffer.append(ParenthesesUtils.getParenthesized(elseReturn.getExpression(), ParenthesesUtils.CONDITIONAL_PRECENDENCE)); + } + + private static String getImplicitReturnReplacement(JSExpression condition, JSReturnStatement thenBranch, JSReturnStatement elseBranch) { + assert (thenBranch != null); + assert (elseBranch != null); + + JSExpression thenReturnValue = thenBranch.getExpression(); + JSExpression elseReturnValue = elseBranch.getExpression(); + + String thenValue = ParenthesesUtils.getParenthesized(thenReturnValue, ParenthesesUtils.CONDITIONAL_PRECENDENCE); + String elseValue = ParenthesesUtils.getParenthesized(elseReturnValue, ParenthesesUtils.CONDITIONAL_PRECENDENCE); + String conditionText = ParenthesesUtils.getParenthesized(condition, ParenthesesUtils.CONDITIONAL_PRECENDENCE); + + return "return " + conditionText + '?' + thenValue + ':' + elseValue + ';'; + } + + private static class ReplaceIfWithConditionalPredicate implements JSElementPredicate { + @Override + public boolean satisfiedBy(@Nonnull PsiElement element) { + if (!(element instanceof JSElement)) { + return false; + } + + PsiElement parent = element.getParent(); + + if (!(parent instanceof JSIfStatement)) { + if (element instanceof JSIfStatement) { + parent = element; + } + else { + return false; + } + } + + if (ErrorUtil.containsError(parent)) { + return false; + } + + JSIfStatement ifStatement = (JSIfStatement)parent; + JSExpression condition = ifStatement.getCondition(); + + if (condition == null || !condition.isValid()) { + return false; + } + return isReplaceableAssignment(ifStatement) + || isReplaceableReturn(ifStatement) + || isReplaceableImplicitReturn(ifStatement); + } + + public static boolean isReplaceableImplicitReturn(JSIfStatement ifStatement) { + PsiElement nextStatement = JSElementFactory.getNonWhiteSpaceSibling(ifStatement, true); + + if (!(nextStatement instanceof JSReturnStatement nextReturnStatement)) { + return false; + } + + JSStatement thenBranch = ConditionalUtils.stripBraces(ifStatement.getThen()); + + return thenBranch instanceof JSReturnStatement thenReturnStatement + && thenReturnStatement.getExpression() != null + && nextReturnStatement.getExpression() != null; + } + + public static boolean isReplaceableReturn(JSIfStatement ifStatement) { + JSStatement thenBranch = ConditionalUtils.stripBraces(ifStatement.getThen()); + JSStatement elseBranch = ConditionalUtils.stripBraces(ifStatement.getElse()); + + if (!(thenBranch instanceof JSReturnStatement thenReturnStatement)) { + return false; + } + + if (elseBranch instanceof JSIfStatement elseIfStatement) { + return isReplaceableReturn(elseIfStatement); + } + + return elseBranch instanceof JSReturnStatement elseReturnStatement + && thenReturnStatement.getExpression() != null + && elseReturnStatement.getExpression() != null; + } + + @RequiredReadAction + public static boolean isReplaceableAssignment(JSIfStatement ifStatement) { + JSStatement thenBranch = ConditionalUtils.stripBraces(ifStatement.getThen()); + if (thenBranch == null) { + return false; + } + + if (!ConditionalUtils.isAssignment(thenBranch)) { + return false; + } + JSStatement elseBranch = ConditionalUtils.stripBraces(ifStatement.getElse()); + + if (elseBranch == null) { + return false; + } + + if (elseBranch instanceof JSIfStatement elseIfStatement) { + return isReplaceableAssignment(elseIfStatement); + } + + if (!ConditionalUtils.isAssignment(elseBranch)) { + return false; + } + + JSAssignmentExpression thenExpression = (JSAssignmentExpression)((JSExpressionStatement)thenBranch).getExpression(); + JSAssignmentExpression elseExpression = (JSAssignmentExpression)((JSExpressionStatement)elseBranch).getExpression(); + IElementType thenSign = thenExpression.getOperationSign(); + IElementType elseSign = elseExpression.getOperationSign(); + + if (!thenSign.equals(elseSign)) { + return false; + } + + JSExpression thenLhs = thenExpression.getLOperand(); + + if (thenExpression.getROperand() == null + || elseExpression.getROperand() == null + || elseExpression.getLOperand() == null) { + return false; + } + JSExpression thenRhs = thenExpression.getROperand(); + assert thenRhs != null; + + JSExpression elseRhs = elseExpression.getROperand(); + if (elseRhs == null) { + return false; + } + + JSExpression elseLhs = elseExpression.getLOperand(); + return EquivalenceChecker.expressionsAreEquivalent(thenLhs, elseLhs); + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSSimplifyIfElseIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSSimplifyIfElseIntention.java index f516bd8e..bf63c521 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSSimplifyIfElseIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSSimplifyIfElseIntention.java @@ -19,83 +19,79 @@ import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.JSIfStatement; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.ConditionalUtils; import org.intellij.idea.lang.javascript.psiutil.ErrorUtil; -import javax.annotation.Nonnull; - @ExtensionImpl -@IntentionMetaData(ignoreId = "JSSimplifyIfElseIntention", categories = { - "JavaScript", - "Control Flow" -}, fileExtensions = "js") -public class JSSimplifyIfElseIntention extends JSIntention -{ - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new SimplifyIfElsePredicate(); - } +@IntentionMetaData( + ignoreId = "JSSimplifyIfElseIntention", + categories = {"JavaScript", "Control Flow"}, + fileExtensions = "js" +) +public class JSSimplifyIfElseIntention extends JSIntention { + @Nonnull + @Override + public LocalizeValue getText() { + return JSIntentionLocalize.trivialifSimplifyIfElse(); + } - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final PsiElement statement = (element.getParent() instanceof JSIfStatement ? element.getParent() : element); + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new SimplifyIfElsePredicate(); + } - ConditionalUtils.replaceAssignmentOrReturnIfSimplifiable((JSIfStatement) statement); - } + @Override + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + PsiElement statement = element.getParent() instanceof JSIfStatement ? element.getParent() : element; - private static class SimplifyIfElsePredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - if(!(element instanceof JSElement)) - { - return false; - } + ConditionalUtils.replaceAssignmentOrReturnIfSimplifiable((JSIfStatement)statement); + } - PsiElement parent = element.getParent(); + private static class SimplifyIfElsePredicate implements JSElementPredicate { + @Override + public boolean satisfiedBy(@Nonnull PsiElement element) { + if (!(element instanceof JSElement)) { + return false; + } - if(!(parent instanceof JSIfStatement)) - { - if(element instanceof JSIfStatement) - { - parent = element; - } - else - { - return false; - } - } - if(ErrorUtil.containsError(parent)) - { - return false; - } + PsiElement parent = element.getParent(); - final JSIfStatement ifStatement = (JSIfStatement) parent; - final JSExpression condition = ifStatement.getCondition(); + if (!(parent instanceof JSIfStatement)) { + if (element instanceof JSIfStatement) { + parent = element; + } + else { + return false; + } + } + if (ErrorUtil.containsError(parent)) { + return false; + } - if(condition == null || !condition.isValid()) - { - return false; - } + JSIfStatement ifStatement = (JSIfStatement)parent; + JSExpression condition = ifStatement.getCondition(); - return (ConditionalUtils.isSimplifiableAssignment(ifStatement, false) || - ConditionalUtils.isSimplifiableAssignment(ifStatement, true) || - ConditionalUtils.isSimplifiableReturn(ifStatement, false) || - ConditionalUtils.isSimplifiableReturn(ifStatement, true) || - ConditionalUtils.isSimplifiableImplicitReturn(ifStatement, false) || - ConditionalUtils.isSimplifiableImplicitReturn(ifStatement, true) || - ConditionalUtils.isSimplifiableImplicitAssignment(ifStatement, false) || - ConditionalUtils.isSimplifiableImplicitAssignment(ifStatement, true)); + if (condition == null || !condition.isValid()) { + return false; + } - } - } + return ConditionalUtils.isSimplifiableAssignment(ifStatement, false) + || ConditionalUtils.isSimplifiableAssignment(ifStatement, true) + || ConditionalUtils.isSimplifiableReturn(ifStatement, false) + || ConditionalUtils.isSimplifiableReturn(ifStatement, true) + || ConditionalUtils.isSimplifiableImplicitReturn(ifStatement, false) + || ConditionalUtils.isSimplifiableImplicitReturn(ifStatement, true) + || ConditionalUtils.isSimplifiableImplicitAssignment(ifStatement, false) + || ConditionalUtils.isSimplifiableImplicitAssignment(ifStatement, true); + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSSplitElseIfIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSSplitElseIfIntention.java index 701c162b..4596975c 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSSplitElseIfIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSSplitElseIfIntention.java @@ -17,67 +17,69 @@ import com.intellij.lang.javascript.psi.JSIfStatement; import com.intellij.lang.javascript.psi.JSStatement; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.ErrorUtil; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; -import javax.annotation.Nonnull; - @ExtensionImpl -@IntentionMetaData(ignoreId = "JSSplitElseIfIntention", categories = { - "JavaScript", - "Control Flow" -}, fileExtensions = "js") -public class JSSplitElseIfIntention extends JSIntention -{ - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new SplitElseIfPredicate(); - } +@IntentionMetaData( + ignoreId = "JSSplitElseIfIntention", + categories = {"JavaScript", "Control Flow"}, + fileExtensions = "js" +) +public class JSSplitElseIfIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.trivialifSplitElseIf(); + } + + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new SplitElseIfPredicate(); + } - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final JSIfStatement parentStatement = (JSIfStatement) element.getParent(); + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + JSIfStatement parentStatement = (JSIfStatement)element.getParent(); - assert (parentStatement != null); + assert (parentStatement != null); - final JSStatement elseBranch = parentStatement.getElse(); - final String newStatement = '{' + elseBranch.getText() + '}'; + JSStatement elseBranch = parentStatement.getElse(); + String newStatement = '{' + elseBranch.getText() + '}'; - JSElementFactory.replaceStatement(elseBranch, newStatement); - } + JSElementFactory.replaceStatement(elseBranch, newStatement); + } - private static class SplitElseIfPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - final PsiElement parent = element.getParent(); + private static class SplitElseIfPredicate implements JSElementPredicate { + @Override + public boolean satisfiedBy(@Nonnull PsiElement element) { + PsiElement parent = element.getParent(); - if(!(parent instanceof JSIfStatement)) - { - return false; - } + if (!(parent instanceof JSIfStatement)) { + return false; + } - final JSIfStatement ifStatement = (JSIfStatement) parent; + JSIfStatement ifStatement = (JSIfStatement)parent; - if(ErrorUtil.containsError(ifStatement)) - { - return false; - } - final JSStatement thenBranch = ifStatement.getThen(); - final JSStatement elseBranch = ifStatement.getElse(); + if (ErrorUtil.containsError(ifStatement)) { + return false; + } + JSStatement thenBranch = ifStatement.getThen(); + JSStatement elseBranch = ifStatement.getElse(); - return (thenBranch != null && elseBranch != null && - elseBranch instanceof JSIfStatement); - } - } + return thenBranch != null && elseBranch != null && elseBranch instanceof JSIfStatement; + } + } } \ No newline at end of file diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSSplitIfAndIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSSplitIfAndIntention.java index c3bf0f3b..c1cbad4c 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSSplitIfAndIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSSplitIfAndIntention.java @@ -20,115 +20,103 @@ import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.JSIfStatement; import com.intellij.lang.javascript.psi.JSStatement; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.ErrorUtil; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; import org.intellij.idea.lang.javascript.psiutil.ParenthesesUtils; -import org.jetbrains.annotations.NonNls; - -import javax.annotation.Nonnull; @ExtensionImpl -@IntentionMetaData(ignoreId = "JSSplitIfAndIntention", categories = { - "JavaScript", - "Control Flow" -}, fileExtensions = "js") -public class JSSplitIfAndIntention extends JSIntention -{ - @NonNls - private static final String IF_STATEMENT_PREFIX = "if ("; - @NonNls - private static final String INNER_IF_STATEMENT_PREFIX = ") {\n if ("; - @NonNls - private static final String ELSE_KEYWORD = "else "; - - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new SplitIfAndPredicate(); - } - - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final PsiElement jsElement = (element.getParent() instanceof JSIfStatement ? element.getParent() : element); - - assert (jsElement != null); - assert (jsElement instanceof JSIfStatement); - - final JSIfStatement ifStatement = (JSIfStatement) jsElement; - - assert (ifStatement.getCondition() instanceof JSBinaryExpression); - - final JSBinaryExpression condition = (JSBinaryExpression) ifStatement.getCondition(); - final String lhsText = ParenthesesUtils.removeParentheses(condition.getLOperand()); - final String rhsText = ParenthesesUtils.removeParentheses(condition.getROperand()); - final JSStatement thenBranch = ifStatement.getThen(); - final JSStatement elseBranch = ifStatement.getElse(); - final String thenText = thenBranch.getText(); - final String elseText = ((elseBranch == null) ? null : elseBranch.getText()); - final int elseLength = ((elseBranch == null) ? 0 : elseText.length()); - - assert (condition.getOperationSign().equals(JSTokenTypes.ANDAND)); - - final StringBuilder statement = new StringBuilder(ifStatement.getTextLength() + elseLength + 30); - - statement.append(IF_STATEMENT_PREFIX) - .append(lhsText) - .append(INNER_IF_STATEMENT_PREFIX) - .append(rhsText) - .append(')') - .append(thenText); - if(elseBranch != null) - { - statement.append(ELSE_KEYWORD) - .append(elseText); - } - statement.append('}'); - if(elseBranch != null) - { - statement.append(ELSE_KEYWORD) - .append(elseText); - } - - JSElementFactory.replaceStatement(ifStatement, statement.toString()); - } - - private static class SplitIfAndPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - PsiElement parent = element.getParent(); - - if(!(parent instanceof JSIfStatement)) - { - if(element instanceof JSIfStatement) - { - parent = element; - } - else - { - return false; - } - } - - final JSIfStatement ifStatement = (JSIfStatement) parent; - final JSExpression condition = ifStatement.getCondition(); - - if(condition == null || ErrorUtil.containsError(condition)) - { - return false; - } - - return (condition instanceof JSBinaryExpression && - ((JSBinaryExpression) condition).getOperationSign().equals(JSTokenTypes.ANDAND)); - } - } +@IntentionMetaData( + ignoreId = "JSSplitIfAndIntention", + categories = {"JavaScript", "Control Flow"}, + fileExtensions = "js" +) +public class JSSplitIfAndIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.trivialifSplitIfAnd(); + } + + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new SplitIfAndPredicate(); + } + + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + PsiElement jsElement = (element.getParent() instanceof JSIfStatement ? element.getParent() : element); + + assert (jsElement != null); + assert (jsElement instanceof JSIfStatement); + + JSIfStatement ifStatement = (JSIfStatement)jsElement; + + assert (ifStatement.getCondition() instanceof JSBinaryExpression); + + JSBinaryExpression condition = (JSBinaryExpression)ifStatement.getCondition(); + String lhsText = ParenthesesUtils.removeParentheses(condition.getLOperand()); + String rhsText = ParenthesesUtils.removeParentheses(condition.getROperand()); + JSStatement thenBranch = ifStatement.getThen(); + JSStatement elseBranch = ifStatement.getElse(); + String thenText = thenBranch.getText(); + String elseText = (elseBranch == null) ? null : elseBranch.getText(); + int elseLength = (elseBranch == null) ? 0 : elseText.length(); + + assert JSTokenTypes.ANDAND.equals(condition.getOperationSign()); + + StringBuilder statement = new StringBuilder(ifStatement.getTextLength() + elseLength + 30); + + statement.append("if (") + .append(lhsText) + .append(") {\n if (") + .append(rhsText) + .append(')') + .append(thenText); + if (elseBranch != null) { + statement.append("else ").append(elseText); + } + statement.append('}'); + if (elseBranch != null) { + statement.append("else ").append(elseText); + } + + JSElementFactory.replaceStatement(ifStatement, statement.toString()); + } + + private static class SplitIfAndPredicate implements JSElementPredicate { + @Override + @RequiredReadAction + public boolean satisfiedBy(@Nonnull PsiElement element) { + PsiElement parent = element.getParent(); + + if (!(parent instanceof JSIfStatement)) { + if (element instanceof JSIfStatement) { + parent = element; + } + else { + return false; + } + } + + JSIfStatement ifStatement = (JSIfStatement)parent; + JSExpression condition = ifStatement.getCondition(); + + return condition != null + && !ErrorUtil.containsError(condition) + && condition instanceof JSBinaryExpression binaryExpression + && JSTokenTypes.ANDAND.equals(binaryExpression.getOperationSign()); + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSSplitIfOrIntention.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSSplitIfOrIntention.java index 12adcd7f..3d6ba289 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSSplitIfOrIntention.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/intention/trivialif/JSSplitIfOrIntention.java @@ -20,109 +20,96 @@ import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.JSIfStatement; import com.intellij.lang.javascript.psi.JSStatement; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.intention.localize.JSIntentionLocalize; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import org.intellij.idea.lang.javascript.intention.JSElementPredicate; import org.intellij.idea.lang.javascript.intention.JSIntention; import org.intellij.idea.lang.javascript.psiutil.ErrorUtil; import org.intellij.idea.lang.javascript.psiutil.JSElementFactory; import org.intellij.idea.lang.javascript.psiutil.ParenthesesUtils; -import org.jetbrains.annotations.NonNls; - -import javax.annotation.Nonnull; @ExtensionImpl -@IntentionMetaData(ignoreId = "JSSplitIfOrIntention", categories = { - "JavaScript", - "Control Flow" -}, fileExtensions = "js") -public class JSSplitIfOrIntention extends JSIntention -{ - @NonNls - private static final String IF_STATEMENT_PREFIX = "if ("; - @NonNls - private static final String ELSE_IF_STATEMENT_PREFIX = "else if ("; - @NonNls - private static final String ELSE_KEYWORD = "else "; - - @Override - @Nonnull - public JSElementPredicate getElementPredicate() - { - return new SplitIfOrPredicate(); - } - - @Override - public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException - { - final PsiElement jsElement = (element.getParent() instanceof JSIfStatement ? element.getParent() : element); - - assert (jsElement != null); - assert (jsElement instanceof JSIfStatement); - - final JSIfStatement ifStatement = (JSIfStatement) jsElement; - - assert (ifStatement.getCondition() instanceof JSBinaryExpression); - - final JSBinaryExpression condition = (JSBinaryExpression) ifStatement.getCondition(); - final String lhsText = ParenthesesUtils.removeParentheses(condition.getLOperand()); - final String rhsText = ParenthesesUtils.removeParentheses(condition.getROperand()); - final JSStatement thenBranch = ifStatement.getThen(); - final JSStatement elseBranch = ifStatement.getElse(); - final String thenText = thenBranch.getText(); - - assert (condition.getOperationSign().equals(JSTokenTypes.OROR)); - - final StringBuilder statement = new StringBuilder(ifStatement.getTextLength()); - - statement.append(IF_STATEMENT_PREFIX) - .append(lhsText) - .append(')') - .append(thenText) - .append(ELSE_IF_STATEMENT_PREFIX) - .append(rhsText) - .append(')') - .append(thenText); - if(elseBranch != null) - { - statement.append(ELSE_KEYWORD) - .append(elseBranch.getText()); - } - - JSElementFactory.replaceStatement(ifStatement, statement.toString()); - } - - private static class SplitIfOrPredicate implements JSElementPredicate - { - @Override - public boolean satisfiedBy(@Nonnull PsiElement element) - { - PsiElement parent = element.getParent(); - - if(!(parent instanceof JSIfStatement)) - { - if(element instanceof JSIfStatement) - { - parent = element; - } - else - { - return false; - } - } - - final JSIfStatement ifStatement = (JSIfStatement) parent; - final JSExpression condition = ifStatement.getCondition(); - - if(condition == null || ErrorUtil.containsError(condition)) - { - return false; - } - - return (condition instanceof JSBinaryExpression && - ((JSBinaryExpression) condition).getOperationSign().equals(JSTokenTypes.OROR)); - } - } +@IntentionMetaData( + ignoreId = "JSSplitIfOrIntention", + categories = {"JavaScript", "Control Flow"}, + fileExtensions = "js" +) +public class JSSplitIfOrIntention extends JSIntention { + @Override + @Nonnull + public LocalizeValue getText() { + return JSIntentionLocalize.trivialifSplitIfOr(); + } + + @Override + @Nonnull + public JSElementPredicate getElementPredicate() { + return new SplitIfOrPredicate(); + } + + @Override + @RequiredReadAction + public void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException { + PsiElement jsElement = (element.getParent() instanceof JSIfStatement ? element.getParent() : element); + + assert (jsElement != null); + assert (jsElement instanceof JSIfStatement); + + JSIfStatement ifStatement = (JSIfStatement)jsElement; + + assert (ifStatement.getCondition() instanceof JSBinaryExpression); + + JSBinaryExpression condition = (JSBinaryExpression)ifStatement.getCondition(); + String lhsText = ParenthesesUtils.removeParentheses(condition.getLOperand()); + String rhsText = ParenthesesUtils.removeParentheses(condition.getROperand()); + JSStatement thenBranch = ifStatement.getThen(); + JSStatement elseBranch = ifStatement.getElse(); + String thenText = thenBranch.getText(); + + assert JSTokenTypes.OROR.equals(condition.getOperationSign()); + + StringBuilder statement = new StringBuilder(ifStatement.getTextLength()); + + statement.append("if (").append(lhsText).append(')') + .append(thenText) + .append("else if (").append(rhsText).append(')') + .append(thenText); + + if (elseBranch != null) { + statement.append("else ").append(elseBranch.getText()); + } + + JSElementFactory.replaceStatement(ifStatement, statement.toString()); + } + + private static class SplitIfOrPredicate implements JSElementPredicate { + @Override + @RequiredReadAction + public boolean satisfiedBy(@Nonnull PsiElement element) { + PsiElement parent = element.getParent(); + + if (!(parent instanceof JSIfStatement)) { + if (element instanceof JSIfStatement) { + parent = element; + } + else { + return false; + } + } + + JSIfStatement ifStatement = (JSIfStatement)parent; + JSExpression condition = ifStatement.getCondition(); + + return condition != null + && !ErrorUtil.containsError(condition) + && condition instanceof JSBinaryExpression binaryExpression + && JSTokenTypes.OROR.equals(binaryExpression.getOperationSign()); + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ArrayStack.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ArrayStack.java index 712115cb..07ad8b11 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ArrayStack.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ArrayStack.java @@ -34,119 +34,108 @@ * please use the standard {@link java.util.Stack java.util.Stack} class * instead. */ -public class ArrayStack extends ArrayList implements Cloneable -{ +public class ArrayStack extends ArrayList implements Cloneable { + /** + * Creates an empty ArrayStack. + */ + public ArrayStack() { + } - /** - * Creates an empty ArrayStack. - */ - public ArrayStack() - { - } + /** + * Pushes an item onto the top of this stack. This has exactly + * the same effect as: + *

+     * add(item)
+ * + * @param item the item to be pushed onto this stack. + * @return the item argument. + * @see ArrayList#add + */ + public E push(E item) { + this.add(item); + return item; + } - /** - * Pushes an item onto the top of this stack. This has exactly - * the same effect as: - *
-	 * add(item)
- * - * @param item the item to be pushed onto this stack. - * @return the item argument. - * @see ArrayList#add - */ - public E push(E item) - { - this.add(item); - return item; - } + /** + * Removes the object at the top of this stack and returns that + * object as the value of this function. + * + * @return The object at the top of this stack (the last item + * of the ArrayList object). + * @throws EmptyStackException if this stack is empty. + */ + public E pop() { + int len = this.size(); + E obj = this.peek(); - /** - * Removes the object at the top of this stack and returns that - * object as the value of this function. - * - * @return The object at the top of this stack (the last item - * of the ArrayList object). - * @throws EmptyStackException if this stack is empty. - */ - public E pop() - { - int len = this.size(); - E obj = this.peek(); + this.remove(len - 1); + return obj; + } - this.remove(len - 1); - return obj; - } + /** + * Looks at the object at the top of this stack without removing it + * from the stack. + * + * @return the object at the top of this stack (the last item + * of the ArrayList object). + * @throws EmptyStackException if this stack is empty. + */ + public E peek() { + int len = this.size(); - /** - * Looks at the object at the top of this stack without removing it - * from the stack. - * - * @return the object at the top of this stack (the last item - * of the ArrayList object). - * @throws EmptyStackException if this stack is empty. - */ - public E peek() - { - int len = this.size(); + if (len == 0) { + throw new EmptyStackException(); + } + return this.get(len - 1); + } - if(len == 0) - { - throw new EmptyStackException(); - } - return this.get(len - 1); - } + /** + * Tests if this stack is empty. + * + * @return true if and only if this stack contains + * no items; false otherwise. + */ + public boolean empty() { + return (this.size() == 0); + } - /** - * Tests if this stack is empty. - * - * @return true if and only if this stack contains - * no items; false otherwise. - */ - public boolean empty() - { - return (this.size() == 0); - } + /** + * Returns the 1-based position where an object is on this stack. + * If the object o occurs as an item in this stack, this + * method returns the distance from the top of the stack of the + * occurrence nearest the top of the stack; the topmost item on the + * stack is considered to be at distance 1. The equals + * method is used to compare o to the + * items in this stack. + * + * @param o the desired object. + * @return the 1-based position from the top of the stack where + * the object is located; the return value -1 + * indicates that the object is not on the stack. + */ + public int search(E o) { + int index = this.lastIndexOf(o); - /** - * Returns the 1-based position where an object is on this stack. - * If the object o occurs as an item in this stack, this - * method returns the distance from the top of the stack of the - * occurrence nearest the top of the stack; the topmost item on the - * stack is considered to be at distance 1. The equals - * method is used to compare o to the - * items in this stack. - * - * @param o the desired object. - * @return the 1-based position from the top of the stack where - * the object is located; the return value -1 - * indicates that the object is not on the stack. - */ - public int search(E o) - { - int index = this.lastIndexOf(o); + if (index >= 0) { + return this.size() - index; + } - if(index >= 0) - { - return this.size() - index; - } + return -1; + } - return -1; - } + /** + * Returns a shallow copy of this ArrayList instance. (The + * elements themselves are not copied.) + * + * @return a clone of this ArrayList instance. + */ + @Override + public Object clone() { + return super.clone(); + } - /** - * Returns a shallow copy of this ArrayList instance. (The - * elements themselves are not copied.) - * - * @return a clone of this ArrayList instance. - */ - @Override - public Object clone() - { - return (ArrayStack) super.clone(); - } - - /** - * use java.util.Stack#serialVersionUID from JDK 1.0.2 for interoperability - */ - private static final long serialVersionUID = 1224463164541339165L; + /** + * use java.util.Stack#serialVersionUID from JDK 1.0.2 for interoperability + */ + private static final long serialVersionUID = 1224463164541339165L; } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/BinaryOperatorUtils.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/BinaryOperatorUtils.java index e0e421f8..5fd6db38 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/BinaryOperatorUtils.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/BinaryOperatorUtils.java @@ -24,116 +24,103 @@ import java.util.HashMap; import java.util.Map; -public class BinaryOperatorUtils -{ - private static final Map operators; +public class BinaryOperatorUtils { + private static final Map operators; - private BinaryOperatorUtils() - { - } + private BinaryOperatorUtils() { + } - public static boolean isBinaryOperator(JSExpression expression) - { - return (expression instanceof JSBinaryExpression && - operators.containsKey(((JSBinaryExpression) expression).getOperationSign())); - } + public static boolean isBinaryOperator(JSExpression expression) { + return expression instanceof JSBinaryExpression binaryExpression + && operators.containsKey(binaryExpression.getOperationSign()); + } - public static boolean isShiftOperator(JSExpression expression) - { - if(expression instanceof JSBinaryExpression) - { - final IElementType sign = ((JSBinaryExpression) expression).getOperationSign(); + public static boolean isShiftOperator(JSExpression expression) { + if (expression instanceof JSBinaryExpression binaryExpression) { + IElementType sign = binaryExpression.getOperationSign(); - return (sign.equals(JSTokenTypes.LTLT) || - sign.equals(JSTokenTypes.GTGT) || - sign.equals(JSTokenTypes.GTGTGT)); - } - else - { - return false; - } - } + return JSTokenTypes.LTLT.equals(sign) || + JSTokenTypes.GTGT.equals(sign) || + JSTokenTypes.GTGTGT.equals(sign); + } + else { + return false; + } + } - public static String getOperatorText(IElementType operator) - { - if(operator == null) - { - return ""; - } - final OperatorProperties operatorProperties = operators.get(operator); - assert operatorProperties != null : "Operator properties is null for " + operator; - return operatorProperties.text; - } + public static String getOperatorText(IElementType operator) { + if (operator == null) { + return ""; + } + OperatorProperties operatorProperties = operators.get(operator); + assert operatorProperties != null : "Operator properties is null for " + operator; + return operatorProperties.text; + } - public static boolean isCommutative(IElementType operator) - { - if(operator == null) - { - return false; - } - final OperatorProperties operatorProperties = operators.get(operator); - assert operatorProperties != null : "Operator properties is null for " + operator; - return operatorProperties.commutative; - } + public static boolean isCommutative(IElementType operator) { + if (operator == null) { + return false; + } + OperatorProperties operatorProperties = operators.get(operator); + assert operatorProperties != null : "Operator properties is null for " + operator; + return operatorProperties.commutative; + } - static - { - operators = new HashMap(39); + static { + operators = new HashMap(39); - operators.put(JSTokenTypes.LT, new OperatorProperties("<", false)); - operators.put(JSTokenTypes.GT, new OperatorProperties(">", false)); - operators.put(JSTokenTypes.LE, new OperatorProperties("<=", false)); - operators.put(JSTokenTypes.GE, new OperatorProperties(">=", false)); - operators.put(JSTokenTypes.EQEQ, new OperatorProperties("==", true)); - operators.put(JSTokenTypes.NE, new OperatorProperties("!=", true)); - operators.put(JSTokenTypes.EQEQEQ, new OperatorProperties("===", true)); - operators.put(JSTokenTypes.NEQEQ, new OperatorProperties("!==", true)); - operators.put(JSTokenTypes.PLUS, new OperatorProperties("+", true)); - operators.put(JSTokenTypes.MINUS, new OperatorProperties("-", false)); - operators.put(JSTokenTypes.MULT, new OperatorProperties("*", true)); - operators.put(JSTokenTypes.DIV, new OperatorProperties("/", false)); - operators.put(JSTokenTypes.PERC, new OperatorProperties("%", false)); - operators.put(JSTokenTypes.PLUSPLUS, new OperatorProperties("++", false)); - operators.put(JSTokenTypes.MINUSMINUS, new OperatorProperties("--", false)); - operators.put(JSTokenTypes.LTLT, new OperatorProperties("<<", false)); - operators.put(JSTokenTypes.GTGT, new OperatorProperties(">>", false)); - operators.put(JSTokenTypes.GTGTGT, new OperatorProperties(">>>", false)); - operators.put(JSTokenTypes.AND, new OperatorProperties("&", true)); - operators.put(JSTokenTypes.OR, new OperatorProperties("|", true)); - operators.put(JSTokenTypes.XOR, new OperatorProperties("^", true)); - operators.put(JSTokenTypes.EXCL, new OperatorProperties("!", false)); - operators.put(JSTokenTypes.TILDE, new OperatorProperties("~", false)); - operators.put(JSTokenTypes.ANDAND, new OperatorProperties("&&", true)); - operators.put(JSTokenTypes.OROR, new OperatorProperties("||", true)); - operators.put(JSTokenTypes.EQ, new OperatorProperties("=", false)); - operators.put(JSTokenTypes.PLUSEQ, new OperatorProperties("+=", false)); - operators.put(JSTokenTypes.MINUSEQ, new OperatorProperties("-=", false)); - operators.put(JSTokenTypes.MULTEQ, new OperatorProperties("*=", false)); - operators.put(JSTokenTypes.PERCEQ, new OperatorProperties("%=", false)); - operators.put(JSTokenTypes.LTLTEQ, new OperatorProperties("<<=", false)); - operators.put(JSTokenTypes.GTGTEQ, new OperatorProperties(">>=", false)); - operators.put(JSTokenTypes.GTGTGTEQ, new OperatorProperties(">>>=", false)); - operators.put(JSTokenTypes.ANDEQ, new OperatorProperties("&=", false)); - operators.put(JSTokenTypes.OREQ, new OperatorProperties("|=", false)); - operators.put(JSTokenTypes.XOREQ, new OperatorProperties("^=", false)); - operators.put(JSTokenTypes.DIVEQ, new OperatorProperties("/=", false)); - operators.put(JSTokenTypes.COMMA, new OperatorProperties(",", false)); - operators.put(JSTokenTypes.IS_KEYWORD, new OperatorProperties("is", false)); - operators.put(JSTokenTypes.AS_KEYWORD, new OperatorProperties("as", false)); - operators.put(JSTokenTypes.DELETE_KEYWORD, new OperatorProperties("delete ", false)); - operators.put(JSTokenTypes.VOID_KEYWORD, new OperatorProperties("void ", false)); - operators.put(JSTokenTypes.TYPEOF_KEYWORD, new OperatorProperties("typeof ", false)); - } + operators.put(JSTokenTypes.LT, new OperatorProperties("<", false)); + operators.put(JSTokenTypes.GT, new OperatorProperties(">", false)); + operators.put(JSTokenTypes.LE, new OperatorProperties("<=", false)); + operators.put(JSTokenTypes.GE, new OperatorProperties(">=", false)); + operators.put(JSTokenTypes.EQEQ, new OperatorProperties("==", true)); + operators.put(JSTokenTypes.NE, new OperatorProperties("!=", true)); + operators.put(JSTokenTypes.EQEQEQ, new OperatorProperties("===", true)); + operators.put(JSTokenTypes.NEQEQ, new OperatorProperties("!==", true)); + operators.put(JSTokenTypes.PLUS, new OperatorProperties("+", true)); + operators.put(JSTokenTypes.MINUS, new OperatorProperties("-", false)); + operators.put(JSTokenTypes.MULT, new OperatorProperties("*", true)); + operators.put(JSTokenTypes.DIV, new OperatorProperties("/", false)); + operators.put(JSTokenTypes.PERC, new OperatorProperties("%", false)); + operators.put(JSTokenTypes.PLUSPLUS, new OperatorProperties("++", false)); + operators.put(JSTokenTypes.MINUSMINUS, new OperatorProperties("--", false)); + operators.put(JSTokenTypes.LTLT, new OperatorProperties("<<", false)); + operators.put(JSTokenTypes.GTGT, new OperatorProperties(">>", false)); + operators.put(JSTokenTypes.GTGTGT, new OperatorProperties(">>>", false)); + operators.put(JSTokenTypes.AND, new OperatorProperties("&", true)); + operators.put(JSTokenTypes.OR, new OperatorProperties("|", true)); + operators.put(JSTokenTypes.XOR, new OperatorProperties("^", true)); + operators.put(JSTokenTypes.EXCL, new OperatorProperties("!", false)); + operators.put(JSTokenTypes.TILDE, new OperatorProperties("~", false)); + operators.put(JSTokenTypes.ANDAND, new OperatorProperties("&&", true)); + operators.put(JSTokenTypes.OROR, new OperatorProperties("||", true)); + operators.put(JSTokenTypes.EQ, new OperatorProperties("=", false)); + operators.put(JSTokenTypes.PLUSEQ, new OperatorProperties("+=", false)); + operators.put(JSTokenTypes.MINUSEQ, new OperatorProperties("-=", false)); + operators.put(JSTokenTypes.MULTEQ, new OperatorProperties("*=", false)); + operators.put(JSTokenTypes.PERCEQ, new OperatorProperties("%=", false)); + operators.put(JSTokenTypes.LTLTEQ, new OperatorProperties("<<=", false)); + operators.put(JSTokenTypes.GTGTEQ, new OperatorProperties(">>=", false)); + operators.put(JSTokenTypes.GTGTGTEQ, new OperatorProperties(">>>=", false)); + operators.put(JSTokenTypes.ANDEQ, new OperatorProperties("&=", false)); + operators.put(JSTokenTypes.OREQ, new OperatorProperties("|=", false)); + operators.put(JSTokenTypes.XOREQ, new OperatorProperties("^=", false)); + operators.put(JSTokenTypes.DIVEQ, new OperatorProperties("/=", false)); + operators.put(JSTokenTypes.COMMA, new OperatorProperties(",", false)); + operators.put(JSTokenTypes.IS_KEYWORD, new OperatorProperties("is", false)); + operators.put(JSTokenTypes.AS_KEYWORD, new OperatorProperties("as", false)); + operators.put(JSTokenTypes.DELETE_KEYWORD, new OperatorProperties("delete ", false)); + operators.put(JSTokenTypes.VOID_KEYWORD, new OperatorProperties("void ", false)); + operators.put(JSTokenTypes.TYPEOF_KEYWORD, new OperatorProperties("typeof ", false)); + } - private static class OperatorProperties - { - String text; - boolean commutative; + private static class OperatorProperties { + String text; + boolean commutative; - public OperatorProperties(@NonNls String text, boolean commutative) - { - this.text = text; - this.commutative = commutative; - } - } + public OperatorProperties(@NonNls String text, boolean commutative) { + this.text = text; + this.commutative = commutative; + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/BoolUtils.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/BoolUtils.java index e336f3c6..8e78ff10 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/BoolUtils.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/BoolUtils.java @@ -19,185 +19,144 @@ import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.impl.JSChangeUtil; import consulo.language.ast.IElementType; +import jakarta.annotation.Nullable; import org.jetbrains.annotations.NonNls; -import javax.annotation.Nullable; - -public class BoolUtils -{ - - @NonNls - public static final String TRUE = "true"; - @NonNls - public static final String FALSE = "false"; - - private BoolUtils() - { - } - - public static boolean isNegated(JSExpression condition) - { - return (findNegation(condition) != null); - } - - @Nullable - public static JSExpression findNegation(JSExpression condition) - { - JSExpression ancestor = condition; - - while(ancestor.getParent() instanceof JSParenthesizedExpression) - { - ancestor = (JSExpression) ancestor.getParent(); - } - - if(ancestor.getParent() instanceof JSPrefixExpression) - { - final JSPrefixExpression prefixAncestor = (JSPrefixExpression) ancestor.getParent(); - if(prefixAncestor.getOperationSign().equals(JSTokenTypes.EXCL)) - { - return prefixAncestor; - } - } - - return null; - } - - public static boolean isNegation(JSExpression condition) - { - return isNegation(condition, false); - } - - public static boolean isNegation(JSExpression condition, boolean ignoreNegatedNullComparison) - { - if(condition instanceof JSPrefixExpression) - { - final JSPrefixExpression prefixExpression = (JSPrefixExpression) condition; - final IElementType sign = prefixExpression.getOperationSign(); - - return sign.equals(JSTokenTypes.EXCL); - } - else if(condition instanceof JSBinaryExpression) - { - final JSBinaryExpression binaryExpression = (JSBinaryExpression) condition; - final IElementType sign = binaryExpression.getOperationSign(); - final JSExpression lhs = binaryExpression.getLOperand(); - final JSExpression rhs = binaryExpression.getROperand(); - - if(rhs != null && sign.equals(JSTokenTypes.NE)) - { - if(!ignoreNegatedNullComparison) - { - return true; - } - - return !isNullLiteral(lhs) && !isNullLiteral(rhs); - } - else - { - return false; - } - } - else if(condition instanceof JSParenthesizedExpression) - { - return isNegation(((JSParenthesizedExpression) condition).getInnerExpression()); - } - else - { - return false; - } - } - - private static boolean isNullLiteral(final JSExpression lhs) - { - return lhs.getNode() != null && JSTokenTypes.NULL_KEYWORD.equals(lhs.getNode().getElementType()); - } - - public static JSExpression getNegated(JSExpression condition) - { - if(condition instanceof JSPrefixExpression) - { - final JSPrefixExpression prefixExp = (JSPrefixExpression) condition; - final JSExpression operand = prefixExp.getExpression(); - - return ParenthesesUtils.stripParentheses(operand); - } - else if(condition instanceof JSBinaryExpression) - { - final JSBinaryExpression binaryExpression = (JSBinaryExpression) condition; - final IElementType sign = binaryExpression.getOperationSign(); - final JSExpression lhs = binaryExpression.getLOperand(); - final JSExpression rhs = binaryExpression.getROperand(); - final String negatedSign = ComparisonUtils.getNegatedOperatorText(sign); - final String negatedText = lhs.getText() + negatedSign + rhs.getText(); - - return (JSExpression) JSChangeUtil.createExpressionFromText( - condition.getProject(), - negatedText); - } - else if(condition instanceof JSParenthesizedExpression) - { - return getNegated(((JSParenthesizedExpression) condition).getInnerExpression()); - } - return condition; - } - - public static boolean isBooleanLiteral(JSExpression condition) - { - if(!(condition instanceof JSLiteralExpression)) - { - return false; - } - - final String text = condition.getText(); - - return (TRUE.equals(text) || FALSE.equals(text)); - } - - public static Boolean getBooleanLiteral(JSExpression condition) - { - if(!(condition instanceof JSLiteralExpression)) - { - return null; - } - - final String text = condition.getText(); - - return (TRUE.equals(text) ? Boolean.TRUE : - FALSE.equals(text) ? Boolean.FALSE - : null); - } - - public static boolean isTrue(@Nullable JSExpression condition) - { - return (condition instanceof JSLiteralExpression && - TRUE.equals(condition.getText())); - } - - public static boolean isFalse(@Nullable JSExpression condition) - { - return (condition instanceof JSLiteralExpression && - FALSE.equals(condition.getText())); - } - - public static String getNegatedExpressionText(JSExpression condition) - { - if(BoolUtils.isNegation(condition)) - { - return ParenthesesUtils.getParenthesized(BoolUtils.getNegated(condition), ParenthesesUtils.OR_PRECENDENCE); - } - else if(ComparisonUtils.isComparisonOperator(condition)) - { - final JSBinaryExpression binaryExpression = (JSBinaryExpression) condition; - final IElementType sign = binaryExpression.getOperationSign(); - final String negatedComparison = ComparisonUtils.getNegatedOperatorText(sign); - final JSExpression leftOperand = binaryExpression.getLOperand(); - final JSExpression rightOperand = binaryExpression.getROperand(); - - return leftOperand.getText() + negatedComparison + (rightOperand != null ? rightOperand.getText() : ""); - } - else - { - return '!' + ParenthesesUtils.getParenthesized(condition, ParenthesesUtils.PREFIX_PRECENDENCE); - } - } +public class BoolUtils { + @NonNls + public static final String TRUE = "true"; + @NonNls + public static final String FALSE = "false"; + + private BoolUtils() { + } + + public static boolean isNegated(JSExpression condition) { + return (findNegation(condition) != null); + } + + @Nullable + public static JSExpression findNegation(JSExpression condition) { + JSExpression ancestor = condition; + + while (ancestor.getParent() instanceof JSParenthesizedExpression) { + ancestor = (JSExpression)ancestor.getParent(); + } + + if (ancestor.getParent() instanceof JSPrefixExpression) { + JSPrefixExpression prefixAncestor = (JSPrefixExpression)ancestor.getParent(); + if (JSTokenTypes.EXCL.equals(prefixAncestor.getOperationSign())) { + return prefixAncestor; + } + } + + return null; + } + + public static boolean isNegation(JSExpression condition) { + return isNegation(condition, false); + } + + public static boolean isNegation(JSExpression condition, boolean ignoreNegatedNullComparison) { + if (condition instanceof JSPrefixExpression prefixExpression) { + IElementType sign = prefixExpression.getOperationSign(); + + return JSTokenTypes.EXCL.equals(sign); + } + else if (condition instanceof JSBinaryExpression binaryExpression) { + IElementType sign = binaryExpression.getOperationSign(); + JSExpression lhs = binaryExpression.getLOperand(); + JSExpression rhs = binaryExpression.getROperand(); + + if (rhs != null && JSTokenTypes.NE.equals(sign)) { + if (!ignoreNegatedNullComparison) { + return true; + } + + return !isNullLiteral(lhs) && !isNullLiteral(rhs); + } + else { + return false; + } + } + else if (condition instanceof JSParenthesizedExpression parenExp) { + return isNegation(parenExp.getInnerExpression()); + } + else { + return false; + } + } + + private static boolean isNullLiteral(JSExpression lhs) { + return lhs.getNode() != null && JSTokenTypes.NULL_KEYWORD.equals(lhs.getNode().getElementType()); + } + + public static JSExpression getNegated(JSExpression condition) { + if (condition instanceof JSPrefixExpression prefixExp) { + JSExpression operand = prefixExp.getExpression(); + + return ParenthesesUtils.stripParentheses(operand); + } + else if (condition instanceof JSBinaryExpression binaryExpression) { + IElementType sign = binaryExpression.getOperationSign(); + JSExpression lhs = binaryExpression.getLOperand(); + JSExpression rhs = binaryExpression.getROperand(); + String negatedSign = ComparisonUtils.getNegatedOperatorText(sign); + String negatedText = lhs.getText() + negatedSign + rhs.getText(); + + return JSChangeUtil.createExpressionFromText(condition.getProject(), negatedText); + } + else if (condition instanceof JSParenthesizedExpression parenExp) { + return getNegated(parenExp.getInnerExpression()); + } + return condition; + } + + public static boolean isBooleanLiteral(JSExpression condition) { + if (!(condition instanceof JSLiteralExpression)) { + return false; + } + + String text = condition.getText(); + + return (TRUE.equals(text) || FALSE.equals(text)); + } + + public static Boolean getBooleanLiteral(JSExpression condition) { + if (!(condition instanceof JSLiteralExpression)) { + return null; + } + + String text = condition.getText(); + + return TRUE.equals(text) ? Boolean.TRUE + : FALSE.equals(text) ? Boolean.FALSE + : null; + } + + public static boolean isTrue(@Nullable JSExpression condition) { + return condition instanceof JSLiteralExpression && TRUE.equals(condition.getText()); + } + + public static boolean isFalse(@Nullable JSExpression condition) { + return condition instanceof JSLiteralExpression && FALSE.equals(condition.getText()); + } + + public static String getNegatedExpressionText(JSExpression condition) { + if (BoolUtils.isNegation(condition)) { + return ParenthesesUtils.getParenthesized(BoolUtils.getNegated(condition), ParenthesesUtils.OR_PRECENDENCE); + } + else if (ComparisonUtils.isComparisonOperator(condition)) { + JSBinaryExpression binaryExpression = (JSBinaryExpression)condition; + IElementType sign = binaryExpression.getOperationSign(); + String negatedComparison = ComparisonUtils.getNegatedOperatorText(sign); + JSExpression leftOperand = binaryExpression.getLOperand(); + JSExpression rightOperand = binaryExpression.getROperand(); + + return leftOperand.getText() + negatedComparison + (rightOperand != null ? rightOperand.getText() : ""); + } + else { + return '!' + ParenthesesUtils.getParenthesized(condition, ParenthesesUtils.PREFIX_PRECENDENCE); + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ComparisonUtils.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ComparisonUtils.java index 93e92d35..842d99e4 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ComparisonUtils.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ComparisonUtils.java @@ -23,90 +23,74 @@ import java.util.HashMap; import java.util.Map; -public class ComparisonUtils -{ - - private static final Map operators; - - private ComparisonUtils() - { - } - - public static boolean isComparisonOperator(JSExpression expression) - { - return (expression instanceof JSBinaryExpression && - operators.containsKey(((JSBinaryExpression) expression).getOperationSign())); - } - - public static String getOperatorText(IElementType operator) - { - return operators.get(operator).getText(); - } - - public static boolean isEqualityTestExpression(JSBinaryExpression expression) - { - IElementType operator = expression.getOperationSign(); - return (operator.equals(JSTokenTypes.EQEQ) || operator.equals(JSTokenTypes.NE)); - } - - public static boolean mayBeEqualExpression(JSBinaryExpression expression) - { - IElementType operator = expression.getOperationSign(); - return (operator.equals(JSTokenTypes.EQEQ) || operator.equals(JSTokenTypes.EQEQEQ) || - operator.equals(JSTokenTypes.LE) || operator.equals(JSTokenTypes.GE)); - } - - public static String getNegatedOperatorText(IElementType operator) - { - return operators.get(operator).getNegatedText(); - } - - public static String getFlippedOperatorText(IElementType operator) - { - return operators.get(operator).getFlippedText(); - } - - static - { - operators = new HashMap(8); - - operators.put(JSTokenTypes.EQEQ, new OperatorTexts("==", "!=", "==")); - operators.put(JSTokenTypes.EQEQEQ, new OperatorTexts("===", "!==", "===")); - operators.put(JSTokenTypes.NE, new OperatorTexts("!=", "==", "!=")); - operators.put(JSTokenTypes.NEQEQ, new OperatorTexts("!==", "===", "!==")); - operators.put(JSTokenTypes.GT, new OperatorTexts(">", "<=", "<")); - operators.put(JSTokenTypes.LT, new OperatorTexts("<", ">=", ">")); - operators.put(JSTokenTypes.GE, new OperatorTexts(">=", "<", "<=")); - operators.put(JSTokenTypes.LE, new OperatorTexts("<=", ">", ">=")); - } - - private static class OperatorTexts - { - private String text; - private String negatedText; - private String flippedText; - - public OperatorTexts(String text, String negatedText, String flippedText) - { - this.text = text; - this.negatedText = negatedText; - this.flippedText = flippedText; - } - - public String getText() - { - return this.text; - } - - public String getNegatedText() - { - return this.negatedText; - } - - public String getFlippedText() - { - return this.flippedText; - } - } +public class ComparisonUtils { + private static final Map operators; + + private ComparisonUtils() { + } + + public static boolean isComparisonOperator(JSExpression expression) { + return expression instanceof JSBinaryExpression binaryExpression + && operators.containsKey(binaryExpression.getOperationSign()); + } + + public static String getOperatorText(IElementType operator) { + return operators.get(operator).getText(); + } + + public static boolean isEqualityTestExpression(JSBinaryExpression expression) { + IElementType operator = expression.getOperationSign(); + return JSTokenTypes.EQEQ.equals(operator) || JSTokenTypes.NE.equals(operator); + } + + public static boolean mayBeEqualExpression(JSBinaryExpression expression) { + IElementType operator = expression.getOperationSign(); + return JSTokenTypes.EQEQ.equals(operator) || JSTokenTypes.EQEQEQ.equals(operator) + || JSTokenTypes.LE.equals(operator) || JSTokenTypes.GE.equals(operator); + } + + public static String getNegatedOperatorText(IElementType operator) { + return operators.get(operator).getNegatedText(); + } + + public static String getFlippedOperatorText(IElementType operator) { + return operators.get(operator).getFlippedText(); + } + + static { + operators = new HashMap(8); + + operators.put(JSTokenTypes.EQEQ, new OperatorTexts("==", "!=", "==")); + operators.put(JSTokenTypes.EQEQEQ, new OperatorTexts("===", "!==", "===")); + operators.put(JSTokenTypes.NE, new OperatorTexts("!=", "==", "!=")); + operators.put(JSTokenTypes.NEQEQ, new OperatorTexts("!==", "===", "!==")); + operators.put(JSTokenTypes.GT, new OperatorTexts(">", "<=", "<")); + operators.put(JSTokenTypes.LT, new OperatorTexts("<", ">=", ">")); + operators.put(JSTokenTypes.GE, new OperatorTexts(">=", "<", "<=")); + operators.put(JSTokenTypes.LE, new OperatorTexts("<=", ">", ">=")); + } + + private static class OperatorTexts { + private String text; + private String negatedText; + private String flippedText; + + public OperatorTexts(String text, String negatedText, String flippedText) { + this.text = text; + this.negatedText = negatedText; + this.flippedText = flippedText; + } + + public String getText() { + return this.text; + } + + public String getNegatedText() { + return this.negatedText; + } + + public String getFlippedText() { + return this.flippedText; + } + } } - diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ConditionalUtils.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ConditionalUtils.java index c7114316..8e10ef32 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ConditionalUtils.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ConditionalUtils.java @@ -23,363 +23,301 @@ import consulo.language.util.IncorrectOperationException; import org.jetbrains.annotations.NonNls; -public class ConditionalUtils -{ - private ConditionalUtils() - { - } - - public static JSStatement stripBraces(JSStatement branch) - { - if(branch != null && branch instanceof JSBlockStatement) - { - final JSBlockStatement block = (JSBlockStatement) branch; - final JSStatement[] statements = block.getStatements(); - - if(statements.length == 1) - { - return statements[0]; - } - else - { - return block; - } - } - - return branch; - } - - public static boolean isReturn(JSStatement statement, String value) - { - if(statement == null) - { - return false; - } - if(!(statement instanceof JSReturnStatement)) - { - return false; - } - - final JSExpression returnExpression = ((JSReturnStatement) statement).getExpression(); - - return (returnExpression != null && value.equals(returnExpression.getText())); - } - - public static boolean isAssignment(JSStatement statement, String value) - { - if(statement == null || !(statement instanceof JSExpressionStatement)) - { - return false; - } - - final JSExpression expression = ((JSExpressionStatement) statement).getExpression(); - - if(!(expression instanceof JSAssignmentExpression)) - { - return false; - } - - final JSExpression rhs = ((JSAssignmentExpression) expression).getROperand(); - - return (rhs != null && rhs.getText().equals(value)); - } - - public static boolean isAssignment(JSStatement statement) - { - if(!(statement instanceof JSExpressionStatement)) - { - return false; - } - - final JSExpressionStatement expressionStatement = (JSExpressionStatement) statement; - - return (expressionStatement.getExpression() instanceof JSAssignmentExpression); - } - - public static boolean isConditional(JSExpression expression) - { - expression = ParenthesesUtils.stripParentheses(expression); - - if(expression == null) - { - return false; - } - - if(expression instanceof JSConditionalExpression) - { - return true; - } - - if(expression instanceof JSBinaryExpression) - { - final JSBinaryExpression binaryExpression = (JSBinaryExpression) expression; - final IElementType sign = binaryExpression.getOperationSign(); - - if(JSTokenTypes.XOR.equals(sign)) - { - return (isConditional(binaryExpression.getLOperand()) && - isConditional(binaryExpression.getROperand())); - } - - return (JSTokenTypes.ANDAND.equals(sign) || JSTokenTypes.OROR.equals(sign) || - JSTokenTypes.EQ.equals(sign) || JSTokenTypes.NE.equals(sign) || - JSTokenTypes.LT.equals(sign) || JSTokenTypes.LE.equals(sign) || - JSTokenTypes.GT.equals(sign) || JSTokenTypes.GE.equals(sign)); - } - - return BoolUtils.isBooleanLiteral(expression); - } - - public static boolean isSimplifiableImplicitReturn(JSIfStatement ifStatement, boolean negated) - { - final JSStatement thenBranch = ConditionalUtils.stripBraces(ifStatement.getThen()); - final PsiElement nextStatement = JSElementFactory.getNonWhiteSpaceSibling(ifStatement, true); - - if(!(nextStatement instanceof JSStatement)) - { - return false; - } - - final JSStatement elseBranch = (JSStatement) nextStatement; - - if(negated) - { - return (ConditionalUtils.isReturn(thenBranch, BoolUtils.FALSE) && - ConditionalUtils.isReturn(elseBranch, BoolUtils.TRUE)); - } - else - { - return (ConditionalUtils.isReturn(thenBranch, BoolUtils.TRUE) && - ConditionalUtils.isReturn(elseBranch, BoolUtils.FALSE)); - } - } - - public static boolean isSimplifiableReturn(JSIfStatement ifStatement, boolean negated) - { - final JSStatement thenBranch = ConditionalUtils.stripBraces(ifStatement.getThen()); - final JSStatement elseBranch = ConditionalUtils.stripBraces(ifStatement.getElse()); - - if(negated) - { - return (ConditionalUtils.isReturn(thenBranch, BoolUtils.FALSE) && - ConditionalUtils.isReturn(elseBranch, BoolUtils.TRUE)); - } - else - { - return (ConditionalUtils.isReturn(thenBranch, BoolUtils.TRUE) && - ConditionalUtils.isReturn(elseBranch, BoolUtils.FALSE)); - } - } - - public static boolean isSimplifiableAssignment(JSIfStatement ifStatement, boolean negated) - { - final JSStatement thenBranch = ConditionalUtils.stripBraces(ifStatement.getThen()); - final JSStatement elseBranch = ConditionalUtils.stripBraces(ifStatement.getElse()); - - final boolean isAssignment; - - if(negated) - { - isAssignment = (ConditionalUtils.isAssignment(thenBranch, BoolUtils.FALSE) && - ConditionalUtils.isAssignment(elseBranch, BoolUtils.TRUE)); - } - else - { - isAssignment = (ConditionalUtils.isAssignment(thenBranch, BoolUtils.TRUE) && - ConditionalUtils.isAssignment(elseBranch, BoolUtils.FALSE)); - } - - if(isAssignment) - { - final JSAssignmentExpression thenExpression = (JSAssignmentExpression) ((JSExpressionStatement) thenBranch).getExpression(); - final JSAssignmentExpression elseExpression = (JSAssignmentExpression) ((JSExpressionStatement) elseBranch).getExpression(); - final IElementType thenSign = thenExpression.getOperationSign(); - final IElementType elseSign = elseExpression.getOperationSign(); - - if(!thenSign.equals(elseSign)) - { - return false; - } - - final JSExpression thenLhs = thenExpression.getLOperand(); - final JSExpression elseLhs = elseExpression.getLOperand(); - - return EquivalenceChecker.expressionsAreEquivalent(thenLhs, elseLhs); - } - else - { - return false; - } - } - - public static boolean isSimplifiableImplicitAssignment(JSIfStatement ifStatement, boolean negated) - { - if(ifStatement.getElse() != null) - { - return false; - } - final JSStatement thenBranch = ConditionalUtils.stripBraces(ifStatement.getThen()); - final PsiElement nextStatement = JSElementFactory.getNonWhiteSpaceSibling(ifStatement, false); - - if(!(nextStatement instanceof JSStatement)) - { - return false; - } - - final JSStatement elseBranch = ConditionalUtils.stripBraces((JSStatement) nextStatement); - - final boolean isAssignment; - - if(negated) - { - isAssignment = (ConditionalUtils.isAssignment(thenBranch, BoolUtils.FALSE) && - ConditionalUtils.isAssignment(elseBranch, BoolUtils.TRUE)); - } - else - { - isAssignment = (ConditionalUtils.isAssignment(thenBranch, BoolUtils.TRUE) && - ConditionalUtils.isAssignment(elseBranch, BoolUtils.FALSE)); - } - - if(isAssignment) - { - final JSAssignmentExpression thenExpression = (JSAssignmentExpression) ((JSExpressionStatement) thenBranch).getExpression(); - final JSAssignmentExpression elseExpression = (JSAssignmentExpression) ((JSExpressionStatement) elseBranch).getExpression(); - final IElementType thenSign = thenExpression.getOperationSign(); - final IElementType elseSign = elseExpression.getOperationSign(); - - if(!thenSign.equals(elseSign)) - { - return false; - } - - final JSExpression thenLhs = thenExpression.getLOperand(); - final JSExpression elseLhs = elseExpression.getLOperand(); - - return EquivalenceChecker.expressionsAreEquivalent(thenLhs, elseLhs); - } - else - { - return false; - } - } - - public static void replaceSimplifiableImplicitReturn(JSIfStatement statement, boolean negated) - throws IncorrectOperationException - { - final JSExpression condition = statement.getCondition(); - final String conditionText = (negated ? BoolUtils.getNegatedExpressionText(condition) : condition.getText()); - final JSElement nextStatement = (JSElement) JSElementFactory.getNonWhiteSpaceSibling(statement, true); - @NonNls final String newStatement = "return " + conditionText + ';'; - - JSElementFactory.replaceStatement(statement, newStatement); - assert (nextStatement != null); - JSElementFactory.removeElement(nextStatement); - } - - public static void replaceSimplifiableReturn(JSIfStatement statement, boolean negated) - throws IncorrectOperationException - { - final JSExpression condition = statement.getCondition(); - final String conditionText = (negated ? BoolUtils.getNegatedExpressionText(condition) : condition.getText()); - @NonNls final String newStatement = "return " + conditionText + ';'; - - JSElementFactory.replaceStatement(statement, newStatement); - } - - public static void replaceSimplifiableAssignment(JSIfStatement statement, boolean negated) - throws IncorrectOperationException - { - final JSExpression condition = statement.getCondition(); - final String conditionText = (negated ? BoolUtils.getNegatedExpressionText(condition) : condition.getText()); - final JSExpressionStatement assignmentStatement = (JSExpressionStatement) ConditionalUtils.stripBraces(statement.getThen()); - final JSAssignmentExpression assignmentExpression = (JSAssignmentExpression) assignmentStatement.getExpression(); - final IElementType operator = assignmentExpression.getOperationSign(); - final String operand = BinaryOperatorUtils.getOperatorText(operator); - final JSExpression lhs = assignmentExpression.getLOperand(); - final String lhsText = lhs.getText(); - - JSElementFactory.replaceStatement(statement, lhsText + operand + conditionText + ';'); - } - - public static void replaceSimplifiableImplicitAssignment(JSIfStatement statement, boolean negated) - throws IncorrectOperationException - { - final JSElement prevStatement = (JSElement) JSElementFactory.getNonWhiteSpaceSibling(statement, false); - final JSExpression condition = statement.getCondition(); - final String conditionText = (negated ? BoolUtils.getNegatedExpressionText(condition) : condition.getText()); - final JSExpressionStatement assignmentStatement = (JSExpressionStatement) ConditionalUtils.stripBraces(statement.getThen()); - final JSAssignmentExpression assignmentExpression = (JSAssignmentExpression) assignmentStatement.getExpression(); - final IElementType operator = assignmentExpression.getOperationSign(); - final String operand = BinaryOperatorUtils.getOperatorText(operator); - final JSExpression lhs = assignmentExpression.getLOperand(); - final String lhsText = lhs.getText(); - - JSElementFactory.replaceStatement(statement, lhsText + operand + conditionText + ';'); - - assert (prevStatement != null); - - JSElementFactory.removeElement(prevStatement); - } - - public static void replaceAssignmentOrReturnIfSimplifiable(JSIfStatement statement) - throws IncorrectOperationException - { - if(isSimplifiableAssignment(statement, false)) - { - replaceSimplifiableAssignment(statement, false); - } - else if(isSimplifiableAssignment(statement, true)) - { - replaceSimplifiableAssignment(statement, true); - } - else if(isSimplifiableReturn(statement, false)) - { - replaceSimplifiableReturn(statement, false); - } - else if(isSimplifiableReturn(statement, true)) - { - replaceSimplifiableReturn(statement, true); - } - else if(isSimplifiableImplicitReturn(statement, false)) - { - replaceSimplifiableImplicitReturn(statement, false); - } - else if(isSimplifiableImplicitReturn(statement, true)) - { - replaceSimplifiableImplicitReturn(statement, true); - } - else if(isSimplifiableImplicitAssignment(statement, false)) - { - replaceSimplifiableImplicitAssignment(statement, false); - } - else if(isSimplifiableImplicitAssignment(statement, true)) - { - replaceSimplifiableImplicitAssignment(statement, true); - } - } - - public static void replaceConditionalWithIf(JSConditionalExpression conditional) - throws IncorrectOperationException - { - final JSStatement statement = PsiTreeUtil.getParentOfType(conditional, JSStatement.class); - - assert (statement != null); - - final String statementText = statement.getText(); - final String conditionalText = ParenthesesUtils.unstripParentheses(conditional).getText(); - final int conditionalIndex = statementText.indexOf(conditionalText); - final String statementStart = statementText.substring(0, conditionalIndex); - final String statementEnd = statementText.substring(conditionalIndex + conditionalText.length()); - final JSExpression condition = ParenthesesUtils.stripParentheses(conditional.getCondition()); - final JSExpression thenExpression = ParenthesesUtils.stripParentheses(conditional.getThen()); - final JSExpression elseExpression = ParenthesesUtils.stripParentheses(conditional.getElse()); - - @NonNls final String ifStatementText = "if (" + condition.getText() + ") {" + - statementStart + thenExpression.getText() + statementEnd + - "} else {" + - statementStart + elseExpression.getText() + statementEnd + - '}'; - JSElementFactory.replaceStatement(statement, ifStatementText); - } +public class ConditionalUtils { + private ConditionalUtils() { + } + + public static JSStatement stripBraces(JSStatement branch) { + if (branch != null && branch instanceof JSBlockStatement block) { + JSStatement[] statements = block.getStatements(); + + if (statements.length == 1) { + return statements[0]; + } + else { + return block; + } + } + + return branch; + } + + public static boolean isReturn(JSStatement statement, String value) { + if (statement == null) { + return false; + } + if (!(statement instanceof JSReturnStatement)) { + return false; + } + + JSExpression returnExpression = ((JSReturnStatement)statement).getExpression(); + + return (returnExpression != null && value.equals(returnExpression.getText())); + } + + public static boolean isAssignment(JSStatement statement, String value) { + if (statement == null || !(statement instanceof JSExpressionStatement)) { + return false; + } + + JSExpression expression = ((JSExpressionStatement)statement).getExpression(); + + if (!(expression instanceof JSAssignmentExpression)) { + return false; + } + + JSExpression rhs = ((JSAssignmentExpression)expression).getROperand(); + + return (rhs != null && rhs.getText().equals(value)); + } + + public static boolean isAssignment(JSStatement statement) { + if (!(statement instanceof JSExpressionStatement)) { + return false; + } + + JSExpressionStatement expressionStatement = (JSExpressionStatement)statement; + + return (expressionStatement.getExpression() instanceof JSAssignmentExpression); + } + + public static boolean isConditional(JSExpression expression) { + expression = ParenthesesUtils.stripParentheses(expression); + + if (expression == null) { + return false; + } + + if (expression instanceof JSConditionalExpression) { + return true; + } + + if (expression instanceof JSBinaryExpression) { + JSBinaryExpression binaryExpression = (JSBinaryExpression)expression; + IElementType sign = binaryExpression.getOperationSign(); + + if (JSTokenTypes.XOR.equals(sign)) { + return (isConditional(binaryExpression.getLOperand()) && + isConditional(binaryExpression.getROperand())); + } + + return (JSTokenTypes.ANDAND.equals(sign) || JSTokenTypes.OROR.equals(sign) || + JSTokenTypes.EQ.equals(sign) || JSTokenTypes.NE.equals(sign) || + JSTokenTypes.LT.equals(sign) || JSTokenTypes.LE.equals(sign) || + JSTokenTypes.GT.equals(sign) || JSTokenTypes.GE.equals(sign)); + } + + return BoolUtils.isBooleanLiteral(expression); + } + + public static boolean isSimplifiableImplicitReturn(JSIfStatement ifStatement, boolean negated) { + JSStatement thenBranch = ConditionalUtils.stripBraces(ifStatement.getThen()); + PsiElement nextStatement = JSElementFactory.getNonWhiteSpaceSibling(ifStatement, true); + + if (!(nextStatement instanceof JSStatement)) { + return false; + } + + JSStatement elseBranch = (JSStatement)nextStatement; + + if (negated) { + return ConditionalUtils.isReturn(thenBranch, BoolUtils.FALSE) + && ConditionalUtils.isReturn(elseBranch, BoolUtils.TRUE); + } + else { + return ConditionalUtils.isReturn(thenBranch, BoolUtils.TRUE) + && ConditionalUtils.isReturn(elseBranch, BoolUtils.FALSE); + } + } + + public static boolean isSimplifiableReturn(JSIfStatement ifStatement, boolean negated) { + JSStatement thenBranch = ConditionalUtils.stripBraces(ifStatement.getThen()); + JSStatement elseBranch = ConditionalUtils.stripBraces(ifStatement.getElse()); + + if (negated) { + return ConditionalUtils.isReturn(thenBranch, BoolUtils.FALSE) + && ConditionalUtils.isReturn(elseBranch, BoolUtils.TRUE); + } + else { + return ConditionalUtils.isReturn(thenBranch, BoolUtils.TRUE) + && ConditionalUtils.isReturn(elseBranch, BoolUtils.FALSE); + } + } + + public static boolean isSimplifiableAssignment(JSIfStatement ifStatement, boolean negated) { + JSStatement thenBranch = ConditionalUtils.stripBraces(ifStatement.getThen()); + JSStatement elseBranch = ConditionalUtils.stripBraces(ifStatement.getElse()); + + boolean isAssignment; + + if (negated) { + isAssignment = ConditionalUtils.isAssignment(thenBranch, BoolUtils.FALSE) + && ConditionalUtils.isAssignment(elseBranch, BoolUtils.TRUE); + } + else { + isAssignment = ConditionalUtils.isAssignment(thenBranch, BoolUtils.TRUE) + && ConditionalUtils.isAssignment(elseBranch, BoolUtils.FALSE); + } + + if (isAssignment) { + JSAssignmentExpression thenExpression = (JSAssignmentExpression)((JSExpressionStatement)thenBranch).getExpression(); + JSAssignmentExpression elseExpression = (JSAssignmentExpression)((JSExpressionStatement)elseBranch).getExpression(); + IElementType thenSign = thenExpression.getOperationSign(); + IElementType elseSign = elseExpression.getOperationSign(); + + if (!thenSign.equals(elseSign)) { + return false; + } + + JSExpression thenLhs = thenExpression.getLOperand(); + JSExpression elseLhs = elseExpression.getLOperand(); + + return EquivalenceChecker.expressionsAreEquivalent(thenLhs, elseLhs); + } + else { + return false; + } + } + + public static boolean isSimplifiableImplicitAssignment(JSIfStatement ifStatement, boolean negated) { + if (ifStatement.getElse() != null) { + return false; + } + JSStatement thenBranch = ConditionalUtils.stripBraces(ifStatement.getThen()); + PsiElement nextStatement = JSElementFactory.getNonWhiteSpaceSibling(ifStatement, false); + + if (!(nextStatement instanceof JSStatement)) { + return false; + } + + JSStatement elseBranch = ConditionalUtils.stripBraces((JSStatement)nextStatement); + + boolean isAssignment = negated + ? ConditionalUtils.isAssignment(thenBranch, BoolUtils.FALSE) && ConditionalUtils.isAssignment(elseBranch, BoolUtils.TRUE) + : ConditionalUtils.isAssignment(thenBranch, BoolUtils.TRUE) && ConditionalUtils.isAssignment(elseBranch, BoolUtils.FALSE); + + if (isAssignment) { + JSAssignmentExpression thenExpression = (JSAssignmentExpression)((JSExpressionStatement)thenBranch).getExpression(); + JSAssignmentExpression elseExpression = (JSAssignmentExpression)((JSExpressionStatement)elseBranch).getExpression(); + IElementType thenSign = thenExpression.getOperationSign(); + IElementType elseSign = elseExpression.getOperationSign(); + + if (!thenSign.equals(elseSign)) { + return false; + } + + JSExpression thenLhs = thenExpression.getLOperand(); + JSExpression elseLhs = elseExpression.getLOperand(); + + return EquivalenceChecker.expressionsAreEquivalent(thenLhs, elseLhs); + } + else { + return false; + } + } + + public static void replaceSimplifiableImplicitReturn(JSIfStatement statement, boolean negated) + throws IncorrectOperationException { + JSExpression condition = statement.getCondition(); + String conditionText = negated ? BoolUtils.getNegatedExpressionText(condition) : condition.getText(); + JSElement nextStatement = (JSElement)JSElementFactory.getNonWhiteSpaceSibling(statement, true); + @NonNls String newStatement = "return " + conditionText + ';'; + + JSElementFactory.replaceStatement(statement, newStatement); + assert (nextStatement != null); + JSElementFactory.removeElement(nextStatement); + } + + public static void replaceSimplifiableReturn(JSIfStatement statement, boolean negated) + throws IncorrectOperationException { + JSExpression condition = statement.getCondition(); + String conditionText = (negated ? BoolUtils.getNegatedExpressionText(condition) : condition.getText()); + @NonNls String newStatement = "return " + conditionText + ';'; + + JSElementFactory.replaceStatement(statement, newStatement); + } + + public static void replaceSimplifiableAssignment(JSIfStatement statement, boolean negated) + throws IncorrectOperationException { + JSExpression condition = statement.getCondition(); + String conditionText = negated ? BoolUtils.getNegatedExpressionText(condition) : condition.getText(); + JSExpressionStatement assignmentStatement = (JSExpressionStatement)ConditionalUtils.stripBraces(statement.getThen()); + JSAssignmentExpression assignmentExpression = (JSAssignmentExpression)assignmentStatement.getExpression(); + IElementType operator = assignmentExpression.getOperationSign(); + String operand = BinaryOperatorUtils.getOperatorText(operator); + JSExpression lhs = assignmentExpression.getLOperand(); + String lhsText = lhs.getText(); + + JSElementFactory.replaceStatement(statement, lhsText + operand + conditionText + ';'); + } + + public static void replaceSimplifiableImplicitAssignment(JSIfStatement statement, boolean negated) + throws IncorrectOperationException { + JSElement prevStatement = (JSElement)JSElementFactory.getNonWhiteSpaceSibling(statement, false); + JSExpression condition = statement.getCondition(); + String conditionText = (negated ? BoolUtils.getNegatedExpressionText(condition) : condition.getText()); + JSExpressionStatement assignmentStatement = (JSExpressionStatement)ConditionalUtils.stripBraces(statement.getThen()); + JSAssignmentExpression assignmentExpression = (JSAssignmentExpression)assignmentStatement.getExpression(); + IElementType operator = assignmentExpression.getOperationSign(); + String operand = BinaryOperatorUtils.getOperatorText(operator); + JSExpression lhs = assignmentExpression.getLOperand(); + String lhsText = lhs.getText(); + + JSElementFactory.replaceStatement(statement, lhsText + operand + conditionText + ';'); + + assert (prevStatement != null); + + JSElementFactory.removeElement(prevStatement); + } + + public static void replaceAssignmentOrReturnIfSimplifiable(JSIfStatement statement) + throws IncorrectOperationException { + if (isSimplifiableAssignment(statement, false)) { + replaceSimplifiableAssignment(statement, false); + } + else if (isSimplifiableAssignment(statement, true)) { + replaceSimplifiableAssignment(statement, true); + } + else if (isSimplifiableReturn(statement, false)) { + replaceSimplifiableReturn(statement, false); + } + else if (isSimplifiableReturn(statement, true)) { + replaceSimplifiableReturn(statement, true); + } + else if (isSimplifiableImplicitReturn(statement, false)) { + replaceSimplifiableImplicitReturn(statement, false); + } + else if (isSimplifiableImplicitReturn(statement, true)) { + replaceSimplifiableImplicitReturn(statement, true); + } + else if (isSimplifiableImplicitAssignment(statement, false)) { + replaceSimplifiableImplicitAssignment(statement, false); + } + else if (isSimplifiableImplicitAssignment(statement, true)) { + replaceSimplifiableImplicitAssignment(statement, true); + } + } + + public static void replaceConditionalWithIf(JSConditionalExpression conditional) + throws IncorrectOperationException { + JSStatement statement = PsiTreeUtil.getParentOfType(conditional, JSStatement.class); + + assert (statement != null); + + String statementText = statement.getText(); + String conditionalText = ParenthesesUtils.unstripParentheses(conditional).getText(); + int conditionalIndex = statementText.indexOf(conditionalText); + String statementStart = statementText.substring(0, conditionalIndex); + String statementEnd = statementText.substring(conditionalIndex + conditionalText.length()); + JSExpression condition = ParenthesesUtils.stripParentheses(conditional.getCondition()); + JSExpression thenExpression = ParenthesesUtils.stripParentheses(conditional.getThen()); + JSExpression elseExpression = ParenthesesUtils.stripParentheses(conditional.getElse()); + + @NonNls String ifStatementText = "if (" + condition.getText() + ") {" + + statementStart + thenExpression.getText() + statementEnd + + "} else {" + + statementStart + elseExpression.getText() + statementEnd + + '}'; + JSElementFactory.replaceStatement(statement, ifStatementText); + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ControlFlowUtils.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ControlFlowUtils.java index d1c34480..ee57b6f7 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ControlFlowUtils.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ControlFlowUtils.java @@ -20,758 +20,588 @@ import consulo.language.psi.PsiReference; import consulo.language.psi.util.PsiTreeUtil; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; + import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; -public class ControlFlowUtils -{ - private ControlFlowUtils() - { - } - - public static boolean statementMayCompleteNormally(@Nullable JSStatement statement) - { - if(statement == null || - statement instanceof JSBreakStatement || - statement instanceof JSContinueStatement || - statement instanceof JSReturnStatement || - statement instanceof JSThrowStatement || - statement instanceof JSWithStatement) - { - return false; - } - else if(statement instanceof JSExpressionStatement || - statement instanceof JSEmptyStatement || - statement instanceof JSVarStatement) - { - return true; - } - else if(statement instanceof JSForStatement) - { - final JSForStatement loopStatement = (JSForStatement) statement; - final JSExpression condition = loopStatement.getCondition(); - - return (condition != null && !isBooleanConstant(condition, false) || - statementIsBreakTarget(loopStatement)); - } - else if(statement instanceof JSForInStatement) - { - return (statementIsBreakTarget(statement)); - } - else if(statement instanceof JSWhileStatement) - { - final JSWhileStatement loopStatement = (JSWhileStatement) statement; - - return (!isBooleanConstant(loopStatement.getCondition(), true) || - statementIsBreakTarget(loopStatement)); - } - else if(statement instanceof JSDoWhileStatement) - { - final JSDoWhileStatement loopStatement = (JSDoWhileStatement) statement; - - return (statementMayCompleteNormally(loopStatement.getBody()) && - (!isBooleanConstant(loopStatement.getCondition(), true) || - statementIsBreakTarget(loopStatement))); - } - else if(statement instanceof JSBlockStatement) - { - return codeBlockMayCompleteNormally(((JSBlockStatement) statement).getStatements()); - } - else if(statement instanceof JSLabeledStatement) - { - final JSLabeledStatement labeledStatement = (JSLabeledStatement) statement; - final JSStatement body = labeledStatement.getStatement(); - - return (statementMayCompleteNormally(body) || statementIsBreakTarget(body)); - } - else if(statement instanceof JSIfStatement) - { - final JSIfStatement ifStatement = (JSIfStatement) statement; - final JSStatement thenBranch = ifStatement.getThen(); - final JSStatement elseBranch = ifStatement.getElse(); - - return (elseBranch == null || - statementMayCompleteNormally(thenBranch) || - statementMayCompleteNormally(elseBranch)); - } - else if(statement instanceof JSTryStatement) - { - final JSTryStatement tryStatement = (JSTryStatement) statement; - - if(!statementMayCompleteNormally(tryStatement.getFinallyStatement())) - { - return false; - } - if(statementMayCompleteNormally(tryStatement.getStatement())) - { - return true; - } - - final JSCatchBlock catchBlock = tryStatement.getCatchBlock(); - - return (catchBlock != null && statementMayCompleteNormally(catchBlock.getStatement())); - } - else if(statement instanceof JSSwitchStatement) - { - final JSSwitchStatement switchStatement = (JSSwitchStatement) statement; - - if(statementIsBreakTarget(switchStatement)) - { - return true; - } - - for(JSCaseClause caseClause : switchStatement.getCaseClauses()) - { - if(!codeBlockMayCompleteNormally(caseClause.getStatements())) - { - return false; - } - } - return true; - } - else - { - return false; - } - } - - public static boolean codeBlockMayCompleteNormally(@Nullable JSStatement[] statements) - { - if(statements != null) - { - for(final JSStatement statement : statements) - { - if(!statementMayCompleteNormally(statement)) - { - return false; - } - } - } - return true; - } - - @SuppressWarnings({"UnnecessaryUnboxing"}) - private static boolean isBooleanConstant(JSExpression test, boolean val) - { - if(!ExpressionUtil.isConstantExpression(test)) - { - return false; - } - final Object value = ExpressionUtil.computeConstantExpression(test); - return (value != null && - value instanceof Boolean && - ((Boolean) value).booleanValue() == val); - } - - private static boolean statementIsBreakTarget(@Nullable JSStatement statement) - { - if(statement == null) - { - return false; - } - - final BreakTargetFinder breakFinder = new BreakTargetFinder(statement); - - statement.accept(breakFinder); - return breakFinder.breakFound(); - } - - public static boolean statementContainsExitingBreak(@Nullable JSStatement statement) - { - if(statement == null) - { - return false; - } - - final ExitingBreakFinder breakFinder = new ExitingBreakFinder(); - - statement.accept(breakFinder); - return breakFinder.breakFound(); - } - - public static boolean statementIsContinueTarget(@Nullable JSStatement statement) - { - if(statement == null) - { - return false; - } - - final ContinueTargetFinder continueFinder = new ContinueTargetFinder(statement); - - statement.accept(continueFinder); - return continueFinder.continueFound(); - } - - public static boolean statementContainsReturn(@Nullable JSStatement statement) - { - if(statement == null) - { - return false; - } - - final ReturnFinder returnFinder = new ReturnFinder(); - - statement.accept(returnFinder); - return returnFinder.returnFound(); - } - - public static boolean statementCompletesWithStatement( - @Nonnull JSStatement containingStatement, - @Nonnull JSStatement statement) - { - JSElement statementToCheck = statement; - - while(true) - { - if(statementToCheck.equals(containingStatement)) - { - return true; - } - - final JSStatement container = PsiTreeUtil.getParentOfType(statementToCheck, JSStatement.class); - - if(container == null) - { - return false; - } - if(container instanceof JSBlockStatement) - { - if(!statementIsLastInBlock((JSBlockStatement) container, - (JSStatement) statementToCheck)) - { - return false; - } - } - if(container instanceof JSLoopStatement) - { - return false; - } - statementToCheck = container; - } - } - - private static boolean elementCompletesWithStatement( - @Nonnull JSElement element, - @Nonnull JSStatement statement) - { - PsiElement statementToCheck = statement; - - while(true) - { - if(statementToCheck == null) - { - return false; - } - if(statementToCheck.equals(element)) - { - return true; - } - - final JSElement container = PsiTreeUtil.getParentOfType(statementToCheck, JSElement.class); - - if(container == null || container instanceof JSLoopStatement) - { - return false; - } - - if(container instanceof JSBlockStatement) - { - if(!statementIsLastInBlock((JSBlockStatement) container, - (JSStatement) statementToCheck)) - { - return false; - } - if(container.equals(element)) - { - return true; - } - statementToCheck = PsiTreeUtil.getParentOfType(container, JSStatement.class, JSFunction.class); - } - else - { - statementToCheck = container; - } - } - } - - public static boolean functionCompletesWithStatement( - @Nonnull JSFunction function, - @Nonnull JSStatement statement) - { - return elementCompletesWithStatement(function, statement); - } - - public static boolean blockCompletesWithStatement( - @Nonnull JSBlockStatement block, - @Nonnull JSStatement statement) - { - return elementCompletesWithStatement(block, statement); - } - - private static boolean statementIsLastInBlock( - @Nonnull JSBlockStatement block, @Nonnull JSStatement statement) - { - final JSStatement[] statements = block.getStatements(); - - //noinspection ForLoopWithMissingComponent - for(int index = statements.length; --index >= 0; ) - { - final JSStatement childStatement = statements[index]; - - if(statement.equals(childStatement)) - { - return true; - } - if(!(statement instanceof JSEmptyStatement)) - { - return false; - } - } - return false; - } - - @Nullable - public static JSVariable resolveVariable(@Nullable JSExpression expression) - { - if(expression == null) - { - return null; - } - else if(expression instanceof JSReferenceExpression) - { - final PsiElement variable = ((JSReferenceExpression) expression).resolve(); - - return ((variable != null && variable instanceof JSVariable) ? (JSVariable) variable : null); - } - else if(expression instanceof JSDefinitionExpression) - { - final JSExpression referentExpression = ((JSDefinitionExpression) expression).getExpression(); - final PsiReference reference = (referentExpression == null) ? null : referentExpression.getReference(); - final PsiElement variable = (reference == null) ? null : reference.resolve(); - - return ((variable != null && variable instanceof JSVariable) ? (JSVariable) variable : null); - } - else - { - return null; - } - } - - @Nullable - public static JSFunction resolveMethod(JSCallExpression expression) - { - final JSExpression methodExpression = (expression == null) ? null : expression.getMethodExpression(); - - if(methodExpression != null && methodExpression instanceof JSReferenceExpression) - { - final PsiElement referent = ((JSReferenceExpression) methodExpression).resolve(); - - return ((referent != null && referent instanceof JSFunction) ? (JSFunction) referent : null); - } - return null; - } - - public static boolean canBeMerged(JSStatement statement1, - JSStatement statement2) - { - if(!ControlFlowUtils.statementMayCompleteNormally(statement1)) - { - return false; - } - final Set statement1Declarations = calculateTopLevelDeclarations(statement1); - if(containsConflictingDeclarations(statement1Declarations, statement2)) - { - return false; - } - final Set statement2Declarations = calculateTopLevelDeclarations(statement2); - return (!containsConflictingDeclarations(statement2Declarations, statement1)); - } - - public static boolean isInLoopStatementBody(@Nonnull PsiElement element) - { - final JSLoopStatement forStatement = PsiTreeUtil.getParentOfType(element, JSLoopStatement.class); - - if(forStatement == null) - { - return false; - } - - final JSStatement body = forStatement.getBody(); - - return (body != null && PsiTreeUtil.isAncestor(body, element, true)); - } - - @Nonnull - public static List getRecursiveCalls(@Nonnull JSFunction function) - { - final RecursiveCallVisitor recursiveCallVisitor = new RecursiveCallVisitor(function); - - function.accept(recursiveCallVisitor); - return recursiveCallVisitor.getCalls(); - } - - private static boolean containsConflictingDeclarations(Set declarations, - JSStatement statement) - { - final DeclarationUtils.DeclarationConflictVisitor visitor = - new DeclarationUtils.DeclarationConflictVisitor(declarations); - statement.accept(visitor); - return visitor.hasConflict(); - } - - public static boolean containsConflictingDeclarations( - JSBlockStatement block, JSBlockStatement parentBlock) - { - final JSStatement[] statements = block.getStatements(); - final Set declaredVars = new HashSet(); - - for(final JSStatement statement : statements) - { - if(statement instanceof JSVarStatement) - { - final JSVarStatement declaration = (JSVarStatement) statement; - - for(final JSVariable var : declaration.getVariables()) - { - declaredVars.add(var); - } - } - } - - for(final JSVariable variable : declaredVars) - { - if(conflictingDeclarationExists(variable.getName(), parentBlock, block)) - { - return true; - } - } - - return false; - } - - private static boolean conflictingDeclarationExists( - String name, - JSBlockStatement parentBlock, - JSBlockStatement exceptBlock) - { - final ConflictingDeclarationVisitor visitor = new ConflictingDeclarationVisitor(name, exceptBlock); - parentBlock.accept(visitor); - return visitor.hasConflictingDeclaration(); - } - - private static Set calculateTopLevelDeclarations(JSStatement statement) - { - final Set out = new HashSet(); - - if(statement instanceof JSVarStatement) - { - addDeclarations((JSVarStatement) statement, out); - } - else if(statement instanceof JSBlockStatement) - { - for(JSStatement subStatement : ((JSBlockStatement) statement).getStatements()) - { - if(subStatement instanceof JSVarStatement) - { - addDeclarations((JSVarStatement) subStatement, out); - } - } - } - return out; - } - - private static void addDeclarations(JSVarStatement statement, - Set declaredVars) - { - for(final JSVariable variable : statement.getVariables()) - { - declaredVars.add(variable.getName()); - } - } - - public static void appendStatementsInSequence(StringBuilder buffer, - JSStatement statement1, - JSStatement statement2) - { - if(statement1 == null) - { - buffer.append(' ') - .append(statement2.getText()); - } - else if(statement2 == null) - { - buffer.append(' ') - .append(statement1.getText()); - } - else - { - buffer.append('{'); - appendStatementStripped(buffer, statement1); - appendStatementStripped(buffer, statement2); - buffer.append('}'); - } - } - - private static void appendStatementStripped(StringBuilder buffer, JSStatement statement) - { - if(statement instanceof JSBlockStatement) - { - for(PsiElement child : statement.getChildren()) - { - buffer.append(child.getText()); - } - } - else - { - buffer.append(statement.getText()); - } - } - - private static class BreakTargetFinder extends JSRecursiveElementVisitor - { - private boolean found; - private final JSStatement target; - - private BreakTargetFinder(JSStatement target) - { - this.target = target; - } - - private boolean breakFound() - { - return this.found; - } - - @Override - public void visitJSReferenceExpression(JSReferenceExpression JSReferenceExpression) - { - } - - @Override - public void visitJSBreakStatement(JSBreakStatement breakStatement) - { - super.visitJSBreakStatement(breakStatement); - final JSStatement exitedStatement = breakStatement.getStatementToBreak(); - if(exitedStatement == null) - { - return; - } - this.found = (exitedStatement.equals(this.target)); - } - } - - private static class ContinueTargetFinder extends JSRecursiveElementVisitor - { - private boolean found; - private final JSStatement target; - - private ContinueTargetFinder(JSStatement target) - { - this.target = target; - } - - private boolean continueFound() - { - return this.found; - } - - @Override - public void visitJSReferenceExpression(JSReferenceExpression JSReferenceExpression) - { - } - - @Override - public void visitJSContinueStatement(JSContinueStatement continueStatement) - { - super.visitJSContinueStatement(continueStatement); - final JSStatement statement = continueStatement.getStatementToContinue(); - if(statement == null) - { - return; - } - this.found = (statement.equals(this.target)); - } - } - - private static class ExitingBreakFinder extends JSRecursiveElementVisitor - { - private boolean found; - - private ExitingBreakFinder() - { - } - - private boolean breakFound() - { - return this.found; - } - - @Override - public void visitJSReferenceExpression(JSReferenceExpression exp) - { - } - - @Override - public void visitJSBreakStatement(JSBreakStatement breakStatement) - { - if(breakStatement.getLabel() != null) - { - return; - } - this.found = true; - } - - @Override - public void visitJSDoWhileStatement(JSDoWhileStatement statement) - { - // don't drill down - } - - @Override - public void visitJSForStatement(JSForStatement statement) - { - // don't drill down - } - - @Override - public void visitJSForInStatement(JSForInStatement statement) - { - // don't drill down - } - - @Override - public void visitJSWhileStatement(JSWhileStatement statement) - { - // don't drill down - } - - @Override - public void visitJSSwitchStatement(JSSwitchStatement statement) - { - // don't drill down - } - } - - private static class ReturnFinder extends JSRecursiveElementVisitor - { - private boolean found; - - private ReturnFinder() - { - } - - private boolean returnFound() - { - return this.found; - } - - @Override - public void visitJSReturnStatement(JSReturnStatement returnStatement) - { - this.found = true; - } - } - - private static class ConflictingDeclarationVisitor extends JSRecursiveElementVisitor - { - - private final String variableName; - private final JSBlockStatement exceptBlock; - private boolean hasConflictingDeclaration; - - ConflictingDeclarationVisitor(String variableName, - JSBlockStatement exceptBlock) - { - this.variableName = variableName; - this.exceptBlock = exceptBlock; - } - - @Override - public void visitJSElement(JSElement element) - { - if(!this.hasConflictingDeclaration) - { - super.visitJSElement(element); - } - } - - @Override - public void visitJSBlock(JSBlockStatement block) - { - if(!(this.hasConflictingDeclaration || - block.equals(this.exceptBlock))) - { - super.visitJSBlock(block); - } - } - - @Override - public void visitJSVariable(JSVariable variable) - { - if(!this.hasConflictingDeclaration) - { - super.visitJSVariable(variable); - final String name = variable.getName(); - this.hasConflictingDeclaration = (name != null && name.equals(this.variableName)); - } - } - - public boolean hasConflictingDeclaration() - { - return this.hasConflictingDeclaration; - } - } - - private static class RecursiveCallVisitor extends JSRecursiveElementVisitor - { - - private final JSFunction function; - private List recursionReturns; - - RecursiveCallVisitor(JSFunction function) - { - this.function = function; - this.recursionReturns = new ArrayList(); - } - - @Override - public void visitJSCallExpression(JSCallExpression callExpression) - { - super.visitJSCallExpression(callExpression); - - final JSExpression methodExpression = callExpression.getMethodExpression(); - - if(methodExpression == null || !(methodExpression instanceof JSReferenceExpression)) - { - return; - } - - final JSReturnStatement returnStatement = PsiTreeUtil.getParentOfType(callExpression, JSReturnStatement.class); - - if(returnStatement == null) - { - return; - } - - final PsiElement calledFunction = ((JSReferenceExpression) methodExpression).resolve(); - - if(calledFunction == null || - (!(calledFunction instanceof JSFunction) || !calledFunction.equals(this.function))) - { - return; - } - - - this.recursionReturns.add(callExpression); - } - - public List getCalls() - { - return this.recursionReturns; - } - } +public class ControlFlowUtils { + private ControlFlowUtils() { + } + + public static boolean statementMayCompleteNormally(@Nullable JSStatement statement) { + if (statement == null + || statement instanceof JSBreakStatement + || statement instanceof JSContinueStatement + || statement instanceof JSReturnStatement + || statement instanceof JSThrowStatement + || statement instanceof JSWithStatement) { + return false; + } + else if (statement instanceof JSExpressionStatement + || statement instanceof JSEmptyStatement + || statement instanceof JSVarStatement) { + return true; + } + else if (statement instanceof JSForStatement loopStatement) { + JSExpression condition = loopStatement.getCondition(); + + return condition != null && !isBooleanConstant(condition, false) || statementIsBreakTarget(loopStatement); + } + else if (statement instanceof JSForInStatement) { + return statementIsBreakTarget(statement); + } + else if (statement instanceof JSWhileStatement loopStatement) { + return !isBooleanConstant(loopStatement.getCondition(), true) || statementIsBreakTarget(loopStatement); + } + else if (statement instanceof JSDoWhileStatement loopStatement) { + return statementMayCompleteNormally(loopStatement.getBody()) + && (!isBooleanConstant(loopStatement.getCondition(), true) || statementIsBreakTarget(loopStatement)); + } + else if (statement instanceof JSBlockStatement blockStatement) { + return codeBlockMayCompleteNormally(blockStatement.getStatements()); + } + else if (statement instanceof JSLabeledStatement) { + JSLabeledStatement labeledStatement = (JSLabeledStatement)statement; + JSStatement body = labeledStatement.getStatement(); + + return (statementMayCompleteNormally(body) || statementIsBreakTarget(body)); + } + else if (statement instanceof JSIfStatement ifStatement) { + JSStatement thenBranch = ifStatement.getThen(); + JSStatement elseBranch = ifStatement.getElse(); + + return elseBranch == null || + statementMayCompleteNormally(thenBranch) || + statementMayCompleteNormally(elseBranch); + } + else if (statement instanceof JSTryStatement tryStatement) { + if (!statementMayCompleteNormally(tryStatement.getFinallyStatement())) { + return false; + } + if (statementMayCompleteNormally(tryStatement.getStatement())) { + return true; + } + + JSCatchBlock catchBlock = tryStatement.getCatchBlock(); + + return catchBlock != null && statementMayCompleteNormally(catchBlock.getStatement()); + } + else if (statement instanceof JSSwitchStatement switchStatement) { + if (statementIsBreakTarget(switchStatement)) { + return true; + } + + for (JSCaseClause caseClause : switchStatement.getCaseClauses()) { + if (!codeBlockMayCompleteNormally(caseClause.getStatements())) { + return false; + } + } + return true; + } + else { + return false; + } + } + + public static boolean codeBlockMayCompleteNormally(@Nullable JSStatement[] statements) { + if (statements != null) { + for (JSStatement statement : statements) { + if (!statementMayCompleteNormally(statement)) { + return false; + } + } + } + return true; + } + + @SuppressWarnings({"UnnecessaryUnboxing"}) + private static boolean isBooleanConstant(JSExpression test, boolean val) { + if (!ExpressionUtil.isConstantExpression(test)) { + return false; + } + Object value = ExpressionUtil.computeConstantExpression(test); + return value != null && value instanceof Boolean && ((Boolean)value).booleanValue() == val; + } + + private static boolean statementIsBreakTarget(@Nullable JSStatement statement) { + if (statement == null) { + return false; + } + + BreakTargetFinder breakFinder = new BreakTargetFinder(statement); + + statement.accept(breakFinder); + return breakFinder.breakFound(); + } + + public static boolean statementContainsExitingBreak(@Nullable JSStatement statement) { + if (statement == null) { + return false; + } + + ExitingBreakFinder breakFinder = new ExitingBreakFinder(); + + statement.accept(breakFinder); + return breakFinder.breakFound(); + } + + public static boolean statementIsContinueTarget(@Nullable JSStatement statement) { + if (statement == null) { + return false; + } + + ContinueTargetFinder continueFinder = new ContinueTargetFinder(statement); + + statement.accept(continueFinder); + return continueFinder.continueFound(); + } + + public static boolean statementContainsReturn(@Nullable JSStatement statement) { + if (statement == null) { + return false; + } + + ReturnFinder returnFinder = new ReturnFinder(); + + statement.accept(returnFinder); + return returnFinder.returnFound(); + } + + public static boolean statementCompletesWithStatement(@Nonnull JSStatement containingStatement, @Nonnull JSStatement statement) { + JSElement statementToCheck = statement; + + while (true) { + if (statementToCheck.equals(containingStatement)) { + return true; + } + + JSStatement container = PsiTreeUtil.getParentOfType(statementToCheck, JSStatement.class); + + if (container == null) { + return false; + } + if (container instanceof JSBlockStatement blockStatement) { + if (!statementIsLastInBlock(blockStatement, (JSStatement)statementToCheck)) { + return false; + } + } + if (container instanceof JSLoopStatement) { + return false; + } + statementToCheck = container; + } + } + + private static boolean elementCompletesWithStatement(@Nonnull JSElement element, @Nonnull JSStatement statement) { + PsiElement statementToCheck = statement; + + while (true) { + if (statementToCheck == null) { + return false; + } + if (statementToCheck.equals(element)) { + return true; + } + + JSElement container = PsiTreeUtil.getParentOfType(statementToCheck, JSElement.class); + + if (container == null || container instanceof JSLoopStatement) { + return false; + } + + if (container instanceof JSBlockStatement blockStatement) { + if (!statementIsLastInBlock(blockStatement, (JSStatement)statementToCheck)) { + return false; + } + if (container.equals(element)) { + return true; + } + statementToCheck = PsiTreeUtil.getParentOfType(container, JSStatement.class, JSFunction.class); + } + else { + statementToCheck = container; + } + } + } + + public static boolean functionCompletesWithStatement(@Nonnull JSFunction function, @Nonnull JSStatement statement) { + return elementCompletesWithStatement(function, statement); + } + + public static boolean blockCompletesWithStatement(@Nonnull JSBlockStatement block, @Nonnull JSStatement statement) { + return elementCompletesWithStatement(block, statement); + } + + private static boolean statementIsLastInBlock(@Nonnull JSBlockStatement block, @Nonnull JSStatement statement) { + JSStatement[] statements = block.getStatements(); + + //noinspection ForLoopWithMissingComponent + for (int index = statements.length; --index >= 0; ) { + JSStatement childStatement = statements[index]; + + if (statement.equals(childStatement)) { + return true; + } + if (!(statement instanceof JSEmptyStatement)) { + return false; + } + } + return false; + } + + @Nullable + public static JSVariable resolveVariable(@Nullable JSExpression expression) { + if (expression == null) { + return null; + } + else if (expression instanceof JSReferenceExpression referenceExpression) { + PsiElement variable = referenceExpression.resolve(); + + return variable != null && variable instanceof JSVariable jsVariable ? jsVariable : null; + } + else if (expression instanceof JSDefinitionExpression definitionExpression) { + JSExpression referentExpression = definitionExpression.getExpression(); + PsiReference reference = (referentExpression == null) ? null : referentExpression.getReference(); + PsiElement variable = (reference == null) ? null : reference.resolve(); + + return variable != null && variable instanceof JSVariable jsVariable ? jsVariable : null; + } + else { + return null; + } + } + + @Nullable + public static JSFunction resolveMethod(JSCallExpression expression) { + JSExpression methodExpression = (expression == null) ? null : expression.getMethodExpression(); + + if (methodExpression != null && methodExpression instanceof JSReferenceExpression referenceExpression) { + PsiElement referent = referenceExpression.resolve(); + + return referent != null && referent instanceof JSFunction function ? function : null; + } + return null; + } + + public static boolean canBeMerged(JSStatement statement1, JSStatement statement2) { + if (!ControlFlowUtils.statementMayCompleteNormally(statement1)) { + return false; + } + Set statement1Declarations = calculateTopLevelDeclarations(statement1); + if (containsConflictingDeclarations(statement1Declarations, statement2)) { + return false; + } + Set statement2Declarations = calculateTopLevelDeclarations(statement2); + return (!containsConflictingDeclarations(statement2Declarations, statement1)); + } + + public static boolean isInLoopStatementBody(@Nonnull PsiElement element) { + JSLoopStatement forStatement = PsiTreeUtil.getParentOfType(element, JSLoopStatement.class); + + if (forStatement == null) { + return false; + } + + JSStatement body = forStatement.getBody(); + + return (body != null && PsiTreeUtil.isAncestor(body, element, true)); + } + + @Nonnull + public static List getRecursiveCalls(@Nonnull JSFunction function) { + RecursiveCallVisitor recursiveCallVisitor = new RecursiveCallVisitor(function); + + function.accept(recursiveCallVisitor); + return recursiveCallVisitor.getCalls(); + } + + private static boolean containsConflictingDeclarations(Set declarations, JSStatement statement) { + DeclarationUtils.DeclarationConflictVisitor visitor = + new DeclarationUtils.DeclarationConflictVisitor(declarations); + statement.accept(visitor); + return visitor.hasConflict(); + } + + public static boolean containsConflictingDeclarations(JSBlockStatement block, JSBlockStatement parentBlock) { + JSStatement[] statements = block.getStatements(); + Set declaredVars = new HashSet<>(); + + for (JSStatement statement : statements) { + if (statement instanceof JSVarStatement declaration) { + for (JSVariable var : declaration.getVariables()) { + declaredVars.add(var); + } + } + } + + for (JSVariable variable : declaredVars) { + if (conflictingDeclarationExists(variable.getName(), parentBlock, block)) { + return true; + } + } + + return false; + } + + private static boolean conflictingDeclarationExists(String name, JSBlockStatement parentBlock, JSBlockStatement exceptBlock) { + ConflictingDeclarationVisitor visitor = new ConflictingDeclarationVisitor(name, exceptBlock); + parentBlock.accept(visitor); + return visitor.hasConflictingDeclaration(); + } + + private static Set calculateTopLevelDeclarations(JSStatement statement) { + Set out = new HashSet<>(); + + if (statement instanceof JSVarStatement varStatement) { + addDeclarations(varStatement, out); + } + else if (statement instanceof JSBlockStatement blockStatement) { + for (JSStatement subStatement : blockStatement.getStatements()) { + if (subStatement instanceof JSVarStatement varStatement) { + addDeclarations(varStatement, out); + } + } + } + return out; + } + + private static void addDeclarations(JSVarStatement statement, Set declaredVars) { + for (JSVariable variable : statement.getVariables()) { + declaredVars.add(variable.getName()); + } + } + + public static void appendStatementsInSequence(StringBuilder buffer, JSStatement statement1, JSStatement statement2) { + if (statement1 == null) { + buffer.append(' ') + .append(statement2.getText()); + } + else if (statement2 == null) { + buffer.append(' ') + .append(statement1.getText()); + } + else { + buffer.append('{'); + appendStatementStripped(buffer, statement1); + appendStatementStripped(buffer, statement2); + buffer.append('}'); + } + } + + private static void appendStatementStripped(StringBuilder buffer, JSStatement statement) { + if (statement instanceof JSBlockStatement) { + for (PsiElement child : statement.getChildren()) { + buffer.append(child.getText()); + } + } + else { + buffer.append(statement.getText()); + } + } + + private static class BreakTargetFinder extends JSRecursiveElementVisitor { + private boolean found; + private final JSStatement target; + + private BreakTargetFinder(JSStatement target) { + this.target = target; + } + + private boolean breakFound() { + return this.found; + } + + @Override + public void visitJSReferenceExpression(JSReferenceExpression JSReferenceExpression) { + } + + @Override + public void visitJSBreakStatement(JSBreakStatement breakStatement) { + super.visitJSBreakStatement(breakStatement); + JSStatement exitedStatement = breakStatement.getStatementToBreak(); + if (exitedStatement == null) { + return; + } + this.found = (exitedStatement.equals(this.target)); + } + } + + private static class ContinueTargetFinder extends JSRecursiveElementVisitor { + private boolean found; + private final JSStatement target; + + private ContinueTargetFinder(JSStatement target) { + this.target = target; + } + + private boolean continueFound() { + return this.found; + } + + @Override + public void visitJSReferenceExpression(JSReferenceExpression JSReferenceExpression) { + } + + @Override + public void visitJSContinueStatement(JSContinueStatement continueStatement) { + super.visitJSContinueStatement(continueStatement); + JSStatement statement = continueStatement.getStatementToContinue(); + if (statement == null) { + return; + } + this.found = (statement.equals(this.target)); + } + } + + private static class ExitingBreakFinder extends JSRecursiveElementVisitor { + private boolean found; + + private ExitingBreakFinder() { + } + + private boolean breakFound() { + return this.found; + } + + @Override + public void visitJSReferenceExpression(JSReferenceExpression exp) { + } + + @Override + public void visitJSBreakStatement(JSBreakStatement breakStatement) { + if (breakStatement.getLabel() != null) { + return; + } + this.found = true; + } + + @Override + public void visitJSDoWhileStatement(JSDoWhileStatement statement) { + // don't drill down + } + + @Override + public void visitJSForStatement(JSForStatement statement) { + // don't drill down + } + + @Override + public void visitJSForInStatement(JSForInStatement statement) { + // don't drill down + } + + @Override + public void visitJSWhileStatement(JSWhileStatement statement) { + // don't drill down + } + + @Override + public void visitJSSwitchStatement(JSSwitchStatement statement) { + // don't drill down + } + } + + private static class ReturnFinder extends JSRecursiveElementVisitor { + private boolean found; + + private ReturnFinder() { + } + + private boolean returnFound() { + return this.found; + } + + @Override + public void visitJSReturnStatement(JSReturnStatement returnStatement) { + this.found = true; + } + } + + private static class ConflictingDeclarationVisitor extends JSRecursiveElementVisitor { + + private final String variableName; + private final JSBlockStatement exceptBlock; + private boolean hasConflictingDeclaration; + + ConflictingDeclarationVisitor( + String variableName, + JSBlockStatement exceptBlock + ) { + this.variableName = variableName; + this.exceptBlock = exceptBlock; + } + + @Override + public void visitJSElement(JSElement element) { + if (!this.hasConflictingDeclaration) { + super.visitJSElement(element); + } + } + + @Override + public void visitJSBlock(JSBlockStatement block) { + if (!(this.hasConflictingDeclaration || + block.equals(this.exceptBlock))) { + super.visitJSBlock(block); + } + } + + @Override + public void visitJSVariable(JSVariable variable) { + if (!this.hasConflictingDeclaration) { + super.visitJSVariable(variable); + String name = variable.getName(); + this.hasConflictingDeclaration = (name != null && name.equals(this.variableName)); + } + } + + public boolean hasConflictingDeclaration() { + return this.hasConflictingDeclaration; + } + } + + private static class RecursiveCallVisitor extends JSRecursiveElementVisitor { + private final JSFunction function; + private List recursionReturns; + + RecursiveCallVisitor(JSFunction function) { + this.function = function; + this.recursionReturns = new ArrayList<>(); + } + + @Override + public void visitJSCallExpression(JSCallExpression callExpression) { + super.visitJSCallExpression(callExpression); + + JSExpression methodExpression = callExpression.getMethodExpression(); + + if (methodExpression == null || !(methodExpression instanceof JSReferenceExpression)) { + return; + } + + JSReturnStatement returnStatement = PsiTreeUtil.getParentOfType(callExpression, JSReturnStatement.class); + + if (returnStatement == null) { + return; + } + + PsiElement calledFunction = ((JSReferenceExpression)methodExpression).resolve(); + + if (calledFunction == null || + (!(calledFunction instanceof JSFunction) || !calledFunction.equals(this.function))) { + return; + } + + + this.recursionReturns.add(callExpression); + } + + public List getCalls() { + return this.recursionReturns; + } + } } \ No newline at end of file diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/DeclarationUtils.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/DeclarationUtils.java index 1d1bcbd7..414a2439 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/DeclarationUtils.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/DeclarationUtils.java @@ -20,185 +20,186 @@ import java.util.HashSet; import java.util.Set; -public class DeclarationUtils -{ - private DeclarationUtils() - { - } - - public static void calculateVariablesDeclared(JSStatement statement, - Set variablesDeclaredAtTopLevel, - Set variablesDeclaredAtLowerLevels, - boolean isTopLevel) - { - if(statement == null) - { - return; - } - - if(statement instanceof JSBreakStatement || - statement instanceof JSExpressionStatement || - statement instanceof JSContinueStatement || - statement instanceof JSThrowStatement || - statement instanceof JSReturnStatement) - { - // Nothing to do. - } - else if(statement instanceof JSVarStatement) - { - calculateVariablesDeclared((JSVarStatement) statement, variablesDeclaredAtTopLevel, - variablesDeclaredAtLowerLevels, isTopLevel); - } - else if(statement instanceof JSForStatement) - { - final JSForStatement loopStatement = (JSForStatement) statement; - - calculateVariablesDeclared(loopStatement.getVarDeclaration(), variablesDeclaredAtTopLevel, - variablesDeclaredAtLowerLevels, false); - calculateVariablesDeclared(loopStatement.getBody(), variablesDeclaredAtTopLevel, - variablesDeclaredAtLowerLevels, false); - } - else if(statement instanceof JSWhileStatement) - { - final JSWhileStatement loopStatement = (JSWhileStatement) statement; - - calculateVariablesDeclared(loopStatement.getBody(), variablesDeclaredAtTopLevel, - variablesDeclaredAtLowerLevels, false); - } - else if(statement instanceof JSDoWhileStatement) - { - final JSDoWhileStatement loopStatement = (JSDoWhileStatement) statement; - - calculateVariablesDeclared(loopStatement.getBody(), variablesDeclaredAtTopLevel, - variablesDeclaredAtLowerLevels, false); - } - else if(statement instanceof JSBlockStatement) - { - final JSBlockStatement block = (JSBlockStatement) statement; - - calculateVariablesDeclared(block.getStatements(), variablesDeclaredAtTopLevel, - variablesDeclaredAtLowerLevels, false); - } - else if(statement instanceof JSLabeledStatement) - { - final JSLabeledStatement labeledStatement = (JSLabeledStatement) statement; - - calculateVariablesDeclared(labeledStatement.getStatement(), variablesDeclaredAtTopLevel, - variablesDeclaredAtLowerLevels, false); - } - else if(statement instanceof JSIfStatement) - { - final JSIfStatement ifStatement = (JSIfStatement) statement; - final JSStatement thenBranch = ifStatement.getThen(); - final JSStatement elseBranch = ifStatement.getElse(); - - calculateVariablesDeclared(thenBranch, variablesDeclaredAtTopLevel, - variablesDeclaredAtLowerLevels, false); - calculateVariablesDeclared(elseBranch, variablesDeclaredAtTopLevel, - variablesDeclaredAtLowerLevels, false); - } - else if(statement instanceof JSTryStatement) - { - final JSTryStatement tryStatement = (JSTryStatement) statement; - - calculateVariablesDeclared(tryStatement.getStatement(), - variablesDeclaredAtTopLevel, - variablesDeclaredAtLowerLevels, - false); - calculateVariablesDeclared(tryStatement.getFinallyStatement(), - variablesDeclaredAtTopLevel, - variablesDeclaredAtLowerLevels, - false); - - final JSCatchBlock catchBlock = tryStatement.getCatchBlock(); - - if(catchBlock != null) - { - calculateVariablesDeclared(catchBlock.getStatement(), - variablesDeclaredAtTopLevel, - variablesDeclaredAtLowerLevels, - false); - } - } - else if(statement instanceof JSSwitchStatement) - { - final JSSwitchStatement switchStatement = (JSSwitchStatement) statement; - - for(JSCaseClause caseClause : switchStatement.getCaseClauses()) - { - calculateVariablesDeclared(caseClause.getStatements(), variablesDeclaredAtTopLevel, - variablesDeclaredAtLowerLevels, false); - } - } - } - - private static void calculateVariablesDeclared(JSVarStatement statement, - Set variablesDeclaredAtTopLevel, - Set variablesDeclaredAtLowerLevels, - boolean isTopLevel) - { - for(JSVariable variable : statement.getVariables()) - { - final String variableName = variable.getName(); - - if(isTopLevel) - { - variablesDeclaredAtTopLevel.add(variableName); - } - else - { - variablesDeclaredAtLowerLevels.add(variableName); - } - } - } - - private static void calculateVariablesDeclared(JSStatement[] statements, - Set variablesDeclaredAtTopLevel, - Set variablesDeclaredAtLowerLevels, - boolean isTopLevel) - { - if(statements != null) - { - for(JSStatement statement : statements) - { - calculateVariablesDeclared(statement, - variablesDeclaredAtTopLevel, - variablesDeclaredAtLowerLevels, - isTopLevel); - } - } - } - - public static class DeclarationConflictVisitor extends JSRecursiveElementVisitor - { - private final Set declarations; - private boolean hasConflict; - - public DeclarationConflictVisitor(Set declarations) - { - this.declarations = new HashSet(declarations); - } - - @Override - public void visitJSVariable(JSVariable variable) - { - super.visitJSVariable(variable); - - final String name = variable.getName(); - - for(String declaration : this.declarations) - { - if(declaration.equals(name)) - { - this.hasConflict = true; - break; - } - } - } - - public boolean hasConflict() - { - return this.hasConflict; - } - } +public class DeclarationUtils { + private DeclarationUtils() { + } + + public static void calculateVariablesDeclared( + JSStatement statement, + Set variablesDeclaredAtTopLevel, + Set variablesDeclaredAtLowerLevels, + boolean isTopLevel + ) { + if (statement == null) { + return; + } + + if (statement instanceof JSBreakStatement + || statement instanceof JSExpressionStatement + || statement instanceof JSContinueStatement + || statement instanceof JSThrowStatement + || statement instanceof JSReturnStatement) { + // Nothing to do. + } + else if (statement instanceof JSVarStatement varStatement) { + calculateVariablesDeclared(varStatement, variablesDeclaredAtTopLevel, + variablesDeclaredAtLowerLevels, isTopLevel + ); + } + else if (statement instanceof JSForStatement loopStatement) { + calculateVariablesDeclared( + loopStatement.getVarDeclaration(), + variablesDeclaredAtTopLevel, + variablesDeclaredAtLowerLevels, + false + ); + calculateVariablesDeclared( + loopStatement.getBody(), + variablesDeclaredAtTopLevel, + variablesDeclaredAtLowerLevels, + false + ); + } + else if (statement instanceof JSWhileStatement loopStatement) { + calculateVariablesDeclared( + loopStatement.getBody(), + variablesDeclaredAtTopLevel, + variablesDeclaredAtLowerLevels, + false + ); + } + else if (statement instanceof JSDoWhileStatement loopStatement) { + calculateVariablesDeclared( + loopStatement.getBody(), + variablesDeclaredAtTopLevel, + variablesDeclaredAtLowerLevels, + false + ); + } + else if (statement instanceof JSBlockStatement block) { + calculateVariablesDeclared( + block.getStatements(), + variablesDeclaredAtTopLevel, + variablesDeclaredAtLowerLevels, + false + ); + } + else if (statement instanceof JSLabeledStatement labeledStatement) { + calculateVariablesDeclared( + labeledStatement.getStatement(), + variablesDeclaredAtTopLevel, + variablesDeclaredAtLowerLevels, + false + ); + } + else if (statement instanceof JSIfStatement ifStatement) { + JSStatement thenBranch = ifStatement.getThen(); + JSStatement elseBranch = ifStatement.getElse(); + + calculateVariablesDeclared(thenBranch, variablesDeclaredAtTopLevel, + variablesDeclaredAtLowerLevels, false + ); + calculateVariablesDeclared(elseBranch, variablesDeclaredAtTopLevel, + variablesDeclaredAtLowerLevels, false + ); + } + else if (statement instanceof JSTryStatement tryStatement) { + calculateVariablesDeclared( + tryStatement.getStatement(), + variablesDeclaredAtTopLevel, + variablesDeclaredAtLowerLevels, + false + ); + calculateVariablesDeclared( + tryStatement.getFinallyStatement(), + variablesDeclaredAtTopLevel, + variablesDeclaredAtLowerLevels, + false + ); + + JSCatchBlock catchBlock = tryStatement.getCatchBlock(); + + if (catchBlock != null) { + calculateVariablesDeclared( + catchBlock.getStatement(), + variablesDeclaredAtTopLevel, + variablesDeclaredAtLowerLevels, + false + ); + } + } + else if (statement instanceof JSSwitchStatement switchStatement) { + for (JSCaseClause caseClause : switchStatement.getCaseClauses()) { + calculateVariablesDeclared( + caseClause.getStatements(), + variablesDeclaredAtTopLevel, + variablesDeclaredAtLowerLevels, + false + ); + } + } + } + + private static void calculateVariablesDeclared( + JSVarStatement statement, + Set variablesDeclaredAtTopLevel, + Set variablesDeclaredAtLowerLevels, + boolean isTopLevel + ) { + for (JSVariable variable : statement.getVariables()) { + String variableName = variable.getName(); + + if (isTopLevel) { + variablesDeclaredAtTopLevel.add(variableName); + } + else { + variablesDeclaredAtLowerLevels.add(variableName); + } + } + } + + private static void calculateVariablesDeclared( + JSStatement[] statements, + Set variablesDeclaredAtTopLevel, + Set variablesDeclaredAtLowerLevels, + boolean isTopLevel + ) { + if (statements != null) { + for (JSStatement statement : statements) { + calculateVariablesDeclared( + statement, + variablesDeclaredAtTopLevel, + variablesDeclaredAtLowerLevels, + isTopLevel + ); + } + } + } + + public static class DeclarationConflictVisitor extends JSRecursiveElementVisitor { + private final Set declarations; + private boolean hasConflict; + + public DeclarationConflictVisitor(Set declarations) { + this.declarations = new HashSet(declarations); + } + + @Override + public void visitJSVariable(JSVariable variable) { + super.visitJSVariable(variable); + + String name = variable.getName(); + + for (String declaration : this.declarations) { + if (declaration.equals(name)) { + this.hasConflict = true; + break; + } + } + } + + public boolean hasConflict() { + return this.hasConflict; + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/EquivalenceChecker.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/EquivalenceChecker.java index e3ec9489..c5fef4e4 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/EquivalenceChecker.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/EquivalenceChecker.java @@ -20,777 +20,624 @@ import consulo.language.ast.IElementType; import consulo.language.psi.PsiElement; -public class EquivalenceChecker -{ - - private EquivalenceChecker() - { - } - - private static final int THIS_EXPRESSION = 0; - private static final int LITERAL_EXPRESSION = 1; - private static final int CLASS_OBJECT_EXPRESSION = 2; - private static final int REFERENCE_EXPRESSION = 3; - private static final int SUPER_EXPRESSION = 4; - private static final int CALL_EXPRESSION = 5; - private static final int NEW_EXPRESSION = 6; - private static final int ARRAY_LITERAL_EXPRESSION = 7; - private static final int PREFIX_EXPRESSION = 8; - private static final int POSTFIX_EXPRESSION = 9; - private static final int ASSIGNMENT_EXPRESSION = 10; - private static final int BINARY_EXPRESSION = 11; - private static final int CONDITIONAL_EXPRESSION = 12; - private static final int INDEX_PROPERTY_ACCESS_EXPRESSION = 13; - private static final int OBJECT_LITERAL_EXPRESSION = 14; - private static final int FUNCTION_EXPRESSION = 15; - private static final int DEFINITION_EXPRESSION = 16; - - private static final int BLOCK_STATEMENT = 0; - private static final int BREAK_STATEMENT = 1; - private static final int CONTINUE_STATEMENT = 2; - private static final int VAR_STATEMENT = 3; - private static final int DO_WHILE_STATEMENT = 4; - private static final int EMPTY_STATEMENT = 5; - private static final int EXPRESSION_STATEMENT = 6; - private static final int FOR_STATEMENT = 7; - private static final int FOR_IN_STATEMENT = 8; - private static final int IF_STATEMENT = 9; - private static final int LABELED_STATEMENT = 10; - private static final int RETURN_STATEMENT = 11; - private static final int SWITCH_STATEMENT = 12; - private static final int THROW_STATEMENT = 13; - private static final int TRY_STATEMENT = 14; - private static final int WHILE_STATEMENT = 15; - private static final int WITH_STATEMENT = 16; - - public static boolean statementsAreEquivalent(JSStatement exp1, - JSStatement exp2) - { - if(exp1 == null && exp2 == null) - { - return true; - } - - if(exp1 == null || exp2 == null) - { - return false; - } - - final int type1 = getStatementType(exp1); - final int type2 = getStatementType(exp2); - - if(type1 != type2) - { - return false; - } - - switch(type1) - { - case BLOCK_STATEMENT: - return codeBlocksAreEquivalent((JSBlockStatement) exp1, - (JSBlockStatement) exp2); - case BREAK_STATEMENT: - return breakStatementsAreEquivalent((JSBreakStatement) exp1, - (JSBreakStatement) exp2); - case CONTINUE_STATEMENT: - return continueStatementsAreEquivalent((JSContinueStatement) exp1, - (JSContinueStatement) exp2); - case VAR_STATEMENT: - return declarationStatementsAreEquivalent((JSVarStatement) exp1, - (JSVarStatement) exp2); - case DO_WHILE_STATEMENT: - return doWhileStatementsAreEquivalent((JSDoWhileStatement) exp1, - (JSDoWhileStatement) exp2); - case EMPTY_STATEMENT: - return true; - case EXPRESSION_STATEMENT: - return expressionStatementsAreEquivalent((JSExpressionStatement) exp1, - (JSExpressionStatement) exp2); - case FOR_STATEMENT: - return forStatementsAreEquivalent((JSForStatement) exp1, - (JSForStatement) exp2); - case FOR_IN_STATEMENT: - return forInStatementsAreEquivalent((JSForInStatement) exp1, - (JSForInStatement) exp2); - case IF_STATEMENT: - return ifStatementsAreEquivalent((JSIfStatement) exp1, - (JSIfStatement) exp2); - case LABELED_STATEMENT: - return labeledStatementsAreEquivalent((JSLabeledStatement) exp1, - (JSLabeledStatement) exp2); - case RETURN_STATEMENT: - return returnStatementsAreEquivalent((JSReturnStatement) exp1, - (JSReturnStatement) exp2); - case SWITCH_STATEMENT: - return switchStatementsAreEquivalent((JSSwitchStatement) exp1, - (JSSwitchStatement) exp2); - case THROW_STATEMENT: - return throwStatementsAreEquivalent((JSThrowStatement) exp1, - (JSThrowStatement) exp2); - case TRY_STATEMENT: - return tryStatementsAreEquivalent((JSTryStatement) exp1, - (JSTryStatement) exp2); - case WHILE_STATEMENT: - return whileStatementsAreEquivalent((JSWhileStatement) exp1, - (JSWhileStatement) exp2); - case WITH_STATEMENT: - return withStatementsAreEquivalent((JSWithStatement) exp1, - (JSWithStatement) exp2); - default: - return false; - } - } - - private static boolean declarationStatementsAreEquivalent(JSVarStatement statement1, - JSVarStatement statement2) - { - if(statement1 == null || statement2 == null) - { - return statement1 == statement2; - } - JSVariable[] vars1 = statement1.getVariables(); - JSVariable[] vars2 = statement2.getVariables(); - - if(vars1.length == vars2.length) - { - for(int index = 0; index < vars2.length; index++) - { - if(!localVariableAreEquivalent(vars1[index], vars2[index])) - { - return false; - } - } - } - - return true; - } - - private static boolean tryStatementsAreEquivalent(JSTryStatement statement1, - JSTryStatement statement2) - { - if(!statementsAreEquivalent(statement1.getStatement(), - statement2.getStatement())) - { - return false; - } - if(!statementsAreEquivalent(statement1.getFinallyStatement(), - statement2.getFinallyStatement())) - { - return false; - } - JSCatchBlock catchBlock1 = statement1.getCatchBlock(); - JSCatchBlock catchBlock2 = statement2.getCatchBlock(); - if(catchBlock1 == null) - { - return (catchBlock2 == null); - } - else if(catchBlock2 == null) - { - return false; - } - - if(!parametersAreEquivalent(catchBlock1.getParameter(), - catchBlock2.getParameter())) - { - return false; - } - return statementsAreEquivalent(catchBlock1.getStatement(), - catchBlock2.getStatement()); - } - - private static boolean localVariableAreEquivalent(JSVariable var1, - JSVariable var2) - { - return (expressionsAreEquivalent(var1.getInitializer(), var2.getInitializer()) && - typesAreEquivalent(var1.getType(), var2.getType()) && - areEqual(var1.getName(), var2.getName())); - } - - private static boolean parametersAreEquivalent(JSParameter parameter1, - JSParameter parameter2) - { - return (typesAreEquivalent(parameter1.getType(), parameter2.getType()) && - areEqual(parameter1.getName(), parameter2.getName())); - } - - private static boolean typesAreEquivalent(JavaScriptType type1, JavaScriptType type2) - { - return areEqual(type1, type2); - } - - private static boolean whileStatementsAreEquivalent(JSWhileStatement statement1, - JSWhileStatement statement2) - { - return (expressionsAreEquivalent(statement1.getCondition(), statement2.getCondition()) && - statementsAreEquivalent(statement1.getBody(), statement2.getBody())); - } - - private static boolean forStatementsAreEquivalent(JSForStatement statement1, - JSForStatement statement2) - { - return (expressionsAreEquivalent(statement1.getCondition(), statement2.getCondition()) && - expressionsAreEquivalent(statement1.getInitialization(), statement2.getInitialization()) && - expressionsAreEquivalent(statement1.getUpdate(), statement2.getUpdate()) && - statementsAreEquivalent(statement1.getBody(), statement2.getBody())); - } - - private static boolean forInStatementsAreEquivalent(JSForInStatement statement1, - JSForInStatement statement2) - { - return (expressionsAreEquivalent(statement1.getCollectionExpression(), statement2.getCollectionExpression()) && - expressionsAreEquivalent(statement1.getVariableExpression(), statement2.getVariableExpression()) && - declarationStatementsAreEquivalent(statement1.getDeclarationStatement(), statement2.getDeclarationStatement()) && - statementsAreEquivalent(statement1.getBody(), statement2.getBody())); - } - - private static boolean switchStatementsAreEquivalent(JSSwitchStatement statement1, - JSSwitchStatement statement2) - { - if(!expressionsAreEquivalent(statement1.getSwitchExpression(), - statement2.getSwitchExpression())) - { - return false; - } - - final JSCaseClause[] caseClauses1 = statement1.getCaseClauses(); - final JSCaseClause[] caseClauses2 = statement2.getCaseClauses(); - - if(caseClauses1.length != caseClauses2.length) - { - return false; - } - - for(int index = 0; index < caseClauses1.length; index++) - { - if(!caseClausesAreEquivalent(caseClauses1[index], caseClauses2[index])) - { - return false; - } - } - - return true; - } - - private static boolean caseClausesAreEquivalent(JSCaseClause caseClause1, JSCaseClause caseClause2) - { - if(caseClause1.isDefault() != caseClause2.isDefault()) - { - return false; - } - if(!expressionsAreEquivalent(caseClause1.getCaseExpression(), caseClause2.getCaseExpression())) - { - return false; - } - - final JSStatement[] statements1 = caseClause1.getStatements(); - final JSStatement[] statements2 = caseClause2.getStatements(); - - if(statements1.length != statements2.length) - { - return false; - } - - for(int index = 0; index < statements1.length; index++) - { - if(!statementsAreEquivalent(statements1[index], statements2[index])) - { - return false; - } - } - - return false; - } - - private static boolean doWhileStatementsAreEquivalent(JSDoWhileStatement statement1, - JSDoWhileStatement statement2) - { - return (expressionsAreEquivalent(statement1.getCondition(), statement2.getCondition()) && - statementsAreEquivalent(statement1.getBody(), statement2.getBody())); - } - - private static boolean codeBlocksAreEquivalent(JSBlockStatement statement1, - JSBlockStatement statement2) - { - if(statement1 == null && statement2 == null) - { - return true; - } - if(statement1 == null || statement2 == null) - { - return false; - } - return blockStatementsAreEquivalent(statement1.getStatements(), statement2.getStatements()); - } - - private static boolean breakStatementsAreEquivalent(JSBreakStatement statement1, - JSBreakStatement statement2) - { - return areEqual(statement1.getLabel(), statement2.getLabel()); - } - - private static boolean continueStatementsAreEquivalent(JSContinueStatement statement1, - JSContinueStatement statement2) - { - return areEqual(statement1.getLabel(), statement2.getLabel()); - } - - private static boolean labeledStatementsAreEquivalent(JSLabeledStatement statement1, - JSLabeledStatement statement2) - { - final PsiElement element1 = statement1.getLabelIdentifier(); - final PsiElement element2 = statement2.getLabelIdentifier(); - - return ((element1 == null) ? (element2 == null) - : (element2 != null && element1.getText().equals(element2.getText()))); - } - - private static boolean blockStatementsAreEquivalent(JSStatement[] statements1, - JSStatement[] statements2) - { - if(statements1.length != statements2.length) - { - return false; - } - for(int index = 0; index < statements1.length; index++) - { - if(!statementsAreEquivalent(statements1[index], statements2[index])) - { - return false; - } - } - return true; - } - - private static boolean ifStatementsAreEquivalent(JSIfStatement statement1, - JSIfStatement statement2) - { - return (expressionsAreEquivalent(statement1.getCondition(), statement2.getCondition()) && - statementsAreEquivalent(statement1.getThen(), statement2.getThen()) && - statementsAreEquivalent(statement1.getElse(), statement2.getElse())); - } - - private static boolean expressionStatementsAreEquivalent(JSExpressionStatement statement1, - JSExpressionStatement statement2) - { - return expressionsAreEquivalent(statement1.getExpression(), statement2.getExpression()); - } - - private static boolean returnStatementsAreEquivalent(JSReturnStatement statement1, - JSReturnStatement statement2) - { - return expressionsAreEquivalent(statement1.getExpression(), statement2.getExpression()); - } - - private static boolean throwStatementsAreEquivalent(JSThrowStatement statement1, - JSThrowStatement statement2) - { - return expressionsAreEquivalent(statement1.getExpression(), statement2.getExpression()); - } - - private static boolean withStatementsAreEquivalent(JSWithStatement statement1, - JSWithStatement statement2) - { - return (expressionsAreEquivalent(statement1.getExpression(), statement2.getExpression()) && - statementsAreEquivalent(statement1.getStatement(), statement2.getStatement())); - } - - public static boolean expressionsAreEquivalent(JSExpression exp1, - JSExpression exp2) - { - if(exp1 == null && exp2 == null) - { - return true; - } - if(exp1 == null || exp2 == null) - { - return false; - } - - final JSExpression expToCompare1 = ParenthesesUtils.stripParentheses(exp1); - final JSExpression expToCompare2 = ParenthesesUtils.stripParentheses(exp2); - final int type1 = getExpressionType(expToCompare1); - final int type2 = getExpressionType(expToCompare2); - - if(type1 != type2) - { - return false; - } - switch(type1) - { - case THIS_EXPRESSION: - case SUPER_EXPRESSION: - return true; - - case LITERAL_EXPRESSION: - case CLASS_OBJECT_EXPRESSION: - case REFERENCE_EXPRESSION: - case DEFINITION_EXPRESSION: - return expToCompare1.getText().equals(expToCompare2.getText()); - - case CALL_EXPRESSION: - return callExpressionsAreEquivalent((JSCallExpression) expToCompare1, - (JSCallExpression) expToCompare2); - - case NEW_EXPRESSION: - return newExpressionsAreEquivalent((JSNewExpression) expToCompare1, - (JSNewExpression) expToCompare2); - - case ARRAY_LITERAL_EXPRESSION: - return arrayLiteralExpressionsAreEquivalent((JSArrayLiteralExpression) expToCompare1, - (JSArrayLiteralExpression) expToCompare2); - - case PREFIX_EXPRESSION: - return prefixExpressionsAreEquivalent((JSPrefixExpression) expToCompare1, - (JSPrefixExpression) expToCompare2); - - case POSTFIX_EXPRESSION: - return postfixExpressionsAreEquivalent((JSPostfixExpression) expToCompare1, - (JSPostfixExpression) expToCompare2); - - case BINARY_EXPRESSION: - return binaryExpressionsAreEquivalent((JSBinaryExpression) expToCompare1, - (JSBinaryExpression) expToCompare2); - - case ASSIGNMENT_EXPRESSION: - return assignmentExpressionsAreEquivalent((JSAssignmentExpression) expToCompare1, - (JSAssignmentExpression) expToCompare2); - - case CONDITIONAL_EXPRESSION: - return conditionalExpressionsAreEquivalent((JSConditionalExpression) expToCompare1, - (JSConditionalExpression) expToCompare2); - - case INDEX_PROPERTY_ACCESS_EXPRESSION: - return indexedPropertyAccessExpressionsAreEquivalent((JSIndexedPropertyAccessExpression) expToCompare1, - (JSIndexedPropertyAccessExpression) expToCompare2); - - case OBJECT_LITERAL_EXPRESSION: - return objectLiteralExpressionsAreEquivalent((JSObjectLiteralExpression) expToCompare1, - (JSObjectLiteralExpression) expToCompare2); - - case FUNCTION_EXPRESSION: - return functionExpressionsAreEquivalent((JSFunctionExpression) expToCompare1, - (JSFunctionExpression) expToCompare2); - - default: - return false; - } - } - - @SuppressWarnings({"UNUSED_SYMBOL"}) - private static boolean functionExpressionsAreEquivalent(JSFunctionExpression functionExp1, - JSFunctionExpression functionExp2) - { - return false; - } - - private static boolean objectLiteralExpressionsAreEquivalent(JSObjectLiteralExpression objectLiteralExp1, - JSObjectLiteralExpression objectLiteralExp2) - { - final JSProperty[] properties1 = objectLiteralExp1.getProperties(); - final JSProperty[] properties2 = objectLiteralExp2.getProperties(); - - if(properties1.length != properties2.length) - { - return false; - } - - for(int index = 0; index < properties2.length; index++) - { - final JSProperty property1 = properties1[index]; - final JSProperty property2 = properties2[index]; - final String propertyName1 = property1.getName(); - final String propertyName2 = property2.getName(); - - if(!(propertyName1 != null && propertyName2 != null && - propertyName2.equals(propertyName1) && - expressionsAreEquivalent(property1.getValue(), property2.getValue()))) - { - return false; - } - } - - return true; - } - - private static boolean indexedPropertyAccessExpressionsAreEquivalent(JSIndexedPropertyAccessExpression exp1, - JSIndexedPropertyAccessExpression exp2) - { - return (expressionsAreEquivalent(exp1.getIndexExpression(), exp2.getIndexExpression()) && - expressionsAreEquivalent(exp1.getQualifier(), exp2.getQualifier())); - } - - private static boolean callExpressionsAreEquivalent(JSCallExpression methodExp1, - JSCallExpression methodExp2) - { - JSExpression exp1; - JSExpression exp2; - - try - { - exp1 = methodExp1.getMethodExpression(); - exp2 = methodExp2.getMethodExpression(); - } - catch(Exception exception) - { - return false; - } - - if(!expressionsAreEquivalent(exp1, exp2)) - { - return false; - } - - final JSArgumentList argumentList1 = methodExp1.getArgumentList(); - final JSArgumentList argumentList2 = methodExp2.getArgumentList(); - - return (argumentList1 != null && - argumentList2 != null && - expressionListsAreEquivalent(argumentList1.getArguments(), argumentList2.getArguments())); - } - - private static boolean newExpressionsAreEquivalent(JSNewExpression newExp1, - JSNewExpression newExp2) - { - final JSExpression exp1 = newExp1.getMethodExpression(); - final JSExpression exp2 = newExp2.getMethodExpression(); - - if(!expressionsAreEquivalent(exp1, exp2)) - { - return false; - } - - final JSArgumentList argumentList1 = newExp1.getArgumentList(); - final JSArgumentList argumentList2 = newExp2.getArgumentList(); - - return (argumentList1 != null && - argumentList2 != null && - expressionListsAreEquivalent(argumentList1.getArguments(), argumentList2.getArguments())); - } - - private static boolean arrayLiteralExpressionsAreEquivalent(JSArrayLiteralExpression arrInitExp1, - JSArrayLiteralExpression arrInitExp2) - { - return expressionListsAreEquivalent(arrInitExp1.getExpressions(), arrInitExp2.getExpressions()); - } - - private static boolean prefixExpressionsAreEquivalent(JSPrefixExpression prefixExp1, - JSPrefixExpression prefixExp2) - { - final IElementType operator1 = prefixExp1.getOperationSign(); - final IElementType operator2 = prefixExp2.getOperationSign(); - - return (operator1 != null && operator2 != null && - operator1.equals(operator2) && - expressionsAreEquivalent(prefixExp1.getExpression(), prefixExp2.getExpression())); - } - - private static boolean postfixExpressionsAreEquivalent(JSPostfixExpression postfixExp1, - JSPostfixExpression postfixExp2) - { - final IElementType operator1 = postfixExp1.getOperationSign(); - final IElementType operator2 = postfixExp2.getOperationSign(); - - return (operator1.equals(operator2) && - expressionsAreEquivalent(postfixExp1.getExpression(), postfixExp2.getExpression())); - } - - private static boolean binaryExpressionsAreEquivalent(JSBinaryExpression binaryExp1, - JSBinaryExpression binaryExp2) - { - final IElementType operator1 = binaryExp1.getOperationSign(); - final IElementType operator2 = binaryExp2.getOperationSign(); - - return (operator1.equals(operator2) && - expressionsAreEquivalent(binaryExp1.getLOperand(), binaryExp2.getLOperand()) && - expressionsAreEquivalent(binaryExp1.getROperand(), binaryExp2.getROperand())); - } - - private static boolean assignmentExpressionsAreEquivalent(JSAssignmentExpression assignExp1, - JSAssignmentExpression assignExp2) - { - final IElementType operator1 = assignExp1.getOperationSign(); - final IElementType operator2 = assignExp2.getOperationSign(); - - return (operator1.equals(operator2) && - expressionsAreEquivalent(assignExp1.getLOperand(), assignExp2.getLOperand()) && - expressionsAreEquivalent(assignExp1.getROperand(), assignExp2.getROperand())); - } - - private static boolean conditionalExpressionsAreEquivalent(JSConditionalExpression condExp1, - JSConditionalExpression condExp2) - { - return (expressionsAreEquivalent(condExp1.getCondition(), condExp2.getCondition()) && - expressionsAreEquivalent(condExp1.getThen(), condExp2.getThen()) && - expressionsAreEquivalent(condExp1.getElse(), condExp2.getElse())); - } - - private static boolean expressionListsAreEquivalent(JSExpression[] expressions1, - JSExpression[] expressions2) - { - if(expressions1 == null && expressions2 == null) - { - return true; - } - - if(expressions1 == null || expressions2 == null) - { - return false; - } - if(expressions1.length != expressions2.length) - { - return false; - } - - for(int index = 0; index < expressions1.length; index++) - { - if(!expressionsAreEquivalent(expressions1[index], expressions2[index])) - { - return false; - } - } - return true; - } - - private static boolean areEqual(Object o1, Object o2) - { - return ((o1 == null) ? (o2 == null) : o1.equals(o2)); - } - - private static int getExpressionType(JSExpression exp) - { - if(exp instanceof JSThisExpression) - { - return THIS_EXPRESSION; - } - if(exp instanceof JSLiteralExpression) - { - return LITERAL_EXPRESSION; - } - if(exp instanceof JSReferenceExpression) - { - return REFERENCE_EXPRESSION; - } - if(exp instanceof JSNewExpression) - { - return NEW_EXPRESSION; - } - if(exp instanceof JSCallExpression) - { - return CALL_EXPRESSION; - } - if(exp instanceof JSArrayLiteralExpression) - { - return ARRAY_LITERAL_EXPRESSION; - } - if(exp instanceof JSPrefixExpression) - { - return PREFIX_EXPRESSION; - } - if(exp instanceof JSPostfixExpression) - { - return POSTFIX_EXPRESSION; - } - if(exp instanceof JSAssignmentExpression) - { - return ASSIGNMENT_EXPRESSION; - } - if(exp instanceof JSBinaryExpression) - { - return BINARY_EXPRESSION; - } - if(exp instanceof JSConditionalExpression) - { - return CONDITIONAL_EXPRESSION; - } - if(exp instanceof JSIndexedPropertyAccessExpression) - { - return INDEX_PROPERTY_ACCESS_EXPRESSION; - } - if(exp instanceof JSFunctionExpression) - { - return FUNCTION_EXPRESSION; - } - if(exp instanceof JSObjectLiteralExpression) - { - return OBJECT_LITERAL_EXPRESSION; - } - if(exp instanceof JSDefinitionExpression) - { - return DEFINITION_EXPRESSION; - } - return -1; - } - - private static int getStatementType(JSStatement statement) - { - if(statement instanceof JSBlockStatement) - { - return BLOCK_STATEMENT; - } - if(statement instanceof JSBreakStatement) - { - return BREAK_STATEMENT; - } - if(statement instanceof JSContinueStatement) - { - return CONTINUE_STATEMENT; - } - if(statement instanceof JSVarStatement) - { - return VAR_STATEMENT; - } - if(statement instanceof JSDoWhileStatement) - { - return DO_WHILE_STATEMENT; - } - if(statement instanceof JSEmptyStatement) - { - return EMPTY_STATEMENT; - } - if(statement instanceof JSExpressionStatement) - { - return EXPRESSION_STATEMENT; - } - if(statement instanceof JSForStatement) - { - return FOR_STATEMENT; - } - if(statement instanceof JSForInStatement) - { - return FOR_IN_STATEMENT; - } - if(statement instanceof JSIfStatement) - { - return IF_STATEMENT; - } - if(statement instanceof JSLabeledStatement) - { - return LABELED_STATEMENT; - } - if(statement instanceof JSReturnStatement) - { - return RETURN_STATEMENT; - } - if(statement instanceof JSSwitchStatement) - { - return SWITCH_STATEMENT; - } - if(statement instanceof JSThrowStatement) - { - return THROW_STATEMENT; - } - if(statement instanceof JSTryStatement) - { - return TRY_STATEMENT; - } - if(statement instanceof JSWhileStatement) - { - return WHILE_STATEMENT; - } - if(statement instanceof JSWithStatement) - { - return WITH_STATEMENT; - } - return -1; - } +public class EquivalenceChecker { + private EquivalenceChecker() { + } + + private static final int THIS_EXPRESSION = 0; + private static final int LITERAL_EXPRESSION = 1; + private static final int CLASS_OBJECT_EXPRESSION = 2; + private static final int REFERENCE_EXPRESSION = 3; + private static final int SUPER_EXPRESSION = 4; + private static final int CALL_EXPRESSION = 5; + private static final int NEW_EXPRESSION = 6; + private static final int ARRAY_LITERAL_EXPRESSION = 7; + private static final int PREFIX_EXPRESSION = 8; + private static final int POSTFIX_EXPRESSION = 9; + private static final int ASSIGNMENT_EXPRESSION = 10; + private static final int BINARY_EXPRESSION = 11; + private static final int CONDITIONAL_EXPRESSION = 12; + private static final int INDEX_PROPERTY_ACCESS_EXPRESSION = 13; + private static final int OBJECT_LITERAL_EXPRESSION = 14; + private static final int FUNCTION_EXPRESSION = 15; + private static final int DEFINITION_EXPRESSION = 16; + + private static final int BLOCK_STATEMENT = 0; + private static final int BREAK_STATEMENT = 1; + private static final int CONTINUE_STATEMENT = 2; + private static final int VAR_STATEMENT = 3; + private static final int DO_WHILE_STATEMENT = 4; + private static final int EMPTY_STATEMENT = 5; + private static final int EXPRESSION_STATEMENT = 6; + private static final int FOR_STATEMENT = 7; + private static final int FOR_IN_STATEMENT = 8; + private static final int IF_STATEMENT = 9; + private static final int LABELED_STATEMENT = 10; + private static final int RETURN_STATEMENT = 11; + private static final int SWITCH_STATEMENT = 12; + private static final int THROW_STATEMENT = 13; + private static final int TRY_STATEMENT = 14; + private static final int WHILE_STATEMENT = 15; + private static final int WITH_STATEMENT = 16; + + public static boolean statementsAreEquivalent(JSStatement exp1, JSStatement exp2) { + if (exp1 == null && exp2 == null) { + return true; + } + + if (exp1 == null || exp2 == null) { + return false; + } + + int type1 = getStatementType(exp1); + int type2 = getStatementType(exp2); + + if (type1 != type2) { + return false; + } + + switch (type1) { + case BLOCK_STATEMENT: + return codeBlocksAreEquivalent((JSBlockStatement)exp1, (JSBlockStatement)exp2); + case BREAK_STATEMENT: + return breakStatementsAreEquivalent((JSBreakStatement)exp1, (JSBreakStatement)exp2); + case CONTINUE_STATEMENT: + return continueStatementsAreEquivalent((JSContinueStatement)exp1, (JSContinueStatement)exp2); + case VAR_STATEMENT: + return declarationStatementsAreEquivalent((JSVarStatement)exp1, (JSVarStatement)exp2); + case DO_WHILE_STATEMENT: + return doWhileStatementsAreEquivalent((JSDoWhileStatement)exp1, (JSDoWhileStatement)exp2); + case EMPTY_STATEMENT: + return true; + case EXPRESSION_STATEMENT: + return expressionStatementsAreEquivalent((JSExpressionStatement)exp1, (JSExpressionStatement)exp2); + case FOR_STATEMENT: + return forStatementsAreEquivalent((JSForStatement)exp1, (JSForStatement)exp2); + case FOR_IN_STATEMENT: + return forInStatementsAreEquivalent((JSForInStatement)exp1, (JSForInStatement)exp2); + case IF_STATEMENT: + return ifStatementsAreEquivalent((JSIfStatement)exp1, (JSIfStatement)exp2); + case LABELED_STATEMENT: + return labeledStatementsAreEquivalent((JSLabeledStatement)exp1, (JSLabeledStatement)exp2); + case RETURN_STATEMENT: + return returnStatementsAreEquivalent((JSReturnStatement)exp1, (JSReturnStatement)exp2); + case SWITCH_STATEMENT: + return switchStatementsAreEquivalent((JSSwitchStatement)exp1, (JSSwitchStatement)exp2); + case THROW_STATEMENT: + return throwStatementsAreEquivalent((JSThrowStatement)exp1, (JSThrowStatement)exp2); + case TRY_STATEMENT: + return tryStatementsAreEquivalent((JSTryStatement)exp1, (JSTryStatement)exp2); + case WHILE_STATEMENT: + return whileStatementsAreEquivalent((JSWhileStatement)exp1, (JSWhileStatement)exp2); + case WITH_STATEMENT: + return withStatementsAreEquivalent((JSWithStatement)exp1, (JSWithStatement)exp2); + default: + return false; + } + } + + private static boolean declarationStatementsAreEquivalent(JSVarStatement statement1, JSVarStatement statement2) { + if (statement1 == null || statement2 == null) { + return statement1 == statement2; + } + JSVariable[] vars1 = statement1.getVariables(); + JSVariable[] vars2 = statement2.getVariables(); + + if (vars1.length == vars2.length) { + for (int index = 0; index < vars2.length; index++) { + if (!localVariableAreEquivalent(vars1[index], vars2[index])) { + return false; + } + } + } + + return true; + } + + private static boolean tryStatementsAreEquivalent(JSTryStatement statement1, JSTryStatement statement2) { + if (!statementsAreEquivalent( + statement1.getStatement(), + statement2.getStatement() + )) { + return false; + } + if (!statementsAreEquivalent( + statement1.getFinallyStatement(), + statement2.getFinallyStatement() + )) { + return false; + } + JSCatchBlock catchBlock1 = statement1.getCatchBlock(); + JSCatchBlock catchBlock2 = statement2.getCatchBlock(); + if (catchBlock1 == null) { + return (catchBlock2 == null); + } + else if (catchBlock2 == null) { + return false; + } + + if (!parametersAreEquivalent( + catchBlock1.getParameter(), + catchBlock2.getParameter() + )) { + return false; + } + return statementsAreEquivalent( + catchBlock1.getStatement(), + catchBlock2.getStatement() + ); + } + + private static boolean localVariableAreEquivalent(JSVariable var1, JSVariable var2) { + return expressionsAreEquivalent(var1.getInitializer(), var2.getInitializer()) + && typesAreEquivalent(var1.getType(), var2.getType()) + && areEqual(var1.getName(), var2.getName()); + } + + private static boolean parametersAreEquivalent(JSParameter parameter1, JSParameter parameter2) { + return typesAreEquivalent(parameter1.getType(), parameter2.getType()) + && areEqual(parameter1.getName(), parameter2.getName()); + } + + private static boolean typesAreEquivalent(JavaScriptType type1, JavaScriptType type2) { + return areEqual(type1, type2); + } + + private static boolean whileStatementsAreEquivalent(JSWhileStatement statement1, JSWhileStatement statement2) { + return expressionsAreEquivalent(statement1.getCondition(), statement2.getCondition()) + && statementsAreEquivalent(statement1.getBody(), statement2.getBody()); + } + + private static boolean forStatementsAreEquivalent(JSForStatement statement1, JSForStatement statement2) { + return expressionsAreEquivalent(statement1.getCondition(), statement2.getCondition()) + && expressionsAreEquivalent(statement1.getInitialization(), statement2.getInitialization()) + && expressionsAreEquivalent(statement1.getUpdate(), statement2.getUpdate()) + && statementsAreEquivalent(statement1.getBody(), statement2.getBody()); + } + + private static boolean forInStatementsAreEquivalent(JSForInStatement statement1, JSForInStatement statement2) { + return expressionsAreEquivalent(statement1.getCollectionExpression(), statement2.getCollectionExpression()) + && expressionsAreEquivalent(statement1.getVariableExpression(), statement2.getVariableExpression()) + && declarationStatementsAreEquivalent(statement1.getDeclarationStatement(), statement2.getDeclarationStatement()) + && statementsAreEquivalent(statement1.getBody(), statement2.getBody()); + } + + private static boolean switchStatementsAreEquivalent(JSSwitchStatement statement1, JSSwitchStatement statement2) { + if (!expressionsAreEquivalent(statement1.getSwitchExpression(), statement2.getSwitchExpression())) { + return false; + } + + JSCaseClause[] caseClauses1 = statement1.getCaseClauses(); + JSCaseClause[] caseClauses2 = statement2.getCaseClauses(); + + if (caseClauses1.length != caseClauses2.length) { + return false; + } + + for (int index = 0; index < caseClauses1.length; index++) { + if (!caseClausesAreEquivalent(caseClauses1[index], caseClauses2[index])) { + return false; + } + } + + return true; + } + + private static boolean caseClausesAreEquivalent(JSCaseClause caseClause1, JSCaseClause caseClause2) { + if (caseClause1.isDefault() != caseClause2.isDefault()) { + return false; + } + if (!expressionsAreEquivalent(caseClause1.getCaseExpression(), caseClause2.getCaseExpression())) { + return false; + } + + JSStatement[] statements1 = caseClause1.getStatements(); + JSStatement[] statements2 = caseClause2.getStatements(); + + if (statements1.length != statements2.length) { + return false; + } + + for (int index = 0; index < statements1.length; index++) { + if (!statementsAreEquivalent(statements1[index], statements2[index])) { + return false; + } + } + + return false; + } + + private static boolean doWhileStatementsAreEquivalent(JSDoWhileStatement statement1, JSDoWhileStatement statement2) { + return (expressionsAreEquivalent(statement1.getCondition(), statement2.getCondition()) && + statementsAreEquivalent(statement1.getBody(), statement2.getBody())); + } + + private static boolean codeBlocksAreEquivalent(JSBlockStatement statement1, JSBlockStatement statement2) { + if (statement1 == null && statement2 == null) { + return true; + } + if (statement1 == null || statement2 == null) { + return false; + } + return blockStatementsAreEquivalent(statement1.getStatements(), statement2.getStatements()); + } + + private static boolean breakStatementsAreEquivalent(JSBreakStatement statement1, JSBreakStatement statement2) { + return areEqual(statement1.getLabel(), statement2.getLabel()); + } + + private static boolean continueStatementsAreEquivalent(JSContinueStatement statement1, JSContinueStatement statement2) { + return areEqual(statement1.getLabel(), statement2.getLabel()); + } + + private static boolean labeledStatementsAreEquivalent(JSLabeledStatement statement1, JSLabeledStatement statement2) { + PsiElement element1 = statement1.getLabelIdentifier(); + PsiElement element2 = statement2.getLabelIdentifier(); + + return element1 == null + ? element2 == null + : element2 != null && element1.getText().equals(element2.getText()); + } + + private static boolean blockStatementsAreEquivalent(JSStatement[] statements1, JSStatement[] statements2) { + if (statements1.length != statements2.length) { + return false; + } + for (int index = 0; index < statements1.length; index++) { + if (!statementsAreEquivalent(statements1[index], statements2[index])) { + return false; + } + } + return true; + } + + private static boolean ifStatementsAreEquivalent(JSIfStatement statement1, JSIfStatement statement2) { + return expressionsAreEquivalent(statement1.getCondition(), statement2.getCondition()) + && statementsAreEquivalent(statement1.getThen(), statement2.getThen()) + && statementsAreEquivalent(statement1.getElse(), statement2.getElse()); + } + + private static boolean expressionStatementsAreEquivalent(JSExpressionStatement statement1, JSExpressionStatement statement2) { + return expressionsAreEquivalent(statement1.getExpression(), statement2.getExpression()); + } + + private static boolean returnStatementsAreEquivalent(JSReturnStatement statement1, JSReturnStatement statement2) { + return expressionsAreEquivalent(statement1.getExpression(), statement2.getExpression()); + } + + private static boolean throwStatementsAreEquivalent(JSThrowStatement statement1, JSThrowStatement statement2) { + return expressionsAreEquivalent(statement1.getExpression(), statement2.getExpression()); + } + + private static boolean withStatementsAreEquivalent(JSWithStatement statement1, JSWithStatement statement2) { + return expressionsAreEquivalent(statement1.getExpression(), statement2.getExpression()) + && statementsAreEquivalent(statement1.getStatement(), statement2.getStatement()); + } + + public static boolean expressionsAreEquivalent(JSExpression exp1, JSExpression exp2) { + if (exp1 == null && exp2 == null) { + return true; + } + if (exp1 == null || exp2 == null) { + return false; + } + + JSExpression expToCompare1 = ParenthesesUtils.stripParentheses(exp1); + JSExpression expToCompare2 = ParenthesesUtils.stripParentheses(exp2); + int type1 = getExpressionType(expToCompare1); + int type2 = getExpressionType(expToCompare2); + + if (type1 != type2) { + return false; + } + switch (type1) { + case THIS_EXPRESSION: + case SUPER_EXPRESSION: + return true; + + case LITERAL_EXPRESSION: + case CLASS_OBJECT_EXPRESSION: + case REFERENCE_EXPRESSION: + case DEFINITION_EXPRESSION: + return expToCompare1.getText().equals(expToCompare2.getText()); + + case CALL_EXPRESSION: + return callExpressionsAreEquivalent((JSCallExpression)expToCompare1, (JSCallExpression)expToCompare2); + + case NEW_EXPRESSION: + return newExpressionsAreEquivalent((JSNewExpression)expToCompare1, (JSNewExpression)expToCompare2); + + case ARRAY_LITERAL_EXPRESSION: + return arrayLiteralExpressionsAreEquivalent( + (JSArrayLiteralExpression)expToCompare1, + (JSArrayLiteralExpression)expToCompare2 + ); + + case PREFIX_EXPRESSION: + return prefixExpressionsAreEquivalent((JSPrefixExpression)expToCompare1, (JSPrefixExpression)expToCompare2); + + case POSTFIX_EXPRESSION: + return postfixExpressionsAreEquivalent((JSPostfixExpression)expToCompare1, (JSPostfixExpression)expToCompare2); + + case BINARY_EXPRESSION: + return binaryExpressionsAreEquivalent((JSBinaryExpression)expToCompare1, (JSBinaryExpression)expToCompare2); + + case ASSIGNMENT_EXPRESSION: + return assignmentExpressionsAreEquivalent((JSAssignmentExpression)expToCompare1, (JSAssignmentExpression)expToCompare2); + + case CONDITIONAL_EXPRESSION: + return conditionalExpressionsAreEquivalent((JSConditionalExpression)expToCompare1, (JSConditionalExpression)expToCompare2); + + case INDEX_PROPERTY_ACCESS_EXPRESSION: + return indexedPropertyAccessExpressionsAreEquivalent( + (JSIndexedPropertyAccessExpression)expToCompare1, + (JSIndexedPropertyAccessExpression)expToCompare2 + ); + + case OBJECT_LITERAL_EXPRESSION: + return objectLiteralExpressionsAreEquivalent( + (JSObjectLiteralExpression)expToCompare1, + (JSObjectLiteralExpression)expToCompare2 + ); + + case FUNCTION_EXPRESSION: + return functionExpressionsAreEquivalent((JSFunctionExpression)expToCompare1, (JSFunctionExpression)expToCompare2); + + default: + return false; + } + } + + @SuppressWarnings({"UNUSED_SYMBOL"}) + private static boolean functionExpressionsAreEquivalent(JSFunctionExpression functionExp1, JSFunctionExpression functionExp2) { + return false; + } + + private static boolean objectLiteralExpressionsAreEquivalent( + JSObjectLiteralExpression objectLiteralExp1, + JSObjectLiteralExpression objectLiteralExp2 + ) { + JSProperty[] properties1 = objectLiteralExp1.getProperties(); + JSProperty[] properties2 = objectLiteralExp2.getProperties(); + + if (properties1.length != properties2.length) { + return false; + } + + for (int index = 0; index < properties2.length; index++) { + JSProperty property1 = properties1[index]; + JSProperty property2 = properties2[index]; + String propertyName1 = property1.getName(); + String propertyName2 = property2.getName(); + + if (!(propertyName1 != null && propertyName2 != null && + propertyName2.equals(propertyName1) && + expressionsAreEquivalent(property1.getValue(), property2.getValue()))) { + return false; + } + } + + return true; + } + + private static boolean indexedPropertyAccessExpressionsAreEquivalent( + JSIndexedPropertyAccessExpression exp1, + JSIndexedPropertyAccessExpression exp2 + ) { + return (expressionsAreEquivalent(exp1.getIndexExpression(), exp2.getIndexExpression()) && + expressionsAreEquivalent(exp1.getQualifier(), exp2.getQualifier())); + } + + private static boolean callExpressionsAreEquivalent(JSCallExpression methodExp1, JSCallExpression methodExp2) { + JSExpression exp1; + JSExpression exp2; + + try { + exp1 = methodExp1.getMethodExpression(); + exp2 = methodExp2.getMethodExpression(); + } + catch (Exception exception) { + return false; + } + + if (!expressionsAreEquivalent(exp1, exp2)) { + return false; + } + + JSArgumentList argumentList1 = methodExp1.getArgumentList(); + JSArgumentList argumentList2 = methodExp2.getArgumentList(); + + return argumentList1 != null && argumentList2 != null + && expressionListsAreEquivalent(argumentList1.getArguments(), argumentList2.getArguments()); + } + + private static boolean newExpressionsAreEquivalent(JSNewExpression newExp1, JSNewExpression newExp2) { + JSExpression exp1 = newExp1.getMethodExpression(); + JSExpression exp2 = newExp2.getMethodExpression(); + + if (!expressionsAreEquivalent(exp1, exp2)) { + return false; + } + + JSArgumentList argumentList1 = newExp1.getArgumentList(); + JSArgumentList argumentList2 = newExp2.getArgumentList(); + + return argumentList1 != null && argumentList2 != null + && expressionListsAreEquivalent(argumentList1.getArguments(), argumentList2.getArguments()); + } + + private static boolean arrayLiteralExpressionsAreEquivalent( + JSArrayLiteralExpression arrInitExp1, + JSArrayLiteralExpression arrInitExp2 + ) { + return expressionListsAreEquivalent(arrInitExp1.getExpressions(), arrInitExp2.getExpressions()); + } + + private static boolean prefixExpressionsAreEquivalent(JSPrefixExpression prefixExp1, JSPrefixExpression prefixExp2) { + IElementType operator1 = prefixExp1.getOperationSign(); + IElementType operator2 = prefixExp2.getOperationSign(); + + return (operator1 != null && operator2 != null && + operator1.equals(operator2) && + expressionsAreEquivalent(prefixExp1.getExpression(), prefixExp2.getExpression())); + } + + private static boolean postfixExpressionsAreEquivalent(JSPostfixExpression postfixExp1, JSPostfixExpression postfixExp2) { + IElementType operator1 = postfixExp1.getOperationSign(); + IElementType operator2 = postfixExp2.getOperationSign(); + + return operator1.equals(operator2) && expressionsAreEquivalent(postfixExp1.getExpression(), postfixExp2.getExpression()); + } + + private static boolean binaryExpressionsAreEquivalent(JSBinaryExpression binaryExp1, JSBinaryExpression binaryExp2) { + IElementType operator1 = binaryExp1.getOperationSign(); + IElementType operator2 = binaryExp2.getOperationSign(); + + return operator1.equals(operator2) + && expressionsAreEquivalent(binaryExp1.getLOperand(), binaryExp2.getLOperand()) + && expressionsAreEquivalent(binaryExp1.getROperand(), binaryExp2.getROperand()); + } + + private static boolean assignmentExpressionsAreEquivalent(JSAssignmentExpression assignExp1, JSAssignmentExpression assignExp2) { + IElementType operator1 = assignExp1.getOperationSign(); + IElementType operator2 = assignExp2.getOperationSign(); + + return operator1.equals(operator2) + && expressionsAreEquivalent(assignExp1.getLOperand(), assignExp2.getLOperand()) + && expressionsAreEquivalent(assignExp1.getROperand(), assignExp2.getROperand()); + } + + private static boolean conditionalExpressionsAreEquivalent(JSConditionalExpression condExp1, JSConditionalExpression condExp2) { + return expressionsAreEquivalent(condExp1.getCondition(), condExp2.getCondition()) + && expressionsAreEquivalent(condExp1.getThen(), condExp2.getThen()) + && expressionsAreEquivalent(condExp1.getElse(), condExp2.getElse()); + } + + private static boolean expressionListsAreEquivalent(JSExpression[] expressions1, JSExpression[] expressions2) { + if (expressions1 == null && expressions2 == null) { + return true; + } + + if (expressions1 == null || expressions2 == null) { + return false; + } + if (expressions1.length != expressions2.length) { + return false; + } + + for (int index = 0; index < expressions1.length; index++) { + if (!expressionsAreEquivalent(expressions1[index], expressions2[index])) { + return false; + } + } + return true; + } + + private static boolean areEqual(Object o1, Object o2) { + return o1 == null ? o2 == null : o1.equals(o2); + } + + private static int getExpressionType(JSExpression exp) { + if (exp instanceof JSThisExpression) { + return THIS_EXPRESSION; + } + if (exp instanceof JSLiteralExpression) { + return LITERAL_EXPRESSION; + } + if (exp instanceof JSReferenceExpression) { + return REFERENCE_EXPRESSION; + } + if (exp instanceof JSNewExpression) { + return NEW_EXPRESSION; + } + if (exp instanceof JSCallExpression) { + return CALL_EXPRESSION; + } + if (exp instanceof JSArrayLiteralExpression) { + return ARRAY_LITERAL_EXPRESSION; + } + if (exp instanceof JSPrefixExpression) { + return PREFIX_EXPRESSION; + } + if (exp instanceof JSPostfixExpression) { + return POSTFIX_EXPRESSION; + } + if (exp instanceof JSAssignmentExpression) { + return ASSIGNMENT_EXPRESSION; + } + if (exp instanceof JSBinaryExpression) { + return BINARY_EXPRESSION; + } + if (exp instanceof JSConditionalExpression) { + return CONDITIONAL_EXPRESSION; + } + if (exp instanceof JSIndexedPropertyAccessExpression) { + return INDEX_PROPERTY_ACCESS_EXPRESSION; + } + if (exp instanceof JSFunctionExpression) { + return FUNCTION_EXPRESSION; + } + if (exp instanceof JSObjectLiteralExpression) { + return OBJECT_LITERAL_EXPRESSION; + } + if (exp instanceof JSDefinitionExpression) { + return DEFINITION_EXPRESSION; + } + return -1; + } + + private static int getStatementType(JSStatement statement) { + if (statement instanceof JSBlockStatement) { + return BLOCK_STATEMENT; + } + if (statement instanceof JSBreakStatement) { + return BREAK_STATEMENT; + } + if (statement instanceof JSContinueStatement) { + return CONTINUE_STATEMENT; + } + if (statement instanceof JSVarStatement) { + return VAR_STATEMENT; + } + if (statement instanceof JSDoWhileStatement) { + return DO_WHILE_STATEMENT; + } + if (statement instanceof JSEmptyStatement) { + return EMPTY_STATEMENT; + } + if (statement instanceof JSExpressionStatement) { + return EXPRESSION_STATEMENT; + } + if (statement instanceof JSForStatement) { + return FOR_STATEMENT; + } + if (statement instanceof JSForInStatement) { + return FOR_IN_STATEMENT; + } + if (statement instanceof JSIfStatement) { + return IF_STATEMENT; + } + if (statement instanceof JSLabeledStatement) { + return LABELED_STATEMENT; + } + if (statement instanceof JSReturnStatement) { + return RETURN_STATEMENT; + } + if (statement instanceof JSSwitchStatement) { + return SWITCH_STATEMENT; + } + if (statement instanceof JSThrowStatement) { + return THROW_STATEMENT; + } + if (statement instanceof JSTryStatement) { + return TRY_STATEMENT; + } + if (statement instanceof JSWhileStatement) { + return WHILE_STATEMENT; + } + if (statement instanceof JSWithStatement) { + return WITH_STATEMENT; + } + return -1; + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ErrorUtil.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ErrorUtil.java index ffa37cf4..62050497 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ErrorUtil.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ErrorUtil.java @@ -19,46 +19,37 @@ import consulo.language.psi.PsiElement; import consulo.language.psi.PsiErrorElement; import consulo.language.psi.PsiRecursiveElementVisitor; - -import javax.annotation.Nonnull; - -public class ErrorUtil -{ - private ErrorUtil() - { - } - - private static final boolean fullTraversal = false; - - public static boolean containsError(@Nonnull PsiElement element) - { - // check only immediate children, full tree traversal is too expensive - if(fullTraversal) - { - final ErrorElementVisitor visitor = new ErrorElementVisitor(); - - element.accept(visitor); - return visitor.containsErrorElement(); - } - else - { - return PsiUtilBase.hasErrorElementChild(element); - } - } - - private static class ErrorElementVisitor extends PsiRecursiveElementVisitor - { - private boolean containsErrorElement; - - @Override - public void visitErrorElement(PsiErrorElement element) - { - this.containsErrorElement = true; - } - - private boolean containsErrorElement() - { - return this.containsErrorElement; - } - } +import jakarta.annotation.Nonnull; + +public class ErrorUtil { + private ErrorUtil() { + } + + private static final boolean fullTraversal = false; + + public static boolean containsError(@Nonnull PsiElement element) { + // check only immediate children, full tree traversal is too expensive + if (fullTraversal) { + ErrorElementVisitor visitor = new ErrorElementVisitor(); + + element.accept(visitor); + return visitor.containsErrorElement(); + } + else { + return PsiUtilBase.hasErrorElementChild(element); + } + } + + private static class ErrorElementVisitor extends PsiRecursiveElementVisitor { + private boolean containsErrorElement; + + @Override + public void visitErrorElement(PsiErrorElement element) { + this.containsErrorElement = true; + } + + private boolean containsErrorElement() { + return this.containsErrorElement; + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ExpressionUtil.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ExpressionUtil.java index 29ce3d62..f4a9d1d5 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ExpressionUtil.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ExpressionUtil.java @@ -21,209 +21,176 @@ import consulo.language.ast.IElementType; import consulo.language.psi.PsiElement; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; + import java.util.HashMap; import java.util.Map; -public class ExpressionUtil -{ - - private ExpressionUtil() - { - } - - public static boolean isConstantExpression(JSExpression expression) - { - if(expression == null) - { - return false; - } - IsConstantExpressionVisitor visitor = new IsConstantExpressionVisitor(); - expression.accept(visitor); - return visitor.isConstant; - } - - public static boolean isIncrementDecrementExpression(@Nonnull PsiElement expression) - { - if(expression instanceof JSPostfixExpression) - { - final IElementType operator = ((JSPostfixExpression) expression).getOperationSign(); - return (JSTokenTypes.PLUSPLUS.equals(operator) || JSTokenTypes.MINUSMINUS.equals(operator)); - } - else if(expression instanceof JSPrefixExpression) - { - final IElementType operator = ((JSPrefixExpression) expression).getOperationSign(); - return (JSTokenTypes.PLUSPLUS.equals(operator) || JSTokenTypes.MINUSMINUS.equals(operator)); - } - else - { - return false; - } - } - - public static class IsConstantExpressionVisitor extends JSElementVisitor - { - protected boolean isConstant; - private final Map isVariableConstant = new HashMap(); - - public boolean isConstant() - { - return this.isConstant; - } - - @Override - public void visitJSExpression(JSExpression expression) - { - this.isConstant = false; - } - - @Override - public void visitJSLiteralExpression(JSSimpleLiteralExpression expression) - { - this.isConstant = true; - } - - @Override - public void visitJSParenthesizedExpression(JSParenthesizedExpression expression) - { - JSExpression expr = expression.getInnerExpression(); - if(expr != null) - { - expr.accept(this); - } - } - - @Override - public void visitJSPrefixExpression(JSPrefixExpression expression) - { - this.visitJSPrefixOrPostfixExpression(expression.getExpression(), expression.getOperationSign()); - } - - @Override - public void visitJSPostfixExpression(JSPostfixExpression expression) - { - this.visitJSPrefixOrPostfixExpression(expression.getExpression(), expression.getOperationSign()); - } - - public void visitJSPrefixOrPostfixExpression(JSExpression operand, IElementType sign) - { - if(operand == null) - { - this.isConstant = false; - return; - } - - operand.accept(this); - if(!this.isConstant) - { - return; - } - - if(sign == JSTokenTypes.PLUS || - sign == JSTokenTypes.MINUS || - sign == JSTokenTypes.TILDE || - sign == JSTokenTypes.EXCL) - { - return; - } - this.isConstant = false; - } - - @Override - public void visitJSBinaryExpression(JSBinaryExpression expression) - { - final JSExpression jsExpression = expression.getLOperand(); - if(jsExpression == null) - { - return; - } - jsExpression.accept(this); - if(!this.isConstant) - { - return; - } - JSExpression rOperand = expression.getROperand(); - if(rOperand != null) - { - rOperand.accept(this); - } - } - - @Override - public void visitJSConditionalExpression(JSConditionalExpression expression) - { - JSExpression thenExpr = expression.getThen(); - JSExpression elseExpr = expression.getElse(); - if(thenExpr == null || elseExpr == null) - { - this.isConstant = false; - return; - } - - expression.getCondition().accept(this); - if(!this.isConstant) - { - return; - } - thenExpr.accept(this); - if(!this.isConstant) - { - return; - } - elseExpr.accept(this); - } - - @Override - public void visitJSReferenceExpression(JSReferenceExpression expression) - { - JSElement refElement = (JSElement) expression.resolve(); - - if(!(refElement instanceof JSVariable)) - { - this.isConstant = false; - return; - } - - JSVariable variable = (JSVariable) refElement; - Boolean isConst = this.isVariableConstant.get(variable); - - if(isConst != null) - { - this.isConstant &= isConst; - return; - } - - this.isVariableConstant.put(variable, Boolean.FALSE); - this.isConstant = false; - } - } - - @Nullable - public static Object computeConstantExpression(JSExpression expression) - { - if(expression == null) - { - return null; - } - - //try { - // final PsiManager manager = expression.getManager(); - // final PsiElementFactory factory = manager.getElementFactory(); - // final PsiConstantEvaluationHelper helper = manager.getConstantEvaluationHelper(); - // PsiExpression expr = factory.createExpressionFromText(expression.getText(), expression); - // final PsiType exprType = expr.getType(); - // - // if (exprType != null && exprType.equals(PsiType.INT)) { - // expr = factory.createExpressionFromText("(long)" + expression.getText(), expression); - // } - // - // return helper.computeConstantExpression(expr); - //} catch (IncorrectOperationException e) { - // return null; - //} - - // TODO: constant expressions are not evaluated by PsiManager et al - return null; - } +public class ExpressionUtil { + private ExpressionUtil() { + } + + public static boolean isConstantExpression(JSExpression expression) { + if (expression == null) { + return false; + } + IsConstantExpressionVisitor visitor = new IsConstantExpressionVisitor(); + expression.accept(visitor); + return visitor.isConstant; + } + + public static boolean isIncrementDecrementExpression(@Nonnull PsiElement expression) { + if (expression instanceof JSPostfixExpression postfixExpression) { + IElementType operator = postfixExpression.getOperationSign(); + return JSTokenTypes.PLUSPLUS.equals(operator) || JSTokenTypes.MINUSMINUS.equals(operator); + } + else if (expression instanceof JSPrefixExpression prefixExpression) { + IElementType operator = prefixExpression.getOperationSign(); + return JSTokenTypes.PLUSPLUS.equals(operator) || JSTokenTypes.MINUSMINUS.equals(operator); + } + else { + return false; + } + } + + public static class IsConstantExpressionVisitor extends JSElementVisitor { + protected boolean isConstant; + private final Map isVariableConstant = new HashMap<>(); + + public boolean isConstant() { + return this.isConstant; + } + + @Override + public void visitJSExpression(JSExpression expression) { + this.isConstant = false; + } + + @Override + public void visitJSLiteralExpression(JSSimpleLiteralExpression expression) { + this.isConstant = true; + } + + @Override + public void visitJSParenthesizedExpression(JSParenthesizedExpression expression) { + JSExpression expr = expression.getInnerExpression(); + if (expr != null) { + expr.accept(this); + } + } + + @Override + public void visitJSPrefixExpression(JSPrefixExpression expression) { + this.visitJSPrefixOrPostfixExpression(expression.getExpression(), expression.getOperationSign()); + } + + @Override + public void visitJSPostfixExpression(JSPostfixExpression expression) { + this.visitJSPrefixOrPostfixExpression(expression.getExpression(), expression.getOperationSign()); + } + + public void visitJSPrefixOrPostfixExpression(JSExpression operand, IElementType sign) { + if (operand == null) { + this.isConstant = false; + return; + } + + operand.accept(this); + if (!this.isConstant) { + return; + } + + if (sign == JSTokenTypes.PLUS || + sign == JSTokenTypes.MINUS || + sign == JSTokenTypes.TILDE || + sign == JSTokenTypes.EXCL) { + return; + } + this.isConstant = false; + } + + @Override + public void visitJSBinaryExpression(JSBinaryExpression expression) { + JSExpression jsExpression = expression.getLOperand(); + if (jsExpression == null) { + return; + } + jsExpression.accept(this); + if (!this.isConstant) { + return; + } + JSExpression rOperand = expression.getROperand(); + if (rOperand != null) { + rOperand.accept(this); + } + } + + @Override + public void visitJSConditionalExpression(JSConditionalExpression expression) { + JSExpression thenExpr = expression.getThen(); + JSExpression elseExpr = expression.getElse(); + if (thenExpr == null || elseExpr == null) { + this.isConstant = false; + return; + } + + expression.getCondition().accept(this); + if (!this.isConstant) { + return; + } + thenExpr.accept(this); + if (!this.isConstant) { + return; + } + elseExpr.accept(this); + } + + @Override + public void visitJSReferenceExpression(JSReferenceExpression expression) { + JSElement refElement = (JSElement)expression.resolve(); + + if (!(refElement instanceof JSVariable)) { + this.isConstant = false; + return; + } + + JSVariable variable = (JSVariable)refElement; + Boolean isConst = this.isVariableConstant.get(variable); + + if (isConst != null) { + this.isConstant &= isConst; + return; + } + + this.isVariableConstant.put(variable, Boolean.FALSE); + this.isConstant = false; + } + } + + @Nullable + public static Object computeConstantExpression(JSExpression expression) { + if (expression == null) { + return null; + } + + //try { + // final PsiManager manager = expression.getManager(); + // final PsiElementFactory factory = manager.getElementFactory(); + // final PsiConstantEvaluationHelper helper = manager.getConstantEvaluationHelper(); + // PsiExpression expr = factory.createExpressionFromText(expression.getText(), expression); + // final PsiType exprType = expr.getType(); + // + // if (exprType != null && exprType.equals(PsiType.INT)) { + // expr = factory.createExpressionFromText("(long)" + expression.getText(), expression); + // } + // + // return helper.computeConstantExpression(expr); + //} catch (IncorrectOperationException e) { + // return null; + //} + + // TODO: constant expressions are not evaluated by PsiManager et al + return null; + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/FindReferenceUtil.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/FindReferenceUtil.java index d81294d0..46db52b5 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/FindReferenceUtil.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/FindReferenceUtil.java @@ -22,193 +22,163 @@ import consulo.language.psi.PsiElement; import consulo.language.psi.util.PsiTreeUtil; import consulo.xml.psi.xml.XmlFile; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; import org.intellij.idea.lang.javascript.intention.JSElementIterator; import org.intellij.idea.lang.javascript.intention.JSFunctionVisitor; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Iterator; import java.util.List; -public class FindReferenceUtil -{ - private FindReferenceUtil() - { - } - - public static JSReferenceExpression[] findReferences(@Nonnull JSVariable variable) - { - final JSReferenceVisitor visitor = new JSReferenceVisitor(variable, Integer.MAX_VALUE, 0, Integer.MAX_VALUE); - JSElement scope = PsiTreeUtil.getParentOfType(variable, JSFunction.class); - - if(scope == null) - { - scope = getFarthestAncestor(variable, JSElement.class); - } - visitor.visitJSElement(scope); - - return visitor.getReferences(); - } - - public static T getFarthestAncestor(@Nonnull PsiElement element, @Nonnull Class aClass) - { - PsiElement previousElement = element; - PsiElement currentElement; - - do - { - currentElement = previousElement.getParent(); - if(!aClass.isInstance(currentElement)) - { - //noinspection unchecked - return (T) previousElement; - } - previousElement = currentElement; - } - while(currentElement != null); - - return null; - } - - private static final class JSReferenceVisitor extends JSFunctionVisitor - { - private final JSVariable variable; - private final String variableName; - private final int maxCount; - private final int minTextOffset; - private final int maxTextOffset; - private List references; - - public JSReferenceVisitor(@Nonnull JSVariable variable, int maxCount, int minTextOffset, int maxTextOffset) - { - this.variable = variable; - this.variableName = variable.getName(); - this.maxCount = maxCount; - this.minTextOffset = minTextOffset; - this.maxTextOffset = maxTextOffset; - this.references = new ArrayList(); - } - - @Override - public void visitElement(PsiElement element) - { - if(this.references.size() < this.maxCount) - { - final int elementTextOffset = element.getTextOffset(); - - if(elementTextOffset + element.getTextLength() >= this.minTextOffset && - elementTextOffset <= this.maxTextOffset) - { - super.visitElement(element); - } - } - } - - @Override - public void visitJSReferenceExpression(final JSReferenceExpression expression) - { - super.visitJSReferenceExpression(expression); - - if(expression.getText().equals(this.variableName)) - { - final JSVariable referent = ControlFlowUtils.resolveVariable(expression); - - if(referent != null && this.variable.equals(referent)) - { - this.references.add(expression); - } - } - } - - public JSReferenceExpression[] getReferences() - { - return this.references.toArray(new JSReferenceExpression[this.references.size()]); - } - - public JSReferenceExpression getReference(int index) - { - return ((index >= 0 && index < this.references.size()) - ? this.references.get(index) - : null); - } - } - - - public static Iterable getReferences(@Nonnull JSVariable variable) - { - return getReferences(variable, null, 0, Integer.MAX_VALUE); - } - - public static Iterable getReferences(@Nonnull JSVariable variable, - @Nullable PsiElement scope) - { - return getReferences(variable, scope, 0, Integer.MAX_VALUE); - } - - public static Iterable getReferencesBefore(@Nonnull JSVariable variable, int textOffset) - { - return getReferences(variable, null, 0, textOffset); - } - - public static Iterable getReferencesAfter(@Nonnull JSVariable variable, int textOffset) - { - return getReferences(variable, null, textOffset, Integer.MAX_VALUE); - } - - private static Iterable getReferences(@Nonnull final JSVariable variable, - @Nullable final PsiElement scope, - final int minTextOffset, final int maxTextOffset) - { - final PsiElement iteratedScope; - - if(scope == null) - { - JSElement function = PsiTreeUtil.getParentOfType(variable, JSFunction.class); - iteratedScope = ((function == null) ? FindReferenceUtil.getFarthestAncestor(variable, XmlFile.class) - : function); - } - else - { - iteratedScope = scope; - } - - return new Iterable() - { - @Override - public Iterator iterator() - { - return new JSReferenceIterator(variable, minTextOffset, maxTextOffset, iteratedScope); - } - }; - } - - public static final class JSReferenceIterator extends JSElementIterator - { - private final JSVariable variable; - private final String variableName; - - public JSReferenceIterator(@Nonnull JSVariable variable, - int minTextOffset, int maxTextOffset, - @Nonnull PsiElement element) - { - super(element, false, minTextOffset, maxTextOffset); - this.variable = variable; - this.variableName = variable.getName(); - } - - @Override - public boolean visitElement(PsiElement element) - { - if(!(element.getText().equals(this.variableName) && - element instanceof JSReferenceExpression)) - { - return false; - } - - final JSVariable referent = ControlFlowUtils.resolveVariable((JSReferenceExpression) element); - - return (referent != null && this.variable.equals(referent)); - } - } +public class FindReferenceUtil { + private FindReferenceUtil() { + } + + public static JSReferenceExpression[] findReferences(@Nonnull JSVariable variable) { + JSReferenceVisitor visitor = new JSReferenceVisitor(variable, Integer.MAX_VALUE, 0, Integer.MAX_VALUE); + JSElement scope = PsiTreeUtil.getParentOfType(variable, JSFunction.class); + + if (scope == null) { + scope = getFarthestAncestor(variable, JSElement.class); + } + visitor.visitJSElement(scope); + + return visitor.getReferences(); + } + + public static T getFarthestAncestor(@Nonnull PsiElement element, @Nonnull Class aClass) { + PsiElement previousElement = element; + PsiElement currentElement; + + do { + currentElement = previousElement.getParent(); + if (!aClass.isInstance(currentElement)) { + //noinspection unchecked + return (T)previousElement; + } + previousElement = currentElement; + } + while (currentElement != null); + + return null; + } + + private static final class JSReferenceVisitor extends JSFunctionVisitor { + private final JSVariable variable; + private final String variableName; + private final int maxCount; + private final int minTextOffset; + private final int maxTextOffset; + private List references; + + public JSReferenceVisitor(@Nonnull JSVariable variable, int maxCount, int minTextOffset, int maxTextOffset) { + this.variable = variable; + this.variableName = variable.getName(); + this.maxCount = maxCount; + this.minTextOffset = minTextOffset; + this.maxTextOffset = maxTextOffset; + this.references = new ArrayList<>(); + } + + @Override + public void visitElement(PsiElement element) { + if (this.references.size() < this.maxCount) { + int elementTextOffset = element.getTextOffset(); + + if (elementTextOffset + element.getTextLength() >= this.minTextOffset && + elementTextOffset <= this.maxTextOffset) { + super.visitElement(element); + } + } + } + + @Override + public void visitJSReferenceExpression(JSReferenceExpression expression) { + super.visitJSReferenceExpression(expression); + + if (expression.getText().equals(this.variableName)) { + JSVariable referent = ControlFlowUtils.resolveVariable(expression); + + if (referent != null && this.variable.equals(referent)) { + this.references.add(expression); + } + } + } + + public JSReferenceExpression[] getReferences() { + return this.references.toArray(new JSReferenceExpression[this.references.size()]); + } + + public JSReferenceExpression getReference(int index) { + return index >= 0 && index < this.references.size() + ? this.references.get(index) + : null; + } + } + + + public static Iterable getReferences(@Nonnull JSVariable variable) { + return getReferences(variable, null, 0, Integer.MAX_VALUE); + } + + public static Iterable getReferences(@Nonnull JSVariable variable, @Nullable PsiElement scope) { + return getReferences(variable, scope, 0, Integer.MAX_VALUE); + } + + public static Iterable getReferencesBefore(@Nonnull JSVariable variable, int textOffset) { + return getReferences(variable, null, 0, textOffset); + } + + public static Iterable getReferencesAfter(@Nonnull JSVariable variable, int textOffset) { + return getReferences(variable, null, textOffset, Integer.MAX_VALUE); + } + + private static Iterable getReferences( + @Nonnull JSVariable variable, + @Nullable PsiElement scope, + int minTextOffset, + int maxTextOffset + ) { + PsiElement iteratedScope; + + if (scope == null) { + JSElement function = PsiTreeUtil.getParentOfType(variable, JSFunction.class); + iteratedScope = function == null + ? FindReferenceUtil.getFarthestAncestor(variable, XmlFile.class) + : function; + } + else { + iteratedScope = scope; + } + + return () -> new JSReferenceIterator(variable, minTextOffset, maxTextOffset, iteratedScope); + } + + public static final class JSReferenceIterator extends JSElementIterator { + private final JSVariable variable; + private final String variableName; + + public JSReferenceIterator( + @Nonnull JSVariable variable, + int minTextOffset, + int maxTextOffset, + @Nonnull PsiElement element + ) { + super(element, false, minTextOffset, maxTextOffset); + this.variable = variable; + this.variableName = variable.getName(); + } + + @Override + public boolean visitElement(PsiElement element) { + if (!(element.getText().equals(this.variableName) && element instanceof JSReferenceExpression)) { + return false; + } + + JSVariable referent = ControlFlowUtils.resolveVariable((JSReferenceExpression)element); + + return referent != null && this.variable.equals(referent); + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/JSElementFactory.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/JSElementFactory.java index c14ce614..3fd24921 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/JSElementFactory.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/JSElementFactory.java @@ -33,360 +33,306 @@ import consulo.virtualFileSystem.VirtualFile; import org.jetbrains.annotations.NonNls; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * */ -public class JSElementFactory -{ - private static final Class[] WHITESPACE_CLASS = new Class[]{PsiWhiteSpace.class}; - - private JSElementFactory() - { - } - - public static PsiElement addElementBefore(@Nonnull PsiElement element, - @Nonnull PsiElement newElement) - { - final ASTNode oldElementParentNode = element.getNode(); - final PsiElement parentNode = element.getParent(); - final ASTNode newElementParentNode = parentNode.getNode(); - final ASTNode newElementNode = newElement.getNode(); - - if(newElementParentNode == null || newElementNode == null) - { - return null; - } - newElementParentNode.addChild(newElementNode, oldElementParentNode); - return newElement; - } - - public static PsiElement addElementAfter(@Nonnull PsiElement element, - @Nonnull PsiElement newElement) - { - final ASTNode elementNode = element.getNode(); - final ASTNode oldElementParentNode = ((elementNode == null) ? null : elementNode.getTreeNext()); - final PsiElement parentNode = element.getParent(); - final ASTNode newElementParentNode = parentNode.getNode(); - final ASTNode newElementNode = newElement.getNode(); - - if(newElementParentNode == null || newElementNode == null) - { - return null; - } - newElementParentNode.addChild(newElementNode, oldElementParentNode); - - return newElement; - } - - public static PsiElement addElementBefore(@Nonnull PsiElement element, - @NonNls @Nonnull String elementText) - { - final PsiElement newElement = createDummyFile(element.getProject(), elementText).getFirstChild(); - - assert (newElement != null); - return addElementBefore(element, newElement); - } - - public static PsiElement addElementAfter(@Nonnull PsiElement element, - @Nonnull String elementText) - { - final PsiElement newElement = createDummyFile(element.getProject(), elementText).getFirstChild(); - - assert (newElement != null); - return addElementAfter(element, newElement); - } - - public static ASTNode createElementFromText(Project project, String text) - { - final PsiElement element = createDummyFile(project, text).getFirstChild(); - - assert (element != null); - return element.getNode(); - } - - @Nonnull - private static PsiFile createDummyFile(Project project, String text) - { - final ParserDefinition def = ParserDefinition.forLanguage(JavaScriptLanguage.INSTANCE); - - assert (def != null); - return PsiFileFactory.getInstance(project) - .createFileFromText("dummy.js", text); - } - - public static JSStatement replaceElementWithStatement(@Nonnull JSElement element, - @NonNls @Nonnull String statementText) - throws IncorrectOperationException - { - final ASTNode newStatementNode = JSChangeUtil.createStatementFromText( - element.getProject(), - statementText); - - final ASTNode oldStatementParentNode = element.getNode(); - final PsiElement parentNode = element.getParent(); - final ASTNode newStatementParentNode = parentNode.getNode(); - - if(newStatementParentNode == null || oldStatementParentNode == null || newStatementNode == null) - { - return null; - } - newStatementParentNode.replaceChild(oldStatementParentNode, newStatementNode); - reformat(parentNode); - - return (JSStatement) newStatementNode.getPsi(); - } - - public static JSExpression replaceExpression(@Nonnull JSExpression expression, - @NonNls @Nonnull String text) - throws IncorrectOperationException - { - final JSExpression newExpressionNode = JSChangeUtil.createExpressionFromText( - expression.getProject(), - text); - - return replaceExpression(expression, newExpressionNode); - } - - public static JSExpression replaceExpression(@Nonnull JSExpression expression, - @Nonnull JSExpression newExpression) - throws IncorrectOperationException - { - final ASTNode newExpressionNode = newExpression.getNode(); - final ASTNode oldExpressionNode = expression.getNode(); - final PsiElement parentNode = expression.getParent(); - final ASTNode grandParentNode = parentNode.getNode(); - - if(grandParentNode == null || oldExpressionNode == null || newExpressionNode == null) - { - return null; - } - - grandParentNode.replaceChild(oldExpressionNode, newExpressionNode); - reformat(parentNode); - - return (JSExpression) newExpressionNode.getPsi(); - } - - public static JSStatement replaceStatement(@Nonnull JSStatement statement, - @NonNls @Nonnull String text) - throws IncorrectOperationException - { - final ASTNode newStatementNode = JSChangeUtil.createStatementFromText( - statement.getProject(), - text); - - final ASTNode oldStatementParentNode = statement.getNode(); - final PsiElement parentNode = statement.getParent(); - final ASTNode newStatementParentNode = parentNode.getNode(); - - if(newStatementParentNode == null || oldStatementParentNode == null || newStatementNode == null) - { - return null; - } - - newStatementParentNode.replaceChild(oldStatementParentNode, newStatementNode); - reformat(parentNode); - - return (JSStatement) newStatementNode.getPsi(); - } - - public static JSStatement addStatementBefore(@Nonnull JSStatement statement, - @NonNls @Nonnull String previousStatementText) - throws IncorrectOperationException - { - final ASTNode newStatementNode = JSChangeUtil.createStatementFromText( - statement.getProject(), - previousStatementText); - final ASTNode oldStatementParentNode = statement.getNode(); - final PsiElement parentNode = statement.getParent(); - final ASTNode newStatementParentNode = parentNode.getNode(); - - if(newStatementParentNode == null || newStatementNode == null) - { - return null; - } - - newStatementParentNode.addChild(newStatementNode, oldStatementParentNode); - reformat(parentNode); - - return (JSStatement) newStatementNode.getPsi(); - } - - public static JSStatement addStatementAfter(@Nonnull JSStatement statement, - @NonNls @Nonnull String nextStatementText) - throws IncorrectOperationException - { - final ASTNode newStatementNode = JSChangeUtil.createStatementFromText( - statement.getProject(), - nextStatementText); - final ASTNode statementNode = statement.getNode(); - final ASTNode oldStatementParentNode = ((statementNode == null) ? null : statementNode.getTreeNext()); - final PsiElement parentNode = statement.getParent(); - final ASTNode newStatementParentNode = parentNode.getNode(); - - if(newStatementParentNode == null || newStatementNode == null) - { - return null; - } - - newStatementParentNode.addChild(newStatementNode, oldStatementParentNode); - reformat(parentNode); - - return (JSStatement) newStatementNode.getPsi(); - } - - public static void addRangeBefore(JSStatement[] statements, JSStatement statement) - throws IncorrectOperationException - { - addRangeBefore(statements, 0, statements.length, statement); - } - - public static void addRangeAfter(JSStatement[] statements, JSStatement statement) - throws IncorrectOperationException - { - addRangeAfter(statements, 0, statements.length, statement); - } - - @SuppressWarnings({"ForLoopWithMissingComponent"}) - public static void addRangeBefore(JSStatement[] statements, int start, int length, JSStatement statement) - throws IncorrectOperationException - { - for(int index = start; index < length; index++) - { - addStatementBefore(statement, statements[index].getText()); - } - } - - @SuppressWarnings({"ForLoopWithMissingComponent"}) - public static void addRangeAfter(JSStatement[] statements, int start, int length, JSStatement statement) - throws IncorrectOperationException - { - for(int index = length; --index >= start; ) - { - addStatementAfter(statement, statements[index].getText()); - } - } - - public static void replaceExpressionWithNegatedExpression(@Nonnull JSExpression newExpression, - @Nonnull JSExpression exp) - throws IncorrectOperationException - { - JSExpression expressionToReplace = BoolUtils.findNegation(exp); - final String replacementString; - - if(expressionToReplace == null) - { - expressionToReplace = exp; - - if(ComparisonUtils.isComparisonOperator(newExpression)) - { - final JSBinaryExpression binaryExpression = (JSBinaryExpression) newExpression; - final IElementType operationSign = binaryExpression.getOperationSign(); - final String negatedComparison = ComparisonUtils.getNegatedOperatorText(operationSign); - final JSExpression leftOperand = binaryExpression.getLOperand(); - final JSExpression rightOperand = binaryExpression.getROperand(); - - assert (rightOperand != null); - - replacementString = leftOperand.getText() + negatedComparison + rightOperand.getText(); - } - else - { - replacementString = '!' + ParenthesesUtils.getParenthesized(newExpression, ParenthesesUtils.PREFIX_PRECENDENCE); - } - } - else - { - replacementString = newExpression.getText(); - } - replaceExpression(expressionToReplace, replacementString); - } - - public static void replaceExpressionWithNegatedExpressionString(JSExpression exp, String newExpression) - throws IncorrectOperationException - { - assert (exp != null); - - JSExpression expressionToReplace = BoolUtils.findNegation(exp); - String replacementString = newExpression; - - if(expressionToReplace == null) - { - expressionToReplace = exp; - replacementString = "!(" + newExpression + ')'; - } - - replaceExpression(expressionToReplace, replacementString); - } - - - public static void replaceStatementWithUnwrapping(JSStatement statement, JSStatement newBranch) - throws IncorrectOperationException - { - if(!(newBranch instanceof JSBlockStatement)) - { - JSElementFactory.replaceStatement(statement, newBranch.getText()); - return; - } - - final JSBlockStatement parentBlock = PsiTreeUtil.getParentOfType(newBranch, JSBlockStatement.class); - - if(parentBlock == null) - { - JSElementFactory.replaceStatement(statement, newBranch.getText()); - return; - } - - final JSBlockStatement block = (JSBlockStatement) newBranch; - - if(ControlFlowUtils.containsConflictingDeclarations(block, parentBlock)) - { - JSElementFactory.replaceStatement(statement, newBranch.getText()); - return; - } - - final PsiElement containingElement = statement.getParent(); - - assert (containingElement instanceof JSStatement); - - JSElementFactory.addRangeBefore(block.getStatements(), statement); - JSElementFactory.removeElement(statement); - } - - public static void removeElement(PsiElement element) - { - final ASTNode node = element.getNode(); - final ASTNode parentNode = element.getParent().getNode(); - - if(node != null && parentNode != null) - { - parentNode.removeChild(node); - } - } - - public static void reformat(PsiElement statement) throws IncorrectOperationException - { - // Reformat only in .js files due to a bug in JavaScript reformatting module when doing it in JSP files - if(statement.getContainingFile() instanceof JSFile) - { - CodeStyleManager.getInstance(statement.getProject()).reformat(statement); - } - } - - public static PsiElement getNonWhiteSpaceSibling(PsiElement element, boolean forward) - { - return forward - ? PsiTreeUtil.skipSiblingsForward(element, WHITESPACE_CLASS) - : PsiTreeUtil.skipSiblingsBackward(element, WHITESPACE_CLASS); - } - - public static boolean isFileReadOnly(Project project, PsiFile file) - { - final ReadonlyStatusHandler instance = ReadonlyStatusHandler.getInstance(project); - final VirtualFile virtualFile = file.getVirtualFile(); - - return virtualFile != null && instance.ensureFilesWritable(virtualFile).hasReadonlyFiles(); - } +public class JSElementFactory { + private static final Class[] WHITESPACE_CLASS = new Class[]{PsiWhiteSpace.class}; + + private JSElementFactory() { + } + + public static PsiElement addElementBefore(@Nonnull PsiElement element, @Nonnull PsiElement newElement) { + ASTNode oldElementParentNode = element.getNode(); + PsiElement parentNode = element.getParent(); + ASTNode newElementParentNode = parentNode.getNode(); + ASTNode newElementNode = newElement.getNode(); + + if (newElementParentNode == null || newElementNode == null) { + return null; + } + newElementParentNode.addChild(newElementNode, oldElementParentNode); + return newElement; + } + + public static PsiElement addElementAfter(@Nonnull PsiElement element, @Nonnull PsiElement newElement) { + ASTNode elementNode = element.getNode(); + ASTNode oldElementParentNode = ((elementNode == null) ? null : elementNode.getTreeNext()); + PsiElement parentNode = element.getParent(); + ASTNode newElementParentNode = parentNode.getNode(); + ASTNode newElementNode = newElement.getNode(); + + if (newElementParentNode == null || newElementNode == null) { + return null; + } + newElementParentNode.addChild(newElementNode, oldElementParentNode); + + return newElement; + } + + public static PsiElement addElementBefore(@Nonnull PsiElement element, @NonNls @Nonnull String elementText) { + PsiElement newElement = createDummyFile(element.getProject(), elementText).getFirstChild(); + + assert (newElement != null); + return addElementBefore(element, newElement); + } + + public static PsiElement addElementAfter(@Nonnull PsiElement element, @Nonnull String elementText) { + PsiElement newElement = createDummyFile(element.getProject(), elementText).getFirstChild(); + + assert (newElement != null); + return addElementAfter(element, newElement); + } + + public static ASTNode createElementFromText(Project project, String text) { + PsiElement element = createDummyFile(project, text).getFirstChild(); + + assert (element != null); + return element.getNode(); + } + + @Nonnull + private static PsiFile createDummyFile(Project project, String text) { + ParserDefinition def = ParserDefinition.forLanguage(JavaScriptLanguage.INSTANCE); + + assert (def != null); + return PsiFileFactory.getInstance(project) + .createFileFromText("dummy.js", text); + } + + public static JSStatement replaceElementWithStatement(@Nonnull JSElement element, @NonNls @Nonnull String statementText) + throws IncorrectOperationException { + ASTNode newStatementNode = JSChangeUtil.createStatementFromText( + element.getProject(), + statementText + ); + + ASTNode oldStatementParentNode = element.getNode(); + PsiElement parentNode = element.getParent(); + ASTNode newStatementParentNode = parentNode.getNode(); + + if (newStatementParentNode == null || oldStatementParentNode == null || newStatementNode == null) { + return null; + } + newStatementParentNode.replaceChild(oldStatementParentNode, newStatementNode); + reformat(parentNode); + + return (JSStatement)newStatementNode.getPsi(); + } + + public static JSExpression replaceExpression(@Nonnull JSExpression expression, @NonNls @Nonnull String text) + throws IncorrectOperationException { + JSExpression newExpressionNode = JSChangeUtil.createExpressionFromText( + expression.getProject(), + text + ); + + return replaceExpression(expression, newExpressionNode); + } + + public static JSExpression replaceExpression(@Nonnull JSExpression expression, @Nonnull JSExpression newExpression) + throws IncorrectOperationException { + ASTNode newExpressionNode = newExpression.getNode(); + ASTNode oldExpressionNode = expression.getNode(); + PsiElement parentNode = expression.getParent(); + ASTNode grandParentNode = parentNode.getNode(); + + if (grandParentNode == null || oldExpressionNode == null || newExpressionNode == null) { + return null; + } + + grandParentNode.replaceChild(oldExpressionNode, newExpressionNode); + reformat(parentNode); + + return (JSExpression)newExpressionNode.getPsi(); + } + + public static JSStatement replaceStatement(@Nonnull JSStatement statement, @NonNls @Nonnull String text) + throws IncorrectOperationException { + ASTNode newStatementNode = JSChangeUtil.createStatementFromText( + statement.getProject(), + text + ); + + ASTNode oldStatementParentNode = statement.getNode(); + PsiElement parentNode = statement.getParent(); + ASTNode newStatementParentNode = parentNode.getNode(); + + if (newStatementParentNode == null || oldStatementParentNode == null || newStatementNode == null) { + return null; + } + + newStatementParentNode.replaceChild(oldStatementParentNode, newStatementNode); + reformat(parentNode); + + return (JSStatement)newStatementNode.getPsi(); + } + + public static JSStatement addStatementBefore(@Nonnull JSStatement statement, @NonNls @Nonnull String previousStatementText) + throws IncorrectOperationException { + ASTNode newStatementNode = JSChangeUtil.createStatementFromText( + statement.getProject(), + previousStatementText + ); + ASTNode oldStatementParentNode = statement.getNode(); + PsiElement parentNode = statement.getParent(); + ASTNode newStatementParentNode = parentNode.getNode(); + + if (newStatementParentNode == null || newStatementNode == null) { + return null; + } + + newStatementParentNode.addChild(newStatementNode, oldStatementParentNode); + reformat(parentNode); + + return (JSStatement)newStatementNode.getPsi(); + } + + public static JSStatement addStatementAfter(@Nonnull JSStatement statement, @NonNls @Nonnull String nextStatementText) + throws IncorrectOperationException { + ASTNode newStatementNode = JSChangeUtil.createStatementFromText( + statement.getProject(), + nextStatementText + ); + ASTNode statementNode = statement.getNode(); + ASTNode oldStatementParentNode = ((statementNode == null) ? null : statementNode.getTreeNext()); + PsiElement parentNode = statement.getParent(); + ASTNode newStatementParentNode = parentNode.getNode(); + + if (newStatementParentNode == null || newStatementNode == null) { + return null; + } + + newStatementParentNode.addChild(newStatementNode, oldStatementParentNode); + reformat(parentNode); + + return (JSStatement)newStatementNode.getPsi(); + } + + public static void addRangeBefore(JSStatement[] statements, JSStatement statement) throws IncorrectOperationException { + addRangeBefore(statements, 0, statements.length, statement); + } + + public static void addRangeAfter(JSStatement[] statements, JSStatement statement) throws IncorrectOperationException { + addRangeAfter(statements, 0, statements.length, statement); + } + + @SuppressWarnings({"ForLoopWithMissingComponent"}) + public static void addRangeBefore(JSStatement[] statements, int start, int length, JSStatement statement) + throws IncorrectOperationException { + for (int index = start; index < length; index++) { + addStatementBefore(statement, statements[index].getText()); + } + } + + @SuppressWarnings({"ForLoopWithMissingComponent"}) + public static void addRangeAfter(JSStatement[] statements, int start, int length, JSStatement statement) + throws IncorrectOperationException { + for (int index = length; --index >= start; ) { + addStatementAfter(statement, statements[index].getText()); + } + } + + public static void replaceExpressionWithNegatedExpression(@Nonnull JSExpression newExpression, @Nonnull JSExpression exp) + throws IncorrectOperationException { + JSExpression expressionToReplace = BoolUtils.findNegation(exp); + String replacementString; + + if (expressionToReplace == null) { + expressionToReplace = exp; + + if (ComparisonUtils.isComparisonOperator(newExpression)) { + JSBinaryExpression binaryExpression = (JSBinaryExpression)newExpression; + IElementType operationSign = binaryExpression.getOperationSign(); + String negatedComparison = ComparisonUtils.getNegatedOperatorText(operationSign); + JSExpression leftOperand = binaryExpression.getLOperand(); + JSExpression rightOperand = binaryExpression.getROperand(); + + assert (rightOperand != null); + + replacementString = leftOperand.getText() + negatedComparison + rightOperand.getText(); + } + else { + replacementString = '!' + ParenthesesUtils.getParenthesized(newExpression, ParenthesesUtils.PREFIX_PRECENDENCE); + } + } + else { + replacementString = newExpression.getText(); + } + replaceExpression(expressionToReplace, replacementString); + } + + public static void replaceExpressionWithNegatedExpressionString(JSExpression exp, String newExpression) + throws IncorrectOperationException { + assert (exp != null); + + JSExpression expressionToReplace = BoolUtils.findNegation(exp); + String replacementString = newExpression; + + if (expressionToReplace == null) { + expressionToReplace = exp; + replacementString = "!(" + newExpression + ')'; + } + + replaceExpression(expressionToReplace, replacementString); + } + + public static void replaceStatementWithUnwrapping(JSStatement statement, JSStatement newBranch) throws IncorrectOperationException { + if (!(newBranch instanceof JSBlockStatement)) { + JSElementFactory.replaceStatement(statement, newBranch.getText()); + return; + } + + JSBlockStatement parentBlock = PsiTreeUtil.getParentOfType(newBranch, JSBlockStatement.class); + + if (parentBlock == null) { + JSElementFactory.replaceStatement(statement, newBranch.getText()); + return; + } + + JSBlockStatement block = (JSBlockStatement)newBranch; + + if (ControlFlowUtils.containsConflictingDeclarations(block, parentBlock)) { + JSElementFactory.replaceStatement(statement, newBranch.getText()); + return; + } + + PsiElement containingElement = statement.getParent(); + + assert (containingElement instanceof JSStatement); + + JSElementFactory.addRangeBefore(block.getStatements(), statement); + JSElementFactory.removeElement(statement); + } + + public static void removeElement(PsiElement element) { + ASTNode node = element.getNode(); + ASTNode parentNode = element.getParent().getNode(); + + if (node != null && parentNode != null) { + parentNode.removeChild(node); + } + } + + public static void reformat(PsiElement statement) throws IncorrectOperationException { + // Reformat only in .js files due to a bug in JavaScript reformatting module when doing it in JSP files + if (statement.getContainingFile() instanceof JSFile) { + CodeStyleManager.getInstance(statement.getProject()).reformat(statement); + } + } + + public static PsiElement getNonWhiteSpaceSibling(PsiElement element, boolean forward) { + return forward + ? PsiTreeUtil.skipSiblingsForward(element, WHITESPACE_CLASS) + : PsiTreeUtil.skipSiblingsBackward(element, WHITESPACE_CLASS); + } + + public static boolean isFileReadOnly(Project project, PsiFile file) { + ReadonlyStatusHandler instance = ReadonlyStatusHandler.getInstance(project); + VirtualFile virtualFile = file.getVirtualFile(); + + return virtualFile != null && instance.ensureFilesWritable(virtualFile).hasReadonlyFiles(); + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/JSRecursionVisitor.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/JSRecursionVisitor.java index bddde225..51b94fde 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/JSRecursionVisitor.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/JSRecursionVisitor.java @@ -19,66 +19,53 @@ import consulo.language.psi.PsiElement; import consulo.language.psi.PsiReference; -public class JSRecursionVisitor extends JSRecursiveElementVisitor -{ +public class JSRecursionVisitor extends JSRecursiveElementVisitor { + private final JSFunction function; + private final String functionName; + private boolean recursive; - private final JSFunction function; - private final String functionName; - private boolean recursive; + public JSRecursionVisitor(JSFunction function) { + this.function = function; + this.functionName = function.getName(); + } - public JSRecursionVisitor(JSFunction function) - { - this.function = function; - this.functionName = function.getName(); - } + @Override + public void visitJSElement(JSElement element) { + if (!this.recursive) { + super.visitJSElement(element); + } + } - @Override - public void visitJSElement(JSElement element) - { - if(!this.recursive) - { - super.visitJSElement(element); - } - } + @Override + public void visitJSCallExpression(JSCallExpression call) { + if (!this.recursive) { + super.visitJSCallExpression(call); - @Override - public void visitJSCallExpression(JSCallExpression call) - { - if(!this.recursive) - { - super.visitJSCallExpression(call); + JSExpression methodExpression = call.getMethodExpression(); + String qualifiedMethodText = methodExpression.getText(); + String methodText = qualifiedMethodText.substring(qualifiedMethodText.lastIndexOf('.') + 1); - final JSExpression methodExpression = call.getMethodExpression(); - final String qualifiedMethodText = methodExpression.getText(); - final String methodText = qualifiedMethodText.substring(qualifiedMethodText.lastIndexOf('.') + 1); + if (methodText.equals(this.functionName)) { + PsiReference methodReference = methodExpression.getReference(); + PsiElement referent = methodReference == null ? null : methodReference.resolve(); - if(methodText.equals(this.functionName)) - { - final PsiReference methodReference = methodExpression.getReference(); - final PsiElement referent = ((methodReference == null) ? null : methodReference.resolve()); + if (referent != null) { + if (referent instanceof JSFunction) { + this.recursive = referent.equals(this.function); + } + else if (referent instanceof JSFunctionExpression functionExpression) { + this.recursive = functionExpression.getFunction().equals(this.function); + } + } + } + } + } - if(referent != null) - { - if(referent instanceof JSFunction) - { - this.recursive = referent.equals(this.function); - } - else if(referent instanceof JSFunctionExpression) - { - this.recursive = ((JSFunctionExpression) referent).getFunction().equals(this.function); - } - } - } - } - } + public boolean isFunctionNamed() { + return (this.functionName != null); + } - public boolean isFunctionNamed() - { - return (this.functionName != null); - } - - public boolean isRecursive() - { - return this.recursive; - } + public boolean isRecursive() { + return this.recursive; + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/JSRecursiveElementVisitor.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/JSRecursiveElementVisitor.java index ebfac5ff..cf105fd1 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/JSRecursiveElementVisitor.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/JSRecursiveElementVisitor.java @@ -22,12 +22,10 @@ * Represents a JS element visitor which recursively visits the children of the element * on which the visit was started. */ -public abstract class JSRecursiveElementVisitor extends JSElementVisitor -{ - @Override - public void visitJSElement(JSElement element) - { - element.acceptChildren(this); - } +public abstract class JSRecursiveElementVisitor extends JSElementVisitor { + @Override + public void visitJSElement(JSElement element) { + element.acceptChildren(this); + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/NumberUtil.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/NumberUtil.java index f2634cc2..fcceb313 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/NumberUtil.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/NumberUtil.java @@ -24,57 +24,47 @@ /** * */ -public class NumberUtil -{ - private NumberUtil() - { - } +public class NumberUtil { + private NumberUtil() { + } - @NonNls - public static final Pattern decimalPattern = Pattern.compile("[0-9]+"); - @NonNls - public static final Pattern octalPattern = Pattern.compile("0[0-7]+"); - @NonNls - public static final Pattern hexPattern = Pattern.compile("0[xX][0-9a-fA-F]+"); + @NonNls + public static final Pattern decimalPattern = Pattern.compile("[0-9]+"); + @NonNls + public static final Pattern octalPattern = Pattern.compile("0[0-7]+"); + @NonNls + public static final Pattern hexPattern = Pattern.compile("0[xX][0-9a-fA-F]+"); - public static BigInteger getLiteralNumber(JSLiteralExpression expression) - { - String expressionText = expression.getText(); - int radix = 10; + public static BigInteger getLiteralNumber(JSLiteralExpression expression) { + String expressionText = expression.getText(); + int radix = 10; - if(expressionText == null || expressionText.length() == 0) - { - return new BigInteger(new byte[]{0}); - } + if (expressionText == null || expressionText.length() == 0) { + return new BigInteger(new byte[]{0}); + } - if(expressionText.charAt(0) == '0') - { - if(expressionText.length() > 2 && Character.toUpperCase(expressionText.charAt(1)) == 'X') - { - expressionText = expressionText.substring(2); - radix = 16; - } - else if(octalPattern.matcher(expressionText).matches()) - { - radix = 8; - } - } + if (expressionText.charAt(0) == '0') { + if (expressionText.length() > 2 && Character.toUpperCase(expressionText.charAt(1)) == 'X') { + expressionText = expressionText.substring(2); + radix = 16; + } + else if (octalPattern.matcher(expressionText).matches()) { + radix = 8; + } + } - return new BigInteger(expressionText, radix); - } + return new BigInteger(expressionText, radix); + } - public static boolean isOctal(String number) - { - return octalPattern.matcher(number).matches(); - } + public static boolean isOctal(String number) { + return octalPattern.matcher(number).matches(); + } - public static boolean isDecimal(String number) - { - return decimalPattern.matcher(number).matches(); - } + public static boolean isDecimal(String number) { + return decimalPattern.matcher(number).matches(); + } - public static boolean isHex(String number) - { - return hexPattern.matcher(number).matches(); - } + public static boolean isHex(String number) { + return hexPattern.matcher(number).matches(); + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ParenthesesUtils.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ParenthesesUtils.java index 83cb1f22..9d099475 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ParenthesesUtils.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/ParenthesesUtils.java @@ -24,369 +24,310 @@ import java.util.HashMap; import java.util.Map; -public class ParenthesesUtils -{ - private ParenthesesUtils() - { - } - - private static final int PARENTHESIZED_PRECENDENCE = 0; - private static final int LITERAL_PRECENDENCE = 0; - public static final int METHOD_CALL_PRECENDENCE = 1; - - private static final int POSTFIX_PRECENDENCE = 2; - public static final int PREFIX_PRECENDENCE = 3; - public static final int TYPE_CAST_PRECENDENCE = 4; - public static final int MULTIPLICATIVE_PRECENDENCE = 5; - private static final int ADDITIVE_PRECENDENCE = 6; - public static final int SHIFT_PRECENDENCE = 7; - private static final int RELATIONAL_PRECENDENCE = 8; - public static final int EQUALITY_PRECENDENCE = 9; - - private static final int BINARY_AND_PRECENDENCE = 10; - private static final int BINARY_XOR_PRECENDENCE = 11; - private static final int BINARY_OR_PRECENDENCE = 12; - public static final int AND_PRECENDENCE = 13; - public static final int OR_PRECENDENCE = 14; - public static final int CONDITIONAL_PRECENDENCE = 15; - private static final int ASSIGNMENT_PRECENDENCE = 16; - - private static final int NUM_PRECENDENCES = 17; - - private static final Map binaryOperatorPrecendence = - new HashMap(NUM_PRECENDENCES); - - static - { - binaryOperatorPrecendence.put(JSTokenTypes.PLUS, ADDITIVE_PRECENDENCE); - binaryOperatorPrecendence.put(JSTokenTypes.MINUS, ADDITIVE_PRECENDENCE); - binaryOperatorPrecendence.put(JSTokenTypes.MULT, MULTIPLICATIVE_PRECENDENCE); - binaryOperatorPrecendence.put(JSTokenTypes.DIV, MULTIPLICATIVE_PRECENDENCE); - binaryOperatorPrecendence.put(JSTokenTypes.PERC, MULTIPLICATIVE_PRECENDENCE); - binaryOperatorPrecendence.put(JSTokenTypes.ANDAND, AND_PRECENDENCE); - binaryOperatorPrecendence.put(JSTokenTypes.OROR, OR_PRECENDENCE); - binaryOperatorPrecendence.put(JSTokenTypes.AND, BINARY_AND_PRECENDENCE); - binaryOperatorPrecendence.put(JSTokenTypes.OR, BINARY_OR_PRECENDENCE); - binaryOperatorPrecendence.put(JSTokenTypes.XOR, BINARY_XOR_PRECENDENCE); - binaryOperatorPrecendence.put(JSTokenTypes.COMMA, ASSIGNMENT_PRECENDENCE); - binaryOperatorPrecendence.put(JSTokenTypes.LTLT, SHIFT_PRECENDENCE); - binaryOperatorPrecendence.put(JSTokenTypes.GTGT, SHIFT_PRECENDENCE); - binaryOperatorPrecendence.put(JSTokenTypes.GTGTGT, SHIFT_PRECENDENCE); - binaryOperatorPrecendence.put(JSTokenTypes.GT, RELATIONAL_PRECENDENCE); - binaryOperatorPrecendence.put(JSTokenTypes.GE, RELATIONAL_PRECENDENCE); - binaryOperatorPrecendence.put(JSTokenTypes.LT, RELATIONAL_PRECENDENCE); - binaryOperatorPrecendence.put(JSTokenTypes.LE, RELATIONAL_PRECENDENCE); - binaryOperatorPrecendence.put(JSTokenTypes.EQEQ, EQUALITY_PRECENDENCE); - binaryOperatorPrecendence.put(JSTokenTypes.NE, EQUALITY_PRECENDENCE); - binaryOperatorPrecendence.put(JSTokenTypes.EQEQEQ, EQUALITY_PRECENDENCE); - binaryOperatorPrecendence.put(JSTokenTypes.NEQEQ, EQUALITY_PRECENDENCE); - } - - public static JSExpression stripParentheses(JSExpression expression) - { - JSExpression parenthesized = expression; - - if(parenthesized != null) - { - while(parenthesized instanceof JSParenthesizedExpression) - { - parenthesized = ((JSParenthesizedExpression) parenthesized).getInnerExpression(); - } - } - - return parenthesized; - } - - public static JSExpression unstripParentheses(JSExpression expression) - { - JSExpression parenthesized = expression; - - if(parenthesized != null) - { - PsiElement parent = parenthesized.getParent(); - - while(parent instanceof JSParenthesizedExpression) - { - parenthesized = (JSParenthesizedExpression) parent; - parent = parenthesized.getParent(); - } - } - - return parenthesized; - } - - public static String getParenthesized(JSExpression expression, int precendence) - { - return (ParenthesesUtils.getPrecendence(expression) > precendence - ? '(' + expression.getText() + ')' - : expression.getText()); - } - - public static int getPrecendence(JSExpression expression) - { - if(expression instanceof JSThisExpression || - expression instanceof JSLiteralExpression || - expression instanceof JSArrayLiteralExpression || - expression instanceof JSObjectLiteralExpression || - expression instanceof JSIndexedPropertyAccessExpression) - { - return LITERAL_PRECENDENCE; - } - if(expression instanceof JSReferenceExpression) - { - return ((JSReferenceExpression) expression).getQualifier() == null - ? LITERAL_PRECENDENCE - : METHOD_CALL_PRECENDENCE; - } - if(expression instanceof JSNewExpression) - { - return TYPE_CAST_PRECENDENCE; - } - if(expression instanceof JSCallExpression) - { - return METHOD_CALL_PRECENDENCE; - } - if(expression instanceof JSPostfixExpression) - { - return POSTFIX_PRECENDENCE; - } - if(expression instanceof JSPrefixExpression) - { - return PREFIX_PRECENDENCE; - } - if(expression instanceof JSAssignmentExpression) - { - return ASSIGNMENT_PRECENDENCE; - } - if(expression instanceof JSBinaryExpression) - { - return getBinaryOperatorPrecendence(((JSBinaryExpression) expression).getOperationSign()); - } - if(expression instanceof JSConditionalExpression) - { - return CONDITIONAL_PRECENDENCE; - } - if(expression instanceof JSParenthesizedExpression) - { - return PARENTHESIZED_PRECENDENCE; - } - - // expression instanceof JSCommaExpression || - // expression instanceof JSDefinitionExpression || - // expression instanceof JSFunctionExpression - return -1; - } - - private static int getBinaryOperatorPrecendence(IElementType sign) - { - if(binaryOperatorPrecendence.containsKey(sign)) - { - return binaryOperatorPrecendence.get(sign); - } - return ASSIGNMENT_PRECENDENCE; - } - - public static String removeParentheses(JSExpression expression) - { - if(expression instanceof JSCallExpression) - { - return removeParensFromFunctionCallExpression((JSCallExpression) expression); - } - if(expression instanceof JSReferenceExpression) - { - return removeParensFromReferenceExpression( - (JSReferenceExpression) expression); - } - if(expression instanceof JSAssignmentExpression) - { - return removeParensFromAssignmentExpression( - (JSAssignmentExpression) expression); - } - if(expression instanceof JSArrayLiteralExpression) - { - return removeParensFromArrayLiteralExpression((JSArrayLiteralExpression) expression); - } - if(expression instanceof JSPrefixExpression) - { - return removeParensFromPrefixExpression((JSPrefixExpression) expression); - } - if(expression instanceof JSPostfixExpression) - { - return removeParensFromPostfixExpression((JSPostfixExpression) expression); - } - if(expression instanceof JSBinaryExpression) - { - return removeParensFromBinaryExpression((JSBinaryExpression) expression); - } - if(expression instanceof JSConditionalExpression) - { - return removeParensFromConditionalExpression((JSConditionalExpression) expression); - } - if(expression instanceof JSParenthesizedExpression) - { - return removeParensFromParenthesizedExpression((JSParenthesizedExpression) expression); - } - - return expression.getText(); - } - - private static String removeParensFromReferenceExpression(JSReferenceExpression expression) - { - final JSExpression qualifier = expression.getQualifier(); - - if(qualifier != null) - { - return removeParentheses(qualifier) + '.' + expression.getReferencedName(); - } - else - { - return expression.getText(); - } - } - - private static String removeParensFromParenthesizedExpression(JSParenthesizedExpression parenthesizedExp) - { - final JSExpression body = stripParentheses(parenthesizedExp.getInnerExpression()); - - if(!(parenthesizedExp.getParent() instanceof JSExpression)) - { - return removeParentheses(body); - } - - final JSExpression parentExp = (JSExpression) parenthesizedExp.getParent(); - final int parentPrecendence = getPrecendence(parentExp); - final int childPrecendence = getPrecendence(body); - - if(parentPrecendence < childPrecendence) - { - return '(' + removeParentheses(body) + ')'; - } - else if(parentPrecendence == childPrecendence) - { - if(parentExp instanceof JSBinaryExpression && body instanceof JSBinaryExpression) - { - final IElementType parentOperator = ((JSBinaryExpression) parentExp).getOperationSign(); - final IElementType bodyOperator = ((JSBinaryExpression) body).getOperationSign(); - final JSExpression lhs = ((JSBinaryExpression) parentExp).getLOperand(); - - if(lhs.equals(parenthesizedExp) && parentOperator.equals(bodyOperator)) - { - return removeParentheses(body); - } - else - { - return '(' + removeParentheses(body) + ')'; - } - } - else - { - return removeParentheses(body); - } - } - else - { - return removeParentheses(body); - } - } - - private static String removeParensFromConditionalExpression(JSConditionalExpression conditionalExp) - { - final JSExpression condition = conditionalExp.getCondition(); - final JSExpression thenBranch = conditionalExp.getThen(); - final JSExpression elseBranch = conditionalExp.getElse(); - - return removeParentheses(condition) + " ? " + - removeParentheses(thenBranch) + " : " + - removeParentheses(elseBranch); - } - - private static String removeParensFromBinaryExpression(JSBinaryExpression binaryExp) - { - final JSExpression lhs = binaryExp.getLOperand(); - final JSExpression rhs = binaryExp.getROperand(); - final IElementType sign = binaryExp.getOperationSign(); - - return removeParentheses(lhs) + ' ' + BinaryOperatorUtils.getOperatorText(sign) + ' ' + removeParentheses(rhs); - } - - private static String removeParensFromPostfixExpression(JSPostfixExpression postfixExp) - { - final JSExpression body = postfixExp.getExpression(); - final IElementType sign = postfixExp.getOperationSign(); - - return removeParentheses(body) + BinaryOperatorUtils.getOperatorText(sign); - } - - private static String removeParensFromPrefixExpression(JSPrefixExpression prefixExp) - { - final JSExpression body = prefixExp.getExpression(); - IElementType sign = prefixExp.getOperationSign(); - if(sign == null) - { - final ASTNode[] astNodes = prefixExp.getNode().getChildren(JSTokenTypes.UNARY_OPERATIONS); // hack for 8.1 - sign = astNodes.length == 1 ? astNodes[0].getElementType() : null; - } - - return (sign != null ? BinaryOperatorUtils.getOperatorText(sign) : "delete ") + removeParentheses(body); - } - - private static String removeParensFromArrayLiteralExpression(JSArrayLiteralExpression init) - { - final JSExpression[] contents = init.getExpressions(); - final String text = init.getText(); - final int textLength = text.length(); - final StringBuilder out = new StringBuilder(textLength); - - out.append('('); - for(int index = 0; index < contents.length; index++) - { - final JSExpression arg = contents[index]; - - if(index != 0) - { - out.append(','); - } - out.append(removeParentheses(arg)); - } - - return out.append(')').toString(); - } - - private static String removeParensFromAssignmentExpression(JSAssignmentExpression assignment) - { - final JSExpression lhs = assignment.getLOperand(); - final JSExpression rhs = assignment.getROperand(); - final IElementType sign = assignment.getOperationSign(); - return removeParentheses(lhs) + ' ' + - BinaryOperatorUtils.getOperatorText(sign) + ' ' + - removeParentheses(rhs); - } - - private static String removeParensFromFunctionCallExpression(JSCallExpression functionCall) - { - final JSExpression target = functionCall.getMethodExpression(); - final JSArgumentList argumentList = functionCall.getArgumentList(); - - assert (argumentList != null); - - final JSExpression[] args = argumentList.getArguments(); - final String methodCallText = functionCall.getText(); - final int length = methodCallText.length(); - final StringBuilder out = new StringBuilder(length); - final String strippedTarget = removeParentheses(target); - - out.append(strippedTarget); - out.append('('); - for(int index = 0; index < args.length; index++) - { - final JSExpression arg = args[index]; - if(index != 0) - { - out.append(','); - } - out.append(removeParentheses(arg)); - } - out.append(')'); - return out.toString(); - } +public class ParenthesesUtils { + private ParenthesesUtils() { + } + + private static final int PARENTHESIZED_PRECENDENCE = 0; + private static final int LITERAL_PRECENDENCE = 0; + public static final int METHOD_CALL_PRECENDENCE = 1; + + private static final int POSTFIX_PRECENDENCE = 2; + public static final int PREFIX_PRECENDENCE = 3; + public static final int TYPE_CAST_PRECENDENCE = 4; + public static final int MULTIPLICATIVE_PRECENDENCE = 5; + private static final int ADDITIVE_PRECENDENCE = 6; + public static final int SHIFT_PRECENDENCE = 7; + private static final int RELATIONAL_PRECENDENCE = 8; + public static final int EQUALITY_PRECENDENCE = 9; + + private static final int BINARY_AND_PRECENDENCE = 10; + private static final int BINARY_XOR_PRECENDENCE = 11; + private static final int BINARY_OR_PRECENDENCE = 12; + public static final int AND_PRECENDENCE = 13; + public static final int OR_PRECENDENCE = 14; + public static final int CONDITIONAL_PRECENDENCE = 15; + private static final int ASSIGNMENT_PRECENDENCE = 16; + + private static final int NUM_PRECENDENCES = 17; + + private static final Map binaryOperatorPrecendence = + new HashMap(NUM_PRECENDENCES); + + static { + binaryOperatorPrecendence.put(JSTokenTypes.PLUS, ADDITIVE_PRECENDENCE); + binaryOperatorPrecendence.put(JSTokenTypes.MINUS, ADDITIVE_PRECENDENCE); + binaryOperatorPrecendence.put(JSTokenTypes.MULT, MULTIPLICATIVE_PRECENDENCE); + binaryOperatorPrecendence.put(JSTokenTypes.DIV, MULTIPLICATIVE_PRECENDENCE); + binaryOperatorPrecendence.put(JSTokenTypes.PERC, MULTIPLICATIVE_PRECENDENCE); + binaryOperatorPrecendence.put(JSTokenTypes.ANDAND, AND_PRECENDENCE); + binaryOperatorPrecendence.put(JSTokenTypes.OROR, OR_PRECENDENCE); + binaryOperatorPrecendence.put(JSTokenTypes.AND, BINARY_AND_PRECENDENCE); + binaryOperatorPrecendence.put(JSTokenTypes.OR, BINARY_OR_PRECENDENCE); + binaryOperatorPrecendence.put(JSTokenTypes.XOR, BINARY_XOR_PRECENDENCE); + binaryOperatorPrecendence.put(JSTokenTypes.COMMA, ASSIGNMENT_PRECENDENCE); + binaryOperatorPrecendence.put(JSTokenTypes.LTLT, SHIFT_PRECENDENCE); + binaryOperatorPrecendence.put(JSTokenTypes.GTGT, SHIFT_PRECENDENCE); + binaryOperatorPrecendence.put(JSTokenTypes.GTGTGT, SHIFT_PRECENDENCE); + binaryOperatorPrecendence.put(JSTokenTypes.GT, RELATIONAL_PRECENDENCE); + binaryOperatorPrecendence.put(JSTokenTypes.GE, RELATIONAL_PRECENDENCE); + binaryOperatorPrecendence.put(JSTokenTypes.LT, RELATIONAL_PRECENDENCE); + binaryOperatorPrecendence.put(JSTokenTypes.LE, RELATIONAL_PRECENDENCE); + binaryOperatorPrecendence.put(JSTokenTypes.EQEQ, EQUALITY_PRECENDENCE); + binaryOperatorPrecendence.put(JSTokenTypes.NE, EQUALITY_PRECENDENCE); + binaryOperatorPrecendence.put(JSTokenTypes.EQEQEQ, EQUALITY_PRECENDENCE); + binaryOperatorPrecendence.put(JSTokenTypes.NEQEQ, EQUALITY_PRECENDENCE); + } + + public static JSExpression stripParentheses(JSExpression expression) { + JSExpression parenthesized = expression; + + if (parenthesized != null) { + while (parenthesized instanceof JSParenthesizedExpression) { + parenthesized = ((JSParenthesizedExpression)parenthesized).getInnerExpression(); + } + } + + return parenthesized; + } + + public static JSExpression unstripParentheses(JSExpression expression) { + JSExpression parenthesized = expression; + + if (parenthesized != null) { + PsiElement parent = parenthesized.getParent(); + + while (parent instanceof JSParenthesizedExpression parenExp) { + parenthesized = parenExp; + parent = parenthesized.getParent(); + } + } + + return parenthesized; + } + + public static String getParenthesized(JSExpression expression, int precendence) { + return ParenthesesUtils.getPrecendence(expression) > precendence + ? '(' + expression.getText() + ')' + : expression.getText(); + } + + public static int getPrecendence(JSExpression expression) { + if (expression instanceof JSThisExpression + || expression instanceof JSLiteralExpression + || expression instanceof JSArrayLiteralExpression + || expression instanceof JSObjectLiteralExpression + || expression instanceof JSIndexedPropertyAccessExpression) { + return LITERAL_PRECENDENCE; + } + if (expression instanceof JSReferenceExpression referenceExpression) { + return referenceExpression.getQualifier() == null + ? LITERAL_PRECENDENCE + : METHOD_CALL_PRECENDENCE; + } + if (expression instanceof JSNewExpression) { + return TYPE_CAST_PRECENDENCE; + } + if (expression instanceof JSCallExpression) { + return METHOD_CALL_PRECENDENCE; + } + if (expression instanceof JSPostfixExpression) { + return POSTFIX_PRECENDENCE; + } + if (expression instanceof JSPrefixExpression) { + return PREFIX_PRECENDENCE; + } + if (expression instanceof JSAssignmentExpression) { + return ASSIGNMENT_PRECENDENCE; + } + if (expression instanceof JSBinaryExpression binaryExpression) { + return getBinaryOperatorPrecendence(binaryExpression.getOperationSign()); + } + if (expression instanceof JSConditionalExpression) { + return CONDITIONAL_PRECENDENCE; + } + if (expression instanceof JSParenthesizedExpression) { + return PARENTHESIZED_PRECENDENCE; + } + + // expression instanceof JSCommaExpression || + // expression instanceof JSDefinitionExpression || + // expression instanceof JSFunctionExpression + return -1; + } + + private static int getBinaryOperatorPrecendence(IElementType sign) { + if (binaryOperatorPrecendence.containsKey(sign)) { + return binaryOperatorPrecendence.get(sign); + } + return ASSIGNMENT_PRECENDENCE; + } + + public static String removeParentheses(JSExpression expression) { + if (expression instanceof JSCallExpression callExpression) { + return removeParensFromFunctionCallExpression(callExpression); + } + if (expression instanceof JSReferenceExpression referenceExpression) { + return removeParensFromReferenceExpression(referenceExpression); + } + if (expression instanceof JSAssignmentExpression assignmentExpression) { + return removeParensFromAssignmentExpression(assignmentExpression); + } + if (expression instanceof JSArrayLiteralExpression arrayLiteralExpression) { + return removeParensFromArrayLiteralExpression(arrayLiteralExpression); + } + if (expression instanceof JSPrefixExpression prefixExpression) { + return removeParensFromPrefixExpression(prefixExpression); + } + if (expression instanceof JSPostfixExpression postfixExpression) { + return removeParensFromPostfixExpression(postfixExpression); + } + if (expression instanceof JSBinaryExpression binaryExpression) { + return removeParensFromBinaryExpression(binaryExpression); + } + if (expression instanceof JSConditionalExpression conditionalExpression) { + return removeParensFromConditionalExpression(conditionalExpression); + } + if (expression instanceof JSParenthesizedExpression parenthesizedExpression) { + return removeParensFromParenthesizedExpression(parenthesizedExpression); + } + + return expression.getText(); + } + + private static String removeParensFromReferenceExpression(JSReferenceExpression expression) { + JSExpression qualifier = expression.getQualifier(); + + if (qualifier != null) { + return removeParentheses(qualifier) + '.' + expression.getReferencedName(); + } + else { + return expression.getText(); + } + } + + private static String removeParensFromParenthesizedExpression(JSParenthesizedExpression parenthesizedExp) { + JSExpression body = stripParentheses(parenthesizedExp.getInnerExpression()); + + if (!(parenthesizedExp.getParent() instanceof JSExpression)) { + return removeParentheses(body); + } + + JSExpression parentExp = (JSExpression)parenthesizedExp.getParent(); + int parentPrecendence = getPrecendence(parentExp); + int childPrecendence = getPrecendence(body); + + if (parentPrecendence < childPrecendence) { + return '(' + removeParentheses(body) + ')'; + } + else if (parentPrecendence == childPrecendence) { + if (parentExp instanceof JSBinaryExpression parentBiExp && body instanceof JSBinaryExpression bodyBiExp) { + IElementType parentOperator = parentBiExp.getOperationSign(); + IElementType bodyOperator = bodyBiExp.getOperationSign(); + JSExpression lhs = parentBiExp.getLOperand(); + + if (lhs.equals(parenthesizedExp) && parentOperator.equals(bodyOperator)) { + return removeParentheses(body); + } + else { + return '(' + removeParentheses(body) + ')'; + } + } + else { + return removeParentheses(body); + } + } + else { + return removeParentheses(body); + } + } + + private static String removeParensFromConditionalExpression(JSConditionalExpression conditionalExp) { + JSExpression condition = conditionalExp.getCondition(); + JSExpression thenBranch = conditionalExp.getThen(); + JSExpression elseBranch = conditionalExp.getElse(); + + return removeParentheses(condition) + " ? " + + removeParentheses(thenBranch) + " : " + + removeParentheses(elseBranch); + } + + private static String removeParensFromBinaryExpression(JSBinaryExpression binaryExp) { + JSExpression lhs = binaryExp.getLOperand(); + JSExpression rhs = binaryExp.getROperand(); + IElementType sign = binaryExp.getOperationSign(); + + return removeParentheses(lhs) + ' ' + BinaryOperatorUtils.getOperatorText(sign) + ' ' + removeParentheses(rhs); + } + + private static String removeParensFromPostfixExpression(JSPostfixExpression postfixExp) { + JSExpression body = postfixExp.getExpression(); + IElementType sign = postfixExp.getOperationSign(); + + return removeParentheses(body) + BinaryOperatorUtils.getOperatorText(sign); + } + + private static String removeParensFromPrefixExpression(JSPrefixExpression prefixExp) { + JSExpression body = prefixExp.getExpression(); + IElementType sign = prefixExp.getOperationSign(); + if (sign == null) { + ASTNode[] astNodes = prefixExp.getNode().getChildren(JSTokenTypes.UNARY_OPERATIONS); // hack for 8.1 + sign = astNodes.length == 1 ? astNodes[0].getElementType() : null; + } + + return (sign != null ? BinaryOperatorUtils.getOperatorText(sign) : "delete ") + removeParentheses(body); + } + + private static String removeParensFromArrayLiteralExpression(JSArrayLiteralExpression init) { + JSExpression[] contents = init.getExpressions(); + String text = init.getText(); + int textLength = text.length(); + StringBuilder out = new StringBuilder(textLength); + + out.append('('); + for (int index = 0; index < contents.length; index++) { + JSExpression arg = contents[index]; + + if (index != 0) { + out.append(','); + } + out.append(removeParentheses(arg)); + } + + return out.append(')').toString(); + } + + private static String removeParensFromAssignmentExpression(JSAssignmentExpression assignment) { + JSExpression lhs = assignment.getLOperand(); + JSExpression rhs = assignment.getROperand(); + IElementType sign = assignment.getOperationSign(); + return removeParentheses(lhs) + ' ' + + BinaryOperatorUtils.getOperatorText(sign) + ' ' + + removeParentheses(rhs); + } + + private static String removeParensFromFunctionCallExpression(JSCallExpression functionCall) { + JSExpression target = functionCall.getMethodExpression(); + JSArgumentList argumentList = functionCall.getArgumentList(); + + assert (argumentList != null); + + JSExpression[] args = argumentList.getArguments(); + String methodCallText = functionCall.getText(); + int length = methodCallText.length(); + StringBuilder out = new StringBuilder(length); + String strippedTarget = removeParentheses(target); + + out.append(strippedTarget); + out.append('('); + for (int index = 0; index < args.length; index++) { + JSExpression arg = args[index]; + if (index != 0) { + out.append(','); + } + out.append(removeParentheses(arg)); + } + out.append(')'); + return out.toString(); + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/RecursionUtil.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/RecursionUtil.java index 4c9cca65..e2711dd3 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/RecursionUtil.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/RecursionUtil.java @@ -18,721 +18,510 @@ import com.intellij.lang.javascript.JSTokenTypes; import com.intellij.lang.javascript.psi.*; import consulo.language.ast.IElementType; - -import javax.annotation.Nonnull; - -public class RecursionUtil -{ - - private RecursionUtil() - { - } - - public static boolean statementMayReturnBeforeRecursing( - JSStatement statement, JSFunction method) - { - if(statement == null) - { - return true; - } - - if(statement instanceof JSBreakStatement || - statement instanceof JSContinueStatement || - statement instanceof JSThrowStatement || - statement instanceof JSExpressionStatement || - statement instanceof JSEmptyStatement || - statement instanceof JSVarStatement) - { - return false; - } - else if(statement instanceof JSReturnStatement) - { - final JSReturnStatement returnStatement = - (JSReturnStatement) statement; - final JSExpression returnValue = returnStatement.getExpression(); - return (returnValue == null || - !RecursionUtil.expressionDefinitelyRecurses(returnValue, method)); - } - else if(statement instanceof JSForStatement) - { - return RecursionUtil.forStatementMayReturnBeforeRecursing( - (JSForStatement) statement, method); - } - else if(statement instanceof JSForInStatement) - { - return RecursionUtil.forInStatementMayReturnBeforeRecursing( - (JSForInStatement) statement, method); - } - else if(statement instanceof JSWhileStatement) - { - return RecursionUtil.whileStatementMayReturnBeforeRecursing( - (JSWhileStatement) statement, method); - } - else if(statement instanceof JSDoWhileStatement) - { - return RecursionUtil.doWhileStatementMayReturnBeforeRecursing( - (JSDoWhileStatement) statement, method); - } - else if(statement instanceof JSBlockStatement) - { - final JSBlockStatement blockStatement = - (JSBlockStatement) statement; - return RecursionUtil.blockStatementMayReturnBeforeRecursing(blockStatement, method, false); - } - else if(statement instanceof JSLabeledStatement) - { - return RecursionUtil.labeledStatementMayReturnBeforeRecursing( - (JSLabeledStatement) statement, method); - } - else if(statement instanceof JSIfStatement) - { - return RecursionUtil.ifStatementMayReturnBeforeRecursing( - (JSIfStatement) statement, method); - } - else if(statement instanceof JSTryStatement) - { - return RecursionUtil.tryStatementMayReturnBeforeRecursing( - (JSTryStatement) statement, method); - } - else if(statement instanceof JSSwitchStatement) - { - return RecursionUtil.switchStatementMayReturnBeforeRecursing( - (JSSwitchStatement) statement, method); - } - else - { - // unknown statement type - return true; - } - } - - private static boolean doWhileStatementMayReturnBeforeRecursing( - JSDoWhileStatement loopStatement, JSFunction method) - { - final JSStatement body = loopStatement.getBody(); - return RecursionUtil.statementMayReturnBeforeRecursing(body, method); - } - - private static boolean whileStatementMayReturnBeforeRecursing( - JSWhileStatement loopStatement, JSFunction method) - { - final JSExpression test = loopStatement.getCondition(); - if(RecursionUtil.expressionDefinitelyRecurses(test, method)) - { - return false; - } - final JSStatement body = loopStatement.getBody(); - return RecursionUtil.statementMayReturnBeforeRecursing(body, method); - } - - private static boolean forStatementMayReturnBeforeRecursing( - JSForStatement loopStatement, JSFunction method) - { - - if(RecursionUtil.statementMayReturnBeforeRecursing(loopStatement.getVarDeclaration(), method)) - { - return true; - } - if(RecursionUtil.expressionDefinitelyRecurses(loopStatement.getInitialization(), method)) - { - return false; - } - if(RecursionUtil.expressionDefinitelyRecurses(loopStatement.getCondition(), method)) - { - return false; - } - return RecursionUtil.statementMayReturnBeforeRecursing(loopStatement.getBody(), method); - } - - private static boolean forInStatementMayReturnBeforeRecursing( - JSForInStatement loopStatement, JSFunction method) - { - final JSExpression collection = loopStatement.getCollectionExpression(); - if(RecursionUtil.expressionDefinitelyRecurses(collection, method)) - { - return false; - } - final JSStatement body = loopStatement.getBody(); - return RecursionUtil.statementMayReturnBeforeRecursing(body, method); - } - - private static boolean switchStatementMayReturnBeforeRecursing( - JSSwitchStatement switchStatement, JSFunction method) - { - - for(final JSCaseClause clause : switchStatement.getCaseClauses()) - { - for(final JSStatement statement : clause.getStatements()) - { - if(RecursionUtil.statementMayReturnBeforeRecursing(statement, method)) - { - return true; - } - } - } - return false; - } - - private static boolean tryStatementMayReturnBeforeRecursing( - JSTryStatement tryStatement, JSFunction method) - { - final JSStatement finallyStatement = tryStatement.getFinallyStatement(); - - if(finallyStatement != null) - { - if(RecursionUtil.statementMayReturnBeforeRecursing(finallyStatement, method)) - { - return true; - } - if(RecursionUtil.statementDefinitelyRecurses(finallyStatement, method)) - { - return false; - } - } - - final JSStatement statement = tryStatement.getStatement(); - - if(RecursionUtil.statementMayReturnBeforeRecursing(statement, method)) - { - return true; - } - - final JSCatchBlock catchBlock = tryStatement.getCatchBlock(); - - if(catchBlock != null) - { - final JSStatement catchStatement = catchBlock.getStatement(); - - if(RecursionUtil.statementMayReturnBeforeRecursing(catchStatement, method)) - { - return true; - } - } - return false; - } - - private static boolean ifStatementMayReturnBeforeRecursing( - JSIfStatement ifStatement, JSFunction method) - { - final JSExpression test = ifStatement.getCondition(); - if(RecursionUtil.expressionDefinitelyRecurses(test, method)) - { - return false; - } - final JSStatement thenBranch = ifStatement.getThen(); - if(RecursionUtil.statementMayReturnBeforeRecursing(thenBranch, method)) - { - return true; - } - final JSStatement elseBranch = ifStatement.getElse(); - return elseBranch != null && - RecursionUtil.statementMayReturnBeforeRecursing(elseBranch, method); - } - - private static boolean labeledStatementMayReturnBeforeRecursing( - JSLabeledStatement labeledStatement, JSFunction method) - { - final JSStatement statement = labeledStatement.getStatement(); - return RecursionUtil.statementMayReturnBeforeRecursing(statement, method); - } - - private static boolean blockStatementMayReturnBeforeRecursing( - JSBlockStatement block, JSFunction method, boolean endsInImplicitReturn) - { - if(block == null) - { - return true; - } - - final JSStatement[] statements = block.getStatements(); - - for(final JSStatement statement : statements) - { - if(RecursionUtil.statementMayReturnBeforeRecursing(statement, method)) - { - return true; - } - if(RecursionUtil.statementDefinitelyRecurses(statement, method)) - { - return false; - } - } - return endsInImplicitReturn; - } - - public static boolean functionMayRecurse(@Nonnull JSFunction function) - { - final JSRecursionVisitor recursionVisitor = new JSRecursionVisitor(function); - - if(recursionVisitor.isFunctionNamed()) - { - function.accept(recursionVisitor); - } - return recursionVisitor.isRecursive(); - } - - private static boolean expressionDefinitelyRecurses(JSExpression exp, - JSFunction method) - { - if(exp == null) - { - return false; - } - if(exp instanceof JSNewExpression) - { - return RecursionUtil.newExpressionDefinitelyRecurses( - (JSNewExpression) exp, method); - } - if(exp instanceof JSCallExpression) - { - return RecursionUtil.callExpressionDefinitelyRecurses( - (JSCallExpression) exp, method); - } - if(exp instanceof JSAssignmentExpression) - { - return RecursionUtil.assignmentExpressionDefinitelyRecurses( - (JSAssignmentExpression) exp, method); - } - if(exp instanceof JSArrayLiteralExpression) - { - return RecursionUtil.arrayLiteralExpressionDefinitelyRecurses( - (JSArrayLiteralExpression) exp, method); - } - if(exp instanceof JSIndexedPropertyAccessExpression) - { - return RecursionUtil.indexedPropertyAccessExpressionDefinitelyRecurses( - (JSIndexedPropertyAccessExpression) exp, method); - } - if(exp instanceof JSPrefixExpression) - { - return RecursionUtil.prefixExpressionDefinitelyRecurses( - (JSPrefixExpression) exp, method); - } - if(exp instanceof JSPostfixExpression) - { - return RecursionUtil.postfixExpressionDefinitelyRecurses( - (JSPostfixExpression) exp, method); - } - if(exp instanceof JSBinaryExpression) - { - return RecursionUtil.binaryExpressionDefinitelyRecurses( - (JSBinaryExpression) exp, method); - } - if(exp instanceof JSConditionalExpression) - { - return RecursionUtil.conditionalExpressionDefinitelyRecurses( - (JSConditionalExpression) exp, method); - } - if(exp instanceof JSParenthesizedExpression) - { - return RecursionUtil.parenthesizedExpressionDefinitelyRecurses( - (JSParenthesizedExpression) exp, method); - } - if(exp instanceof JSReferenceExpression) - { - return RecursionUtil.referenceExpressionDefinitelyRecurses( - (JSReferenceExpression) exp, method); - } - if(exp instanceof JSLiteralExpression || - exp instanceof JSThisExpression) - { - return false; - } - return false; - } - - private static boolean conditionalExpressionDefinitelyRecurses( - JSConditionalExpression expression, JSFunction method) - { - final JSExpression condExpression = expression.getCondition(); - - return RecursionUtil.expressionDefinitelyRecurses(condExpression, method) || - (RecursionUtil.expressionDefinitelyRecurses(expression.getThen(), method) && - RecursionUtil.expressionDefinitelyRecurses(expression.getElse(), method)); - - } - - private static boolean binaryExpressionDefinitelyRecurses( - JSBinaryExpression expression, JSFunction method) - { - final JSExpression lhs = expression.getLOperand(); - - if(RecursionUtil.expressionDefinitelyRecurses(lhs, method)) - { - return true; - } - - final IElementType tokenType = expression.getOperationSign(); - - if(tokenType.equals(JSTokenTypes.ANDAND) || - tokenType.equals(JSTokenTypes.OROR)) - { - return false; - } - - return RecursionUtil.expressionDefinitelyRecurses(expression.getROperand(), method); - } - - private static boolean indexedPropertyAccessExpressionDefinitelyRecurses( - JSIndexedPropertyAccessExpression expression, JSFunction method) - { - final JSExpression arrayExp = expression.getQualifier(); - final JSExpression indexExp = expression.getIndexExpression(); - return (RecursionUtil.expressionDefinitelyRecurses(arrayExp, method) || - RecursionUtil.expressionDefinitelyRecurses(indexExp, method)); - } - - private static boolean arrayLiteralExpressionDefinitelyRecurses( - JSArrayLiteralExpression expression, JSFunction method) - { - for(final JSExpression initializer : expression.getExpressions()) - { - if(RecursionUtil.expressionDefinitelyRecurses(initializer, method)) - { - return true; - } - } - return false; - } - - private static boolean prefixExpressionDefinitelyRecurses( - JSPrefixExpression expression, JSFunction method) - { - final JSExpression operand = expression.getExpression(); - return RecursionUtil.expressionDefinitelyRecurses(operand, method); - } - - private static boolean postfixExpressionDefinitelyRecurses( - JSPostfixExpression expression, JSFunction method) - { - final JSExpression operand = expression.getExpression(); - return RecursionUtil.expressionDefinitelyRecurses(operand, method); - } - - private static boolean parenthesizedExpressionDefinitelyRecurses( - JSParenthesizedExpression expression, JSFunction method) - { - final JSExpression innerExpression = expression.getInnerExpression(); - return RecursionUtil.expressionDefinitelyRecurses(innerExpression, method); - } - - private static boolean referenceExpressionDefinitelyRecurses( - JSReferenceExpression expression, JSFunction method) - { - final JSExpression qualifierExpression = expression.getQualifier(); - return (qualifierExpression != null && - RecursionUtil.expressionDefinitelyRecurses(qualifierExpression, method)); - } - - private static boolean assignmentExpressionDefinitelyRecurses( - JSAssignmentExpression assignmentExpression, JSFunction method) - { - final JSExpression lhs = assignmentExpression.getLOperand(); - final JSExpression rhs = assignmentExpression.getROperand(); - return (RecursionUtil.expressionDefinitelyRecurses(rhs, method) || - RecursionUtil.expressionDefinitelyRecurses(lhs, method)); - } - - private static boolean newExpressionDefinitelyRecurses(JSNewExpression exp, - JSFunction method) - { - final JSArgumentList argumentList = exp.getArgumentList(); - if(argumentList != null) - { - final JSExpression[] args = argumentList.getArguments(); - for(final JSExpression arg : args) - { - if(RecursionUtil.expressionDefinitelyRecurses(arg, method)) - { - return true; - } - } - } - return false; - } - - private static boolean callExpressionDefinitelyRecurses( - JSCallExpression exp, JSFunction method) - { - final JSFunction calledMethod = ControlFlowUtils.resolveMethod(exp); - - if(calledMethod != null && calledMethod.equals(method)) - { - return true; - } - - final JSExpression methodExpression = exp.getMethodExpression(); - - if(methodExpression == null) - { - return false; - } - else if(RecursionUtil.expressionDefinitelyRecurses(methodExpression, method)) - { - return true; - } - - for(final JSExpression arg : exp.getArgumentList().getArguments()) - { - if(RecursionUtil.expressionDefinitelyRecurses(arg, method)) - { - return true; - } - } - return false; - } - - private static boolean statementDefinitelyRecurses(JSStatement statement, - JSFunction method) - { - if(statement == null) - { - return false; - } - if(statement instanceof JSBreakStatement || - statement instanceof JSContinueStatement || - statement instanceof JSThrowStatement || - statement instanceof JSEmptyStatement) - { - return false; - } - else if(statement instanceof JSExpressionStatement) - { - final JSExpressionStatement expressionStatement = - (JSExpressionStatement) statement; - final JSExpression expression = - expressionStatement.getExpression(); - return RecursionUtil.expressionDefinitelyRecurses(expression, method); - } - else if(statement instanceof JSVarStatement) - { - final JSVarStatement varStatement = - (JSVarStatement) statement; - for(final JSVariable variable : varStatement.getVariables()) - { - final JSExpression initializer = variable.getInitializer(); - if(RecursionUtil.expressionDefinitelyRecurses(initializer, method)) - { - return true; - } - } - return false; - } - else if(statement instanceof JSReturnStatement) - { - final JSReturnStatement returnStatement = - (JSReturnStatement) statement; - final JSExpression returnValue = returnStatement.getExpression(); - if(returnValue != null) - { - if(RecursionUtil.expressionDefinitelyRecurses(returnValue, method)) - { - return true; - } - } - return false; - } - else if(statement instanceof JSForStatement) - { - return RecursionUtil.forStatementDefinitelyRecurses((JSForStatement) - statement, method); - } - else if(statement instanceof JSForInStatement) - { - return RecursionUtil.forInStatementDefinitelyRecurses( - (JSForInStatement) statement, method); - } - else if(statement instanceof JSWhileStatement) - { - return RecursionUtil.whileStatementDefinitelyRecurses( - (JSWhileStatement) statement, method); - } - else if(statement instanceof JSDoWhileStatement) - { - return RecursionUtil.doWhileStatementDefinitelyRecurses( - (JSDoWhileStatement) statement, method); - } - else if(statement instanceof JSBlockStatement) - { - return RecursionUtil.blockStatementDefinitelyRecurses( - (JSBlockStatement) statement, method); - } - else if(statement instanceof JSLabeledStatement) - { - return RecursionUtil.labeledStatementDefinitelyRecurses( - (JSLabeledStatement) statement, method); - } - else if(statement instanceof JSIfStatement) - { - return RecursionUtil.ifStatementDefinitelyRecurses( - (JSIfStatement) statement, method); - } - else if(statement instanceof JSTryStatement) - { - return RecursionUtil.tryStatementDefinitelyRecurses( - (JSTryStatement) statement, method); - } - else if(statement instanceof JSSwitchStatement) - { - return RecursionUtil.switchStatementDefinitelyRecurses( - (JSSwitchStatement) statement, method); - } - else - { - // unknown statement type - return false; - } - } - - private static boolean switchStatementDefinitelyRecurses( - JSSwitchStatement switchStatement, JSFunction method) - { - final JSExpression switchExpression = switchStatement.getSwitchExpression(); - return RecursionUtil.expressionDefinitelyRecurses(switchExpression, method); - } - - private static boolean tryStatementDefinitelyRecurses( - JSTryStatement tryStatement, JSFunction method) - { - final JSStatement statement = tryStatement.getStatement(); - if(RecursionUtil.statementDefinitelyRecurses(statement, method)) - { - return true; - } - final JSStatement finallyStatement = tryStatement.getFinallyStatement(); - return RecursionUtil.statementDefinitelyRecurses(finallyStatement, method); - } - - private static boolean blockStatementDefinitelyRecurses(JSBlockStatement block, - JSFunction method) - { - if(block != null) - { - for(final JSStatement statement : block.getStatements()) - { - if(RecursionUtil.statementDefinitelyRecurses(statement, method)) - { - return true; - } - } - } - return false; - } - - private static boolean ifStatementDefinitelyRecurses( - JSIfStatement ifStatement, JSFunction method) - { - final JSExpression condition = ifStatement.getCondition(); - if(RecursionUtil.expressionDefinitelyRecurses(condition, method)) - { - return true; - } - final JSStatement thenBranch = ifStatement.getThen(); - final JSStatement elseBranch = ifStatement.getElse(); - if(thenBranch == null || elseBranch == null) - { - return false; - } - return RecursionUtil.statementDefinitelyRecurses(thenBranch, method) && - RecursionUtil.statementDefinitelyRecurses(elseBranch, method); - } - - private static boolean forStatementDefinitelyRecurses( - JSForStatement forStatement, JSFunction method) - { - final JSStatement declaration = forStatement.getVarDeclaration(); - final JSExpression initialization = forStatement.getInitialization(); - - if(declaration != null && - RecursionUtil.statementDefinitelyRecurses(declaration, method)) - { - return true; - } - else if(initialization != null && - RecursionUtil.expressionDefinitelyRecurses(initialization, method)) - { - return true; - } - - final JSExpression condition = forStatement.getCondition(); - - if(RecursionUtil.expressionDefinitelyRecurses(condition, method)) - { - return true; - } - if(BoolUtils.isTrue(condition)) - { - final JSStatement body = forStatement.getBody(); - return RecursionUtil.statementDefinitelyRecurses(body, method); - } - return false; - } - - private static boolean forInStatementDefinitelyRecurses( - JSForInStatement foreachStatement, JSFunction method) - { - final JSExpression collection = foreachStatement.getCollectionExpression(); - return RecursionUtil.expressionDefinitelyRecurses(collection, method); - } - - private static boolean whileStatementDefinitelyRecurses( - JSWhileStatement whileStatement, JSFunction method) - { - - final JSExpression condition = whileStatement.getCondition(); - if(RecursionUtil.expressionDefinitelyRecurses(condition, method)) - { - return true; - } - if(BoolUtils.isTrue(condition)) - { - final JSStatement body = whileStatement.getBody(); - return RecursionUtil.statementDefinitelyRecurses(body, method); - } - return false; - } - - private static boolean doWhileStatementDefinitelyRecurses( - JSDoWhileStatement doWhileStatement, JSFunction method) - { - - final JSStatement body = doWhileStatement.getBody(); - if(RecursionUtil.statementDefinitelyRecurses(body, method)) - { - return true; - } - final JSExpression condition = doWhileStatement.getCondition(); - return RecursionUtil.expressionDefinitelyRecurses(condition, method); - } - - private static boolean labeledStatementDefinitelyRecurses( - JSLabeledStatement labeledStatement, JSFunction method) - { - final JSStatement body = labeledStatement.getStatement(); - return RecursionUtil.statementDefinitelyRecurses(body, method); - } - - public static boolean functionDefinitelyRecurses( - @Nonnull JSFunction method) - { - final JSSourceElement[] body = method.getBody(); - - if(body != null) - { - for(final JSSourceElement element : body) - { - if(element instanceof JSStatement && - RecursionUtil.statementDefinitelyRecurses((JSStatement) element, method)) - { - return true; - } - else if(element instanceof JSExpression && - RecursionUtil.expressionDefinitelyRecurses((JSExpression) element, method)) - { - return true; - } - } - } - return false; - } +import jakarta.annotation.Nonnull; + +public class RecursionUtil { + private RecursionUtil() { + } + + public static boolean statementMayReturnBeforeRecursing(JSStatement statement, JSFunction method) { + if (statement == null) { + return true; + } + + if (statement instanceof JSBreakStatement + || statement instanceof JSContinueStatement + || statement instanceof JSThrowStatement + || statement instanceof JSExpressionStatement + || statement instanceof JSEmptyStatement + || statement instanceof JSVarStatement) { + return false; + } + else if (statement instanceof JSReturnStatement returnStatement) { + JSExpression returnValue = returnStatement.getExpression(); + return returnValue == null || !RecursionUtil.expressionDefinitelyRecurses(returnValue, method); + } + else if (statement instanceof JSForStatement forStatement) { + return RecursionUtil.forStatementMayReturnBeforeRecursing(forStatement, method); + } + else if (statement instanceof JSForInStatement forInStatement) { + return RecursionUtil.forInStatementMayReturnBeforeRecursing(forInStatement, method); + } + else if (statement instanceof JSWhileStatement whileStatement) { + return RecursionUtil.whileStatementMayReturnBeforeRecursing(whileStatement, method); + } + else if (statement instanceof JSDoWhileStatement doWhileStatement) { + return RecursionUtil.doWhileStatementMayReturnBeforeRecursing(doWhileStatement, method); + } + else if (statement instanceof JSBlockStatement blockStatement) { + return RecursionUtil.blockStatementMayReturnBeforeRecursing(blockStatement, method, false); + } + else if (statement instanceof JSLabeledStatement labeledStatement) { + return RecursionUtil.labeledStatementMayReturnBeforeRecursing(labeledStatement, method); + } + else if (statement instanceof JSIfStatement ifStatement) { + return RecursionUtil.ifStatementMayReturnBeforeRecursing(ifStatement, method); + } + else if (statement instanceof JSTryStatement tryStatement) { + return RecursionUtil.tryStatementMayReturnBeforeRecursing(tryStatement, method); + } + else if (statement instanceof JSSwitchStatement switchStatement) { + return RecursionUtil.switchStatementMayReturnBeforeRecursing(switchStatement, method); + } + else { + // unknown statement type + return true; + } + } + + private static boolean doWhileStatementMayReturnBeforeRecursing(JSDoWhileStatement loopStatement, JSFunction method) { + JSStatement body = loopStatement.getBody(); + return RecursionUtil.statementMayReturnBeforeRecursing(body, method); + } + + private static boolean whileStatementMayReturnBeforeRecursing(JSWhileStatement loopStatement, JSFunction method) { + JSExpression test = loopStatement.getCondition(); + if (RecursionUtil.expressionDefinitelyRecurses(test, method)) { + return false; + } + JSStatement body = loopStatement.getBody(); + return RecursionUtil.statementMayReturnBeforeRecursing(body, method); + } + + private static boolean forStatementMayReturnBeforeRecursing(JSForStatement loopStatement, JSFunction method) { + if (RecursionUtil.statementMayReturnBeforeRecursing(loopStatement.getVarDeclaration(), method)) { + return true; + } + if (RecursionUtil.expressionDefinitelyRecurses(loopStatement.getInitialization(), method)) { + return false; + } + if (RecursionUtil.expressionDefinitelyRecurses(loopStatement.getCondition(), method)) { + return false; + } + return RecursionUtil.statementMayReturnBeforeRecursing(loopStatement.getBody(), method); + } + + private static boolean forInStatementMayReturnBeforeRecursing(JSForInStatement loopStatement, JSFunction method) { + JSExpression collection = loopStatement.getCollectionExpression(); + if (RecursionUtil.expressionDefinitelyRecurses(collection, method)) { + return false; + } + JSStatement body = loopStatement.getBody(); + return RecursionUtil.statementMayReturnBeforeRecursing(body, method); + } + + private static boolean switchStatementMayReturnBeforeRecursing(JSSwitchStatement switchStatement, JSFunction method) { + for (JSCaseClause clause : switchStatement.getCaseClauses()) { + for (JSStatement statement : clause.getStatements()) { + if (RecursionUtil.statementMayReturnBeforeRecursing(statement, method)) { + return true; + } + } + } + return false; + } + + private static boolean tryStatementMayReturnBeforeRecursing(JSTryStatement tryStatement, JSFunction method) { + JSStatement finallyStatement = tryStatement.getFinallyStatement(); + + if (finallyStatement != null) { + if (RecursionUtil.statementMayReturnBeforeRecursing(finallyStatement, method)) { + return true; + } + if (RecursionUtil.statementDefinitelyRecurses(finallyStatement, method)) { + return false; + } + } + + JSStatement statement = tryStatement.getStatement(); + + if (RecursionUtil.statementMayReturnBeforeRecursing(statement, method)) { + return true; + } + + JSCatchBlock catchBlock = tryStatement.getCatchBlock(); + + if (catchBlock != null) { + JSStatement catchStatement = catchBlock.getStatement(); + + if (RecursionUtil.statementMayReturnBeforeRecursing(catchStatement, method)) { + return true; + } + } + return false; + } + + private static boolean ifStatementMayReturnBeforeRecursing(JSIfStatement ifStatement, JSFunction method) { + JSExpression test = ifStatement.getCondition(); + if (RecursionUtil.expressionDefinitelyRecurses(test, method)) { + return false; + } + JSStatement thenBranch = ifStatement.getThen(); + if (RecursionUtil.statementMayReturnBeforeRecursing(thenBranch, method)) { + return true; + } + JSStatement elseBranch = ifStatement.getElse(); + return elseBranch != null && RecursionUtil.statementMayReturnBeforeRecursing(elseBranch, method); + } + + private static boolean labeledStatementMayReturnBeforeRecursing(JSLabeledStatement labeledStatement, JSFunction method) { + JSStatement statement = labeledStatement.getStatement(); + return RecursionUtil.statementMayReturnBeforeRecursing(statement, method); + } + + private static boolean blockStatementMayReturnBeforeRecursing(JSBlockStatement block, JSFunction method, boolean endsInImplicitReturn) { + if (block == null) { + return true; + } + + JSStatement[] statements = block.getStatements(); + + for (JSStatement statement : statements) { + if (RecursionUtil.statementMayReturnBeforeRecursing(statement, method)) { + return true; + } + if (RecursionUtil.statementDefinitelyRecurses(statement, method)) { + return false; + } + } + return endsInImplicitReturn; + } + + public static boolean functionMayRecurse(@Nonnull JSFunction function) { + JSRecursionVisitor recursionVisitor = new JSRecursionVisitor(function); + + if (recursionVisitor.isFunctionNamed()) { + function.accept(recursionVisitor); + } + return recursionVisitor.isRecursive(); + } + + private static boolean expressionDefinitelyRecurses(JSExpression exp, JSFunction method) { + if (exp == null) { + return false; + } + if (exp instanceof JSNewExpression newExpression) { + return RecursionUtil.newExpressionDefinitelyRecurses(newExpression, method); + } + if (exp instanceof JSCallExpression callExpression) { + return RecursionUtil.callExpressionDefinitelyRecurses(callExpression, method); + } + if (exp instanceof JSAssignmentExpression assignmentExpression) { + return RecursionUtil.assignmentExpressionDefinitelyRecurses(assignmentExpression, method); + } + if (exp instanceof JSArrayLiteralExpression arrayLiteralExpression) { + return RecursionUtil.arrayLiteralExpressionDefinitelyRecurses(arrayLiteralExpression, method); + } + if (exp instanceof JSIndexedPropertyAccessExpression indexedPropertyAccessExpression) { + return RecursionUtil.indexedPropertyAccessExpressionDefinitelyRecurses(indexedPropertyAccessExpression, method); + } + if (exp instanceof JSPrefixExpression prefixExpression) { + return RecursionUtil.prefixExpressionDefinitelyRecurses(prefixExpression, method); + } + if (exp instanceof JSPostfixExpression postfixExpression) { + return RecursionUtil.postfixExpressionDefinitelyRecurses(postfixExpression, method); + } + if (exp instanceof JSBinaryExpression binaryExpression) { + return RecursionUtil.binaryExpressionDefinitelyRecurses(binaryExpression, method); + } + if (exp instanceof JSConditionalExpression conditionalExpression) { + return RecursionUtil.conditionalExpressionDefinitelyRecurses(conditionalExpression, method); + } + if (exp instanceof JSParenthesizedExpression parenthesizedExpression) { + return RecursionUtil.parenthesizedExpressionDefinitelyRecurses(parenthesizedExpression, method); + } + if (exp instanceof JSReferenceExpression referenceExpression) { + return RecursionUtil.referenceExpressionDefinitelyRecurses(referenceExpression, method); + } + if (exp instanceof JSLiteralExpression || exp instanceof JSThisExpression) { + return false; + } + return false; + } + + private static boolean conditionalExpressionDefinitelyRecurses(JSConditionalExpression expression, JSFunction method) { + JSExpression condExpression = expression.getCondition(); + + return RecursionUtil.expressionDefinitelyRecurses(condExpression, method) || + (RecursionUtil.expressionDefinitelyRecurses(expression.getThen(), method) && + RecursionUtil.expressionDefinitelyRecurses(expression.getElse(), method)); + } + + private static boolean binaryExpressionDefinitelyRecurses(JSBinaryExpression expression, JSFunction method) { + JSExpression lhs = expression.getLOperand(); + + if (RecursionUtil.expressionDefinitelyRecurses(lhs, method)) { + return true; + } + + IElementType tokenType = expression.getOperationSign(); + + if (JSTokenTypes.ANDAND.equals(tokenType) || JSTokenTypes.OROR.equals(tokenType)) { + return false; + } + + return RecursionUtil.expressionDefinitelyRecurses(expression.getROperand(), method); + } + + private static boolean indexedPropertyAccessExpressionDefinitelyRecurses( + JSIndexedPropertyAccessExpression expression, + JSFunction method + ) { + JSExpression arrayExp = expression.getQualifier(); + JSExpression indexExp = expression.getIndexExpression(); + return RecursionUtil.expressionDefinitelyRecurses(arrayExp, method) + || RecursionUtil.expressionDefinitelyRecurses(indexExp, method); + } + + private static boolean arrayLiteralExpressionDefinitelyRecurses(JSArrayLiteralExpression expression, JSFunction method) { + for (JSExpression initializer : expression.getExpressions()) { + if (RecursionUtil.expressionDefinitelyRecurses(initializer, method)) { + return true; + } + } + return false; + } + + private static boolean prefixExpressionDefinitelyRecurses(JSPrefixExpression expression, JSFunction method) { + JSExpression operand = expression.getExpression(); + return RecursionUtil.expressionDefinitelyRecurses(operand, method); + } + + private static boolean postfixExpressionDefinitelyRecurses(JSPostfixExpression expression, JSFunction method) { + JSExpression operand = expression.getExpression(); + return RecursionUtil.expressionDefinitelyRecurses(operand, method); + } + + private static boolean parenthesizedExpressionDefinitelyRecurses(JSParenthesizedExpression expression, JSFunction method) { + JSExpression innerExpression = expression.getInnerExpression(); + return RecursionUtil.expressionDefinitelyRecurses(innerExpression, method); + } + + private static boolean referenceExpressionDefinitelyRecurses(JSReferenceExpression expression, JSFunction method) { + JSExpression qualifierExpression = expression.getQualifier(); + return (qualifierExpression != null && + RecursionUtil.expressionDefinitelyRecurses(qualifierExpression, method)); + } + + private static boolean assignmentExpressionDefinitelyRecurses(JSAssignmentExpression assignmentExpression, JSFunction method) { + JSExpression lhs = assignmentExpression.getLOperand(); + JSExpression rhs = assignmentExpression.getROperand(); + return RecursionUtil.expressionDefinitelyRecurses(rhs, method) + || RecursionUtil.expressionDefinitelyRecurses(lhs, method); + } + + private static boolean newExpressionDefinitelyRecurses(JSNewExpression exp, JSFunction method) { + JSArgumentList argumentList = exp.getArgumentList(); + if (argumentList != null) { + JSExpression[] args = argumentList.getArguments(); + for (JSExpression arg : args) { + if (RecursionUtil.expressionDefinitelyRecurses(arg, method)) { + return true; + } + } + } + return false; + } + + private static boolean callExpressionDefinitelyRecurses(JSCallExpression exp, JSFunction method) { + JSFunction calledMethod = ControlFlowUtils.resolveMethod(exp); + + if (calledMethod != null && calledMethod.equals(method)) { + return true; + } + + JSExpression methodExpression = exp.getMethodExpression(); + + if (methodExpression == null) { + return false; + } + else if (RecursionUtil.expressionDefinitelyRecurses(methodExpression, method)) { + return true; + } + + for (JSExpression arg : exp.getArgumentList().getArguments()) { + if (RecursionUtil.expressionDefinitelyRecurses(arg, method)) { + return true; + } + } + return false; + } + + private static boolean statementDefinitelyRecurses(JSStatement statement, JSFunction method) { + if (statement == null) { + return false; + } + if (statement instanceof JSBreakStatement + || statement instanceof JSContinueStatement + || statement instanceof JSThrowStatement + || statement instanceof JSEmptyStatement) { + return false; + } + else if (statement instanceof JSExpressionStatement expressionStatement) { + JSExpression expression = expressionStatement.getExpression(); + return RecursionUtil.expressionDefinitelyRecurses(expression, method); + } + else if (statement instanceof JSVarStatement varStatement) { + for (JSVariable variable : varStatement.getVariables()) { + JSExpression initializer = variable.getInitializer(); + if (RecursionUtil.expressionDefinitelyRecurses(initializer, method)) { + return true; + } + } + return false; + } + else if (statement instanceof JSReturnStatement returnStatement) { + JSExpression returnValue = returnStatement.getExpression(); + if (returnValue != null) { + if (RecursionUtil.expressionDefinitelyRecurses(returnValue, method)) { + return true; + } + } + return false; + } + else if (statement instanceof JSForStatement forStatement) { + return RecursionUtil.forStatementDefinitelyRecurses(forStatement, method); + } + else if (statement instanceof JSForInStatement forInStatement) { + return RecursionUtil.forInStatementDefinitelyRecurses(forInStatement, method); + } + else if (statement instanceof JSWhileStatement whileStatement) { + return RecursionUtil.whileStatementDefinitelyRecurses(whileStatement, method); + } + else if (statement instanceof JSDoWhileStatement doWhileStatement) { + return RecursionUtil.doWhileStatementDefinitelyRecurses(doWhileStatement, method); + } + else if (statement instanceof JSBlockStatement blockStatement) { + return RecursionUtil.blockStatementDefinitelyRecurses(blockStatement, method); + } + else if (statement instanceof JSLabeledStatement labeledStatement) { + return RecursionUtil.labeledStatementDefinitelyRecurses(labeledStatement, method); + } + else if (statement instanceof JSIfStatement ifStatement) { + return RecursionUtil.ifStatementDefinitelyRecurses(ifStatement, method); + } + else if (statement instanceof JSTryStatement tryStatement) { + return RecursionUtil.tryStatementDefinitelyRecurses(tryStatement, method); + } + else if (statement instanceof JSSwitchStatement switchStatement) { + return RecursionUtil.switchStatementDefinitelyRecurses(switchStatement, method); + } + else { + // unknown statement type + return false; + } + } + + private static boolean switchStatementDefinitelyRecurses(JSSwitchStatement switchStatement, JSFunction method) { + JSExpression switchExpression = switchStatement.getSwitchExpression(); + return RecursionUtil.expressionDefinitelyRecurses(switchExpression, method); + } + + private static boolean tryStatementDefinitelyRecurses(JSTryStatement tryStatement, JSFunction method) { + JSStatement statement = tryStatement.getStatement(); + if (RecursionUtil.statementDefinitelyRecurses(statement, method)) { + return true; + } + JSStatement finallyStatement = tryStatement.getFinallyStatement(); + return RecursionUtil.statementDefinitelyRecurses(finallyStatement, method); + } + + private static boolean blockStatementDefinitelyRecurses(JSBlockStatement block, JSFunction method) { + if (block != null) { + for (JSStatement statement : block.getStatements()) { + if (RecursionUtil.statementDefinitelyRecurses(statement, method)) { + return true; + } + } + } + return false; + } + + private static boolean ifStatementDefinitelyRecurses(JSIfStatement ifStatement, JSFunction method) { + JSExpression condition = ifStatement.getCondition(); + if (RecursionUtil.expressionDefinitelyRecurses(condition, method)) { + return true; + } + JSStatement thenBranch = ifStatement.getThen(); + JSStatement elseBranch = ifStatement.getElse(); + if (thenBranch == null || elseBranch == null) { + return false; + } + return RecursionUtil.statementDefinitelyRecurses(thenBranch, method) + && RecursionUtil.statementDefinitelyRecurses(elseBranch, method); + } + + private static boolean forStatementDefinitelyRecurses(JSForStatement forStatement, JSFunction method) { + JSStatement declaration = forStatement.getVarDeclaration(); + JSExpression initialization = forStatement.getInitialization(); + + if (declaration != null && + RecursionUtil.statementDefinitelyRecurses(declaration, method)) { + return true; + } + else if (initialization != null && + RecursionUtil.expressionDefinitelyRecurses(initialization, method)) { + return true; + } + + JSExpression condition = forStatement.getCondition(); + + if (RecursionUtil.expressionDefinitelyRecurses(condition, method)) { + return true; + } + if (BoolUtils.isTrue(condition)) { + JSStatement body = forStatement.getBody(); + return RecursionUtil.statementDefinitelyRecurses(body, method); + } + return false; + } + + private static boolean forInStatementDefinitelyRecurses(JSForInStatement foreachStatement, JSFunction method) { + JSExpression collection = foreachStatement.getCollectionExpression(); + return RecursionUtil.expressionDefinitelyRecurses(collection, method); + } + + private static boolean whileStatementDefinitelyRecurses(JSWhileStatement whileStatement, JSFunction method) { + JSExpression condition = whileStatement.getCondition(); + if (RecursionUtil.expressionDefinitelyRecurses(condition, method)) { + return true; + } + if (BoolUtils.isTrue(condition)) { + JSStatement body = whileStatement.getBody(); + return RecursionUtil.statementDefinitelyRecurses(body, method); + } + return false; + } + + private static boolean doWhileStatementDefinitelyRecurses(JSDoWhileStatement doWhileStatement, JSFunction method) { + JSStatement body = doWhileStatement.getBody(); + if (RecursionUtil.statementDefinitelyRecurses(body, method)) { + return true; + } + JSExpression condition = doWhileStatement.getCondition(); + return RecursionUtil.expressionDefinitelyRecurses(condition, method); + } + + private static boolean labeledStatementDefinitelyRecurses(JSLabeledStatement labeledStatement, JSFunction method) { + JSStatement body = labeledStatement.getStatement(); + return RecursionUtil.statementDefinitelyRecurses(body, method); + } + + public static boolean functionDefinitelyRecurses(@Nonnull JSFunction method) { + JSSourceElement[] body = method.getBody(); + + if (body != null) { + for (JSSourceElement element : body) { + if (element instanceof JSStatement && + RecursionUtil.statementDefinitelyRecurses((JSStatement)element, method)) { + return true; + } + else if (element instanceof JSExpression && + RecursionUtil.expressionDefinitelyRecurses((JSExpression)element, method)) { + return true; + } + } + } + return false; + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/SideEffectChecker.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/SideEffectChecker.java index 0393c7b8..a6d853fa 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/SideEffectChecker.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/SideEffectChecker.java @@ -19,81 +19,63 @@ import com.intellij.lang.javascript.psi.*; import consulo.language.ast.IElementType; -public class SideEffectChecker -{ - private SideEffectChecker() - { - } +public class SideEffectChecker { + private SideEffectChecker() { + } - public static boolean mayHaveSideEffects(JSExpression exp) - { - final SideEffectsVisitor visitor = new SideEffectsVisitor(); - exp.accept(visitor); - return visitor.mayHaveSideEffects(); - } + public static boolean mayHaveSideEffects(JSExpression exp) { + SideEffectsVisitor visitor = new SideEffectsVisitor(); + exp.accept(visitor); + return visitor.mayHaveSideEffects(); + } - private static class SideEffectsVisitor extends JSRecursiveElementVisitor - { - private boolean mayHaveSideEffects; + private static class SideEffectsVisitor extends JSRecursiveElementVisitor { + private boolean mayHaveSideEffects; - @Override - public void visitJSElement(JSElement element) - { - if(!this.mayHaveSideEffects) - { - super.visitJSElement(element); - } - } + @Override + public void visitJSElement(JSElement element) { + if (!this.mayHaveSideEffects) { + super.visitJSElement(element); + } + } - @Override - public void visitJSCallExpression(JSCallExpression expression) - { - this.mayHaveSideEffects = true; - } + @Override + public void visitJSCallExpression(JSCallExpression expression) { + this.mayHaveSideEffects = true; + } - @Override - public void visitJSNewExpression(JSNewExpression expression) - { - this.mayHaveSideEffects = true; - } + @Override + public void visitJSNewExpression(JSNewExpression expression) { + this.mayHaveSideEffects = true; + } - @Override - public void visitJSAssignmentExpression(JSAssignmentExpression expression) - { - this.mayHaveSideEffects = true; - } + @Override + public void visitJSAssignmentExpression(JSAssignmentExpression expression) { + this.mayHaveSideEffects = true; + } - @Override - public void visitJSPrefixExpression(JSPrefixExpression expression) - { - super.visitJSPrefixExpression(expression); - final IElementType sign = expression.getOperationSign(); + @Override + public void visitJSPrefixExpression(JSPrefixExpression expression) { + super.visitJSPrefixExpression(expression); + IElementType sign = expression.getOperationSign(); - if(sign != null && - (sign.equals(JSTokenTypes.PLUSPLUS) || - sign.equals(JSTokenTypes.MINUSMINUS))) - { - this.mayHaveSideEffects = true; - } - } + if (sign != null && (JSTokenTypes.PLUSPLUS.equals(sign) || JSTokenTypes.MINUSMINUS.equals(sign))) { + this.mayHaveSideEffects = true; + } + } - @Override - public void visitJSPostfixExpression(JSPostfixExpression expression) - { - super.visitJSPostfixExpression(expression); - final IElementType sign = expression.getOperationSign(); + @Override + public void visitJSPostfixExpression(JSPostfixExpression expression) { + super.visitJSPostfixExpression(expression); + IElementType sign = expression.getOperationSign(); - if(sign != null && - (sign.equals(JSTokenTypes.PLUSPLUS) || - sign.equals(JSTokenTypes.MINUSMINUS))) - { - this.mayHaveSideEffects = true; - } - } + if (sign != null && (JSTokenTypes.PLUSPLUS.equals(sign) || JSTokenTypes.MINUSMINUS.equals(sign))) { + this.mayHaveSideEffects = true; + } + } - public boolean mayHaveSideEffects() - { - return this.mayHaveSideEffects; - } - } + public boolean mayHaveSideEffects() { + return this.mayHaveSideEffects; + } + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/TreeUtil.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/TreeUtil.java index 3f694678..fa1d2e14 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/TreeUtil.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/TreeUtil.java @@ -18,165 +18,145 @@ import com.intellij.lang.javascript.psi.JSElement; import consulo.language.psi.PsiElement; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public class TreeUtil -{ - private TreeUtil() - { - } - - public static PsiElement getNextLeaf(PsiElement element) - { - if(element == null) - { - return null; - } - final PsiElement sibling = element.getNextSibling(); - if(sibling == null) - { - final PsiElement parent = element.getParent(); - return getNextLeaf(parent); - } - return getFirstLeaf(sibling); - } - - private static PsiElement getFirstLeaf(PsiElement element) - { - final PsiElement[] children = element.getChildren(); - if(children.length == 0) - { - return element; - } - return getFirstLeaf(children[0]); - } - - public static PsiElement getPrevLeaf(PsiElement element) - { - if(element == null) - { - return null; - } - final PsiElement sibling = element.getPrevSibling(); - if(sibling == null) - { - final PsiElement parent = element.getParent(); - return getPrevLeaf(parent); - } - return getLastLeaf(sibling); - } - - private static PsiElement getLastLeaf(PsiElement element) - { - final PsiElement[] children = element.getChildren(); - if(children.length == 0) - { - return element; - } - return getLastLeaf(children[children.length - 1]); - } - - @Nullable - public static ParentType getParentOfType(@Nullable PsiElement element, - @Nonnull Class aClass) - { - return getParentOfType(element, aClass, true); - } - - public static ParentType getParentOfType(PsiElement element, - Class aClass, - boolean strict) - { - if(element == null) - { - return null; - } - if(strict) - { - element = element.getParent(); - } - - while(element != null && !aClass.isInstance(element)) - { - element = element.getParent(); - } - - return (ParentType) element; - } - - @Nullable - public static ParentType getPrevLeafOfType(@Nullable PsiElement element, - @Nonnull Class aClass) - { - return getPrevLeafOfType(element, aClass, true); - } - - public static ParentType getPrevLeafOfType(PsiElement element, - Class aClass, - boolean strict) - { - if(element == null) - { - return null; - } - if(strict) - { - element = getPrevLeaf(element); - } - - while(element != null && !aClass.isInstance(element)) - { - element = getPrevLeaf(element); - } - - return (ParentType) element; - } - - @Nullable - public static ParentType getNextLeafOfType(@Nullable PsiElement element, - @Nonnull Class aClass) - { - return getNextLeafOfType(element, aClass, true); - } - - public static ParentType getNextLeafOfType(PsiElement element, - Class aClass, - boolean strict) - { - if(element == null) - { - return null; - } - if(strict) - { - element = getNextLeaf(element); - } - - while(element != null && !aClass.isInstance(element)) - { - element = getNextLeaf(element); - } - - return (ParentType) element; - } - - public static boolean isAncestor(@Nonnull JSElement ancestor, - @Nonnull JSElement element, - boolean strict) - { - PsiElement parent = (strict ? element.getParent() : element); - - while(parent != null && parent instanceof JSElement) - { - if(parent.equals(ancestor)) - { - return true; - } - - parent = parent.getParent(); - } - - return false; - } +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; + +public class TreeUtil { + private TreeUtil() { + } + + public static PsiElement getNextLeaf(PsiElement element) { + if (element == null) { + return null; + } + PsiElement sibling = element.getNextSibling(); + if (sibling == null) { + PsiElement parent = element.getParent(); + return getNextLeaf(parent); + } + return getFirstLeaf(sibling); + } + + private static PsiElement getFirstLeaf(PsiElement element) { + PsiElement[] children = element.getChildren(); + if (children.length == 0) { + return element; + } + return getFirstLeaf(children[0]); + } + + public static PsiElement getPrevLeaf(PsiElement element) { + if (element == null) { + return null; + } + PsiElement sibling = element.getPrevSibling(); + if (sibling == null) { + PsiElement parent = element.getParent(); + return getPrevLeaf(parent); + } + return getLastLeaf(sibling); + } + + private static PsiElement getLastLeaf(PsiElement element) { + PsiElement[] children = element.getChildren(); + if (children.length == 0) { + return element; + } + return getLastLeaf(children[children.length - 1]); + } + + @Nullable + public static ParentType getParentOfType( + @Nullable PsiElement element, + @Nonnull Class aClass + ) { + return getParentOfType(element, aClass, true); + } + + public static ParentType getParentOfType( + PsiElement element, + Class aClass, + boolean strict + ) { + if (element == null) { + return null; + } + if (strict) { + element = element.getParent(); + } + + while (element != null && !aClass.isInstance(element)) { + element = element.getParent(); + } + + return (ParentType)element; + } + + @Nullable + public static ParentType getPrevLeafOfType( + @Nullable PsiElement element, + @Nonnull Class aClass + ) { + return getPrevLeafOfType(element, aClass, true); + } + + public static ParentType getPrevLeafOfType( + PsiElement element, + Class aClass, + boolean strict + ) { + if (element == null) { + return null; + } + if (strict) { + element = getPrevLeaf(element); + } + + while (element != null && !aClass.isInstance(element)) { + element = getPrevLeaf(element); + } + + return (ParentType)element; + } + + @Nullable + public static ParentType getNextLeafOfType( + @Nullable PsiElement element, + @Nonnull Class aClass + ) { + return getNextLeafOfType(element, aClass, true); + } + + public static ParentType getNextLeafOfType( + PsiElement element, + Class aClass, + boolean strict + ) { + if (element == null) { + return null; + } + if (strict) { + element = getNextLeaf(element); + } + + while (element != null && !aClass.isInstance(element)) { + element = getNextLeaf(element); + } + + return (ParentType)element; + } + + public static boolean isAncestor(@Nonnull JSElement ancestor, @Nonnull JSElement element, boolean strict) { + PsiElement parent = strict ? element.getParent() : element; + + while (parent != null && parent instanceof JSElement) { + if (parent.equals(ancestor)) { + return true; + } + + parent = parent.getParent(); + } + + return false; + } } diff --git a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/VariableAccessUtil.java b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/VariableAccessUtil.java index 7122df6a..e2a6e067 100644 --- a/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/VariableAccessUtil.java +++ b/intentions/src/main/java/org/intellij/idea/lang/javascript/psiutil/VariableAccessUtil.java @@ -20,538 +20,441 @@ import consulo.language.ast.IElementType; import consulo.language.psi.PsiElement; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; + import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; -public class VariableAccessUtil -{ - - private VariableAccessUtil() - { - } - - public static boolean variableIsAssignedFrom(JSVariable variable, - JSElement context) - { - final VariableAssignedFromVisitor visitor = new VariableAssignedFromVisitor(variable); - context.accept(visitor); - return visitor.isAssignedFrom(); - } - - // public static boolean variableIsPassedAsMethodArgument( - // JSVariable variable, JSElement context) { - // final VariablePassedAsArgumentVisitor visitor = - // new VariablePassedAsArgumentVisitor(variable); - // context.accept(visitor); - // return visitor.isPassed(); - // } - - // public static boolean variableIsUsedInArrayInitializer( - // JSVariable variable, JSElement context) { - // final VariableUsedInArrayInitializerVisitor visitor = - // new VariableUsedInArrayInitializerVisitor(variable); - // context.accept(visitor); - // return visitor.isPassed(); - // } - - public static boolean variableIsAssigned( - JSVariable variable, JSElement context) - { - //noinspection unchecked - return variableIsAssigned(variable, context, Collections.EMPTY_SET, Collections.EMPTY_SET); - } - - public static boolean variableIsAssigned( - JSVariable variable, - JSElement context, - Set notUpdatedSymbols) - { - //noinspection unchecked - return variableIsAssigned(variable, context, notUpdatedSymbols, Collections.EMPTY_SET); - } - - private static boolean variableIsAssigned( - JSVariable variable, - JSElement context, - Set notUpdatedSymbols, - Set candidateSymbols) - { - final VariableAssignedVisitor visitor = new VariableAssignedVisitor(variable, context, notUpdatedSymbols, - candidateSymbols); - context.accept(visitor); - return visitor.isAssigned(); - } - - public static boolean variableIsReturned( - JSVariable variable, JSElement context) - { - final VariableReturnedVisitor visitor = new VariableReturnedVisitor(variable); - context.accept(visitor); - return visitor.isReturned(); - } - - public static boolean arrayContentsAreAccessed( - JSVariable variable, JSElement context) - { - final ArrayContentsAccessedVisitor visitor = new ArrayContentsAccessedVisitor(variable); - context.accept(visitor); - return visitor.isAccessed(); - } - - public static boolean arrayContentsAreAssigned( - JSVariable variable, JSElement context) - { - final ArrayContentsAssignedVisitor visitor = new ArrayContentsAssignedVisitor(variable); - context.accept(visitor); - return visitor.isAssigned(); - } - - public static boolean mayEvaluateToVariable(JSExpression expression, - JSVariable variable) - { - final String variableName = variable.getName(); - JSExpression expr = expression; - - if(variableName == null) - { - return false; - } - - while(true) - { - if(expr == null) - { - return false; - } - else if(expr instanceof JSParenthesizedExpression) - { - expr = ((JSParenthesizedExpression) expr).getInnerExpression(); - } - else if(expr instanceof JSConditionalExpression) - { - final JSConditionalExpression conditional = (JSConditionalExpression) expr; - - return (mayEvaluateToVariable(conditional.getThen(), variable) || - mayEvaluateToVariable(conditional.getElse(), variable)); - } - else if(expr instanceof JSIndexedPropertyAccessExpression) - { - expr = ((JSIndexedPropertyAccessExpression) expr).getQualifier(); - } - else if(expr instanceof JSDefinitionExpression) - { - expr = ((JSDefinitionExpression) expr).getExpression(); - } - else if(expr instanceof JSReferenceExpression) - { - final PsiElement referent = ((JSReferenceExpression) expr).resolve(); - - return (referent != null && referent.equals(variable)); - } - else - { - return false; - } - } - } - - public static boolean variableIsUsed(JSVariable variable, - PsiElement context) - { - return (variable.getName() != null && - FindReferenceUtil.getReferences(variable, context).iterator().hasNext()); - } - - public static Set getUsedVariables(PsiElement context) - { - final UsedVariableVisitor visitor = new UsedVariableVisitor(); - context.accept(visitor); - return visitor.getVariables(); - } - - private static class VariableAssignedVisitor extends JSRecursiveElementVisitor - { - private final JSVariable variable; - private final JSElement context; - private Set notUpdatedSymbols; - private final Set candidateSymbols; - private boolean assigned; - - public VariableAssignedVisitor(@Nonnull JSVariable variable, - @Nonnull JSElement context, - @Nonnull Set notUpdatedSymbols) - { - this.variable = variable; - this.context = context; - this.notUpdatedSymbols = notUpdatedSymbols; - this.candidateSymbols = new LinkedHashSet<>(); - - this.candidateSymbols.add(variable); - } - - private VariableAssignedVisitor(@Nonnull JSVariable variable, - @Nonnull JSElement context, - @Nonnull Set notUpdatedSymbols, - @Nonnull Set candidateSymbols) - { - this.variable = variable; - this.context = context; - this.notUpdatedSymbols = notUpdatedSymbols; - this.candidateSymbols = candidateSymbols; - } - - @Override - public void visitJSElement(JSElement element) - { - if(!this.assigned) - { - super.visitJSElement(element); - } - } - - @Override - public void visitJSAssignmentExpression(JSAssignmentExpression assignment) - { - if(!this.assigned) - { - super.visitJSAssignmentExpression(assignment); - - final JSExpression arg = assignment.getLOperand(); - - if(VariableAccessUtil.mayEvaluateToVariable(arg, this.variable)) - { - final Set usedVariables = getUsedVariables(assignment.getROperand()); - final Set newCandidateSet = new LinkedHashSet<>(); - boolean assigned = false; - - newCandidateSet.addAll(this.candidateSymbols); - newCandidateSet.add(this.variable); - for(JSVariable variable : usedVariables) - { - if(newCandidateSet.contains(variable) || - variableIsAssigned(variable, this.context, this.notUpdatedSymbols, newCandidateSet)) - { - assigned = true; - } - else - { - if(this.notUpdatedSymbols.isEmpty()) - { - this.notUpdatedSymbols = new LinkedHashSet<>(); - } - this.notUpdatedSymbols.add(variable); - } - } - this.assigned = assigned; - } - else - { - this.assigned = false; - } - } - } - - @Override - public void visitJSPrefixExpression(JSPrefixExpression expression) - { - if(!this.assigned) - { - super.visitJSPrefixExpression(expression); - - final IElementType tokenType = expression.getOperationSign(); - - if(!(tokenType.equals(JSTokenTypes.PLUSPLUS) || - tokenType.equals(JSTokenTypes.MINUSMINUS))) - { - return; - } - - final JSExpression operand = expression.getExpression(); - - this.assigned = (VariableAccessUtil.mayEvaluateToVariable(operand, this.variable)); - } - } - - @Override - public void visitJSPostfixExpression(JSPostfixExpression postfixExpression) - { - if(!this.assigned) - { - super.visitJSPostfixExpression(postfixExpression); - - final IElementType tokenType = postfixExpression.getOperationSign(); - - if(!(tokenType.equals(JSTokenTypes.PLUSPLUS) || - tokenType.equals(JSTokenTypes.MINUSMINUS))) - { - return; - } - - final JSExpression operand = postfixExpression.getExpression(); - - this.assigned = VariableAccessUtil.mayEvaluateToVariable(operand, this.variable); - } - } - - public boolean isAssigned() - { - return this.assigned; - } - } - - private static class VariableAssignedFromVisitor extends JSRecursiveElementVisitor - { - private final JSVariable variable; - private boolean assignedFrom; - - public VariableAssignedFromVisitor(@Nonnull JSVariable variable) - { - this.variable = variable; - } - - @Override - public void visitJSElement(@Nonnull JSElement element) - { - if(!this.assignedFrom) - { - super.visitJSElement(element); - } - } - - @Override - public void visitJSAssignmentExpression(@Nonnull JSAssignmentExpression assignment) - { - if(!this.assignedFrom) - { - super.visitJSAssignmentExpression(assignment); - - this.assignedFrom = VariableAccessUtil.mayEvaluateToVariable(assignment.getROperand(), this.variable); - } - } - - @Override - public void visitJSVarStatement(@Nonnull JSVarStatement statement) - { - if(!this.assignedFrom) - { - super.visitJSVarStatement(statement); - - for(JSVariable declaredVariable : statement.getVariables()) - { - final JSExpression initializer = declaredVariable.getInitializer(); - - if(initializer != null) - { - this.assignedFrom = VariableAccessUtil.mayEvaluateToVariable(initializer, this.variable); - } - } - } - } - - @Override - public void visitJSVariable(JSVariable var) - { - if(!this.assignedFrom) - { - super.visitJSVariable(var); - this.assignedFrom = (VariableAccessUtil.mayEvaluateToVariable(var.getInitializer(), this.variable)); - } - } - - public boolean isAssignedFrom() - { - return this.assignedFrom; - } - } - - private static class VariableReturnedVisitor extends JSRecursiveElementVisitor - { - @Nonnull - private final JSVariable variable; - private boolean returned; - - public VariableReturnedVisitor(@Nonnull JSVariable variable) - { - this.variable = variable; - } - - @Override - public void visitJSReturnStatement(@Nonnull JSReturnStatement returnStatement) - { - if(!this.returned) - { - super.visitJSReturnStatement(returnStatement); - this.returned = VariableAccessUtil.mayEvaluateToVariable(returnStatement.getExpression(), this.variable); - } - } - - public boolean isReturned() - { - return this.returned; - } - } - - private static class ArrayContentsAccessedVisitor extends JSRecursiveElementVisitor - { - private final JSVariable variable; - private boolean accessed; - - public ArrayContentsAccessedVisitor(@Nonnull JSVariable variable) - { - this.variable = variable; - } - - @Override - public void visitJSForInStatement(@Nonnull JSForInStatement statement) - { - if(!this.accessed) - { - super.visitJSForInStatement(statement); - this.checkQualifier(statement.getCollectionExpression()); - } - } - - @Override - public void visitJSIndexedPropertyAccessExpression(@Nonnull JSIndexedPropertyAccessExpression accessExpression) - { - if(!this.accessed) - { - super.visitJSIndexedPropertyAccessExpression(accessExpression); - - final PsiElement parent = accessExpression.getParent(); - - if(!(parent instanceof JSAssignmentExpression || - ((JSAssignmentExpression) parent).getLOperand().equals(accessExpression))) - { - this.checkQualifier(accessExpression.getQualifier()); - } - } - } - - private void checkQualifier(JSExpression qualifier) - { - if(qualifier instanceof JSReferenceExpression) - { - final PsiElement referent = ((JSReferenceExpression) qualifier).resolve(); - - this.accessed = (referent != null && referent.equals(this.variable)); - } - } - - public boolean isAccessed() - { - return this.accessed; - } - } - - private static class ArrayContentsAssignedVisitor extends JSRecursiveElementVisitor - { - private final JSVariable variable; - private boolean assigned; - - public ArrayContentsAssignedVisitor(@Nonnull JSVariable variable) - { - this.variable = variable; - } - - @Override - public void visitJSAssignmentExpression(@Nonnull JSAssignmentExpression assignment) - { - if(!this.assigned) - { - super.visitJSAssignmentExpression(assignment); - this.checkExpression(null, assignment.getLOperand()); - } - } - - @Override - public void visitJSPrefixExpression(@Nonnull JSPrefixExpression expression) - { - if(!this.assigned) - { - super.visitJSPrefixExpression(expression); - this.checkExpression(expression.getOperationSign(), expression.getExpression()); - } - } - - @Override - public void visitJSPostfixExpression(@Nonnull JSPostfixExpression expression) - { - if(!this.assigned) - { - super.visitJSPostfixExpression(expression); - this.checkExpression(expression.getOperationSign(), expression.getExpression()); - } - } - - private void checkExpression(IElementType tokenType, JSExpression expression) - { - if(!(tokenType == null || - tokenType.equals(JSTokenTypes.PLUSPLUS) || - tokenType.equals(JSTokenTypes.MINUSMINUS))) - { - return; - } - if(!(expression instanceof JSIndexedPropertyAccessExpression)) - { - return; - } - - JSExpression arrayExpression = ((JSIndexedPropertyAccessExpression) expression).getQualifier(); - - while(arrayExpression instanceof JSIndexedPropertyAccessExpression) - { - final JSIndexedPropertyAccessExpression accessExpression = (JSIndexedPropertyAccessExpression) arrayExpression; - - arrayExpression = accessExpression.getQualifier(); - } - - if(arrayExpression instanceof JSReferenceExpression) - { - final String referencedName = ((JSReferenceExpression) arrayExpression).getReferencedName(); - - - // TODO maybe it's better to check ((JSReferenceExpression) arrayExpression).isReferenceTo(variable) ? - this.assigned = referencedName != null && referencedName.equals(this.variable.getName()); - } - } - - public boolean isAssigned() - { - return this.assigned; - } - } - - private static class UsedVariableVisitor extends JSRecursiveElementVisitor - { - - @Nonnull - private final Set variables; - - public UsedVariableVisitor() - { - this.variables = new HashSet(); - } - - @Override - public void visitJSReferenceExpression(@Nonnull JSReferenceExpression ref) - { - super.visitJSReferenceExpression(ref); - - final PsiElement referent = ref.resolve(); - - if(referent != null && referent instanceof JSVariable) - { - this.variables.add((JSVariable) referent); - } - } - - public Set getVariables() - { - return this.variables; - } - } +public class VariableAccessUtil { + private VariableAccessUtil() { + } + + public static boolean variableIsAssignedFrom( + JSVariable variable, + JSElement context + ) { + VariableAssignedFromVisitor visitor = new VariableAssignedFromVisitor(variable); + context.accept(visitor); + return visitor.isAssignedFrom(); + } + + // public static boolean variableIsPassedAsMethodArgument( + // JSVariable variable, JSElement context) { + // final VariablePassedAsArgumentVisitor visitor = + // new VariablePassedAsArgumentVisitor(variable); + // context.accept(visitor); + // return visitor.isPassed(); + // } + + // public static boolean variableIsUsedInArrayInitializer( + // JSVariable variable, JSElement context) { + // final VariableUsedInArrayInitializerVisitor visitor = + // new VariableUsedInArrayInitializerVisitor(variable); + // context.accept(visitor); + // return visitor.isPassed(); + // } + + public static boolean variableIsAssigned(JSVariable variable, JSElement context) { + //noinspection unchecked + return variableIsAssigned(variable, context, Collections.EMPTY_SET, Collections.EMPTY_SET); + } + + public static boolean variableIsAssigned(JSVariable variable, JSElement context, Set notUpdatedSymbols) { + //noinspection unchecked + return variableIsAssigned(variable, context, notUpdatedSymbols, Collections.EMPTY_SET); + } + + private static boolean variableIsAssigned( + JSVariable variable, + JSElement context, + Set notUpdatedSymbols, + Set candidateSymbols + ) { + VariableAssignedVisitor visitor = new VariableAssignedVisitor(variable, context, notUpdatedSymbols, + candidateSymbols + ); + context.accept(visitor); + return visitor.isAssigned(); + } + + public static boolean variableIsReturned(JSVariable variable, JSElement context) { + VariableReturnedVisitor visitor = new VariableReturnedVisitor(variable); + context.accept(visitor); + return visitor.isReturned(); + } + + public static boolean arrayContentsAreAccessed(JSVariable variable, JSElement context) { + ArrayContentsAccessedVisitor visitor = new ArrayContentsAccessedVisitor(variable); + context.accept(visitor); + return visitor.isAccessed(); + } + + public static boolean arrayContentsAreAssigned(JSVariable variable, JSElement context) { + ArrayContentsAssignedVisitor visitor = new ArrayContentsAssignedVisitor(variable); + context.accept(visitor); + return visitor.isAssigned(); + } + + public static boolean mayEvaluateToVariable(JSExpression expression, JSVariable variable) { + String variableName = variable.getName(); + JSExpression expr = expression; + + if (variableName == null) { + return false; + } + + while (true) { + if (expr == null) { + return false; + } + else if (expr instanceof JSParenthesizedExpression parenExpr) { + expr = parenExpr.getInnerExpression(); + } + else if (expr instanceof JSConditionalExpression conditional) { + return mayEvaluateToVariable(conditional.getThen(), variable) + || mayEvaluateToVariable(conditional.getElse(), variable); + } + else if (expr instanceof JSIndexedPropertyAccessExpression indexedExpr) { + expr = indexedExpr.getQualifier(); + } + else if (expr instanceof JSDefinitionExpression defExpr) { + expr = defExpr.getExpression(); + } + else if (expr instanceof JSReferenceExpression refExpr) { + PsiElement referent = refExpr.resolve(); + + return referent != null && referent.equals(variable); + } + else { + return false; + } + } + } + + public static boolean variableIsUsed(JSVariable variable, PsiElement context) { + return variable.getName() != null && + FindReferenceUtil.getReferences(variable, context).iterator().hasNext(); + } + + public static Set getUsedVariables(PsiElement context) { + UsedVariableVisitor visitor = new UsedVariableVisitor(); + context.accept(visitor); + return visitor.getVariables(); + } + + private static class VariableAssignedVisitor extends JSRecursiveElementVisitor { + private final JSVariable variable; + private final JSElement context; + private Set notUpdatedSymbols; + private final Set candidateSymbols; + private boolean assigned; + + public VariableAssignedVisitor( + @Nonnull JSVariable variable, + @Nonnull JSElement context, + @Nonnull Set notUpdatedSymbols + ) { + this.variable = variable; + this.context = context; + this.notUpdatedSymbols = notUpdatedSymbols; + this.candidateSymbols = new LinkedHashSet<>(); + + this.candidateSymbols.add(variable); + } + + private VariableAssignedVisitor( + @Nonnull JSVariable variable, + @Nonnull JSElement context, + @Nonnull Set notUpdatedSymbols, + @Nonnull Set candidateSymbols + ) { + this.variable = variable; + this.context = context; + this.notUpdatedSymbols = notUpdatedSymbols; + this.candidateSymbols = candidateSymbols; + } + + @Override + public void visitJSElement(JSElement element) { + if (!this.assigned) { + super.visitJSElement(element); + } + } + + @Override + public void visitJSAssignmentExpression(JSAssignmentExpression assignment) { + if (!this.assigned) { + super.visitJSAssignmentExpression(assignment); + + JSExpression arg = assignment.getLOperand(); + + if (VariableAccessUtil.mayEvaluateToVariable(arg, this.variable)) { + Set usedVariables = getUsedVariables(assignment.getROperand()); + Set newCandidateSet = new LinkedHashSet<>(); + boolean assigned = false; + + newCandidateSet.addAll(this.candidateSymbols); + newCandidateSet.add(this.variable); + for (JSVariable variable : usedVariables) { + if (newCandidateSet.contains(variable) || + variableIsAssigned(variable, this.context, this.notUpdatedSymbols, newCandidateSet)) { + assigned = true; + } + else { + if (this.notUpdatedSymbols.isEmpty()) { + this.notUpdatedSymbols = new LinkedHashSet<>(); + } + this.notUpdatedSymbols.add(variable); + } + } + this.assigned = assigned; + } + else { + this.assigned = false; + } + } + } + + @Override + public void visitJSPrefixExpression(JSPrefixExpression expression) { + if (!this.assigned) { + super.visitJSPrefixExpression(expression); + + IElementType tokenType = expression.getOperationSign(); + + if (!(tokenType.equals(JSTokenTypes.PLUSPLUS) || + tokenType.equals(JSTokenTypes.MINUSMINUS))) { + return; + } + + JSExpression operand = expression.getExpression(); + + this.assigned = VariableAccessUtil.mayEvaluateToVariable(operand, this.variable); + } + } + + @Override + public void visitJSPostfixExpression(JSPostfixExpression postfixExpression) { + if (!this.assigned) { + super.visitJSPostfixExpression(postfixExpression); + + IElementType tokenType = postfixExpression.getOperationSign(); + + if (!(tokenType.equals(JSTokenTypes.PLUSPLUS) || + tokenType.equals(JSTokenTypes.MINUSMINUS))) { + return; + } + + JSExpression operand = postfixExpression.getExpression(); + + this.assigned = VariableAccessUtil.mayEvaluateToVariable(operand, this.variable); + } + } + + public boolean isAssigned() { + return this.assigned; + } + } + + private static class VariableAssignedFromVisitor extends JSRecursiveElementVisitor { + private final JSVariable variable; + private boolean assignedFrom; + + public VariableAssignedFromVisitor(@Nonnull JSVariable variable) { + this.variable = variable; + } + + @Override + public void visitJSElement(@Nonnull JSElement element) { + if (!this.assignedFrom) { + super.visitJSElement(element); + } + } + + @Override + public void visitJSAssignmentExpression(@Nonnull JSAssignmentExpression assignment) { + if (!this.assignedFrom) { + super.visitJSAssignmentExpression(assignment); + + this.assignedFrom = VariableAccessUtil.mayEvaluateToVariable(assignment.getROperand(), this.variable); + } + } + + @Override + public void visitJSVarStatement(@Nonnull JSVarStatement statement) { + if (!this.assignedFrom) { + super.visitJSVarStatement(statement); + + for (JSVariable declaredVariable : statement.getVariables()) { + JSExpression initializer = declaredVariable.getInitializer(); + + if (initializer != null) { + this.assignedFrom = VariableAccessUtil.mayEvaluateToVariable(initializer, this.variable); + } + } + } + } + + @Override + public void visitJSVariable(JSVariable var) { + if (!this.assignedFrom) { + super.visitJSVariable(var); + this.assignedFrom = (VariableAccessUtil.mayEvaluateToVariable(var.getInitializer(), this.variable)); + } + } + + public boolean isAssignedFrom() { + return this.assignedFrom; + } + } + + private static class VariableReturnedVisitor extends JSRecursiveElementVisitor { + @Nonnull + private final JSVariable variable; + private boolean returned; + + public VariableReturnedVisitor(@Nonnull JSVariable variable) { + this.variable = variable; + } + + @Override + public void visitJSReturnStatement(@Nonnull JSReturnStatement returnStatement) { + if (!this.returned) { + super.visitJSReturnStatement(returnStatement); + this.returned = VariableAccessUtil.mayEvaluateToVariable(returnStatement.getExpression(), this.variable); + } + } + + public boolean isReturned() { + return this.returned; + } + } + + private static class ArrayContentsAccessedVisitor extends JSRecursiveElementVisitor { + private final JSVariable variable; + private boolean accessed; + + public ArrayContentsAccessedVisitor(@Nonnull JSVariable variable) { + this.variable = variable; + } + + @Override + public void visitJSForInStatement(@Nonnull JSForInStatement statement) { + if (!this.accessed) { + super.visitJSForInStatement(statement); + this.checkQualifier(statement.getCollectionExpression()); + } + } + + @Override + public void visitJSIndexedPropertyAccessExpression(@Nonnull JSIndexedPropertyAccessExpression accessExpression) { + if (!this.accessed) { + super.visitJSIndexedPropertyAccessExpression(accessExpression); + + PsiElement parent = accessExpression.getParent(); + + if (!(parent instanceof JSAssignmentExpression || + ((JSAssignmentExpression)parent).getLOperand().equals(accessExpression))) { + this.checkQualifier(accessExpression.getQualifier()); + } + } + } + + private void checkQualifier(JSExpression qualifier) { + if (qualifier instanceof JSReferenceExpression referenceExpression) { + PsiElement referent = referenceExpression.resolve(); + + this.accessed = (referent != null && referent.equals(this.variable)); + } + } + + public boolean isAccessed() { + return this.accessed; + } + } + + private static class ArrayContentsAssignedVisitor extends JSRecursiveElementVisitor { + private final JSVariable variable; + private boolean assigned; + + public ArrayContentsAssignedVisitor(@Nonnull JSVariable variable) { + this.variable = variable; + } + + @Override + public void visitJSAssignmentExpression(@Nonnull JSAssignmentExpression assignment) { + if (!this.assigned) { + super.visitJSAssignmentExpression(assignment); + this.checkExpression(null, assignment.getLOperand()); + } + } + + @Override + public void visitJSPrefixExpression(@Nonnull JSPrefixExpression expression) { + if (!this.assigned) { + super.visitJSPrefixExpression(expression); + this.checkExpression(expression.getOperationSign(), expression.getExpression()); + } + } + + @Override + public void visitJSPostfixExpression(@Nonnull JSPostfixExpression expression) { + if (!this.assigned) { + super.visitJSPostfixExpression(expression); + this.checkExpression(expression.getOperationSign(), expression.getExpression()); + } + } + + private void checkExpression(IElementType tokenType, JSExpression expression) { + if (!(tokenType == null || JSTokenTypes.PLUSPLUS.equals(tokenType) || JSTokenTypes.MINUSMINUS.equals(tokenType))) { + return; + } + if (!(expression instanceof JSIndexedPropertyAccessExpression)) { + return; + } + + JSExpression arrayExpression = ((JSIndexedPropertyAccessExpression)expression).getQualifier(); + + while (arrayExpression instanceof JSIndexedPropertyAccessExpression accessExpression) { + arrayExpression = accessExpression.getQualifier(); + } + + if (arrayExpression instanceof JSReferenceExpression referenceExpression) { + String referencedName = referenceExpression.getReferencedName(); + + // TODO maybe it's better to check ((JSReferenceExpression) arrayExpression).isReferenceTo(variable) ? + this.assigned = referencedName != null && referencedName.equals(this.variable.getName()); + } + } + + public boolean isAssigned() { + return this.assigned; + } + } + + private static class UsedVariableVisitor extends JSRecursiveElementVisitor { + @Nonnull + private final Set variables; + + public UsedVariableVisitor() { + this.variables = new HashSet<>(); + } + + @Override + public void visitJSReferenceExpression(@Nonnull JSReferenceExpression ref) { + super.visitJSReferenceExpression(ref); + + PsiElement referent = ref.resolve(); + + if (referent != null && referent instanceof JSVariable variable) { + this.variables.add(variable); + } + } + + public Set getVariables() { + return this.variables; + } + } } diff --git a/intentions/src/main/resources/LOCALIZE-LIB/en_US/consulo.javascript.intention.JSIntentionLocalize.yaml b/intentions/src/main/resources/LOCALIZE-LIB/en_US/consulo.javascript.intention.JSIntentionLocalize.yaml new file mode 100644 index 00000000..512e713a --- /dev/null +++ b/intentions/src/main/resources/LOCALIZE-LIB/en_US/consulo.javascript.intention.JSIntentionLocalize.yaml @@ -0,0 +1,118 @@ +bool.de.morgans.law: + text: DeMorgan law +bool.de.morgans.law.and.to.or: + text: Replace && with || +bool.de.morgans.law.or.to.and: + text: Replace || with && +bool.flip.comparison: + text: Flip comparison +bool.flip.comparison.equals: + text: Flip {0} +bool.flip.comparison.not.equals: + text: Flip {0} to {1} +bool.flip.comparison.unknown: + text: Flip comparison +bool.flip.conjunction: + text: Flip conjunction operands +bool.flip.conjunction.message: + text: Flip {0} +bool.negate.comparison: + text: Negate comparison +bool.negate.comparison.equals: + text: Negate {0} +bool.negate.comparison.not.equals: + text: Negate {0} to {1} +bool.remove.boolean.equality: + text: Remove boolean equality +bool.remove.boolean.equality.message: + text: Simplify {0} +braces.add: + text: Add braces +braces.add.message: + text: Add braces from ''{0}'' statement +braces.remove: + text: Remove braces +braces.remove.message: + text: Remove braces from ''{0}'' statement +comment.change.to.cstyle.comment: + text: Replace with C-style comment +comment.change.to.end.of.line.comment: + text: Replace with end-of-line comment +comment.move.comment.to.separate.line: + text: Move comment to separate line +conditional.flip.conditional: + text: 'Flip ?:' +conditional.flip.if: + text: Flip if-else +conditional.remove.conditional: + text: 'Simplify ?:' +conditional.replace.conditional.with.if: + text: 'Replace ?: with if-else' +constant.compute.expression: + text: Compute constant value +constant.compute.subexpression: + text: Compute constant value for subexpression +constant.compute.subexpression.message: + text: Compute constant value of {0} {1} {2} +increment.extract: + text: Extract increment +increment.extract.message: + text: Extract {0} +initialization.merge.declaration.and.initialization: + text: Merge declaration and initialization +initialization.split.declaration.and.initialization: + text: Split into declaration and initialization +loop.merge.parallel.for.loops: + text: Merge 'for' loops +loop.merge.parallel.for.in.loops: + text: Merge 'for-in' loops +number.convert.integer.to.decimal: + text: Convert to decimal +number.convert.integer.to.hex: + text: Convert to hex +number.convert.integer.to.octal: + text: Convert to octal +number.replace.multiply.with.shift: + text: Replace multiply with shift +number.replace.multiply.with.shift.message: + text: Replace {0} with {1} +number.replace.shift.with.multiply: + text: Replace shift with multiply +number.replace.shift.with.multiply.message: + text: Replace {0} with {1} +opassign.replace.with.operator.assignment: + text: Replace assignment with operator assignment +opassign.replace.with.operator.assignment.message: + text: Replace = with {0}= +parenthesis.remove.unnecessary.parentheses: + text: Remove unnecessary parentheses +string.double.quoted.to.single.quoted: + text: Replace double-quoted string with single-quoted string +string.join.concatenated.string.literals: + text: Join concatenated String literals +string.single.to.double.quoted.string: + text: Replace single-quoted string with double-quoted string +switchtoif.replace.if.with.switch: + text: Replace if with switch +switchtoif.replace.switch.with.if: + text: Replace switch with if +trivialif.merge.else.if: + text: Merge else-if +trivialif.merge.if.and: + text: Merge 'if's +trivialif.merge.if.or: + text: Merge 'if's +trivialif.merge.parallel.ifs: + text: Merge 'if's +trivialif.remove.redundant.else: + text: Remove redundant else +trivialif.replace.if.with.conditional: + text: 'Replace if-else with ?:' +trivialif.simplify.if.else: + text: Simplify if-else +trivialif.split.else.if: + text: Split else-if +trivialif.split.if.and: + text: Split AND-ed if +trivialif.split.if.or: + text: Split OR-ed if diff --git a/intentions/src/main/resources/org/intellij/idea/lang/javascript/intention/JavaScriptIntentionBundle.properties b/intentions/src/main/resources/org/intellij/idea/lang/javascript/intention/JavaScriptIntentionBundle.properties deleted file mode 100644 index fafa58fb..00000000 --- a/intentions/src/main/resources/org/intellij/idea/lang/javascript/intention/JavaScriptIntentionBundle.properties +++ /dev/null @@ -1,104 +0,0 @@ -plugin.test.processing = Processing intention: {0} -plugin.test.title = Testing JSIntentionPowerPack plugin... -plugin.test.summary = {0} completed, {1} failed ({2} due to detection, {3} due to fix) -plugin.intention.untested = Intention {0} not tested. - -plugin.category.numbers = JavaScript/Numbers -plugin.category.boolean = JavaScript/Boolean -plugin.category.conditional = JavaScript/Conditional Operator -plugin.category.shift = JavaScript/Shift Operation -plugin.category.declaration = JavaScript/Declaration -plugin.category.comments = JavaScript/Comments -plugin.category.control-flow = JavaScript/Control Flow -plugin.category.other = JavaScript/Other - -bool.de-morgans-law.display-name.ANDAND = Replace && with || -bool.de-morgans-law.display-name.OROR = Replace || with && -bool.de-morgans-law.family-name = DeMorgan Law -bool.flip-comparison.display-name.equals = Flip {0} -bool.flip-comparison.display-name.not-equals = Flip {0} to {1} -bool.flip-comparison.display-name.unknown = Flip Comparison -bool.flip-comparison.family-name = Flip Comparison -bool.flip-conjunction.display-name = Flip {0} -bool.flip-conjunction.family-name = Flip Conjunction Operands -bool.negate-comparison.display-name.equals = Negate {0} -bool.negate-comparison.display-name.not-equals = Negate {0} to {1} -bool.negate-comparison.family-name = Negate Comparison -bool.remove-boolean-equality.display-name = Simplify {0} -bool.remove-boolean-equality.family-name = Remove Boolean Equality -braces.add-braces.display-name = Add braces from ''{0}'' statement -braces.add-braces.family-name = Add Braces -braces.remove-braces.display-name = Remove braces from ''{0}'' statement -braces.remove-braces.family-name = Remove Braces -comment.change-to-cstyle-comment.display-name = Replace with C-style comment -comment.change-to-cstyle-comment.family-name = Replace With C-Style Comment -comment.change-to-end-of-line-comment.display-name = Replace with end-of-line comment -comment.change-to-end-of-line-comment.family-name = Replace With End Of Line Comment -comment.move-comment-to-separate-line.display-name = Move comment to separate line -comment.move-comment-to-separate-line.family-name = Move Comment To Separate Line -conditional.flip-conditional.display-name = Flip ?: -conditional.flip-conditional.family-name = Flip Conditional -conditional.flip-if.display-name = Flip if-else -conditional.flip-if.family-name = Flip If -conditional.remove-conditional.display-name = Simplify ?: -conditional.remove-conditional.family-name = Remove Pointless Conditional -conditional.replace-conditional-with-if.display-name = Replace ?: with if-else -conditional.replace-conditional-with-if.family-name = Replace Conditional With If Else -constant.constant-expression.display-name = Compute constant value -constant.constant-expression.family-name = Compute Constant Value -constant.constant-subexpression.display-name = Compute constant value of {0} {1} {2} -constant.constant-subexpression.family-name = Compute Constant Value For Subexpression -increment.extract-increment.display-name = Extract {0} -increment.extract-increment.family-name = Extract Increment -initialization.merge-declaration-and-initialization.display-name = Merge declaration and initialization -initialization.merge-declaration-and-initialization.family-name = Merge Declaration And Initialization -initialization.split-declaration-and-initialization.display-name = Split into declaration and initialization -initialization.split-declaration-and-initialization.family-name = Split Declaration And Initialization -loop.merge-parallel-for-loops.display-name = Merge 'for' loops -loop.merge-parallel-for-loops.family-name = Merge Parallel For Loops -loop.merge-parallel-for-in-loops.display-name = Merge 'for-in' loops -loop.merge-parallel-for-in-loops.family-name = Merge Parallel For-In Loops -number.convert-integer-to-decimal.display-name = Convert to decimal -number.convert-integer-to-decimal.family-name = Convert To Decimal -number.convert-integer-to-hex.display-name = Convert to hex -number.convert-integer-to-hex.family-name = Convert To Hexadecimal -number.convert-integer-to-octal.display-name = Convert to octal -number.convert-integer-to-octal.family-name = Convert To Octal -number.replace-multiply-with-shift.display-name = Replace {0} with {1} -number.replace-multiply-with-shift.family-name = Replace Multiply with Shift -number.replace-shift-with-multiply.display-name = Replace {0} with {1} -number.replace-shift-with-multiply.family-name = Replace Shift with Multiply -opassign.replace-with-operator-assignment.display-name = Replace = with {0}= -opassign.replace-with-operator-assignment.family-name = Replace Assignment With Operator Assignment -parenthesis.remove-unnecessary-parentheses.display-name = Remove unnecessary parentheses -parenthesis.remove-unnecessary-parentheses.family-name = Remove Unnecessary Parentheses -string.double-to-single-quoted-string.display-name = Replace double-quoted string with single-quoted string -string.double-to-single-quoted-string.family-name = Replace Double-Quoted String with Single-Quoted String -string.join-concatenated-string-literals.display-name = Join concatenated String literals -string.join-concatenated-string-literals.family-name = Join Concatenated String Literals -string.single-to-double-quoted-string.display-name = Replace single-quoted string with double-quoted string -string.single-to-double-quoted-string.family-name = Replace Single-Quoted String with Double-Quoted String -switchtoif.replace-if-with-switch.display-name = Replace if with switch -switchtoif.replace-if-with-switch.family-name = Replace If With Switch -switchtoif.replace-switch-with-if.display-name = Replace switch with if -switchtoif.replace-switch-with-if.family-name = Replace Switch With If -trivialif.merge-else-if.display-name = Merge else-if -trivialif.merge-else-if.family-name = Merge Else If -trivialif.merge-if-and.display-name = Merge 'if's -trivialif.merge-if-and.family-name = Merge Nested Ifs To ANDed Condition -trivialif.merge-if-or.display-name = Merge 'if's -trivialif.merge-if-or.family-name = Merge Equivalent Ifs To ORed Condition -trivialif.merge-parallel-ifs.display-name = Merge 'if's -trivialif.merge-parallel-ifs.family-name = Merge Parallel Ifs -trivialif.remove-redundant-else.display-name = Remove redundant else -trivialif.remove-redundant-else.family-name = Remove Redundant Else -trivialif.replace-if-with-conditional.display-name = Replace if-else with ?: -trivialif.replace-if-with-conditional.family-name = Replace If Else With Conditional -trivialif.simplify-if-else.display-name = Simplify if-else -trivialif.simplify-if-else.family-name = Simplify If Else -trivialif.split-else-if.display-name = Split else-if -trivialif.split-else-if.family-name = Split Else If -trivialif.split-if-and.display-name = Split AND-ed if -trivialif.split-if-and.family-name = Split ANDed Condition To Nested Ifs -trivialif.split-if-or.display-name = Split OR-ed if -trivialif.split-if-or.family-name = Split ORed Condition To Equivalent Ifs diff --git a/lang-version-impl/actionscript-impl/pom.xml b/lang-version-impl/actionscript-impl/pom.xml index 92eca256..4b9975c1 100644 --- a/lang-version-impl/actionscript-impl/pom.xml +++ b/lang-version-impl/actionscript-impl/pom.xml @@ -32,7 +32,7 @@ consulo - https://maven.consulo.io/repository/snapshots/ + https://maven.consulo.dev/repository/snapshots/ true interval:60 diff --git a/lang-version-impl/actionscript-impl/src/main/java/consulo/actionscript/ActionScriptFileType.java b/lang-version-impl/actionscript-impl/src/main/java/consulo/actionscript/ActionScriptFileType.java index 2c46e82a..68b0dc9d 100644 --- a/lang-version-impl/actionscript-impl/src/main/java/consulo/actionscript/ActionScriptFileType.java +++ b/lang-version-impl/actionscript-impl/src/main/java/consulo/actionscript/ActionScriptFileType.java @@ -28,55 +28,48 @@ import consulo.ui.image.Image; import consulo.virtualFileSystem.VirtualFile; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL * @since 02.12.13. */ -public class ActionScriptFileType extends LanguageFileType implements JavaScriptFileTypeWithVersion -{ - public static final ActionScriptFileType INSTANCE = new ActionScriptFileType(); +public class ActionScriptFileType extends LanguageFileType implements JavaScriptFileTypeWithVersion { + public static final ActionScriptFileType INSTANCE = new ActionScriptFileType(); - private ActionScriptFileType() - { - super(JavaScriptLanguage.INSTANCE); - } + private ActionScriptFileType() { + super(JavaScriptLanguage.INSTANCE); + } - @Nonnull - @Override - public String getId() - { - return "ACTIONSCRIPT"; - } + @Nonnull + @Override + public String getId() { + return "ACTIONSCRIPT"; + } - @Nonnull - @Override - public LocalizeValue getDescription() - { - return LocalizeValue.localizeTODO("ActionScript files"); - } + @Nonnull + @Override + public LocalizeValue getDescription() { + return LocalizeValue.localizeTODO("ActionScript files"); + } - @Nonnull - @Override - public String getDefaultExtension() - { - return "as"; - } + @Nonnull + @Override + public String getDefaultExtension() { + return "as"; + } - @Nullable - @Override - public Image getIcon() - { - return JavaScriptIconGroup.as(); - } + @Nullable + @Override + public Image getIcon() { + return JavaScriptIconGroup.as(); + } - @RequiredReadAction - @Nonnull - @Override - public LanguageVersion getLanguageVersion(@Nullable Module module, @Nullable VirtualFile virtualFile) - { - return ActionScriptLanguageVersion.getInstance(); - } + @RequiredReadAction + @Nonnull + @Override + public LanguageVersion getLanguageVersion(@Nullable Module module, @Nullable VirtualFile virtualFile) { + return ActionScriptLanguageVersion.getInstance(); + } } diff --git a/lang-version-impl/actionscript-impl/src/main/java/consulo/actionscript/ActionScriptFileTypeFactory.java b/lang-version-impl/actionscript-impl/src/main/java/consulo/actionscript/ActionScriptFileTypeFactory.java index 068e7de0..d13d334e 100644 --- a/lang-version-impl/actionscript-impl/src/main/java/consulo/actionscript/ActionScriptFileTypeFactory.java +++ b/lang-version-impl/actionscript-impl/src/main/java/consulo/actionscript/ActionScriptFileTypeFactory.java @@ -3,19 +3,16 @@ import consulo.annotation.component.ExtensionImpl; import consulo.virtualFileSystem.fileType.FileTypeConsumer; import consulo.virtualFileSystem.fileType.FileTypeFactory; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 06.04.2015 */ @ExtensionImpl -public class ActionScriptFileTypeFactory extends FileTypeFactory -{ - @Override - public void createFileTypes(@Nonnull FileTypeConsumer consumer) - { - consumer.consume(ActionScriptFileType.INSTANCE); - } +public class ActionScriptFileTypeFactory extends FileTypeFactory { + @Override + public void createFileTypes(@Nonnull FileTypeConsumer consumer) { + consumer.consume(ActionScriptFileType.INSTANCE); + } } diff --git a/lang-version-impl/actionscript-impl/src/main/java/consulo/actionscript/lang/ActionScriptLanguageVersion.java b/lang-version-impl/actionscript-impl/src/main/java/consulo/actionscript/lang/ActionScriptLanguageVersion.java index 744e4aa7..7ad902a1 100644 --- a/lang-version-impl/actionscript-impl/src/main/java/consulo/actionscript/lang/ActionScriptLanguageVersion.java +++ b/lang-version-impl/actionscript-impl/src/main/java/consulo/actionscript/lang/ActionScriptLanguageVersion.java @@ -10,53 +10,46 @@ import consulo.language.lexer.Lexer; import consulo.language.parser.PsiParser; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 06.04.2015 */ @ExtensionImpl -public class ActionScriptLanguageVersion extends BaseJavaScriptLanguageVersion -{ - @Nonnull - public static ActionScriptLanguageVersion getInstance() - { - return JavaScriptLanguage.INSTANCE.findVersionByClass(ActionScriptLanguageVersion.class); - } - - private final DialectOptionHolder myDialectOptionHolder = new DialectOptionHolder(true, false); - - public ActionScriptLanguageVersion() - { - super("ACTIONSCRIPT"); - } - - @Nonnull - @Override - public String getPresentableName() - { - return "ActionScript"; - } - - @Nonnull - @Override - public PsiParser createParser() - { - return new EcmaScript4Parser(); - } - - @Nonnull - @Override - public JSHighlighter getSyntaxHighlighter() - { - return new JSHighlighter(myDialectOptionHolder); - } - - @Nonnull - @Override - public Lexer createLexer() - { - return new JavaScriptParsingFlexLexer(myDialectOptionHolder); - } +public class ActionScriptLanguageVersion extends BaseJavaScriptLanguageVersion { + @Nonnull + public static ActionScriptLanguageVersion getInstance() { + return JavaScriptLanguage.INSTANCE.findVersionByClass(ActionScriptLanguageVersion.class); + } + + private final DialectOptionHolder myDialectOptionHolder = new DialectOptionHolder(true, false); + + public ActionScriptLanguageVersion() { + super("ACTIONSCRIPT"); + } + + @Nonnull + @Override + public String getPresentableName() { + return "ActionScript"; + } + + @Nonnull + @Override + public PsiParser createParser() { + return new EcmaScript4Parser(); + } + + @Nonnull + @Override + public JSHighlighter getSyntaxHighlighter() { + return new JSHighlighter(myDialectOptionHolder); + } + + @Nonnull + @Override + public Lexer createLexer() { + return new JavaScriptParsingFlexLexer(myDialectOptionHolder); + } } diff --git a/lang-version-impl/actionscript-impl/src/main/java/module-info.java b/lang-version-impl/actionscript-impl/src/main/java/module-info.java index e17104fe..04bc48a7 100644 --- a/lang-version-impl/actionscript-impl/src/main/java/module-info.java +++ b/lang-version-impl/actionscript-impl/src/main/java/module-info.java @@ -2,10 +2,9 @@ * @author VISTALL * @since 23-Aug-22 */ -module consulo.javascript.actionscript.impl -{ - requires transitive consulo.javascript.ecmascript4.impl; +module consulo.javascript.actionscript.impl { + requires transitive consulo.javascript.ecmascript4.impl; - exports consulo.actionscript; - exports consulo.actionscript.lang; + exports consulo.actionscript; + exports consulo.actionscript.lang; } \ No newline at end of file diff --git a/lang-version-impl/ecmascript-impl/pom.xml b/lang-version-impl/ecmascript-impl/pom.xml index 10bd6993..dd2a4e34 100644 --- a/lang-version-impl/ecmascript-impl/pom.xml +++ b/lang-version-impl/ecmascript-impl/pom.xml @@ -15,75 +15,75 @@ - limitations under the License. --> - 4.0.0 - - consulo - arch.ide-api-provided - 3-SNAPSHOT - - + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + + consulo + arch.ide-api-provided + 3-SNAPSHOT + + - consulo.plugin - consulo.javascript-ecmascript.impl - 3-SNAPSHOT - jar + consulo.plugin + consulo.javascript-ecmascript.impl + 3-SNAPSHOT + jar - - - consulo - https://maven.consulo.io/repository/snapshots/ - - true - always - - - + + + consulo + https://maven.consulo.dev/repository/snapshots/ + + true + always + + + - - - - consulo.maven - maven-consulo-plugin - true - - - generate-sources - - generate-lexers - - - - - - + + + + consulo.maven + maven-consulo-plugin + true + + + generate-sources + + generate-lexers + + + + + + - - - ${project.groupId} - consulo.javascript-base.impl - ${project.version} - + + + ${project.groupId} + consulo.javascript-base.impl + ${project.version} + - - consulo - consulo-language-editor-impl - ${project.version} - + + consulo + consulo-language-editor-impl + ${project.version} + - - ${project.groupId} - com.intellij.xml - ${project.version} - provided - + + ${project.groupId} + com.intellij.xml + ${project.version} + provided + - - - consulo - consulo-ide-impl - ${project.version} - provided - - + + + consulo + consulo-ide-impl + ${project.version} + provided + + \ No newline at end of file diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/codeInsight/EcmaScript6QuickFixFactory.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/codeInsight/EcmaScript6QuickFixFactory.java index 79cd0c9f..a4b7d28b 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/codeInsight/EcmaScript6QuickFixFactory.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/codeInsight/EcmaScript6QuickFixFactory.java @@ -22,25 +22,21 @@ import consulo.javascript.ecmascript.lang.BaseEcmaScriptJavaScriptVersion; import consulo.javascript.ide.codeInsight.JavaScriptQuickFixFactory; import consulo.javascript.language.JavaScriptLanguageVersion; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 24.02.2016 */ @ExtensionImpl -public class EcmaScript6QuickFixFactory extends JavaScriptQuickFixFactory -{ - @Override - public CreateJSFunctionOrMethodFix createFunctionOrMethodFix(String referenceName, boolean isMethod) - { - return new EcmaScript6CreateJSFunctionOrMethodFix(referenceName, isMethod); - } +public class EcmaScript6QuickFixFactory extends JavaScriptQuickFixFactory { + @Override + public CreateJSFunctionOrMethodFix createFunctionOrMethodFix(String referenceName, boolean isMethod) { + return new EcmaScript6CreateJSFunctionOrMethodFix(referenceName, isMethod); + } - @Override - public boolean isMyVersion(@Nonnull JavaScriptLanguageVersion version) - { - return version instanceof BaseEcmaScriptJavaScriptVersion; - } + @Override + public boolean isMyVersion(@Nonnull JavaScriptLanguageVersion version) { + return version instanceof BaseEcmaScriptJavaScriptVersion; + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/codeInsight/quickFixes/EcmaScript6CreateJSFunctionOrMethodFix.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/codeInsight/quickFixes/EcmaScript6CreateJSFunctionOrMethodFix.java index 745518ff..bf74c723 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/codeInsight/quickFixes/EcmaScript6CreateJSFunctionOrMethodFix.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/codeInsight/quickFixes/EcmaScript6CreateJSFunctionOrMethodFix.java @@ -13,19 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package consulo.javascript.ecmascript.codeInsight.quickFixes; import com.intellij.lang.javascript.inspections.qucikFixes.CreateJSFunctionOrMethodFix; /** * @author VISTALL - * @since 24.02.2016 + * @since 2016-02-24 */ -public class EcmaScript6CreateJSFunctionOrMethodFix extends CreateJSFunctionOrMethodFix -{ - public EcmaScript6CreateJSFunctionOrMethodFix(String name, boolean isMethod) - { - super(name, isMethod); - } +public class EcmaScript6CreateJSFunctionOrMethodFix extends CreateJSFunctionOrMethodFix { + public EcmaScript6CreateJSFunctionOrMethodFix(String name, boolean isMethod) { + super(name, isMethod); + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/completion/EcmaScript6KeywordCompletionExtender.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/completion/EcmaScript6KeywordCompletionExtender.java index c6b42d32..6c88e784 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/completion/EcmaScript6KeywordCompletionExtender.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/completion/EcmaScript6KeywordCompletionExtender.java @@ -7,19 +7,16 @@ import consulo.language.editor.completion.lookup.LookupElementBuilder; import consulo.language.util.ProcessingContext; import consulo.javascript.ide.completion.JavaScriptKeywordCompletionExtender; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 2019-12-17 */ @ExtensionImpl -public class EcmaScript6KeywordCompletionExtender implements JavaScriptKeywordCompletionExtender -{ - @Override - public void fillCompletion(@Nonnull CompletionParameters parameters, ProcessingContext context, @Nonnull CompletionResultSet result) - { - result.addElement(LookupElementBuilder.create("let").withInsertHandler(AddSpaceInsertHandler.INSTANCE).bold()); - } +public class EcmaScript6KeywordCompletionExtender implements JavaScriptKeywordCompletionExtender { + @Override + public void fillCompletion(@Nonnull CompletionParameters parameters, ProcessingContext context, @Nonnull CompletionResultSet result) { + result.addElement(LookupElementBuilder.create("let").withInsertHandler(AddSpaceInsertHandler.INSTANCE).bold()); + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/BaseEcmaScriptJavaScriptVersion.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/BaseEcmaScriptJavaScriptVersion.java index 7cb98e99..4cefcee5 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/BaseEcmaScriptJavaScriptVersion.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/BaseEcmaScriptJavaScriptVersion.java @@ -9,61 +9,56 @@ import consulo.javascript.lang.lexer.JavaScriptFlexAdapter; import consulo.javascript.lang.psi.impl.resolve.JavaScriptVersionWithHelper; import consulo.javascript.lang.psi.impl.resolve.ResolveHelper; -import consulo.javascript.language.StandardJavaScriptVersions; +import consulo.javascript.language.StandardJavaScriptVersion; import consulo.language.ast.TokenSet; import consulo.language.editor.highlight.SyntaxHighlighter; import consulo.language.lexer.Lexer; import consulo.language.lexer.MergingLexerAdapter; import consulo.language.parser.PsiParser; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 06/12/2021 */ -public abstract class BaseEcmaScriptJavaScriptVersion extends BaseJavaScriptLanguageVersion implements StandardJavaScriptVersions.Marker, JavaScriptVersionWithHelper -{ - protected BaseEcmaScriptJavaScriptVersion(@Nonnull String id) - { - super(id); - } +public abstract class BaseEcmaScriptJavaScriptVersion extends BaseJavaScriptLanguageVersion implements StandardJavaScriptVersion, JavaScriptVersionWithHelper { + protected BaseEcmaScriptJavaScriptVersion(@Nonnull String id) { + super(id); + } - protected BaseEcmaScriptJavaScriptVersion(String name, String... mimeTypes) - { - super(name, mimeTypes); - } + protected BaseEcmaScriptJavaScriptVersion(String name, String... mimeTypes) { + super(name, mimeTypes); + } - @Nonnull - @Override - public Lexer createLexer() - { - return createLexer(false); - } + @Nonnull + @Override + public Lexer createLexer() { + return createLexer(false); + } - @Nonnull - @Override - public SyntaxHighlighter getSyntaxHighlighter() - { - return new JavaScriptHighlighter(() -> createLexer(true)); - } + @Nonnull + @Override + public SyntaxHighlighter getSyntaxHighlighter() { + return new JavaScriptHighlighter(() -> createLexer(true)); + } - private Lexer createLexer(boolean hightlight) - { - return new MergingLexerAdapter(new JavaScriptFlexAdapter(new _EcmaScript6Lexer(hightlight)), TokenSet.create(JSTokenTypes.XML_JS_SCRIPT)); - } + private Lexer createLexer(boolean hightlight) { + return new MergingLexerAdapter( + new JavaScriptFlexAdapter(new _EcmaScript6Lexer(hightlight)), + TokenSet.create(JSTokenTypes.XML_JS_SCRIPT) + ); + } - @Nonnull - @Override - public PsiParser createParser() - { - return new EcmaScriptParser(); - } + @Nonnull + @Override + public PsiParser createParser() { + return new EcmaScriptParser(); + } - @Nonnull - @Override - public ResolveHelper getHelper() - { - return EcmaScript6ResolveHelper.INSTANCE; - } + @Nonnull + @Override + public ResolveHelper getHelper() { + return EcmaScript6ResolveHelper.INSTANCE; + } } \ No newline at end of file diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript10JavaScriptVersion.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript10JavaScriptVersion.java index b35eff5f..2baaabe4 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript10JavaScriptVersion.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript10JavaScriptVersion.java @@ -3,31 +3,27 @@ import consulo.annotation.component.ExtensionImpl; import jakarta.inject.Inject; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 06/12/2021 */ @ExtensionImpl -public class EcmaScript10JavaScriptVersion extends EcmaScript6JavaScriptVersion -{ - @Inject - public EcmaScript10JavaScriptVersion() - { - super("ECMASCRIPT_10"); - } +public class EcmaScript10JavaScriptVersion extends EcmaScript6JavaScriptVersion { + @Inject + public EcmaScript10JavaScriptVersion() { + super("ECMASCRIPT_10"); + } - @Nonnull - @Override - public String getPresentableName() - { - return "ECMAScript 10"; - } + @Nonnull + @Override + public String getPresentableName() { + return "ECMAScript 10"; + } - @Override - public int getWeight() - { - return 1000; - } + @Override + public int getWeight() { + return 1000; + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript11JavaScriptVersion.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript11JavaScriptVersion.java index 74207140..06f6e281 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript11JavaScriptVersion.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript11JavaScriptVersion.java @@ -2,35 +2,30 @@ import consulo.annotation.component.ExtensionImpl; import consulo.javascript.language.JavaScriptFeature; +import jakarta.annotation.Nonnull; import jakarta.inject.Inject; -import javax.annotation.Nonnull; - /** * @author VISTALL * @since 06/12/2021 */ @ExtensionImpl -public class EcmaScript11JavaScriptVersion extends EcmaScript6JavaScriptVersion -{ - @Inject - public EcmaScript11JavaScriptVersion() - { - super("ECMASCRIPT_11"); +public class EcmaScript11JavaScriptVersion extends EcmaScript6JavaScriptVersion { + @Inject + public EcmaScript11JavaScriptVersion() { + super("ECMASCRIPT_11"); - addFeature(JavaScriptFeature.OPTIONAL_CHAINING_OPERATOR); - } + addFeature(JavaScriptFeature.OPTIONAL_CHAINING_OPERATOR); + } - @Nonnull - @Override - public String getPresentableName() - { - return "ECMAScript 11"; - } + @Nonnull + @Override + public String getPresentableName() { + return "ECMAScript 11"; + } - @Override - public int getWeight() - { - return 1100; - } + @Override + public int getWeight() { + return 1100; + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript12JavaScriptVersion.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript12JavaScriptVersion.java index 76cdf9bc..e6d5bc0c 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript12JavaScriptVersion.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript12JavaScriptVersion.java @@ -1,40 +1,36 @@ package consulo.javascript.ecmascript.lang; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.internal.DefaultJavaScriptVersion; import consulo.javascript.language.JavaScriptLanguage; import jakarta.inject.Inject; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 06/12/2021 */ @ExtensionImpl -public class EcmaScript12JavaScriptVersion extends EcmaScript6JavaScriptVersion -{ - @Nonnull - public static EcmaScript12JavaScriptVersion getInstance() - { - return JavaScriptLanguage.INSTANCE.findVersionByClass(EcmaScript12JavaScriptVersion.class); - } +public class EcmaScript12JavaScriptVersion extends EcmaScript6JavaScriptVersion implements DefaultJavaScriptVersion { + @Nonnull + public static EcmaScript12JavaScriptVersion getInstance() { + return JavaScriptLanguage.INSTANCE.findVersionByClass(EcmaScript12JavaScriptVersion.class); + } - @Inject - public EcmaScript12JavaScriptVersion() - { - super("ECMASCRIPT_12"); - } + @Inject + public EcmaScript12JavaScriptVersion() { + super("ECMASCRIPT_12"); + } - @Nonnull - @Override - public String getPresentableName() - { - return "ECMAScript 12"; - } + @Nonnull + @Override + public String getPresentableName() { + return "ECMAScript 12"; + } - @Override - public int getWeight() - { - return 1200; - } + @Override + public int getWeight() { + return 1200; + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript6JavaScriptVersion.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript6JavaScriptVersion.java index 844dc01b..d48013ee 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript6JavaScriptVersion.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript6JavaScriptVersion.java @@ -20,52 +20,46 @@ import consulo.javascript.lang.psi.impl.resolve.JavaScriptVersionWithHelper; import consulo.javascript.language.JavaScriptFeature; import consulo.javascript.language.JavaScriptLanguage; -import consulo.javascript.language.StandardJavaScriptVersions; +import consulo.javascript.language.StandardJavaScriptVersion; import jakarta.inject.Inject; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 12.12.2015 */ @ExtensionImpl -public class EcmaScript6JavaScriptVersion extends BaseEcmaScriptJavaScriptVersion implements StandardJavaScriptVersions.Marker, JavaScriptVersionWithHelper -{ - @Nonnull - public static EcmaScript6JavaScriptVersion getInstance() - { - return JavaScriptLanguage.INSTANCE.findVersionByClass(EcmaScript6JavaScriptVersion.class); - } +public class EcmaScript6JavaScriptVersion extends BaseEcmaScriptJavaScriptVersion implements StandardJavaScriptVersion, JavaScriptVersionWithHelper { + @Nonnull + public static EcmaScript6JavaScriptVersion getInstance() { + return JavaScriptLanguage.INSTANCE.findVersionByClass(EcmaScript6JavaScriptVersion.class); + } - @Inject - public EcmaScript6JavaScriptVersion() - { - super("ECMASCRIPT_6"); - } + @Inject + public EcmaScript6JavaScriptVersion() { + super("ECMASCRIPT_6"); + } - public EcmaScript6JavaScriptVersion(@Nonnull String id) - { - super(id); + public EcmaScript6JavaScriptVersion(@Nonnull String id) { + super(id); - addFeature(JavaScriptFeature.CLASS); - addFeature(JavaScriptFeature.BINARY_LITERAL); - addFeature(JavaScriptFeature.OCTAL_LITERAL); - addFeature(JavaScriptFeature.PARAMETER_DEFAULT_VALUE); - addFeature(JavaScriptFeature.REST_PARAMETER); - addFeature(JavaScriptFeature.FUNCTION_PROPERTY); - } + addFeature(JavaScriptFeature.CLASS); + addFeature(JavaScriptFeature.BINARY_LITERAL); + addFeature(JavaScriptFeature.OCTAL_LITERAL); + addFeature(JavaScriptFeature.PARAMETER_DEFAULT_VALUE); + addFeature(JavaScriptFeature.REST_PARAMETER); + addFeature(JavaScriptFeature.FUNCTION_PROPERTY); + } - @Nonnull - @Override - public String getPresentableName() - { - return "ECMAScript 6"; - } + @Nonnull + @Override + public String getPresentableName() { + return "ECMAScript 6"; + } - @Override - public int getWeight() - { - return 600; - } + @Override + public int getWeight() { + return 600; + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript7JavaScriptVersion.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript7JavaScriptVersion.java index cd75a50f..502aae46 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript7JavaScriptVersion.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript7JavaScriptVersion.java @@ -4,33 +4,29 @@ import consulo.javascript.language.JavaScriptFeature; import jakarta.inject.Inject; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 06/12/2021 */ @ExtensionImpl -public class EcmaScript7JavaScriptVersion extends EcmaScript6JavaScriptVersion -{ - @Inject - public EcmaScript7JavaScriptVersion() - { - super("ECMASCRIPT_7"); +public class EcmaScript7JavaScriptVersion extends EcmaScript6JavaScriptVersion { + @Inject + public EcmaScript7JavaScriptVersion() { + super("ECMASCRIPT_7"); - addFeature(JavaScriptFeature.EXPONENTIATION_OPERATOR); - } + addFeature(JavaScriptFeature.EXPONENTIATION_OPERATOR); + } - @Nonnull - @Override - public String getPresentableName() - { - return "ECMAScript 7"; - } + @Nonnull + @Override + public String getPresentableName() { + return "ECMAScript 7"; + } - @Override - public int getWeight() - { - return 700; - } + @Override + public int getWeight() { + return 700; + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript8JavaScriptVersion.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript8JavaScriptVersion.java index 864433dd..891e9b45 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript8JavaScriptVersion.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript8JavaScriptVersion.java @@ -1,33 +1,28 @@ package consulo.javascript.ecmascript.lang; import consulo.annotation.component.ExtensionImpl; +import jakarta.annotation.Nonnull; import jakarta.inject.Inject; -import javax.annotation.Nonnull; - /** * @author VISTALL * @since 06/12/2021 */ @ExtensionImpl -public class EcmaScript8JavaScriptVersion extends EcmaScript6JavaScriptVersion -{ - @Inject - public EcmaScript8JavaScriptVersion() - { - super("ECMASCRIPT_8"); - } +public class EcmaScript8JavaScriptVersion extends EcmaScript6JavaScriptVersion { + @Inject + public EcmaScript8JavaScriptVersion() { + super("ECMASCRIPT_8"); + } - @Nonnull - @Override - public String getPresentableName() - { - return "ECMAScript 8"; - } + @Nonnull + @Override + public String getPresentableName() { + return "ECMAScript 8"; + } - @Override - public int getWeight() - { - return 800; - } + @Override + public int getWeight() { + return 800; + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript9JavaScriptVersion.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript9JavaScriptVersion.java index c8a80313..aa53f532 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript9JavaScriptVersion.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScript9JavaScriptVersion.java @@ -2,10 +2,9 @@ import consulo.annotation.component.ExtensionImpl; import consulo.javascript.language.JavaScriptFeature; +import jakarta.annotation.Nonnull; import jakarta.inject.Inject; -import javax.annotation.Nonnull; - /** * @author VISTALL * @since 06/12/2021 diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScriptFileType.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScriptFileType.java index 364781fc..79e9e536 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScriptFileType.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScriptFileType.java @@ -29,65 +29,56 @@ import consulo.ui.image.Image; import consulo.virtualFileSystem.VirtualFile; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL * @since 23.12.13. */ -public class EcmaScriptFileType extends LanguageFileType implements JavaScriptFileTypeWithVersion -{ - public static final EcmaScriptFileType INSTANCE = new EcmaScriptFileType(); +public class EcmaScriptFileType extends LanguageFileType implements JavaScriptFileTypeWithVersion { + public static final EcmaScriptFileType INSTANCE = new EcmaScriptFileType(); - private EcmaScriptFileType() - { - super(JavaScriptLanguage.INSTANCE); - } + private EcmaScriptFileType() { + super(JavaScriptLanguage.INSTANCE); + } - @Nonnull - @Override - public String getId() - { - return "ECMASCRIPT"; - } + @Nonnull + @Override + public String getId() { + return "ECMASCRIPT"; + } - @Nonnull - @Override - public LocalizeValue getDescription() - { - return LocalizeValue.localizeTODO("ECMAScript files"); - } + @Nonnull + @Override + public LocalizeValue getDescription() { + return LocalizeValue.localizeTODO("ECMAScript files"); + } - @Nonnull - @Override - public String getDefaultExtension() - { - return "es"; - } + @Nonnull + @Override + public String getDefaultExtension() { + return "es"; + } - @Nullable - @Override - public Image getIcon() - { - return JavaScriptIconGroup.ecmascript(); - } + @Nullable + @Override + public Image getIcon() { + return JavaScriptIconGroup.ecmascript(); + } - @RequiredReadAction - @Nonnull - @Override - public LanguageVersion getLanguageVersion(@Nullable Module module, @Nullable VirtualFile virtualFile) - { - if(module == null) - { - return EcmaScript12JavaScriptVersion.getInstance(); - } + @RequiredReadAction + @Nonnull + @Override + public LanguageVersion getLanguageVersion(@Nullable Module module, @Nullable VirtualFile virtualFile) { + if (module == null) { + return EcmaScript12JavaScriptVersion.getInstance(); + } - JavaScriptModuleExtension extension = ModuleUtilCore.getExtension(module, JavaScriptModuleExtension.class); - if(extension != null) - { - return extension.getLanguageVersion(); - } - return EcmaScript12JavaScriptVersion.getInstance(); - } + JavaScriptModuleExtension extension = ModuleUtilCore.getExtension(module, JavaScriptModuleExtension.class); + if (extension != null) { + return extension.getLanguageVersion(); + } + return EcmaScript12JavaScriptVersion.getInstance(); + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScriptFileTypeFactory.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScriptFileTypeFactory.java index 9e18e457..2ae27109 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScriptFileTypeFactory.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/EcmaScriptFileTypeFactory.java @@ -4,18 +4,16 @@ import consulo.virtualFileSystem.fileType.FileTypeConsumer; import consulo.virtualFileSystem.fileType.FileTypeFactory; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 05.03.2015 */ @ExtensionImpl -public class EcmaScriptFileTypeFactory extends FileTypeFactory -{ - @Override - public void createFileTypes(@Nonnull FileTypeConsumer consumer) - { - consumer.consume(EcmaScriptFileType.INSTANCE, "es;js2"); - } +public class EcmaScriptFileTypeFactory extends FileTypeFactory { + @Override + public void createFileTypes(@Nonnull FileTypeConsumer consumer) { + consumer.consume(EcmaScriptFileType.INSTANCE, "es;js2"); + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/lexer/ecmascript6.flex b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/lexer/ecmascript6.flex index 8631686d..6357c9d9 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/lexer/ecmascript6.flex +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/lexer/ecmascript6.flex @@ -67,7 +67,7 @@ DOUBLE_QUOTED_LITERAL=\"([^\\\"\r\n]|{ESCAPE_SEQUENCE}|\\{CRLF})*(\"|\\)? ESCAPE_SEQUENCE=\\[^\r\n] GROUP = "[" [^\]]* "]" -REGEXP_LITERAL="/"([^\*\\/\r\n]|{ESCAPE_SEQUENCE}|{GROUP})([^\\/\r\n]|{ESCAPE_SEQUENCE}|{GROUP})*("/"[gimxu]*)? +REGEXP_LITERAL="/"([^\*\\/\r\n]|{ESCAPE_SEQUENCE}|{GROUP})([^\\/\r\n]|{ESCAPE_SEQUENCE}|{GROUP})*("/"[gimsuy]*)? INTERPOLATION_STRING_LITERAL="`" [^"`"]* "`" ALPHA=[:letter:] diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/parsing/EcmaScriptExpressionParsing.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/parsing/EcmaScriptExpressionParsing.java index c8de1739..edeb6577 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/parsing/EcmaScriptExpressionParsing.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/parsing/EcmaScriptExpressionParsing.java @@ -19,7 +19,6 @@ import com.intellij.lang.javascript.JSElementTypes; import com.intellij.lang.javascript.JSTokenTypes; import consulo.javascript.lang.parsing.ExpressionParsing; -import consulo.javascript.language.JavaScriptBundle; import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.ast.IElementType; import consulo.language.parser.PsiBuilder; @@ -28,215 +27,179 @@ * @author VISTALL * @since 03.03.2016 */ -public class EcmaScriptExpressionParsing extends ExpressionParsing -{ - public EcmaScriptExpressionParsing(EcmaScriptParsingContext context) - { - super(context); - } - - @Override - public EcmaScriptStatementParsing getStatementParsing() - { - return (EcmaScriptStatementParsing) super.getStatementParsing(); - } - - @Override - protected boolean parsePrimaryExpression(PsiBuilder builder) - { - if(builder.getTokenType() == JSTokenTypes.DOT_DOT_DOT) - { - PsiBuilder.Marker mark = builder.mark(); - builder.advanceLexer(); - - if(!parseExpressionOptional(builder)) - { - mark.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); - } - else - { - mark.done(JSElementTypes.SPREAD_EXPRESSION); - } - - return true; - } - else if(builder.getTokenType() == JSTokenTypes.CLASS_KEYWORD) - { - PsiBuilder.Marker mark = builder.mark(); - getStatementParsing().parseClassWithMarker(builder, builder.mark(), false); - mark.done(JSElementTypes.CLASS_EXPRESSION); - return true; - } - - if(canParseLambdaExpression(builder)) - { - return parseLambdaExpression(builder); - } - return super.parsePrimaryExpression(builder); - } - - private boolean parseLambdaExpression(PsiBuilder builder) - { - PsiBuilder.Marker mark = builder.mark(); - - IElementType tokenType = builder.getTokenType(); - if(tokenType == JSTokenTypes.IDENTIFIER) - { - PsiBuilder.Marker parameterList = builder.mark(); - getFunctionParsing().parseParameter(builder, null); - parameterList.done(JSElementTypes.PARAMETER_LIST); - } - else - { - getFunctionParsing().parseParameterList(builder); - } - - if(builder.getTokenType() == JSTokenTypes.DARROW) - { - builder.advanceLexer(); - } - else - { - mark.rollbackTo(); - return false; - } - - if(builder.getTokenType() == JSTokenTypes.LBRACE) - { - getStatementParsing().parseBlock(builder); - } - else - { - parseAssignmentExpression(builder); - } - - mark.done(JSElementTypes.LAMBDA_EXPRESSION); - return true; - } - - private boolean canParseLambdaExpression(PsiBuilder builder) - { - PsiBuilder.Marker marker = builder.mark(); - try - { - IElementType tokenType = builder.getTokenType(); - if(tokenType == JSTokenTypes.IDENTIFIER) - { - builder.advanceLexer(); - if(builder.getTokenType() == JSTokenTypes.DARROW) - { - return true; - } - } - else if(tokenType == JSTokenTypes.LPAR) - { - getFunctionParsing().parseParameterList(builder); - - if(builder.getTokenType() == JSTokenTypes.DARROW) - { - return true; - } - } - return false; - } - finally - { - marker.rollbackTo(); - } - } - - @Override - protected void parseProperty(PsiBuilder builder) - { - final IElementType nameTokenType = builder.getTokenType(); - PsiBuilder.Marker propertyMark = builder.mark(); - - IElementType isSetterOrGetterType = null; - - if(nameTokenType == JSTokenTypes.LBRACKET) - { - PsiBuilder.Marker mark = builder.mark(); - builder.advanceLexer(); - parseExpression(builder); - checkMatches(builder, JSTokenTypes.RBRACKET, JavaScriptBundle.message("javascript.parser.message.expected.rbracket")); - mark.done(JSElementTypes.COMPUTED_NAME); - } - else - { - if(isNotPropertyStart(builder, nameTokenType)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.identifier.string.literal.or.numeric.literal")); - } - - IElementType setOrGetToken = isContextKeyword(builder, JSTokenTypes.GET_SET_TOKEN_SET); - - if(setOrGetToken != null && builder.lookAhead(1) == JSTokenTypes.IDENTIFIER) - { - isSetterOrGetterType = setOrGetToken; - - advanceContextKeyword(builder, isSetterOrGetterType); - } - else - { - // just advance identifier - builder.advanceLexer(); - } - } - - IElementType doneElement = JSElementTypes.PROPERTY; - - if(isSetterOrGetterType != null) - { - // advance name - see isSetterOrGetterType set - builder.advanceLexer(); - - getFunctionParsing().parseParameterList(builder); - - getStatementParsing().parseFunctionBody(builder); - - doneElement = JSElementTypes.FUNCTION_PROPERTY; - } - else - { - IElementType nextTokenType = builder.getTokenType(); - // we finished property - if((nextTokenType == JSTokenTypes.COMMA || nextTokenType == JSTokenTypes.RBRACE) && nameTokenType == JSTokenTypes.IDENTIFIER) - { - propertyMark.rollbackTo(); // rollback it - - propertyMark = builder.mark(); - - PsiBuilder.Marker referenceMark = builder.mark(); - builder.advanceLexer(); - referenceMark.done(JSElementTypes.REFERENCE_EXPRESSION); - } - else if(nextTokenType == JSTokenTypes.LPAR) - { - getFunctionParsing().parseParameterList(builder); - - getStatementParsing().parseFunctionBody(builder); - - doneElement = JSElementTypes.FUNCTION_PROPERTY; - } - else - { - checkMatches(builder, JSTokenTypes.COLON, JavaScriptBundle.message("javascript.parser.message.expected.colon")); - - builder.putUserData(WITHIN_OBJECT_LITERAL_EXPRESSION, Boolean.TRUE); - if(!parseAssignmentExpression(builder)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - builder.putUserData(WITHIN_OBJECT_LITERAL_EXPRESSION, null); - } - } - - propertyMark.done(doneElement); - } - - @Override - public boolean isNotPropertyStart(PsiBuilder builder, IElementType elementType) - { - return super.isNotPropertyStart(builder, elementType) && elementType != JSTokenTypes.LBRACKET; - } +public class EcmaScriptExpressionParsing extends ExpressionParsing { + public EcmaScriptExpressionParsing(EcmaScriptParsingContext context) { + super(context); + } + + @Override + public EcmaScriptStatementParsing getStatementParsing() { + return (EcmaScriptStatementParsing)super.getStatementParsing(); + } + + @Override + protected boolean parsePrimaryExpression(PsiBuilder builder) { + if (builder.getTokenType() == JSTokenTypes.DOT_DOT_DOT) { + PsiBuilder.Marker mark = builder.mark(); + builder.advanceLexer(); + + if (!parseExpressionOptional(builder)) { + mark.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + else { + mark.done(JSElementTypes.SPREAD_EXPRESSION); + } + + return true; + } + else if (builder.getTokenType() == JSTokenTypes.CLASS_KEYWORD) { + PsiBuilder.Marker mark = builder.mark(); + getStatementParsing().parseClassWithMarker(builder, builder.mark(), false); + mark.done(JSElementTypes.CLASS_EXPRESSION); + return true; + } + + if (canParseLambdaExpression(builder)) { + return parseLambdaExpression(builder); + } + return super.parsePrimaryExpression(builder); + } + + private boolean parseLambdaExpression(PsiBuilder builder) { + PsiBuilder.Marker mark = builder.mark(); + + IElementType tokenType = builder.getTokenType(); + if (tokenType == JSTokenTypes.IDENTIFIER) { + PsiBuilder.Marker parameterList = builder.mark(); + getFunctionParsing().parseParameter(builder, null); + parameterList.done(JSElementTypes.PARAMETER_LIST); + } + else { + getFunctionParsing().parseParameterList(builder); + } + + if (builder.getTokenType() == JSTokenTypes.DARROW) { + builder.advanceLexer(); + } + else { + mark.rollbackTo(); + return false; + } + + if (builder.getTokenType() == JSTokenTypes.LBRACE) { + getStatementParsing().parseBlock(builder); + } + else { + parseAssignmentExpression(builder); + } + + mark.done(JSElementTypes.LAMBDA_EXPRESSION); + return true; + } + + private boolean canParseLambdaExpression(PsiBuilder builder) { + PsiBuilder.Marker marker = builder.mark(); + try { + IElementType tokenType = builder.getTokenType(); + if (tokenType == JSTokenTypes.IDENTIFIER) { + builder.advanceLexer(); + if (builder.getTokenType() == JSTokenTypes.DARROW) { + return true; + } + } + else if (tokenType == JSTokenTypes.LPAR) { + getFunctionParsing().parseParameterList(builder); + + if (builder.getTokenType() == JSTokenTypes.DARROW) { + return true; + } + } + return false; + } + finally { + marker.rollbackTo(); + } + } + + @Override + protected void parseProperty(PsiBuilder builder) { + IElementType nameTokenType = builder.getTokenType(); + PsiBuilder.Marker propertyMark = builder.mark(); + + IElementType isSetterOrGetterType = null; + + if (nameTokenType == JSTokenTypes.LBRACKET) { + PsiBuilder.Marker mark = builder.mark(); + builder.advanceLexer(); + parseExpression(builder); + checkMatches(builder, JSTokenTypes.RBRACKET, JavaScriptLocalize.javascriptParserMessageExpectedRbracket()); + mark.done(JSElementTypes.COMPUTED_NAME); + } + else { + if (isNotPropertyStart(builder, nameTokenType)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedIdentifierStringLiteralOrNumericLiteral()); + } + + IElementType setOrGetToken = isContextKeyword(builder, JSTokenTypes.GET_SET_TOKEN_SET); + + if (setOrGetToken != null && builder.lookAhead(1) == JSTokenTypes.IDENTIFIER) { + isSetterOrGetterType = setOrGetToken; + + advanceContextKeyword(builder, isSetterOrGetterType); + } + else { + // just advance identifier + builder.advanceLexer(); + } + } + + IElementType doneElement = JSElementTypes.PROPERTY; + + if (isSetterOrGetterType != null) { + // advance name - see isSetterOrGetterType set + builder.advanceLexer(); + + getFunctionParsing().parseParameterList(builder); + + getStatementParsing().parseFunctionBody(builder); + + doneElement = JSElementTypes.FUNCTION_PROPERTY; + } + else { + IElementType nextTokenType = builder.getTokenType(); + // we finished property + if ((nextTokenType == JSTokenTypes.COMMA || nextTokenType == JSTokenTypes.RBRACE) && nameTokenType == JSTokenTypes.IDENTIFIER) { + propertyMark.rollbackTo(); // rollback it + + propertyMark = builder.mark(); + + PsiBuilder.Marker referenceMark = builder.mark(); + builder.advanceLexer(); + referenceMark.done(JSElementTypes.REFERENCE_EXPRESSION); + } + else if (nextTokenType == JSTokenTypes.LPAR) { + getFunctionParsing().parseParameterList(builder); + + getStatementParsing().parseFunctionBody(builder); + + doneElement = JSElementTypes.FUNCTION_PROPERTY; + } + else { + checkMatches(builder, JSTokenTypes.COLON, JavaScriptLocalize.javascriptParserMessageExpectedColon()); + + builder.putUserData(WITHIN_OBJECT_LITERAL_EXPRESSION, Boolean.TRUE); + if (!parseAssignmentExpression(builder)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + builder.putUserData(WITHIN_OBJECT_LITERAL_EXPRESSION, null); + } + } + + propertyMark.done(doneElement); + } + + @Override + public boolean isNotPropertyStart(PsiBuilder builder, IElementType elementType) { + return super.isNotPropertyStart(builder, elementType) && elementType != JSTokenTypes.LBRACKET; + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/parsing/EcmaScriptParser.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/parsing/EcmaScriptParser.java index 7a9a5529..8a0133e0 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/parsing/EcmaScriptParser.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/parsing/EcmaScriptParser.java @@ -21,25 +21,22 @@ import consulo.javascript.lang.parsing.JavaScriptParsingContext; import consulo.language.parser.PsiBuilder; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 15.02.2016 */ -public class EcmaScriptParser extends JavaScriptParser -{ - @Nonnull - @Override - public JavaScriptParsingContext createParsingContext() - { - return new EcmaScriptParsingContext(); - } +public class EcmaScriptParser extends JavaScriptParser { + @Nonnull + @Override + public JavaScriptParsingContext createParsingContext() { + return new EcmaScriptParsingContext(); + } - @Nonnull - @Override - public JavaScriptParserBuilder createBuilder(PsiBuilder builder) - { - return new EcmaScriptStrictParserBuilder(builder); - } + @Nonnull + @Override + public JavaScriptParserBuilder createBuilder(PsiBuilder builder) { + return new EcmaScriptStrictParserBuilder(builder); + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/parsing/EcmaScriptParsingContext.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/parsing/EcmaScriptParsingContext.java index adc740ae..0270a2e0 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/parsing/EcmaScriptParsingContext.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/parsing/EcmaScriptParsingContext.java @@ -20,25 +20,22 @@ import consulo.javascript.lang.parsing.JavaScriptParsingContext; import consulo.javascript.lang.parsing.StatementParsing; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 15.02.2016 */ -public class EcmaScriptParsingContext extends JavaScriptParsingContext -{ - @Nonnull - @Override - protected StatementParsing createStatementParsing() - { - return new EcmaScriptStatementParsing(this); - } +public class EcmaScriptParsingContext extends JavaScriptParsingContext { + @Nonnull + @Override + protected StatementParsing createStatementParsing() { + return new EcmaScriptStatementParsing(this); + } - @Nonnull - @Override - protected ExpressionParsing createExpressionParsing() - { - return new EcmaScriptExpressionParsing(this); - } + @Nonnull + @Override + protected ExpressionParsing createExpressionParsing() { + return new EcmaScriptExpressionParsing(this); + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/parsing/EcmaScriptStatementParsing.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/parsing/EcmaScriptStatementParsing.java index 7c2c3f32..7bf16e9b 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/parsing/EcmaScriptStatementParsing.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/parsing/EcmaScriptStatementParsing.java @@ -22,490 +22,408 @@ import consulo.javascript.lang.JavaScriptTokenSets; import consulo.javascript.lang.parsing.Parsing; import consulo.javascript.lang.parsing.StatementParsing; -import consulo.javascript.language.JavaScriptBundle; import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.ast.IElementType; import consulo.language.ast.TokenSet; import consulo.language.parser.PsiBuilder; import consulo.logging.Logger; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 15.02.2016 */ -public class EcmaScriptStatementParsing extends StatementParsing -{ - private static final Logger LOGGER = Logger.getInstance(EcmaScriptStatementParsing.class); - - public EcmaScriptStatementParsing(EcmaScriptParsingContext context) - { - super(context); - } - - @Override - public void parseSourceElement(PsiBuilder builder) - { - final IElementType tokenType = builder.getTokenType(); - if(tokenType == JSTokenTypes.FUNCTION_KEYWORD) - { - getFunctionParsing().parseFunctionDeclaration(builder); - } - else if(tokenType == JSTokenTypes.EXPORT_KEYWORD && builder.lookAhead(1) == JSTokenTypes.DEFAULT_KEYWORD) - { - PsiBuilder.Marker mark = builder.mark(); - builder.advanceLexer(); - builder.advanceLexer(); - - parseSourceElement(builder); - - mark.done(EcmaScript6ElementTypes.EXPORT_DEFAULT_ASSIGMENT); - } - else if(tokenType == JSTokenTypes.EXPORT_KEYWORD) - { - PsiBuilder.Marker mark = builder.mark(); - PsiBuilder.Marker attributeMark = builder.mark(); - builder.advanceLexer(); - attributeMark.done(JSElementTypes.ATTRIBUTE_LIST); - - IElementType nextType = builder.getTokenType(); - if(nextType == JSTokenTypes.FUNCTION_KEYWORD) - { - getFunctionParsing().parseFunctionNoMarker(builder, false, mark); - } - else if(nextType == JSTokenTypes.CLASS_KEYWORD) - { - parseClassWithMarker(builder, mark, false); - } - else if(nextType == JSTokenTypes.VAR_KEYWORD || - nextType == JSTokenTypes.CONST_KEYWORD || - nextType == JSTokenTypes.LET_KEYWORD) - { - parseVarStatementWithMarker(builder, false, mark); - } - else - { - mark.error("Expected function or variable"); - } - } - else - { - doParseStatement(builder, true); - } - } - - @Override - protected boolean parseForLoopHeader(final PsiBuilder builder) - { - builder.advanceLexer(); - - Parsing.checkMatches(builder, JSTokenTypes.LPAR, JavaScriptBundle.message("javascript.parser.message.expected.lparen")); - final boolean empty; - if(builder.getTokenType() == JSTokenTypes.VAR_KEYWORD || builder.getTokenType() == JSTokenTypes.LET_KEYWORD || builder.getTokenType() == JSTokenTypes.CONST_KEYWORD) - { - parseVarStatement(builder, true); - empty = false; - } - else - { - empty = !getExpressionParsing().parseExpressionOptional(builder, false); - } - - boolean forin = false; - if(builder.getTokenType() == JSTokenTypes.SEMICOLON) - { - builder.advanceLexer(); - getExpressionParsing().parseExpressionOptional(builder); - - if(builder.getTokenType() == JSTokenTypes.SEMICOLON) - { - builder.advanceLexer(); - } - else - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.semicolon")); - } - getExpressionParsing().parseExpressionOptional(builder); - } - else if(isContextKeyword(builder, JSTokenTypes.OF_KEYWORD) || builder.getTokenType() == JSTokenTypes.IN_KEYWORD) - { - forin = true; - if(empty) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.forloop.left.hand.side.expression.or.variable.declaration")); - } - - if(builder.getTokenType() == JSTokenTypes.IN_KEYWORD) - { - builder.advanceLexer(); - } - else - { - advanceContextKeyword(builder, JSTokenTypes.OF_KEYWORD); - } - - getExpressionParsing().parseExpression(builder); - } - else - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.forloop.in.of.or.semicolon")); - } - - Parsing.checkMatches(builder, JSTokenTypes.RPAR, JavaScriptBundle.message("javascript.parser.message.expected.rparen")); - return forin; - } - - @Override - protected void doParseStatement(PsiBuilder builder, boolean canHaveClasses) - { - if(canHaveClasses) - { - if(builder.getTokenType() == JSTokenTypes.IMPORT_KEYWORD) - { - parseImportStatement(builder); - return; - } - } - super.doParseStatement(builder, canHaveClasses); - } - - private void parseImportStatement(final PsiBuilder builder) - { - final PsiBuilder.Marker importStatement = builder.mark(); - try - { - builder.advanceLexer(); - - boolean wantFrom = true; - - if(builder.getTokenType() == JSTokenTypes.ASTERISK) - { - PsiBuilder.Marker bindingMark = builder.mark(); - - builder.advanceLexer(); - - if(isContextKeyword(builder, JSTokenTypes.AS_KEYWORD)) - { - advanceContextKeyword(builder, JSTokenTypes.AS_KEYWORD); - - if(builder.getTokenType() == JSTokenTypes.IDENTIFIER) - { - builder.advanceLexer(); - } - else - { - builder.error(JavaScriptLocalize.javascriptParserMessageExpectedIdentifier()); - } - } - - bindingMark.done(EcmaScript6ElementTypes.IMPORTED_BINDING); - } - else if(JavaScriptTokenSets.STRING_LITERALS.contains(builder.getTokenType())) - { - builder.advanceLexer(); - wantFrom = false; - } - else - { - boolean firstBinding = true; - - while(!builder.eof()) - { - if(builder.getTokenType() != JSTokenTypes.COMMA && !isIdentifierToken(builder) && builder.getTokenType() != JSTokenTypes.LBRACE) - { - break; - } - - if(isContextKeyword(builder, JSTokenTypes.FROM_KEYWORD)) - { - break; - } - - if(!firstBinding) - { - Parsing.checkMatches(builder, JSTokenTypes.COMMA, "Comma expected"); - } - - if(builder.getTokenType() == JSTokenTypes.LBRACE) - { - PsiBuilder.Marker namedImportsMark = builder.mark(); - builder.advanceLexer(); - - boolean first = true; - while(!builder.eof()) - { - if(builder.getTokenType() == JSTokenTypes.RBRACE) - { - break; - } - - if(!first) - { - if(builder.getTokenType() == JSTokenTypes.COMMA) - { - builder.advanceLexer(); - } - else - { - builder.error("Comma expected"); - } - } - - first = false; - - if(builder.getTokenType() == JSTokenTypes.IDENTIFIER) - { - PsiBuilder.Marker importBindingMark = builder.mark(); - builder.advanceLexer(); - - if(isContextKeyword(builder, JSTokenTypes.AS_KEYWORD)) - { - PsiBuilder.Marker importSpecificMark = builder.mark(); - advanceContextKeyword(builder, JSTokenTypes.AS_KEYWORD); - - if(builder.getTokenType() == JSTokenTypes.IDENTIFIER) - { - builder.advanceLexer(); - - importSpecificMark.done(EcmaScript6ElementTypes.IMPORT_SPECIFIER); - } - else - { - importSpecificMark.error("Expected identifier"); - } - } - - importBindingMark.done(EcmaScript6ElementTypes.IMPORTED_BINDING); - } - else if(builder.getTokenType() != JSTokenTypes.RBRACE) - { - builder.error("Expected identifier"); - break; - } - } - - Parsing.checkMatches(builder, JSTokenTypes.RBRACE, "'}' expected"); - - namedImportsMark.done(EcmaScript6ElementTypes.NAMED_IMPORTS); - } - else if(builder.getTokenType() == JSTokenTypes.IDENTIFIER) - { - PsiBuilder.Marker importBindingMark = builder.mark(); - builder.advanceLexer(); - importBindingMark.done(EcmaScript6ElementTypes.IMPORTED_BINDING); - } - else - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.typename")); - break; - } - - firstBinding = false; - } - } - - if(wantFrom && isContextKeyword(builder, JSTokenTypes.FROM_KEYWORD)) - { - advanceContextKeyword(builder, JSTokenTypes.FROM_KEYWORD); - - if(JavaScriptTokenSets.STRING_LITERALS.contains(builder.getTokenType())) - { - builder.advanceLexer(); - } - else - { - builder.error("Expecte from target"); - } - } - - checkForSemicolon(builder); - } - finally - { - importStatement.done(EcmaScript6ElementTypes.IMPORT_DECLARATION); - } - } - - @Override - protected boolean doParseStatementSub(PsiBuilder builder, boolean canHaveClasses) - { - IElementType tokenType = builder.getTokenType(); - if(canHaveClasses) - { - if(tokenType == JSTokenTypes.CLASS_KEYWORD) - { - parseClass(builder, true); - return true; - } - } - return false; - } - - private void parseClass(final PsiBuilder builder, boolean nameRequired) - { - parseClassWithMarker(builder, builder.mark(), nameRequired); - } - - public void parseClassWithMarker(final PsiBuilder builder, final @Nonnull PsiBuilder.Marker clazz, boolean nameRequired) - { - builder.advanceLexer(); - - if(builder.getTokenType() != JSTokenTypes.IDENTIFIER) - { - if(nameRequired) - { - builder.error(JavaScriptLocalize.javascriptParserMessageExpectedIdentifier()); - } - } - else - { - builder.advanceLexer(); - } - - if(builder.getTokenType() == JSTokenTypes.EXTENDS_KEYWORD) - { - parseReferenceList(builder); - } - - parseClassBody(builder, BlockType.PACKAGE_OR_CLASS_BODY); - clazz.done(JSElementTypes.CLASS); - } - - protected void parseClassBody(final PsiBuilder builder, BlockType type) - { - if(builder.getTokenType() != JSTokenTypes.LBRACE) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.lbrace")); - return; - } - - builder.advanceLexer(); - while(builder.getTokenType() != JSTokenTypes.RBRACE) - { - if(builder.eof()) - { - builder.error(JavaScriptLocalize.javascriptParserMessageMissingRbrace()); - return; - } - - PsiBuilder.Marker attributeListMarker = builder.mark(); - if(expectStaticKeywordExpected(builder)) - { - attributeListMarker.done(JSElementTypes.ATTRIBUTE_LIST); - } - else - { - attributeListMarker.drop(); - attributeListMarker = null; - } - - IElementType tokenType = builder.getTokenType(); - if(tokenType != JSTokenTypes.IDENTIFIER && tokenType != JSTokenTypes.MULT) - { - if(attributeListMarker != null) - { - attributeListMarker.rollbackTo(); - } - - PsiBuilder.Marker mark = builder.mark(); - - if(attributeListMarker != null) - { - PsiBuilder.Marker temp = builder.mark(); - expectStaticKeywordExpected(builder); - temp.done(JSElementTypes.ATTRIBUTE_LIST); - } - - builder.advanceLexer(); - mark.error("Expected identifier or *"); - } - else - { - if(attributeListMarker != null) - { - attributeListMarker.rollbackTo(); - } - - PsiBuilder.Marker mark = builder.mark(); - - if(attributeListMarker != null) - { - PsiBuilder.Marker temp = builder.mark(); - expectStaticKeywordExpected(builder); - temp.done(JSElementTypes.ATTRIBUTE_LIST); - } - - if(builder.getTokenType() == JSTokenTypes.MULT) - { - builder.advanceLexer(); - } - else - { - if(isContextKeyword(builder, JSTokenTypes.GET_SET_TOKEN_SET) != null && builder.lookAhead(1) == JSTokenTypes.IDENTIFIER) - { - advanceContextKeyword(builder, JSTokenTypes.GET_SET_TOKEN_SET); - } - } - - if(!JSTokenTypes.IDENTIFIER_TOKENS_SET.contains(builder.getTokenType())) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.identifier")); - } - else - { - builder.advanceLexer(); - } - - getFunctionParsing().parseParameterList(builder); - getStatementParsing().parseFunctionBody(builder); - - checkForSemicolon(builder); - - mark.done(JSElementTypes.FUNCTION_DECLARATION); - } - } - - builder.advanceLexer(); - } - - private boolean expectStaticKeywordExpected(PsiBuilder builder) - { - IElementType tokenType = builder.getTokenType(); - if(tokenType == JSTokenTypes.STATIC_KEYWORD) - { - builder.advanceLexer(); - return true; - } - else if(isContextKeyword(builder, TokenSet.create(JSTokenTypes.STATIC_KEYWORD)) != null) - { - if(builder.lookAhead(1) == JSTokenTypes.IDENTIFIER) - { - advanceContextKeyword(builder, TokenSet.create(JSTokenTypes.STATIC_KEYWORD)); - return true; - } - } - return false; - } - - private void parseReferenceList(final PsiBuilder builder) - { - final IElementType tokenType = builder.getTokenType(); - LOGGER.assertTrue(tokenType == JSTokenTypes.EXTENDS_KEYWORD || tokenType == JSTokenTypes.IMPLEMENTS_KEYWORD); - final PsiBuilder.Marker referenceList = builder.mark(); - builder.advanceLexer(); - - if(getExpressionParsing().parseQualifiedTypeName(builder)) - { - while(builder.getTokenType() == JSTokenTypes.COMMA) - { - builder.advanceLexer(); - if(!getExpressionParsing().parseQualifiedTypeName(builder)) - { - break; - } - } - } - referenceList.done(JSElementTypes.EXTENDS_LIST); - } +public class EcmaScriptStatementParsing extends StatementParsing { + private static final Logger LOGGER = Logger.getInstance(EcmaScriptStatementParsing.class); + + public EcmaScriptStatementParsing(EcmaScriptParsingContext context) { + super(context); + } + + @Override + public void parseSourceElement(PsiBuilder builder) { + IElementType tokenType = builder.getTokenType(); + if (tokenType == JSTokenTypes.FUNCTION_KEYWORD) { + getFunctionParsing().parseFunctionDeclaration(builder); + } + else if (tokenType == JSTokenTypes.EXPORT_KEYWORD && builder.lookAhead(1) == JSTokenTypes.DEFAULT_KEYWORD) { + PsiBuilder.Marker mark = builder.mark(); + builder.advanceLexer(); + builder.advanceLexer(); + + parseSourceElement(builder); + + mark.done(EcmaScript6ElementTypes.EXPORT_DEFAULT_ASSIGMENT); + } + else if (tokenType == JSTokenTypes.EXPORT_KEYWORD) { + PsiBuilder.Marker mark = builder.mark(); + PsiBuilder.Marker attributeMark = builder.mark(); + builder.advanceLexer(); + attributeMark.done(JSElementTypes.ATTRIBUTE_LIST); + + IElementType nextType = builder.getTokenType(); + if (nextType == JSTokenTypes.FUNCTION_KEYWORD) { + getFunctionParsing().parseFunctionNoMarker(builder, false, mark); + } + else if (nextType == JSTokenTypes.CLASS_KEYWORD) { + parseClassWithMarker(builder, mark, false); + } + else if (nextType == JSTokenTypes.VAR_KEYWORD || + nextType == JSTokenTypes.CONST_KEYWORD || + nextType == JSTokenTypes.LET_KEYWORD) { + parseVarStatementWithMarker(builder, false, mark); + } + else { + mark.error("Expected function or variable"); + } + } + else { + doParseStatement(builder, true); + } + } + + @Override + protected boolean parseForLoopHeader(PsiBuilder builder) { + builder.advanceLexer(); + + Parsing.checkMatches(builder, JSTokenTypes.LPAR, JavaScriptLocalize.javascriptParserMessageExpectedLparen()); + boolean empty; + if (builder.getTokenType() == JSTokenTypes.VAR_KEYWORD + || builder.getTokenType() == JSTokenTypes.LET_KEYWORD + || builder.getTokenType() == JSTokenTypes.CONST_KEYWORD) { + parseVarStatement(builder, true); + empty = false; + } + else { + empty = !getExpressionParsing().parseExpressionOptional(builder, false); + } + + boolean forin = false; + if (builder.getTokenType() == JSTokenTypes.SEMICOLON) { + builder.advanceLexer(); + getExpressionParsing().parseExpressionOptional(builder); + + if (builder.getTokenType() == JSTokenTypes.SEMICOLON) { + builder.advanceLexer(); + } + else { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedSemicolon()); + } + getExpressionParsing().parseExpressionOptional(builder); + } + else if (isContextKeyword(builder, JSTokenTypes.OF_KEYWORD) || builder.getTokenType() == JSTokenTypes.IN_KEYWORD) { + forin = true; + if (empty) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedForloopLeftHandSideExpressionOrVariableDeclaration()); + } + + if (builder.getTokenType() == JSTokenTypes.IN_KEYWORD) { + builder.advanceLexer(); + } + else { + advanceContextKeyword(builder, JSTokenTypes.OF_KEYWORD); + } + + getExpressionParsing().parseExpression(builder); + } + else { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedForloopInOfOrSemicolon()); + } + + Parsing.checkMatches(builder, JSTokenTypes.RPAR, JavaScriptLocalize.javascriptParserMessageExpectedRparen()); + return forin; + } + + @Override + protected void doParseStatement(PsiBuilder builder, boolean canHaveClasses) { + if (canHaveClasses) { + if (builder.getTokenType() == JSTokenTypes.IMPORT_KEYWORD) { + parseImportStatement(builder); + return; + } + } + super.doParseStatement(builder, canHaveClasses); + } + + private void parseImportStatement(PsiBuilder builder) { + PsiBuilder.Marker importStatement = builder.mark(); + try { + builder.advanceLexer(); + + boolean wantFrom = true; + + if (builder.getTokenType() == JSTokenTypes.ASTERISK) { + PsiBuilder.Marker bindingMark = builder.mark(); + + builder.advanceLexer(); + + if (isContextKeyword(builder, JSTokenTypes.AS_KEYWORD)) { + advanceContextKeyword(builder, JSTokenTypes.AS_KEYWORD); + + if (builder.getTokenType() == JSTokenTypes.IDENTIFIER) { + builder.advanceLexer(); + } + else { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedIdentifier()); + } + } + + bindingMark.done(EcmaScript6ElementTypes.IMPORTED_BINDING); + } + else if (JavaScriptTokenSets.STRING_LITERALS.contains(builder.getTokenType())) { + builder.advanceLexer(); + wantFrom = false; + } + else { + boolean firstBinding = true; + + while (!builder.eof()) { + if (builder.getTokenType() != JSTokenTypes.COMMA + && !isIdentifierToken(builder) + && builder.getTokenType() != JSTokenTypes.LBRACE) { + break; + } + + if (isContextKeyword(builder, JSTokenTypes.FROM_KEYWORD)) { + break; + } + + if (!firstBinding) { + Parsing.checkMatches(builder, JSTokenTypes.COMMA, JavaScriptLocalize.javascriptParserMessageExpectedComma()); + } + + if (builder.getTokenType() == JSTokenTypes.LBRACE) { + PsiBuilder.Marker namedImportsMark = builder.mark(); + builder.advanceLexer(); + + boolean first = true; + while (!builder.eof()) { + if (builder.getTokenType() == JSTokenTypes.RBRACE) { + break; + } + + if (!first) { + if (builder.getTokenType() == JSTokenTypes.COMMA) { + builder.advanceLexer(); + } + else { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedComma()); + } + } + + first = false; + + if (builder.getTokenType() == JSTokenTypes.IDENTIFIER) { + PsiBuilder.Marker importBindingMark = builder.mark(); + builder.advanceLexer(); + + if (isContextKeyword(builder, JSTokenTypes.AS_KEYWORD)) { + PsiBuilder.Marker importSpecificMark = builder.mark(); + advanceContextKeyword(builder, JSTokenTypes.AS_KEYWORD); + + if (builder.getTokenType() == JSTokenTypes.IDENTIFIER) { + builder.advanceLexer(); + + importSpecificMark.done(EcmaScript6ElementTypes.IMPORT_SPECIFIER); + } + else { + importSpecificMark.error(JavaScriptLocalize.javascriptParserMessageExpectedIdentifier()); + } + } + + importBindingMark.done(EcmaScript6ElementTypes.IMPORTED_BINDING); + } + else if (builder.getTokenType() != JSTokenTypes.RBRACE) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedIdentifier()); + break; + } + } + + Parsing.checkMatches(builder, JSTokenTypes.RBRACE, JavaScriptLocalize.javascriptParserMessageExpectedRbrace()); + + namedImportsMark.done(EcmaScript6ElementTypes.NAMED_IMPORTS); + } + else if (builder.getTokenType() == JSTokenTypes.IDENTIFIER) { + PsiBuilder.Marker importBindingMark = builder.mark(); + builder.advanceLexer(); + importBindingMark.done(EcmaScript6ElementTypes.IMPORTED_BINDING); + } + else { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedTypename()); + break; + } + + firstBinding = false; + } + } + + if (wantFrom && isContextKeyword(builder, JSTokenTypes.FROM_KEYWORD)) { + advanceContextKeyword(builder, JSTokenTypes.FROM_KEYWORD); + + if (JavaScriptTokenSets.STRING_LITERALS.contains(builder.getTokenType())) { + builder.advanceLexer(); + } + else { + builder.error("Expected 'from' target"); + } + } + + checkForSemicolon(builder); + } + finally { + importStatement.done(EcmaScript6ElementTypes.IMPORT_DECLARATION); + } + } + + @Override + protected boolean doParseStatementSub(PsiBuilder builder, boolean canHaveClasses) { + IElementType tokenType = builder.getTokenType(); + if (canHaveClasses) { + if (tokenType == JSTokenTypes.CLASS_KEYWORD) { + parseClass(builder, true); + return true; + } + } + return false; + } + + private void parseClass(PsiBuilder builder, boolean nameRequired) { + parseClassWithMarker(builder, builder.mark(), nameRequired); + } + + public void parseClassWithMarker(PsiBuilder builder, @Nonnull PsiBuilder.Marker clazz, boolean nameRequired) { + builder.advanceLexer(); + + if (builder.getTokenType() != JSTokenTypes.IDENTIFIER) { + if (nameRequired) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedIdentifier()); + } + } + else { + builder.advanceLexer(); + } + + if (builder.getTokenType() == JSTokenTypes.EXTENDS_KEYWORD) { + parseReferenceList(builder); + } + + parseClassBody(builder, BlockType.PACKAGE_OR_CLASS_BODY); + clazz.done(JSElementTypes.CLASS); + } + + protected void parseClassBody(PsiBuilder builder, BlockType type) { + if (builder.getTokenType() != JSTokenTypes.LBRACE) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedLbrace()); + return; + } + + builder.advanceLexer(); + while (builder.getTokenType() != JSTokenTypes.RBRACE) { + if (builder.eof()) { + builder.error(JavaScriptLocalize.javascriptParserMessageMissingRbrace()); + return; + } + + PsiBuilder.Marker attributeListMarker = builder.mark(); + if (expectStaticKeywordExpected(builder)) { + attributeListMarker.done(JSElementTypes.ATTRIBUTE_LIST); + } + else { + attributeListMarker.drop(); + attributeListMarker = null; + } + + IElementType tokenType = builder.getTokenType(); + if (tokenType != JSTokenTypes.IDENTIFIER && tokenType != JSTokenTypes.MULT) { + if (attributeListMarker != null) { + attributeListMarker.rollbackTo(); + } + + PsiBuilder.Marker mark = builder.mark(); + + if (attributeListMarker != null) { + PsiBuilder.Marker temp = builder.mark(); + expectStaticKeywordExpected(builder); + temp.done(JSElementTypes.ATTRIBUTE_LIST); + } + + builder.advanceLexer(); + mark.error("Expected identifier or *"); + } + else { + if (attributeListMarker != null) { + attributeListMarker.rollbackTo(); + } + + PsiBuilder.Marker mark = builder.mark(); + + if (attributeListMarker != null) { + PsiBuilder.Marker temp = builder.mark(); + expectStaticKeywordExpected(builder); + temp.done(JSElementTypes.ATTRIBUTE_LIST); + } + + if (builder.getTokenType() == JSTokenTypes.MULT) { + builder.advanceLexer(); + } + else { + if (isContextKeyword( + builder, + JSTokenTypes.GET_SET_TOKEN_SET + ) != null && builder.lookAhead(1) == JSTokenTypes.IDENTIFIER) { + advanceContextKeyword(builder, JSTokenTypes.GET_SET_TOKEN_SET); + } + } + + if (!JSTokenTypes.IDENTIFIER_TOKENS_SET.contains(builder.getTokenType())) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedIdentifier()); + } + else { + builder.advanceLexer(); + } + + getFunctionParsing().parseParameterList(builder); + getStatementParsing().parseFunctionBody(builder); + + checkForSemicolon(builder); + + mark.done(JSElementTypes.FUNCTION_DECLARATION); + } + } + + builder.advanceLexer(); + } + + private boolean expectStaticKeywordExpected(PsiBuilder builder) { + IElementType tokenType = builder.getTokenType(); + if (tokenType == JSTokenTypes.STATIC_KEYWORD) { + builder.advanceLexer(); + return true; + } + else if (isContextKeyword(builder, TokenSet.create(JSTokenTypes.STATIC_KEYWORD)) != null) { + if (builder.lookAhead(1) == JSTokenTypes.IDENTIFIER) { + advanceContextKeyword(builder, TokenSet.create(JSTokenTypes.STATIC_KEYWORD)); + return true; + } + } + return false; + } + + private void parseReferenceList(PsiBuilder builder) { + IElementType tokenType = builder.getTokenType(); + LOGGER.assertTrue(tokenType == JSTokenTypes.EXTENDS_KEYWORD || tokenType == JSTokenTypes.IMPLEMENTS_KEYWORD); + PsiBuilder.Marker referenceList = builder.mark(); + builder.advanceLexer(); + + if (getExpressionParsing().parseSimpleExpression(builder)) { + while (builder.getTokenType() == JSTokenTypes.COMMA) { + builder.advanceLexer(); + if (!getExpressionParsing().parseSimpleExpression(builder)) { + break; + } + } + } + referenceList.done(JSElementTypes.EXTENDS_LIST); + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/parsing/EcmaScriptStrictParserBuilder.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/parsing/EcmaScriptStrictParserBuilder.java index fd05746a..89e957ab 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/parsing/EcmaScriptStrictParserBuilder.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/lang/parsing/EcmaScriptStrictParserBuilder.java @@ -8,18 +8,16 @@ * @author VISTALL * @since 15.02.2016 */ -public class EcmaScriptStrictParserBuilder extends JavaScriptStrictParserBuilder -{ - public EcmaScriptStrictParserBuilder(PsiBuilder delegate) - { - super(delegate); +public class EcmaScriptStrictParserBuilder extends JavaScriptStrictParserBuilder { + public EcmaScriptStrictParserBuilder(PsiBuilder delegate) { + super(delegate); - onlyInStrictMode(JSTokenTypes.IMPLEMENTS_KEYWORD); - onlyInStrictMode(JSTokenTypes.PACKAGE_KEYWORD); - onlyInStrictMode(JSTokenTypes.PUBLIC_KEYWORD); - onlyInStrictMode(JSTokenTypes.PRIVATE_KEYWORD); - onlyInStrictMode(JSTokenTypes.PROTECTED_KEYWORD); - onlyInStrictMode(JSTokenTypes.INTERFACE_KEYWORD); - onlyInStrictMode(JSTokenTypes.STATIC_KEYWORD); - } + onlyInStrictMode(JSTokenTypes.IMPLEMENTS_KEYWORD); + onlyInStrictMode(JSTokenTypes.PACKAGE_KEYWORD); + onlyInStrictMode(JSTokenTypes.PUBLIC_KEYWORD); + onlyInStrictMode(JSTokenTypes.PRIVATE_KEYWORD); + onlyInStrictMode(JSTokenTypes.PROTECTED_KEYWORD); + onlyInStrictMode(JSTokenTypes.INTERFACE_KEYWORD); + onlyInStrictMode(JSTokenTypes.STATIC_KEYWORD); + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/ES6ExportDefaultAssignment.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/ES6ExportDefaultAssignment.java index 3fd3ff17..001e62fc 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/ES6ExportDefaultAssignment.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/ES6ExportDefaultAssignment.java @@ -6,6 +6,5 @@ * @author VISTALL * @since 2019-12-14 */ -public interface ES6ExportDefaultAssignment extends JSStatement -{ +public interface ES6ExportDefaultAssignment extends JSStatement { } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/ES6ImportDeclaration.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/ES6ImportDeclaration.java index 45afdd32..e62f8616 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/ES6ImportDeclaration.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/ES6ImportDeclaration.java @@ -8,6 +8,5 @@ * * import ... */ -public interface ES6ImportDeclaration extends JavaScriptImportStatementBase -{ +public interface ES6ImportDeclaration extends JavaScriptImportStatementBase { } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/ES6ImportSpecifier.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/ES6ImportSpecifier.java index 658ea9c5..9341ccc6 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/ES6ImportSpecifier.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/ES6ImportSpecifier.java @@ -9,6 +9,5 @@ * * import {import as importSpecifier} ... */ -public interface ES6ImportSpecifier extends JSElement, PsiNameIdentifierOwner -{ +public interface ES6ImportSpecifier extends JSElement, PsiNameIdentifierOwner { } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/ES6ImportedBinding.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/ES6ImportedBinding.java index b2718d8c..de9c92ba 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/ES6ImportedBinding.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/ES6ImportedBinding.java @@ -3,8 +3,7 @@ import com.intellij.lang.javascript.psi.JSElement; import consulo.annotation.access.RequiredReadAction; import consulo.language.psi.PsiNameIdentifierOwner; - -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; /** * @author VISTALL @@ -16,9 +15,8 @@ *

* import * as util ... */ -public interface ES6ImportedBinding extends JSElement, PsiNameIdentifierOwner -{ - @Nullable - @RequiredReadAction - ES6ImportSpecifier getImportSpecifier(); +public interface ES6ImportedBinding extends JSElement, PsiNameIdentifierOwner { + @Nullable + @RequiredReadAction + ES6ImportSpecifier getImportSpecifier(); } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/ES6NamedImports.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/ES6NamedImports.java index 8b268040..52ad21e0 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/ES6NamedImports.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/ES6NamedImports.java @@ -3,7 +3,7 @@ import com.intellij.lang.javascript.psi.JSElement; import consulo.annotation.access.RequiredReadAction; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL @@ -12,9 +12,8 @@ * import { test } ... * .......^^^^^^^ named imports group */ -public interface ES6NamedImports extends JSElement -{ - @Nonnull - @RequiredReadAction - ES6ImportedBinding[] getBindings(); +public interface ES6NamedImports extends JSElement { + @Nonnull + @RequiredReadAction + ES6ImportedBinding[] getBindings(); } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/ES6ExportDefaultAssignmentImpl.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/ES6ExportDefaultAssignmentImpl.java index 8bd18081..c721f470 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/ES6ExportDefaultAssignmentImpl.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/ES6ExportDefaultAssignmentImpl.java @@ -10,40 +10,39 @@ import consulo.language.psi.resolve.PsiScopeProcessor; import consulo.language.psi.resolve.ResolveState; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL * @since 2019-12-14 */ -public class ES6ExportDefaultAssignmentImpl extends JSStatementImpl implements ES6ExportDefaultAssignment -{ - public ES6ExportDefaultAssignmentImpl(ASTNode node) - { - super(node); - } +public class ES6ExportDefaultAssignmentImpl extends JSStatementImpl implements ES6ExportDefaultAssignment { + public ES6ExportDefaultAssignmentImpl(ASTNode node) { + super(node); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSElement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSElement(this); + } - @Nullable - public JSElement getElement() - { - return findChildByClass(JSClass.class); - } + @Nullable + public JSElement getElement() { + return findChildByClass(JSClass.class); + } - @Override - public boolean processDeclarations(@Nonnull PsiScopeProcessor processor, @Nonnull ResolveState state, PsiElement lastParent, @Nonnull PsiElement place) - { - JSElement element = getElement(); - if(element != null && !element.processDeclarations(processor, state, lastParent, place)) - { - return false; - } - return super.processDeclarations(processor, state, lastParent, place); - } + @Override + public boolean processDeclarations( + @Nonnull PsiScopeProcessor processor, + @Nonnull ResolveState state, + PsiElement lastParent, + @Nonnull PsiElement place + ) { + JSElement element = getElement(); + if (element != null && !element.processDeclarations(processor, state, lastParent, place)) { + return false; + } + return super.processDeclarations(processor, state, lastParent, place); + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/ES6ImportDeclarationImpl.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/ES6ImportDeclarationImpl.java index 975ea395..ef0d54d4 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/ES6ImportDeclarationImpl.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/ES6ImportDeclarationImpl.java @@ -8,35 +8,34 @@ import consulo.language.psi.resolve.PsiScopeProcessor; import consulo.language.psi.resolve.ResolveState; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 2019-12-14 */ -public class ES6ImportDeclarationImpl extends JSStatementImpl implements ES6ImportDeclaration -{ - public ES6ImportDeclarationImpl(ASTNode node) - { - super(node); - } +public class ES6ImportDeclarationImpl extends JSStatementImpl implements ES6ImportDeclaration { + public ES6ImportDeclarationImpl(ASTNode node) { + super(node); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSElement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSElement(this); + } - @Override - public boolean processDeclarations(@Nonnull PsiScopeProcessor processor, @Nonnull ResolveState state, PsiElement lastParent, @Nonnull PsiElement place) - { - for(PsiElement child : getChildren()) - { - if(!child.processDeclarations(processor, state, lastParent, place)) - { - return false; - } - } - return true; - } + @Override + public boolean processDeclarations( + @Nonnull PsiScopeProcessor processor, + @Nonnull ResolveState state, + PsiElement lastParent, + @Nonnull PsiElement place + ) { + for (PsiElement child : getChildren()) { + if (!child.processDeclarations(processor, state, lastParent, place)) { + return false; + } + } + return true; + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/ES6ImportSpecifierImpl.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/ES6ImportSpecifierImpl.java index cae389d9..22fd511a 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/ES6ImportSpecifierImpl.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/ES6ImportSpecifierImpl.java @@ -10,38 +10,33 @@ import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL * @since 2020-08-26 */ -public class ES6ImportSpecifierImpl extends JSElementImpl implements ES6ImportSpecifier -{ - public ES6ImportSpecifierImpl(ASTNode node) - { - super(node); - } +public class ES6ImportSpecifierImpl extends JSElementImpl implements ES6ImportSpecifier { + public ES6ImportSpecifierImpl(ASTNode node) { + super(node); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSElement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSElement(this); + } - @RequiredReadAction - @Nullable - @Override - public PsiElement getNameIdentifier() - { - return findChildByType(JSTokenTypes.IDENTIFIER); - } + @RequiredReadAction + @Nullable + @Override + public PsiElement getNameIdentifier() { + return findChildByType(JSTokenTypes.IDENTIFIER); + } - @RequiredWriteAction - @Override - public PsiElement setName(@Nonnull String s) throws IncorrectOperationException - { - return null; - } + @RequiredWriteAction + @Override + public PsiElement setName(@Nonnull String s) throws IncorrectOperationException { + return null; + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/ES6ImportedBindingImpl.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/ES6ImportedBindingImpl.java index 0a879af6..70f5b3b2 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/ES6ImportedBindingImpl.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/ES6ImportedBindingImpl.java @@ -13,73 +13,68 @@ import consulo.language.psi.resolve.ResolveState; import consulo.language.util.IncorrectOperationException; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL * @since 2019-12-14 */ -public class ES6ImportedBindingImpl extends JSElementImpl implements ES6ImportedBinding -{ - public ES6ImportedBindingImpl(ASTNode node) - { - super(node); - } +public class ES6ImportedBindingImpl extends JSElementImpl implements ES6ImportedBinding { + public ES6ImportedBindingImpl(ASTNode node) { + super(node); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSElement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSElement(this); + } - @RequiredReadAction - @Override - public String getName() - { - PsiElement nameIdentifier = getNameIdentifier(); - return nameIdentifier == null ? null : nameIdentifier.getText(); - } + @RequiredReadAction + @Override + public String getName() { + PsiElement nameIdentifier = getNameIdentifier(); + return nameIdentifier == null ? null : nameIdentifier.getText(); + } - @RequiredReadAction - @Nullable - @Override - public PsiElement getNameIdentifier() - { - ES6ImportSpecifier importSpecifier = getImportSpecifier(); - if(importSpecifier != null) - { - return importSpecifier.getNameIdentifier(); - } - return findChildByType(JSTokenTypes.IDENTIFIER); - } + @RequiredReadAction + @Nullable + @Override + public PsiElement getNameIdentifier() { + ES6ImportSpecifier importSpecifier = getImportSpecifier(); + if (importSpecifier != null) { + return importSpecifier.getNameIdentifier(); + } + return findChildByType(JSTokenTypes.IDENTIFIER); + } - @RequiredReadAction - @Override - public int getTextOffset() - { - PsiElement nameIdentifier = getNameIdentifier(); - return nameIdentifier == null ? super.getTextOffset() : nameIdentifier.getTextOffset(); - } + @RequiredReadAction + @Override + public int getTextOffset() { + PsiElement nameIdentifier = getNameIdentifier(); + return nameIdentifier == null ? super.getTextOffset() : nameIdentifier.getTextOffset(); + } - @RequiredWriteAction - @Override - public PsiElement setName(@Nonnull String s) throws IncorrectOperationException - { - return null; - } + @RequiredWriteAction + @Override + public PsiElement setName(@Nonnull String s) throws IncorrectOperationException { + return null; + } - @Override - public boolean processDeclarations(@Nonnull PsiScopeProcessor processor, @Nonnull ResolveState state, PsiElement lastParent, @Nonnull PsiElement place) - { - return processor.execute(this, state); - } + @Override + public boolean processDeclarations( + @Nonnull PsiScopeProcessor processor, + @Nonnull ResolveState state, + PsiElement lastParent, + @Nonnull PsiElement place + ) { + return processor.execute(this, state); + } - @RequiredReadAction - @Nullable - @Override - public ES6ImportSpecifier getImportSpecifier() - { - return findChildByClass(ES6ImportSpecifier.class); - } + @RequiredReadAction + @Nullable + @Override + public ES6ImportSpecifier getImportSpecifier() { + return findChildByClass(ES6ImportSpecifier.class); + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/ES6NamedImportsImpl.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/ES6NamedImportsImpl.java index 2c21b944..04f126ac 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/ES6NamedImportsImpl.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/ES6NamedImportsImpl.java @@ -10,43 +10,41 @@ import consulo.language.psi.resolve.PsiScopeProcessor; import consulo.language.psi.resolve.ResolveState; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 2019-12-14 */ -public class ES6NamedImportsImpl extends JSElementImpl implements ES6NamedImports -{ - public ES6NamedImportsImpl(ASTNode node) - { - super(node); - } +public class ES6NamedImportsImpl extends JSElementImpl implements ES6NamedImports { + public ES6NamedImportsImpl(ASTNode node) { + super(node); + } - @Override - protected void accept(@Nonnull JSElementVisitor visitor) - { - visitor.visitJSElement(this); - } + @Override + protected void accept(@Nonnull JSElementVisitor visitor) { + visitor.visitJSElement(this); + } - @Override - public boolean processDeclarations(@Nonnull PsiScopeProcessor processor, @Nonnull ResolveState state, PsiElement lastParent, @Nonnull PsiElement place) - { - for(PsiElement child : getChildren()) - { - if(!child.processDeclarations(processor, state, lastParent, place)) - { - return false; - } - } - return true; - } + @Override + public boolean processDeclarations( + @Nonnull PsiScopeProcessor processor, + @Nonnull ResolveState state, + PsiElement lastParent, + @Nonnull PsiElement place + ) { + for (PsiElement child : getChildren()) { + if (!child.processDeclarations(processor, state, lastParent, place)) { + return false; + } + } + return true; + } - @RequiredReadAction - @Nonnull - @Override - public ES6ImportedBinding[] getBindings() - { - return findChildrenByClass(ES6ImportedBinding.class); - } + @RequiredReadAction + @Nonnull + @Override + public ES6ImportedBinding[] getBindings() { + return findChildrenByClass(ES6ImportedBinding.class); + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/EcmaScript6ElementTypes.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/EcmaScript6ElementTypes.java index c2ca4834..f9e96af8 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/EcmaScript6ElementTypes.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/EcmaScript6ElementTypes.java @@ -8,15 +8,19 @@ * @author VISTALL * @since 2019-12-14 */ -public interface EcmaScript6ElementTypes -{ - IElementType EXPORT_DEFAULT_ASSIGMENT = new ElementTypeAsPsiFactory("EXPORT_DEFAULT_ASSIGMENT", JavaScriptLanguage.INSTANCE, ES6ExportDefaultAssignmentImpl::new); +public interface EcmaScript6ElementTypes { + IElementType EXPORT_DEFAULT_ASSIGMENT = + new ElementTypeAsPsiFactory("EXPORT_DEFAULT_ASSIGMENT", JavaScriptLanguage.INSTANCE, ES6ExportDefaultAssignmentImpl::new); - IElementType IMPORT_DECLARATION = new ElementTypeAsPsiFactory("IMPORT_DECLARATION", JavaScriptLanguage.INSTANCE, ES6ImportDeclarationImpl::new); + IElementType IMPORT_DECLARATION = + new ElementTypeAsPsiFactory("IMPORT_DECLARATION", JavaScriptLanguage.INSTANCE, ES6ImportDeclarationImpl::new); - IElementType IMPORTED_BINDING = new ElementTypeAsPsiFactory("IMPORTED_BINDING", JavaScriptLanguage.INSTANCE, ES6ImportedBindingImpl::new); + IElementType IMPORTED_BINDING = + new ElementTypeAsPsiFactory("IMPORTED_BINDING", JavaScriptLanguage.INSTANCE, ES6ImportedBindingImpl::new); - IElementType NAMED_IMPORTS = new ElementTypeAsPsiFactory("NAMED_IMPORTS", JavaScriptLanguage.INSTANCE, ES6NamedImportsImpl::new); + IElementType NAMED_IMPORTS = + new ElementTypeAsPsiFactory("NAMED_IMPORTS", JavaScriptLanguage.INSTANCE, ES6NamedImportsImpl::new); - IElementType IMPORT_SPECIFIER = new ElementTypeAsPsiFactory("IMPORT_SPECIFIER", JavaScriptLanguage.INSTANCE, ES6ImportSpecifierImpl::new); + IElementType IMPORT_SPECIFIER = + new ElementTypeAsPsiFactory("IMPORT_SPECIFIER", JavaScriptLanguage.INSTANCE, ES6ImportSpecifierImpl::new); } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/resolve/EcmaScript6ResolveHelper.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/resolve/EcmaScript6ResolveHelper.java index e3a22089..1c29d353 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/resolve/EcmaScript6ResolveHelper.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/ecmascript/psi/impl/resolve/EcmaScript6ResolveHelper.java @@ -15,85 +15,77 @@ import consulo.language.psi.resolve.ResolveState; import consulo.language.psi.util.PsiTreeUtil; import consulo.util.lang.Comparing; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; /** * @author VISTALL * @since 2019-12-14 */ -public class EcmaScript6ResolveHelper extends ResolveHelper -{ - public static final ResolveHelper INSTANCE = new EcmaScript6ResolveHelper(); +public class EcmaScript6ResolveHelper extends ResolveHelper { + public static final ResolveHelper INSTANCE = new EcmaScript6ResolveHelper(); - private static class ImportProcessor extends BaseScopeProcessor - { - private final String myReferencedName; - private JSImportedElementResolveResult myResult; + private static class ImportProcessor extends BaseScopeProcessor { + private final String myReferencedName; + private JSImportedElementResolveResult myResult; - public ImportProcessor(String referencedName) - { - myReferencedName = referencedName; - } + public ImportProcessor(String referencedName) { + myReferencedName = referencedName; + } - @Override - public boolean execute(@Nonnull PsiElement psiElement, ResolveState resolveState) - { - if(psiElement instanceof ES6ImportedBinding && myReferencedName.equals(((ES6ImportedBinding) psiElement).getName())) - { - myResult = new JSImportedElementResolveResult(myReferencedName, psiElement, PsiTreeUtil.getParentOfType(psiElement, ES6ImportDeclaration.class)); - return false; - } - return true; - } - } + @Override + public boolean execute(@Nonnull PsiElement psiElement, ResolveState resolveState) { + if (psiElement instanceof ES6ImportedBinding es6ImportedBinding && myReferencedName.equals(es6ImportedBinding.getName())) { + myResult = new JSImportedElementResolveResult( + myReferencedName, + psiElement, + PsiTreeUtil.getParentOfType(psiElement, ES6ImportDeclaration.class) + ); + return false; + } + return true; + } + } - @Nullable - @Override - public JSImportedElementResolveResult resolveTypeNameUsingImports(@Nonnull String referencedName, PsiNamedElement parent) - { - ImportProcessor processor = new ImportProcessor(referencedName); + @Nullable + @Override + public JSImportedElementResolveResult resolveTypeNameUsingImports(@Nonnull String referencedName, PsiNamedElement parent) { + ImportProcessor processor = new ImportProcessor(referencedName); - PsiFile containingFile = parent.getContainingFile(); - if(containingFile instanceof JSFile) - { - ES6ImportDeclaration[] childrenOfType = PsiTreeUtil.getChildrenOfType(containingFile, ES6ImportDeclaration.class); - if(childrenOfType == null) - { - return null; - } + PsiFile containingFile = parent.getContainingFile(); + if (containingFile instanceof JSFile) { + ES6ImportDeclaration[] childrenOfType = PsiTreeUtil.getChildrenOfType(containingFile, ES6ImportDeclaration.class); + if (childrenOfType == null) { + return null; + } - for(ES6ImportDeclaration declaration : childrenOfType) - { - if(!declaration.processDeclarations(processor, ResolveState.initial(), declaration, parent)) - { - break; - } - } - } + for (ES6ImportDeclaration declaration : childrenOfType) { + if (!declaration.processDeclarations(processor, ResolveState.initial(), declaration, parent)) { + break; + } + } + } - return processor.myResult; - } + return processor.myResult; + } - @Override - public boolean execute(ResolveProcessor resolveProcessor, PsiElement element, ResolveState state) - { - if(element instanceof ES6ImportedBinding && Comparing.equal(((ES6ImportedBinding) element).getName(), resolveProcessor.getName())) - { - return true; - } - return false; - } + @Override + public boolean execute(ResolveProcessor resolveProcessor, PsiElement element, ResolveState state) { + if (element instanceof ES6ImportedBinding es6ImportedBinding + && Comparing.equal(es6ImportedBinding.getName(), resolveProcessor.getName())) { + return true; + } + return false; + } - @RequiredReadAction - @Override - public boolean isResolveTo(JSReferenceExpressionImpl expression, PsiElement element) - { - if(element instanceof ES6ImportedBinding && Comparing.equal(expression.getReferencedName(), ((ES6ImportedBinding) element).getName())) - { - return true; - } - return super.isResolveTo(expression, element); - } + @RequiredReadAction + @Override + public boolean isResolveTo(JSReferenceExpressionImpl expression, PsiElement element) { + if (element instanceof ES6ImportedBinding es6ImportedBinding + && Comparing.equal(expression.getReferencedName(), es6ImportedBinding.getName())) { + return true; + } + return super.isResolveTo(expression, element); + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/codeInsight/JSXTagTreeHighlightingPassFactory.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/codeInsight/JSXTagTreeHighlightingPassFactory.java index 0e32bf7e..e966e3e4 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/codeInsight/JSXTagTreeHighlightingPassFactory.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/codeInsight/JSXTagTreeHighlightingPassFactory.java @@ -5,41 +5,31 @@ import consulo.codeEditor.EditorEx; import consulo.javascript.jsx.language.JSXJavaScriptVersion; import consulo.language.editor.Pass; -import consulo.language.editor.impl.highlight.TextEditorHighlightingPass; -import consulo.language.editor.impl.highlight.TextEditorHighlightingPassFactory; +import consulo.language.editor.highlight.TextEditorHighlightingPass; +import consulo.language.editor.highlight.TextEditorHighlightingPassFactory; import consulo.language.psi.PsiFile; import consulo.xml.codeInsight.daemon.impl.tagTreeHighlighting.XmlTagTreeHighlightingPass; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 2019-12-15 */ @ExtensionImpl -public class JSXTagTreeHighlightingPassFactory implements TextEditorHighlightingPassFactory -{ - @Override - public void register(@Nonnull Registrar registrar) - { - registrar.registerTextEditorHighlightingPass(this, new int[]{Pass.UPDATE_ALL}, null, false, -1); - } - - @Override - public TextEditorHighlightingPass createHighlightingPass(@Nonnull final PsiFile file, @Nonnull final Editor editor) - { - if(editor.isOneLineMode()) - { - return null; - } - - if(!(editor instanceof EditorEx) || !(file.getLanguageVersion() instanceof JSXJavaScriptVersion)) - { - return null; - } - - return new XmlTagTreeHighlightingPass(file, (EditorEx) editor); - } +public class JSXTagTreeHighlightingPassFactory implements TextEditorHighlightingPassFactory { + @Override + public void register(@Nonnull Registrar registrar) { + registrar.registerTextEditorHighlightingPass(this, new int[]{Pass.UPDATE_ALL}, null, false, -1); + } + + @Override + public TextEditorHighlightingPass createHighlightingPass(@Nonnull PsiFile file, @Nonnull Editor editor) { + if (editor.isOneLineMode() || !(editor instanceof EditorEx) || !(file.getLanguageVersion() instanceof JSXJavaScriptVersion)) { + return null; + } + + return new XmlTagTreeHighlightingPass(file, (EditorEx)editor); + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/fileTemplate/JSXCreateFromTemplateHandler.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/fileTemplate/JSXCreateFromTemplateHandler.java index ddbde5cb..d1b90062 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/fileTemplate/JSXCreateFromTemplateHandler.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/fileTemplate/JSXCreateFromTemplateHandler.java @@ -5,30 +5,25 @@ import consulo.fileTemplate.CreateFromTemplateHandler; import consulo.fileTemplate.FileTemplate; import consulo.javascript.jsx.language.JSXFileType; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 2019-12-17 */ @ExtensionImpl -public class JSXCreateFromTemplateHandler implements CreateFromTemplateHandler -{ - @Override - public boolean handlesTemplate(FileTemplate template) - { - return template.getExtension().equals(JavaScriptFileType.INSTANCE.getDefaultExtension()); - } +public class JSXCreateFromTemplateHandler implements CreateFromTemplateHandler { + @Override + public boolean handlesTemplate(FileTemplate template) { + return template.getExtension().equals(JavaScriptFileType.INSTANCE.getDefaultExtension()); + } - @Nonnull - @Override - public String checkAppendExtension(String fileName, FileTemplate template) - { - if(fileName.endsWith("." + JSXFileType.INSTANCE.getDefaultExtension())) - { - return fileName; - } - return CreateFromTemplateHandler.super.checkAppendExtension(fileName, template); - } + @Nonnull + @Override + public String checkAppendExtension(String fileName, FileTemplate template) { + if (fileName.endsWith("." + JSXFileType.INSTANCE.getDefaultExtension())) { + return fileName; + } + return CreateFromTemplateHandler.super.checkAppendExtension(fileName, template); + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/language/JSXFileType.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/language/JSXFileType.java index 8215ed78..eea40447 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/language/JSXFileType.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/language/JSXFileType.java @@ -11,55 +11,48 @@ import consulo.ui.image.Image; import consulo.virtualFileSystem.VirtualFile; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL * @since 2019-12-16 */ -public class JSXFileType extends LanguageFileType implements JavaScriptFileTypeWithVersion -{ - public static final JSXFileType INSTANCE = new JSXFileType(); - - private JSXFileType() - { - super(JavaScriptLanguage.INSTANCE); - } - - @Nonnull - @Override - public String getId() - { - return "JSX"; - } - - @Nonnull - @Override - public LocalizeValue getDescription() - { - return LocalizeValue.localizeTODO("JSX files"); - } - - @Nonnull - @Override - public String getDefaultExtension() - { - return "jsx"; - } - - @Nullable - @Override - public Image getIcon() - { - return JavaScriptIconGroup.jsx(); - } - - @RequiredReadAction - @Nonnull - @Override - public LanguageVersion getLanguageVersion(@Nullable Module module, @Nullable VirtualFile virtualFile) - { - return JSXJavaScriptVersion.getInstance(); - } +public class JSXFileType extends LanguageFileType implements JavaScriptFileTypeWithVersion { + public static final JSXFileType INSTANCE = new JSXFileType(); + + private JSXFileType() { + super(JavaScriptLanguage.INSTANCE); + } + + @Nonnull + @Override + public String getId() { + return "JSX"; + } + + @Nonnull + @Override + public LocalizeValue getDescription() { + return LocalizeValue.localizeTODO("JSX files"); + } + + @Nonnull + @Override + public String getDefaultExtension() { + return "jsx"; + } + + @Nullable + @Override + public Image getIcon() { + return JavaScriptIconGroup.jsx(); + } + + @RequiredReadAction + @Nonnull + @Override + public LanguageVersion getLanguageVersion(@Nullable Module module, @Nullable VirtualFile virtualFile) { + return JSXJavaScriptVersion.getInstance(); + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/language/JSXFileTypeFactory.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/language/JSXFileTypeFactory.java index 68170888..3db5b739 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/language/JSXFileTypeFactory.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/language/JSXFileTypeFactory.java @@ -4,18 +4,16 @@ import consulo.virtualFileSystem.fileType.FileTypeConsumer; import consulo.virtualFileSystem.fileType.FileTypeFactory; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 2019-12-16 */ @ExtensionImpl -public class JSXFileTypeFactory extends FileTypeFactory -{ - @Override - public void createFileTypes(@Nonnull FileTypeConsumer fileTypeConsumer) - { - fileTypeConsumer.consume(JSXFileType.INSTANCE); - } +public class JSXFileTypeFactory extends FileTypeFactory { + @Override + public void createFileTypes(@Nonnull FileTypeConsumer fileTypeConsumer) { + fileTypeConsumer.consume(JSXFileType.INSTANCE); + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/language/JSXJavaScriptVersion.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/language/JSXJavaScriptVersion.java index 3db5f974..ffd168ab 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/language/JSXJavaScriptVersion.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/language/JSXJavaScriptVersion.java @@ -3,37 +3,31 @@ import consulo.annotation.component.ExtensionImpl; import consulo.javascript.ecmascript.lang.EcmaScript6JavaScriptVersion; import consulo.javascript.language.JavaScriptLanguage; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 2019-12-16 */ @ExtensionImpl -public class JSXJavaScriptVersion extends EcmaScript6JavaScriptVersion -{ - @Nonnull - public static EcmaScript6JavaScriptVersion getInstance() - { - return JavaScriptLanguage.INSTANCE.findVersionByClass(JSXJavaScriptVersion.class); - } +public class JSXJavaScriptVersion extends EcmaScript6JavaScriptVersion { + @Nonnull + public static EcmaScript6JavaScriptVersion getInstance() { + return JavaScriptLanguage.INSTANCE.findVersionByClass(JSXJavaScriptVersion.class); + } - public JSXJavaScriptVersion() - { - super("JSX"); - } + public JSXJavaScriptVersion() { + super("JSX"); + } - @Override - public int getWeight() - { - return 60; - } + @Override + public int getWeight() { + return 60; + } - @Nonnull - @Override - public String getPresentableName() - { - return "JSX"; - } + @Nonnull + @Override + public String getPresentableName() { + return "JSX"; + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/language/psi/impl/JSXmlTagReference.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/language/psi/impl/JSXmlTagReference.java index b95b6769..0cb87032 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/language/psi/impl/JSXmlTagReference.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/language/psi/impl/JSXmlTagReference.java @@ -3,34 +3,30 @@ import consulo.annotation.access.RequiredReadAction; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiReferenceBase; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; /** * @author VISTALL * @since 2019-12-17 */ -public class JSXmlTagReference extends PsiReferenceBase -{ - public JSXmlTagReference(@Nonnull PsiElement element) - { - super(element); - } +public class JSXmlTagReference extends PsiReferenceBase { + public JSXmlTagReference(@Nonnull PsiElement element) { + super(element); + } - @RequiredReadAction - @Nullable - @Override - public PsiElement resolve() - { - return null; - } + @RequiredReadAction + @Nullable + @Override + public PsiElement resolve() { + return null; + } - @RequiredReadAction - @Nonnull - @Override - public Object[] getVariants() - { - return new Object[0]; - } + @RequiredReadAction + @Nonnull + @Override + public Object[] getVariants() { + return new Object[0]; + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/language/psi/impl/JSXmlTagReferenceContributor.java b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/language/psi/impl/JSXmlTagReferenceContributor.java index ce6fabb9..7b441d58 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/language/psi/impl/JSXmlTagReferenceContributor.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/consulo/javascript/jsx/language/psi/impl/JSXmlTagReferenceContributor.java @@ -8,40 +8,35 @@ import consulo.language.psi.*; import consulo.language.util.ProcessingContext; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 2019-12-17 */ @ExtensionImpl -public class JSXmlTagReferenceContributor extends PsiReferenceContributor -{ - @Override - public void registerReferenceProviders(PsiReferenceRegistrar registrar) - { - registrar.registerReferenceProvider(StandardPatterns.psiElement(JSXmlLiteralExpressionImpl.class), new PsiReferenceProvider() - { - @Nonnull - @Override - public PsiReference[] getReferencesByElement(@Nonnull PsiElement psiElement, @Nonnull ProcessingContext processingContext) - { - return PsiReference.EMPTY_ARRAY; - // TODO +public class JSXmlTagReferenceContributor extends PsiReferenceContributor { + @Override + public void registerReferenceProviders(PsiReferenceRegistrar registrar) { + registrar.registerReferenceProvider(StandardPatterns.psiElement(JSXmlLiteralExpressionImpl.class), new PsiReferenceProvider() { + @Nonnull + @Override + public PsiReference[] getReferencesByElement(@Nonnull PsiElement psiElement, @Nonnull ProcessingContext processingContext) { + return PsiReference.EMPTY_ARRAY; + // TODO // ASTNode[] children = psiElement.getNode().getChildren(TokenSet.create(JSTokenTypes.XML_NAME)); // if(children.length == 0) // { // return PsiReference.EMPTY_ARRAY; // } // return Arrays.stream(children).map(node -> new JSXmlTagReference(node.getPsi())).toArray(PsiReference[]::new); - } - }); - } + } + }); + } - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } } diff --git a/lang-version-impl/ecmascript-impl/src/main/java/module-info.java b/lang-version-impl/ecmascript-impl/src/main/java/module-info.java index 938bdbfb..eeda9ade 100644 --- a/lang-version-impl/ecmascript-impl/src/main/java/module-info.java +++ b/lang-version-impl/ecmascript-impl/src/main/java/module-info.java @@ -2,23 +2,22 @@ * @author VISTALL * @since 23-Aug-22 */ -module consulo.javascript.ecmascript.impl -{ - requires transitive consulo.javascript.base.impl; +module consulo.javascript.ecmascript.impl { + requires transitive consulo.javascript.base.impl; - requires consulo.language.editor.impl; + requires consulo.language.editor.impl; - requires com.intellij.xml; + requires com.intellij.xml; - exports consulo.javascript.ecmascript.codeInsight; - exports consulo.javascript.ecmascript.codeInsight.quickFixes; - exports consulo.javascript.ecmascript.completion; - exports consulo.javascript.ecmascript.lang; - exports consulo.javascript.ecmascript.lang.parsing; - exports consulo.javascript.ecmascript.psi; - exports consulo.javascript.ecmascript.psi.impl; - exports consulo.javascript.ecmascript.psi.impl.resolve; - exports consulo.javascript.jsx.fileTemplate; - exports consulo.javascript.jsx.language; - exports consulo.javascript.jsx.language.psi.impl; + exports consulo.javascript.ecmascript.codeInsight; + exports consulo.javascript.ecmascript.codeInsight.quickFixes; + exports consulo.javascript.ecmascript.completion; + exports consulo.javascript.ecmascript.lang; + exports consulo.javascript.ecmascript.lang.parsing; + exports consulo.javascript.ecmascript.psi; + exports consulo.javascript.ecmascript.psi.impl; + exports consulo.javascript.ecmascript.psi.impl.resolve; + exports consulo.javascript.jsx.fileTemplate; + exports consulo.javascript.jsx.language; + exports consulo.javascript.jsx.language.psi.impl; } \ No newline at end of file diff --git a/lang-version-impl/ecmascript4-impl/pom.xml b/lang-version-impl/ecmascript4-impl/pom.xml index 85c15b93..29438c5b 100644 --- a/lang-version-impl/ecmascript4-impl/pom.xml +++ b/lang-version-impl/ecmascript4-impl/pom.xml @@ -33,7 +33,7 @@ consulo - https://maven.consulo.io/repository/snapshots/ + https://maven.consulo.dev/repository/snapshots/ true interval:60 diff --git a/lang-version-impl/ecmascript4-impl/src/main/java/consulo/javascript/ecmascript4/lang/EcmaScript4JavaScriptVersion.java b/lang-version-impl/ecmascript4-impl/src/main/java/consulo/javascript/ecmascript4/lang/EcmaScript4JavaScriptVersion.java index 169b05df..b08e4b56 100644 --- a/lang-version-impl/ecmascript4-impl/src/main/java/consulo/javascript/ecmascript4/lang/EcmaScript4JavaScriptVersion.java +++ b/lang-version-impl/ecmascript4-impl/src/main/java/consulo/javascript/ecmascript4/lang/EcmaScript4JavaScriptVersion.java @@ -10,8 +10,7 @@ import consulo.javascript.language.JavaScriptFeature; import consulo.language.lexer.Lexer; import consulo.language.parser.PsiParser; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL @@ -20,34 +19,29 @@ @Deprecated @DeprecationInfo("This language version was dropped. We keep it only for history, many options may not supported") @ExtensionImpl -public class EcmaScript4JavaScriptVersion extends BaseJavaScriptLanguageVersion -{ - private final DialectOptionHolder myDialectOptionHolder = new DialectOptionHolder(true, false); +public class EcmaScript4JavaScriptVersion extends BaseJavaScriptLanguageVersion { + private final DialectOptionHolder myDialectOptionHolder = new DialectOptionHolder(true, false); - public EcmaScript4JavaScriptVersion() - { - super("ECMA4"); - addFeature(JavaScriptFeature.CLASS); - } + public EcmaScript4JavaScriptVersion() { + super("ECMA4"); + addFeature(JavaScriptFeature.CLASS); + } - @Nonnull - @Override - public PsiParser createParser() - { - return new EcmaScript4Parser(); - } + @Nonnull + @Override + public PsiParser createParser() { + return new EcmaScript4Parser(); + } - @Nonnull - @Override - public JSHighlighter getSyntaxHighlighter() - { - return new JSHighlighter(myDialectOptionHolder); - } + @Nonnull + @Override + public JSHighlighter getSyntaxHighlighter() { + return new JSHighlighter(myDialectOptionHolder); + } - @Nonnull - @Override - public Lexer createLexer() - { - return new JavaScriptParsingFlexLexer(myDialectOptionHolder); - } + @Nonnull + @Override + public Lexer createLexer() { + return new JavaScriptParsingFlexLexer(myDialectOptionHolder); + } } diff --git a/lang-version-impl/ecmascript4-impl/src/main/java/consulo/javascript/ecmascript4/lang/parsing/EcmaScript4ExpressionParsing.java b/lang-version-impl/ecmascript4-impl/src/main/java/consulo/javascript/ecmascript4/lang/parsing/EcmaScript4ExpressionParsing.java index 3c39debb..48bcd749 100644 --- a/lang-version-impl/ecmascript4-impl/src/main/java/consulo/javascript/ecmascript4/lang/parsing/EcmaScript4ExpressionParsing.java +++ b/lang-version-impl/ecmascript4-impl/src/main/java/consulo/javascript/ecmascript4/lang/parsing/EcmaScript4ExpressionParsing.java @@ -4,7 +4,7 @@ import com.intellij.lang.javascript.JSTokenTypes; import consulo.javascript.lang.parsing.ExpressionParsing; import consulo.javascript.lang.parsing.JavaScriptParsingContext; -import consulo.javascript.language.JavaScriptBundle; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.ast.IElementType; import consulo.language.ast.TokenSet; import consulo.language.parser.PsiBuilder; @@ -13,199 +13,166 @@ * @author VISTALL * @since 24.08.14 */ -public class EcmaScript4ExpressionParsing extends ExpressionParsing -{ - public EcmaScript4ExpressionParsing(JavaScriptParsingContext context) - { - super(context); - } - - @Override - protected boolean parseMemberExpression(PsiBuilder builder, boolean allowCallSyntax) - { - PsiBuilder.Marker expr = builder.mark(); - boolean isNew; - - final IElementType type = builder.getTokenType(); - - if(type == JSTokenTypes.NEW_KEYWORD) - { - isNew = true; - final boolean isfunction = parseNewExpression(builder); - - if(isfunction) - { - expr.done(JSElementTypes.NEW_EXPRESSION); - if(builder.getTokenType() != JSTokenTypes.LPAR) - { - return true; - } - expr = expr.precede(); - isNew = false; - } - } - else - { - isNew = false; - if(!parsePrimaryExpression(builder)) - { - expr.drop(); - return false; - } - } - - boolean currentlyAllowCallSyntax = allowCallSyntax && (type != JSTokenTypes.LBRACE && type != JSTokenTypes.LBRACKET); - - while(true) - { - IElementType tokenType = builder.getTokenType(); - if(tokenType == JSTokenTypes.DOT || (tokenType == JSTokenTypes.COLON_COLON || tokenType == JSTokenTypes.DOT_DOT)) - { - currentlyAllowCallSyntax = allowCallSyntax; - builder.advanceLexer(); - - if(builder.getTokenType() == JSTokenTypes.AT) - { - builder.advanceLexer(); - } - - tokenType = builder.getTokenType(); - - if(tokenType == JSTokenTypes.LT) - { - parseGenericSignature(builder); - expr.done(JSElementTypes.REFERENCE_EXPRESSION); - expr = expr.precede(); - continue; - } - - if(tokenType == JSTokenTypes.LBRACKET || tokenType == JSTokenTypes.LPAR) - { - continue; - } - - if(tokenType == JSTokenTypes.ANY_IDENTIFIER || isIdentifierToken(builder, tokenType)) - { - builder.advanceLexer(); - } - else - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.name")); - } - - expr.done(JSElementTypes.REFERENCE_EXPRESSION); - expr = expr.precede(); - } - else if(tokenType == JSTokenTypes.LBRACKET) - { - builder.advanceLexer(); - parseExpression(builder); - checkMatches(builder, JSTokenTypes.RBRACKET, JavaScriptBundle.message("javascript.parser.message.expected.rbracket")); - expr.done(JSElementTypes.INDEXED_PROPERTY_ACCESS_EXPRESSION); - expr = expr.precede(); - } - else if(currentlyAllowCallSyntax && tokenType == JSTokenTypes.LPAR) - { - parseArgumentList(builder); - expr.done(isNew ? JSElementTypes.NEW_EXPRESSION : JSElementTypes.CALL_EXPRESSION); - expr = expr.precede(); - isNew = false; - } - else - { - if(isNew) - { - expr.done(JSElementTypes.NEW_EXPRESSION); - } - else - { - expr.drop(); - } - break; - } - } - - return true; - } - - @Override - public boolean parseQualifiedTypeName(PsiBuilder builder, boolean allowStar, TokenSet separatorsSet) - { - if(!JSTokenTypes.IDENTIFIER_TOKENS_SET.contains(builder.getTokenType())) - { - return false; - } - PsiBuilder.Marker expr = builder.mark(); - buildTokenElement(JSElementTypes.REFERENCE_EXPRESSION, builder); - boolean hasGenerics = false; - - while(separatorsSet.contains(builder.getTokenType())) - { - boolean stop = false; - builder.advanceLexer(); - - final IElementType tokenType = builder.getTokenType(); - if(tokenType == JSTokenTypes.ANY_IDENTIFIER && allowStar) - { - builder.advanceLexer(); - stop = true; - } - else if(tokenType == JSTokenTypes.LT) - { - parseGenericSignature(builder); - stop = true; - hasGenerics = true; - } - else if(tokenType == JSTokenTypes.DEFAULT_KEYWORD || (tokenType != JSTokenTypes.IDENTIFIER && JSTokenTypes.IDENTIFIER_TOKENS_SET - .contains(tokenType))) - { - builder.advanceLexer(); // TODO: allow any keyword - } - else - { - checkMatches(builder, JSTokenTypes.IDENTIFIER, JavaScriptBundle.message("javascript.parser.message.expected.name")); - } - expr.done(JSElementTypes.REFERENCE_EXPRESSION); - expr = expr.precede(); - - if(stop) - { - break; - } - } - - if(!hasGenerics && builder.getTokenType() == JSTokenTypes.LT) - { - parseGenericSignature(builder); - expr.done(JSElementTypes.REFERENCE_EXPRESSION); - } - else - { - expr.drop(); - } - return true; - } - - @Override - public boolean tryParseType(final PsiBuilder builder) - { - if(builder.getTokenType() == JSTokenTypes.COLON) - { - builder.advanceLexer(); - - return parseType(builder); - } - - return false; - } - - private void parseGenericSignature(final PsiBuilder builder) - { - assert builder.getTokenType() == JSTokenTypes.LT; - PsiBuilder.Marker genericTypeSignature = builder.mark(); - builder.advanceLexer(); - parseType(builder); - checkMatches(builder, JSTokenTypes.GT, JavaScriptBundle.message("javascript.parser.message.expected.lt")); - genericTypeSignature.done(JSElementTypes.GENERIC_SIGNATURE); - } +public class EcmaScript4ExpressionParsing extends ExpressionParsing { + public EcmaScript4ExpressionParsing(JavaScriptParsingContext context) { + super(context); + } + + @Override + protected boolean parseMemberExpression(PsiBuilder builder, boolean allowCallSyntax) { + PsiBuilder.Marker expr = builder.mark(); + boolean isNew; + + IElementType type = builder.getTokenType(); + + if (type == JSTokenTypes.NEW_KEYWORD) { + isNew = true; + boolean isfunction = parseNewExpression(builder); + + if (isfunction) { + expr.done(JSElementTypes.NEW_EXPRESSION); + if (builder.getTokenType() != JSTokenTypes.LPAR) { + return true; + } + expr = expr.precede(); + isNew = false; + } + } + else { + isNew = false; + if (!parsePrimaryExpression(builder)) { + expr.drop(); + return false; + } + } + + boolean currentlyAllowCallSyntax = allowCallSyntax && (type != JSTokenTypes.LBRACE && type != JSTokenTypes.LBRACKET); + + while (true) { + IElementType tokenType = builder.getTokenType(); + if (tokenType == JSTokenTypes.DOT || (tokenType == JSTokenTypes.COLON_COLON || tokenType == JSTokenTypes.DOT_DOT)) { + currentlyAllowCallSyntax = allowCallSyntax; + builder.advanceLexer(); + + if (builder.getTokenType() == JSTokenTypes.AT) { + builder.advanceLexer(); + } + + tokenType = builder.getTokenType(); + + if (tokenType == JSTokenTypes.LT) { + parseGenericSignature(builder); + expr.done(JSElementTypes.REFERENCE_EXPRESSION); + expr = expr.precede(); + continue; + } + + if (tokenType == JSTokenTypes.LBRACKET || tokenType == JSTokenTypes.LPAR) { + continue; + } + + if (tokenType == JSTokenTypes.ANY_IDENTIFIER || isIdentifierToken(builder, tokenType)) { + builder.advanceLexer(); + } + else { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedName()); + } + + expr.done(JSElementTypes.REFERENCE_EXPRESSION); + expr = expr.precede(); + } + else if (tokenType == JSTokenTypes.LBRACKET) { + builder.advanceLexer(); + parseExpression(builder); + checkMatches(builder, JSTokenTypes.RBRACKET, JavaScriptLocalize.javascriptParserMessageExpectedRbracket()); + expr.done(JSElementTypes.INDEXED_PROPERTY_ACCESS_EXPRESSION); + expr = expr.precede(); + } + else if (currentlyAllowCallSyntax && tokenType == JSTokenTypes.LPAR) { + parseArgumentList(builder); + expr.done(isNew ? JSElementTypes.NEW_EXPRESSION : JSElementTypes.CALL_EXPRESSION); + expr = expr.precede(); + isNew = false; + } + else { + if (isNew) { + expr.done(JSElementTypes.NEW_EXPRESSION); + } + else { + expr.drop(); + } + break; + } + } + + return true; + } + + @Override + public boolean parseQualifiedTypeName(PsiBuilder builder, boolean allowStar, TokenSet separatorsSet) { + if (!JSTokenTypes.IDENTIFIER_TOKENS_SET.contains(builder.getTokenType())) { + return false; + } + PsiBuilder.Marker expr = builder.mark(); + buildTokenElement(JSElementTypes.REFERENCE_EXPRESSION, builder); + boolean hasGenerics = false; + + while (separatorsSet.contains(builder.getTokenType())) { + boolean stop = false; + builder.advanceLexer(); + + IElementType tokenType = builder.getTokenType(); + if (tokenType == JSTokenTypes.ANY_IDENTIFIER && allowStar) { + builder.advanceLexer(); + stop = true; + } + else if (tokenType == JSTokenTypes.LT) { + parseGenericSignature(builder); + stop = true; + hasGenerics = true; + } + else if (tokenType == JSTokenTypes.DEFAULT_KEYWORD + || (tokenType != JSTokenTypes.IDENTIFIER && JSTokenTypes.IDENTIFIER_TOKENS_SET.contains(tokenType))) { + builder.advanceLexer(); // TODO: allow any keyword + } + else { + checkMatches(builder, JSTokenTypes.IDENTIFIER, JavaScriptLocalize.javascriptParserMessageExpectedName()); + } + expr.done(JSElementTypes.REFERENCE_EXPRESSION); + expr = expr.precede(); + + if (stop) { + break; + } + } + + if (!hasGenerics && builder.getTokenType() == JSTokenTypes.LT) { + parseGenericSignature(builder); + expr.done(JSElementTypes.REFERENCE_EXPRESSION); + } + else { + expr.drop(); + } + return true; + } + + @Override + public boolean tryParseType(PsiBuilder builder) { + if (builder.getTokenType() == JSTokenTypes.COLON) { + builder.advanceLexer(); + + return parseType(builder); + } + + return false; + } + + private void parseGenericSignature(PsiBuilder builder) { + assert builder.getTokenType() == JSTokenTypes.LT; + PsiBuilder.Marker genericTypeSignature = builder.mark(); + builder.advanceLexer(); + parseType(builder); + checkMatches(builder, JSTokenTypes.GT, JavaScriptLocalize.javascriptParserMessageExpectedLt()); + genericTypeSignature.done(JSElementTypes.GENERIC_SIGNATURE); + } } diff --git a/lang-version-impl/ecmascript4-impl/src/main/java/consulo/javascript/ecmascript4/lang/parsing/EcmaScript4FunctionParsing.java b/lang-version-impl/ecmascript4-impl/src/main/java/consulo/javascript/ecmascript4/lang/parsing/EcmaScript4FunctionParsing.java index 623801eb..04a53b46 100644 --- a/lang-version-impl/ecmascript4-impl/src/main/java/consulo/javascript/ecmascript4/lang/parsing/EcmaScript4FunctionParsing.java +++ b/lang-version-impl/ecmascript4-impl/src/main/java/consulo/javascript/ecmascript4/lang/parsing/EcmaScript4FunctionParsing.java @@ -4,7 +4,7 @@ import com.intellij.lang.javascript.JSTokenTypes; import consulo.javascript.lang.parsing.FunctionParsing; import consulo.javascript.lang.parsing.JavaScriptParsingContext; -import consulo.javascript.language.JavaScriptBundle; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.ast.IElementType; import consulo.language.parser.PsiBuilder; @@ -12,181 +12,153 @@ * @author VISTALL * @since 24.08.14 */ -public class EcmaScript4FunctionParsing extends FunctionParsing -{ - public EcmaScript4FunctionParsing(JavaScriptParsingContext context) - { - super(context); - } - - public void parseAttributeWithoutBrackets(final PsiBuilder builder) - { - final PsiBuilder.Marker attribute = builder.mark(); - if(!checkMatches(builder, JSTokenTypes.IDENTIFIER, JavaScriptBundle.message("javascript.parser.message.expected.identifier"))) - { - attribute.drop(); - return; - } - parseAttributeBody(builder); - attribute.done(JSElementTypes.ATTRIBUTE); - } - - void parseAttributesList(final PsiBuilder builder) - { - final PsiBuilder.Marker modifierList = builder.mark(); - - boolean seenNs = false; - boolean seenAnyAttributes = false; - - try - { - boolean hasSomethingInAttrList = true; - - while(hasSomethingInAttrList) - { - hasSomethingInAttrList = false; - - while(builder.getTokenType() == JSTokenTypes.LBRACKET) - { - seenAnyAttributes = true; - PsiBuilder.Marker attribute = builder.mark(); - - builder.advanceLexer(); - - if(builder.eof() || (!checkMatches(builder, JSTokenTypes.IDENTIFIER, JavaScriptBundle.message("javascript.parser.message.expected.identifier")) && - builder.getTokenType() != JSTokenTypes.RBRACKET)) - { - attribute.drop(); - return; - } - - while(builder.getTokenType() != JSTokenTypes.RBRACKET) - { - parseAttributeBody(builder); - - if(builder.eof()) - { - attribute.done(JSElementTypes.ATTRIBUTE); - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.rbracket")); - return; - } - } - - builder.advanceLexer(); - attribute.done(JSElementTypes.ATTRIBUTE); - hasSomethingInAttrList = true; - } - - if(builder.getTokenType() == JSTokenTypes.INCLUDE_KEYWORD) - { - hasSomethingInAttrList = true; - getStatementParsing().parseIncludeDirective(builder); - } - - if(builder.getTokenType() == JSTokenTypes.IDENTIFIER && !seenNs) - { - hasSomethingInAttrList = true; - seenNs = true; - PsiBuilder.Marker marker = builder.mark(); - builder.advanceLexer(); - marker.done(JSElementTypes.REFERENCE_EXPRESSION); - } - - while(JSTokenTypes.MODIFIERS.contains(builder.getTokenType())) - { - seenAnyAttributes = true; - hasSomethingInAttrList = true; - builder.advanceLexer(); - } - - if(builder.eof()) - { - return; - } - } - } - finally - { - final IElementType currentTokenType = builder.getTokenType(); - - if(seenNs && - !seenAnyAttributes && - (currentTokenType != JSTokenTypes.VAR_KEYWORD && - currentTokenType != JSTokenTypes.FUNCTION_KEYWORD && - currentTokenType != JSTokenTypes.CLASS_KEYWORD && - currentTokenType != JSTokenTypes.INTERFACE_KEYWORD)) - { - modifierList.drop(); - } - else - { - modifierList.done(JSElementTypes.ATTRIBUTE_LIST); - } - } - } - - private void parseAttributeBody(final PsiBuilder builder) - { - final boolean haveLParen = checkMatches(builder, JSTokenTypes.LPAR, JavaScriptBundle.message("javascript.parser.message.expected.lparen")); - boolean hasName; - - while(haveLParen) - { - PsiBuilder.Marker attributeNameValuePair; - hasName = builder.getTokenType() == JSTokenTypes.IDENTIFIER; - - if(builder.getTokenType() == JSTokenTypes.COMMA) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.identifer.or.value")); - break; - } - if(builder.getTokenType() == JSTokenTypes.RBRACKET) - { - break; - } - - attributeNameValuePair = builder.mark(); - builder.advanceLexer(); - - if(hasName && builder.getTokenType() != JSTokenTypes.COMMA && builder.getTokenType() != JSTokenTypes.RPAR) - { - checkMatches(builder, JSTokenTypes.EQ, JavaScriptBundle.message("javascript.parser.message.expected.equal")); - - if(builder.getTokenType() != JSTokenTypes.COMMA && builder.getTokenType() != JSTokenTypes.RBRACKET && builder.getTokenType() != - JSTokenTypes.RPAR) - { - builder.advanceLexer(); - } - else - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.value")); - } - } - - if(attributeNameValuePair != null) - { - attributeNameValuePair.done(JSElementTypes.ATTRIBUTE_NAME_VALUE_PAIR); - } - if(builder.getTokenType() != JSTokenTypes.COMMA) - { - break; - } - builder.advanceLexer(); - - if(builder.eof()) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.rparen")); - return; - } - } - - if(haveLParen) - { - checkMatches(builder, JSTokenTypes.RPAR, JavaScriptBundle.message("javascript.parser.message.expected.rparen")); - } - else - { - builder.advanceLexer(); - } - } +public class EcmaScript4FunctionParsing extends FunctionParsing { + public EcmaScript4FunctionParsing(JavaScriptParsingContext context) { + super(context); + } + + public void parseAttributeWithoutBrackets(PsiBuilder builder) { + PsiBuilder.Marker attribute = builder.mark(); + if (!checkMatches(builder, JSTokenTypes.IDENTIFIER, JavaScriptLocalize.javascriptParserMessageExpectedIdentifier())) { + attribute.drop(); + return; + } + parseAttributeBody(builder); + attribute.done(JSElementTypes.ATTRIBUTE); + } + + void parseAttributesList(PsiBuilder builder) { + PsiBuilder.Marker modifierList = builder.mark(); + + boolean seenNs = false; + boolean seenAnyAttributes = false; + + try { + boolean hasSomethingInAttrList = true; + + while (hasSomethingInAttrList) { + hasSomethingInAttrList = false; + + while (builder.getTokenType() == JSTokenTypes.LBRACKET) { + seenAnyAttributes = true; + PsiBuilder.Marker attribute = builder.mark(); + + builder.advanceLexer(); + + if (builder.eof() || ( + !checkMatches(builder, JSTokenTypes.IDENTIFIER, JavaScriptLocalize.javascriptParserMessageExpectedIdentifier()) + && builder.getTokenType() != JSTokenTypes.RBRACKET + )) { + attribute.drop(); + return; + } + + while (builder.getTokenType() != JSTokenTypes.RBRACKET) { + parseAttributeBody(builder); + + if (builder.eof()) { + attribute.done(JSElementTypes.ATTRIBUTE); + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedRbracket()); + return; + } + } + + builder.advanceLexer(); + attribute.done(JSElementTypes.ATTRIBUTE); + hasSomethingInAttrList = true; + } + + if (builder.getTokenType() == JSTokenTypes.INCLUDE_KEYWORD) { + hasSomethingInAttrList = true; + getStatementParsing().parseIncludeDirective(builder); + } + + if (builder.getTokenType() == JSTokenTypes.IDENTIFIER && !seenNs) { + hasSomethingInAttrList = true; + seenNs = true; + PsiBuilder.Marker marker = builder.mark(); + builder.advanceLexer(); + marker.done(JSElementTypes.REFERENCE_EXPRESSION); + } + + while (JSTokenTypes.MODIFIERS.contains(builder.getTokenType())) { + seenAnyAttributes = true; + hasSomethingInAttrList = true; + builder.advanceLexer(); + } + + if (builder.eof()) { + return; + } + } + } + finally { + IElementType currentTokenType = builder.getTokenType(); + + if (seenNs && !seenAnyAttributes + && currentTokenType != JSTokenTypes.VAR_KEYWORD + && currentTokenType != JSTokenTypes.FUNCTION_KEYWORD + && currentTokenType != JSTokenTypes.CLASS_KEYWORD + && currentTokenType != JSTokenTypes.INTERFACE_KEYWORD) { + modifierList.drop(); + } + else { + modifierList.done(JSElementTypes.ATTRIBUTE_LIST); + } + } + } + + private void parseAttributeBody(PsiBuilder builder) { + boolean haveLParen = checkMatches(builder, JSTokenTypes.LPAR, JavaScriptLocalize.javascriptParserMessageExpectedLparen()); + boolean hasName; + + while (haveLParen) { + PsiBuilder.Marker attributeNameValuePair; + hasName = builder.getTokenType() == JSTokenTypes.IDENTIFIER; + + if (builder.getTokenType() == JSTokenTypes.COMMA) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedIdentiferOrValue()); + break; + } + if (builder.getTokenType() == JSTokenTypes.RBRACKET) { + break; + } + + attributeNameValuePair = builder.mark(); + builder.advanceLexer(); + + if (hasName && builder.getTokenType() != JSTokenTypes.COMMA && builder.getTokenType() != JSTokenTypes.RPAR) { + checkMatches(builder, JSTokenTypes.EQ, JavaScriptLocalize.javascriptParserMessageExpectedEqual()); + + if (builder.getTokenType() != JSTokenTypes.COMMA + && builder.getTokenType() != JSTokenTypes.RBRACKET + && builder.getTokenType() != JSTokenTypes.RPAR) { + builder.advanceLexer(); + } + else { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedValue()); + } + } + + if (attributeNameValuePair != null) { + attributeNameValuePair.done(JSElementTypes.ATTRIBUTE_NAME_VALUE_PAIR); + } + if (builder.getTokenType() != JSTokenTypes.COMMA) { + break; + } + builder.advanceLexer(); + + if (builder.eof()) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedRparen()); + return; + } + } + + if (haveLParen) { + checkMatches(builder, JSTokenTypes.RPAR, JavaScriptLocalize.javascriptParserMessageExpectedRparen()); + } + else { + builder.advanceLexer(); + } + } } diff --git a/lang-version-impl/ecmascript4-impl/src/main/java/consulo/javascript/ecmascript4/lang/parsing/EcmaScript4Parser.java b/lang-version-impl/ecmascript4-impl/src/main/java/consulo/javascript/ecmascript4/lang/parsing/EcmaScript4Parser.java index 8aaaad41..44560b9a 100644 --- a/lang-version-impl/ecmascript4-impl/src/main/java/consulo/javascript/ecmascript4/lang/parsing/EcmaScript4Parser.java +++ b/lang-version-impl/ecmascript4-impl/src/main/java/consulo/javascript/ecmascript4/lang/parsing/EcmaScript4Parser.java @@ -3,18 +3,16 @@ import consulo.javascript.lang.parsing.JavaScriptParser; import consulo.javascript.lang.parsing.JavaScriptParsingContext; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 24.08.14 */ -public class EcmaScript4Parser extends JavaScriptParser -{ - @Nonnull - @Override - public JavaScriptParsingContext createParsingContext() - { - return new EcmaScript4ParsingContext(); - } +public class EcmaScript4Parser extends JavaScriptParser { + @Nonnull + @Override + public JavaScriptParsingContext createParsingContext() { + return new EcmaScript4ParsingContext(); + } } diff --git a/lang-version-impl/ecmascript4-impl/src/main/java/consulo/javascript/ecmascript4/lang/parsing/EcmaScript4ParsingContext.java b/lang-version-impl/ecmascript4-impl/src/main/java/consulo/javascript/ecmascript4/lang/parsing/EcmaScript4ParsingContext.java index d3a2da3a..18a97942 100644 --- a/lang-version-impl/ecmascript4-impl/src/main/java/consulo/javascript/ecmascript4/lang/parsing/EcmaScript4ParsingContext.java +++ b/lang-version-impl/ecmascript4-impl/src/main/java/consulo/javascript/ecmascript4/lang/parsing/EcmaScript4ParsingContext.java @@ -4,33 +4,28 @@ import consulo.javascript.lang.parsing.FunctionParsing; import consulo.javascript.lang.parsing.JavaScriptParsingContext; import consulo.javascript.lang.parsing.StatementParsing; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 24.08.14 */ -public class EcmaScript4ParsingContext extends JavaScriptParsingContext -{ - @Nonnull - @Override - protected StatementParsing createStatementParsing() - { - return new EcmaScript4StatementParsing(this); - } +public class EcmaScript4ParsingContext extends JavaScriptParsingContext { + @Nonnull + @Override + protected StatementParsing createStatementParsing() { + return new EcmaScript4StatementParsing(this); + } - @Nonnull - @Override - protected FunctionParsing createFunctionParsing() - { - return new EcmaScript4FunctionParsing(this); - } + @Nonnull + @Override + protected FunctionParsing createFunctionParsing() { + return new EcmaScript4FunctionParsing(this); + } - @Nonnull - @Override - protected ExpressionParsing createExpressionParsing() - { - return new EcmaScript4ExpressionParsing(this); - } + @Nonnull + @Override + protected ExpressionParsing createExpressionParsing() { + return new EcmaScript4ExpressionParsing(this); + } } diff --git a/lang-version-impl/ecmascript4-impl/src/main/java/consulo/javascript/ecmascript4/lang/parsing/EcmaScript4StatementParsing.java b/lang-version-impl/ecmascript4-impl/src/main/java/consulo/javascript/ecmascript4/lang/parsing/EcmaScript4StatementParsing.java index 8c0f5bea..385a02cb 100644 --- a/lang-version-impl/ecmascript4-impl/src/main/java/consulo/javascript/ecmascript4/lang/parsing/EcmaScript4StatementParsing.java +++ b/lang-version-impl/ecmascript4-impl/src/main/java/consulo/javascript/ecmascript4/lang/parsing/EcmaScript4StatementParsing.java @@ -3,520 +3,425 @@ import com.intellij.lang.javascript.JSElementTypes; import com.intellij.lang.javascript.JSTokenTypes; import consulo.javascript.lang.parsing.StatementParsing; -import consulo.javascript.language.JavaScriptBundle; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.ast.IElementType; import consulo.language.parser.PsiBuilder; import consulo.logging.Logger; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 24.08.14 */ -public class EcmaScript4StatementParsing extends StatementParsing -{ - public static final Logger LOGGER = Logger.getInstance(EcmaScript4StatementParsing.class); - - public EcmaScript4StatementParsing(EcmaScript4ParsingContext context) - { - super(context); - } - - @Override - public EcmaScript4FunctionParsing getFunctionParsing() - { - return (EcmaScript4FunctionParsing) super.getFunctionParsing(); - } - - @Override - public void parseSourceElement(PsiBuilder builder) - { - final IElementType tokenType = builder.getTokenType(); - if(tokenType == JSTokenTypes.FUNCTION_KEYWORD) - { - getFunctionParsing().parseFunctionDeclaration(builder); - } - else if(tokenType == JSTokenTypes.PACKAGE_KEYWORD) - { - parsePackage(builder); - } - else if(tokenType == JSTokenTypes.AT) - { - builder.advanceLexer(); - getFunctionParsing().parseAttributeWithoutBrackets(builder); - } - else - { - doParseStatement(builder, true); - } - } - - @Override - protected void parseVarDeclaration(final PsiBuilder builder, boolean allowIn) - { - if(!JSTokenTypes.IDENTIFIER_TOKENS_SET.contains(builder.getTokenType())) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.variable.name")); - builder.advanceLexer(); - return; - } - - PsiBuilder.Marker var = builder.mark(); - - getExpressionParsing().parseQualifiedTypeName(builder, false); - - getExpressionParsing().tryParseType(builder); - - if(builder.getTokenType() == JSTokenTypes.EQ) - { - builder.advanceLexer(); - if(allowIn) - { - if(!getExpressionParsing().parseAssignmentExpression(builder)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - } - else - { - if(!getExpressionParsing().parseAssignmentExpressionNoIn(builder)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - } - } - var.done(JSElementTypes.VARIABLE); - } - - @Override - protected void doParseStatement(final PsiBuilder builder, boolean canHaveClasses) - { - final IElementType firstToken = builder.getTokenType(); - - if(firstToken == null) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.statement")); - return; - } - - if(firstToken == JSTokenTypes.LBRACE) - { - parseBlock(builder); - return; - } - - if(firstToken == JSTokenTypes.VAR_KEYWORD || - firstToken == JSTokenTypes.CONST_KEYWORD || - firstToken == JSTokenTypes.LET_KEYWORD) - { - parseVarStatement(builder, false); - return; - } - - if(firstToken == JSTokenTypes.SEMICOLON) - { - parseEmptyStatement(builder); - return; - } - - if(firstToken == JSTokenTypes.IF_KEYWORD) - { - parseIfStatement(builder); - return; - } - - if(firstToken == JSTokenTypes.DO_KEYWORD || - firstToken == JSTokenTypes.WHILE_KEYWORD || - firstToken == JSTokenTypes.FOR_KEYWORD) - { - parseIterationStatement(builder); - return; - } - - if(firstToken == JSTokenTypes.CONTINUE_KEYWORD) - { - parseContinueStatement(builder); - return; - } - - if(firstToken == JSTokenTypes.BREAK_KEYWORD) - { - parseBreakStatement(builder); - return; - } - - if(firstToken == JSTokenTypes.RETURN_KEYWORD) - { - parseReturnStatement(builder); - return; - } - - if(firstToken == JSTokenTypes.WITH_KEYWORD) - { - parseWithStatement(builder); - return; - } - - if(firstToken == JSTokenTypes.YIELD_KEYWORD) - { - parseYieldStatement(builder); - return; - } - - if(firstToken == JSTokenTypes.LET_KEYWORD) - { - parseLetStatement(builder); - return; - } - - if(firstToken == JSTokenTypes.SWITCH_KEYWORD) - { - parseSwitchStatement(builder); - return; - } - - if(firstToken == JSTokenTypes.THROW_KEYWORD) - { - parseThrowStatement(builder); - return; - } - - if(firstToken == JSTokenTypes.TRY_KEYWORD) - { - parseTryStatement(builder); - return; - } - - if(firstToken == JSTokenTypes.DEFAULT_KEYWORD) - { - parseDefaultNsStatement(builder); - return; - } - - if(firstToken == JSTokenTypes.FUNCTION_KEYWORD) - { - getFunctionParsing().parseFunctionDeclaration(builder); - return; - } - - if(canHaveClasses) - { - if(firstToken == JSTokenTypes.IMPORT_KEYWORD) - { - parseImportStatement(builder); - return; - } - - if((firstToken == JSTokenTypes.CLASS_KEYWORD || firstToken == JSTokenTypes.INTERFACE_KEYWORD)) - { - parseClass(builder); - return; - } - - if(firstToken == JSTokenTypes.USE_KEYWORD) - { - parseUseNamespaceDirective(builder); - return; - } - - if(firstToken == JSTokenTypes.INCLUDE_KEYWORD) - { - parseIncludeDirective(builder); - return; - } - - if(firstToken == JSTokenTypes.NAMESPACE_KEYWORD) - { - if(parseNamespaceNoMarker(builder, builder.mark())) - { - return; - } - } - - if((JSTokenTypes.IDENTIFIER == firstToken || - JSTokenTypes.MODIFIERS.contains(firstToken) || - JSTokenTypes.LBRACKET == firstToken)) - { - PsiBuilder.Marker marker = builder.mark(); - getFunctionParsing().parseAttributesList(builder); - - if(builder.eof()) - { - marker.drop(); - return; - } - - final IElementType tokenType = builder.getTokenType(); - if(tokenType == JSTokenTypes.FUNCTION_KEYWORD) - { - getFunctionParsing().parseFunctionNoMarker(builder, false, marker); - return; - } - else if(tokenType == JSTokenTypes.VAR_KEYWORD || tokenType == JSTokenTypes.CONST_KEYWORD) - { - parseVarStatementWithMarker(builder, false, marker); - return; - } - else if(tokenType == JSTokenTypes.NAMESPACE_KEYWORD) - { - if(parseNamespaceNoMarker(builder, marker)) - { - return; - } - else - { - builder.advanceLexer(); - } - } - else if(tokenType == JSTokenTypes.CLASS_KEYWORD || tokenType == JSTokenTypes.INTERFACE_KEYWORD) - { - parseClassNoMarker(builder, marker); - return; - } - else - { - - if(firstToken == JSTokenTypes.IDENTIFIER) - { - marker.rollbackTo(); - } - else if(JSTokenTypes.COLON_COLON == builder.getTokenType()) - { - marker.rollbackTo(); - if(parseExpressionStatement(builder)) - { - return; - } - } - else - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.function.var.class.interface.namespace")); - marker.drop(); - } - } - } - } - - if(firstToken == JSTokenTypes.IDENTIFIER) - { - // Try labeled statement: - final PsiBuilder.Marker labeledStatement = builder.mark(); - builder.advanceLexer(); - if(builder.getTokenType() == JSTokenTypes.COLON) - { - builder.advanceLexer(); - parseStatement(builder); - labeledStatement.done(JSElementTypes.LABELED_STATEMENT); - return; - } - else - { - labeledStatement.rollbackTo(); - } - } - - if(firstToken != JSTokenTypes.LBRACE && firstToken != JSTokenTypes.FUNCTION_KEYWORD) - { - if(parseExpressionStatement(builder)) - { - return; - } - } - - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.statement")); - builder.advanceLexer(); - } - - private void parseDefaultNsStatement(final PsiBuilder builder) - { - EcmaScript4StatementParsing.LOGGER.assertTrue(builder.getTokenType() == JSTokenTypes.DEFAULT_KEYWORD); - final PsiBuilder.Marker marker = builder.mark(); - builder.advanceLexer(); - - if(builder.getTokenType() == JSTokenTypes.IDENTIFIER && "xml".equals(builder.getTokenText())) - { - builder.advanceLexer(); - - if(checkMatches(builder, JSTokenTypes.NAMESPACE_KEYWORD, JavaScriptBundle.message("javascript.parser.message.expected.namespace"))) - { - if(checkMatches(builder, JSTokenTypes.EQ, JavaScriptBundle.message("javascript.parser.message.expected.equal"))) - { - getExpressionParsing().parseExpression(builder); - } - } - } - else - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.xml")); - } - marker.done(JSElementTypes.ASSIGNMENT_EXPRESSION); - } - - - private void parseImportStatement(final PsiBuilder builder) - { - final PsiBuilder.Marker importStatement = builder.mark(); - try - { - builder.advanceLexer(); - - final PsiBuilder.Marker nsAssignment = builder.mark(); - if(!getExpressionParsing().parseQualifiedTypeName(builder, true)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.typename")); - nsAssignment.drop(); - return; - } - - if(builder.getTokenType() == JSTokenTypes.EQ) - { - builder.advanceLexer(); - if(!getExpressionParsing().parseQualifiedTypeName(builder)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.typename")); - } - - nsAssignment.done(JSElementTypes.ASSIGNMENT_EXPRESSION); - } - else - { - nsAssignment.drop(); - } - - checkForSemicolon(builder); - } - finally - { - importStatement.done(JSElementTypes.ES4_IMPORT_STATEMENT); - } - } - - private boolean parseNamespaceNoMarker(final PsiBuilder builder, final @Nonnull PsiBuilder.Marker useNSStatement) - { - EcmaScript4StatementParsing.LOGGER.assertTrue(builder.getTokenType() == JSTokenTypes.NAMESPACE_KEYWORD); - - builder.advanceLexer(); - if(builder.getTokenType() == JSTokenTypes.LPAR) - { - useNSStatement.rollbackTo(); - return false; - } - - if(!getExpressionParsing().parseQualifiedTypeName(builder)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.typename")); - } - if(builder.getTokenType() == JSTokenTypes.EQ) - { - builder.advanceLexer(); - checkMatches(builder, JSTokenTypes.STRING_LITERAL, JavaScriptBundle.message("javascript.parser.message.expected.string.literal")); - } - checkForSemicolon(builder); - useNSStatement.done(JSElementTypes.NAMESPACE_DECLARATION); - return true; - } - - private void parseUseNamespaceDirective(final PsiBuilder builder) - { - final PsiBuilder.Marker useNSStatement = builder.mark(); - builder.advanceLexer(); - - if(builder.getTokenType() != JSTokenTypes.NAMESPACE_KEYWORD) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.namespace")); - } - else - { - builder.advanceLexer(); - - if(!getExpressionParsing().parseQualifiedTypeName(builder)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.typename")); - } - - while(builder.getTokenType() == JSTokenTypes.COMMA) - { - builder.advanceLexer(); - if(!getExpressionParsing().parseQualifiedTypeName(builder)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.typename")); - break; - } - } - } - checkForSemicolon(builder); - useNSStatement.done(JSElementTypes.USE_NAMESPACE_DIRECTIVE); - } - - private void parseClass(final PsiBuilder builder) - { - parseClassNoMarker(builder, builder.mark()); - } - - private void parseClassNoMarker(final PsiBuilder builder, final @Nonnull PsiBuilder.Marker clazz) - { - final IElementType tokenType = builder.getTokenType(); - EcmaScript4StatementParsing.LOGGER.assertTrue(JSTokenTypes.CLASS_KEYWORD == tokenType || JSTokenTypes.INTERFACE_KEYWORD == tokenType); - - builder.advanceLexer(); - if(!getExpressionParsing().parseQualifiedTypeName(builder)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.typename")); - } - - if(builder.getTokenType() == JSTokenTypes.EXTENDS_KEYWORD) - { - parseReferenceList(builder); - } - - if(builder.getTokenType() == JSTokenTypes.IMPLEMENTS_KEYWORD) - { - parseReferenceList(builder); - } - - parseBlockOrFunctionBody(builder, BlockType.PACKAGE_OR_CLASS_BODY); - clazz.done(JSElementTypes.CLASS); - } - - private void parseReferenceList(final PsiBuilder builder) - { - final IElementType tokenType = builder.getTokenType(); - EcmaScript4StatementParsing.LOGGER.assertTrue(tokenType == JSTokenTypes.EXTENDS_KEYWORD || tokenType == JSTokenTypes.IMPLEMENTS_KEYWORD); - final PsiBuilder.Marker referenceList = builder.mark(); - builder.advanceLexer(); - - if(getExpressionParsing().parseQualifiedTypeName(builder)) - { - while(builder.getTokenType() == JSTokenTypes.COMMA) - { - builder.advanceLexer(); - if(!getExpressionParsing().parseQualifiedTypeName(builder)) - { - break; - } - } - } - referenceList.done(tokenType == JSTokenTypes.EXTENDS_KEYWORD ? JSElementTypes.EXTENDS_LIST : JSElementTypes.IMPLEMENTS_LIST); - } - - private void parsePackage(final PsiBuilder builder) - { - final PsiBuilder.Marker packageMarker = builder.mark(); - builder.advanceLexer(); - if(builder.getTokenType() == JSTokenTypes.IDENTIFIER) - { - getExpressionParsing().parseQualifiedTypeName(builder); - } - - if(builder.getTokenType() != JSTokenTypes.LBRACE) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.name.or.lbrace")); - } - else - { - parseBlockOrFunctionBody(builder, BlockType.PACKAGE_OR_CLASS_BODY); - } - packageMarker.done(JSElementTypes.PACKAGE_STATEMENT); - } +public class EcmaScript4StatementParsing extends StatementParsing { + public static final Logger LOGGER = Logger.getInstance(EcmaScript4StatementParsing.class); + + public EcmaScript4StatementParsing(EcmaScript4ParsingContext context) { + super(context); + } + + @Override + public EcmaScript4FunctionParsing getFunctionParsing() { + return (EcmaScript4FunctionParsing)super.getFunctionParsing(); + } + + @Override + public void parseSourceElement(PsiBuilder builder) { + IElementType tokenType = builder.getTokenType(); + if (tokenType == JSTokenTypes.FUNCTION_KEYWORD) { + getFunctionParsing().parseFunctionDeclaration(builder); + } + else if (tokenType == JSTokenTypes.PACKAGE_KEYWORD) { + parsePackage(builder); + } + else if (tokenType == JSTokenTypes.AT) { + builder.advanceLexer(); + getFunctionParsing().parseAttributeWithoutBrackets(builder); + } + else { + doParseStatement(builder, true); + } + } + + @Override + protected void parseVarDeclaration(PsiBuilder builder, boolean allowIn) { + if (!JSTokenTypes.IDENTIFIER_TOKENS_SET.contains(builder.getTokenType())) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedVariableName()); + builder.advanceLexer(); + return; + } + + PsiBuilder.Marker var = builder.mark(); + + getExpressionParsing().parseQualifiedTypeName(builder, false); + + getExpressionParsing().tryParseType(builder); + + if (builder.getTokenType() == JSTokenTypes.EQ) { + builder.advanceLexer(); + if (allowIn) { + if (!getExpressionParsing().parseAssignmentExpression(builder)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + } + else { + if (!getExpressionParsing().parseAssignmentExpressionNoIn(builder)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedExpression()); + } + } + } + var.done(JSElementTypes.VARIABLE); + } + + @Override + protected void doParseStatement(PsiBuilder builder, boolean canHaveClasses) { + IElementType firstToken = builder.getTokenType(); + + if (firstToken == null) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedStatement()); + return; + } + + if (firstToken == JSTokenTypes.LBRACE) { + parseBlock(builder); + return; + } + + if (firstToken == JSTokenTypes.VAR_KEYWORD || + firstToken == JSTokenTypes.CONST_KEYWORD || + firstToken == JSTokenTypes.LET_KEYWORD) { + parseVarStatement(builder, false); + return; + } + + if (firstToken == JSTokenTypes.SEMICOLON) { + parseEmptyStatement(builder); + return; + } + + if (firstToken == JSTokenTypes.IF_KEYWORD) { + parseIfStatement(builder); + return; + } + + if (firstToken == JSTokenTypes.DO_KEYWORD || + firstToken == JSTokenTypes.WHILE_KEYWORD || + firstToken == JSTokenTypes.FOR_KEYWORD) { + parseIterationStatement(builder); + return; + } + + if (firstToken == JSTokenTypes.CONTINUE_KEYWORD) { + parseContinueStatement(builder); + return; + } + + if (firstToken == JSTokenTypes.BREAK_KEYWORD) { + parseBreakStatement(builder); + return; + } + + if (firstToken == JSTokenTypes.RETURN_KEYWORD) { + parseReturnStatement(builder); + return; + } + + if (firstToken == JSTokenTypes.WITH_KEYWORD) { + parseWithStatement(builder); + return; + } + + if (firstToken == JSTokenTypes.YIELD_KEYWORD) { + parseYieldStatement(builder); + return; + } + + if (firstToken == JSTokenTypes.LET_KEYWORD) { + parseLetStatement(builder); + return; + } + + if (firstToken == JSTokenTypes.SWITCH_KEYWORD) { + parseSwitchStatement(builder); + return; + } + + if (firstToken == JSTokenTypes.THROW_KEYWORD) { + parseThrowStatement(builder); + return; + } + + if (firstToken == JSTokenTypes.TRY_KEYWORD) { + parseTryStatement(builder); + return; + } + + if (firstToken == JSTokenTypes.DEFAULT_KEYWORD) { + parseDefaultNsStatement(builder); + return; + } + + if (firstToken == JSTokenTypes.FUNCTION_KEYWORD) { + getFunctionParsing().parseFunctionDeclaration(builder); + return; + } + + if (canHaveClasses) { + if (firstToken == JSTokenTypes.IMPORT_KEYWORD) { + parseImportStatement(builder); + return; + } + + if ((firstToken == JSTokenTypes.CLASS_KEYWORD || firstToken == JSTokenTypes.INTERFACE_KEYWORD)) { + parseClass(builder); + return; + } + + if (firstToken == JSTokenTypes.USE_KEYWORD) { + parseUseNamespaceDirective(builder); + return; + } + + if (firstToken == JSTokenTypes.INCLUDE_KEYWORD) { + parseIncludeDirective(builder); + return; + } + + if (firstToken == JSTokenTypes.NAMESPACE_KEYWORD && parseNamespaceNoMarker(builder, builder.mark())) { + return; + } + + if (JSTokenTypes.IDENTIFIER == firstToken + || JSTokenTypes.MODIFIERS.contains(firstToken) + || JSTokenTypes.LBRACKET == firstToken) { + PsiBuilder.Marker marker = builder.mark(); + getFunctionParsing().parseAttributesList(builder); + + if (builder.eof()) { + marker.drop(); + return; + } + + IElementType tokenType = builder.getTokenType(); + if (tokenType == JSTokenTypes.FUNCTION_KEYWORD) { + getFunctionParsing().parseFunctionNoMarker(builder, false, marker); + return; + } + else if (tokenType == JSTokenTypes.VAR_KEYWORD || tokenType == JSTokenTypes.CONST_KEYWORD) { + parseVarStatementWithMarker(builder, false, marker); + return; + } + else if (tokenType == JSTokenTypes.NAMESPACE_KEYWORD) { + if (parseNamespaceNoMarker(builder, marker)) { + return; + } + else { + builder.advanceLexer(); + } + } + else if (tokenType == JSTokenTypes.CLASS_KEYWORD || tokenType == JSTokenTypes.INTERFACE_KEYWORD) { + parseClassNoMarker(builder, marker); + return; + } + else if (firstToken == JSTokenTypes.IDENTIFIER) { + marker.rollbackTo(); + } + else if (JSTokenTypes.COLON_COLON == builder.getTokenType()) { + marker.rollbackTo(); + if (parseExpressionStatement(builder)) { + return; + } + } + else { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedFunctionVarClassInterfaceNamespace()); + marker.drop(); + } + } + } + + if (firstToken == JSTokenTypes.IDENTIFIER) { + // Try labeled statement: + PsiBuilder.Marker labeledStatement = builder.mark(); + builder.advanceLexer(); + if (builder.getTokenType() == JSTokenTypes.COLON) { + builder.advanceLexer(); + parseStatement(builder); + labeledStatement.done(JSElementTypes.LABELED_STATEMENT); + return; + } + else { + labeledStatement.rollbackTo(); + } + } + + if (firstToken != JSTokenTypes.LBRACE && firstToken != JSTokenTypes.FUNCTION_KEYWORD) { + if (parseExpressionStatement(builder)) { + return; + } + } + + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedStatement().get()); + builder.advanceLexer(); + } + + private void parseDefaultNsStatement(PsiBuilder builder) { + EcmaScript4StatementParsing.LOGGER.assertTrue(builder.getTokenType() == JSTokenTypes.DEFAULT_KEYWORD); + PsiBuilder.Marker marker = builder.mark(); + builder.advanceLexer(); + + if (builder.getTokenType() == JSTokenTypes.IDENTIFIER && "xml".equals(builder.getTokenText())) { + builder.advanceLexer(); + + if (checkMatches(builder, JSTokenTypes.NAMESPACE_KEYWORD, JavaScriptLocalize.javascriptParserMessageExpectedNamespace())) { + if (checkMatches(builder, JSTokenTypes.EQ, JavaScriptLocalize.javascriptParserMessageExpectedEqual())) { + getExpressionParsing().parseExpression(builder); + } + } + } + else { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedXml()); + } + marker.done(JSElementTypes.ASSIGNMENT_EXPRESSION); + } + + private void parseImportStatement(PsiBuilder builder) { + PsiBuilder.Marker importStatement = builder.mark(); + try { + builder.advanceLexer(); + + PsiBuilder.Marker nsAssignment = builder.mark(); + if (!getExpressionParsing().parseQualifiedTypeName(builder, true)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedTypename()); + nsAssignment.drop(); + return; + } + + if (builder.getTokenType() == JSTokenTypes.EQ) { + builder.advanceLexer(); + if (!getExpressionParsing().parseQualifiedTypeName(builder)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedTypename()); + } + + nsAssignment.done(JSElementTypes.ASSIGNMENT_EXPRESSION); + } + else { + nsAssignment.drop(); + } + + checkForSemicolon(builder); + } + finally { + importStatement.done(JSElementTypes.ES4_IMPORT_STATEMENT); + } + } + + private boolean parseNamespaceNoMarker(PsiBuilder builder, @Nonnull PsiBuilder.Marker useNSStatement) { + EcmaScript4StatementParsing.LOGGER.assertTrue(builder.getTokenType() == JSTokenTypes.NAMESPACE_KEYWORD); + + builder.advanceLexer(); + if (builder.getTokenType() == JSTokenTypes.LPAR) { + useNSStatement.rollbackTo(); + return false; + } + + if (!getExpressionParsing().parseQualifiedTypeName(builder)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedTypename()); + } + if (builder.getTokenType() == JSTokenTypes.EQ) { + builder.advanceLexer(); + checkMatches(builder, JSTokenTypes.STRING_LITERAL, JavaScriptLocalize.javascriptParserMessageExpectedStringLiteral()); + } + checkForSemicolon(builder); + useNSStatement.done(JSElementTypes.NAMESPACE_DECLARATION); + return true; + } + + private void parseUseNamespaceDirective(PsiBuilder builder) { + PsiBuilder.Marker useNSStatement = builder.mark(); + builder.advanceLexer(); + + if (builder.getTokenType() != JSTokenTypes.NAMESPACE_KEYWORD) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedNamespace()); + } + else { + builder.advanceLexer(); + + if (!getExpressionParsing().parseQualifiedTypeName(builder)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedTypename()); + } + + while (builder.getTokenType() == JSTokenTypes.COMMA) { + builder.advanceLexer(); + if (!getExpressionParsing().parseQualifiedTypeName(builder)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedTypename()); + break; + } + } + } + checkForSemicolon(builder); + useNSStatement.done(JSElementTypes.USE_NAMESPACE_DIRECTIVE); + } + + private void parseClass(PsiBuilder builder) { + parseClassNoMarker(builder, builder.mark()); + } + + private void parseClassNoMarker(PsiBuilder builder, @Nonnull PsiBuilder.Marker clazz) { + IElementType tokenType = builder.getTokenType(); + EcmaScript4StatementParsing.LOGGER.assertTrue( + JSTokenTypes.CLASS_KEYWORD == tokenType || JSTokenTypes.INTERFACE_KEYWORD == tokenType + ); + + builder.advanceLexer(); + if (!getExpressionParsing().parseQualifiedTypeName(builder)) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedTypename()); + } + + if (builder.getTokenType() == JSTokenTypes.EXTENDS_KEYWORD) { + parseReferenceList(builder); + } + + if (builder.getTokenType() == JSTokenTypes.IMPLEMENTS_KEYWORD) { + parseReferenceList(builder); + } + + parseBlockOrFunctionBody(builder, BlockType.PACKAGE_OR_CLASS_BODY); + clazz.done(JSElementTypes.CLASS); + } + + private void parseReferenceList(PsiBuilder builder) { + IElementType tokenType = builder.getTokenType(); + EcmaScript4StatementParsing.LOGGER.assertTrue( + tokenType == JSTokenTypes.EXTENDS_KEYWORD || tokenType == JSTokenTypes.IMPLEMENTS_KEYWORD + ); + PsiBuilder.Marker referenceList = builder.mark(); + builder.advanceLexer(); + + if (getExpressionParsing().parseQualifiedTypeName(builder)) { + while (builder.getTokenType() == JSTokenTypes.COMMA) { + builder.advanceLexer(); + if (!getExpressionParsing().parseQualifiedTypeName(builder)) { + break; + } + } + } + referenceList.done(tokenType == JSTokenTypes.EXTENDS_KEYWORD ? JSElementTypes.EXTENDS_LIST : JSElementTypes.IMPLEMENTS_LIST); + } + + private void parsePackage(PsiBuilder builder) { + PsiBuilder.Marker packageMarker = builder.mark(); + builder.advanceLexer(); + if (builder.getTokenType() == JSTokenTypes.IDENTIFIER) { + getExpressionParsing().parseQualifiedTypeName(builder); + } + + if (builder.getTokenType() != JSTokenTypes.LBRACE) { + builder.error(JavaScriptLocalize.javascriptParserMessageExpectedNameOrLbrace()); + } + else { + parseBlockOrFunctionBody(builder, BlockType.PACKAGE_OR_CLASS_BODY); + } + packageMarker.done(JSElementTypes.PACKAGE_STATEMENT); + } } diff --git a/lang-version-impl/ecmascript4-impl/src/main/java/module-info.java b/lang-version-impl/ecmascript4-impl/src/main/java/module-info.java index 2e12821c..2d84b4f0 100644 --- a/lang-version-impl/ecmascript4-impl/src/main/java/module-info.java +++ b/lang-version-impl/ecmascript4-impl/src/main/java/module-info.java @@ -2,10 +2,9 @@ * @author VISTALL * @since 23-Aug-22 */ -module consulo.javascript.ecmascript4.impl -{ - requires transitive consulo.javascript.base.impl; +module consulo.javascript.ecmascript4.impl { + requires transitive consulo.javascript.base.impl; - exports consulo.javascript.ecmascript4.lang; - exports consulo.javascript.ecmascript4.lang.parsing; + exports consulo.javascript.ecmascript4.lang; + exports consulo.javascript.ecmascript4.lang.parsing; } \ No newline at end of file diff --git a/lang-version-impl/javascript16-impl/pom.xml b/lang-version-impl/javascript16-impl/pom.xml index aa705801..cfcf5dea 100644 --- a/lang-version-impl/javascript16-impl/pom.xml +++ b/lang-version-impl/javascript16-impl/pom.xml @@ -32,7 +32,7 @@ consulo - https://maven.consulo.io/repository/snapshots/ + https://maven.consulo.dev/repository/snapshots/ true interval:60 diff --git a/lang-version-impl/javascript16-impl/src/main/java/consulo/javascript/javascript16/lang/JavaScript16LanguageVersion.java b/lang-version-impl/javascript16-impl/src/main/java/consulo/javascript/javascript16/lang/JavaScript16LanguageVersion.java index a73956c6..b6c51243 100644 --- a/lang-version-impl/javascript16-impl/src/main/java/consulo/javascript/javascript16/lang/JavaScript16LanguageVersion.java +++ b/lang-version-impl/javascript16-impl/src/main/java/consulo/javascript/javascript16/lang/JavaScript16LanguageVersion.java @@ -21,11 +21,12 @@ import consulo.javascript.javascript16.lang.lexer.JavaScript16Lexer; import consulo.javascript.lang.BaseJavaScriptLanguageVersion; import consulo.javascript.language.JavaScriptLanguage; -import consulo.javascript.language.StandardJavaScriptVersions; +import consulo.javascript.language.StandardJavaScriptVersion; import consulo.language.editor.highlight.SyntaxHighlighter; import consulo.language.lexer.Lexer; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; + import java.util.function.Supplier; /** @@ -33,45 +34,38 @@ * @since 11.12.2015 */ @ExtensionImpl -public class JavaScript16LanguageVersion extends BaseJavaScriptLanguageVersion implements StandardJavaScriptVersions.Marker -{ - private static final Supplier ourLexerFactory = () -> new JavaScript16Lexer(); +public class JavaScript16LanguageVersion extends BaseJavaScriptLanguageVersion implements StandardJavaScriptVersion { + private static final Supplier ourLexerFactory = () -> new JavaScript16Lexer(); - @Nonnull - public static JavaScript16LanguageVersion getInstance() - { - return JavaScriptLanguage.INSTANCE.findVersionByClass(JavaScript16LanguageVersion.class); - } + @Nonnull + public static JavaScript16LanguageVersion getInstance() { + return JavaScriptLanguage.INSTANCE.findVersionByClass(JavaScript16LanguageVersion.class); + } - public JavaScript16LanguageVersion() - { - super("JAVASCRIPT_1_6"); - } + public JavaScript16LanguageVersion() { + super("JAVASCRIPT_1_6"); + } - @Nonnull - @Override - public String getPresentableName() - { - return "JavaScript 1.6"; - } + @Nonnull + @Override + public String getPresentableName() { + return "JavaScript 1.6"; + } - @Nonnull - @Override - public Lexer createLexer() - { - return ourLexerFactory.get(); - } + @Nonnull + @Override + public Lexer createLexer() { + return ourLexerFactory.get(); + } - @Nonnull - @Override - public SyntaxHighlighter getSyntaxHighlighter() - { - return new JavaScriptHighlighter(ourLexerFactory); - } + @Nonnull + @Override + public SyntaxHighlighter getSyntaxHighlighter() { + return new JavaScriptHighlighter(ourLexerFactory); + } - @Override - public int getWeight() - { - return 10; - } + @Override + public int getWeight() { + return 10; + } } \ No newline at end of file diff --git a/lang-version-impl/javascript16-impl/src/main/java/consulo/javascript/javascript16/lang/lexer/JavaScript16Lexer.java b/lang-version-impl/javascript16-impl/src/main/java/consulo/javascript/javascript16/lang/lexer/JavaScript16Lexer.java index a700f38a..53525432 100644 --- a/lang-version-impl/javascript16-impl/src/main/java/consulo/javascript/javascript16/lang/lexer/JavaScript16Lexer.java +++ b/lang-version-impl/javascript16-impl/src/main/java/consulo/javascript/javascript16/lang/lexer/JavaScript16Lexer.java @@ -6,1202 +6,1415 @@ import consulo.language.ast.IElementType; import com.intellij.lang.javascript.JSTokenTypes; - /** - * This class is a scanner generated by + * This class is a scanner generated by * JFlex 1.4.4 * on 15.02.16 12:38 from the specification file * R:/_github.com/consulo/consulo-javascript/javascript16-impl/src/org/mustbe/consulo/javascript/lang/lexer/javascript16.flex */ public class JavaScript16Lexer extends LexerBase { - /** initial size of the lookahead buffer */ - private static final int ZZ_BUFFERSIZE = 16384; - - /** lexical states */ - public static final int DIV_OR_GT = 2; - public static final int YYINITIAL = 0; - - /** - * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l - * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l - * at the beginning of a line - * l is of the form l = 2*k, k a non negative integer - */ - private static final int ZZ_LEXSTATE[] = { - 0, 0, 1, 1 - }; - - /** - * Translates characters to character classes - */ - private static final String ZZ_CMAP_PACKED = - "\11\5\1\3\1\16\1\0\1\3\1\10\16\5\4\0\1\3\1\54"+ - "\1\21\1\0\1\4\1\63\1\60\1\17\1\64\1\65\1\7\1\55"+ - "\1\71\1\15\1\13\1\6\1\11\7\1\2\1\1\74\1\70\1\56"+ - "\1\53\1\57\1\73\1\0\4\2\1\14\1\2\21\4\1\12\2\4"+ - "\1\22\1\20\1\23\1\62\1\4\1\0\1\33\1\41\1\43\1\37"+ - "\1\31\1\32\1\52\1\44\1\40\1\4\1\42\1\34\1\24\1\36"+ - "\1\45\1\50\1\4\1\27\1\35\1\26\1\30\1\51\1\47\1\25"+ - "\1\46\1\4\1\66\1\61\1\67\1\72\41\5\2\0\4\4\4\0"+ - "\1\4\2\0\1\5\7\0\1\4\4\0\1\4\5\0\27\4\1\0"+ - "\37\4\1\0\u013f\4\31\0\162\4\4\0\14\4\16\0\5\4\11\0"+ - "\1\4\21\0\130\5\5\0\23\5\12\0\1\4\13\0\1\4\1\0"+ - "\3\4\1\0\1\4\1\0\24\4\1\0\54\4\1\0\46\4\1\0"+ - "\5\4\4\0\202\4\1\0\4\5\3\0\105\4\1\0\46\4\2\0"+ - "\2\4\6\0\20\4\41\0\46\4\2\0\1\4\7\0\47\4\11\0"+ - "\21\5\1\0\27\5\1\0\3\5\1\0\1\5\1\0\2\5\1\0"+ - "\1\5\13\0\33\4\5\0\3\4\15\0\4\5\14\0\6\5\13\0"+ - "\32\4\5\0\13\4\16\5\7\0\12\5\4\0\2\4\1\5\143\4"+ - "\1\0\1\4\10\5\1\0\6\5\2\4\2\5\1\0\4\5\2\4"+ - "\12\5\3\4\2\0\1\4\17\0\1\5\1\4\1\5\36\4\33\5"+ - "\2\0\3\4\60\0\46\4\13\5\1\4\u014f\0\3\5\66\4\2\0"+ - "\1\5\1\4\20\5\2\0\1\4\4\5\3\0\12\4\2\5\2\0"+ - "\12\5\21\0\3\5\1\0\10\4\2\0\2\4\2\0\26\4\1\0"+ - "\7\4\1\0\1\4\3\0\4\4\2\0\1\5\1\4\7\5\2\0"+ - "\2\5\2\0\3\5\11\0\1\5\4\0\2\4\1\0\3\4\2\5"+ - "\2\0\12\5\4\4\15\0\3\5\1\0\6\4\4\0\2\4\2\0"+ - "\26\4\1\0\7\4\1\0\2\4\1\0\2\4\1\0\2\4\2\0"+ - "\1\5\1\0\5\5\4\0\2\5\2\0\3\5\13\0\4\4\1\0"+ - "\1\4\7\0\14\5\3\4\14\0\3\5\1\0\11\4\1\0\3\4"+ - "\1\0\26\4\1\0\7\4\1\0\2\4\1\0\5\4\2\0\1\5"+ - "\1\4\10\5\1\0\3\5\1\0\3\5\2\0\1\4\17\0\2\4"+ - "\2\5\2\0\12\5\1\0\1\4\17\0\3\5\1\0\10\4\2\0"+ - "\2\4\2\0\26\4\1\0\7\4\1\0\2\4\1\0\5\4\2\0"+ - "\1\5\1\4\6\5\3\0\2\5\2\0\3\5\10\0\2\5\4\0"+ - "\2\4\1\0\3\4\4\0\12\5\1\0\1\4\20\0\1\5\1\4"+ - "\1\0\6\4\3\0\3\4\1\0\4\4\3\0\2\4\1\0\1\4"+ - "\1\0\2\4\3\0\2\4\3\0\3\4\3\0\10\4\1\0\3\4"+ - "\4\0\5\5\3\0\3\5\1\0\4\5\11\0\1\5\17\0\11\5"+ - "\11\0\1\4\7\0\3\5\1\0\10\4\1\0\3\4\1\0\27\4"+ - "\1\0\12\4\1\0\5\4\4\0\7\5\1\0\3\5\1\0\4\5"+ - "\7\0\2\5\11\0\2\4\4\0\12\5\22\0\2\5\1\0\10\4"+ - "\1\0\3\4\1\0\27\4\1\0\12\4\1\0\5\4\2\0\1\5"+ - "\1\4\7\5\1\0\3\5\1\0\4\5\7\0\2\5\7\0\1\4"+ - "\1\0\2\4\4\0\12\5\22\0\2\5\1\0\10\4\1\0\3\4"+ - "\1\0\27\4\1\0\20\4\4\0\6\5\2\0\3\5\1\0\4\5"+ - "\11\0\1\5\10\0\2\4\4\0\12\5\22\0\2\5\1\0\22\4"+ - "\3\0\30\4\1\0\11\4\1\0\1\4\2\0\7\4\3\0\1\5"+ - "\4\0\6\5\1\0\1\5\1\0\10\5\22\0\2\5\15\0\60\4"+ - "\1\5\2\4\7\5\4\0\10\4\10\5\1\0\12\5\47\0\2\4"+ - "\1\0\1\4\2\0\2\4\1\0\1\4\2\0\1\4\6\0\4\4"+ - "\1\0\7\4\1\0\3\4\1\0\1\4\1\0\1\4\2\0\2\4"+ - "\1\0\4\4\1\5\2\4\6\5\1\0\2\5\1\4\2\0\5\4"+ - "\1\0\1\4\1\0\6\5\2\0\12\5\2\0\2\4\42\0\1\4"+ - "\27\0\2\5\6\0\12\5\13\0\1\5\1\0\1\5\1\0\1\5"+ - "\4\0\2\5\10\4\1\0\42\4\6\0\24\5\1\0\2\5\4\4"+ - "\4\0\10\5\1\0\44\5\11\0\1\5\71\0\42\4\1\0\5\4"+ - "\1\0\2\4\1\0\7\5\3\0\4\5\6\0\12\5\6\0\6\4"+ - "\4\5\106\0\46\4\12\0\51\4\7\0\132\4\5\0\104\4\5\0"+ - "\122\4\6\0\7\4\1\0\77\4\1\0\1\4\1\0\4\4\2\0"+ - "\7\4\1\0\1\4\1\0\4\4\2\0\47\4\1\0\1\4\1\0"+ - "\4\4\2\0\37\4\1\0\1\4\1\0\4\4\2\0\7\4\1\0"+ - "\1\4\1\0\4\4\2\0\7\4\1\0\7\4\1\0\27\4\1\0"+ - "\37\4\1\0\1\4\1\0\4\4\2\0\7\4\1\0\47\4\1\0"+ - "\23\4\16\0\11\5\56\0\125\4\14\0\u026c\4\2\0\10\4\12\0"+ - "\32\4\5\0\113\4\3\0\3\4\17\0\15\4\1\0\4\4\3\5"+ - "\13\0\22\4\3\5\13\0\22\4\2\5\14\0\15\4\1\0\3\4"+ - "\1\0\2\5\14\0\64\4\40\5\3\0\1\4\3\0\2\4\1\5"+ - "\2\0\12\5\41\0\3\5\2\0\12\5\6\0\130\4\10\0\51\4"+ - "\1\5\126\0\35\4\3\0\14\5\4\0\14\5\12\0\12\5\36\4"+ - "\2\0\5\4\u038b\0\154\4\224\0\234\4\4\0\132\4\6\0\26\4"+ - "\2\0\6\4\2\0\46\4\2\0\6\4\2\0\10\4\1\0\1\4"+ - "\1\0\1\4\1\0\1\4\1\0\37\4\2\0\65\4\1\0\7\4"+ - "\1\0\1\4\3\0\3\4\1\0\7\4\3\0\4\4\2\0\6\4"+ - "\4\0\15\4\5\0\3\4\1\0\7\4\17\0\4\5\32\0\5\5"+ - "\20\0\2\4\23\0\1\4\13\0\4\5\6\0\6\5\1\0\1\4"+ - "\15\0\1\4\40\0\22\4\36\0\15\5\4\0\1\5\3\0\6\5"+ - "\27\0\1\4\4\0\1\4\2\0\12\4\1\0\1\4\3\0\5\4"+ - "\6\0\1\4\1\0\1\4\1\0\1\4\1\0\4\4\1\0\3\4"+ - "\1\0\7\4\3\0\3\4\5\0\5\4\26\0\44\4\u0e81\0\3\4"+ - "\31\0\11\4\6\5\1\0\5\4\2\0\5\4\4\0\126\4\2\0"+ - "\2\5\2\0\3\4\1\0\137\4\5\0\50\4\4\0\136\4\21\0"+ - "\30\4\70\0\20\4\u0200\0\u19b6\4\112\0\u51a6\4\132\0\u048d\4\u0773\0"+ - "\u2ba4\4\u215c\0\u012e\4\2\0\73\4\225\0\7\4\14\0\5\4\5\0"+ - "\1\4\1\5\12\4\1\0\15\4\1\0\5\4\1\0\1\4\1\0"+ - "\2\4\1\0\2\4\1\0\154\4\41\0\u016b\4\22\0\100\4\2\0"+ - "\66\4\50\0\15\4\3\0\20\5\20\0\4\5\17\0\2\4\30\0"+ - "\3\4\31\0\1\4\6\0\5\4\1\0\207\4\2\0\1\5\4\0"+ - "\1\4\13\0\12\5\7\0\32\4\4\0\1\4\1\0\32\4\12\0"+ - "\132\4\3\0\6\4\2\0\6\4\2\0\6\4\2\0\3\4\3\0"+ - "\2\4\3\0\2\4\22\0\3\5\4\0"; - - /** - * Translates characters to character classes - */ - private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); - - /** - * Translates DFA states to action switch labels. - */ - private static final int [] ZZ_ACTION = zzUnpackAction(); - - private static final String ZZ_ACTION_PACKED_0 = - "\2\0\1\1\1\2\1\3\1\4\1\5\1\6\1\2"+ - "\1\7\1\10\1\11\1\12\1\13\1\14\16\3\1\15"+ - "\1\16\1\17\1\20\1\21\1\22\1\23\1\24\1\25"+ - "\1\26\1\27\1\30\1\31\1\32\1\33\1\34\1\35"+ - "\1\36\1\6\1\37\2\2\1\40\1\41\1\42\1\0"+ - "\1\40\1\2\1\43\1\44\2\11\2\12\17\3\1\45"+ - "\1\46\1\47\10\3\1\50\1\51\1\52\1\53\1\54"+ - "\1\55\1\56\1\57\1\60\1\61\1\62\1\63\1\64"+ - "\1\65\1\66\1\67\1\2\1\40\1\42\1\70\1\40"+ - "\2\0\2\11\2\12\1\3\1\71\11\3\1\72\1\73"+ - "\2\3\1\74\11\3\1\75\1\3\1\76\1\77\1\100"+ - "\1\101\1\102\1\103\1\0\2\70\1\104\1\3\1\105"+ - "\3\3\1\106\4\3\1\107\5\3\1\110\2\3\1\111"+ - "\1\3\1\112\1\113\1\42\1\0\1\114\4\3\1\115"+ - "\5\3\1\116\1\117\1\3\1\120\1\121\1\122\1\123"+ - "\3\3\1\124\1\3\1\125\4\3\1\126\1\127\3\3"+ - "\1\130\1\3\1\131\1\132\1\3\1\133"; - - private static int [] zzUnpackAction() { - int [] result = new int[217]; - int offset = 0; - offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); - return result; - } - - private static int zzUnpackAction(String packed, int offset, int [] result) { - int i = 0; /* index in packed string */ - int j = offset; /* index in unpacked array */ - int l = packed.length(); - while (i < l) { - int count = packed.charAt(i++); - int value = packed.charAt(i++); - do result[j++] = value; while (--count > 0); - } - return j; - } - - - /** - * Translates a state to a row index in the transition table - */ - private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); - - private static final String ZZ_ROWMAP_PACKED_0 = - "\0\0\0\75\0\172\0\267\0\364\0\u0131\0\u016e\0\172"+ - "\0\u01ab\0\u01e8\0\u0225\0\u0262\0\u029f\0\172\0\172\0\u02dc"+ - "\0\u0319\0\u0356\0\u0393\0\u03d0\0\u040d\0\u044a\0\u0487\0\u04c4"+ - "\0\u0501\0\u053e\0\u057b\0\u05b8\0\u05f5\0\u0632\0\u066f\0\u06ac"+ - "\0\u06e9\0\u0726\0\u0763\0\u07a0\0\u07dd\0\172\0\172\0\172"+ - "\0\172\0\172\0\172\0\172\0\172\0\172\0\u081a\0\u0857"+ - "\0\u0894\0\u08d1\0\u090e\0\u094b\0\u0988\0\u09c5\0\u0a02\0\u0a3f"+ - "\0\u0a7c\0\172\0\172\0\172\0\u0ab9\0\u0af6\0\172\0\u0b33"+ - "\0\u0b70\0\u0bad\0\u0bea\0\u0c27\0\u0c64\0\u0ca1\0\u0cde\0\u0d1b"+ - "\0\u0d58\0\u0d95\0\u0dd2\0\u0e0f\0\u0e4c\0\u0e89\0\364\0\364"+ - "\0\u0ec6\0\u0f03\0\u0f40\0\u0f7d\0\u0fba\0\u0ff7\0\u1034\0\u1071"+ - "\0\u10ae\0\u10eb\0\u1128\0\172\0\172\0\172\0\u1165\0\172"+ - "\0\172\0\172\0\172\0\172\0\172\0\172\0\172\0\172"+ - "\0\u11a2\0\u11df\0\u121c\0\u1259\0\u1296\0\u12d3\0\u1310\0\u134d"+ - "\0\u138a\0\u13c7\0\u1404\0\u1441\0\u147e\0\364\0\u14bb\0\u14f8"+ - "\0\u1535\0\u1572\0\u15af\0\u15ec\0\u1629\0\u1666\0\u16a3\0\364"+ - "\0\364\0\u16e0\0\u171d\0\364\0\u175a\0\u1797\0\u17d4\0\u1811"+ - "\0\u184e\0\u188b\0\u18c8\0\u1905\0\u1942\0\364\0\u197f\0\364"+ - "\0\172\0\172\0\172\0\u19bc\0\172\0\u19f9\0\u1a36\0\172"+ - "\0\364\0\u1a73\0\364\0\u1ab0\0\u1aed\0\u1b2a\0\364\0\u1b67"+ - "\0\u1ba4\0\u1be1\0\u1c1e\0\364\0\u1c5b\0\u1c98\0\u1cd5\0\u1d12"+ - "\0\u1d4f\0\364\0\u1d8c\0\u1dc9\0\364\0\u1e06\0\364\0\172"+ - "\0\172\0\u1e43\0\364\0\u1e80\0\u1ebd\0\u1efa\0\u1f37\0\364"+ - "\0\u1f74\0\u1fb1\0\u1fee\0\u202b\0\u2068\0\364\0\364\0\u20a5"+ - "\0\364\0\364\0\364\0\364\0\u20e2\0\u211f\0\u215c\0\364"+ - "\0\u2199\0\364\0\u21d6\0\u2213\0\u2250\0\u228d\0\364\0\364"+ - "\0\u22ca\0\u2307\0\u2344\0\364\0\u2381\0\364\0\364\0\u23be"+ - "\0\364"; - - private static int [] zzUnpackRowMap() { - int [] result = new int[217]; - int offset = 0; - offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); - return result; - } - - private static int zzUnpackRowMap(String packed, int offset, int [] result) { - int i = 0; /* index in packed string */ - int j = offset; /* index in unpacked array */ - int l = packed.length(); - while (i < l) { - int high = packed.charAt(i++) << 16; - result[j++] = high | packed.charAt(i++); + /** + * initial size of the lookahead buffer + */ + private static final int ZZ_BUFFERSIZE = 16384; + + /** + * lexical states + */ + public static final int DIV_OR_GT = 2; + public static final int YYINITIAL = 0; + + /** + * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l + * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l + * at the beginning of a line + * l is of the form l = 2*k, k a non negative integer + */ + private static final int ZZ_LEXSTATE[] = { + 0, 0, 1, 1 + }; + + /** + * Translates characters to character classes + */ + private static final String ZZ_CMAP_PACKED = + "\11\5\1\3\1\16\1\0\1\3\1\10\16\5\4\0\1\3\1\54" + + "\1\21\1\0\1\4\1\63\1\60\1\17\1\64\1\65\1\7\1\55" + + "\1\71\1\15\1\13\1\6\1\11\7\1\2\1\1\74\1\70\1\56" + + "\1\53\1\57\1\73\1\0\4\2\1\14\1\2\21\4\1\12\2\4" + + "\1\22\1\20\1\23\1\62\1\4\1\0\1\33\1\41\1\43\1\37" + + "\1\31\1\32\1\52\1\44\1\40\1\4\1\42\1\34\1\24\1\36" + + "\1\45\1\50\1\4\1\27\1\35\1\26\1\30\1\51\1\47\1\25" + + "\1\46\1\4\1\66\1\61\1\67\1\72\41\5\2\0\4\4\4\0" + + "\1\4\2\0\1\5\7\0\1\4\4\0\1\4\5\0\27\4\1\0" + + "\37\4\1\0\u013f\4\31\0\162\4\4\0\14\4\16\0\5\4\11\0" + + "\1\4\21\0\130\5\5\0\23\5\12\0\1\4\13\0\1\4\1\0" + + "\3\4\1\0\1\4\1\0\24\4\1\0\54\4\1\0\46\4\1\0" + + "\5\4\4\0\202\4\1\0\4\5\3\0\105\4\1\0\46\4\2\0" + + "\2\4\6\0\20\4\41\0\46\4\2\0\1\4\7\0\47\4\11\0" + + "\21\5\1\0\27\5\1\0\3\5\1\0\1\5\1\0\2\5\1\0" + + "\1\5\13\0\33\4\5\0\3\4\15\0\4\5\14\0\6\5\13\0" + + "\32\4\5\0\13\4\16\5\7\0\12\5\4\0\2\4\1\5\143\4" + + "\1\0\1\4\10\5\1\0\6\5\2\4\2\5\1\0\4\5\2\4" + + "\12\5\3\4\2\0\1\4\17\0\1\5\1\4\1\5\36\4\33\5" + + "\2\0\3\4\60\0\46\4\13\5\1\4\u014f\0\3\5\66\4\2\0" + + "\1\5\1\4\20\5\2\0\1\4\4\5\3\0\12\4\2\5\2\0" + + "\12\5\21\0\3\5\1\0\10\4\2\0\2\4\2\0\26\4\1\0" + + "\7\4\1\0\1\4\3\0\4\4\2\0\1\5\1\4\7\5\2\0" + + "\2\5\2\0\3\5\11\0\1\5\4\0\2\4\1\0\3\4\2\5" + + "\2\0\12\5\4\4\15\0\3\5\1\0\6\4\4\0\2\4\2\0" + + "\26\4\1\0\7\4\1\0\2\4\1\0\2\4\1\0\2\4\2\0" + + "\1\5\1\0\5\5\4\0\2\5\2\0\3\5\13\0\4\4\1\0" + + "\1\4\7\0\14\5\3\4\14\0\3\5\1\0\11\4\1\0\3\4" + + "\1\0\26\4\1\0\7\4\1\0\2\4\1\0\5\4\2\0\1\5" + + "\1\4\10\5\1\0\3\5\1\0\3\5\2\0\1\4\17\0\2\4" + + "\2\5\2\0\12\5\1\0\1\4\17\0\3\5\1\0\10\4\2\0" + + "\2\4\2\0\26\4\1\0\7\4\1\0\2\4\1\0\5\4\2\0" + + "\1\5\1\4\6\5\3\0\2\5\2\0\3\5\10\0\2\5\4\0" + + "\2\4\1\0\3\4\4\0\12\5\1\0\1\4\20\0\1\5\1\4" + + "\1\0\6\4\3\0\3\4\1\0\4\4\3\0\2\4\1\0\1\4" + + "\1\0\2\4\3\0\2\4\3\0\3\4\3\0\10\4\1\0\3\4" + + "\4\0\5\5\3\0\3\5\1\0\4\5\11\0\1\5\17\0\11\5" + + "\11\0\1\4\7\0\3\5\1\0\10\4\1\0\3\4\1\0\27\4" + + "\1\0\12\4\1\0\5\4\4\0\7\5\1\0\3\5\1\0\4\5" + + "\7\0\2\5\11\0\2\4\4\0\12\5\22\0\2\5\1\0\10\4" + + "\1\0\3\4\1\0\27\4\1\0\12\4\1\0\5\4\2\0\1\5" + + "\1\4\7\5\1\0\3\5\1\0\4\5\7\0\2\5\7\0\1\4" + + "\1\0\2\4\4\0\12\5\22\0\2\5\1\0\10\4\1\0\3\4" + + "\1\0\27\4\1\0\20\4\4\0\6\5\2\0\3\5\1\0\4\5" + + "\11\0\1\5\10\0\2\4\4\0\12\5\22\0\2\5\1\0\22\4" + + "\3\0\30\4\1\0\11\4\1\0\1\4\2\0\7\4\3\0\1\5" + + "\4\0\6\5\1\0\1\5\1\0\10\5\22\0\2\5\15\0\60\4" + + "\1\5\2\4\7\5\4\0\10\4\10\5\1\0\12\5\47\0\2\4" + + "\1\0\1\4\2\0\2\4\1\0\1\4\2\0\1\4\6\0\4\4" + + "\1\0\7\4\1\0\3\4\1\0\1\4\1\0\1\4\2\0\2\4" + + "\1\0\4\4\1\5\2\4\6\5\1\0\2\5\1\4\2\0\5\4" + + "\1\0\1\4\1\0\6\5\2\0\12\5\2\0\2\4\42\0\1\4" + + "\27\0\2\5\6\0\12\5\13\0\1\5\1\0\1\5\1\0\1\5" + + "\4\0\2\5\10\4\1\0\42\4\6\0\24\5\1\0\2\5\4\4" + + "\4\0\10\5\1\0\44\5\11\0\1\5\71\0\42\4\1\0\5\4" + + "\1\0\2\4\1\0\7\5\3\0\4\5\6\0\12\5\6\0\6\4" + + "\4\5\106\0\46\4\12\0\51\4\7\0\132\4\5\0\104\4\5\0" + + "\122\4\6\0\7\4\1\0\77\4\1\0\1\4\1\0\4\4\2\0" + + "\7\4\1\0\1\4\1\0\4\4\2\0\47\4\1\0\1\4\1\0" + + "\4\4\2\0\37\4\1\0\1\4\1\0\4\4\2\0\7\4\1\0" + + "\1\4\1\0\4\4\2\0\7\4\1\0\7\4\1\0\27\4\1\0" + + "\37\4\1\0\1\4\1\0\4\4\2\0\7\4\1\0\47\4\1\0" + + "\23\4\16\0\11\5\56\0\125\4\14\0\u026c\4\2\0\10\4\12\0" + + "\32\4\5\0\113\4\3\0\3\4\17\0\15\4\1\0\4\4\3\5" + + "\13\0\22\4\3\5\13\0\22\4\2\5\14\0\15\4\1\0\3\4" + + "\1\0\2\5\14\0\64\4\40\5\3\0\1\4\3\0\2\4\1\5" + + "\2\0\12\5\41\0\3\5\2\0\12\5\6\0\130\4\10\0\51\4" + + "\1\5\126\0\35\4\3\0\14\5\4\0\14\5\12\0\12\5\36\4" + + "\2\0\5\4\u038b\0\154\4\224\0\234\4\4\0\132\4\6\0\26\4" + + "\2\0\6\4\2\0\46\4\2\0\6\4\2\0\10\4\1\0\1\4" + + "\1\0\1\4\1\0\1\4\1\0\37\4\2\0\65\4\1\0\7\4" + + "\1\0\1\4\3\0\3\4\1\0\7\4\3\0\4\4\2\0\6\4" + + "\4\0\15\4\5\0\3\4\1\0\7\4\17\0\4\5\32\0\5\5" + + "\20\0\2\4\23\0\1\4\13\0\4\5\6\0\6\5\1\0\1\4" + + "\15\0\1\4\40\0\22\4\36\0\15\5\4\0\1\5\3\0\6\5" + + "\27\0\1\4\4\0\1\4\2\0\12\4\1\0\1\4\3\0\5\4" + + "\6\0\1\4\1\0\1\4\1\0\1\4\1\0\4\4\1\0\3\4" + + "\1\0\7\4\3\0\3\4\5\0\5\4\26\0\44\4\u0e81\0\3\4" + + "\31\0\11\4\6\5\1\0\5\4\2\0\5\4\4\0\126\4\2\0" + + "\2\5\2\0\3\4\1\0\137\4\5\0\50\4\4\0\136\4\21\0" + + "\30\4\70\0\20\4\u0200\0\u19b6\4\112\0\u51a6\4\132\0\u048d\4\u0773\0" + + "\u2ba4\4\u215c\0\u012e\4\2\0\73\4\225\0\7\4\14\0\5\4\5\0" + + "\1\4\1\5\12\4\1\0\15\4\1\0\5\4\1\0\1\4\1\0" + + "\2\4\1\0\2\4\1\0\154\4\41\0\u016b\4\22\0\100\4\2\0" + + "\66\4\50\0\15\4\3\0\20\5\20\0\4\5\17\0\2\4\30\0" + + "\3\4\31\0\1\4\6\0\5\4\1\0\207\4\2\0\1\5\4\0" + + "\1\4\13\0\12\5\7\0\32\4\4\0\1\4\1\0\32\4\12\0" + + "\132\4\3\0\6\4\2\0\6\4\2\0\6\4\2\0\3\4\3\0" + + "\2\4\3\0\2\4\22\0\3\5\4\0"; + + /** + * Translates characters to character classes + */ + private static final char[] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); + + /** + * Translates DFA states to action switch labels. + */ + private static final int[] ZZ_ACTION = zzUnpackAction(); + + private static final String ZZ_ACTION_PACKED_0 = + "\2\0\1\1\1\2\1\3\1\4\1\5\1\6\1\2" + + "\1\7\1\10\1\11\1\12\1\13\1\14\16\3\1\15" + + "\1\16\1\17\1\20\1\21\1\22\1\23\1\24\1\25" + + "\1\26\1\27\1\30\1\31\1\32\1\33\1\34\1\35" + + "\1\36\1\6\1\37\2\2\1\40\1\41\1\42\1\0" + + "\1\40\1\2\1\43\1\44\2\11\2\12\17\3\1\45" + + "\1\46\1\47\10\3\1\50\1\51\1\52\1\53\1\54" + + "\1\55\1\56\1\57\1\60\1\61\1\62\1\63\1\64" + + "\1\65\1\66\1\67\1\2\1\40\1\42\1\70\1\40" + + "\2\0\2\11\2\12\1\3\1\71\11\3\1\72\1\73" + + "\2\3\1\74\11\3\1\75\1\3\1\76\1\77\1\100" + + "\1\101\1\102\1\103\1\0\2\70\1\104\1\3\1\105" + + "\3\3\1\106\4\3\1\107\5\3\1\110\2\3\1\111" + + "\1\3\1\112\1\113\1\42\1\0\1\114\4\3\1\115" + + "\5\3\1\116\1\117\1\3\1\120\1\121\1\122\1\123" + + "\3\3\1\124\1\3\1\125\4\3\1\126\1\127\3\3" + + "\1\130\1\3\1\131\1\132\1\3\1\133"; + + private static int[] zzUnpackAction() { + int[] result = new int[217]; + int offset = 0; + offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); + return result; } - return j; - } - - /** - * The transition table of the DFA - */ - private static final int [] ZZ_TRANS = zzUnpackTrans(); - - private static final String ZZ_TRANS_PACKED_0 = - "\1\3\1\4\1\5\1\6\1\5\1\3\1\7\1\10"+ - "\1\6\1\11\1\5\1\12\1\5\1\13\1\6\1\14"+ - "\1\3\1\15\1\16\1\17\2\5\1\20\1\21\1\22"+ - "\1\23\1\24\2\5\1\25\1\26\1\27\1\30\1\31"+ - "\1\5\1\32\3\5\1\33\1\5\1\34\1\35\1\36"+ - "\1\37\1\40\1\3\1\41\1\42\1\43\1\44\1\45"+ - "\1\46\1\47\1\50\1\51\1\52\1\53\1\54\1\55"+ - "\1\56\1\3\1\4\1\5\1\6\1\5\1\3\1\57"+ - "\1\60\1\6\1\11\1\5\1\12\1\5\1\13\1\6"+ - "\1\14\1\3\1\15\1\16\1\17\2\5\1\20\1\21"+ - "\1\22\1\23\1\24\2\5\1\25\1\26\1\27\1\30"+ - "\1\31\1\5\1\32\3\5\1\33\1\5\1\34\1\35"+ - "\1\36\1\37\1\40\1\61\1\41\1\42\1\43\1\44"+ - "\1\45\1\46\1\47\1\50\1\51\1\52\1\53\1\54"+ - "\1\55\1\56\76\0\1\4\7\0\1\4\1\0\1\62"+ - "\1\63\14\0\1\63\44\0\2\5\1\0\2\5\3\0"+ - "\2\5\1\0\1\5\7\0\27\5\25\0\1\6\4\0"+ - "\1\6\5\0\1\6\56\0\6\64\1\65\1\66\1\0"+ - "\5\64\1\0\1\64\1\67\1\64\1\70\52\64\1\0"+ - "\1\4\7\0\1\4\1\71\1\62\1\63\10\0\1\71"+ - "\3\0\1\63\44\0\1\62\7\0\1\62\100\0\1\72"+ - "\35\0\1\73\21\0\10\14\1\0\5\14\1\0\1\74"+ - "\1\75\54\14\10\15\1\0\5\15\1\0\1\15\1\76"+ - "\1\77\53\15\1\0\2\5\1\0\2\5\3\0\2\5"+ - "\1\0\1\5\7\0\3\5\1\100\14\5\1\101\1\5"+ - "\1\102\4\5\23\0\2\5\1\0\2\5\3\0\2\5"+ - "\1\0\1\5\7\0\5\5\1\103\21\5\23\0\2\5"+ - "\1\0\2\5\3\0\2\5\1\0\1\5\7\0\12\5"+ - "\1\104\14\5\23\0\2\5\1\0\2\5\3\0\2\5"+ - "\1\0\1\5\7\0\10\5\1\105\16\5\23\0\2\5"+ - "\1\0\2\5\3\0\2\5\1\0\1\5\7\0\4\5"+ - "\1\106\2\5\1\107\4\5\1\110\4\5\1\111\5\5"+ - "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5"+ - "\7\0\5\5\1\112\15\5\1\113\3\5\23\0\2\5"+ - "\1\0\2\5\3\0\2\5\1\0\1\5\7\0\4\5"+ - "\1\114\1\115\21\5\23\0\2\5\1\0\2\5\3\0"+ - "\2\5\1\0\1\5\7\0\5\5\1\116\13\5\1\117"+ - "\5\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0"+ - "\1\5\7\0\6\5\1\120\3\5\1\121\14\5\23\0"+ - "\2\5\1\0\2\5\3\0\2\5\1\0\1\5\7\0"+ - "\3\5\1\122\23\5\23\0\2\5\1\0\2\5\3\0"+ - "\2\5\1\0\1\5\7\0\7\5\1\123\11\5\1\124"+ - "\5\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0"+ - "\1\5\7\0\14\5\1\125\3\5\1\126\6\5\23\0"+ - "\2\5\1\0\2\5\3\0\2\5\1\0\1\5\7\0"+ - "\7\5\1\127\11\5\1\130\5\5\23\0\2\5\1\0"+ - "\2\5\3\0\2\5\1\0\1\5\7\0\5\5\1\131"+ - "\21\5\75\0\1\132\74\0\1\133\74\0\1\134\1\0"+ - "\1\135\72\0\1\136\3\0\1\137\70\0\1\140\4\0"+ - "\1\141\67\0\1\142\5\0\1\143\66\0\1\144\74\0"+ - "\1\145\27\0\1\65\1\66\43\0\1\146\74\0\1\147"+ - "\74\0\1\150\2\0\1\151\17\0\1\62\7\0\1\62"+ - "\2\0\1\63\14\0\1\63\44\0\1\152\7\0\1\152"+ - "\3\0\1\152\37\0\1\152\17\0\6\64\1\153\1\64"+ - "\1\0\5\64\1\0\1\64\1\67\1\64\1\70\52\64"+ - "\10\65\1\0\5\65\1\0\56\65\7\154\1\155\65\154"+ - "\10\64\1\0\5\64\1\0\56\64\6\70\1\156\1\70"+ - "\1\157\5\70\1\157\1\70\1\160\2\70\1\64\51\70"+ - "\1\0\2\71\6\0\1\71\2\0\1\71\14\0\3\71"+ - "\3\0\1\71\1\0\1\71\1\0\1\71\31\0\3\14"+ - "\1\161\4\14\1\162\64\14\3\15\1\163\4\15\1\164"+ - "\64\15\1\0\2\5\1\0\2\5\3\0\2\5\1\0"+ - "\1\5\7\0\4\5\1\165\15\5\1\166\4\5\23\0"+ - "\2\5\1\0\2\5\3\0\2\5\1\0\1\5\7\0"+ - "\3\5\1\167\10\5\1\170\12\5\23\0\2\5\1\0"+ - "\2\5\3\0\2\5\1\0\1\5\7\0\24\5\1\171"+ - "\2\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0"+ - "\1\5\7\0\2\5\1\172\24\5\23\0\2\5\1\0"+ - "\2\5\3\0\2\5\1\0\1\5\7\0\13\5\1\173"+ - "\13\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0"+ - "\1\5\7\0\11\5\1\174\15\5\23\0\2\5\1\0"+ - "\2\5\3\0\2\5\1\0\1\5\7\0\12\5\1\175"+ - "\14\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0"+ - "\1\5\7\0\10\5\1\176\16\5\23\0\2\5\1\0"+ - "\2\5\3\0\2\5\1\0\1\5\7\0\12\5\1\177"+ - "\14\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0"+ - "\1\5\7\0\3\5\1\200\23\5\23\0\2\5\1\0"+ - "\2\5\3\0\2\5\1\0\1\5\7\0\2\5\1\201"+ - "\24\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0"+ - "\1\5\7\0\14\5\1\202\12\5\23\0\2\5\1\0"+ - "\2\5\3\0\2\5\1\0\1\5\7\0\10\5\1\203"+ - "\16\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0"+ - "\1\5\7\0\23\5\1\204\3\5\23\0\2\5\1\0"+ - "\2\5\3\0\2\5\1\0\1\5\7\0\6\5\1\205"+ - "\1\5\1\206\16\5\23\0\2\5\1\0\2\5\3\0"+ - "\2\5\1\0\1\5\7\0\11\5\1\207\15\5\23\0"+ - "\2\5\1\0\2\5\3\0\2\5\1\0\1\5\7\0"+ - "\5\5\1\210\21\5\23\0\2\5\1\0\2\5\3\0"+ - "\2\5\1\0\1\5\7\0\2\5\1\211\6\5\1\212"+ - "\15\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0"+ - "\1\5\7\0\12\5\1\213\14\5\23\0\2\5\1\0"+ - "\2\5\3\0\2\5\1\0\1\5\7\0\2\5\1\214"+ - "\24\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0"+ - "\1\5\7\0\14\5\1\215\12\5\23\0\2\5\1\0"+ - "\2\5\3\0\2\5\1\0\1\5\7\0\3\5\1\216"+ - "\23\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0"+ - "\1\5\7\0\14\5\1\217\12\5\23\0\2\5\1\0"+ - "\2\5\3\0\2\5\1\0\1\5\7\0\2\5\1\220"+ - "\24\5\75\0\1\221\74\0\1\222\74\0\1\223\3\0"+ - "\1\224\70\0\1\225\22\0\1\152\7\0\1\152\107\0"+ - "\2\153\12\0\1\153\11\0\1\153\22\0\7\154\1\226"+ - "\65\154\6\227\1\230\1\155\65\227\23\157\1\64\2\156"+ - "\12\157\1\156\11\157\1\156\45\157\1\64\51\157\10\70"+ - "\1\157\5\70\1\157\4\70\1\64\51\70\3\14\1\161"+ - "\4\14\1\162\6\14\1\74\1\75\64\14\1\0\6\14"+ - "\1\74\1\75\54\14\3\15\1\163\4\15\1\164\7\15"+ - "\1\76\1\77\63\15\1\0\7\15\1\76\1\77\53\15"+ - "\1\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5"+ - "\7\0\5\5\1\231\21\5\23\0\2\5\1\0\2\5"+ - "\3\0\2\5\1\0\1\5\7\0\21\5\1\232\5\5"+ - "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5"+ - "\7\0\11\5\1\233\15\5\23\0\2\5\1\0\2\5"+ - "\3\0\2\5\1\0\1\5\7\0\5\5\1\234\21\5"+ - "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5"+ - "\7\0\4\5\1\235\22\5\23\0\2\5\1\0\2\5"+ - "\3\0\2\5\1\0\1\5\7\0\5\5\1\236\21\5"+ - "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5"+ - "\7\0\5\5\1\237\21\5\23\0\2\5\1\0\2\5"+ - "\3\0\2\5\1\0\1\5\7\0\17\5\1\240\7\5"+ - "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5"+ - "\7\0\11\5\1\241\15\5\23\0\2\5\1\0\2\5"+ - "\3\0\2\5\1\0\1\5\7\0\7\5\1\242\17\5"+ - "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5"+ - "\7\0\2\5\1\243\24\5\23\0\2\5\1\0\2\5"+ - "\3\0\2\5\1\0\1\5\7\0\10\5\1\244\16\5"+ - "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5"+ - "\7\0\7\5\1\245\17\5\23\0\2\5\1\0\2\5"+ - "\3\0\2\5\1\0\1\5\7\0\5\5\1\246\21\5"+ - "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5"+ - "\7\0\2\5\1\247\24\5\23\0\2\5\1\0\2\5"+ - "\3\0\2\5\1\0\1\5\7\0\7\5\1\250\17\5"+ - "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5"+ - "\7\0\17\5\1\251\7\5\23\0\2\5\1\0\2\5"+ - "\3\0\2\5\1\0\1\5\7\0\5\5\1\252\21\5"+ - "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5"+ - "\7\0\2\5\1\253\6\5\1\254\15\5\23\0\2\5"+ - "\1\0\2\5\3\0\2\5\1\0\1\5\7\0\20\5"+ - "\1\255\6\5\23\0\2\5\1\0\2\5\3\0\2\5"+ - "\1\0\1\5\7\0\10\5\1\256\16\5\23\0\2\5"+ - "\1\0\2\5\3\0\2\5\1\0\1\5\7\0\13\5"+ - "\1\257\13\5\75\0\1\260\21\0\6\154\1\261\1\226"+ - "\65\154\7\227\1\262\65\227\1\0\2\5\1\0\2\5"+ - "\3\0\2\5\1\0\1\5\7\0\23\5\1\263\3\5"+ - "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5"+ - "\7\0\21\5\1\264\5\5\23\0\2\5\1\0\2\5"+ - "\3\0\2\5\1\0\1\5\7\0\3\5\1\265\23\5"+ - "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5"+ - "\7\0\6\5\1\266\20\5\23\0\2\5\1\0\2\5"+ - "\3\0\2\5\1\0\1\5\7\0\2\5\1\267\24\5"+ - "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5"+ - "\7\0\5\5\1\270\21\5\23\0\2\5\1\0\2\5"+ - "\3\0\2\5\1\0\1\5\7\0\10\5\1\271\16\5"+ - "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5"+ - "\7\0\17\5\1\272\7\5\23\0\2\5\1\0\2\5"+ - "\3\0\2\5\1\0\1\5\7\0\4\5\1\273\22\5"+ - "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5"+ - "\7\0\2\5\1\274\24\5\23\0\2\5\1\0\2\5"+ - "\3\0\2\5\1\0\1\5\7\0\7\5\1\275\17\5"+ - "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5"+ - "\7\0\16\5\1\276\10\5\23\0\2\5\1\0\2\5"+ - "\3\0\2\5\1\0\1\5\7\0\20\5\1\277\6\5"+ - "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5"+ - "\7\0\14\5\1\300\12\5\23\0\2\5\1\0\2\5"+ - "\3\0\2\5\1\0\1\5\7\0\2\5\1\301\24\5"+ - "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5"+ - "\7\0\5\5\1\302\21\5\22\0\6\227\1\230\1\262"+ - "\65\227\1\0\2\5\1\0\2\5\3\0\2\5\1\0"+ - "\1\5\7\0\6\5\1\303\20\5\23\0\2\5\1\0"+ - "\2\5\3\0\2\5\1\0\1\5\7\0\12\5\1\304"+ - "\14\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0"+ - "\1\5\7\0\14\5\1\305\12\5\23\0\2\5\1\0"+ - "\2\5\3\0\2\5\1\0\1\5\7\0\14\5\1\306"+ - "\12\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0"+ - "\1\5\7\0\10\5\1\307\16\5\23\0\2\5\1\0"+ - "\2\5\3\0\2\5\1\0\1\5\7\0\20\5\1\310"+ - "\6\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0"+ - "\1\5\7\0\10\5\1\311\16\5\23\0\2\5\1\0"+ - "\2\5\3\0\2\5\1\0\1\5\7\0\5\5\1\312"+ - "\21\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0"+ - "\1\5\7\0\12\5\1\313\14\5\23\0\2\5\1\0"+ - "\2\5\3\0\2\5\1\0\1\5\7\0\12\5\1\314"+ - "\14\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0"+ - "\1\5\7\0\12\5\1\315\14\5\23\0\2\5\1\0"+ - "\2\5\3\0\2\5\1\0\1\5\7\0\21\5\1\316"+ - "\5\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0"+ - "\1\5\7\0\22\5\1\317\4\5\23\0\2\5\1\0"+ - "\2\5\3\0\2\5\1\0\1\5\7\0\2\5\1\320"+ - "\24\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0"+ - "\1\5\7\0\17\5\1\321\7\5\23\0\2\5\1\0"+ - "\2\5\3\0\2\5\1\0\1\5\7\0\4\5\1\322"+ - "\22\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0"+ - "\1\5\7\0\5\5\1\323\21\5\23\0\2\5\1\0"+ - "\2\5\3\0\2\5\1\0\1\5\7\0\12\5\1\324"+ - "\14\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0"+ - "\1\5\7\0\5\5\1\325\21\5\23\0\2\5\1\0"+ - "\2\5\3\0\2\5\1\0\1\5\7\0\5\5\1\326"+ - "\21\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0"+ - "\1\5\7\0\13\5\1\327\13\5\23\0\2\5\1\0"+ - "\2\5\3\0\2\5\1\0\1\5\7\0\21\5\1\330"+ - "\5\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0"+ - "\1\5\7\0\6\5\1\331\20\5\22\0"; - - private static int [] zzUnpackTrans() { - int [] result = new int[9211]; - int offset = 0; - offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); - return result; - } - - private static int zzUnpackTrans(String packed, int offset, int [] result) { - int i = 0; /* index in packed string */ - int j = offset; /* index in unpacked array */ - int l = packed.length(); - while (i < l) { - int count = packed.charAt(i++); - int value = packed.charAt(i++); - value--; - do result[j++] = value; while (--count > 0); + + private static int zzUnpackAction(String packed, int offset, int[] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; + while (--count > 0); + } + return j; } - return j; - } - - - /* error codes */ - private static final int ZZ_UNKNOWN_ERROR = 0; - private static final int ZZ_NO_MATCH = 1; - private static final int ZZ_PUSHBACK_2BIG = 2; - private static final char[] EMPTY_BUFFER = new char[0]; - private static final int YYEOF = -1; - - /* error messages for the codes above */ - private static final String ZZ_ERROR_MSG[] = { - "Unkown internal scanner error", - "Error: could not match input", - "Error: pushback value was too large" - }; - - /** - * ZZ_ATTRIBUTE[aState] contains the attributes of state aState - */ - private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); - - private static final String ZZ_ATTRIBUTE_PACKED_0 = - "\2\0\1\11\4\1\1\11\5\1\2\11\26\1\11\11"+ - "\10\1\1\0\2\1\3\11\2\1\1\11\34\1\3\11"+ - "\1\1\11\11\6\1\2\0\40\1\3\11\1\1\1\11"+ - "\1\0\1\1\1\11\27\1\2\11\1\0\47\1"; - - private static int [] zzUnpackAttribute() { - int [] result = new int[217]; - int offset = 0; - offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); - return result; - } - - private static int zzUnpackAttribute(String packed, int offset, int [] result) { - int i = 0; /* index in packed string */ - int j = offset; /* index in unpacked array */ - int l = packed.length(); - while (i < l) { - int count = packed.charAt(i++); - int value = packed.charAt(i++); - do result[j++] = value; while (--count > 0); + + + /** + * Translates a state to a row index in the transition table + */ + private static final int[] ZZ_ROWMAP = zzUnpackRowMap(); + + private static final String ZZ_ROWMAP_PACKED_0 = + "\0\0\0\75\0\172\0\267\0\364\0\u0131\0\u016e\0\172" + + "\0\u01ab\0\u01e8\0\u0225\0\u0262\0\u029f\0\172\0\172\0\u02dc" + + "\0\u0319\0\u0356\0\u0393\0\u03d0\0\u040d\0\u044a\0\u0487\0\u04c4" + + "\0\u0501\0\u053e\0\u057b\0\u05b8\0\u05f5\0\u0632\0\u066f\0\u06ac" + + "\0\u06e9\0\u0726\0\u0763\0\u07a0\0\u07dd\0\172\0\172\0\172" + + "\0\172\0\172\0\172\0\172\0\172\0\172\0\u081a\0\u0857" + + "\0\u0894\0\u08d1\0\u090e\0\u094b\0\u0988\0\u09c5\0\u0a02\0\u0a3f" + + "\0\u0a7c\0\172\0\172\0\172\0\u0ab9\0\u0af6\0\172\0\u0b33" + + "\0\u0b70\0\u0bad\0\u0bea\0\u0c27\0\u0c64\0\u0ca1\0\u0cde\0\u0d1b" + + "\0\u0d58\0\u0d95\0\u0dd2\0\u0e0f\0\u0e4c\0\u0e89\0\364\0\364" + + "\0\u0ec6\0\u0f03\0\u0f40\0\u0f7d\0\u0fba\0\u0ff7\0\u1034\0\u1071" + + "\0\u10ae\0\u10eb\0\u1128\0\172\0\172\0\172\0\u1165\0\172" + + "\0\172\0\172\0\172\0\172\0\172\0\172\0\172\0\172" + + "\0\u11a2\0\u11df\0\u121c\0\u1259\0\u1296\0\u12d3\0\u1310\0\u134d" + + "\0\u138a\0\u13c7\0\u1404\0\u1441\0\u147e\0\364\0\u14bb\0\u14f8" + + "\0\u1535\0\u1572\0\u15af\0\u15ec\0\u1629\0\u1666\0\u16a3\0\364" + + "\0\364\0\u16e0\0\u171d\0\364\0\u175a\0\u1797\0\u17d4\0\u1811" + + "\0\u184e\0\u188b\0\u18c8\0\u1905\0\u1942\0\364\0\u197f\0\364" + + "\0\172\0\172\0\172\0\u19bc\0\172\0\u19f9\0\u1a36\0\172" + + "\0\364\0\u1a73\0\364\0\u1ab0\0\u1aed\0\u1b2a\0\364\0\u1b67" + + "\0\u1ba4\0\u1be1\0\u1c1e\0\364\0\u1c5b\0\u1c98\0\u1cd5\0\u1d12" + + "\0\u1d4f\0\364\0\u1d8c\0\u1dc9\0\364\0\u1e06\0\364\0\172" + + "\0\172\0\u1e43\0\364\0\u1e80\0\u1ebd\0\u1efa\0\u1f37\0\364" + + "\0\u1f74\0\u1fb1\0\u1fee\0\u202b\0\u2068\0\364\0\364\0\u20a5" + + "\0\364\0\364\0\364\0\364\0\u20e2\0\u211f\0\u215c\0\364" + + "\0\u2199\0\364\0\u21d6\0\u2213\0\u2250\0\u228d\0\364\0\364" + + "\0\u22ca\0\u2307\0\u2344\0\364\0\u2381\0\364\0\364\0\u23be" + + "\0\364"; + + private static int[] zzUnpackRowMap() { + int[] result = new int[217]; + int offset = 0; + offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); + return result; } - return j; - } - /** the current state of the DFA */ - private int zzState; + private static int zzUnpackRowMap(String packed, int offset, int[] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int high = packed.charAt(i++) << 16; + result[j++] = high | packed.charAt(i++); + } + return j; + } - /** the current lexical state */ - private int zzLexicalState = YYINITIAL; + /** + * The transition table of the DFA + */ + private static final int[] ZZ_TRANS = zzUnpackTrans(); + + private static final String ZZ_TRANS_PACKED_0 = + "\1\3\1\4\1\5\1\6\1\5\1\3\1\7\1\10" + + "\1\6\1\11\1\5\1\12\1\5\1\13\1\6\1\14" + + "\1\3\1\15\1\16\1\17\2\5\1\20\1\21\1\22" + + "\1\23\1\24\2\5\1\25\1\26\1\27\1\30\1\31" + + "\1\5\1\32\3\5\1\33\1\5\1\34\1\35\1\36" + + "\1\37\1\40\1\3\1\41\1\42\1\43\1\44\1\45" + + "\1\46\1\47\1\50\1\51\1\52\1\53\1\54\1\55" + + "\1\56\1\3\1\4\1\5\1\6\1\5\1\3\1\57" + + "\1\60\1\6\1\11\1\5\1\12\1\5\1\13\1\6" + + "\1\14\1\3\1\15\1\16\1\17\2\5\1\20\1\21" + + "\1\22\1\23\1\24\2\5\1\25\1\26\1\27\1\30" + + "\1\31\1\5\1\32\3\5\1\33\1\5\1\34\1\35" + + "\1\36\1\37\1\40\1\61\1\41\1\42\1\43\1\44" + + "\1\45\1\46\1\47\1\50\1\51\1\52\1\53\1\54" + + "\1\55\1\56\76\0\1\4\7\0\1\4\1\0\1\62" + + "\1\63\14\0\1\63\44\0\2\5\1\0\2\5\3\0" + + "\2\5\1\0\1\5\7\0\27\5\25\0\1\6\4\0" + + "\1\6\5\0\1\6\56\0\6\64\1\65\1\66\1\0" + + "\5\64\1\0\1\64\1\67\1\64\1\70\52\64\1\0" + + "\1\4\7\0\1\4\1\71\1\62\1\63\10\0\1\71" + + "\3\0\1\63\44\0\1\62\7\0\1\62\100\0\1\72" + + "\35\0\1\73\21\0\10\14\1\0\5\14\1\0\1\74" + + "\1\75\54\14\10\15\1\0\5\15\1\0\1\15\1\76" + + "\1\77\53\15\1\0\2\5\1\0\2\5\3\0\2\5" + + "\1\0\1\5\7\0\3\5\1\100\14\5\1\101\1\5" + + "\1\102\4\5\23\0\2\5\1\0\2\5\3\0\2\5" + + "\1\0\1\5\7\0\5\5\1\103\21\5\23\0\2\5" + + "\1\0\2\5\3\0\2\5\1\0\1\5\7\0\12\5" + + "\1\104\14\5\23\0\2\5\1\0\2\5\3\0\2\5" + + "\1\0\1\5\7\0\10\5\1\105\16\5\23\0\2\5" + + "\1\0\2\5\3\0\2\5\1\0\1\5\7\0\4\5" + + "\1\106\2\5\1\107\4\5\1\110\4\5\1\111\5\5" + + "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5" + + "\7\0\5\5\1\112\15\5\1\113\3\5\23\0\2\5" + + "\1\0\2\5\3\0\2\5\1\0\1\5\7\0\4\5" + + "\1\114\1\115\21\5\23\0\2\5\1\0\2\5\3\0" + + "\2\5\1\0\1\5\7\0\5\5\1\116\13\5\1\117" + + "\5\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0" + + "\1\5\7\0\6\5\1\120\3\5\1\121\14\5\23\0" + + "\2\5\1\0\2\5\3\0\2\5\1\0\1\5\7\0" + + "\3\5\1\122\23\5\23\0\2\5\1\0\2\5\3\0" + + "\2\5\1\0\1\5\7\0\7\5\1\123\11\5\1\124" + + "\5\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0" + + "\1\5\7\0\14\5\1\125\3\5\1\126\6\5\23\0" + + "\2\5\1\0\2\5\3\0\2\5\1\0\1\5\7\0" + + "\7\5\1\127\11\5\1\130\5\5\23\0\2\5\1\0" + + "\2\5\3\0\2\5\1\0\1\5\7\0\5\5\1\131" + + "\21\5\75\0\1\132\74\0\1\133\74\0\1\134\1\0" + + "\1\135\72\0\1\136\3\0\1\137\70\0\1\140\4\0" + + "\1\141\67\0\1\142\5\0\1\143\66\0\1\144\74\0" + + "\1\145\27\0\1\65\1\66\43\0\1\146\74\0\1\147" + + "\74\0\1\150\2\0\1\151\17\0\1\62\7\0\1\62" + + "\2\0\1\63\14\0\1\63\44\0\1\152\7\0\1\152" + + "\3\0\1\152\37\0\1\152\17\0\6\64\1\153\1\64" + + "\1\0\5\64\1\0\1\64\1\67\1\64\1\70\52\64" + + "\10\65\1\0\5\65\1\0\56\65\7\154\1\155\65\154" + + "\10\64\1\0\5\64\1\0\56\64\6\70\1\156\1\70" + + "\1\157\5\70\1\157\1\70\1\160\2\70\1\64\51\70" + + "\1\0\2\71\6\0\1\71\2\0\1\71\14\0\3\71" + + "\3\0\1\71\1\0\1\71\1\0\1\71\31\0\3\14" + + "\1\161\4\14\1\162\64\14\3\15\1\163\4\15\1\164" + + "\64\15\1\0\2\5\1\0\2\5\3\0\2\5\1\0" + + "\1\5\7\0\4\5\1\165\15\5\1\166\4\5\23\0" + + "\2\5\1\0\2\5\3\0\2\5\1\0\1\5\7\0" + + "\3\5\1\167\10\5\1\170\12\5\23\0\2\5\1\0" + + "\2\5\3\0\2\5\1\0\1\5\7\0\24\5\1\171" + + "\2\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0" + + "\1\5\7\0\2\5\1\172\24\5\23\0\2\5\1\0" + + "\2\5\3\0\2\5\1\0\1\5\7\0\13\5\1\173" + + "\13\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0" + + "\1\5\7\0\11\5\1\174\15\5\23\0\2\5\1\0" + + "\2\5\3\0\2\5\1\0\1\5\7\0\12\5\1\175" + + "\14\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0" + + "\1\5\7\0\10\5\1\176\16\5\23\0\2\5\1\0" + + "\2\5\3\0\2\5\1\0\1\5\7\0\12\5\1\177" + + "\14\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0" + + "\1\5\7\0\3\5\1\200\23\5\23\0\2\5\1\0" + + "\2\5\3\0\2\5\1\0\1\5\7\0\2\5\1\201" + + "\24\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0" + + "\1\5\7\0\14\5\1\202\12\5\23\0\2\5\1\0" + + "\2\5\3\0\2\5\1\0\1\5\7\0\10\5\1\203" + + "\16\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0" + + "\1\5\7\0\23\5\1\204\3\5\23\0\2\5\1\0" + + "\2\5\3\0\2\5\1\0\1\5\7\0\6\5\1\205" + + "\1\5\1\206\16\5\23\0\2\5\1\0\2\5\3\0" + + "\2\5\1\0\1\5\7\0\11\5\1\207\15\5\23\0" + + "\2\5\1\0\2\5\3\0\2\5\1\0\1\5\7\0" + + "\5\5\1\210\21\5\23\0\2\5\1\0\2\5\3\0" + + "\2\5\1\0\1\5\7\0\2\5\1\211\6\5\1\212" + + "\15\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0" + + "\1\5\7\0\12\5\1\213\14\5\23\0\2\5\1\0" + + "\2\5\3\0\2\5\1\0\1\5\7\0\2\5\1\214" + + "\24\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0" + + "\1\5\7\0\14\5\1\215\12\5\23\0\2\5\1\0" + + "\2\5\3\0\2\5\1\0\1\5\7\0\3\5\1\216" + + "\23\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0" + + "\1\5\7\0\14\5\1\217\12\5\23\0\2\5\1\0" + + "\2\5\3\0\2\5\1\0\1\5\7\0\2\5\1\220" + + "\24\5\75\0\1\221\74\0\1\222\74\0\1\223\3\0" + + "\1\224\70\0\1\225\22\0\1\152\7\0\1\152\107\0" + + "\2\153\12\0\1\153\11\0\1\153\22\0\7\154\1\226" + + "\65\154\6\227\1\230\1\155\65\227\23\157\1\64\2\156" + + "\12\157\1\156\11\157\1\156\45\157\1\64\51\157\10\70" + + "\1\157\5\70\1\157\4\70\1\64\51\70\3\14\1\161" + + "\4\14\1\162\6\14\1\74\1\75\64\14\1\0\6\14" + + "\1\74\1\75\54\14\3\15\1\163\4\15\1\164\7\15" + + "\1\76\1\77\63\15\1\0\7\15\1\76\1\77\53\15" + + "\1\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5" + + "\7\0\5\5\1\231\21\5\23\0\2\5\1\0\2\5" + + "\3\0\2\5\1\0\1\5\7\0\21\5\1\232\5\5" + + "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5" + + "\7\0\11\5\1\233\15\5\23\0\2\5\1\0\2\5" + + "\3\0\2\5\1\0\1\5\7\0\5\5\1\234\21\5" + + "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5" + + "\7\0\4\5\1\235\22\5\23\0\2\5\1\0\2\5" + + "\3\0\2\5\1\0\1\5\7\0\5\5\1\236\21\5" + + "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5" + + "\7\0\5\5\1\237\21\5\23\0\2\5\1\0\2\5" + + "\3\0\2\5\1\0\1\5\7\0\17\5\1\240\7\5" + + "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5" + + "\7\0\11\5\1\241\15\5\23\0\2\5\1\0\2\5" + + "\3\0\2\5\1\0\1\5\7\0\7\5\1\242\17\5" + + "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5" + + "\7\0\2\5\1\243\24\5\23\0\2\5\1\0\2\5" + + "\3\0\2\5\1\0\1\5\7\0\10\5\1\244\16\5" + + "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5" + + "\7\0\7\5\1\245\17\5\23\0\2\5\1\0\2\5" + + "\3\0\2\5\1\0\1\5\7\0\5\5\1\246\21\5" + + "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5" + + "\7\0\2\5\1\247\24\5\23\0\2\5\1\0\2\5" + + "\3\0\2\5\1\0\1\5\7\0\7\5\1\250\17\5" + + "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5" + + "\7\0\17\5\1\251\7\5\23\0\2\5\1\0\2\5" + + "\3\0\2\5\1\0\1\5\7\0\5\5\1\252\21\5" + + "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5" + + "\7\0\2\5\1\253\6\5\1\254\15\5\23\0\2\5" + + "\1\0\2\5\3\0\2\5\1\0\1\5\7\0\20\5" + + "\1\255\6\5\23\0\2\5\1\0\2\5\3\0\2\5" + + "\1\0\1\5\7\0\10\5\1\256\16\5\23\0\2\5" + + "\1\0\2\5\3\0\2\5\1\0\1\5\7\0\13\5" + + "\1\257\13\5\75\0\1\260\21\0\6\154\1\261\1\226" + + "\65\154\7\227\1\262\65\227\1\0\2\5\1\0\2\5" + + "\3\0\2\5\1\0\1\5\7\0\23\5\1\263\3\5" + + "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5" + + "\7\0\21\5\1\264\5\5\23\0\2\5\1\0\2\5" + + "\3\0\2\5\1\0\1\5\7\0\3\5\1\265\23\5" + + "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5" + + "\7\0\6\5\1\266\20\5\23\0\2\5\1\0\2\5" + + "\3\0\2\5\1\0\1\5\7\0\2\5\1\267\24\5" + + "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5" + + "\7\0\5\5\1\270\21\5\23\0\2\5\1\0\2\5" + + "\3\0\2\5\1\0\1\5\7\0\10\5\1\271\16\5" + + "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5" + + "\7\0\17\5\1\272\7\5\23\0\2\5\1\0\2\5" + + "\3\0\2\5\1\0\1\5\7\0\4\5\1\273\22\5" + + "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5" + + "\7\0\2\5\1\274\24\5\23\0\2\5\1\0\2\5" + + "\3\0\2\5\1\0\1\5\7\0\7\5\1\275\17\5" + + "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5" + + "\7\0\16\5\1\276\10\5\23\0\2\5\1\0\2\5" + + "\3\0\2\5\1\0\1\5\7\0\20\5\1\277\6\5" + + "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5" + + "\7\0\14\5\1\300\12\5\23\0\2\5\1\0\2\5" + + "\3\0\2\5\1\0\1\5\7\0\2\5\1\301\24\5" + + "\23\0\2\5\1\0\2\5\3\0\2\5\1\0\1\5" + + "\7\0\5\5\1\302\21\5\22\0\6\227\1\230\1\262" + + "\65\227\1\0\2\5\1\0\2\5\3\0\2\5\1\0" + + "\1\5\7\0\6\5\1\303\20\5\23\0\2\5\1\0" + + "\2\5\3\0\2\5\1\0\1\5\7\0\12\5\1\304" + + "\14\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0" + + "\1\5\7\0\14\5\1\305\12\5\23\0\2\5\1\0" + + "\2\5\3\0\2\5\1\0\1\5\7\0\14\5\1\306" + + "\12\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0" + + "\1\5\7\0\10\5\1\307\16\5\23\0\2\5\1\0" + + "\2\5\3\0\2\5\1\0\1\5\7\0\20\5\1\310" + + "\6\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0" + + "\1\5\7\0\10\5\1\311\16\5\23\0\2\5\1\0" + + "\2\5\3\0\2\5\1\0\1\5\7\0\5\5\1\312" + + "\21\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0" + + "\1\5\7\0\12\5\1\313\14\5\23\0\2\5\1\0" + + "\2\5\3\0\2\5\1\0\1\5\7\0\12\5\1\314" + + "\14\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0" + + "\1\5\7\0\12\5\1\315\14\5\23\0\2\5\1\0" + + "\2\5\3\0\2\5\1\0\1\5\7\0\21\5\1\316" + + "\5\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0" + + "\1\5\7\0\22\5\1\317\4\5\23\0\2\5\1\0" + + "\2\5\3\0\2\5\1\0\1\5\7\0\2\5\1\320" + + "\24\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0" + + "\1\5\7\0\17\5\1\321\7\5\23\0\2\5\1\0" + + "\2\5\3\0\2\5\1\0\1\5\7\0\4\5\1\322" + + "\22\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0" + + "\1\5\7\0\5\5\1\323\21\5\23\0\2\5\1\0" + + "\2\5\3\0\2\5\1\0\1\5\7\0\12\5\1\324" + + "\14\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0" + + "\1\5\7\0\5\5\1\325\21\5\23\0\2\5\1\0" + + "\2\5\3\0\2\5\1\0\1\5\7\0\5\5\1\326" + + "\21\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0" + + "\1\5\7\0\13\5\1\327\13\5\23\0\2\5\1\0" + + "\2\5\3\0\2\5\1\0\1\5\7\0\21\5\1\330" + + "\5\5\23\0\2\5\1\0\2\5\3\0\2\5\1\0" + + "\1\5\7\0\6\5\1\331\20\5\22\0"; + + private static int[] zzUnpackTrans() { + int[] result = new int[9211]; + int offset = 0; + offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); + return result; + } - /** this buffer contains the current text to be matched and is - the source of the yytext() string */ - private CharSequence zzBuffer = ""; + private static int zzUnpackTrans(String packed, int offset, int[] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + value--; + do result[j++] = value; + while (--count > 0); + } + return j; + } - /** the textposition at the last accepting state */ - private int zzMarkedPos; - /** the textposition at the last state to be included in yytext */ - private int zzPushbackPos; + /* error codes */ + private static final int ZZ_UNKNOWN_ERROR = 0; + private static final int ZZ_NO_MATCH = 1; + private static final int ZZ_PUSHBACK_2BIG = 2; + private static final char[] EMPTY_BUFFER = new char[0]; + private static final int YYEOF = -1; + + /* error messages for the codes above */ + private static final String ZZ_ERROR_MSG[] = { + "Unkown internal scanner error", + "Error: could not match input", + "Error: pushback value was too large" + }; + + /** + * ZZ_ATTRIBUTE[aState] contains the attributes of state aState + */ + private static final int[] ZZ_ATTRIBUTE = zzUnpackAttribute(); + + private static final String ZZ_ATTRIBUTE_PACKED_0 = + "\2\0\1\11\4\1\1\11\5\1\2\11\26\1\11\11" + + "\10\1\1\0\2\1\3\11\2\1\1\11\34\1\3\11" + + "\1\1\11\11\6\1\2\0\40\1\3\11\1\1\1\11" + + "\1\0\1\1\1\11\27\1\2\11\1\0\47\1"; + + private static int[] zzUnpackAttribute() { + int[] result = new int[217]; + int offset = 0; + offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); + return result; + } - /** the current text position in the buffer */ - private int zzCurrentPos; + private static int zzUnpackAttribute(String packed, int offset, int[] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; + while (--count > 0); + } + return j; + } - /** startRead marks the beginning of the yytext() string in the buffer */ - private int zzStartRead; + /** + * the current state of the DFA + */ + private int zzState; + + /** + * the current lexical state + */ + private int zzLexicalState = YYINITIAL; + + /** + * this buffer contains the current text to be matched and is + * the source of the yytext() string + */ + private CharSequence zzBuffer = ""; + + /** + * the textposition at the last accepting state + */ + private int zzMarkedPos; + + /** + * the textposition at the last state to be included in yytext + */ + private int zzPushbackPos; + + /** + * the current text position in the buffer + */ + private int zzCurrentPos; + + /** + * startRead marks the beginning of the yytext() string in the buffer + */ + private int zzStartRead; + + /** + * endRead marks the last character in the buffer, that has been read + * from input + */ + private int zzEndRead; + + /** + * zzAtBOL == true <=> the scanner is currently at the beginning of a line + */ + private boolean zzAtBOL = true; + + /** + * zzAtEOF == true <=> the scanner is at the EOF + */ + private boolean zzAtEOF; + + private IElementType myTokenType; + private int myState; + + /** + * denotes if the user-EOF-code has already been executed + */ + private boolean zzEOFDone; + + + /** + * Unpacks the compressed character translation table. + * + * @param packed the packed character translation table + * @return the unpacked character translation table + */ + private static char[] zzUnpackCMap(String packed) { + char[] map = new char[0x10000]; + int i = 0; /* index in packed string */ + int j = 0; /* index in unpacked array */ + while (i < 1772) { + int count = packed.charAt(i++); + char value = packed.charAt(i++); + do map[j++] = value; + while (--count > 0); + } + return map; + } - /** endRead marks the last character in the buffer, that has been read - from input */ - private int zzEndRead; + @Override + public IElementType getTokenType() { + if (myTokenType == null) { + locateToken(); + } + return myTokenType; + } - /** - * zzAtBOL == true <=> the scanner is currently at the beginning of a line - */ - private boolean zzAtBOL = true; + @Override + public final int getTokenStart() { + if (myTokenType == null) { + locateToken(); + } + return zzStartRead; + } - /** zzAtEOF == true <=> the scanner is at the EOF */ - private boolean zzAtEOF; + @Override + public final int getTokenEnd() { + if (myTokenType == null) { + locateToken(); + } + return getTokenStart() + yylength(); + } - private IElementType myTokenType; - private int myState; + @Override + public void advance() { + if (myTokenType == null) { + locateToken(); + } + myTokenType = null; + } - /** denotes if the user-EOF-code has already been executed */ - private boolean zzEOFDone; + @Override + public int getState() { + if (myTokenType == null) { + locateToken(); + } + return myState; + } + @Override + public void start(CharSequence buffer, int startOffset, int endOffset, int initialState) { + reset(buffer, startOffset, endOffset, initialState); + myTokenType = null; + } + @Override + public CharSequence getBufferSequence() { + return zzBuffer; + } - /** - * Unpacks the compressed character translation table. - * - * @param packed the packed character translation table - * @return the unpacked character translation table - */ - private static char [] zzUnpackCMap(String packed) { - char [] map = new char[0x10000]; - int i = 0; /* index in packed string */ - int j = 0; /* index in unpacked array */ - while (i < 1772) { - int count = packed.charAt(i++); - char value = packed.charAt(i++); - do map[j++] = value; while (--count > 0); + @Override + public int getBufferEnd() { + return zzEndRead; } - return map; - } - - @Override - public IElementType getTokenType() { - if (myTokenType == null) locateToken(); - return myTokenType; - } - - @Override - public final int getTokenStart(){ - if (myTokenType == null) locateToken(); - return zzStartRead; - } - - @Override - public final int getTokenEnd(){ - if (myTokenType == null) locateToken(); - return getTokenStart() + yylength(); - } - - @Override - public void advance() { - if (myTokenType == null) locateToken(); - myTokenType = null; - } - - @Override - public int getState() { - if (myTokenType == null) locateToken(); - return myState; - } - - @Override - public void start(final CharSequence buffer, int startOffset, int endOffset, final int initialState) { - reset(buffer, startOffset, endOffset, initialState); - myTokenType = null; - } - - @Override - public CharSequence getBufferSequence() { - return zzBuffer; - } - - @Override - public int getBufferEnd() { - return zzEndRead; - } - - public void reset(CharSequence buffer, int start, int end,int initialState){ - zzBuffer = buffer; - zzCurrentPos = zzMarkedPos = zzStartRead = start; - zzPushbackPos = 0; - zzAtEOF = false; - zzAtBOL = true; - zzEndRead = end; - yybegin(initialState); - myTokenType = null; - } - - private void locateToken() { - if (myTokenType != null) return; - try { - myState = yystate(); - myTokenType = advanceImpl(); - } - catch (java.io.IOException e) { /*Can't happen*/ } - catch (Error e) { - // add lexer class name to the error - final Error error = new Error(getClass().getName() + ": " + e.getMessage()); - error.setStackTrace(e.getStackTrace()); - throw error; - } - } - - /** - * Refills the input buffer. - * - * @return false, iff there was new input. - * - * @exception java.io.IOException if any I/O-Error occurs - */ - private boolean zzRefill() throws java.io.IOException { - return true; - } - - - /** - * Returns the current lexical state. - */ - public final int yystate() { - return zzLexicalState; - } - - - /** - * Enters a new lexical state - * - * @param newState the new lexical state - */ - public final void yybegin(int newState) { - zzLexicalState = newState; - } - - - /** - * Returns the text matched by the current regular expression. - */ - public final CharSequence yytext() { - return zzBuffer.subSequence(zzStartRead, zzMarkedPos); - } - - - /** - * Returns the character at position pos from the - * matched text. - * - * It is equivalent to yytext().charAt(pos), but faster - * - * @param pos the position of the character to fetch. - * A value from 0 to yylength()-1. - * - * @return the character at position pos - */ - public final char yycharat(int pos) { - return zzBuffer.charAt(zzStartRead+pos); - } - - - /** - * Returns the length of the matched text region. - */ - public final int yylength() { - return zzMarkedPos-zzStartRead; - } - - - /** - * Reports an error that occured while scanning. - * - * In a wellformed scanner (no or only correct usage of - * yypushback(int) and a match-all fallback rule) this method - * will only be called with things that "Can't Possibly Happen". - * If this method is called, something is seriously wrong - * (e.g. a JFlex bug producing a faulty scanner etc.). - * - * Usual syntax/scanner level error handling should be done - * in error fallback rules. - * - * @param errorCode the code of the errormessage to display - */ - private void zzScanError(int errorCode) { - String message; - try { - message = ZZ_ERROR_MSG[errorCode]; + + public void reset(CharSequence buffer, int start, int end, int initialState) { + zzBuffer = buffer; + zzCurrentPos = zzMarkedPos = zzStartRead = start; + zzPushbackPos = 0; + zzAtEOF = false; + zzAtBOL = true; + zzEndRead = end; + yybegin(initialState); + myTokenType = null; } - catch (ArrayIndexOutOfBoundsException e) { - message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; + + private void locateToken() { + if (myTokenType != null) { + return; + } + try { + myState = yystate(); + myTokenType = advanceImpl(); + } + catch (java.io.IOException e) { /*Can't happen*/ } + catch (Error e) { + // add lexer class name to the error + Error error = new Error(getClass().getName() + ": " + e.getMessage()); + error.setStackTrace(e.getStackTrace()); + throw error; + } } - throw new Error(message); - } - - - /** - * Pushes the specified amount of characters back into the input stream. - * - * They will be read again by then next call of the scanning method - * - * @param number the number of characters to be read again. - * This number must not be greater than yylength()! - */ - public void yypushback(int number) { - if ( number > yylength() ) - zzScanError(ZZ_PUSHBACK_2BIG); - - zzMarkedPos -= number; - } - - - /** - * Contains user EOF-code, which will be executed exactly once, - * when the end of file is reached - */ - private void zzDoEOF() { - if (!zzEOFDone) { - zzEOFDone = true; - + /** + * Refills the input buffer. + * + * @return false, iff there was new input. + * @throws java.io.IOException if any I/O-Error occurs + */ + private boolean zzRefill() throws java.io.IOException { + return true; } - } - /** - * Resumes scanning until the next regular expression is matched, - * the end of input is encountered or an I/O-Error occurs. - * - * @return the next token - * @exception java.io.IOException if any I/O-Error occurs - */ - public IElementType advanceImpl() throws java.io.IOException { - int zzInput; - int zzAction; + /** + * Returns the current lexical state. + */ + public final int yystate() { + return zzLexicalState; + } - // cached fields: - int zzCurrentPosL; - int zzMarkedPosL; - int zzEndReadL = zzEndRead; - CharSequence zzBufferL = zzBuffer; - char [] zzCMapL = ZZ_CMAP; - int [] zzTransL = ZZ_TRANS; - int [] zzRowMapL = ZZ_ROWMAP; - int [] zzAttrL = ZZ_ATTRIBUTE; + /** + * Enters a new lexical state + * + * @param newState the new lexical state + */ + public final void yybegin(int newState) { + zzLexicalState = newState; + } - while (true) { - zzMarkedPosL = zzMarkedPos; - zzAction = -1; + /** + * Returns the text matched by the current regular expression. + */ + public final CharSequence yytext() { + return zzBuffer.subSequence(zzStartRead, zzMarkedPos); + } - zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; - zzState = ZZ_LEXSTATE[zzLexicalState]; + /** + * Returns the character at position pos from the + * matched text. + *

+ * It is equivalent to yytext().charAt(pos), but faster + * + * @param pos the position of the character to fetch. + * A value from 0 to yylength()-1. + * @return the character at position pos + */ + public final char yycharat(int pos) { + return zzBuffer.charAt(zzStartRead + pos); + } - zzForAction: { - while (true) { + /** + * Returns the length of the matched text region. + */ + public final int yylength() { + return zzMarkedPos - zzStartRead; + } - if (zzCurrentPosL < zzEndReadL) - zzInput = zzBufferL.charAt(zzCurrentPosL++); - else if (zzAtEOF) { - zzInput = YYEOF; - break zzForAction; - } - else { - // store back cached positions - zzCurrentPos = zzCurrentPosL; - zzMarkedPos = zzMarkedPosL; - boolean eof = zzRefill(); - // get translated positions and possibly new buffer - zzCurrentPosL = zzCurrentPos; - zzMarkedPosL = zzMarkedPos; - zzBufferL = zzBuffer; - zzEndReadL = zzEndRead; - if (eof) { - zzInput = YYEOF; - break zzForAction; - } - else { - zzInput = zzBufferL.charAt(zzCurrentPosL++); - } - } - int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ]; - if (zzNext == -1) break zzForAction; - zzState = zzNext; - - int zzAttributes = zzAttrL[zzState]; - if ( (zzAttributes & 1) == 1 ) { - zzAction = zzState; - zzMarkedPosL = zzCurrentPosL; - if ( (zzAttributes & 8) == 8 ) break zzForAction; - } + /** + * Reports an error that occured while scanning. + *

+ * In a wellformed scanner (no or only correct usage of + * yypushback(int) and a match-all fallback rule) this method + * will only be called with things that "Can't Possibly Happen". + * If this method is called, something is seriously wrong + * (e.g. a JFlex bug producing a faulty scanner etc.). + *

+ * Usual syntax/scanner level error handling should be done + * in error fallback rules. + * + * @param errorCode the code of the errormessage to display + */ + private void zzScanError(int errorCode) { + String message; + try { + message = ZZ_ERROR_MSG[errorCode]; } - } + catch (ArrayIndexOutOfBoundsException e) { + message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; + } + + throw new Error(message); + } - // store back cached position - zzMarkedPos = zzMarkedPosL; - - switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { - case 88: - { yybegin(YYINITIAL); return JSTokenTypes.FUNCTION_KEYWORD; - } - case 92: break; - case 29: - { yybegin(YYINITIAL); return JSTokenTypes.COLON; - } - case 93: break; - case 4: - { return JSTokenTypes.WHITE_SPACE; - } - case 94: break; - case 32: - { return JSTokenTypes.REGEXP_LITERAL; - } - case 95: break; - case 81: - { yybegin(YYINITIAL); return JSTokenTypes.WHILE_KEYWORD; - } - case 96: break; - case 21: - { yybegin(YYINITIAL); return JSTokenTypes.LPAR; - } - case 97: break; - case 68: - { yybegin(DIV_OR_GT); return JSTokenTypes.TRUE_KEYWORD; - } - case 98: break; - case 44: - { yybegin(YYINITIAL); return JSTokenTypes.GE; - } - case 99: break; - case 84: - { yybegin(YYINITIAL); return JSTokenTypes.SWITCH_KEYWORD; - } - case 100: break; - case 34: - { return JSTokenTypes.C_STYLE_COMMENT; - } - case 101: break; - case 49: - { yybegin(YYINITIAL); return JSTokenTypes.OROR; - } - case 102: break; - case 56: - { return JSTokenTypes.DOC_COMMENT; - } - case 103: break; - case 58: - { yybegin(YYINITIAL); return JSTokenTypes.FOR_KEYWORD; - } - case 104: break; - case 65: - { yybegin(YYINITIAL); return JSTokenTypes.GTGTEQ; - } - case 105: break; - case 26: - { yybegin(YYINITIAL); return JSTokenTypes.COMMA; - } - case 106: break; - case 13: - { yybegin(YYINITIAL); return JSTokenTypes.EQ; - } - case 107: break; - case 37: - { yybegin(YYINITIAL); return JSTokenTypes.DO_KEYWORD; - } - case 108: break; - case 47: - { yybegin(YYINITIAL); return JSTokenTypes.ANDAND; - } - case 109: break; - case 43: - { return JSTokenTypes.PLUSPLUS; - } - case 110: break; - case 10: - { yybegin(YYINITIAL); return JSTokenTypes.STRING_LITERAL; - } - case 111: break; - case 3: - { yybegin(DIV_OR_GT); return JSTokenTypes.IDENTIFIER; - } - case 112: break; - case 5: - { return JSTokenTypes.DIV; - } - case 113: break; - case 25: - { yybegin(YYINITIAL); return JSTokenTypes.SEMICOLON; - } - case 114: break; - case 50: - { yybegin(YYINITIAL); return JSTokenTypes.XOREQ; - } - case 115: break; - case 82: - { yybegin(YYINITIAL); return JSTokenTypes.TYPEOF_KEYWORD; - } - case 116: break; - case 70: - { yybegin(YYINITIAL); return JSTokenTypes.ELSE_KEYWORD; - } - case 117: break; - case 67: - { yybegin(YYINITIAL); return JSTokenTypes.LTLTEQ; - } - case 118: break; - case 57: - { yybegin(YYINITIAL); return JSTokenTypes.TRY_KEYWORD; - } - case 119: break; - case 6: - { yybegin(YYINITIAL); return JSTokenTypes.MULT; - } - case 120: break; - case 53: - { yybegin(YYINITIAL); return JSTokenTypes.MULTEQ; - } - case 121: break; - case 17: - { yybegin(YYINITIAL); return JSTokenTypes.AND; - } - case 122: break; - case 59: - { yybegin(YYINITIAL); return JSTokenTypes.SET_KEYWORD; - } - case 123: break; - case 63: - { yybegin(YYINITIAL); return JSTokenTypes.EQEQEQ; - } - case 124: break; - case 69: - { yybegin(DIV_OR_GT); return JSTokenTypes.THIS_KEYWORD; - } - case 125: break; - case 36: - { yybegin(YYINITIAL); return JSTokenTypes.MINUSEQ; - } - case 126: break; - case 52: - { yybegin(YYINITIAL); return JSTokenTypes.DIVEQ; - } - case 127: break; - case 62: - { yybegin(YYINITIAL); return JSTokenTypes.GET_KEYWORD; - } - case 128: break; - case 61: - { yybegin(YYINITIAL); return JSTokenTypes.VAR_KEYWORD; - } - case 129: break; - case 15: - { yybegin(YYINITIAL); return JSTokenTypes.PLUS; - } - case 130: break; - case 33: - { return JSTokenTypes.END_OF_LINE_COMMENT; - } - case 131: break; - case 71: - { yybegin(DIV_OR_GT); return JSTokenTypes.NULL_KEYWORD; - } - case 132: break; - case 79: - { yybegin(YYINITIAL); return JSTokenTypes.CATCH_KEYWORD; - } - case 133: break; - case 40: - { yybegin(YYINITIAL); return JSTokenTypes.EQEQ; - } - case 134: break; - case 1: - { return JSTokenTypes.BAD_CHARACTER; - } - case 135: break; - case 86: - { yybegin(YYINITIAL); return JSTokenTypes.FINALLY_KEYWORD; - } - case 136: break; - case 85: - { yybegin(YYINITIAL); return JSTokenTypes.DELETE_KEYWORD; - } - case 137: break; - case 76: - { yybegin(YYINITIAL); return JSTokenTypes.THROW_KEYWORD; - } - case 138: break; - case 80: - { yybegin(YYINITIAL); return JSTokenTypes.CONST_KEYWORD; - } - case 139: break; - case 46: - { yybegin(YYINITIAL); return JSTokenTypes.ANDEQ; - } - case 140: break; - case 55: - { yybegin(YYINITIAL); return JSTokenTypes.LTLT; - } - case 141: break; - case 31: - { yybegin(YYINITIAL); return JSTokenTypes.LT; - } - case 142: break; - case 74: - { yybegin(YYINITIAL); return JSTokenTypes.VOID_KEYWORD; - } - case 143: break; - case 14: - { yybegin(YYINITIAL); return JSTokenTypes.EXCL; - } - case 144: break; - case 38: - { yybegin(YYINITIAL); return JSTokenTypes.IF_KEYWORD; - } - case 145: break; - case 64: - { yybegin(YYINITIAL); return JSTokenTypes.NEQEQ; - } - case 146: break; - case 42: - { yybegin(YYINITIAL); return JSTokenTypes.PLUSEQ; - } - case 147: break; - case 48: - { yybegin(YYINITIAL); return JSTokenTypes.OREQ; - } - case 148: break; - case 89: - { yybegin(YYINITIAL); return JSTokenTypes.CONTINUE_KEYWORD; - } - case 149: break; - case 66: - { yybegin(YYINITIAL); return JSTokenTypes.GTGTGT; - } - case 150: break; - case 45: - { yybegin(YYINITIAL); return JSTokenTypes.GTGT; - } - case 151: break; - case 27: - { yybegin(YYINITIAL); return JSTokenTypes.TILDE; - } - case 152: break; - case 87: - { yybegin(YYINITIAL); return JSTokenTypes.DEFAULT_KEYWORD; - } - case 153: break; - case 2: - { yybegin(DIV_OR_GT); return JSTokenTypes.NUMERIC_LITERAL; - } - case 154: break; - case 19: - { yybegin(YYINITIAL); return JSTokenTypes.XOR; - } - case 155: break; - case 30: - { yybegin(YYINITIAL); return JSTokenTypes.DIV; - } - case 156: break; - case 16: - { yybegin(YYINITIAL); return JSTokenTypes.GT; - } - case 157: break; - case 39: - { yybegin(YYINITIAL); return JSTokenTypes.IN_KEYWORD; - } - case 158: break; - case 83: - { yybegin(YYINITIAL); return JSTokenTypes.RETURN_KEYWORD; - } - case 159: break; - case 60: - { yybegin(YYINITIAL); return JSTokenTypes.NEW_KEYWORD; - } - case 160: break; - case 77: - { yybegin(DIV_OR_GT); return JSTokenTypes.FALSE_KEYWORD; - } - case 161: break; - case 9: - { return JSTokenTypes.SINGLE_QUOTE_STRING_LITERAL; - } - case 162: break; - case 18: - { yybegin(YYINITIAL); return JSTokenTypes.OR; - } - case 163: break; - case 51: - { yybegin(YYINITIAL); return JSTokenTypes.PERCEQ; - } - case 164: break; - case 8: - { yybegin(YYINITIAL); return JSTokenTypes.MINUS; - } - case 165: break; - case 35: - { return JSTokenTypes.MINUSMINUS; - } - case 166: break; - case 28: - { yybegin(YYINITIAL); return JSTokenTypes.QUEST; - } - case 167: break; - case 78: - { yybegin(YYINITIAL); return JSTokenTypes.BREAK_KEYWORD; - } - case 168: break; - case 7: - { yybegin(YYINITIAL); return JSTokenTypes.DOT; - } - case 169: break; - case 72: - { yybegin(YYINITIAL); return JSTokenTypes.CASE_KEYWORD; - } - case 170: break; - case 12: - { yybegin(DIV_OR_GT); return JSTokenTypes.RBRACKET; - } - case 171: break; - case 24: - { yybegin(YYINITIAL); return JSTokenTypes.RBRACE; - } - case 172: break; - case 91: - { yybegin(YYINITIAL); return JSTokenTypes.INSTANCEOF_KEYWORD; - } - case 173: break; - case 41: - { yybegin(YYINITIAL); return JSTokenTypes.NE; - } - case 174: break; - case 23: - { yybegin(YYINITIAL); return JSTokenTypes.LBRACE; - } - case 175: break; - case 22: - { yybegin(DIV_OR_GT); return JSTokenTypes.RPAR; - } - case 176: break; - case 20: - { yybegin(YYINITIAL); return JSTokenTypes.PERC; - } - case 177: break; - case 73: - { yybegin(YYINITIAL); return JSTokenTypes.WITH_KEYWORD; - } - case 178: break; - case 54: - { yybegin(YYINITIAL); return JSTokenTypes.LE; - } - case 179: break; - case 11: - { yybegin(YYINITIAL); return JSTokenTypes.LBRACKET; - } - case 180: break; - case 75: - { yybegin(YYINITIAL); return JSTokenTypes.GTGTGTEQ; - } - case 181: break; - case 90: - { yybegin(DIV_OR_GT); return JSTokenTypes.UNDEFINED_KEYWORD; - } - case 182: break; - default: - if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { - zzAtEOF = true; - zzDoEOF(); - return null; - } - else { - zzScanError(ZZ_NO_MATCH); - } + + /** + * Pushes the specified amount of characters back into the input stream. + *

+ * They will be read again by then next call of the scanning method + * + * @param number the number of characters to be read again. + * This number must not be greater than yylength()! + */ + public void yypushback(int number) { + if (number > yylength()) { + zzScanError(ZZ_PUSHBACK_2BIG); } + + zzMarkedPos -= number; + } + + + /** + * Contains user EOF-code, which will be executed exactly once, + * when the end of file is reached + */ + private void zzDoEOF() { + if (!zzEOFDone) { + zzEOFDone = true; + + } } - } + /** + * Resumes scanning until the next regular expression is matched, + * the end of input is encountered or an I/O-Error occurs. + * + * @return the next token + * @throws java.io.IOException if any I/O-Error occurs + */ + public IElementType advanceImpl() throws java.io.IOException { + int zzInput; + int zzAction; + + // cached fields: + int zzCurrentPosL; + int zzMarkedPosL; + int zzEndReadL = zzEndRead; + CharSequence zzBufferL = zzBuffer; + char[] zzCMapL = ZZ_CMAP; + + int[] zzTransL = ZZ_TRANS; + int[] zzRowMapL = ZZ_ROWMAP; + int[] zzAttrL = ZZ_ATTRIBUTE; + + while (true) { + zzMarkedPosL = zzMarkedPos; + + zzAction = -1; + + zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; + + zzState = ZZ_LEXSTATE[zzLexicalState]; + + + zzForAction: + { + while (true) { + + if (zzCurrentPosL < zzEndReadL) { + zzInput = zzBufferL.charAt(zzCurrentPosL++); + } + else if (zzAtEOF) { + zzInput = YYEOF; + break zzForAction; + } + else { + // store back cached positions + zzCurrentPos = zzCurrentPosL; + zzMarkedPos = zzMarkedPosL; + boolean eof = zzRefill(); + // get translated positions and possibly new buffer + zzCurrentPosL = zzCurrentPos; + zzMarkedPosL = zzMarkedPos; + zzBufferL = zzBuffer; + zzEndReadL = zzEndRead; + if (eof) { + zzInput = YYEOF; + break zzForAction; + } + else { + zzInput = zzBufferL.charAt(zzCurrentPosL++); + } + } + int zzNext = zzTransL[zzRowMapL[zzState] + zzCMapL[zzInput]]; + if (zzNext == -1) { + break zzForAction; + } + zzState = zzNext; + + int zzAttributes = zzAttrL[zzState]; + if ((zzAttributes & 1) == 1) { + zzAction = zzState; + zzMarkedPosL = zzCurrentPosL; + if ((zzAttributes & 8) == 8) { + break zzForAction; + } + } + + } + } + + // store back cached position + zzMarkedPos = zzMarkedPosL; + + switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { + case 88: { + yybegin(YYINITIAL); + return JSTokenTypes.FUNCTION_KEYWORD; + } + case 92: + break; + case 29: { + yybegin(YYINITIAL); + return JSTokenTypes.COLON; + } + case 93: + break; + case 4: { + return JSTokenTypes.WHITE_SPACE; + } + case 94: + break; + case 32: { + return JSTokenTypes.REGEXP_LITERAL; + } + case 95: + break; + case 81: { + yybegin(YYINITIAL); + return JSTokenTypes.WHILE_KEYWORD; + } + case 96: + break; + case 21: { + yybegin(YYINITIAL); + return JSTokenTypes.LPAR; + } + case 97: + break; + case 68: { + yybegin(DIV_OR_GT); + return JSTokenTypes.TRUE_KEYWORD; + } + case 98: + break; + case 44: { + yybegin(YYINITIAL); + return JSTokenTypes.GE; + } + case 99: + break; + case 84: { + yybegin(YYINITIAL); + return JSTokenTypes.SWITCH_KEYWORD; + } + case 100: + break; + case 34: { + return JSTokenTypes.C_STYLE_COMMENT; + } + case 101: + break; + case 49: { + yybegin(YYINITIAL); + return JSTokenTypes.OROR; + } + case 102: + break; + case 56: { + return JSTokenTypes.DOC_COMMENT; + } + case 103: + break; + case 58: { + yybegin(YYINITIAL); + return JSTokenTypes.FOR_KEYWORD; + } + case 104: + break; + case 65: { + yybegin(YYINITIAL); + return JSTokenTypes.GTGTEQ; + } + case 105: + break; + case 26: { + yybegin(YYINITIAL); + return JSTokenTypes.COMMA; + } + case 106: + break; + case 13: { + yybegin(YYINITIAL); + return JSTokenTypes.EQ; + } + case 107: + break; + case 37: { + yybegin(YYINITIAL); + return JSTokenTypes.DO_KEYWORD; + } + case 108: + break; + case 47: { + yybegin(YYINITIAL); + return JSTokenTypes.ANDAND; + } + case 109: + break; + case 43: { + return JSTokenTypes.PLUSPLUS; + } + case 110: + break; + case 10: { + yybegin(YYINITIAL); + return JSTokenTypes.STRING_LITERAL; + } + case 111: + break; + case 3: { + yybegin(DIV_OR_GT); + return JSTokenTypes.IDENTIFIER; + } + case 112: + break; + case 5: { + return JSTokenTypes.DIV; + } + case 113: + break; + case 25: { + yybegin(YYINITIAL); + return JSTokenTypes.SEMICOLON; + } + case 114: + break; + case 50: { + yybegin(YYINITIAL); + return JSTokenTypes.XOREQ; + } + case 115: + break; + case 82: { + yybegin(YYINITIAL); + return JSTokenTypes.TYPEOF_KEYWORD; + } + case 116: + break; + case 70: { + yybegin(YYINITIAL); + return JSTokenTypes.ELSE_KEYWORD; + } + case 117: + break; + case 67: { + yybegin(YYINITIAL); + return JSTokenTypes.LTLTEQ; + } + case 118: + break; + case 57: { + yybegin(YYINITIAL); + return JSTokenTypes.TRY_KEYWORD; + } + case 119: + break; + case 6: { + yybegin(YYINITIAL); + return JSTokenTypes.MULT; + } + case 120: + break; + case 53: { + yybegin(YYINITIAL); + return JSTokenTypes.MULTEQ; + } + case 121: + break; + case 17: { + yybegin(YYINITIAL); + return JSTokenTypes.AND; + } + case 122: + break; + case 59: { + yybegin(YYINITIAL); + return JSTokenTypes.SET_KEYWORD; + } + case 123: + break; + case 63: { + yybegin(YYINITIAL); + return JSTokenTypes.EQEQEQ; + } + case 124: + break; + case 69: { + yybegin(DIV_OR_GT); + return JSTokenTypes.THIS_KEYWORD; + } + case 125: + break; + case 36: { + yybegin(YYINITIAL); + return JSTokenTypes.MINUSEQ; + } + case 126: + break; + case 52: { + yybegin(YYINITIAL); + return JSTokenTypes.DIVEQ; + } + case 127: + break; + case 62: { + yybegin(YYINITIAL); + return JSTokenTypes.GET_KEYWORD; + } + case 128: + break; + case 61: { + yybegin(YYINITIAL); + return JSTokenTypes.VAR_KEYWORD; + } + case 129: + break; + case 15: { + yybegin(YYINITIAL); + return JSTokenTypes.PLUS; + } + case 130: + break; + case 33: { + return JSTokenTypes.END_OF_LINE_COMMENT; + } + case 131: + break; + case 71: { + yybegin(DIV_OR_GT); + return JSTokenTypes.NULL_KEYWORD; + } + case 132: + break; + case 79: { + yybegin(YYINITIAL); + return JSTokenTypes.CATCH_KEYWORD; + } + case 133: + break; + case 40: { + yybegin(YYINITIAL); + return JSTokenTypes.EQEQ; + } + case 134: + break; + case 1: { + return JSTokenTypes.BAD_CHARACTER; + } + case 135: + break; + case 86: { + yybegin(YYINITIAL); + return JSTokenTypes.FINALLY_KEYWORD; + } + case 136: + break; + case 85: { + yybegin(YYINITIAL); + return JSTokenTypes.DELETE_KEYWORD; + } + case 137: + break; + case 76: { + yybegin(YYINITIAL); + return JSTokenTypes.THROW_KEYWORD; + } + case 138: + break; + case 80: { + yybegin(YYINITIAL); + return JSTokenTypes.CONST_KEYWORD; + } + case 139: + break; + case 46: { + yybegin(YYINITIAL); + return JSTokenTypes.ANDEQ; + } + case 140: + break; + case 55: { + yybegin(YYINITIAL); + return JSTokenTypes.LTLT; + } + case 141: + break; + case 31: { + yybegin(YYINITIAL); + return JSTokenTypes.LT; + } + case 142: + break; + case 74: { + yybegin(YYINITIAL); + return JSTokenTypes.VOID_KEYWORD; + } + case 143: + break; + case 14: { + yybegin(YYINITIAL); + return JSTokenTypes.EXCL; + } + case 144: + break; + case 38: { + yybegin(YYINITIAL); + return JSTokenTypes.IF_KEYWORD; + } + case 145: + break; + case 64: { + yybegin(YYINITIAL); + return JSTokenTypes.NEQEQ; + } + case 146: + break; + case 42: { + yybegin(YYINITIAL); + return JSTokenTypes.PLUSEQ; + } + case 147: + break; + case 48: { + yybegin(YYINITIAL); + return JSTokenTypes.OREQ; + } + case 148: + break; + case 89: { + yybegin(YYINITIAL); + return JSTokenTypes.CONTINUE_KEYWORD; + } + case 149: + break; + case 66: { + yybegin(YYINITIAL); + return JSTokenTypes.GTGTGT; + } + case 150: + break; + case 45: { + yybegin(YYINITIAL); + return JSTokenTypes.GTGT; + } + case 151: + break; + case 27: { + yybegin(YYINITIAL); + return JSTokenTypes.TILDE; + } + case 152: + break; + case 87: { + yybegin(YYINITIAL); + return JSTokenTypes.DEFAULT_KEYWORD; + } + case 153: + break; + case 2: { + yybegin(DIV_OR_GT); + return JSTokenTypes.NUMERIC_LITERAL; + } + case 154: + break; + case 19: { + yybegin(YYINITIAL); + return JSTokenTypes.XOR; + } + case 155: + break; + case 30: { + yybegin(YYINITIAL); + return JSTokenTypes.DIV; + } + case 156: + break; + case 16: { + yybegin(YYINITIAL); + return JSTokenTypes.GT; + } + case 157: + break; + case 39: { + yybegin(YYINITIAL); + return JSTokenTypes.IN_KEYWORD; + } + case 158: + break; + case 83: { + yybegin(YYINITIAL); + return JSTokenTypes.RETURN_KEYWORD; + } + case 159: + break; + case 60: { + yybegin(YYINITIAL); + return JSTokenTypes.NEW_KEYWORD; + } + case 160: + break; + case 77: { + yybegin(DIV_OR_GT); + return JSTokenTypes.FALSE_KEYWORD; + } + case 161: + break; + case 9: { + return JSTokenTypes.SINGLE_QUOTE_STRING_LITERAL; + } + case 162: + break; + case 18: { + yybegin(YYINITIAL); + return JSTokenTypes.OR; + } + case 163: + break; + case 51: { + yybegin(YYINITIAL); + return JSTokenTypes.PERCEQ; + } + case 164: + break; + case 8: { + yybegin(YYINITIAL); + return JSTokenTypes.MINUS; + } + case 165: + break; + case 35: { + return JSTokenTypes.MINUSMINUS; + } + case 166: + break; + case 28: { + yybegin(YYINITIAL); + return JSTokenTypes.QUEST; + } + case 167: + break; + case 78: { + yybegin(YYINITIAL); + return JSTokenTypes.BREAK_KEYWORD; + } + case 168: + break; + case 7: { + yybegin(YYINITIAL); + return JSTokenTypes.DOT; + } + case 169: + break; + case 72: { + yybegin(YYINITIAL); + return JSTokenTypes.CASE_KEYWORD; + } + case 170: + break; + case 12: { + yybegin(DIV_OR_GT); + return JSTokenTypes.RBRACKET; + } + case 171: + break; + case 24: { + yybegin(YYINITIAL); + return JSTokenTypes.RBRACE; + } + case 172: + break; + case 91: { + yybegin(YYINITIAL); + return JSTokenTypes.INSTANCEOF_KEYWORD; + } + case 173: + break; + case 41: { + yybegin(YYINITIAL); + return JSTokenTypes.NE; + } + case 174: + break; + case 23: { + yybegin(YYINITIAL); + return JSTokenTypes.LBRACE; + } + case 175: + break; + case 22: { + yybegin(DIV_OR_GT); + return JSTokenTypes.RPAR; + } + case 176: + break; + case 20: { + yybegin(YYINITIAL); + return JSTokenTypes.PERC; + } + case 177: + break; + case 73: { + yybegin(YYINITIAL); + return JSTokenTypes.WITH_KEYWORD; + } + case 178: + break; + case 54: { + yybegin(YYINITIAL); + return JSTokenTypes.LE; + } + case 179: + break; + case 11: { + yybegin(YYINITIAL); + return JSTokenTypes.LBRACKET; + } + case 180: + break; + case 75: { + yybegin(YYINITIAL); + return JSTokenTypes.GTGTGTEQ; + } + case 181: + break; + case 90: { + yybegin(DIV_OR_GT); + return JSTokenTypes.UNDEFINED_KEYWORD; + } + case 182: + break; + default: + if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { + zzAtEOF = true; + zzDoEOF(); + return null; + } + else { + zzScanError(ZZ_NO_MATCH); + } + } + } + } } diff --git a/lang-version-impl/javascript16-impl/src/main/java/module-info.java b/lang-version-impl/javascript16-impl/src/main/java/module-info.java index 76447d51..34b49fec 100644 --- a/lang-version-impl/javascript16-impl/src/main/java/module-info.java +++ b/lang-version-impl/javascript16-impl/src/main/java/module-info.java @@ -2,10 +2,9 @@ * @author VISTALL * @since 23-Aug-22 */ -module consulo.javascript.javascript16.impl -{ - requires transitive consulo.javascript.base.impl; +module consulo.javascript.javascript16.impl { + requires transitive consulo.javascript.base.impl; - exports consulo.javascript.javascript16.lang; - exports consulo.javascript.javascript16.lang.lexer; + exports consulo.javascript.javascript16.lang; + exports consulo.javascript.javascript16.lang.lexer; } \ No newline at end of file diff --git a/lang-version-impl/javascript17-impl/pom.xml b/lang-version-impl/javascript17-impl/pom.xml index 07a4cd2b..5682cc44 100644 --- a/lang-version-impl/javascript17-impl/pom.xml +++ b/lang-version-impl/javascript17-impl/pom.xml @@ -32,7 +32,7 @@ consulo - https://maven.consulo.io/repository/snapshots/ + https://maven.consulo.dev/repository/snapshots/ true interval:60 diff --git a/lang-version-impl/javascript17-impl/src/main/java/consulo/javascript/javascript17/lang/JavaScript17LanguageVersion.java b/lang-version-impl/javascript17-impl/src/main/java/consulo/javascript/javascript17/lang/JavaScript17LanguageVersion.java index 349dbc1e..bc892773 100644 --- a/lang-version-impl/javascript17-impl/src/main/java/consulo/javascript/javascript17/lang/JavaScript17LanguageVersion.java +++ b/lang-version-impl/javascript17-impl/src/main/java/consulo/javascript/javascript17/lang/JavaScript17LanguageVersion.java @@ -21,11 +21,12 @@ import consulo.javascript.javascript17.lang.lexer.JavaScript17Lexer; import consulo.javascript.lang.BaseJavaScriptLanguageVersion; import consulo.javascript.language.JavaScriptLanguage; -import consulo.javascript.language.StandardJavaScriptVersions; +import consulo.javascript.language.StandardJavaScriptVersion; import consulo.language.editor.highlight.SyntaxHighlighter; import consulo.language.lexer.Lexer; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; + import java.util.function.Supplier; /** @@ -33,45 +34,38 @@ * @since 11.12.2015 */ @ExtensionImpl -public class JavaScript17LanguageVersion extends BaseJavaScriptLanguageVersion implements StandardJavaScriptVersions.Marker -{ - private static final Supplier ourLexerFactory = JavaScript17Lexer::new; +public class JavaScript17LanguageVersion extends BaseJavaScriptLanguageVersion implements StandardJavaScriptVersion { + private static final Supplier ourLexerFactory = JavaScript17Lexer::new; - @Nonnull - public static JavaScript17LanguageVersion getInstance() - { - return JavaScriptLanguage.INSTANCE.findVersionByClass(JavaScript17LanguageVersion.class); - } + @Nonnull + public static JavaScript17LanguageVersion getInstance() { + return JavaScriptLanguage.INSTANCE.findVersionByClass(JavaScript17LanguageVersion.class); + } - public JavaScript17LanguageVersion() - { - super("JAVASCRIPT_1_7"); - } + public JavaScript17LanguageVersion() { + super("JAVASCRIPT_1_7"); + } - @Nonnull - @Override - public String getPresentableName() - { - return "JavaScript 1.7"; - } + @Nonnull + @Override + public String getPresentableName() { + return "JavaScript 1.7"; + } - @Nonnull - @Override - public Lexer createLexer() - { - return ourLexerFactory.get(); - } + @Nonnull + @Override + public Lexer createLexer() { + return ourLexerFactory.get(); + } - @Nonnull - @Override - public SyntaxHighlighter getSyntaxHighlighter() - { - return new JavaScriptHighlighter(ourLexerFactory); - } + @Nonnull + @Override + public SyntaxHighlighter getSyntaxHighlighter() { + return new JavaScriptHighlighter(ourLexerFactory); + } - @Override - public int getWeight() - { - return 20; - } + @Override + public int getWeight() { + return 20; + } } \ No newline at end of file diff --git a/lang-version-impl/javascript17-impl/src/main/java/consulo/javascript/javascript17/lang/lexer/JavaScript17Lexer.java b/lang-version-impl/javascript17-impl/src/main/java/consulo/javascript/javascript17/lang/lexer/JavaScript17Lexer.java index 072f173c..71c3eb15 100644 --- a/lang-version-impl/javascript17-impl/src/main/java/consulo/javascript/javascript17/lang/lexer/JavaScript17Lexer.java +++ b/lang-version-impl/javascript17-impl/src/main/java/consulo/javascript/javascript17/lang/lexer/JavaScript17Lexer.java @@ -8,1220 +8,1438 @@ /** - * This class is a scanner generated by + * This class is a scanner generated by * JFlex 1.4.4 * on 12.02.16 16:59 from the specification file * R:/_github.com/consulo/consulo-javascript/javascript17-impl/src/org/mustbe/consulo/javascript/lang/lexer/javascript17.flex */ public class JavaScript17Lexer extends LexerBase { - /** initial size of the lookahead buffer */ - private static final int ZZ_BUFFERSIZE = 16384; - - /** lexical states */ - public static final int DIV_OR_GT = 2; - public static final int YYINITIAL = 0; - public static final int LAST_STATE = 4; - - /** - * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l - * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l - * at the beginning of a line - * l is of the form l = 2*k, k a non negative integer - */ - private static final int ZZ_LEXSTATE[] = { - 0, 0, 1, 1, 2, 2 - }; - - /** - * Translates characters to character classes - */ - private static final String ZZ_CMAP_PACKED = - "\11\5\1\3\1\16\1\0\1\3\1\10\16\5\4\0\1\3\1\54"+ - "\1\21\1\0\1\4\1\63\1\60\1\17\1\64\1\65\1\7\1\55"+ - "\1\71\1\15\1\13\1\6\1\11\7\1\2\1\1\74\1\70\1\56"+ - "\1\53\1\57\1\73\1\0\4\2\1\14\1\2\21\4\1\12\2\4"+ - "\1\22\1\20\1\23\1\62\1\4\1\0\1\33\1\41\1\43\1\37"+ - "\1\31\1\32\1\52\1\44\1\40\1\4\1\42\1\34\1\24\1\36"+ - "\1\45\1\50\1\4\1\27\1\35\1\26\1\30\1\51\1\47\1\25"+ - "\1\46\1\4\1\66\1\61\1\67\1\72\41\5\2\0\4\4\4\0"+ - "\1\4\2\0\1\5\7\0\1\4\4\0\1\4\5\0\27\4\1\0"+ - "\37\4\1\0\u013f\4\31\0\162\4\4\0\14\4\16\0\5\4\11\0"+ - "\1\4\21\0\130\5\5\0\23\5\12\0\1\4\13\0\1\4\1\0"+ - "\3\4\1\0\1\4\1\0\24\4\1\0\54\4\1\0\46\4\1\0"+ - "\5\4\4\0\202\4\1\0\4\5\3\0\105\4\1\0\46\4\2\0"+ - "\2\4\6\0\20\4\41\0\46\4\2\0\1\4\7\0\47\4\11\0"+ - "\21\5\1\0\27\5\1\0\3\5\1\0\1\5\1\0\2\5\1\0"+ - "\1\5\13\0\33\4\5\0\3\4\15\0\4\5\14\0\6\5\13\0"+ - "\32\4\5\0\13\4\16\5\7\0\12\5\4\0\2\4\1\5\143\4"+ - "\1\0\1\4\10\5\1\0\6\5\2\4\2\5\1\0\4\5\2\4"+ - "\12\5\3\4\2\0\1\4\17\0\1\5\1\4\1\5\36\4\33\5"+ - "\2\0\3\4\60\0\46\4\13\5\1\4\u014f\0\3\5\66\4\2\0"+ - "\1\5\1\4\20\5\2\0\1\4\4\5\3\0\12\4\2\5\2\0"+ - "\12\5\21\0\3\5\1\0\10\4\2\0\2\4\2\0\26\4\1\0"+ - "\7\4\1\0\1\4\3\0\4\4\2\0\1\5\1\4\7\5\2\0"+ - "\2\5\2\0\3\5\11\0\1\5\4\0\2\4\1\0\3\4\2\5"+ - "\2\0\12\5\4\4\15\0\3\5\1\0\6\4\4\0\2\4\2\0"+ - "\26\4\1\0\7\4\1\0\2\4\1\0\2\4\1\0\2\4\2\0"+ - "\1\5\1\0\5\5\4\0\2\5\2\0\3\5\13\0\4\4\1\0"+ - "\1\4\7\0\14\5\3\4\14\0\3\5\1\0\11\4\1\0\3\4"+ - "\1\0\26\4\1\0\7\4\1\0\2\4\1\0\5\4\2\0\1\5"+ - "\1\4\10\5\1\0\3\5\1\0\3\5\2\0\1\4\17\0\2\4"+ - "\2\5\2\0\12\5\1\0\1\4\17\0\3\5\1\0\10\4\2\0"+ - "\2\4\2\0\26\4\1\0\7\4\1\0\2\4\1\0\5\4\2\0"+ - "\1\5\1\4\6\5\3\0\2\5\2\0\3\5\10\0\2\5\4\0"+ - "\2\4\1\0\3\4\4\0\12\5\1\0\1\4\20\0\1\5\1\4"+ - "\1\0\6\4\3\0\3\4\1\0\4\4\3\0\2\4\1\0\1\4"+ - "\1\0\2\4\3\0\2\4\3\0\3\4\3\0\10\4\1\0\3\4"+ - "\4\0\5\5\3\0\3\5\1\0\4\5\11\0\1\5\17\0\11\5"+ - "\11\0\1\4\7\0\3\5\1\0\10\4\1\0\3\4\1\0\27\4"+ - "\1\0\12\4\1\0\5\4\4\0\7\5\1\0\3\5\1\0\4\5"+ - "\7\0\2\5\11\0\2\4\4\0\12\5\22\0\2\5\1\0\10\4"+ - "\1\0\3\4\1\0\27\4\1\0\12\4\1\0\5\4\2\0\1\5"+ - "\1\4\7\5\1\0\3\5\1\0\4\5\7\0\2\5\7\0\1\4"+ - "\1\0\2\4\4\0\12\5\22\0\2\5\1\0\10\4\1\0\3\4"+ - "\1\0\27\4\1\0\20\4\4\0\6\5\2\0\3\5\1\0\4\5"+ - "\11\0\1\5\10\0\2\4\4\0\12\5\22\0\2\5\1\0\22\4"+ - "\3\0\30\4\1\0\11\4\1\0\1\4\2\0\7\4\3\0\1\5"+ - "\4\0\6\5\1\0\1\5\1\0\10\5\22\0\2\5\15\0\60\4"+ - "\1\5\2\4\7\5\4\0\10\4\10\5\1\0\12\5\47\0\2\4"+ - "\1\0\1\4\2\0\2\4\1\0\1\4\2\0\1\4\6\0\4\4"+ - "\1\0\7\4\1\0\3\4\1\0\1\4\1\0\1\4\2\0\2\4"+ - "\1\0\4\4\1\5\2\4\6\5\1\0\2\5\1\4\2\0\5\4"+ - "\1\0\1\4\1\0\6\5\2\0\12\5\2\0\2\4\42\0\1\4"+ - "\27\0\2\5\6\0\12\5\13\0\1\5\1\0\1\5\1\0\1\5"+ - "\4\0\2\5\10\4\1\0\42\4\6\0\24\5\1\0\2\5\4\4"+ - "\4\0\10\5\1\0\44\5\11\0\1\5\71\0\42\4\1\0\5\4"+ - "\1\0\2\4\1\0\7\5\3\0\4\5\6\0\12\5\6\0\6\4"+ - "\4\5\106\0\46\4\12\0\51\4\7\0\132\4\5\0\104\4\5\0"+ - "\122\4\6\0\7\4\1\0\77\4\1\0\1\4\1\0\4\4\2\0"+ - "\7\4\1\0\1\4\1\0\4\4\2\0\47\4\1\0\1\4\1\0"+ - "\4\4\2\0\37\4\1\0\1\4\1\0\4\4\2\0\7\4\1\0"+ - "\1\4\1\0\4\4\2\0\7\4\1\0\7\4\1\0\27\4\1\0"+ - "\37\4\1\0\1\4\1\0\4\4\2\0\7\4\1\0\47\4\1\0"+ - "\23\4\16\0\11\5\56\0\125\4\14\0\u026c\4\2\0\10\4\12\0"+ - "\32\4\5\0\113\4\3\0\3\4\17\0\15\4\1\0\4\4\3\5"+ - "\13\0\22\4\3\5\13\0\22\4\2\5\14\0\15\4\1\0\3\4"+ - "\1\0\2\5\14\0\64\4\40\5\3\0\1\4\3\0\2\4\1\5"+ - "\2\0\12\5\41\0\3\5\2\0\12\5\6\0\130\4\10\0\51\4"+ - "\1\5\126\0\35\4\3\0\14\5\4\0\14\5\12\0\12\5\36\4"+ - "\2\0\5\4\u038b\0\154\4\224\0\234\4\4\0\132\4\6\0\26\4"+ - "\2\0\6\4\2\0\46\4\2\0\6\4\2\0\10\4\1\0\1\4"+ - "\1\0\1\4\1\0\1\4\1\0\37\4\2\0\65\4\1\0\7\4"+ - "\1\0\1\4\3\0\3\4\1\0\7\4\3\0\4\4\2\0\6\4"+ - "\4\0\15\4\5\0\3\4\1\0\7\4\17\0\4\5\32\0\5\5"+ - "\20\0\2\4\23\0\1\4\13\0\4\5\6\0\6\5\1\0\1\4"+ - "\15\0\1\4\40\0\22\4\36\0\15\5\4\0\1\5\3\0\6\5"+ - "\27\0\1\4\4\0\1\4\2\0\12\4\1\0\1\4\3\0\5\4"+ - "\6\0\1\4\1\0\1\4\1\0\1\4\1\0\4\4\1\0\3\4"+ - "\1\0\7\4\3\0\3\4\5\0\5\4\26\0\44\4\u0e81\0\3\4"+ - "\31\0\11\4\6\5\1\0\5\4\2\0\5\4\4\0\126\4\2\0"+ - "\2\5\2\0\3\4\1\0\137\4\5\0\50\4\4\0\136\4\21\0"+ - "\30\4\70\0\20\4\u0200\0\u19b6\4\112\0\u51a6\4\132\0\u048d\4\u0773\0"+ - "\u2ba4\4\u215c\0\u012e\4\2\0\73\4\225\0\7\4\14\0\5\4\5\0"+ - "\1\4\1\5\12\4\1\0\15\4\1\0\5\4\1\0\1\4\1\0"+ - "\2\4\1\0\2\4\1\0\154\4\41\0\u016b\4\22\0\100\4\2\0"+ - "\66\4\50\0\15\4\3\0\20\5\20\0\4\5\17\0\2\4\30\0"+ - "\3\4\31\0\1\4\6\0\5\4\1\0\207\4\2\0\1\5\4\0"+ - "\1\4\13\0\12\5\7\0\32\4\4\0\1\4\1\0\32\4\12\0"+ - "\132\4\3\0\6\4\2\0\6\4\2\0\6\4\2\0\3\4\3\0"+ - "\2\4\3\0\2\4\22\0\3\5\4\0"; - - /** - * Translates characters to character classes - */ - private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); - - /** - * Translates DFA states to action switch labels. - */ - private static final int [] ZZ_ACTION = zzUnpackAction(); - - private static final String ZZ_ACTION_PACKED_0 = - "\3\0\1\1\1\2\1\3\1\4\1\5\1\6\1\2"+ - "\1\7\1\10\1\11\1\12\1\13\1\14\20\3\1\15"+ - "\1\16\1\17\1\20\1\21\1\22\1\23\1\24\1\25"+ - "\1\26\1\27\1\30\1\31\1\32\1\33\1\34\1\35"+ - "\1\36\1\6\1\37\2\2\1\40\1\41\1\42\1\0"+ - "\1\40\1\2\1\43\1\44\2\11\2\12\20\3\1\45"+ - "\1\46\1\47\11\3\1\50\1\51\1\52\1\53\1\54"+ - "\1\55\1\56\1\57\1\60\1\61\1\62\1\63\1\64"+ - "\1\65\1\66\1\67\1\2\1\40\1\42\1\70\1\40"+ - "\2\0\2\11\2\12\1\3\1\71\11\3\1\72\1\73"+ - "\1\74\2\3\1\75\12\3\1\76\1\3\1\77\1\100"+ - "\1\101\1\102\1\103\1\104\1\0\2\70\1\105\1\3"+ - "\1\106\3\3\1\107\4\3\1\110\5\3\1\111\3\3"+ - "\1\112\1\3\1\113\1\114\1\42\1\0\1\115\4\3"+ - "\1\116\5\3\1\117\1\120\1\3\1\121\1\122\1\123"+ - "\1\124\1\125\3\3\1\126\1\3\1\127\4\3\1\130"+ - "\1\131\3\3\1\132\1\3\1\133\1\134\1\3\1\135"; - - private static int [] zzUnpackAction() { - int [] result = new int[226]; - int offset = 0; - offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); - return result; - } - - private static int zzUnpackAction(String packed, int offset, int [] result) { - int i = 0; /* index in packed string */ - int j = offset; /* index in unpacked array */ - int l = packed.length(); - while (i < l) { - int count = packed.charAt(i++); - int value = packed.charAt(i++); - do result[j++] = value; while (--count > 0); + /** + * initial size of the lookahead buffer + */ + private static final int ZZ_BUFFERSIZE = 16384; + + /** + * lexical states + */ + public static final int DIV_OR_GT = 2; + public static final int YYINITIAL = 0; + public static final int LAST_STATE = 4; + + /** + * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l + * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l + * at the beginning of a line + * l is of the form l = 2*k, k a non negative integer + */ + private static final int ZZ_LEXSTATE[] = { + 0, 0, 1, 1, 2, 2 + }; + + /** + * Translates characters to character classes + */ + private static final String ZZ_CMAP_PACKED = + "\11\5\1\3\1\16\1\0\1\3\1\10\16\5\4\0\1\3\1\54" + + "\1\21\1\0\1\4\1\63\1\60\1\17\1\64\1\65\1\7\1\55" + + "\1\71\1\15\1\13\1\6\1\11\7\1\2\1\1\74\1\70\1\56" + + "\1\53\1\57\1\73\1\0\4\2\1\14\1\2\21\4\1\12\2\4" + + "\1\22\1\20\1\23\1\62\1\4\1\0\1\33\1\41\1\43\1\37" + + "\1\31\1\32\1\52\1\44\1\40\1\4\1\42\1\34\1\24\1\36" + + "\1\45\1\50\1\4\1\27\1\35\1\26\1\30\1\51\1\47\1\25" + + "\1\46\1\4\1\66\1\61\1\67\1\72\41\5\2\0\4\4\4\0" + + "\1\4\2\0\1\5\7\0\1\4\4\0\1\4\5\0\27\4\1\0" + + "\37\4\1\0\u013f\4\31\0\162\4\4\0\14\4\16\0\5\4\11\0" + + "\1\4\21\0\130\5\5\0\23\5\12\0\1\4\13\0\1\4\1\0" + + "\3\4\1\0\1\4\1\0\24\4\1\0\54\4\1\0\46\4\1\0" + + "\5\4\4\0\202\4\1\0\4\5\3\0\105\4\1\0\46\4\2\0" + + "\2\4\6\0\20\4\41\0\46\4\2\0\1\4\7\0\47\4\11\0" + + "\21\5\1\0\27\5\1\0\3\5\1\0\1\5\1\0\2\5\1\0" + + "\1\5\13\0\33\4\5\0\3\4\15\0\4\5\14\0\6\5\13\0" + + "\32\4\5\0\13\4\16\5\7\0\12\5\4\0\2\4\1\5\143\4" + + "\1\0\1\4\10\5\1\0\6\5\2\4\2\5\1\0\4\5\2\4" + + "\12\5\3\4\2\0\1\4\17\0\1\5\1\4\1\5\36\4\33\5" + + "\2\0\3\4\60\0\46\4\13\5\1\4\u014f\0\3\5\66\4\2\0" + + "\1\5\1\4\20\5\2\0\1\4\4\5\3\0\12\4\2\5\2\0" + + "\12\5\21\0\3\5\1\0\10\4\2\0\2\4\2\0\26\4\1\0" + + "\7\4\1\0\1\4\3\0\4\4\2\0\1\5\1\4\7\5\2\0" + + "\2\5\2\0\3\5\11\0\1\5\4\0\2\4\1\0\3\4\2\5" + + "\2\0\12\5\4\4\15\0\3\5\1\0\6\4\4\0\2\4\2\0" + + "\26\4\1\0\7\4\1\0\2\4\1\0\2\4\1\0\2\4\2\0" + + "\1\5\1\0\5\5\4\0\2\5\2\0\3\5\13\0\4\4\1\0" + + "\1\4\7\0\14\5\3\4\14\0\3\5\1\0\11\4\1\0\3\4" + + "\1\0\26\4\1\0\7\4\1\0\2\4\1\0\5\4\2\0\1\5" + + "\1\4\10\5\1\0\3\5\1\0\3\5\2\0\1\4\17\0\2\4" + + "\2\5\2\0\12\5\1\0\1\4\17\0\3\5\1\0\10\4\2\0" + + "\2\4\2\0\26\4\1\0\7\4\1\0\2\4\1\0\5\4\2\0" + + "\1\5\1\4\6\5\3\0\2\5\2\0\3\5\10\0\2\5\4\0" + + "\2\4\1\0\3\4\4\0\12\5\1\0\1\4\20\0\1\5\1\4" + + "\1\0\6\4\3\0\3\4\1\0\4\4\3\0\2\4\1\0\1\4" + + "\1\0\2\4\3\0\2\4\3\0\3\4\3\0\10\4\1\0\3\4" + + "\4\0\5\5\3\0\3\5\1\0\4\5\11\0\1\5\17\0\11\5" + + "\11\0\1\4\7\0\3\5\1\0\10\4\1\0\3\4\1\0\27\4" + + "\1\0\12\4\1\0\5\4\4\0\7\5\1\0\3\5\1\0\4\5" + + "\7\0\2\5\11\0\2\4\4\0\12\5\22\0\2\5\1\0\10\4" + + "\1\0\3\4\1\0\27\4\1\0\12\4\1\0\5\4\2\0\1\5" + + "\1\4\7\5\1\0\3\5\1\0\4\5\7\0\2\5\7\0\1\4" + + "\1\0\2\4\4\0\12\5\22\0\2\5\1\0\10\4\1\0\3\4" + + "\1\0\27\4\1\0\20\4\4\0\6\5\2\0\3\5\1\0\4\5" + + "\11\0\1\5\10\0\2\4\4\0\12\5\22\0\2\5\1\0\22\4" + + "\3\0\30\4\1\0\11\4\1\0\1\4\2\0\7\4\3\0\1\5" + + "\4\0\6\5\1\0\1\5\1\0\10\5\22\0\2\5\15\0\60\4" + + "\1\5\2\4\7\5\4\0\10\4\10\5\1\0\12\5\47\0\2\4" + + "\1\0\1\4\2\0\2\4\1\0\1\4\2\0\1\4\6\0\4\4" + + "\1\0\7\4\1\0\3\4\1\0\1\4\1\0\1\4\2\0\2\4" + + "\1\0\4\4\1\5\2\4\6\5\1\0\2\5\1\4\2\0\5\4" + + "\1\0\1\4\1\0\6\5\2\0\12\5\2\0\2\4\42\0\1\4" + + "\27\0\2\5\6\0\12\5\13\0\1\5\1\0\1\5\1\0\1\5" + + "\4\0\2\5\10\4\1\0\42\4\6\0\24\5\1\0\2\5\4\4" + + "\4\0\10\5\1\0\44\5\11\0\1\5\71\0\42\4\1\0\5\4" + + "\1\0\2\4\1\0\7\5\3\0\4\5\6\0\12\5\6\0\6\4" + + "\4\5\106\0\46\4\12\0\51\4\7\0\132\4\5\0\104\4\5\0" + + "\122\4\6\0\7\4\1\0\77\4\1\0\1\4\1\0\4\4\2\0" + + "\7\4\1\0\1\4\1\0\4\4\2\0\47\4\1\0\1\4\1\0" + + "\4\4\2\0\37\4\1\0\1\4\1\0\4\4\2\0\7\4\1\0" + + "\1\4\1\0\4\4\2\0\7\4\1\0\7\4\1\0\27\4\1\0" + + "\37\4\1\0\1\4\1\0\4\4\2\0\7\4\1\0\47\4\1\0" + + "\23\4\16\0\11\5\56\0\125\4\14\0\u026c\4\2\0\10\4\12\0" + + "\32\4\5\0\113\4\3\0\3\4\17\0\15\4\1\0\4\4\3\5" + + "\13\0\22\4\3\5\13\0\22\4\2\5\14\0\15\4\1\0\3\4" + + "\1\0\2\5\14\0\64\4\40\5\3\0\1\4\3\0\2\4\1\5" + + "\2\0\12\5\41\0\3\5\2\0\12\5\6\0\130\4\10\0\51\4" + + "\1\5\126\0\35\4\3\0\14\5\4\0\14\5\12\0\12\5\36\4" + + "\2\0\5\4\u038b\0\154\4\224\0\234\4\4\0\132\4\6\0\26\4" + + "\2\0\6\4\2\0\46\4\2\0\6\4\2\0\10\4\1\0\1\4" + + "\1\0\1\4\1\0\1\4\1\0\37\4\2\0\65\4\1\0\7\4" + + "\1\0\1\4\3\0\3\4\1\0\7\4\3\0\4\4\2\0\6\4" + + "\4\0\15\4\5\0\3\4\1\0\7\4\17\0\4\5\32\0\5\5" + + "\20\0\2\4\23\0\1\4\13\0\4\5\6\0\6\5\1\0\1\4" + + "\15\0\1\4\40\0\22\4\36\0\15\5\4\0\1\5\3\0\6\5" + + "\27\0\1\4\4\0\1\4\2\0\12\4\1\0\1\4\3\0\5\4" + + "\6\0\1\4\1\0\1\4\1\0\1\4\1\0\4\4\1\0\3\4" + + "\1\0\7\4\3\0\3\4\5\0\5\4\26\0\44\4\u0e81\0\3\4" + + "\31\0\11\4\6\5\1\0\5\4\2\0\5\4\4\0\126\4\2\0" + + "\2\5\2\0\3\4\1\0\137\4\5\0\50\4\4\0\136\4\21\0" + + "\30\4\70\0\20\4\u0200\0\u19b6\4\112\0\u51a6\4\132\0\u048d\4\u0773\0" + + "\u2ba4\4\u215c\0\u012e\4\2\0\73\4\225\0\7\4\14\0\5\4\5\0" + + "\1\4\1\5\12\4\1\0\15\4\1\0\5\4\1\0\1\4\1\0" + + "\2\4\1\0\2\4\1\0\154\4\41\0\u016b\4\22\0\100\4\2\0" + + "\66\4\50\0\15\4\3\0\20\5\20\0\4\5\17\0\2\4\30\0" + + "\3\4\31\0\1\4\6\0\5\4\1\0\207\4\2\0\1\5\4\0" + + "\1\4\13\0\12\5\7\0\32\4\4\0\1\4\1\0\32\4\12\0" + + "\132\4\3\0\6\4\2\0\6\4\2\0\6\4\2\0\3\4\3\0" + + "\2\4\3\0\2\4\22\0\3\5\4\0"; + + /** + * Translates characters to character classes + */ + private static final char[] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); + + /** + * Translates DFA states to action switch labels. + */ + private static final int[] ZZ_ACTION = zzUnpackAction(); + + private static final String ZZ_ACTION_PACKED_0 = + "\3\0\1\1\1\2\1\3\1\4\1\5\1\6\1\2" + + "\1\7\1\10\1\11\1\12\1\13\1\14\20\3\1\15" + + "\1\16\1\17\1\20\1\21\1\22\1\23\1\24\1\25" + + "\1\26\1\27\1\30\1\31\1\32\1\33\1\34\1\35" + + "\1\36\1\6\1\37\2\2\1\40\1\41\1\42\1\0" + + "\1\40\1\2\1\43\1\44\2\11\2\12\20\3\1\45" + + "\1\46\1\47\11\3\1\50\1\51\1\52\1\53\1\54" + + "\1\55\1\56\1\57\1\60\1\61\1\62\1\63\1\64" + + "\1\65\1\66\1\67\1\2\1\40\1\42\1\70\1\40" + + "\2\0\2\11\2\12\1\3\1\71\11\3\1\72\1\73" + + "\1\74\2\3\1\75\12\3\1\76\1\3\1\77\1\100" + + "\1\101\1\102\1\103\1\104\1\0\2\70\1\105\1\3" + + "\1\106\3\3\1\107\4\3\1\110\5\3\1\111\3\3" + + "\1\112\1\3\1\113\1\114\1\42\1\0\1\115\4\3" + + "\1\116\5\3\1\117\1\120\1\3\1\121\1\122\1\123" + + "\1\124\1\125\3\3\1\126\1\3\1\127\4\3\1\130" + + "\1\131\3\3\1\132\1\3\1\133\1\134\1\3\1\135"; + + private static int[] zzUnpackAction() { + int[] result = new int[226]; + int offset = 0; + offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); + return result; } - return j; - } - - - /** - * Translates a state to a row index in the transition table - */ - private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); - - private static final String ZZ_ROWMAP_PACKED_0 = - "\0\0\0\75\0\172\0\172\0\267\0\364\0\u0131\0\u016e"+ - "\0\172\0\u01ab\0\u01e8\0\u0225\0\u0262\0\u029f\0\172\0\172"+ - "\0\u02dc\0\u0319\0\u0356\0\u0393\0\u03d0\0\u040d\0\u044a\0\u0487"+ - "\0\u04c4\0\u0501\0\u053e\0\u057b\0\u05b8\0\u05f5\0\u0632\0\u066f"+ - "\0\u06ac\0\u06e9\0\u0726\0\u0763\0\u07a0\0\u07dd\0\u081a\0\u0857"+ - "\0\172\0\172\0\172\0\172\0\172\0\172\0\172\0\172"+ - "\0\172\0\u0894\0\u08d1\0\u090e\0\u094b\0\u0988\0\u09c5\0\u0a02"+ - "\0\u0a3f\0\u0a7c\0\u0ab9\0\u0af6\0\172\0\172\0\172\0\u0b33"+ - "\0\u0b70\0\172\0\u0bad\0\u0bea\0\u0c27\0\u0c64\0\u0ca1\0\u0cde"+ - "\0\u0d1b\0\u0d58\0\u0d95\0\u0dd2\0\u0e0f\0\u0e4c\0\u0e89\0\u0ec6"+ - "\0\u0f03\0\u0f40\0\364\0\364\0\u0f7d\0\u0fba\0\u0ff7\0\u1034"+ - "\0\u1071\0\u10ae\0\u10eb\0\u1128\0\u1165\0\u11a2\0\u11df\0\u121c"+ - "\0\172\0\172\0\172\0\u1259\0\172\0\172\0\172\0\172"+ - "\0\172\0\172\0\172\0\172\0\172\0\u1296\0\u12d3\0\u1310"+ - "\0\u134d\0\u138a\0\u13c7\0\u1404\0\u1441\0\u147e\0\u14bb\0\u14f8"+ - "\0\u1535\0\u1572\0\364\0\u15af\0\u15ec\0\u1629\0\u1666\0\u16a3"+ - "\0\u16e0\0\u171d\0\u175a\0\u1797\0\364\0\364\0\364\0\u17d4"+ - "\0\u1811\0\364\0\u184e\0\u188b\0\u18c8\0\u1905\0\u1942\0\u197f"+ - "\0\u19bc\0\u19f9\0\u1a36\0\u1a73\0\364\0\u1ab0\0\364\0\172"+ - "\0\172\0\172\0\u1aed\0\172\0\u1b2a\0\u1b67\0\172\0\364"+ - "\0\u1ba4\0\364\0\u1be1\0\u1c1e\0\u1c5b\0\364\0\u1c98\0\u1cd5"+ - "\0\u1d12\0\u1d4f\0\364\0\u1d8c\0\u1dc9\0\u1e06\0\u1e43\0\u1e80"+ - "\0\364\0\u1ebd\0\u1efa\0\u1f37\0\364\0\u1f74\0\364\0\172"+ - "\0\172\0\u1fb1\0\364\0\u1fee\0\u202b\0\u2068\0\u20a5\0\364"+ - "\0\u20e2\0\u211f\0\u215c\0\u2199\0\u21d6\0\364\0\364\0\u2213"+ - "\0\364\0\364\0\364\0\364\0\364\0\u2250\0\u228d\0\u22ca"+ - "\0\364\0\u2307\0\364\0\u2344\0\u2381\0\u23be\0\u23fb\0\364"+ - "\0\364\0\u2438\0\u2475\0\u24b2\0\364\0\u24ef\0\364\0\364"+ - "\0\u252c\0\364"; - - private static int [] zzUnpackRowMap() { - int [] result = new int[226]; - int offset = 0; - offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); - return result; - } - - private static int zzUnpackRowMap(String packed, int offset, int [] result) { - int i = 0; /* index in packed string */ - int j = offset; /* index in unpacked array */ - int l = packed.length(); - while (i < l) { - int high = packed.charAt(i++) << 16; - result[j++] = high | packed.charAt(i++); - } - return j; - } - - /** - * The transition table of the DFA - */ - private static final int [] ZZ_TRANS = zzUnpackTrans(); - - private static final String ZZ_TRANS_PACKED_0 = - "\1\4\1\5\1\6\1\7\1\6\1\4\1\10\1\11"+ - "\1\7\1\12\1\6\1\13\1\6\1\14\1\7\1\15"+ - "\1\4\1\16\1\17\1\20\2\6\1\21\1\22\1\23"+ - "\1\24\1\25\1\6\1\26\1\27\1\30\1\31\1\32"+ - "\1\33\1\6\1\34\2\6\1\35\1\36\1\6\1\37"+ - "\1\40\1\41\1\42\1\43\1\4\1\44\1\45\1\46"+ - "\1\47\1\50\1\51\1\52\1\53\1\54\1\55\1\56"+ - "\1\57\1\60\1\61\1\4\1\5\1\6\1\7\1\6"+ - "\1\4\1\62\1\63\1\7\1\12\1\6\1\13\1\6"+ - "\1\14\1\7\1\15\1\4\1\16\1\17\1\20\2\6"+ - "\1\21\1\22\1\23\1\24\1\25\1\6\1\26\1\27"+ - "\1\30\1\31\1\32\1\33\1\6\1\34\2\6\1\35"+ - "\1\36\1\6\1\37\1\40\1\41\1\42\1\43\1\64"+ - "\1\44\1\45\1\46\1\47\1\50\1\51\1\52\1\53"+ - "\1\54\1\55\1\56\1\57\1\60\1\61\76\0\1\5"+ - "\7\0\1\5\1\0\1\65\1\66\14\0\1\66\44\0"+ - "\2\6\1\0\2\6\3\0\2\6\1\0\1\6\7\0"+ - "\27\6\25\0\1\7\4\0\1\7\5\0\1\7\56\0"+ - "\6\67\1\70\1\71\1\0\5\67\1\0\1\67\1\72"+ - "\1\67\1\73\52\67\1\0\1\5\7\0\1\5\1\74"+ - "\1\65\1\66\10\0\1\74\3\0\1\66\44\0\1\65"+ - "\7\0\1\65\100\0\1\75\35\0\1\76\21\0\10\15"+ - "\1\0\5\15\1\0\1\77\1\100\54\15\10\16\1\0"+ - "\5\16\1\0\1\16\1\101\1\102\53\16\1\0\2\6"+ - "\1\0\2\6\3\0\2\6\1\0\1\6\7\0\3\6"+ - "\1\103\14\6\1\104\1\6\1\105\4\6\23\0\2\6"+ - "\1\0\2\6\3\0\2\6\1\0\1\6\7\0\5\6"+ - "\1\106\21\6\23\0\2\6\1\0\2\6\3\0\2\6"+ - "\1\0\1\6\7\0\12\6\1\107\14\6\23\0\2\6"+ - "\1\0\2\6\3\0\2\6\1\0\1\6\7\0\10\6"+ - "\1\110\16\6\23\0\2\6\1\0\2\6\3\0\2\6"+ - "\1\0\1\6\7\0\4\6\1\111\2\6\1\112\4\6"+ - "\1\113\4\6\1\114\5\6\23\0\2\6\1\0\2\6"+ - "\3\0\2\6\1\0\1\6\7\0\5\6\1\115\21\6"+ - "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6"+ - "\7\0\5\6\1\116\15\6\1\117\3\6\23\0\2\6"+ - "\1\0\2\6\3\0\2\6\1\0\1\6\7\0\4\6"+ - "\1\120\1\121\21\6\23\0\2\6\1\0\2\6\3\0"+ - "\2\6\1\0\1\6\7\0\5\6\1\122\13\6\1\123"+ - "\5\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0"+ - "\1\6\7\0\6\6\1\124\3\6\1\125\14\6\23\0"+ - "\2\6\1\0\2\6\3\0\2\6\1\0\1\6\7\0"+ - "\3\6\1\126\23\6\23\0\2\6\1\0\2\6\3\0"+ - "\2\6\1\0\1\6\7\0\7\6\1\127\11\6\1\130"+ - "\5\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0"+ - "\1\6\7\0\14\6\1\131\12\6\23\0\2\6\1\0"+ - "\2\6\3\0\2\6\1\0\1\6\7\0\14\6\1\132"+ - "\3\6\1\133\6\6\23\0\2\6\1\0\2\6\3\0"+ - "\2\6\1\0\1\6\7\0\7\6\1\134\11\6\1\135"+ - "\5\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0"+ - "\1\6\7\0\5\6\1\136\21\6\75\0\1\137\74\0"+ - "\1\140\74\0\1\141\1\0\1\142\72\0\1\143\3\0"+ - "\1\144\70\0\1\145\4\0\1\146\67\0\1\147\5\0"+ - "\1\150\66\0\1\151\74\0\1\152\27\0\1\70\1\71"+ - "\43\0\1\153\74\0\1\154\74\0\1\155\2\0\1\156"+ - "\17\0\1\65\7\0\1\65\2\0\1\66\14\0\1\66"+ - "\44\0\1\157\7\0\1\157\3\0\1\157\37\0\1\157"+ - "\17\0\6\67\1\160\1\67\1\0\5\67\1\0\1\67"+ - "\1\72\1\67\1\73\52\67\10\70\1\0\5\70\1\0"+ - "\56\70\7\161\1\162\65\161\10\67\1\0\5\67\1\0"+ - "\56\67\6\73\1\163\1\73\1\164\5\73\1\164\1\73"+ - "\1\165\2\73\1\67\51\73\1\0\2\74\6\0\1\74"+ - "\2\0\1\74\14\0\3\74\3\0\1\74\1\0\1\74"+ - "\1\0\1\74\31\0\3\15\1\166\4\15\1\167\64\15"+ - "\3\16\1\170\4\16\1\171\64\16\1\0\2\6\1\0"+ - "\2\6\3\0\2\6\1\0\1\6\7\0\4\6\1\172"+ - "\15\6\1\173\4\6\23\0\2\6\1\0\2\6\3\0"+ - "\2\6\1\0\1\6\7\0\3\6\1\174\10\6\1\175"+ - "\12\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0"+ - "\1\6\7\0\24\6\1\176\2\6\23\0\2\6\1\0"+ - "\2\6\3\0\2\6\1\0\1\6\7\0\2\6\1\177"+ - "\24\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0"+ - "\1\6\7\0\13\6\1\200\13\6\23\0\2\6\1\0"+ - "\2\6\3\0\2\6\1\0\1\6\7\0\11\6\1\201"+ - "\15\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0"+ - "\1\6\7\0\12\6\1\202\14\6\23\0\2\6\1\0"+ - "\2\6\3\0\2\6\1\0\1\6\7\0\10\6\1\203"+ - "\16\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0"+ - "\1\6\7\0\12\6\1\204\14\6\23\0\2\6\1\0"+ - "\2\6\3\0\2\6\1\0\1\6\7\0\3\6\1\205"+ - "\23\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0"+ - "\1\6\7\0\2\6\1\206\24\6\23\0\2\6\1\0"+ - "\2\6\3\0\2\6\1\0\1\6\7\0\2\6\1\207"+ - "\24\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0"+ - "\1\6\7\0\14\6\1\210\12\6\23\0\2\6\1\0"+ - "\2\6\3\0\2\6\1\0\1\6\7\0\10\6\1\211"+ - "\16\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0"+ - "\1\6\7\0\23\6\1\212\3\6\23\0\2\6\1\0"+ - "\2\6\3\0\2\6\1\0\1\6\7\0\6\6\1\213"+ - "\1\6\1\214\16\6\23\0\2\6\1\0\2\6\3\0"+ - "\2\6\1\0\1\6\7\0\11\6\1\215\15\6\23\0"+ - "\2\6\1\0\2\6\3\0\2\6\1\0\1\6\7\0"+ - "\5\6\1\216\21\6\23\0\2\6\1\0\2\6\3\0"+ - "\2\6\1\0\1\6\7\0\2\6\1\217\6\6\1\220"+ - "\15\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0"+ - "\1\6\7\0\12\6\1\221\14\6\23\0\2\6\1\0"+ - "\2\6\3\0\2\6\1\0\1\6\7\0\5\6\1\222"+ - "\21\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0"+ - "\1\6\7\0\2\6\1\223\24\6\23\0\2\6\1\0"+ - "\2\6\3\0\2\6\1\0\1\6\7\0\14\6\1\224"+ - "\12\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0"+ - "\1\6\7\0\3\6\1\225\23\6\23\0\2\6\1\0"+ - "\2\6\3\0\2\6\1\0\1\6\7\0\14\6\1\226"+ - "\12\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0"+ - "\1\6\7\0\2\6\1\227\24\6\75\0\1\230\74\0"+ - "\1\231\74\0\1\232\3\0\1\233\70\0\1\234\22\0"+ - "\1\157\7\0\1\157\107\0\2\160\12\0\1\160\11\0"+ - "\1\160\22\0\7\161\1\235\65\161\6\236\1\237\1\162"+ - "\65\236\23\164\1\67\2\163\12\164\1\163\11\164\1\163"+ - "\45\164\1\67\51\164\10\73\1\164\5\73\1\164\4\73"+ - "\1\67\51\73\3\15\1\166\4\15\1\167\6\15\1\77"+ - "\1\100\64\15\1\0\6\15\1\77\1\100\54\15\3\16"+ - "\1\170\4\16\1\171\7\16\1\101\1\102\63\16\1\0"+ - "\7\16\1\101\1\102\53\16\1\0\2\6\1\0\2\6"+ - "\3\0\2\6\1\0\1\6\7\0\5\6\1\240\21\6"+ - "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6"+ - "\7\0\21\6\1\241\5\6\23\0\2\6\1\0\2\6"+ - "\3\0\2\6\1\0\1\6\7\0\11\6\1\242\15\6"+ - "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6"+ - "\7\0\5\6\1\243\21\6\23\0\2\6\1\0\2\6"+ - "\3\0\2\6\1\0\1\6\7\0\4\6\1\244\22\6"+ - "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6"+ - "\7\0\5\6\1\245\21\6\23\0\2\6\1\0\2\6"+ - "\3\0\2\6\1\0\1\6\7\0\5\6\1\246\21\6"+ - "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6"+ - "\7\0\17\6\1\247\7\6\23\0\2\6\1\0\2\6"+ - "\3\0\2\6\1\0\1\6\7\0\11\6\1\250\15\6"+ - "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6"+ - "\7\0\7\6\1\251\17\6\23\0\2\6\1\0\2\6"+ - "\3\0\2\6\1\0\1\6\7\0\2\6\1\252\24\6"+ - "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6"+ - "\7\0\10\6\1\253\16\6\23\0\2\6\1\0\2\6"+ - "\3\0\2\6\1\0\1\6\7\0\7\6\1\254\17\6"+ - "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6"+ - "\7\0\5\6\1\255\21\6\23\0\2\6\1\0\2\6"+ - "\3\0\2\6\1\0\1\6\7\0\2\6\1\256\24\6"+ - "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6"+ - "\7\0\7\6\1\257\17\6\23\0\2\6\1\0\2\6"+ - "\3\0\2\6\1\0\1\6\7\0\17\6\1\260\7\6"+ - "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6"+ - "\7\0\5\6\1\261\21\6\23\0\2\6\1\0\2\6"+ - "\3\0\2\6\1\0\1\6\7\0\2\6\1\262\6\6"+ - "\1\263\15\6\23\0\2\6\1\0\2\6\3\0\2\6"+ - "\1\0\1\6\7\0\10\6\1\264\16\6\23\0\2\6"+ - "\1\0\2\6\3\0\2\6\1\0\1\6\7\0\20\6"+ - "\1\265\6\6\23\0\2\6\1\0\2\6\3\0\2\6"+ - "\1\0\1\6\7\0\10\6\1\266\16\6\23\0\2\6"+ - "\1\0\2\6\3\0\2\6\1\0\1\6\7\0\13\6"+ - "\1\267\13\6\75\0\1\270\21\0\6\161\1\271\1\235"+ - "\65\161\7\236\1\272\65\236\1\0\2\6\1\0\2\6"+ - "\3\0\2\6\1\0\1\6\7\0\23\6\1\273\3\6"+ - "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6"+ - "\7\0\21\6\1\274\5\6\23\0\2\6\1\0\2\6"+ - "\3\0\2\6\1\0\1\6\7\0\3\6\1\275\23\6"+ - "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6"+ - "\7\0\6\6\1\276\20\6\23\0\2\6\1\0\2\6"+ - "\3\0\2\6\1\0\1\6\7\0\2\6\1\277\24\6"+ - "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6"+ - "\7\0\5\6\1\300\21\6\23\0\2\6\1\0\2\6"+ - "\3\0\2\6\1\0\1\6\7\0\10\6\1\301\16\6"+ - "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6"+ - "\7\0\17\6\1\302\7\6\23\0\2\6\1\0\2\6"+ - "\3\0\2\6\1\0\1\6\7\0\4\6\1\303\22\6"+ - "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6"+ - "\7\0\2\6\1\304\24\6\23\0\2\6\1\0\2\6"+ - "\3\0\2\6\1\0\1\6\7\0\7\6\1\305\17\6"+ - "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6"+ - "\7\0\16\6\1\306\10\6\23\0\2\6\1\0\2\6"+ - "\3\0\2\6\1\0\1\6\7\0\20\6\1\307\6\6"+ - "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6"+ - "\7\0\14\6\1\310\12\6\23\0\2\6\1\0\2\6"+ - "\3\0\2\6\1\0\1\6\7\0\2\6\1\311\24\6"+ - "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6"+ - "\7\0\13\6\1\312\13\6\23\0\2\6\1\0\2\6"+ - "\3\0\2\6\1\0\1\6\7\0\5\6\1\313\21\6"+ - "\22\0\6\236\1\237\1\272\65\236\1\0\2\6\1\0"+ - "\2\6\3\0\2\6\1\0\1\6\7\0\6\6\1\314"+ - "\20\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0"+ - "\1\6\7\0\12\6\1\315\14\6\23\0\2\6\1\0"+ - "\2\6\3\0\2\6\1\0\1\6\7\0\14\6\1\316"+ - "\12\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0"+ - "\1\6\7\0\14\6\1\317\12\6\23\0\2\6\1\0"+ - "\2\6\3\0\2\6\1\0\1\6\7\0\10\6\1\320"+ - "\16\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0"+ - "\1\6\7\0\20\6\1\321\6\6\23\0\2\6\1\0"+ - "\2\6\3\0\2\6\1\0\1\6\7\0\10\6\1\322"+ - "\16\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0"+ - "\1\6\7\0\5\6\1\323\21\6\23\0\2\6\1\0"+ - "\2\6\3\0\2\6\1\0\1\6\7\0\12\6\1\324"+ - "\14\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0"+ - "\1\6\7\0\12\6\1\325\14\6\23\0\2\6\1\0"+ - "\2\6\3\0\2\6\1\0\1\6\7\0\12\6\1\326"+ - "\14\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0"+ - "\1\6\7\0\21\6\1\327\5\6\23\0\2\6\1\0"+ - "\2\6\3\0\2\6\1\0\1\6\7\0\22\6\1\330"+ - "\4\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0"+ - "\1\6\7\0\2\6\1\331\24\6\23\0\2\6\1\0"+ - "\2\6\3\0\2\6\1\0\1\6\7\0\17\6\1\332"+ - "\7\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0"+ - "\1\6\7\0\4\6\1\333\22\6\23\0\2\6\1\0"+ - "\2\6\3\0\2\6\1\0\1\6\7\0\5\6\1\334"+ - "\21\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0"+ - "\1\6\7\0\12\6\1\335\14\6\23\0\2\6\1\0"+ - "\2\6\3\0\2\6\1\0\1\6\7\0\5\6\1\336"+ - "\21\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0"+ - "\1\6\7\0\5\6\1\337\21\6\23\0\2\6\1\0"+ - "\2\6\3\0\2\6\1\0\1\6\7\0\13\6\1\340"+ - "\13\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0"+ - "\1\6\7\0\21\6\1\341\5\6\23\0\2\6\1\0"+ - "\2\6\3\0\2\6\1\0\1\6\7\0\6\6\1\342"+ - "\20\6\22\0"; - - private static int [] zzUnpackTrans() { - int [] result = new int[9577]; - int offset = 0; - offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); - return result; - } - - private static int zzUnpackTrans(String packed, int offset, int [] result) { - int i = 0; /* index in packed string */ - int j = offset; /* index in unpacked array */ - int l = packed.length(); - while (i < l) { - int count = packed.charAt(i++); - int value = packed.charAt(i++); - value--; - do result[j++] = value; while (--count > 0); + + private static int zzUnpackAction(String packed, int offset, int[] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; + while (--count > 0); + } + return j; } - return j; - } - - - /* error codes */ - private static final int ZZ_UNKNOWN_ERROR = 0; - private static final int ZZ_NO_MATCH = 1; - private static final int ZZ_PUSHBACK_2BIG = 2; - private static final char[] EMPTY_BUFFER = new char[0]; - private static final int YYEOF = -1; - - /* error messages for the codes above */ - private static final String ZZ_ERROR_MSG[] = { - "Unkown internal scanner error", - "Error: could not match input", - "Error: pushback value was too large" - }; - - /** - * ZZ_ATTRIBUTE[aState] contains the attributes of state aState - */ - private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); - - private static final String ZZ_ATTRIBUTE_PACKED_0 = - "\2\0\1\10\1\11\4\1\1\11\5\1\2\11\30\1"+ - "\11\11\10\1\1\0\2\1\3\11\2\1\1\11\36\1"+ - "\3\11\1\1\11\11\6\1\2\0\42\1\3\11\1\1"+ - "\1\11\1\0\1\1\1\11\30\1\2\11\1\0\50\1"; - - private static int [] zzUnpackAttribute() { - int [] result = new int[226]; - int offset = 0; - offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); - return result; - } - - private static int zzUnpackAttribute(String packed, int offset, int [] result) { - int i = 0; /* index in packed string */ - int j = offset; /* index in unpacked array */ - int l = packed.length(); - while (i < l) { - int count = packed.charAt(i++); - int value = packed.charAt(i++); - do result[j++] = value; while (--count > 0); + + + /** + * Translates a state to a row index in the transition table + */ + private static final int[] ZZ_ROWMAP = zzUnpackRowMap(); + + private static final String ZZ_ROWMAP_PACKED_0 = + "\0\0\0\75\0\172\0\172\0\267\0\364\0\u0131\0\u016e" + + "\0\172\0\u01ab\0\u01e8\0\u0225\0\u0262\0\u029f\0\172\0\172" + + "\0\u02dc\0\u0319\0\u0356\0\u0393\0\u03d0\0\u040d\0\u044a\0\u0487" + + "\0\u04c4\0\u0501\0\u053e\0\u057b\0\u05b8\0\u05f5\0\u0632\0\u066f" + + "\0\u06ac\0\u06e9\0\u0726\0\u0763\0\u07a0\0\u07dd\0\u081a\0\u0857" + + "\0\172\0\172\0\172\0\172\0\172\0\172\0\172\0\172" + + "\0\172\0\u0894\0\u08d1\0\u090e\0\u094b\0\u0988\0\u09c5\0\u0a02" + + "\0\u0a3f\0\u0a7c\0\u0ab9\0\u0af6\0\172\0\172\0\172\0\u0b33" + + "\0\u0b70\0\172\0\u0bad\0\u0bea\0\u0c27\0\u0c64\0\u0ca1\0\u0cde" + + "\0\u0d1b\0\u0d58\0\u0d95\0\u0dd2\0\u0e0f\0\u0e4c\0\u0e89\0\u0ec6" + + "\0\u0f03\0\u0f40\0\364\0\364\0\u0f7d\0\u0fba\0\u0ff7\0\u1034" + + "\0\u1071\0\u10ae\0\u10eb\0\u1128\0\u1165\0\u11a2\0\u11df\0\u121c" + + "\0\172\0\172\0\172\0\u1259\0\172\0\172\0\172\0\172" + + "\0\172\0\172\0\172\0\172\0\172\0\u1296\0\u12d3\0\u1310" + + "\0\u134d\0\u138a\0\u13c7\0\u1404\0\u1441\0\u147e\0\u14bb\0\u14f8" + + "\0\u1535\0\u1572\0\364\0\u15af\0\u15ec\0\u1629\0\u1666\0\u16a3" + + "\0\u16e0\0\u171d\0\u175a\0\u1797\0\364\0\364\0\364\0\u17d4" + + "\0\u1811\0\364\0\u184e\0\u188b\0\u18c8\0\u1905\0\u1942\0\u197f" + + "\0\u19bc\0\u19f9\0\u1a36\0\u1a73\0\364\0\u1ab0\0\364\0\172" + + "\0\172\0\172\0\u1aed\0\172\0\u1b2a\0\u1b67\0\172\0\364" + + "\0\u1ba4\0\364\0\u1be1\0\u1c1e\0\u1c5b\0\364\0\u1c98\0\u1cd5" + + "\0\u1d12\0\u1d4f\0\364\0\u1d8c\0\u1dc9\0\u1e06\0\u1e43\0\u1e80" + + "\0\364\0\u1ebd\0\u1efa\0\u1f37\0\364\0\u1f74\0\364\0\172" + + "\0\172\0\u1fb1\0\364\0\u1fee\0\u202b\0\u2068\0\u20a5\0\364" + + "\0\u20e2\0\u211f\0\u215c\0\u2199\0\u21d6\0\364\0\364\0\u2213" + + "\0\364\0\364\0\364\0\364\0\364\0\u2250\0\u228d\0\u22ca" + + "\0\364\0\u2307\0\364\0\u2344\0\u2381\0\u23be\0\u23fb\0\364" + + "\0\364\0\u2438\0\u2475\0\u24b2\0\364\0\u24ef\0\364\0\364" + + "\0\u252c\0\364"; + + private static int[] zzUnpackRowMap() { + int[] result = new int[226]; + int offset = 0; + offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); + return result; } - return j; - } - /** the current state of the DFA */ - private int zzState; + private static int zzUnpackRowMap(String packed, int offset, int[] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int high = packed.charAt(i++) << 16; + result[j++] = high | packed.charAt(i++); + } + return j; + } - /** the current lexical state */ - private int zzLexicalState = YYINITIAL; + /** + * The transition table of the DFA + */ + private static final int[] ZZ_TRANS = zzUnpackTrans(); + + private static final String ZZ_TRANS_PACKED_0 = + "\1\4\1\5\1\6\1\7\1\6\1\4\1\10\1\11" + + "\1\7\1\12\1\6\1\13\1\6\1\14\1\7\1\15" + + "\1\4\1\16\1\17\1\20\2\6\1\21\1\22\1\23" + + "\1\24\1\25\1\6\1\26\1\27\1\30\1\31\1\32" + + "\1\33\1\6\1\34\2\6\1\35\1\36\1\6\1\37" + + "\1\40\1\41\1\42\1\43\1\4\1\44\1\45\1\46" + + "\1\47\1\50\1\51\1\52\1\53\1\54\1\55\1\56" + + "\1\57\1\60\1\61\1\4\1\5\1\6\1\7\1\6" + + "\1\4\1\62\1\63\1\7\1\12\1\6\1\13\1\6" + + "\1\14\1\7\1\15\1\4\1\16\1\17\1\20\2\6" + + "\1\21\1\22\1\23\1\24\1\25\1\6\1\26\1\27" + + "\1\30\1\31\1\32\1\33\1\6\1\34\2\6\1\35" + + "\1\36\1\6\1\37\1\40\1\41\1\42\1\43\1\64" + + "\1\44\1\45\1\46\1\47\1\50\1\51\1\52\1\53" + + "\1\54\1\55\1\56\1\57\1\60\1\61\76\0\1\5" + + "\7\0\1\5\1\0\1\65\1\66\14\0\1\66\44\0" + + "\2\6\1\0\2\6\3\0\2\6\1\0\1\6\7\0" + + "\27\6\25\0\1\7\4\0\1\7\5\0\1\7\56\0" + + "\6\67\1\70\1\71\1\0\5\67\1\0\1\67\1\72" + + "\1\67\1\73\52\67\1\0\1\5\7\0\1\5\1\74" + + "\1\65\1\66\10\0\1\74\3\0\1\66\44\0\1\65" + + "\7\0\1\65\100\0\1\75\35\0\1\76\21\0\10\15" + + "\1\0\5\15\1\0\1\77\1\100\54\15\10\16\1\0" + + "\5\16\1\0\1\16\1\101\1\102\53\16\1\0\2\6" + + "\1\0\2\6\3\0\2\6\1\0\1\6\7\0\3\6" + + "\1\103\14\6\1\104\1\6\1\105\4\6\23\0\2\6" + + "\1\0\2\6\3\0\2\6\1\0\1\6\7\0\5\6" + + "\1\106\21\6\23\0\2\6\1\0\2\6\3\0\2\6" + + "\1\0\1\6\7\0\12\6\1\107\14\6\23\0\2\6" + + "\1\0\2\6\3\0\2\6\1\0\1\6\7\0\10\6" + + "\1\110\16\6\23\0\2\6\1\0\2\6\3\0\2\6" + + "\1\0\1\6\7\0\4\6\1\111\2\6\1\112\4\6" + + "\1\113\4\6\1\114\5\6\23\0\2\6\1\0\2\6" + + "\3\0\2\6\1\0\1\6\7\0\5\6\1\115\21\6" + + "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6" + + "\7\0\5\6\1\116\15\6\1\117\3\6\23\0\2\6" + + "\1\0\2\6\3\0\2\6\1\0\1\6\7\0\4\6" + + "\1\120\1\121\21\6\23\0\2\6\1\0\2\6\3\0" + + "\2\6\1\0\1\6\7\0\5\6\1\122\13\6\1\123" + + "\5\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0" + + "\1\6\7\0\6\6\1\124\3\6\1\125\14\6\23\0" + + "\2\6\1\0\2\6\3\0\2\6\1\0\1\6\7\0" + + "\3\6\1\126\23\6\23\0\2\6\1\0\2\6\3\0" + + "\2\6\1\0\1\6\7\0\7\6\1\127\11\6\1\130" + + "\5\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0" + + "\1\6\7\0\14\6\1\131\12\6\23\0\2\6\1\0" + + "\2\6\3\0\2\6\1\0\1\6\7\0\14\6\1\132" + + "\3\6\1\133\6\6\23\0\2\6\1\0\2\6\3\0" + + "\2\6\1\0\1\6\7\0\7\6\1\134\11\6\1\135" + + "\5\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0" + + "\1\6\7\0\5\6\1\136\21\6\75\0\1\137\74\0" + + "\1\140\74\0\1\141\1\0\1\142\72\0\1\143\3\0" + + "\1\144\70\0\1\145\4\0\1\146\67\0\1\147\5\0" + + "\1\150\66\0\1\151\74\0\1\152\27\0\1\70\1\71" + + "\43\0\1\153\74\0\1\154\74\0\1\155\2\0\1\156" + + "\17\0\1\65\7\0\1\65\2\0\1\66\14\0\1\66" + + "\44\0\1\157\7\0\1\157\3\0\1\157\37\0\1\157" + + "\17\0\6\67\1\160\1\67\1\0\5\67\1\0\1\67" + + "\1\72\1\67\1\73\52\67\10\70\1\0\5\70\1\0" + + "\56\70\7\161\1\162\65\161\10\67\1\0\5\67\1\0" + + "\56\67\6\73\1\163\1\73\1\164\5\73\1\164\1\73" + + "\1\165\2\73\1\67\51\73\1\0\2\74\6\0\1\74" + + "\2\0\1\74\14\0\3\74\3\0\1\74\1\0\1\74" + + "\1\0\1\74\31\0\3\15\1\166\4\15\1\167\64\15" + + "\3\16\1\170\4\16\1\171\64\16\1\0\2\6\1\0" + + "\2\6\3\0\2\6\1\0\1\6\7\0\4\6\1\172" + + "\15\6\1\173\4\6\23\0\2\6\1\0\2\6\3\0" + + "\2\6\1\0\1\6\7\0\3\6\1\174\10\6\1\175" + + "\12\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0" + + "\1\6\7\0\24\6\1\176\2\6\23\0\2\6\1\0" + + "\2\6\3\0\2\6\1\0\1\6\7\0\2\6\1\177" + + "\24\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0" + + "\1\6\7\0\13\6\1\200\13\6\23\0\2\6\1\0" + + "\2\6\3\0\2\6\1\0\1\6\7\0\11\6\1\201" + + "\15\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0" + + "\1\6\7\0\12\6\1\202\14\6\23\0\2\6\1\0" + + "\2\6\3\0\2\6\1\0\1\6\7\0\10\6\1\203" + + "\16\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0" + + "\1\6\7\0\12\6\1\204\14\6\23\0\2\6\1\0" + + "\2\6\3\0\2\6\1\0\1\6\7\0\3\6\1\205" + + "\23\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0" + + "\1\6\7\0\2\6\1\206\24\6\23\0\2\6\1\0" + + "\2\6\3\0\2\6\1\0\1\6\7\0\2\6\1\207" + + "\24\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0" + + "\1\6\7\0\14\6\1\210\12\6\23\0\2\6\1\0" + + "\2\6\3\0\2\6\1\0\1\6\7\0\10\6\1\211" + + "\16\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0" + + "\1\6\7\0\23\6\1\212\3\6\23\0\2\6\1\0" + + "\2\6\3\0\2\6\1\0\1\6\7\0\6\6\1\213" + + "\1\6\1\214\16\6\23\0\2\6\1\0\2\6\3\0" + + "\2\6\1\0\1\6\7\0\11\6\1\215\15\6\23\0" + + "\2\6\1\0\2\6\3\0\2\6\1\0\1\6\7\0" + + "\5\6\1\216\21\6\23\0\2\6\1\0\2\6\3\0" + + "\2\6\1\0\1\6\7\0\2\6\1\217\6\6\1\220" + + "\15\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0" + + "\1\6\7\0\12\6\1\221\14\6\23\0\2\6\1\0" + + "\2\6\3\0\2\6\1\0\1\6\7\0\5\6\1\222" + + "\21\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0" + + "\1\6\7\0\2\6\1\223\24\6\23\0\2\6\1\0" + + "\2\6\3\0\2\6\1\0\1\6\7\0\14\6\1\224" + + "\12\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0" + + "\1\6\7\0\3\6\1\225\23\6\23\0\2\6\1\0" + + "\2\6\3\0\2\6\1\0\1\6\7\0\14\6\1\226" + + "\12\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0" + + "\1\6\7\0\2\6\1\227\24\6\75\0\1\230\74\0" + + "\1\231\74\0\1\232\3\0\1\233\70\0\1\234\22\0" + + "\1\157\7\0\1\157\107\0\2\160\12\0\1\160\11\0" + + "\1\160\22\0\7\161\1\235\65\161\6\236\1\237\1\162" + + "\65\236\23\164\1\67\2\163\12\164\1\163\11\164\1\163" + + "\45\164\1\67\51\164\10\73\1\164\5\73\1\164\4\73" + + "\1\67\51\73\3\15\1\166\4\15\1\167\6\15\1\77" + + "\1\100\64\15\1\0\6\15\1\77\1\100\54\15\3\16" + + "\1\170\4\16\1\171\7\16\1\101\1\102\63\16\1\0" + + "\7\16\1\101\1\102\53\16\1\0\2\6\1\0\2\6" + + "\3\0\2\6\1\0\1\6\7\0\5\6\1\240\21\6" + + "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6" + + "\7\0\21\6\1\241\5\6\23\0\2\6\1\0\2\6" + + "\3\0\2\6\1\0\1\6\7\0\11\6\1\242\15\6" + + "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6" + + "\7\0\5\6\1\243\21\6\23\0\2\6\1\0\2\6" + + "\3\0\2\6\1\0\1\6\7\0\4\6\1\244\22\6" + + "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6" + + "\7\0\5\6\1\245\21\6\23\0\2\6\1\0\2\6" + + "\3\0\2\6\1\0\1\6\7\0\5\6\1\246\21\6" + + "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6" + + "\7\0\17\6\1\247\7\6\23\0\2\6\1\0\2\6" + + "\3\0\2\6\1\0\1\6\7\0\11\6\1\250\15\6" + + "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6" + + "\7\0\7\6\1\251\17\6\23\0\2\6\1\0\2\6" + + "\3\0\2\6\1\0\1\6\7\0\2\6\1\252\24\6" + + "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6" + + "\7\0\10\6\1\253\16\6\23\0\2\6\1\0\2\6" + + "\3\0\2\6\1\0\1\6\7\0\7\6\1\254\17\6" + + "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6" + + "\7\0\5\6\1\255\21\6\23\0\2\6\1\0\2\6" + + "\3\0\2\6\1\0\1\6\7\0\2\6\1\256\24\6" + + "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6" + + "\7\0\7\6\1\257\17\6\23\0\2\6\1\0\2\6" + + "\3\0\2\6\1\0\1\6\7\0\17\6\1\260\7\6" + + "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6" + + "\7\0\5\6\1\261\21\6\23\0\2\6\1\0\2\6" + + "\3\0\2\6\1\0\1\6\7\0\2\6\1\262\6\6" + + "\1\263\15\6\23\0\2\6\1\0\2\6\3\0\2\6" + + "\1\0\1\6\7\0\10\6\1\264\16\6\23\0\2\6" + + "\1\0\2\6\3\0\2\6\1\0\1\6\7\0\20\6" + + "\1\265\6\6\23\0\2\6\1\0\2\6\3\0\2\6" + + "\1\0\1\6\7\0\10\6\1\266\16\6\23\0\2\6" + + "\1\0\2\6\3\0\2\6\1\0\1\6\7\0\13\6" + + "\1\267\13\6\75\0\1\270\21\0\6\161\1\271\1\235" + + "\65\161\7\236\1\272\65\236\1\0\2\6\1\0\2\6" + + "\3\0\2\6\1\0\1\6\7\0\23\6\1\273\3\6" + + "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6" + + "\7\0\21\6\1\274\5\6\23\0\2\6\1\0\2\6" + + "\3\0\2\6\1\0\1\6\7\0\3\6\1\275\23\6" + + "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6" + + "\7\0\6\6\1\276\20\6\23\0\2\6\1\0\2\6" + + "\3\0\2\6\1\0\1\6\7\0\2\6\1\277\24\6" + + "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6" + + "\7\0\5\6\1\300\21\6\23\0\2\6\1\0\2\6" + + "\3\0\2\6\1\0\1\6\7\0\10\6\1\301\16\6" + + "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6" + + "\7\0\17\6\1\302\7\6\23\0\2\6\1\0\2\6" + + "\3\0\2\6\1\0\1\6\7\0\4\6\1\303\22\6" + + "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6" + + "\7\0\2\6\1\304\24\6\23\0\2\6\1\0\2\6" + + "\3\0\2\6\1\0\1\6\7\0\7\6\1\305\17\6" + + "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6" + + "\7\0\16\6\1\306\10\6\23\0\2\6\1\0\2\6" + + "\3\0\2\6\1\0\1\6\7\0\20\6\1\307\6\6" + + "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6" + + "\7\0\14\6\1\310\12\6\23\0\2\6\1\0\2\6" + + "\3\0\2\6\1\0\1\6\7\0\2\6\1\311\24\6" + + "\23\0\2\6\1\0\2\6\3\0\2\6\1\0\1\6" + + "\7\0\13\6\1\312\13\6\23\0\2\6\1\0\2\6" + + "\3\0\2\6\1\0\1\6\7\0\5\6\1\313\21\6" + + "\22\0\6\236\1\237\1\272\65\236\1\0\2\6\1\0" + + "\2\6\3\0\2\6\1\0\1\6\7\0\6\6\1\314" + + "\20\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0" + + "\1\6\7\0\12\6\1\315\14\6\23\0\2\6\1\0" + + "\2\6\3\0\2\6\1\0\1\6\7\0\14\6\1\316" + + "\12\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0" + + "\1\6\7\0\14\6\1\317\12\6\23\0\2\6\1\0" + + "\2\6\3\0\2\6\1\0\1\6\7\0\10\6\1\320" + + "\16\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0" + + "\1\6\7\0\20\6\1\321\6\6\23\0\2\6\1\0" + + "\2\6\3\0\2\6\1\0\1\6\7\0\10\6\1\322" + + "\16\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0" + + "\1\6\7\0\5\6\1\323\21\6\23\0\2\6\1\0" + + "\2\6\3\0\2\6\1\0\1\6\7\0\12\6\1\324" + + "\14\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0" + + "\1\6\7\0\12\6\1\325\14\6\23\0\2\6\1\0" + + "\2\6\3\0\2\6\1\0\1\6\7\0\12\6\1\326" + + "\14\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0" + + "\1\6\7\0\21\6\1\327\5\6\23\0\2\6\1\0" + + "\2\6\3\0\2\6\1\0\1\6\7\0\22\6\1\330" + + "\4\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0" + + "\1\6\7\0\2\6\1\331\24\6\23\0\2\6\1\0" + + "\2\6\3\0\2\6\1\0\1\6\7\0\17\6\1\332" + + "\7\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0" + + "\1\6\7\0\4\6\1\333\22\6\23\0\2\6\1\0" + + "\2\6\3\0\2\6\1\0\1\6\7\0\5\6\1\334" + + "\21\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0" + + "\1\6\7\0\12\6\1\335\14\6\23\0\2\6\1\0" + + "\2\6\3\0\2\6\1\0\1\6\7\0\5\6\1\336" + + "\21\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0" + + "\1\6\7\0\5\6\1\337\21\6\23\0\2\6\1\0" + + "\2\6\3\0\2\6\1\0\1\6\7\0\13\6\1\340" + + "\13\6\23\0\2\6\1\0\2\6\3\0\2\6\1\0" + + "\1\6\7\0\21\6\1\341\5\6\23\0\2\6\1\0" + + "\2\6\3\0\2\6\1\0\1\6\7\0\6\6\1\342" + + "\20\6\22\0"; + + private static int[] zzUnpackTrans() { + int[] result = new int[9577]; + int offset = 0; + offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); + return result; + } - /** this buffer contains the current text to be matched and is - the source of the yytext() string */ - private CharSequence zzBuffer = ""; + private static int zzUnpackTrans(String packed, int offset, int[] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + value--; + do result[j++] = value; + while (--count > 0); + } + return j; + } - /** the textposition at the last accepting state */ - private int zzMarkedPos; - /** the textposition at the last state to be included in yytext */ - private int zzPushbackPos; + /* error codes */ + private static final int ZZ_UNKNOWN_ERROR = 0; + private static final int ZZ_NO_MATCH = 1; + private static final int ZZ_PUSHBACK_2BIG = 2; + private static final char[] EMPTY_BUFFER = new char[0]; + private static final int YYEOF = -1; + + /* error messages for the codes above */ + private static final String ZZ_ERROR_MSG[] = { + "Unkown internal scanner error", + "Error: could not match input", + "Error: pushback value was too large" + }; + + /** + * ZZ_ATTRIBUTE[aState] contains the attributes of state aState + */ + private static final int[] ZZ_ATTRIBUTE = zzUnpackAttribute(); + + private static final String ZZ_ATTRIBUTE_PACKED_0 = + "\2\0\1\10\1\11\4\1\1\11\5\1\2\11\30\1" + + "\11\11\10\1\1\0\2\1\3\11\2\1\1\11\36\1" + + "\3\11\1\1\11\11\6\1\2\0\42\1\3\11\1\1" + + "\1\11\1\0\1\1\1\11\30\1\2\11\1\0\50\1"; + + private static int[] zzUnpackAttribute() { + int[] result = new int[226]; + int offset = 0; + offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); + return result; + } - /** the current text position in the buffer */ - private int zzCurrentPos; + private static int zzUnpackAttribute(String packed, int offset, int[] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; + while (--count > 0); + } + return j; + } - /** startRead marks the beginning of the yytext() string in the buffer */ - private int zzStartRead; + /** + * the current state of the DFA + */ + private int zzState; + + /** + * the current lexical state + */ + private int zzLexicalState = YYINITIAL; + + /** + * this buffer contains the current text to be matched and is + * the source of the yytext() string + */ + private CharSequence zzBuffer = ""; + + /** + * the textposition at the last accepting state + */ + private int zzMarkedPos; + + /** + * the textposition at the last state to be included in yytext + */ + private int zzPushbackPos; + + /** + * the current text position in the buffer + */ + private int zzCurrentPos; + + /** + * startRead marks the beginning of the yytext() string in the buffer + */ + private int zzStartRead; + + /** + * endRead marks the last character in the buffer, that has been read + * from input + */ + private int zzEndRead; + + /** + * zzAtBOL == true <=> the scanner is currently at the beginning of a line + */ + private boolean zzAtBOL = true; + + /** + * zzAtEOF == true <=> the scanner is at the EOF + */ + private boolean zzAtEOF; + + private IElementType myTokenType; + private int myState; + + /** + * denotes if the user-EOF-code has already been executed + */ + private boolean zzEOFDone; + + + /** + * Unpacks the compressed character translation table. + * + * @param packed the packed character translation table + * @return the unpacked character translation table + */ + private static char[] zzUnpackCMap(String packed) { + char[] map = new char[0x10000]; + int i = 0; /* index in packed string */ + int j = 0; /* index in unpacked array */ + while (i < 1772) { + int count = packed.charAt(i++); + char value = packed.charAt(i++); + do map[j++] = value; + while (--count > 0); + } + return map; + } - /** endRead marks the last character in the buffer, that has been read - from input */ - private int zzEndRead; + @Override + public IElementType getTokenType() { + if (myTokenType == null) { + locateToken(); + } + return myTokenType; + } - /** - * zzAtBOL == true <=> the scanner is currently at the beginning of a line - */ - private boolean zzAtBOL = true; + @Override + public final int getTokenStart() { + if (myTokenType == null) { + locateToken(); + } + return zzStartRead; + } - /** zzAtEOF == true <=> the scanner is at the EOF */ - private boolean zzAtEOF; + @Override + public final int getTokenEnd() { + if (myTokenType == null) { + locateToken(); + } + return getTokenStart() + yylength(); + } - private IElementType myTokenType; - private int myState; + @Override + public void advance() { + if (myTokenType == null) { + locateToken(); + } + myTokenType = null; + } - /** denotes if the user-EOF-code has already been executed */ - private boolean zzEOFDone; + @Override + public int getState() { + if (myTokenType == null) { + locateToken(); + } + return myState; + } + @Override + public void start(CharSequence buffer, int startOffset, int endOffset, int initialState) { + reset(buffer, startOffset, endOffset, initialState); + myTokenType = null; + } + @Override + public CharSequence getBufferSequence() { + return zzBuffer; + } - /** - * Unpacks the compressed character translation table. - * - * @param packed the packed character translation table - * @return the unpacked character translation table - */ - private static char [] zzUnpackCMap(String packed) { - char [] map = new char[0x10000]; - int i = 0; /* index in packed string */ - int j = 0; /* index in unpacked array */ - while (i < 1772) { - int count = packed.charAt(i++); - char value = packed.charAt(i++); - do map[j++] = value; while (--count > 0); + @Override + public int getBufferEnd() { + return zzEndRead; } - return map; - } - - @Override - public IElementType getTokenType() { - if (myTokenType == null) locateToken(); - return myTokenType; - } - - @Override - public final int getTokenStart(){ - if (myTokenType == null) locateToken(); - return zzStartRead; - } - - @Override - public final int getTokenEnd(){ - if (myTokenType == null) locateToken(); - return getTokenStart() + yylength(); - } - - @Override - public void advance() { - if (myTokenType == null) locateToken(); - myTokenType = null; - } - - @Override - public int getState() { - if (myTokenType == null) locateToken(); - return myState; - } - - @Override - public void start(final CharSequence buffer, int startOffset, int endOffset, final int initialState) { - reset(buffer, startOffset, endOffset, initialState); - myTokenType = null; - } - - @Override - public CharSequence getBufferSequence() { - return zzBuffer; - } - - @Override - public int getBufferEnd() { - return zzEndRead; - } - - public void reset(CharSequence buffer, int start, int end,int initialState){ - zzBuffer = buffer; - zzCurrentPos = zzMarkedPos = zzStartRead = start; - zzPushbackPos = 0; - zzAtEOF = false; - zzAtBOL = true; - zzEndRead = end; - yybegin(initialState); - myTokenType = null; - } - - private void locateToken() { - if (myTokenType != null) return; - try { - myState = yystate(); - myTokenType = advanceImpl(); - } - catch (java.io.IOException e) { /*Can't happen*/ } - catch (Error e) { - // add lexer class name to the error - final Error error = new Error(getClass().getName() + ": " + e.getMessage()); - error.setStackTrace(e.getStackTrace()); - throw error; - } - } - - /** - * Refills the input buffer. - * - * @return false, iff there was new input. - * - * @exception java.io.IOException if any I/O-Error occurs - */ - private boolean zzRefill() throws java.io.IOException { - return true; - } - - - /** - * Returns the current lexical state. - */ - public final int yystate() { - return zzLexicalState; - } - - - /** - * Enters a new lexical state - * - * @param newState the new lexical state - */ - public final void yybegin(int newState) { - zzLexicalState = newState; - } - - - /** - * Returns the text matched by the current regular expression. - */ - public final CharSequence yytext() { - return zzBuffer.subSequence(zzStartRead, zzMarkedPos); - } - - - /** - * Returns the character at position pos from the - * matched text. - * - * It is equivalent to yytext().charAt(pos), but faster - * - * @param pos the position of the character to fetch. - * A value from 0 to yylength()-1. - * - * @return the character at position pos - */ - public final char yycharat(int pos) { - return zzBuffer.charAt(zzStartRead+pos); - } - - - /** - * Returns the length of the matched text region. - */ - public final int yylength() { - return zzMarkedPos-zzStartRead; - } - - - /** - * Reports an error that occured while scanning. - * - * In a wellformed scanner (no or only correct usage of - * yypushback(int) and a match-all fallback rule) this method - * will only be called with things that "Can't Possibly Happen". - * If this method is called, something is seriously wrong - * (e.g. a JFlex bug producing a faulty scanner etc.). - * - * Usual syntax/scanner level error handling should be done - * in error fallback rules. - * - * @param errorCode the code of the errormessage to display - */ - private void zzScanError(int errorCode) { - String message; - try { - message = ZZ_ERROR_MSG[errorCode]; + + public void reset(CharSequence buffer, int start, int end, int initialState) { + zzBuffer = buffer; + zzCurrentPos = zzMarkedPos = zzStartRead = start; + zzPushbackPos = 0; + zzAtEOF = false; + zzAtBOL = true; + zzEndRead = end; + yybegin(initialState); + myTokenType = null; } - catch (ArrayIndexOutOfBoundsException e) { - message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; + + private void locateToken() { + if (myTokenType != null) { + return; + } + try { + myState = yystate(); + myTokenType = advanceImpl(); + } + catch (java.io.IOException e) { /*Can't happen*/ } + catch (Error e) { + // add lexer class name to the error + Error error = new Error(getClass().getName() + ": " + e.getMessage()); + error.setStackTrace(e.getStackTrace()); + throw error; + } } - throw new Error(message); - } - - - /** - * Pushes the specified amount of characters back into the input stream. - * - * They will be read again by then next call of the scanning method - * - * @param number the number of characters to be read again. - * This number must not be greater than yylength()! - */ - public void yypushback(int number) { - if ( number > yylength() ) - zzScanError(ZZ_PUSHBACK_2BIG); - - zzMarkedPos -= number; - } - - - /** - * Contains user EOF-code, which will be executed exactly once, - * when the end of file is reached - */ - private void zzDoEOF() { - if (!zzEOFDone) { - zzEOFDone = true; - + /** + * Refills the input buffer. + * + * @return false, iff there was new input. + * @throws java.io.IOException if any I/O-Error occurs + */ + private boolean zzRefill() throws java.io.IOException { + return true; } - } - /** - * Resumes scanning until the next regular expression is matched, - * the end of input is encountered or an I/O-Error occurs. - * - * @return the next token - * @exception java.io.IOException if any I/O-Error occurs - */ - public IElementType advanceImpl() throws java.io.IOException { - int zzInput; - int zzAction; + /** + * Returns the current lexical state. + */ + public final int yystate() { + return zzLexicalState; + } - // cached fields: - int zzCurrentPosL; - int zzMarkedPosL; - int zzEndReadL = zzEndRead; - CharSequence zzBufferL = zzBuffer; - char [] zzCMapL = ZZ_CMAP; - int [] zzTransL = ZZ_TRANS; - int [] zzRowMapL = ZZ_ROWMAP; - int [] zzAttrL = ZZ_ATTRIBUTE; + /** + * Enters a new lexical state + * + * @param newState the new lexical state + */ + public final void yybegin(int newState) { + zzLexicalState = newState; + } - while (true) { - zzMarkedPosL = zzMarkedPos; - zzAction = -1; + /** + * Returns the text matched by the current regular expression. + */ + public final CharSequence yytext() { + return zzBuffer.subSequence(zzStartRead, zzMarkedPos); + } - zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; - zzState = ZZ_LEXSTATE[zzLexicalState]; + /** + * Returns the character at position pos from the + * matched text. + *

+ * It is equivalent to yytext().charAt(pos), but faster + * + * @param pos the position of the character to fetch. + * A value from 0 to yylength()-1. + * @return the character at position pos + */ + public final char yycharat(int pos) { + return zzBuffer.charAt(zzStartRead + pos); + } - zzForAction: { - while (true) { + /** + * Returns the length of the matched text region. + */ + public final int yylength() { + return zzMarkedPos - zzStartRead; + } - if (zzCurrentPosL < zzEndReadL) - zzInput = zzBufferL.charAt(zzCurrentPosL++); - else if (zzAtEOF) { - zzInput = YYEOF; - break zzForAction; - } - else { - // store back cached positions - zzCurrentPos = zzCurrentPosL; - zzMarkedPos = zzMarkedPosL; - boolean eof = zzRefill(); - // get translated positions and possibly new buffer - zzCurrentPosL = zzCurrentPos; - zzMarkedPosL = zzMarkedPos; - zzBufferL = zzBuffer; - zzEndReadL = zzEndRead; - if (eof) { - zzInput = YYEOF; - break zzForAction; - } - else { - zzInput = zzBufferL.charAt(zzCurrentPosL++); - } - } - int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ]; - if (zzNext == -1) break zzForAction; - zzState = zzNext; - - int zzAttributes = zzAttrL[zzState]; - if ( (zzAttributes & 1) == 1 ) { - zzAction = zzState; - zzMarkedPosL = zzCurrentPosL; - if ( (zzAttributes & 8) == 8 ) break zzForAction; - } + /** + * Reports an error that occured while scanning. + *

+ * In a wellformed scanner (no or only correct usage of + * yypushback(int) and a match-all fallback rule) this method + * will only be called with things that "Can't Possibly Happen". + * If this method is called, something is seriously wrong + * (e.g. a JFlex bug producing a faulty scanner etc.). + *

+ * Usual syntax/scanner level error handling should be done + * in error fallback rules. + * + * @param errorCode the code of the errormessage to display + */ + private void zzScanError(int errorCode) { + String message; + try { + message = ZZ_ERROR_MSG[errorCode]; } - } + catch (ArrayIndexOutOfBoundsException e) { + message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; + } + + throw new Error(message); + } - // store back cached position - zzMarkedPos = zzMarkedPosL; - - switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { - case 90: - { yybegin(YYINITIAL); return JSTokenTypes.FUNCTION_KEYWORD; - } - case 94: break; - case 29: - { yybegin(YYINITIAL); return JSTokenTypes.COLON; - } - case 95: break; - case 4: - { return JSTokenTypes.WHITE_SPACE; - } - case 96: break; - case 32: - { return JSTokenTypes.REGEXP_LITERAL; - } - case 97: break; - case 83: - { yybegin(YYINITIAL); return JSTokenTypes.WHILE_KEYWORD; - } - case 98: break; - case 21: - { yybegin(YYINITIAL); return JSTokenTypes.LPAR; - } - case 99: break; - case 69: - { yybegin(DIV_OR_GT); return JSTokenTypes.TRUE_KEYWORD; - } - case 100: break; - case 44: - { yybegin(YYINITIAL); return JSTokenTypes.GE; - } - case 101: break; - case 86: - { yybegin(YYINITIAL); return JSTokenTypes.SWITCH_KEYWORD; - } - case 102: break; - case 34: - { return JSTokenTypes.C_STYLE_COMMENT; - } - case 103: break; - case 49: - { yybegin(YYINITIAL); return JSTokenTypes.OROR; - } - case 104: break; - case 56: - { return JSTokenTypes.DOC_COMMENT; - } - case 105: break; - case 58: - { yybegin(YYINITIAL); return JSTokenTypes.FOR_KEYWORD; - } - case 106: break; - case 66: - { yybegin(YYINITIAL); return JSTokenTypes.GTGTEQ; - } - case 107: break; - case 26: - { yybegin(YYINITIAL); return JSTokenTypes.COMMA; - } - case 108: break; - case 13: - { yybegin(YYINITIAL); return JSTokenTypes.EQ; - } - case 109: break; - case 37: - { yybegin(YYINITIAL); return JSTokenTypes.DO_KEYWORD; - } - case 110: break; - case 47: - { yybegin(YYINITIAL); return JSTokenTypes.ANDAND; - } - case 111: break; - case 43: - { return JSTokenTypes.PLUSPLUS; - } - case 112: break; - case 10: - { yybegin(YYINITIAL); return JSTokenTypes.STRING_LITERAL; - } - case 113: break; - case 3: - { yybegin(DIV_OR_GT); return JSTokenTypes.IDENTIFIER; - } - case 114: break; - case 5: - { return JSTokenTypes.DIV; - } - case 115: break; - case 25: - { yybegin(YYINITIAL); return JSTokenTypes.SEMICOLON; - } - case 116: break; - case 50: - { yybegin(YYINITIAL); return JSTokenTypes.XOREQ; - } - case 117: break; - case 84: - { yybegin(YYINITIAL); return JSTokenTypes.TYPEOF_KEYWORD; - } - case 118: break; - case 71: - { yybegin(YYINITIAL); return JSTokenTypes.ELSE_KEYWORD; - } - case 119: break; - case 68: - { yybegin(YYINITIAL); return JSTokenTypes.LTLTEQ; - } - case 120: break; - case 57: - { yybegin(YYINITIAL); return JSTokenTypes.TRY_KEYWORD; - } - case 121: break; - case 6: - { yybegin(YYINITIAL); return JSTokenTypes.MULT; - } - case 122: break; - case 53: - { yybegin(YYINITIAL); return JSTokenTypes.MULTEQ; - } - case 123: break; - case 17: - { yybegin(YYINITIAL); return JSTokenTypes.AND; - } - case 124: break; - case 60: - { yybegin(YYINITIAL); return JSTokenTypes.SET_KEYWORD; - } - case 125: break; - case 64: - { yybegin(YYINITIAL); return JSTokenTypes.EQEQEQ; - } - case 126: break; - case 70: - { yybegin(DIV_OR_GT); return JSTokenTypes.THIS_KEYWORD; - } - case 127: break; - case 36: - { yybegin(YYINITIAL); return JSTokenTypes.MINUSEQ; - } - case 128: break; - case 52: - { yybegin(YYINITIAL); return JSTokenTypes.DIVEQ; - } - case 129: break; - case 63: - { yybegin(YYINITIAL); return JSTokenTypes.GET_KEYWORD; - } - case 130: break; - case 62: - { yybegin(YYINITIAL); return JSTokenTypes.VAR_KEYWORD; - } - case 131: break; - case 15: - { yybegin(YYINITIAL); return JSTokenTypes.PLUS; - } - case 132: break; - case 33: - { return JSTokenTypes.END_OF_LINE_COMMENT; - } - case 133: break; - case 72: - { yybegin(DIV_OR_GT); return JSTokenTypes.NULL_KEYWORD; - } - case 134: break; - case 80: - { yybegin(YYINITIAL); return JSTokenTypes.CATCH_KEYWORD; - } - case 135: break; - case 40: - { yybegin(YYINITIAL); return JSTokenTypes.EQEQ; - } - case 136: break; - case 1: - { return JSTokenTypes.BAD_CHARACTER; - } - case 137: break; - case 88: - { yybegin(YYINITIAL); return JSTokenTypes.FINALLY_KEYWORD; - } - case 138: break; - case 87: - { yybegin(YYINITIAL); return JSTokenTypes.DELETE_KEYWORD; - } - case 139: break; - case 77: - { yybegin(YYINITIAL); return JSTokenTypes.THROW_KEYWORD; - } - case 140: break; - case 81: - { yybegin(YYINITIAL); return JSTokenTypes.CONST_KEYWORD; - } - case 141: break; - case 46: - { yybegin(YYINITIAL); return JSTokenTypes.ANDEQ; - } - case 142: break; - case 55: - { yybegin(YYINITIAL); return JSTokenTypes.LTLT; - } - case 143: break; - case 31: - { yybegin(YYINITIAL); return JSTokenTypes.LT; - } - case 144: break; - case 75: - { yybegin(YYINITIAL); return JSTokenTypes.VOID_KEYWORD; - } - case 145: break; - case 14: - { yybegin(YYINITIAL); return JSTokenTypes.EXCL; - } - case 146: break; - case 38: - { yybegin(YYINITIAL); return JSTokenTypes.IF_KEYWORD; - } - case 147: break; - case 65: - { yybegin(YYINITIAL); return JSTokenTypes.NEQEQ; - } - case 148: break; - case 42: - { yybegin(YYINITIAL); return JSTokenTypes.PLUSEQ; - } - case 149: break; - case 48: - { yybegin(YYINITIAL); return JSTokenTypes.OREQ; - } - case 150: break; - case 91: - { yybegin(YYINITIAL); return JSTokenTypes.CONTINUE_KEYWORD; - } - case 151: break; - case 67: - { yybegin(YYINITIAL); return JSTokenTypes.GTGTGT; - } - case 152: break; - case 45: - { yybegin(YYINITIAL); return JSTokenTypes.GTGT; - } - case 153: break; - case 27: - { yybegin(YYINITIAL); return JSTokenTypes.TILDE; - } - case 154: break; - case 89: - { yybegin(YYINITIAL); return JSTokenTypes.DEFAULT_KEYWORD; - } - case 155: break; - case 59: - { yybegin(YYINITIAL); return JSTokenTypes.LET_KEYWORD; - } - case 156: break; - case 2: - { yybegin(DIV_OR_GT); return JSTokenTypes.NUMERIC_LITERAL; - } - case 157: break; - case 19: - { yybegin(YYINITIAL); return JSTokenTypes.XOR; - } - case 158: break; - case 30: - { yybegin(YYINITIAL); return JSTokenTypes.DIV; - } - case 159: break; - case 16: - { yybegin(YYINITIAL); return JSTokenTypes.GT; - } - case 160: break; - case 39: - { yybegin(YYINITIAL); return JSTokenTypes.IN_KEYWORD; - } - case 161: break; - case 85: - { yybegin(YYINITIAL); return JSTokenTypes.RETURN_KEYWORD; - } - case 162: break; - case 82: - { yybegin(YYINITIAL); return JSTokenTypes.YIELD_KEYWORD; - } - case 163: break; - case 61: - { yybegin(YYINITIAL); return JSTokenTypes.NEW_KEYWORD; - } - case 164: break; - case 78: - { yybegin(DIV_OR_GT); return JSTokenTypes.FALSE_KEYWORD; - } - case 165: break; - case 9: - { return JSTokenTypes.SINGLE_QUOTE_STRING_LITERAL; - } - case 166: break; - case 18: - { yybegin(YYINITIAL); return JSTokenTypes.OR; - } - case 167: break; - case 51: - { yybegin(YYINITIAL); return JSTokenTypes.PERCEQ; - } - case 168: break; - case 8: - { yybegin(YYINITIAL); return JSTokenTypes.MINUS; - } - case 169: break; - case 35: - { return JSTokenTypes.MINUSMINUS; - } - case 170: break; - case 28: - { yybegin(YYINITIAL); return JSTokenTypes.QUEST; - } - case 171: break; - case 79: - { yybegin(YYINITIAL); return JSTokenTypes.BREAK_KEYWORD; - } - case 172: break; - case 7: - { yybegin(YYINITIAL); return JSTokenTypes.DOT; - } - case 173: break; - case 73: - { yybegin(YYINITIAL); return JSTokenTypes.CASE_KEYWORD; - } - case 174: break; - case 12: - { yybegin(DIV_OR_GT); return JSTokenTypes.RBRACKET; - } - case 175: break; - case 24: - { yybegin(YYINITIAL); return JSTokenTypes.RBRACE; - } - case 176: break; - case 93: - { yybegin(YYINITIAL); return JSTokenTypes.INSTANCEOF_KEYWORD; - } - case 177: break; - case 41: - { yybegin(YYINITIAL); return JSTokenTypes.NE; - } - case 178: break; - case 23: - { yybegin(YYINITIAL); return JSTokenTypes.LBRACE; - } - case 179: break; - case 22: - { yybegin(DIV_OR_GT); return JSTokenTypes.RPAR; - } - case 180: break; - case 20: - { yybegin(YYINITIAL); return JSTokenTypes.PERC; - } - case 181: break; - case 74: - { yybegin(YYINITIAL); return JSTokenTypes.WITH_KEYWORD; - } - case 182: break; - case 54: - { yybegin(YYINITIAL); return JSTokenTypes.LE; - } - case 183: break; - case 11: - { yybegin(YYINITIAL); return JSTokenTypes.LBRACKET; - } - case 184: break; - case 76: - { yybegin(YYINITIAL); return JSTokenTypes.GTGTGTEQ; - } - case 185: break; - case 92: - { yybegin(DIV_OR_GT); return JSTokenTypes.UNDEFINED_KEYWORD; - } - case 186: break; - default: - if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { - zzAtEOF = true; - zzDoEOF(); - return null; - } - else { - zzScanError(ZZ_NO_MATCH); - } + + /** + * Pushes the specified amount of characters back into the input stream. + *

+ * They will be read again by then next call of the scanning method + * + * @param number the number of characters to be read again. + * This number must not be greater than yylength()! + */ + public void yypushback(int number) { + if (number > yylength()) { + zzScanError(ZZ_PUSHBACK_2BIG); } + + zzMarkedPos -= number; + } + + + /** + * Contains user EOF-code, which will be executed exactly once, + * when the end of file is reached + */ + private void zzDoEOF() { + if (!zzEOFDone) { + zzEOFDone = true; + + } } - } + /** + * Resumes scanning until the next regular expression is matched, + * the end of input is encountered or an I/O-Error occurs. + * + * @return the next token + * @throws java.io.IOException if any I/O-Error occurs + */ + public IElementType advanceImpl() throws java.io.IOException { + int zzInput; + int zzAction; + + // cached fields: + int zzCurrentPosL; + int zzMarkedPosL; + int zzEndReadL = zzEndRead; + CharSequence zzBufferL = zzBuffer; + char[] zzCMapL = ZZ_CMAP; + + int[] zzTransL = ZZ_TRANS; + int[] zzRowMapL = ZZ_ROWMAP; + int[] zzAttrL = ZZ_ATTRIBUTE; + + while (true) { + zzMarkedPosL = zzMarkedPos; + + zzAction = -1; + + zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; + + zzState = ZZ_LEXSTATE[zzLexicalState]; + + + zzForAction: + { + while (true) { + + if (zzCurrentPosL < zzEndReadL) { + zzInput = zzBufferL.charAt(zzCurrentPosL++); + } + else if (zzAtEOF) { + zzInput = YYEOF; + break zzForAction; + } + else { + // store back cached positions + zzCurrentPos = zzCurrentPosL; + zzMarkedPos = zzMarkedPosL; + boolean eof = zzRefill(); + // get translated positions and possibly new buffer + zzCurrentPosL = zzCurrentPos; + zzMarkedPosL = zzMarkedPos; + zzBufferL = zzBuffer; + zzEndReadL = zzEndRead; + if (eof) { + zzInput = YYEOF; + break zzForAction; + } + else { + zzInput = zzBufferL.charAt(zzCurrentPosL++); + } + } + int zzNext = zzTransL[zzRowMapL[zzState] + zzCMapL[zzInput]]; + if (zzNext == -1) { + break zzForAction; + } + zzState = zzNext; + + int zzAttributes = zzAttrL[zzState]; + if ((zzAttributes & 1) == 1) { + zzAction = zzState; + zzMarkedPosL = zzCurrentPosL; + if ((zzAttributes & 8) == 8) { + break zzForAction; + } + } + + } + } + + // store back cached position + zzMarkedPos = zzMarkedPosL; + + switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { + case 90: { + yybegin(YYINITIAL); + return JSTokenTypes.FUNCTION_KEYWORD; + } + case 94: + break; + case 29: { + yybegin(YYINITIAL); + return JSTokenTypes.COLON; + } + case 95: + break; + case 4: { + return JSTokenTypes.WHITE_SPACE; + } + case 96: + break; + case 32: { + return JSTokenTypes.REGEXP_LITERAL; + } + case 97: + break; + case 83: { + yybegin(YYINITIAL); + return JSTokenTypes.WHILE_KEYWORD; + } + case 98: + break; + case 21: { + yybegin(YYINITIAL); + return JSTokenTypes.LPAR; + } + case 99: + break; + case 69: { + yybegin(DIV_OR_GT); + return JSTokenTypes.TRUE_KEYWORD; + } + case 100: + break; + case 44: { + yybegin(YYINITIAL); + return JSTokenTypes.GE; + } + case 101: + break; + case 86: { + yybegin(YYINITIAL); + return JSTokenTypes.SWITCH_KEYWORD; + } + case 102: + break; + case 34: { + return JSTokenTypes.C_STYLE_COMMENT; + } + case 103: + break; + case 49: { + yybegin(YYINITIAL); + return JSTokenTypes.OROR; + } + case 104: + break; + case 56: { + return JSTokenTypes.DOC_COMMENT; + } + case 105: + break; + case 58: { + yybegin(YYINITIAL); + return JSTokenTypes.FOR_KEYWORD; + } + case 106: + break; + case 66: { + yybegin(YYINITIAL); + return JSTokenTypes.GTGTEQ; + } + case 107: + break; + case 26: { + yybegin(YYINITIAL); + return JSTokenTypes.COMMA; + } + case 108: + break; + case 13: { + yybegin(YYINITIAL); + return JSTokenTypes.EQ; + } + case 109: + break; + case 37: { + yybegin(YYINITIAL); + return JSTokenTypes.DO_KEYWORD; + } + case 110: + break; + case 47: { + yybegin(YYINITIAL); + return JSTokenTypes.ANDAND; + } + case 111: + break; + case 43: { + return JSTokenTypes.PLUSPLUS; + } + case 112: + break; + case 10: { + yybegin(YYINITIAL); + return JSTokenTypes.STRING_LITERAL; + } + case 113: + break; + case 3: { + yybegin(DIV_OR_GT); + return JSTokenTypes.IDENTIFIER; + } + case 114: + break; + case 5: { + return JSTokenTypes.DIV; + } + case 115: + break; + case 25: { + yybegin(YYINITIAL); + return JSTokenTypes.SEMICOLON; + } + case 116: + break; + case 50: { + yybegin(YYINITIAL); + return JSTokenTypes.XOREQ; + } + case 117: + break; + case 84: { + yybegin(YYINITIAL); + return JSTokenTypes.TYPEOF_KEYWORD; + } + case 118: + break; + case 71: { + yybegin(YYINITIAL); + return JSTokenTypes.ELSE_KEYWORD; + } + case 119: + break; + case 68: { + yybegin(YYINITIAL); + return JSTokenTypes.LTLTEQ; + } + case 120: + break; + case 57: { + yybegin(YYINITIAL); + return JSTokenTypes.TRY_KEYWORD; + } + case 121: + break; + case 6: { + yybegin(YYINITIAL); + return JSTokenTypes.MULT; + } + case 122: + break; + case 53: { + yybegin(YYINITIAL); + return JSTokenTypes.MULTEQ; + } + case 123: + break; + case 17: { + yybegin(YYINITIAL); + return JSTokenTypes.AND; + } + case 124: + break; + case 60: { + yybegin(YYINITIAL); + return JSTokenTypes.SET_KEYWORD; + } + case 125: + break; + case 64: { + yybegin(YYINITIAL); + return JSTokenTypes.EQEQEQ; + } + case 126: + break; + case 70: { + yybegin(DIV_OR_GT); + return JSTokenTypes.THIS_KEYWORD; + } + case 127: + break; + case 36: { + yybegin(YYINITIAL); + return JSTokenTypes.MINUSEQ; + } + case 128: + break; + case 52: { + yybegin(YYINITIAL); + return JSTokenTypes.DIVEQ; + } + case 129: + break; + case 63: { + yybegin(YYINITIAL); + return JSTokenTypes.GET_KEYWORD; + } + case 130: + break; + case 62: { + yybegin(YYINITIAL); + return JSTokenTypes.VAR_KEYWORD; + } + case 131: + break; + case 15: { + yybegin(YYINITIAL); + return JSTokenTypes.PLUS; + } + case 132: + break; + case 33: { + return JSTokenTypes.END_OF_LINE_COMMENT; + } + case 133: + break; + case 72: { + yybegin(DIV_OR_GT); + return JSTokenTypes.NULL_KEYWORD; + } + case 134: + break; + case 80: { + yybegin(YYINITIAL); + return JSTokenTypes.CATCH_KEYWORD; + } + case 135: + break; + case 40: { + yybegin(YYINITIAL); + return JSTokenTypes.EQEQ; + } + case 136: + break; + case 1: { + return JSTokenTypes.BAD_CHARACTER; + } + case 137: + break; + case 88: { + yybegin(YYINITIAL); + return JSTokenTypes.FINALLY_KEYWORD; + } + case 138: + break; + case 87: { + yybegin(YYINITIAL); + return JSTokenTypes.DELETE_KEYWORD; + } + case 139: + break; + case 77: { + yybegin(YYINITIAL); + return JSTokenTypes.THROW_KEYWORD; + } + case 140: + break; + case 81: { + yybegin(YYINITIAL); + return JSTokenTypes.CONST_KEYWORD; + } + case 141: + break; + case 46: { + yybegin(YYINITIAL); + return JSTokenTypes.ANDEQ; + } + case 142: + break; + case 55: { + yybegin(YYINITIAL); + return JSTokenTypes.LTLT; + } + case 143: + break; + case 31: { + yybegin(YYINITIAL); + return JSTokenTypes.LT; + } + case 144: + break; + case 75: { + yybegin(YYINITIAL); + return JSTokenTypes.VOID_KEYWORD; + } + case 145: + break; + case 14: { + yybegin(YYINITIAL); + return JSTokenTypes.EXCL; + } + case 146: + break; + case 38: { + yybegin(YYINITIAL); + return JSTokenTypes.IF_KEYWORD; + } + case 147: + break; + case 65: { + yybegin(YYINITIAL); + return JSTokenTypes.NEQEQ; + } + case 148: + break; + case 42: { + yybegin(YYINITIAL); + return JSTokenTypes.PLUSEQ; + } + case 149: + break; + case 48: { + yybegin(YYINITIAL); + return JSTokenTypes.OREQ; + } + case 150: + break; + case 91: { + yybegin(YYINITIAL); + return JSTokenTypes.CONTINUE_KEYWORD; + } + case 151: + break; + case 67: { + yybegin(YYINITIAL); + return JSTokenTypes.GTGTGT; + } + case 152: + break; + case 45: { + yybegin(YYINITIAL); + return JSTokenTypes.GTGT; + } + case 153: + break; + case 27: { + yybegin(YYINITIAL); + return JSTokenTypes.TILDE; + } + case 154: + break; + case 89: { + yybegin(YYINITIAL); + return JSTokenTypes.DEFAULT_KEYWORD; + } + case 155: + break; + case 59: { + yybegin(YYINITIAL); + return JSTokenTypes.LET_KEYWORD; + } + case 156: + break; + case 2: { + yybegin(DIV_OR_GT); + return JSTokenTypes.NUMERIC_LITERAL; + } + case 157: + break; + case 19: { + yybegin(YYINITIAL); + return JSTokenTypes.XOR; + } + case 158: + break; + case 30: { + yybegin(YYINITIAL); + return JSTokenTypes.DIV; + } + case 159: + break; + case 16: { + yybegin(YYINITIAL); + return JSTokenTypes.GT; + } + case 160: + break; + case 39: { + yybegin(YYINITIAL); + return JSTokenTypes.IN_KEYWORD; + } + case 161: + break; + case 85: { + yybegin(YYINITIAL); + return JSTokenTypes.RETURN_KEYWORD; + } + case 162: + break; + case 82: { + yybegin(YYINITIAL); + return JSTokenTypes.YIELD_KEYWORD; + } + case 163: + break; + case 61: { + yybegin(YYINITIAL); + return JSTokenTypes.NEW_KEYWORD; + } + case 164: + break; + case 78: { + yybegin(DIV_OR_GT); + return JSTokenTypes.FALSE_KEYWORD; + } + case 165: + break; + case 9: { + return JSTokenTypes.SINGLE_QUOTE_STRING_LITERAL; + } + case 166: + break; + case 18: { + yybegin(YYINITIAL); + return JSTokenTypes.OR; + } + case 167: + break; + case 51: { + yybegin(YYINITIAL); + return JSTokenTypes.PERCEQ; + } + case 168: + break; + case 8: { + yybegin(YYINITIAL); + return JSTokenTypes.MINUS; + } + case 169: + break; + case 35: { + return JSTokenTypes.MINUSMINUS; + } + case 170: + break; + case 28: { + yybegin(YYINITIAL); + return JSTokenTypes.QUEST; + } + case 171: + break; + case 79: { + yybegin(YYINITIAL); + return JSTokenTypes.BREAK_KEYWORD; + } + case 172: + break; + case 7: { + yybegin(YYINITIAL); + return JSTokenTypes.DOT; + } + case 173: + break; + case 73: { + yybegin(YYINITIAL); + return JSTokenTypes.CASE_KEYWORD; + } + case 174: + break; + case 12: { + yybegin(DIV_OR_GT); + return JSTokenTypes.RBRACKET; + } + case 175: + break; + case 24: { + yybegin(YYINITIAL); + return JSTokenTypes.RBRACE; + } + case 176: + break; + case 93: { + yybegin(YYINITIAL); + return JSTokenTypes.INSTANCEOF_KEYWORD; + } + case 177: + break; + case 41: { + yybegin(YYINITIAL); + return JSTokenTypes.NE; + } + case 178: + break; + case 23: { + yybegin(YYINITIAL); + return JSTokenTypes.LBRACE; + } + case 179: + break; + case 22: { + yybegin(DIV_OR_GT); + return JSTokenTypes.RPAR; + } + case 180: + break; + case 20: { + yybegin(YYINITIAL); + return JSTokenTypes.PERC; + } + case 181: + break; + case 74: { + yybegin(YYINITIAL); + return JSTokenTypes.WITH_KEYWORD; + } + case 182: + break; + case 54: { + yybegin(YYINITIAL); + return JSTokenTypes.LE; + } + case 183: + break; + case 11: { + yybegin(YYINITIAL); + return JSTokenTypes.LBRACKET; + } + case 184: + break; + case 76: { + yybegin(YYINITIAL); + return JSTokenTypes.GTGTGTEQ; + } + case 185: + break; + case 92: { + yybegin(DIV_OR_GT); + return JSTokenTypes.UNDEFINED_KEYWORD; + } + case 186: + break; + default: + if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { + zzAtEOF = true; + zzDoEOF(); + return null; + } + else { + zzScanError(ZZ_NO_MATCH); + } + } + } + } } diff --git a/lang-version-impl/javascript17-impl/src/main/java/module-info.java b/lang-version-impl/javascript17-impl/src/main/java/module-info.java index bdde4e91..4fa46039 100644 --- a/lang-version-impl/javascript17-impl/src/main/java/module-info.java +++ b/lang-version-impl/javascript17-impl/src/main/java/module-info.java @@ -2,10 +2,9 @@ * @author VISTALL * @since 23-Aug-22 */ -module consulo.javascript.javascript17.impl -{ - requires transitive consulo.javascript.base.impl; +module consulo.javascript.javascript17.impl { + requires transitive consulo.javascript.base.impl; - exports consulo.javascript.javascript17.lang; - exports consulo.javascript.javascript17.lang.lexer; + exports consulo.javascript.javascript17.lang; + exports consulo.javascript.javascript17.lang.lexer; } \ No newline at end of file diff --git a/lang-version-impl/javascript18-impl/pom.xml b/lang-version-impl/javascript18-impl/pom.xml index a56a5593..513cfbcc 100644 --- a/lang-version-impl/javascript18-impl/pom.xml +++ b/lang-version-impl/javascript18-impl/pom.xml @@ -32,7 +32,7 @@ consulo - https://maven.consulo.io/repository/snapshots/ + https://maven.consulo.dev/repository/snapshots/ true interval:60 diff --git a/lang-version-impl/javascript18-impl/src/main/java/consulo/javascript/javascript18/lang/JavaScript185LanguageVersion.java b/lang-version-impl/javascript18-impl/src/main/java/consulo/javascript/javascript18/lang/JavaScript185LanguageVersion.java index dd9a0fba..6fb550dc 100644 --- a/lang-version-impl/javascript18-impl/src/main/java/consulo/javascript/javascript18/lang/JavaScript185LanguageVersion.java +++ b/lang-version-impl/javascript18-impl/src/main/java/consulo/javascript/javascript18/lang/JavaScript185LanguageVersion.java @@ -21,11 +21,12 @@ import consulo.javascript.javascript17.lang.lexer.JavaScript17Lexer; import consulo.javascript.lang.BaseJavaScriptLanguageVersion; import consulo.javascript.language.JavaScriptLanguage; -import consulo.javascript.language.StandardJavaScriptVersions; +import consulo.javascript.language.StandardJavaScriptVersion; import consulo.language.editor.highlight.SyntaxHighlighter; import consulo.language.lexer.Lexer; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; + import java.util.function.Supplier; /** @@ -33,45 +34,38 @@ * @since 11.12.2015 */ @ExtensionImpl -public class JavaScript185LanguageVersion extends BaseJavaScriptLanguageVersion implements StandardJavaScriptVersions.Marker -{ - private static final Supplier ourLexerFactory = JavaScript17Lexer::new; +public class JavaScript185LanguageVersion extends BaseJavaScriptLanguageVersion implements StandardJavaScriptVersion { + private static final Supplier ourLexerFactory = JavaScript17Lexer::new; - @Nonnull - public static JavaScript185LanguageVersion getInstance() - { - return JavaScriptLanguage.INSTANCE.findVersionByClass(JavaScript185LanguageVersion.class); - } + @Nonnull + public static JavaScript185LanguageVersion getInstance() { + return JavaScriptLanguage.INSTANCE.findVersionByClass(JavaScript185LanguageVersion.class); + } - public JavaScript185LanguageVersion() - { - super("JAVASCRIPT_1_8_5"); - } + public JavaScript185LanguageVersion() { + super("JAVASCRIPT_1_8_5"); + } - @Nonnull - @Override - public String getPresentableName() - { - return "JavaScript 1.8.5"; - } + @Nonnull + @Override + public String getPresentableName() { + return "JavaScript 1.8.5"; + } - @Nonnull - @Override - public Lexer createLexer() - { - return ourLexerFactory.get(); - } + @Nonnull + @Override + public Lexer createLexer() { + return ourLexerFactory.get(); + } - @Nonnull - @Override - public SyntaxHighlighter getSyntaxHighlighter() - { - return new JavaScriptHighlighter(ourLexerFactory); - } + @Nonnull + @Override + public SyntaxHighlighter getSyntaxHighlighter() { + return new JavaScriptHighlighter(ourLexerFactory); + } - @Override - public int getWeight() - { - return 40; - } + @Override + public int getWeight() { + return 40; + } } \ No newline at end of file diff --git a/lang-version-impl/javascript18-impl/src/main/java/consulo/javascript/javascript18/lang/JavaScript18LanguageVersion.java b/lang-version-impl/javascript18-impl/src/main/java/consulo/javascript/javascript18/lang/JavaScript18LanguageVersion.java index d43a56e2..98f9195a 100644 --- a/lang-version-impl/javascript18-impl/src/main/java/consulo/javascript/javascript18/lang/JavaScript18LanguageVersion.java +++ b/lang-version-impl/javascript18-impl/src/main/java/consulo/javascript/javascript18/lang/JavaScript18LanguageVersion.java @@ -21,11 +21,11 @@ import consulo.javascript.javascript17.lang.lexer.JavaScript17Lexer; import consulo.javascript.lang.BaseJavaScriptLanguageVersion; import consulo.javascript.language.JavaScriptLanguage; -import consulo.javascript.language.StandardJavaScriptVersions; +import consulo.javascript.language.StandardJavaScriptVersion; import consulo.language.editor.highlight.SyntaxHighlighter; import consulo.language.lexer.Lexer; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; import java.util.function.Supplier; /** @@ -33,45 +33,38 @@ * @since 11.12.2015 */ @ExtensionImpl -public class JavaScript18LanguageVersion extends BaseJavaScriptLanguageVersion implements StandardJavaScriptVersions.Marker -{ - private static final Supplier ourLexerFactory = JavaScript17Lexer::new; +public class JavaScript18LanguageVersion extends BaseJavaScriptLanguageVersion implements StandardJavaScriptVersion { + private static final Supplier ourLexerFactory = JavaScript17Lexer::new; - @Nonnull - public static JavaScript18LanguageVersion getInstance() - { - return JavaScriptLanguage.INSTANCE.findVersionByClass(JavaScript18LanguageVersion.class); - } + @Nonnull + public static JavaScript18LanguageVersion getInstance() { + return JavaScriptLanguage.INSTANCE.findVersionByClass(JavaScript18LanguageVersion.class); + } - public JavaScript18LanguageVersion() - { - super("JAVASCRIPT_1_8"); - } + public JavaScript18LanguageVersion() { + super("JAVASCRIPT_1_8"); + } - @Nonnull - @Override - public String getPresentableName() - { - return "JavaScript 1.8"; - } + @Nonnull + @Override + public String getPresentableName() { + return "JavaScript 1.8"; + } - @Nonnull - @Override - public Lexer createLexer() - { - return ourLexerFactory.get(); - } + @Nonnull + @Override + public Lexer createLexer() { + return ourLexerFactory.get(); + } - @Nonnull - @Override - public SyntaxHighlighter getSyntaxHighlighter() - { - return new JavaScriptHighlighter(ourLexerFactory); - } + @Nonnull + @Override + public SyntaxHighlighter getSyntaxHighlighter() { + return new JavaScriptHighlighter(ourLexerFactory); + } - @Override - public int getWeight() - { - return 30; - } + @Override + public int getWeight() { + return 30; + } } \ No newline at end of file diff --git a/lang-version-impl/javascript18-impl/src/main/java/module-info.java b/lang-version-impl/javascript18-impl/src/main/java/module-info.java index f169dd24..0693d8fc 100644 --- a/lang-version-impl/javascript18-impl/src/main/java/module-info.java +++ b/lang-version-impl/javascript18-impl/src/main/java/module-info.java @@ -2,11 +2,10 @@ * @author VISTALL * @since 23-Aug-22 */ -module consulo.javascript.javascript18.impl -{ - requires transitive consulo.javascript.base.impl; +module consulo.javascript.javascript18.impl { + requires transitive consulo.javascript.base.impl; - requires consulo.javascript.javascript17.impl; + requires consulo.javascript.javascript17.impl; - exports consulo.javascript.javascript18.lang; + exports consulo.javascript.javascript18.lang; } \ No newline at end of file diff --git a/lang-version-impl/json-javascript-impl/pom.xml b/lang-version-impl/json-javascript-impl/pom.xml deleted file mode 100644 index 02047047..00000000 --- a/lang-version-impl/json-javascript-impl/pom.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - 4.0.0 - - consulo - arch.ide-api-provided - 3-SNAPSHOT - - - - consulo.plugin - consulo.javascript-json.javascript.impl - 3-SNAPSHOT - jar - - - - consulo - https://maven.consulo.io/repository/snapshots/ - - true - interval:60 - - - - - - - ${project.groupId} - consulo.javascript-base.impl - ${project.version} - - - \ No newline at end of file diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/JsonFileType.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/JsonFileType.java deleted file mode 100644 index 455c3d39..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/JsonFileType.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2013-2014 must-be.org - * - * 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 consulo.json; - -import consulo.annotation.access.RequiredReadAction; -import consulo.javascript.icon.JavaScriptIconGroup; -import consulo.javascript.language.JavaScriptFileTypeWithVersion; -import consulo.javascript.language.JavaScriptLanguage; -import consulo.json.lang.JsonJavaScriptVersion; -import consulo.language.file.LanguageFileType; -import consulo.localize.LocalizeValue; -import consulo.module.Module; -import consulo.ui.image.Image; -import consulo.virtualFileSystem.VirtualFile; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * @author VISTALL - * @since 02.12.13. - */ -public class JsonFileType extends LanguageFileType implements JavaScriptFileTypeWithVersion -{ - public static final JsonFileType INSTANCE = new JsonFileType(); - - private JsonFileType() - { - super(JavaScriptLanguage.INSTANCE); - } - - @Nonnull - @Override - public String getId() - { - return "JSON"; - } - - @Nonnull - @Override - public LocalizeValue getDescription() - { - return LocalizeValue.localizeTODO("Json files"); - } - - @Nonnull - @Override - public String getDefaultExtension() - { - return "json"; - } - - @Nullable - @Override - public Image getIcon() - { - return JavaScriptIconGroup.json(); - } - - @RequiredReadAction - @Nonnull - @Override - public JsonJavaScriptVersion getLanguageVersion(@Nullable Module module, @Nullable VirtualFile virtualFile) - { - return JsonJavaScriptVersion.getInstance(); - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/JsonFileTypeFactory.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/JsonFileTypeFactory.java deleted file mode 100644 index ea9f6a79..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/JsonFileTypeFactory.java +++ /dev/null @@ -1,21 +0,0 @@ -package consulo.json; - -import consulo.annotation.component.ExtensionImpl; -import consulo.virtualFileSystem.fileType.FileTypeConsumer; -import consulo.virtualFileSystem.fileType.FileTypeFactory; - -import javax.annotation.Nonnull; - -/** - * @author VISTALL - * @since 05.03.2015 - */ -@ExtensionImpl -public class JsonFileTypeFactory extends FileTypeFactory -{ - @Override - public void createFileTypes(@Nonnull FileTypeConsumer consumer) - { - consumer.consume(JsonFileType.INSTANCE); - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/JomElement.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/JomElement.java deleted file mode 100644 index f45cb566..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/JomElement.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2013-2015 must-be.org - * - * 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 consulo.json.jom; - -/** - * @author VISTALL - * @since 10.11.2015 - */ -public interface JomElement -{ - -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/JomFileDescriptor.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/JomFileDescriptor.java deleted file mode 100644 index ea17af09..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/JomFileDescriptor.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2013-2015 must-be.org - * - * 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 consulo.json.jom; - -import consulo.annotation.component.ComponentScope; -import consulo.annotation.component.ExtensionAPI; -import consulo.component.extension.ExtensionPointName; -import consulo.language.psi.PsiFile; -import consulo.ui.image.Image; - -import javax.annotation.Nonnull; - -/** - * @author VISTALL - * @since 10.11.2015 - */ -@ExtensionAPI(ComponentScope.APPLICATION) -public abstract class JomFileDescriptor -{ - public static ExtensionPointName EP_NAME = ExtensionPointName.create(JomFileDescriptor.class); - - private Class myDefinitionClass; - - public JomFileDescriptor(@Nonnull Class definitionClass) - { - myDefinitionClass = definitionClass; - } - - @Nonnull - public Class getDefinitionClass() - { - return myDefinitionClass; - } - - @Nonnull - public abstract Image getIcon(); - - public abstract boolean isMyFile(@Nonnull PsiFile psiFile); -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/JomFileElement.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/JomFileElement.java deleted file mode 100644 index f6ed4647..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/JomFileElement.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2013-2015 must-be.org - * - * 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 consulo.json.jom; - -import com.intellij.lang.javascript.psi.JSFile; -import com.intellij.lang.javascript.psi.JSObjectLiteralExpression; -import consulo.json.jom.proxy.JomProxyInvocationHandler; -import consulo.language.psi.util.PsiTreeUtil; -import consulo.util.lang.lazy.LazyValue; - -import javax.annotation.Nonnull; -import java.util.function.Supplier; - -/** - * @author VISTALL - * @since 10.11.2015 - */ -public class JomFileElement -{ - private final JomFileDescriptor myFileDescriptor; - private final JSFile myPsiFile; - private final Supplier myRootValue; - - public JomFileElement(JSFile psiFile, JomFileDescriptor fileDescriptor) - { - myPsiFile = psiFile; - myFileDescriptor = fileDescriptor; - myRootValue = LazyValue.notNull(() -> (T) JomProxyInvocationHandler.createProxy(myFileDescriptor.getDefinitionClass(), PsiTreeUtil.findChildOfType(myPsiFile, JSObjectLiteralExpression.class))); - } - - @Nonnull - public T getRootElement() - { - return myRootValue.get(); - } - - @Nonnull - public JomFileDescriptor getFileDescriptor() - { - return myFileDescriptor; - } - - @Nonnull - public JSFile getFile() - { - return myPsiFile; - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/JomIconDescriptorUpdater.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/JomIconDescriptorUpdater.java deleted file mode 100644 index a2dbd22b..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/JomIconDescriptorUpdater.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2013-2015 must-be.org - * - * 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 consulo.json.jom; - -import consulo.annotation.access.RequiredReadAction; -import consulo.annotation.component.ExtensionImpl; -import consulo.language.icon.IconDescriptor; -import consulo.language.icon.IconDescriptorUpdater; -import consulo.language.psi.PsiElement; -import consulo.language.psi.PsiFile; - -import javax.annotation.Nonnull; - -/** - * @author VISTALL - * @since 10.11.2015 - */ -@ExtensionImpl -public class JomIconDescriptorUpdater implements IconDescriptorUpdater -{ - @RequiredReadAction - @Override - public void updateIcon(@Nonnull IconDescriptor iconDescriptor, @Nonnull PsiElement element, int flags) - { - if(element instanceof PsiFile) - { - JomFileElement fileElement = JomManager.getInstance(element.getProject()).getFileElement((PsiFile) element); - if(fileElement != null) - { - iconDescriptor.setMainIcon(fileElement.getFileDescriptor().getIcon()); - } - } - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/JomManager.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/JomManager.java deleted file mode 100644 index ada3199f..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/JomManager.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2013-2015 must-be.org - * - * 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 consulo.json.jom; - -import com.intellij.lang.javascript.psi.JSFile; -import consulo.annotation.access.RequiredReadAction; -import consulo.annotation.component.ComponentScope; -import consulo.annotation.component.ServiceAPI; -import consulo.annotation.component.ServiceImpl; -import consulo.application.util.CachedValue; -import consulo.application.util.CachedValueProvider; -import consulo.application.util.CachedValuesManager; -import consulo.ide.ServiceManager; -import consulo.json.JsonFileType; -import consulo.language.psi.PsiFile; -import consulo.language.psi.PsiModificationTracker; -import consulo.project.Project; -import consulo.util.dataholder.Key; -import consulo.virtualFileSystem.fileType.FileType; -import jakarta.inject.Inject; -import jakarta.inject.Singleton; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * @author VISTALL - * @since 10.11.2015 - */ -@Singleton -@ServiceAPI(ComponentScope.PROJECT) -@ServiceImpl -public class JomManager -{ - @Nonnull - public static JomManager getInstance(@Nonnull Project project) - { - return ServiceManager.getService(project, JomManager.class); - } - - private static final Key>> JOM_FILE_ELEMENT = Key.create("jom.file.lement"); - - private final Project myProject; - - @Inject - public JomManager(Project project) - { - myProject = project; - } - - @Nullable - @RequiredReadAction - @SuppressWarnings("unchecked") - public JomFileElement getFileElement(@Nonnull final PsiFile psiFile) - { - FileType fileType = psiFile.getFileType(); - if(fileType != JsonFileType.INSTANCE) - { - return null; - } - - CachedValue> cachedValue = psiFile.getUserData(JOM_FILE_ELEMENT); - if(cachedValue == null) - { - cachedValue = CachedValuesManager.getManager(myProject).createCachedValue(new CachedValueProvider>() - { - @Nullable - @Override - public Result> compute() - { - JomFileElement value = null; - JomFileDescriptor fileDescriptor = findFileDescriptor(psiFile); - if(fileDescriptor != null) - { - value = new JomFileElement((JSFile) psiFile, fileDescriptor); - } - return Result.>create(value, psiFile, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT); - } - }, false); - - psiFile.putUserData(JOM_FILE_ELEMENT, cachedValue); - } - - return (JomFileElement) cachedValue.getValue(); - } - - @Nullable - private static JomFileDescriptor findFileDescriptor(@Nonnull PsiFile psiFile) - { - JomFileDescriptor jomFileDescriptor = null; - for(JomFileDescriptor temp : JomFileDescriptor.EP_NAME.getExtensions()) - { - if(temp.isMyFile(psiFile)) - { - jomFileDescriptor = temp; - break; - } - } - return jomFileDescriptor; - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/JomModeAsJsonFileDescriptorProvider.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/JomModeAsJsonFileDescriptorProvider.java deleted file mode 100644 index 15b30c1f..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/JomModeAsJsonFileDescriptorProvider.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright 2013-2015 must-be.org - * - * 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 consulo.json.jom; - -import consulo.annotation.access.RequiredReadAction; -import consulo.annotation.component.ExtensionImpl; -import consulo.json.validation.JsonFileDescriptorProvider; -import consulo.json.validation.NativeArray; -import consulo.json.validation.descriptor.JsonObjectDescriptor; -import consulo.json.validation.descriptor.JsonPropertyDescriptor; -import consulo.language.psi.PsiFile; -import consulo.util.collection.ContainerUtil; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.math.BigInteger; -import java.util.*; - -/** - * @author VISTALL - * @since 10.11.2015 - */ -@ExtensionImpl -public class JomModeAsJsonFileDescriptorProvider implements JsonFileDescriptorProvider -{ - @RequiredReadAction - @Override - public boolean isMyFile(@Nonnull PsiFile file) - { - return JomManager.getInstance(file.getProject()).getFileElement(file) != null; - } - - @RequiredReadAction - @Override - public void fillRootObject(@Nonnull JsonObjectDescriptor root, @Nonnull PsiFile file) - { - JomFileElement fileElement = JomManager.getInstance(file.getProject()).getFileElement(file); - if(fileElement == null) - { - return; - } - - fillDescriptor(root, fileElement.getFileDescriptor().getDefinitionClass()); - } - - private static void fillDescriptor(JsonObjectDescriptor objectDescriptor, Class clazz) - { - Set methods = new HashSet(); - collectMethods(clazz, methods, new HashSet>()); - - for(Method method : methods) - { - String jsonGetPropertyName = JomUtil.getJsonGetPropertyName(method); - if(jsonGetPropertyName == null) - { - continue; - } - - JsonPropertyDescriptor propertyDescriptor = fillObjectDescriptor(objectDescriptor, method.getReturnType(), method.getGenericReturnType(), jsonGetPropertyName); - - if(method.isAnnotationPresent(Deprecated.class)) - { - propertyDescriptor.deprecated(); - } - } - } - - @Nonnull - private static JsonPropertyDescriptor fillObjectDescriptor(JsonObjectDescriptor objectDescriptor, @Nonnull Class classType, @Nonnull Type genericType, @Nullable String propertyName) - { - if(classType.isArray()) - { - Class componentType = classType.getComponentType(); - - return objectDescriptor.addProperty(propertyName, new NativeArray(componentType)); - } - else if(classType == Collection.class || classType == Set.class || classType == List.class) - { - if(!(genericType instanceof ParameterizedType)) - { - throw new IllegalArgumentException(); - } - - Type[] actualTypeArguments = ((ParameterizedType) genericType).getActualTypeArguments(); - - return objectDescriptor.addProperty(propertyName, new NativeArray(actualTypeArguments[0])); - } - else if(classType == boolean.class) - { - return objectDescriptor.addProperty(propertyName, Boolean.class); - } - else if(classType == Boolean.class) - { - return objectDescriptor.addProperty(propertyName, Boolean.class).notNull(); - } - else if(classType == String.class) - { - return objectDescriptor.addProperty(propertyName, String.class); - } - else if(classType == byte.class || - classType == short.class || - classType == int.class || - classType == long.class || - classType == float.class || - classType == double.class) - { - return objectDescriptor.addProperty(propertyName, Number.class).notNull(); - } - else if(classType == Byte.class || - classType == Short.class || - classType == Integer.class || - classType == Long.class || - classType == Float.class || - classType == Double.class || - classType == BigInteger.class) - { - return objectDescriptor.addProperty(propertyName, Number.class); - } - else if(classType == Map.class) - { - if(!(genericType instanceof ParameterizedType)) - { - throw new IllegalArgumentException(); - } - - Type[] actualTypeArguments = ((ParameterizedType) genericType).getActualTypeArguments(); - - Class rawType; - Type actualTypeArgument = actualTypeArguments[1]; - if(actualTypeArgument instanceof ParameterizedType) - { - rawType = (Class) ((ParameterizedType) actualTypeArgument).getRawType(); - } - else - { - rawType = (Class) actualTypeArgument; - } - - JsonObjectDescriptor child = new JsonObjectDescriptor(); - fillObjectDescriptor(child, rawType, actualTypeArguments[1], null); - - return objectDescriptor.addProperty(propertyName, child); - } - else - { - JsonObjectDescriptor another = new JsonObjectDescriptor(); - fillDescriptor(another, classType); - return objectDescriptor.addProperty(propertyName, another); - } - } - - private static void collectMethods(Class clazz, Set methods, Set> processClasses) - { - if(processClasses.contains(clazz)) - { - return; - } - - processClasses.add(clazz); - - Method[] declaredMethods = clazz.getDeclaredMethods(); - ContainerUtil.addAllNotNull(methods, declaredMethods); - - Class[] interfaces = clazz.getInterfaces(); - for(Class anInterface : interfaces) - { - collectMethods(anInterface, methods, processClasses); - } - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/JomPropertyGetter.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/JomPropertyGetter.java deleted file mode 100644 index 3d0cd702..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/JomPropertyGetter.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2013-2015 must-be.org - * - * 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 consulo.json.jom; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @author VISTALL - * @since 10.11.2015 - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -public @interface JomPropertyGetter -{ - String value() default ""; -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/JomUtil.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/JomUtil.java deleted file mode 100644 index 65a8652b..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/JomUtil.java +++ /dev/null @@ -1,33 +0,0 @@ -package consulo.json.jom; - -import consulo.util.lang.ObjectUtil; -import consulo.util.lang.StringUtil; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.lang.reflect.Method; - -/** - * @author VISTALL - * @since 13.11.2015 - */ -public class JomUtil -{ - @Nullable - public static String getJsonGetPropertyName(@Nonnull Method method) - { - JomPropertyGetter annotation = method.getAnnotation(JomPropertyGetter.class); - if(annotation == null) - { - return null; - } - - String propertyName = StringUtil.getPropertyName(method.getName()); - propertyName = ObjectUtil.notNull(propertyName, method.getName()); - if(!StringUtil.isEmpty(annotation.value())) - { - propertyName = annotation.value(); - } - return propertyName; - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/JomBadValueExpressionException.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/JomBadValueExpressionException.java deleted file mode 100644 index e6ba5e1f..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/JomBadValueExpressionException.java +++ /dev/null @@ -1,27 +0,0 @@ -package consulo.json.jom.proxy; - -/** - * @author VISTALL - * @since 13.11.2015 - */ -public class JomBadValueExpressionException extends RuntimeException -{ - public JomBadValueExpressionException() - { - } - - public JomBadValueExpressionException(String message) - { - super(message); - } - - public JomBadValueExpressionException(String message, Throwable cause) - { - super(message, cause); - } - - public JomBadValueExpressionException(Throwable cause) - { - super(cause); - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/JomProxyInvocationHandler.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/JomProxyInvocationHandler.java deleted file mode 100644 index 21b70e4a..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/JomProxyInvocationHandler.java +++ /dev/null @@ -1,79 +0,0 @@ -package consulo.json.jom.proxy; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import consulo.annotation.access.RequiredReadAction; -import consulo.json.jom.JomElement; -import consulo.json.jom.JomUtil; -import com.intellij.lang.javascript.psi.JSObjectLiteralExpression; -import com.intellij.lang.javascript.psi.JSProperty; -import consulo.util.lang.Comparing; - -/** - * @author VISTALL - * @since 13.11.2015 - */ -public class JomProxyInvocationHandler implements InvocationHandler -{ - @Nonnull - public static JomElement createProxy(@Nonnull Class interfaceClass, @Nullable final JSObjectLiteralExpression objectLiteralExpression) - { - return (JomElement) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class[]{interfaceClass}, new JomProxyInvocationHandler(objectLiteralExpression)); - } - - private JSObjectLiteralExpression myObjectLiteralExpression; - - public JomProxyInvocationHandler(@Nullable JSObjectLiteralExpression objectLiteralExpression) - { - myObjectLiteralExpression = objectLiteralExpression; - } - - @Override - @RequiredReadAction - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable - { - String propertyName = JomUtil.getJsonGetPropertyName(method); - if(propertyName != null) - { - JSProperty jsProperty = findProperty(myObjectLiteralExpression, propertyName); - if(jsProperty == null) - { - return JomValueConverter.getDefaultValueForType(method.getReturnType()); - } - else - { - try - { - return JomValueConverter.convertToObject(method.getReturnType(), method.getGenericReturnType(), jsProperty.getValue()); - } - catch(JomBadValueExpressionException e) - { - return JomValueConverter.getDefaultValueForType(method.getReturnType()); - } - } - } - return null; - } - - - @Nullable - private static JSProperty findProperty(@Nullable JSObjectLiteralExpression objectLiteralExpression, String name) - { - if(objectLiteralExpression == null) - { - return null; - } - for(JSProperty property : objectLiteralExpression.getProperties()) - { - if(Comparing.equal(property.getName(), name)) - { - return property; - } - } - return null; - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/JomValueConverter.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/JomValueConverter.java deleted file mode 100644 index 302abecd..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/JomValueConverter.java +++ /dev/null @@ -1,132 +0,0 @@ -package consulo.json.jom.proxy; - -import com.intellij.lang.javascript.psi.JSArrayLiteralExpression; -import com.intellij.lang.javascript.psi.JSExpression; -import com.intellij.lang.javascript.psi.JSObjectLiteralExpression; -import consulo.annotation.access.RequiredReadAction; -import consulo.json.jom.JomElement; -import consulo.json.jom.proxy.impl.*; -import consulo.language.psi.PsiElement; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.lang.reflect.Array; -import java.lang.reflect.Type; -import java.util.*; - -/** - * @author VISTALL - * @since 13.11.2015 - */ -public class JomValueConverter -{ - public interface Converter - { - T getDefaultValue(); - - @RequiredReadAction - T parseValue(@Nonnull Class type, @Nonnull Type genericType, @Nonnull PsiElement value) throws JomBadValueExpressionException; - } - - private static Map ourDefaultConverters = new HashMap(); - - static - { - // primitives - ourDefaultConverters.put(byte.class, new JomNumberValue(Byte.class)); - ourDefaultConverters.put(short.class, new JomNumberValue(Short.class)); - ourDefaultConverters.put(int.class, new JomNumberValue(Integer.class)); - ourDefaultConverters.put(long.class, new JomNumberValue(Long.class)); - ourDefaultConverters.put(float.class, new JomNumberValue(Float.class)); - ourDefaultConverters.put(double.class, new JomNumberValue(Double.class)); - ourDefaultConverters.put(boolean.class, new JomBooleanValue(Boolean.FALSE)); - - // primitive wrappers - ourDefaultConverters.put(Byte.class, new JomNullableNumberValue(Byte.class)); - ourDefaultConverters.put(Short.class, new JomNullableNumberValue(Short.class)); - ourDefaultConverters.put(Integer.class, new JomNullableNumberValue(Integer.class)); - ourDefaultConverters.put(Long.class, new JomNullableNumberValue(Long.class)); - ourDefaultConverters.put(Float.class, new JomNullableNumberValue(Float.class)); - ourDefaultConverters.put(Double.class, new JomNullableNumberValue(Double.class)); - ourDefaultConverters.put(Boolean.class, new JomBooleanValue(null)); - - ourDefaultConverters.put(String.class, new JomStringConverter()); - - // collections - ourDefaultConverters.put(Map.class, new JomMapConverter()); - ourDefaultConverters.put(Collection.class, new JomCollectionValue(ArrayList.class)); - ourDefaultConverters.put(List.class, new JomCollectionValue(ArrayList.class)); - ourDefaultConverters.put(Set.class, new JomCollectionValue(LinkedHashSet.class)); - } - - @RequiredReadAction - @SuppressWarnings("unchecked") - public static Object convertToObject(@Nonnull Class type, @Nonnull Type genericType, @Nullable JSExpression value) throws JomBadValueExpressionException - { - if(value == null) - { - throw new JomBadValueExpressionException("No value for property"); - } - - JomValueConverter.Converter converter = JomValueConverter.ourDefaultConverters.get(type); - if(converter != null) - { - return converter.parseValue(type, genericType, value); - } - - if(type.isArray()) - { - if(value instanceof JSArrayLiteralExpression) - { - Class componentType = type.getComponentType(); - - JSExpression[] expressions = ((JSArrayLiteralExpression) value).getExpressions(); - - List list = new ArrayList(expressions.length); - for(JSExpression expression : expressions) - { - try - { - Object o = JomValueConverter.convertToObject(componentType, componentType, expression); - list.add(o); - } - catch(JomBadValueExpressionException e) - { - // we dont interest in bad value - } - } - - return list.toArray((Object[]) Array.newInstance(componentType, list.size())); - } - } - - if(JomElement.class.isAssignableFrom(type)) - { - return JomProxyInvocationHandler.createProxy(type, value instanceof JSObjectLiteralExpression ? (JSObjectLiteralExpression) value : null); - } - - throw new UnsupportedOperationException("Unsupported type: " + genericType); - } - - @Nullable - public static Object getDefaultValueForType(@Nonnull Class type) - { - JomValueConverter.Converter converter = JomValueConverter.ourDefaultConverters.get(type); - if(converter != null) - { - return converter.getDefaultValue(); - } - - if(type.isArray()) - { - return Array.newInstance(type.getComponentType(), 0); - } - - if(JomElement.class.isAssignableFrom(type)) - { - return null; - } - - throw new UnsupportedOperationException("Unsupported type: " + type); - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/impl/JomBooleanValue.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/impl/JomBooleanValue.java deleted file mode 100644 index d5d37e31..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/impl/JomBooleanValue.java +++ /dev/null @@ -1,53 +0,0 @@ -package consulo.json.jom.proxy.impl; - -import java.lang.reflect.Type; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import consulo.annotation.access.RequiredReadAction; -import consulo.json.jom.proxy.JomBadValueExpressionException; -import consulo.json.jom.proxy.JomValueConverter; -import com.intellij.lang.javascript.JSTokenTypes; -import com.intellij.lang.javascript.psi.JSLiteralExpression; -import consulo.language.ast.IElementType; -import consulo.language.psi.PsiElement; -import consulo.language.psi.PsiUtilCore; - -/** - * @author VISTALL - * @since 13.11.2015 - */ -public class JomBooleanValue implements JomValueConverter.Converter -{ - private Boolean myDefaultValue; - - public JomBooleanValue(@Nullable Boolean defaultValue) - { - myDefaultValue = defaultValue; - } - - @Override - public Boolean getDefaultValue() - { - return myDefaultValue; - } - - @RequiredReadAction - @Override - public Boolean parseValue(@Nonnull Class type, @Nonnull Type genericType, @Nonnull PsiElement value) throws JomBadValueExpressionException - { - if(value instanceof JSLiteralExpression) - { - IElementType elementType = PsiUtilCore.getElementType(value.getFirstChild()); - if(elementType == JSTokenTypes.TRUE_KEYWORD) - { - return Boolean.TRUE; - } - else if(elementType == JSTokenTypes.FALSE_KEYWORD) - { - return Boolean.FALSE; - } - } - throw new JomBadValueExpressionException(); - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/impl/JomCollectionValue.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/impl/JomCollectionValue.java deleted file mode 100644 index bcfc0889..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/impl/JomCollectionValue.java +++ /dev/null @@ -1,92 +0,0 @@ -package consulo.json.jom.proxy.impl; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.Collection; - -import javax.annotation.Nonnull; - -import consulo.annotation.access.RequiredReadAction; -import consulo.json.jom.proxy.JomBadValueExpressionException; -import consulo.json.jom.proxy.JomValueConverter; -import com.intellij.lang.javascript.psi.JSArrayLiteralExpression; -import com.intellij.lang.javascript.psi.JSExpression; -import consulo.language.psi.PsiElement; -import consulo.util.lang.Pair; -import consulo.util.lang.reflect.ReflectionUtil; - -/** - * @author VISTALL - * @since 13.11.2015 - */ -public class JomCollectionValue implements JomValueConverter.Converter -{ - private Class myNewInstanceClass; - - public JomCollectionValue(Class newInstanceClass) - { - myNewInstanceClass = newInstanceClass; - } - - @Override - public T getDefaultValue() - { - return ReflectionUtil.newInstance(myNewInstanceClass); - } - - @RequiredReadAction - @Override - @SuppressWarnings("unchecked") - public T parseValue(@Nonnull Class type, @Nonnull Type genericType, @Nonnull PsiElement value) throws JomBadValueExpressionException - { - if(value instanceof JSArrayLiteralExpression) - { - JSExpression[] expressions = ((JSArrayLiteralExpression) value).getExpressions(); - T collection = ReflectionUtil.newInstance(myNewInstanceClass); - - Pair valueType = findValueTypeInsideGeneric(genericType, 0); // E - - for(JSExpression expression : expressions) - { - try - { - Object o = JomValueConverter.convertToObject(valueType.getFirst(), valueType.getSecond(), expression); - collection.add(o); - } - catch(JomBadValueExpressionException e) - { - // we dont interest in bad value - } - } - return collection; - } - throw new JomBadValueExpressionException(); - } - - - public static Pair findValueTypeInsideGeneric(@Nonnull Type genericType, int index) - { - if(!(genericType instanceof ParameterizedType)) - { - throw new JomBadValueExpressionException(); - } - - Type[] actualTypeArguments = ((ParameterizedType) genericType).getActualTypeArguments(); - if(actualTypeArguments.length <= index) - { - throw new JomBadValueExpressionException(); - } - - Class rawType = null; - Type valueType = actualTypeArguments[index]; - if(valueType instanceof ParameterizedType) - { - rawType = (Class) ((ParameterizedType) valueType).getRawType(); - } - else - { - rawType = (Class) valueType; - } - return Pair.create(rawType, valueType); - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/impl/JomMapConverter.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/impl/JomMapConverter.java deleted file mode 100644 index ae1cfabf..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/impl/JomMapConverter.java +++ /dev/null @@ -1,67 +0,0 @@ -package consulo.json.jom.proxy.impl; - -import java.lang.reflect.Type; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; - -import javax.annotation.Nonnull; -import consulo.annotation.access.RequiredReadAction; -import consulo.json.jom.proxy.JomBadValueExpressionException; -import consulo.json.jom.proxy.JomValueConverter; -import com.intellij.lang.javascript.psi.JSObjectLiteralExpression; -import com.intellij.lang.javascript.psi.JSProperty; -import consulo.language.psi.PsiElement; -import consulo.util.lang.Pair; - -/** - * @author VISTALL - * @since 13.11.2015 - */ -public class JomMapConverter implements JomValueConverter.Converter -{ - @Override - public Map getDefaultValue() - { - return Collections.emptyMap(); - } - - @RequiredReadAction - @Override - @SuppressWarnings("unchecked") - public Map parseValue(@Nonnull Class type, @Nonnull Type genericType, @Nonnull PsiElement value) throws JomBadValueExpressionException - { - if(!(value instanceof JSObjectLiteralExpression)) - { - throw new JomBadValueExpressionException(); - } - - Pair valueType = JomCollectionValue.findValueTypeInsideGeneric(genericType, 1); // K, V - - JSProperty[] properties = ((JSObjectLiteralExpression) value).getProperties(); - - Map map = new LinkedHashMap(properties.length); - - for(JSProperty property : properties) - { - String name = property.getName(); - if(name == null) - { - continue; - } - - try - { - Object object = JomValueConverter.convertToObject(valueType.getFirst(), valueType.getSecond(), property.getValue()); - map.put(name, object); - } - catch(JomBadValueExpressionException e) - { - // we dont interest in bad value - } - } - - return map; - } - -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/impl/JomNullableNumberValue.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/impl/JomNullableNumberValue.java deleted file mode 100644 index 9c4dbe50..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/impl/JomNullableNumberValue.java +++ /dev/null @@ -1,72 +0,0 @@ -package consulo.json.jom.proxy.impl; - -import com.intellij.lang.javascript.JSTokenTypes; -import com.intellij.lang.javascript.psi.JSLiteralExpression; -import consulo.annotation.access.RequiredReadAction; -import consulo.json.jom.proxy.JomBadValueExpressionException; -import consulo.json.jom.proxy.JomValueConverter; -import consulo.language.ast.IElementType; -import consulo.language.psi.PsiElement; -import consulo.language.psi.PsiUtilCore; -import consulo.util.lang.StringUtil; -import consulo.util.lang.lazy.LazyValue; -import consulo.util.lang.reflect.ReflectionUtil; - -import javax.annotation.Nonnull; -import java.lang.reflect.Method; -import java.lang.reflect.Type; -import java.util.function.Supplier; - -/** - * @author VISTALL - * @since 13.11.2015 - */ -public class JomNullableNumberValue implements JomValueConverter.Converter -{ - protected Class myClass; - - protected Supplier myParseMethodValue; - - public JomNullableNumberValue(Class aClass) - { - myClass = aClass; - myParseMethodValue = LazyValue.notNull(() -> - { - Class primitiveType = ReflectionUtil.getStaticFieldValue(myClass, Class.class, "TYPE"); - - Method method = ReflectionUtil.getMethod(myClass, "parse" + StringUtil.capitalize(primitiveType.getSimpleName()), String.class); - assert method != null; - return method; - }); - } - - @Override - public T getDefaultValue() - { - return null; - } - - @RequiredReadAction - @Override - @SuppressWarnings("unchecked") - public T parseValue(@Nonnull Class type, @Nonnull Type genericType, @Nonnull PsiElement value) throws JomBadValueExpressionException - { - if(value instanceof JSLiteralExpression) - { - IElementType elementType = PsiUtilCore.getElementType(value.getFirstChild()); - if(elementType == JSTokenTypes.NUMERIC_LITERAL) - { - try - { - return (T) myParseMethodValue.get().invoke(null, value.getText()); - } - catch(Exception e) - { - throw new JomBadValueExpressionException(e); - } - } - } - - throw new JomBadValueExpressionException(); - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/impl/JomNumberValue.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/impl/JomNumberValue.java deleted file mode 100644 index 161e9d8d..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/impl/JomNumberValue.java +++ /dev/null @@ -1,29 +0,0 @@ -package consulo.json.jom.proxy.impl; - -import consulo.json.jom.proxy.JomBadValueExpressionException; - -/** - * @author VISTALL - * @since 13.11.2015 - */ -public class JomNumberValue extends JomNullableNumberValue -{ - public JomNumberValue(Class aClass) - { - super(aClass); - } - - @Override - @SuppressWarnings("unchecked") - public T getDefaultValue() - { - try - { - return (T) myParseMethodValue.get().invoke(null, "0"); - } - catch(Exception e) - { - throw new JomBadValueExpressionException(e); - } - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/impl/JomStringConverter.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/impl/JomStringConverter.java deleted file mode 100644 index c71c9198..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/jom/proxy/impl/JomStringConverter.java +++ /dev/null @@ -1,43 +0,0 @@ -package consulo.json.jom.proxy.impl; - -import java.lang.reflect.Type; - -import javax.annotation.Nonnull; - -import consulo.javascript.psi.JSSimpleLiteralExpression; -import consulo.language.psi.PsiElement; -import consulo.language.ast.IElementType; -import consulo.annotation.access.RequiredReadAction; -import consulo.javascript.lang.JavaScriptTokenSets; -import consulo.json.jom.proxy.JomBadValueExpressionException; -import consulo.json.jom.proxy.JomValueConverter; -import consulo.util.lang.StringUtil; - -/** - * @author VISTALL - * @since 13.11.2015 - */ -public class JomStringConverter implements JomValueConverter.Converter -{ - @Override - public String getDefaultValue() - { - return null; - } - - @RequiredReadAction - @Override - public String parseValue(@Nonnull Class type, @Nonnull Type genericType, @Nonnull PsiElement value) throws JomBadValueExpressionException - { - if(value instanceof JSSimpleLiteralExpression) - { - IElementType elementType = ((JSSimpleLiteralExpression) value).getLiteralElementType(); - if(JavaScriptTokenSets.STRING_LITERALS.contains(elementType)) - { - return StringUtil.unquoteString(value.getText()); - } - } - - throw new JomBadValueExpressionException(); - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/lang/JsonJavaScriptParser.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/lang/JsonJavaScriptParser.java deleted file mode 100644 index 1c9c7be9..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/lang/JsonJavaScriptParser.java +++ /dev/null @@ -1,265 +0,0 @@ -package consulo.json.lang; - -import consulo.language.ast.ASTNode; -import consulo.language.parser.PsiBuilder; -import com.intellij.lang.javascript.JSElementTypes; -import com.intellij.lang.javascript.JSTokenTypes; -import consulo.javascript.language.JavaScriptBundle; -import consulo.language.ast.IElementType; -import consulo.javascript.lang.JavaScriptTokenSets; -import consulo.javascript.lang.parsing.ExpressionParsing; -import consulo.javascript.lang.parsing.Parsing; -import consulo.language.parser.PsiParser; -import consulo.language.version.LanguageVersion; -import consulo.logging.Logger; - -import javax.annotation.Nonnull; - -/** - * @author VISTALL - * @since 05.03.2015 - */ -public class JsonJavaScriptParser implements PsiParser -{ - private static final Logger LOG = Logger.getInstance(JsonJavaScriptParser.class); - - private int myPropertyDepth; - - @Nonnull - @Override - public ASTNode parse(@Nonnull IElementType root, @Nonnull PsiBuilder builder, @Nonnull LanguageVersion languageVersion) - { - final PsiBuilder.Marker rootMarker = builder.mark(); - parseRoot(builder); - rootMarker.done(root); - return builder.getTreeBuilt(); - } - - private void parseRoot(PsiBuilder builder) - { - if(builder.getTokenType() == JSTokenTypes.LBRACKET) - { - parseArrayLiteralExpression(builder); - if(builder.getTokenType() != null) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.eof")); - } - } - else if(builder.getTokenType() == JSTokenTypes.LBRACE) - { - parseObjectLiteralExpression(builder); - if(builder.getTokenType() != null) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.eof")); - } - } - else - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.lbrace.or.lbracket")); - } - - while(builder.getTokenType() != null) - { - builder.advanceLexer(); - } - } - - private void parseProperty(final PsiBuilder builder) - { - if(myPropertyDepth > 1000) - { - builder.error("Too big depth for property"); - int braceCount = 0; - int bracketCount = 0; - while(!builder.eof()) - { - IElementType tokenType = builder.getTokenType(); - if(tokenType == JSTokenTypes.LBRACE) - { - braceCount++; - } - else if(tokenType == JSTokenTypes.LBRACKET) - { - bracketCount++; - } - else if(tokenType == JSTokenTypes.RBRACE) - { - braceCount--; - if(braceCount < 0) - { - break; - } - } - else if(tokenType == JSTokenTypes.RBRACKET) - { - bracketCount--; - if(bracketCount < 0) - { - break; - } - } - builder.advanceLexer(); - } - } - - final IElementType nameToken = builder.getTokenType(); - final PsiBuilder.Marker property = builder.mark(); - myPropertyDepth++; - - if(isNotPropertyStart(nameToken)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.identifier.string.literal.or.numeric.literal")); - } - builder.advanceLexer(); - Parsing.checkMatches(builder, JSTokenTypes.COLON, JavaScriptBundle.message("javascript.parser.message.expected.colon")); - - if(!parseValue(builder)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - } - myPropertyDepth--; - - property.done(JSElementTypes.PROPERTY); - } - - public void parseObjectLiteralExpression(final PsiBuilder builder) - { - LOG.assertTrue(builder.getTokenType() == JSTokenTypes.LBRACE); - final PsiBuilder.Marker expr = builder.mark(); - builder.advanceLexer(); - - IElementType elementType = builder.getTokenType(); - - while(elementType != JSTokenTypes.RBRACE && elementType != null) - { - parseProperty(builder); - - elementType = builder.getTokenType(); - if(elementType == JSTokenTypes.RBRACE) - { - break; - } - else if(elementType == JSTokenTypes.COMMA) - { - builder.advanceLexer(); - - if(builder.getTokenType() == JSTokenTypes.RBRACE) - { - break; - } - } - else - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.comma")); - } - - elementType = builder.getTokenType(); - if(elementType == JSTokenTypes.RBRACE) - { - break; - } - else if(isNotPropertyStart(elementType)) - { - break; - } - } - - Parsing.checkMatches(builder, JSTokenTypes.RBRACE, JavaScriptBundle.message("javascript.parser.message.expected.rbrace")); - expr.done(JSElementTypes.OBJECT_LITERAL_EXPRESSION); - } - - public static boolean isNotPropertyStart(final IElementType elementType) - { - return !JSTokenTypes.IDENTIFIER_TOKENS_SET.contains(elementType) && !JavaScriptTokenSets.STRING_LITERALS.contains(elementType) && elementType != JSTokenTypes.NUMERIC_LITERAL; - } - - public void parseArrayLiteralExpression(final PsiBuilder builder) - { - JsonJavaScriptParser.LOG.assertTrue(builder.getTokenType() == JSTokenTypes.LBRACKET); - final PsiBuilder.Marker expr = builder.mark(); - builder.advanceLexer(); - boolean commaExpected = false; - - while(builder.getTokenType() != JSTokenTypes.RBRACKET) - { - if(commaExpected) - { - final boolean b = Parsing.checkMatches(builder, JSTokenTypes.COMMA, JavaScriptBundle.message("javascript.parser.message.expected.comma")); - if(!b) - { - break; - } - } - - while(builder.getTokenType() == JSTokenTypes.COMMA) - { - builder.advanceLexer(); - } - - commaExpected = false; - if(builder.getTokenType() != JSTokenTypes.RBRACKET) - { - if(!parseValue(builder)) - { - builder.error(JavaScriptBundle.message("javascript.parser.message.expected.expression")); - break; - } - else - { - commaExpected = true; - } - } - } - Parsing.checkMatches(builder, JSTokenTypes.RBRACKET, JavaScriptBundle.message("javascript.parser.message.expected.rbracket")); - expr.done(JSElementTypes.ARRAY_LITERAL_EXPRESSION); - } - - private boolean parseValue(PsiBuilder builder) - { - final IElementType firstToken = builder.getTokenType(); - if(firstToken == JSTokenTypes.NUMERIC_LITERAL || - firstToken == JSTokenTypes.STRING_LITERAL || - firstToken == JSTokenTypes.SINGLE_QUOTE_STRING_LITERAL || - firstToken == JSTokenTypes.NULL_KEYWORD || - firstToken == JSTokenTypes.FALSE_KEYWORD || - firstToken == JSTokenTypes.TRUE_KEYWORD) - { - String errorMessage = ExpressionParsing.validateLiteral(builder); - Parsing.buildTokenElement(JSElementTypes.LITERAL_EXPRESSION, builder); - if(errorMessage != null) - { - builder.error(errorMessage); - } - return true; - } - if(firstToken == JSTokenTypes.LBRACKET) - { - parseArrayLiteralExpression(builder); - return true; - } - else if(firstToken == JSTokenTypes.MINUS) - { - PsiBuilder.Marker marker = builder.mark(); - builder.advanceLexer(); - if(builder.getTokenType() == JSTokenTypes.NUMERIC_LITERAL) - { - builder.advanceLexer(); - marker.done(JSElementTypes.PREFIX_EXPRESSION); - } - else - { - marker.error("Unexpected token"); - } - return true; - } - else if(firstToken == JSTokenTypes.LBRACE) - { - parseObjectLiteralExpression(builder); - return true; - } - else - { - return false; - } - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/lang/JsonJavaScriptVersion.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/lang/JsonJavaScriptVersion.java deleted file mode 100644 index d7a88824..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/lang/JsonJavaScriptVersion.java +++ /dev/null @@ -1,64 +0,0 @@ -package consulo.json.lang; - -import consulo.annotation.component.ExtensionImpl; -import consulo.javascript.ide.hightlight.JavaScriptHighlighter; -import consulo.javascript.lang.BaseJavaScriptLanguageVersion; -import consulo.javascript.language.JavaScriptLanguage; -import consulo.json.JsonFileType; -import consulo.json.lang.lexer.JsonLexer; -import consulo.language.editor.highlight.SyntaxHighlighter; -import consulo.language.lexer.Lexer; -import consulo.language.parser.PsiParser; -import consulo.virtualFileSystem.fileType.FileType; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.function.Supplier; - -/** - * @author VISTALL - * @since 05.03.2015 - */ -@ExtensionImpl -public class JsonJavaScriptVersion extends BaseJavaScriptLanguageVersion -{ - private static final Supplier ourLexerFactory = JsonLexer::new; - - @Nonnull - public static JsonJavaScriptVersion getInstance() - { - return JavaScriptLanguage.INSTANCE.findVersionByClass(JsonJavaScriptVersion.class); - } - - public JsonJavaScriptVersion() - { - super("JSON", "application/json"); - } - - @Nullable - @Override - public FileType getAssociatedFileType() - { - return JsonFileType.INSTANCE; - } - - @Nonnull - @Override - public SyntaxHighlighter getSyntaxHighlighter() - { - return new JavaScriptHighlighter(ourLexerFactory); - } - - @Nonnull - @Override - public Lexer createLexer() - { - return ourLexerFactory.get(); - } - - @Nonnull - @Override - public PsiParser createParser() - { - return new JsonJavaScriptParser(); - }} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/lang/JsonQuoteHandler.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/lang/JsonQuoteHandler.java deleted file mode 100644 index 3f9a44e5..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/lang/JsonQuoteHandler.java +++ /dev/null @@ -1,23 +0,0 @@ -package consulo.json.lang; - -import consulo.annotation.component.ExtensionImpl; -import consulo.javascript.impl.language.JavaScriptQuoteHandler; -import consulo.json.JsonFileType; -import consulo.virtualFileSystem.fileType.FileType; - -import javax.annotation.Nonnull; - -/** - * @author VISTALL - * @since 29-Aug-22 - */ -@ExtensionImpl -public class JsonQuoteHandler extends JavaScriptQuoteHandler -{ - @Nonnull - @Override - public FileType getFileType() - { - return JsonFileType.INSTANCE; - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/lang/lexer/JsonLexer.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/lang/lexer/JsonLexer.java deleted file mode 100644 index 1d8eb18d..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/lang/lexer/JsonLexer.java +++ /dev/null @@ -1,713 +0,0 @@ -/* The following code was generated by JFlex 1.4.4 on 15.02.16 12:22 */ - -package consulo.json.lang.lexer; - -import com.intellij.lang.javascript.JSTokenTypes; -import consulo.language.ast.IElementType; -import consulo.language.lexer.LexerBase; - - -/** - * This class is a scanner generated by - * JFlex 1.4.4 - * on 15.02.16 12:22 from the specification file - * R:/_github.com/consulo/consulo-javascript/json-javascript-impl/src/org/mustbe/consulo/json/lang/lexer/json.flex - */ -public class JsonLexer extends LexerBase -{ - /** initial size of the lookahead buffer */ - private static final int ZZ_BUFFERSIZE = 16384; - - /** lexical states */ - public static final int YYINITIAL = 0; - - /** - * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l - * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l - * at the beginning of a line - * l is of the form l = 2*k, k a non negative integer - */ - private static final int ZZ_LEXSTATE[] = { - 0, 0 - }; - - /** - * Translates characters to character classes - */ - private static final String ZZ_CMAP_PACKED = - "\11\5\1\3\1\16\1\0\1\3\1\10\16\5\4\0\1\3\1\0"+ - "\1\21\1\0\1\4\2\0\1\17\2\0\1\7\1\15\1\37\1\41"+ - "\1\13\1\6\1\11\7\1\2\1\1\40\6\0\4\2\1\14\1\2"+ - "\21\4\1\12\2\4\1\35\1\20\1\36\1\0\1\4\1\0\1\27"+ - "\3\2\1\25\1\26\5\4\1\30\1\4\1\32\3\4\1\23\1\31"+ - "\1\22\1\24\2\4\1\12\2\4\1\33\1\0\1\34\1\0\41\5"+ - "\2\0\4\4\4\0\1\4\2\0\1\5\7\0\1\4\4\0\1\4"+ - "\5\0\27\4\1\0\37\4\1\0\u013f\4\31\0\162\4\4\0\14\4"+ - "\16\0\5\4\11\0\1\4\21\0\130\5\5\0\23\5\12\0\1\4"+ - "\13\0\1\4\1\0\3\4\1\0\1\4\1\0\24\4\1\0\54\4"+ - "\1\0\46\4\1\0\5\4\4\0\202\4\1\0\4\5\3\0\105\4"+ - "\1\0\46\4\2\0\2\4\6\0\20\4\41\0\46\4\2\0\1\4"+ - "\7\0\47\4\11\0\21\5\1\0\27\5\1\0\3\5\1\0\1\5"+ - "\1\0\2\5\1\0\1\5\13\0\33\4\5\0\3\4\15\0\4\5"+ - "\14\0\6\5\13\0\32\4\5\0\13\4\16\5\7\0\12\5\4\0"+ - "\2\4\1\5\143\4\1\0\1\4\10\5\1\0\6\5\2\4\2\5"+ - "\1\0\4\5\2\4\12\5\3\4\2\0\1\4\17\0\1\5\1\4"+ - "\1\5\36\4\33\5\2\0\3\4\60\0\46\4\13\5\1\4\u014f\0"+ - "\3\5\66\4\2\0\1\5\1\4\20\5\2\0\1\4\4\5\3\0"+ - "\12\4\2\5\2\0\12\5\21\0\3\5\1\0\10\4\2\0\2\4"+ - "\2\0\26\4\1\0\7\4\1\0\1\4\3\0\4\4\2\0\1\5"+ - "\1\4\7\5\2\0\2\5\2\0\3\5\11\0\1\5\4\0\2\4"+ - "\1\0\3\4\2\5\2\0\12\5\4\4\15\0\3\5\1\0\6\4"+ - "\4\0\2\4\2\0\26\4\1\0\7\4\1\0\2\4\1\0\2\4"+ - "\1\0\2\4\2\0\1\5\1\0\5\5\4\0\2\5\2\0\3\5"+ - "\13\0\4\4\1\0\1\4\7\0\14\5\3\4\14\0\3\5\1\0"+ - "\11\4\1\0\3\4\1\0\26\4\1\0\7\4\1\0\2\4\1\0"+ - "\5\4\2\0\1\5\1\4\10\5\1\0\3\5\1\0\3\5\2\0"+ - "\1\4\17\0\2\4\2\5\2\0\12\5\1\0\1\4\17\0\3\5"+ - "\1\0\10\4\2\0\2\4\2\0\26\4\1\0\7\4\1\0\2\4"+ - "\1\0\5\4\2\0\1\5\1\4\6\5\3\0\2\5\2\0\3\5"+ - "\10\0\2\5\4\0\2\4\1\0\3\4\4\0\12\5\1\0\1\4"+ - "\20\0\1\5\1\4\1\0\6\4\3\0\3\4\1\0\4\4\3\0"+ - "\2\4\1\0\1\4\1\0\2\4\3\0\2\4\3\0\3\4\3\0"+ - "\10\4\1\0\3\4\4\0\5\5\3\0\3\5\1\0\4\5\11\0"+ - "\1\5\17\0\11\5\11\0\1\4\7\0\3\5\1\0\10\4\1\0"+ - "\3\4\1\0\27\4\1\0\12\4\1\0\5\4\4\0\7\5\1\0"+ - "\3\5\1\0\4\5\7\0\2\5\11\0\2\4\4\0\12\5\22\0"+ - "\2\5\1\0\10\4\1\0\3\4\1\0\27\4\1\0\12\4\1\0"+ - "\5\4\2\0\1\5\1\4\7\5\1\0\3\5\1\0\4\5\7\0"+ - "\2\5\7\0\1\4\1\0\2\4\4\0\12\5\22\0\2\5\1\0"+ - "\10\4\1\0\3\4\1\0\27\4\1\0\20\4\4\0\6\5\2\0"+ - "\3\5\1\0\4\5\11\0\1\5\10\0\2\4\4\0\12\5\22\0"+ - "\2\5\1\0\22\4\3\0\30\4\1\0\11\4\1\0\1\4\2\0"+ - "\7\4\3\0\1\5\4\0\6\5\1\0\1\5\1\0\10\5\22\0"+ - "\2\5\15\0\60\4\1\5\2\4\7\5\4\0\10\4\10\5\1\0"+ - "\12\5\47\0\2\4\1\0\1\4\2\0\2\4\1\0\1\4\2\0"+ - "\1\4\6\0\4\4\1\0\7\4\1\0\3\4\1\0\1\4\1\0"+ - "\1\4\2\0\2\4\1\0\4\4\1\5\2\4\6\5\1\0\2\5"+ - "\1\4\2\0\5\4\1\0\1\4\1\0\6\5\2\0\12\5\2\0"+ - "\2\4\42\0\1\4\27\0\2\5\6\0\12\5\13\0\1\5\1\0"+ - "\1\5\1\0\1\5\4\0\2\5\10\4\1\0\42\4\6\0\24\5"+ - "\1\0\2\5\4\4\4\0\10\5\1\0\44\5\11\0\1\5\71\0"+ - "\42\4\1\0\5\4\1\0\2\4\1\0\7\5\3\0\4\5\6\0"+ - "\12\5\6\0\6\4\4\5\106\0\46\4\12\0\51\4\7\0\132\4"+ - "\5\0\104\4\5\0\122\4\6\0\7\4\1\0\77\4\1\0\1\4"+ - "\1\0\4\4\2\0\7\4\1\0\1\4\1\0\4\4\2\0\47\4"+ - "\1\0\1\4\1\0\4\4\2\0\37\4\1\0\1\4\1\0\4\4"+ - "\2\0\7\4\1\0\1\4\1\0\4\4\2\0\7\4\1\0\7\4"+ - "\1\0\27\4\1\0\37\4\1\0\1\4\1\0\4\4\2\0\7\4"+ - "\1\0\47\4\1\0\23\4\16\0\11\5\56\0\125\4\14\0\u026c\4"+ - "\2\0\10\4\12\0\32\4\5\0\113\4\3\0\3\4\17\0\15\4"+ - "\1\0\4\4\3\5\13\0\22\4\3\5\13\0\22\4\2\5\14\0"+ - "\15\4\1\0\3\4\1\0\2\5\14\0\64\4\40\5\3\0\1\4"+ - "\3\0\2\4\1\5\2\0\12\5\41\0\3\5\2\0\12\5\6\0"+ - "\130\4\10\0\51\4\1\5\126\0\35\4\3\0\14\5\4\0\14\5"+ - "\12\0\12\5\36\4\2\0\5\4\u038b\0\154\4\224\0\234\4\4\0"+ - "\132\4\6\0\26\4\2\0\6\4\2\0\46\4\2\0\6\4\2\0"+ - "\10\4\1\0\1\4\1\0\1\4\1\0\1\4\1\0\37\4\2\0"+ - "\65\4\1\0\7\4\1\0\1\4\3\0\3\4\1\0\7\4\3\0"+ - "\4\4\2\0\6\4\4\0\15\4\5\0\3\4\1\0\7\4\17\0"+ - "\4\5\32\0\5\5\20\0\2\4\23\0\1\4\13\0\4\5\6\0"+ - "\6\5\1\0\1\4\15\0\1\4\40\0\22\4\36\0\15\5\4\0"+ - "\1\5\3\0\6\5\27\0\1\4\4\0\1\4\2\0\12\4\1\0"+ - "\1\4\3\0\5\4\6\0\1\4\1\0\1\4\1\0\1\4\1\0"+ - "\4\4\1\0\3\4\1\0\7\4\3\0\3\4\5\0\5\4\26\0"+ - "\44\4\u0e81\0\3\4\31\0\11\4\6\5\1\0\5\4\2\0\5\4"+ - "\4\0\126\4\2\0\2\5\2\0\3\4\1\0\137\4\5\0\50\4"+ - "\4\0\136\4\21\0\30\4\70\0\20\4\u0200\0\u19b6\4\112\0\u51a6\4"+ - "\132\0\u048d\4\u0773\0\u2ba4\4\u215c\0\u012e\4\2\0\73\4\225\0\7\4"+ - "\14\0\5\4\5\0\1\4\1\5\12\4\1\0\15\4\1\0\5\4"+ - "\1\0\1\4\1\0\2\4\1\0\2\4\1\0\154\4\41\0\u016b\4"+ - "\22\0\100\4\2\0\66\4\50\0\15\4\3\0\20\5\20\0\4\5"+ - "\17\0\2\4\30\0\3\4\31\0\1\4\6\0\5\4\1\0\207\4"+ - "\2\0\1\5\4\0\1\4\13\0\12\5\7\0\32\4\4\0\1\4"+ - "\1\0\32\4\12\0\132\4\3\0\6\4\2\0\6\4\2\0\6\4"+ - "\2\0\3\4\3\0\2\4\3\0\2\4\22\0\3\5\4\0"; - - /** - * Translates characters to character classes - */ - private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); - - /** - * Translates DFA states to action switch labels. - */ - private static final int [] ZZ_ACTION = zzUnpackAction(); - - private static final String ZZ_ACTION_PACKED_0 = - "\1\0\1\1\1\2\1\3\1\4\1\1\1\2\1\1"+ - "\1\5\1\6\3\3\1\7\1\10\1\11\1\12\1\13"+ - "\1\14\1\15\2\2\1\16\1\17\1\2\2\5\2\6"+ - "\3\3\1\2\1\17\2\5\2\6\3\3\1\0\1\20"+ - "\1\3\1\21\1\17\1\22"; - - private static int [] zzUnpackAction() { - int [] result = new int[47]; - int offset = 0; - offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); - return result; - } - - private static int zzUnpackAction(String packed, int offset, int [] result) { - int i = 0; /* index in packed string */ - int j = offset; /* index in unpacked array */ - int l = packed.length(); - while (i < l) { - int count = packed.charAt(i++); - int value = packed.charAt(i++); - do result[j++] = value; while (--count > 0); - } - return j; - } - - - /** - * Translates a state to a row index in the transition table - */ - private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); - - private static final String ZZ_ROWMAP_PACKED_0 = - "\0\0\0\42\0\104\0\146\0\210\0\252\0\314\0\356"+ - "\0\u0110\0\u0132\0\u0154\0\u0176\0\u0198\0\42\0\42\0\42"+ - "\0\42\0\42\0\42\0\42\0\u01ba\0\u01dc\0\u01fe\0\u0220"+ - "\0\u0242\0\42\0\u0264\0\u0286\0\42\0\u02a8\0\u02ca\0\u02ec"+ - "\0\u030e\0\u0330\0\u0352\0\u0374\0\u0396\0\u03b8\0\u03da\0\u03fc"+ - "\0\u041e\0\u0440\0\146\0\u0462\0\146\0\42\0\146"; - - private static int [] zzUnpackRowMap() { - int [] result = new int[47]; - int offset = 0; - offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); - return result; - } - - private static int zzUnpackRowMap(String packed, int offset, int [] result) { - int i = 0; /* index in packed string */ - int j = offset; /* index in unpacked array */ - int l = packed.length(); - while (i < l) { - int high = packed.charAt(i++) << 16; - result[j++] = high | packed.charAt(i++); - } - return j; - } - - /** - * The transition table of the DFA - */ - private static final int [] ZZ_TRANS = zzUnpackTrans(); - - private static final String ZZ_TRANS_PACKED_0 = - "\1\2\1\3\1\4\1\5\1\4\1\2\1\6\1\2"+ - "\1\5\1\7\1\4\1\10\1\4\1\2\1\5\1\11"+ - "\1\2\1\12\1\13\3\4\1\14\3\4\1\15\1\16"+ - "\1\17\1\20\1\21\1\22\1\23\1\24\43\0\1\3"+ - "\7\0\1\3\1\0\1\25\1\26\10\0\1\26\15\0"+ - "\2\4\1\0\2\4\3\0\2\4\1\0\1\4\5\0"+ - "\11\4\12\0\1\5\4\0\1\5\5\0\1\5\31\0"+ - "\1\27\1\30\33\0\1\3\7\0\1\3\1\31\1\25"+ - "\1\26\10\0\1\26\15\0\1\25\7\0\1\25\30\0"+ - "\10\11\1\0\5\11\1\0\1\32\1\33\21\11\10\12"+ - "\1\0\5\12\1\0\1\12\1\34\1\35\20\12\1\0"+ - "\2\4\1\0\2\4\3\0\2\4\1\0\1\4\5\0"+ - "\1\4\1\36\7\4\10\0\2\4\1\0\2\4\3\0"+ - "\2\4\1\0\1\4\5\0\5\4\1\37\3\4\10\0"+ - "\2\4\1\0\2\4\3\0\2\4\1\0\1\4\5\0"+ - "\2\4\1\40\6\4\10\0\1\25\7\0\1\25\2\0"+ - "\1\26\10\0\1\26\15\0\1\41\7\0\1\41\3\0"+ - "\1\41\23\0\1\41\10\27\1\0\5\27\1\0\23\27"+ - "\7\42\1\0\32\42\1\0\2\31\6\0\1\31\2\0"+ - "\1\31\10\0\3\31\12\0\3\11\1\43\4\11\1\44"+ - "\31\11\3\12\1\45\4\12\1\46\31\12\1\0\2\4"+ - "\1\0\2\4\3\0\2\4\1\0\1\4\5\0\2\4"+ - "\1\47\6\4\10\0\2\4\1\0\2\4\3\0\2\4"+ - "\1\0\1\4\5\0\6\4\1\50\2\4\10\0\2\4"+ - "\1\0\2\4\3\0\2\4\1\0\1\4\5\0\6\4"+ - "\1\51\2\4\10\0\1\41\7\0\1\41\30\0\7\42"+ - "\1\52\32\42\3\11\1\43\4\11\1\44\6\11\1\32"+ - "\1\33\31\11\1\0\6\11\1\32\1\33\21\11\3\12"+ - "\1\45\4\12\1\46\7\12\1\34\1\35\30\12\1\0"+ - "\7\12\1\34\1\35\20\12\1\0\2\4\1\0\2\4"+ - "\3\0\2\4\1\0\1\4\5\0\3\4\1\53\5\4"+ - "\10\0\2\4\1\0\2\4\3\0\2\4\1\0\1\4"+ - "\5\0\7\4\1\54\1\4\10\0\2\4\1\0\2\4"+ - "\3\0\2\4\1\0\1\4\5\0\6\4\1\55\2\4"+ - "\7\0\6\42\1\56\1\52\32\42\1\0\2\4\1\0"+ - "\2\4\3\0\2\4\1\0\1\4\5\0\3\4\1\57"+ - "\5\4\7\0"; - - private static int [] zzUnpackTrans() { - int [] result = new int[1156]; - int offset = 0; - offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); - return result; - } - - private static int zzUnpackTrans(String packed, int offset, int [] result) { - int i = 0; /* index in packed string */ - int j = offset; /* index in unpacked array */ - int l = packed.length(); - while (i < l) { - int count = packed.charAt(i++); - int value = packed.charAt(i++); - value--; - do result[j++] = value; while (--count > 0); - } - return j; - } - - - /* error codes */ - private static final int ZZ_UNKNOWN_ERROR = 0; - private static final int ZZ_NO_MATCH = 1; - private static final int ZZ_PUSHBACK_2BIG = 2; - private static final char[] EMPTY_BUFFER = new char[0]; - private static final int YYEOF = -1; - - /* error messages for the codes above */ - private static final String ZZ_ERROR_MSG[] = { - "Unkown internal scanner error", - "Error: could not match input", - "Error: pushback value was too large" - }; - - /** - * ZZ_ATTRIBUTE[aState] contains the attributes of state aState - */ - private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); - - private static final String ZZ_ATTRIBUTE_PACKED_0 = - "\1\0\1\11\13\1\7\11\5\1\1\11\2\1\1\11"+ - "\14\1\1\0\3\1\1\11\1\1"; - - private static int [] zzUnpackAttribute() { - int [] result = new int[47]; - int offset = 0; - offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); - return result; - } - - private static int zzUnpackAttribute(String packed, int offset, int [] result) { - int i = 0; /* index in packed string */ - int j = offset; /* index in unpacked array */ - int l = packed.length(); - while (i < l) { - int count = packed.charAt(i++); - int value = packed.charAt(i++); - do result[j++] = value; while (--count > 0); - } - return j; - } - - /** the current state of the DFA */ - private int zzState; - - /** the current lexical state */ - private int zzLexicalState = YYINITIAL; - - /** this buffer contains the current text to be matched and is - the source of the yytext() string */ - private CharSequence zzBuffer = ""; - - /** the textposition at the last accepting state */ - private int zzMarkedPos; - - /** the textposition at the last state to be included in yytext */ - private int zzPushbackPos; - - /** the current text position in the buffer */ - private int zzCurrentPos; - - /** startRead marks the beginning of the yytext() string in the buffer */ - private int zzStartRead; - - /** endRead marks the last character in the buffer, that has been read - from input */ - private int zzEndRead; - - /** - * zzAtBOL == true <=> the scanner is currently at the beginning of a line - */ - private boolean zzAtBOL = true; - - /** zzAtEOF == true <=> the scanner is at the EOF */ - private boolean zzAtEOF; - - private IElementType myTokenType; - private int myState; - - /** denotes if the user-EOF-code has already been executed */ - private boolean zzEOFDone; - - - - /** - * Unpacks the compressed character translation table. - * - * @param packed the packed character translation table - * @return the unpacked character translation table - */ - private static char [] zzUnpackCMap(String packed) { - char [] map = new char[0x10000]; - int i = 0; /* index in packed string */ - int j = 0; /* index in unpacked array */ - while (i < 1738) { - int count = packed.charAt(i++); - char value = packed.charAt(i++); - do map[j++] = value; while (--count > 0); - } - return map; - } - - @Override - public IElementType getTokenType() { - if (myTokenType == null) locateToken(); - return myTokenType; - } - - @Override - public final int getTokenStart(){ - if (myTokenType == null) locateToken(); - return zzStartRead; - } - - @Override - public final int getTokenEnd(){ - if (myTokenType == null) locateToken(); - return getTokenStart() + yylength(); - } - - @Override - public void advance() { - if (myTokenType == null) locateToken(); - myTokenType = null; - } - - @Override - public int getState() { - if (myTokenType == null) locateToken(); - return myState; - } - - @Override - public void start(final CharSequence buffer, int startOffset, int endOffset, final int initialState) { - reset(buffer, startOffset, endOffset, initialState); - myTokenType = null; - } - - @Override - public CharSequence getBufferSequence() { - return zzBuffer; - } - - @Override - public int getBufferEnd() { - return zzEndRead; - } - - public void reset(CharSequence buffer, int start, int end,int initialState){ - zzBuffer = buffer; - zzCurrentPos = zzMarkedPos = zzStartRead = start; - zzPushbackPos = 0; - zzAtEOF = false; - zzAtBOL = true; - zzEndRead = end; - yybegin(initialState); - myTokenType = null; - } - - private void locateToken() { - if (myTokenType != null) return; - try { - myState = yystate(); - myTokenType = advanceImpl(); - } - catch (java.io.IOException e) { /*Can't happen*/ } - catch (Error e) { - // add lexer class name to the error - final Error error = new Error(getClass().getName() + ": " + e.getMessage()); - error.setStackTrace(e.getStackTrace()); - throw error; - } - } - - /** - * Refills the input buffer. - * - * @return false, iff there was new input. - * - * @exception java.io.IOException if any I/O-Error occurs - */ - private boolean zzRefill() throws java.io.IOException { - return true; - } - - - /** - * Returns the current lexical state. - */ - public final int yystate() { - return zzLexicalState; - } - - - /** - * Enters a new lexical state - * - * @param newState the new lexical state - */ - public final void yybegin(int newState) { - zzLexicalState = newState; - } - - - /** - * Returns the text matched by the current regular expression. - */ - public final CharSequence yytext() { - return zzBuffer.subSequence(zzStartRead, zzMarkedPos); - } - - - /** - * Returns the character at position pos from the - * matched text. - * - * It is equivalent to yytext().charAt(pos), but faster - * - * @param pos the position of the character to fetch. - * A value from 0 to yylength()-1. - * - * @return the character at position pos - */ - public final char yycharat(int pos) { - return zzBuffer.charAt(zzStartRead+pos); - } - - - /** - * Returns the length of the matched text region. - */ - public final int yylength() { - return zzMarkedPos-zzStartRead; - } - - - /** - * Reports an error that occured while scanning. - * - * In a wellformed scanner (no or only correct usage of - * yypushback(int) and a match-all fallback rule) this method - * will only be called with things that "Can't Possibly Happen". - * If this method is called, something is seriously wrong - * (e.g. a JFlex bug producing a faulty scanner etc.). - * - * Usual syntax/scanner level error handling should be done - * in error fallback rules. - * - * @param errorCode the code of the errormessage to display - */ - private void zzScanError(int errorCode) { - String message; - try { - message = ZZ_ERROR_MSG[errorCode]; - } - catch (ArrayIndexOutOfBoundsException e) { - message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; - } - - throw new Error(message); - } - - - /** - * Pushes the specified amount of characters back into the input stream. - * - * They will be read again by then next call of the scanning method - * - * @param number the number of characters to be read again. - * This number must not be greater than yylength()! - */ - public void yypushback(int number) { - if ( number > yylength() ) - zzScanError(ZZ_PUSHBACK_2BIG); - - zzMarkedPos -= number; - } - - - /** - * Contains user EOF-code, which will be executed exactly once, - * when the end of file is reached - */ - private void zzDoEOF() { - if (!zzEOFDone) { - zzEOFDone = true; - - } - } - - - /** - * Resumes scanning until the next regular expression is matched, - * the end of input is encountered or an I/O-Error occurs. - * - * @return the next token - * @exception java.io.IOException if any I/O-Error occurs - */ - public IElementType advanceImpl() throws java.io.IOException { - int zzInput; - int zzAction; - - // cached fields: - int zzCurrentPosL; - int zzMarkedPosL; - int zzEndReadL = zzEndRead; - CharSequence zzBufferL = zzBuffer; - char [] zzCMapL = ZZ_CMAP; - - int [] zzTransL = ZZ_TRANS; - int [] zzRowMapL = ZZ_ROWMAP; - int [] zzAttrL = ZZ_ATTRIBUTE; - - while (true) { - zzMarkedPosL = zzMarkedPos; - - zzAction = -1; - - zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; - - zzState = ZZ_LEXSTATE[zzLexicalState]; - - - zzForAction: { - while (true) { - - if (zzCurrentPosL < zzEndReadL) - zzInput = zzBufferL.charAt(zzCurrentPosL++); - else if (zzAtEOF) { - zzInput = YYEOF; - break zzForAction; - } - else { - // store back cached positions - zzCurrentPos = zzCurrentPosL; - zzMarkedPos = zzMarkedPosL; - boolean eof = zzRefill(); - // get translated positions and possibly new buffer - zzCurrentPosL = zzCurrentPos; - zzMarkedPosL = zzMarkedPos; - zzBufferL = zzBuffer; - zzEndReadL = zzEndRead; - if (eof) { - zzInput = YYEOF; - break zzForAction; - } - else { - zzInput = zzBufferL.charAt(zzCurrentPosL++); - } - } - int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ]; - if (zzNext == -1) break zzForAction; - zzState = zzNext; - - int zzAttributes = zzAttrL[zzState]; - if ( (zzAttributes & 1) == 1 ) { - zzAction = zzState; - zzMarkedPosL = zzCurrentPosL; - if ( (zzAttributes & 8) == 8 ) break zzForAction; - } - - } - } - - // store back cached position - zzMarkedPos = zzMarkedPosL; - - switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { - case 13: - { yybegin(YYINITIAL); return JSTokenTypes.MINUS; - } - case 19: break; - case 7: - { yybegin(YYINITIAL); return JSTokenTypes.LBRACE; - } - case 20: break; - case 6: - { yybegin(YYINITIAL); return JSTokenTypes.STRING_LITERAL; - } - case 21: break; - case 9: - { yybegin(YYINITIAL); return JSTokenTypes.LBRACKET; - } - case 22: break; - case 16: - { yybegin(YYINITIAL); return JSTokenTypes.TRUE_KEYWORD; - } - case 23: break; - case 12: - { yybegin(YYINITIAL); return JSTokenTypes.COLON; - } - case 24: break; - case 4: - { return JSTokenTypes.WHITE_SPACE; - } - case 25: break; - case 17: - { yybegin(YYINITIAL); return JSTokenTypes.NULL_KEYWORD; - } - case 26: break; - case 1: - { return JSTokenTypes.BAD_CHARACTER; - } - case 27: break; - case 18: - { yybegin(YYINITIAL); return JSTokenTypes.FALSE_KEYWORD; - } - case 28: break; - case 10: - { yybegin(YYINITIAL); return JSTokenTypes.RBRACKET; - } - case 29: break; - case 15: - { return JSTokenTypes.C_STYLE_COMMENT; - } - case 30: break; - case 3: - { yybegin(YYINITIAL); return JSTokenTypes.IDENTIFIER; - } - case 31: break; - case 14: - { return JSTokenTypes.END_OF_LINE_COMMENT; - } - case 32: break; - case 2: - { yybegin(YYINITIAL); return JSTokenTypes.NUMERIC_LITERAL; - } - case 33: break; - case 8: - { yybegin(YYINITIAL); return JSTokenTypes.RBRACE; - } - case 34: break; - case 11: - { yybegin(YYINITIAL); return JSTokenTypes.COMMA; - } - case 35: break; - case 5: - { return JSTokenTypes.SINGLE_QUOTE_STRING_LITERAL; - } - case 36: break; - default: - if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { - zzAtEOF = true; - zzDoEOF(); - return null; - } - else { - zzScanError(ZZ_NO_MATCH); - } - } - } - } - - -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/lang/lexer/json.flex b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/lang/lexer/json.flex deleted file mode 100644 index b53b99dc..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/lang/lexer/json.flex +++ /dev/null @@ -1,77 +0,0 @@ -package consulo.json.lang.lexer; - -import com.intellij.lexer.LexerBase; -import com.intellij.psi.tree.IElementType; -import com.intellij.lang.javascript.JSTokenTypes; - -%% - -%public -%class JsonLexer -%extends LexerBase -%unicode -%function advanceImpl -%type IElementType -%eof{ return; -%eof} - -DIGIT=[0-9] -OCTAL_DIGIT=[0-7] -HEX_DIGIT=[0-9A-Fa-f] -WHITE_SPACE_CHAR=[\ \n\r\t\f]+ - -IDENTIFIER=[:jletter:] [:jletterdigit:]* - -C_STYLE_COMMENT=("/*"[^"*"]{COMMENT_TAIL})|"/*" -DOC_COMMENT="/*""*"+("/"|([^"/""*"]{COMMENT_TAIL}))? -COMMENT_TAIL=([^"*"]*("*"+[^"*""/"])?)*("*"+"/")? -END_OF_LINE_COMMENT="/""/"[^\r\n]* - -INTEGER_LITERAL={DECIMAL_INTEGER_LITERAL}|{HEX_INTEGER_LITERAL} -DECIMAL_INTEGER_LITERAL=(0|([1-9]({DIGIT})*)) -HEX_INTEGER_LITERAL=0[Xx]({HEX_DIGIT})* - -FLOAT_LITERAL=({FLOATING_POINT_LITERAL1})|({FLOATING_POINT_LITERAL2})|({FLOATING_POINT_LITERAL3})|({FLOATING_POINT_LITERAL4}) -FLOATING_POINT_LITERAL1=({DIGIT})+"."({DIGIT})*({EXPONENT_PART})? -FLOATING_POINT_LITERAL2="."({DIGIT})+({EXPONENT_PART})? -FLOATING_POINT_LITERAL3=({DIGIT})+({EXPONENT_PART}) -FLOATING_POINT_LITERAL4=({DIGIT})+ -EXPONENT_PART=[Ee]["+""-"]?({DIGIT})* - -CRLF= [\ \t \f]* (\n | \r | \r\n) -QUOTED_LITERAL="'"([^\\\'\r\n]|{ESCAPE_SEQUENCE}|\\{CRLF})*("'"|\\)? -DOUBLE_QUOTED_LITERAL=\"([^\\\"\r\n]|{ESCAPE_SEQUENCE}|\\{CRLF})*(\"|\\)? -ESCAPE_SEQUENCE=\\[^\r\n] - -DIGIT=[0-9] - -%% - - {WHITE_SPACE_CHAR} { return JSTokenTypes.WHITE_SPACE; } - - {C_STYLE_COMMENT} { return JSTokenTypes.C_STYLE_COMMENT; } - {END_OF_LINE_COMMENT} { return JSTokenTypes.END_OF_LINE_COMMENT; } - - {INTEGER_LITERAL} { yybegin(YYINITIAL); return JSTokenTypes.NUMERIC_LITERAL; } - {FLOAT_LITERAL} { yybegin(YYINITIAL); return JSTokenTypes.NUMERIC_LITERAL; } - - {QUOTED_LITERAL} { return JSTokenTypes.SINGLE_QUOTE_STRING_LITERAL; } - - {DOUBLE_QUOTED_LITERAL} { yybegin(YYINITIAL); return JSTokenTypes.STRING_LITERAL; } - - "true" { yybegin(YYINITIAL); return JSTokenTypes.TRUE_KEYWORD; } - "false" { yybegin(YYINITIAL); return JSTokenTypes.FALSE_KEYWORD; } - "null" { yybegin(YYINITIAL); return JSTokenTypes.NULL_KEYWORD; } - - {IDENTIFIER} { yybegin(YYINITIAL); return JSTokenTypes.IDENTIFIER; } - - "{" { yybegin(YYINITIAL); return JSTokenTypes.LBRACE; } - "}" { yybegin(YYINITIAL); return JSTokenTypes.RBRACE; } - "[" { yybegin(YYINITIAL); return JSTokenTypes.LBRACKET; } - "]" { yybegin(YYINITIAL); return JSTokenTypes.RBRACKET; } - "," { yybegin(YYINITIAL); return JSTokenTypes.COMMA; } - ":" { yybegin(YYINITIAL); return JSTokenTypes.COLON; } - "-" { yybegin(YYINITIAL); return JSTokenTypes.MINUS; } - - - [^] {return JSTokenTypes.BAD_CHARACTER; } \ No newline at end of file diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/JsonFileDescriptorProvider.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/JsonFileDescriptorProvider.java deleted file mode 100644 index 73e65058..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/JsonFileDescriptorProvider.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2013-2015 must-be.org - * - * 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 consulo.json.validation; - -import consulo.annotation.access.RequiredReadAction; -import consulo.annotation.component.ComponentScope; -import consulo.annotation.component.ExtensionAPI; -import consulo.component.extension.ExtensionPointName; -import consulo.json.validation.descriptor.JsonObjectDescriptor; -import consulo.language.psi.PsiFile; - -import javax.annotation.Nonnull; - -/** - * @author VISTALL - * @since 10.11.2015 - */ -@ExtensionAPI(ComponentScope.APPLICATION) -public interface JsonFileDescriptorProvider -{ - ExtensionPointName EP_NAME = ExtensionPointName.create(JsonFileDescriptorProvider.class); - - @RequiredReadAction - boolean isMyFile(@Nonnull PsiFile file); - - @RequiredReadAction - void fillRootObject(@Nonnull JsonObjectDescriptor root, @Nonnull PsiFile file); -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/JsonFileDescriptorProviders.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/JsonFileDescriptorProviders.java deleted file mode 100644 index 73acb67a..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/JsonFileDescriptorProviders.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2013-2015 must-be.org - * - * 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 consulo.json.validation; - -import javax.annotation.Nullable; - -import consulo.annotation.access.RequiredReadAction; -import consulo.application.util.CachedValuesManager; -import consulo.json.JsonFileType; -import consulo.json.validation.descriptor.JsonObjectDescriptor; -import consulo.language.psi.PsiFile; -import consulo.application.util.CachedValueProvider; -import consulo.language.psi.PsiModificationTracker; - -/** - * @author VISTALL - * @since 10.11.2015 - */ -public class JsonFileDescriptorProviders -{ - @Nullable - @RequiredReadAction - public static JsonObjectDescriptor getRootDescriptor(@Nullable final PsiFile file) - { - if(file == null || file.getFileType() != JsonFileType.INSTANCE) - { - return null; - } - return CachedValuesManager.getManager(file.getProject()).createCachedValue(new CachedValueProvider() - { - @Nullable - @Override - @RequiredReadAction - public Result compute() - { - for(JsonFileDescriptorProvider provider : JsonFileDescriptorProvider.EP_NAME.getExtensions()) - { - if(provider.isMyFile(file)) - { - JsonObjectDescriptor objectDescriptor = new JsonObjectDescriptor(); - provider.fillRootObject(objectDescriptor, file); - - return Result.create(objectDescriptor, file, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT); - } - } - return null; - } - }, false).getValue(); - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/NativeArray.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/NativeArray.java deleted file mode 100644 index de902df7..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/NativeArray.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2013-2015 must-be.org - * - * 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 consulo.json.validation; - -import javax.annotation.Nonnull; - -/** - * @author VISTALL - * @since 25.11.2015 - */ -public class NativeArray -{ - private final Object myComponentType; - - public NativeArray(@Nonnull Object componentType) - { - myComponentType = componentType; - } - - @Nonnull - public Object getComponentType() - { - return myComponentType; - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/completion/JsonCompletionContributor.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/completion/JsonCompletionContributor.java deleted file mode 100644 index cb6ea592..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/completion/JsonCompletionContributor.java +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright 2013-2015 must-be.org - * - * 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 consulo.json.validation.completion; - -import com.intellij.lang.javascript.JSTokenTypes; -import com.intellij.lang.javascript.psi.JSObjectLiteralExpression; -import com.intellij.lang.javascript.psi.JSProperty; -import consulo.annotation.access.RequiredReadAction; -import consulo.annotation.component.ExtensionImpl; -import consulo.application.AllIcons; -import consulo.javascript.language.JavaScriptLanguage; -import consulo.json.validation.JsonFileDescriptorProviders; -import consulo.json.validation.NativeArray; -import consulo.json.validation.descriptor.JsonObjectDescriptor; -import consulo.json.validation.descriptor.JsonPropertyDescriptor; -import consulo.json.validation.inspections.PropertyValidationInspection; -import consulo.language.Language; -import consulo.language.codeStyle.CodeStyleManager; -import consulo.language.editor.completion.*; -import consulo.language.editor.completion.lookup.InsertHandler; -import consulo.language.editor.completion.lookup.InsertionContext; -import consulo.language.editor.completion.lookup.LookupElement; -import consulo.language.editor.completion.lookup.LookupElementBuilder; -import consulo.language.pattern.StandardPatterns; -import consulo.language.psi.PsiElement; -import consulo.language.psi.PsiFile; -import consulo.language.util.ProcessingContext; -import consulo.ui.image.Image; -import consulo.util.collection.ContainerUtil; -import consulo.util.lang.StringUtil; - -import javax.annotation.Nonnull; -import java.util.*; - -/** - * @author VISTALL - * @since 10.11.2015 - */ -@ExtensionImpl -public class JsonCompletionContributor extends CompletionContributor -{ - public JsonCompletionContributor() - { - extend(CompletionType.BASIC, StandardPatterns.psiElement(JSTokenTypes.IDENTIFIER), new CompletionProvider() - { - @RequiredReadAction - @Override - public void addCompletions(@Nonnull CompletionParameters parameters, ProcessingContext context, @Nonnull CompletionResultSet result) - { - addVariants(parameters, result, true); - } - }); - - extend(CompletionType.BASIC, StandardPatterns.psiElement(JSTokenTypes.SINGLE_QUOTE_STRING_LITERAL), new CompletionProvider() - { - @RequiredReadAction - @Override - public void addCompletions(@Nonnull CompletionParameters parameters, ProcessingContext context, @Nonnull CompletionResultSet result) - { - PsiElement originalPosition = parameters.getOriginalPosition(); - if(originalPosition == null) - { - return; - } - if(!"\'\'".equals(originalPosition.getText())) - { - return; - } - addVariants(parameters, result, false); - } - }); - - extend(CompletionType.BASIC, StandardPatterns.psiElement(JSTokenTypes.STRING_LITERAL), new CompletionProvider() - { - @RequiredReadAction - @Override - public void addCompletions(@Nonnull CompletionParameters parameters, ProcessingContext context, @Nonnull CompletionResultSet result) - { - PsiElement originalPosition = parameters.getOriginalPosition(); - if(originalPosition == null) - { - return; - } - if(!"\"\"".equals(originalPosition.getText())) - { - return; - } - addVariants(parameters, result, false); - } - }); - } - - @RequiredReadAction - private static void addVariants(@Nonnull CompletionParameters parameters, @Nonnull CompletionResultSet result, boolean quotes) - { - final PsiFile originalFile = parameters.getOriginalFile(); - - JsonObjectDescriptor rootDescriptor = JsonFileDescriptorProviders.getRootDescriptor(originalFile); - if(rootDescriptor == null) - { - return; - } - - PsiElement position = parameters.getPosition(); - final PsiElement jsProperty = position.getParent(); - if(!(jsProperty instanceof JSProperty)) - { - return; - } - - Collection jsProperties = PropertyValidationInspection.buildPropertiesAsTree(position, rootDescriptor); - if(jsProperties.isEmpty()) - { - return; - } - - JsonObjectDescriptor parentObject = null; - JsonPropertyDescriptor currentProperty = null; - JsonObjectDescriptor currentObject = rootDescriptor; - for(JSProperty property : jsProperties) - { - String name = property.getName(); - if(name == null) - { - return; - } - - currentProperty = currentObject.getProperty(name); - if(currentProperty == null) - { - if(property == jsProperty) - { - parentObject = currentObject; - break; - } - else - { - return; - } - } - else if(currentProperty.getValue() instanceof JsonObjectDescriptor) - { - currentObject = (JsonObjectDescriptor) currentProperty.getValue(); - } - else if(currentProperty.getValue() instanceof NativeArray) - { - Object componentType = ((NativeArray) currentProperty.getValue()).getComponentType(); - if(componentType instanceof JsonObjectDescriptor) - { - currentObject = (JsonObjectDescriptor) componentType; - } - else - { - return; - } - } - else - { - break; - } - } - - if(parentObject == null) - { - return; - } - - Map properties = parentObject.getProperties(); - - Set alreadyDefined = Collections.emptySet(); - PsiElement parent = jsProperty.getParent(); - if(parent instanceof JSObjectLiteralExpression) - { - JSProperty[] parentProperties = ((JSObjectLiteralExpression) parent).getProperties(); - alreadyDefined = new HashSet(parentProperties.length); - for(JSProperty parentProperty : parentProperties) - { - ContainerUtil.addIfNotNull(alreadyDefined, parentProperty.getName()); - } - } - - for(final Map.Entry entry : properties.entrySet()) - { - String key = entry.getKey(); - if(key == null || alreadyDefined.contains(key)) - { - continue; - } - LookupElementBuilder builder = LookupElementBuilder.create(quotes ? StringUtil.QUOTER.apply(key) : key); - builder = builder.withPresentableText(quotes ? StringUtil.QUOTER.apply(key) : key); - builder = builder.withIcon((Image) AllIcons.Nodes.Property); - final JsonPropertyDescriptor value = entry.getValue(); - if(value.isDeprecated()) - { - builder = builder.strikeout(); - } - final Object type = value.getValue(); - builder = builder.withTypeText(formatValue(type), true); - - if(quotes && ((JSProperty) jsProperty).getValue() == null) - { - builder = builder.withInsertHandler(new InsertHandler() - { - @Override - public void handleInsert(InsertionContext context, LookupElement item) - { - if(type == Object.class) - { - context.getDocument().insertString(context.getTailOffset(), ": {\n}"); - context.getEditor().getCaretModel().moveToOffset(context.getTailOffset() - 2); - - context.commitDocument(); - CodeStyleManager.getInstance(context.getProject()).reformatRange(originalFile, context.getStartOffset(), context.getTailOffset()); - } - else if(type == Boolean.class) - { - context.getDocument().insertString(context.getTailOffset(), ": false"); - context.getEditor().getCaretModel().moveToOffset(context.getTailOffset()); - } - else if(type == String.class) - { - context.getDocument().insertString(context.getTailOffset(), ": \"\""); - context.getEditor().getCaretModel().moveToOffset(context.getTailOffset() - 1); - } - else if(type == Number.class) - { - context.getDocument().insertString(context.getTailOffset(), ": 0"); - context.getEditor().getCaretModel().moveToOffset(context.getTailOffset()); - } - else if(value.getValue() instanceof NativeArray) - { - context.getDocument().insertString(context.getTailOffset(), ": []"); - context.getEditor().getCaretModel().moveToOffset(context.getTailOffset() - 1); - } - else - { - context.getDocument().insertString(context.getTailOffset(), ": "); - context.getEditor().getCaretModel().moveToOffset(context.getTailOffset()); - } - } - }); - } - result.addElement(builder); - } - } - - private static String formatValue(Object value) - { - if(value instanceof Class) - { - return StringUtil.decapitalize(((Class) value).getSimpleName()); - } - else if(value instanceof NativeArray) - { - return formatValue(((NativeArray) value).getComponentType()) + "[]"; - } - // JsonObjectDescriptor - return "object"; - } - - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/descriptionByAnotherPsiElement/DescriptionByAnotherPsiElementEditorNotification.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/descriptionByAnotherPsiElement/DescriptionByAnotherPsiElementEditorNotification.java deleted file mode 100644 index 378c37eb..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/descriptionByAnotherPsiElement/DescriptionByAnotherPsiElementEditorNotification.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 2013-2015 must-be.org - * - * 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 consulo.json.validation.descriptionByAnotherPsiElement; - -import consulo.annotation.access.RequiredReadAction; -import consulo.fileEditor.EditorNotificationBuilder; -import consulo.fileEditor.EditorNotificationProvider; -import consulo.fileEditor.EditorNotifications; -import consulo.fileEditor.FileEditor; -import consulo.json.JsonFileType; -import consulo.json.jom.JomElement; -import consulo.json.jom.JomFileElement; -import consulo.json.jom.JomManager; -import consulo.language.editor.DaemonCodeAnalyzer; -import consulo.language.psi.PsiElement; -import consulo.language.psi.PsiFile; -import consulo.language.psi.PsiManager; -import consulo.language.psi.PsiModificationTracker; -import consulo.localize.LocalizeValue; -import consulo.project.Project; -import consulo.ui.Component; -import consulo.ui.annotation.RequiredUIAccess; -import consulo.ui.event.UIEvent; -import consulo.util.lang.StringUtil; -import consulo.virtualFileSystem.VirtualFile; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.function.Consumer; -import java.util.function.Supplier; - -/** - * @author VISTALL - * @since 12.11.2015 - */ -public class DescriptionByAnotherPsiElementEditorNotification implements EditorNotificationProvider -{ - private Project myProject; - private DescriptionByAnotherPsiElementProvider myProvider; - - public DescriptionByAnotherPsiElementEditorNotification(@Nonnull Project project, @Nonnull DescriptionByAnotherPsiElementProvider provider) - { - myProject = project; - myProvider = provider; - } - - @Nonnull - @Override - public String getId() - { - return myProvider.getId(); - } - - @Override - @Nullable - @RequiredReadAction - public EditorNotificationBuilder buildNotification(@Nonnull VirtualFile file, @Nonnull FileEditor fileEditor, @Nonnull Supplier supplier) - { - if(file.getFileType() != JsonFileType.INSTANCE) - { - return null; - } - - final PsiFile psiFile = PsiManager.getInstance(myProject).findFile(file); - if(psiFile == null) - { - return null; - } - - JomFileElement fileElement = JomManager.getInstance(myProject).getFileElement(psiFile); - if(fileElement != null) - { - return null; - } - - if(!myProvider.isAvailable(myProject)) - { - return null; - } - - String registeredPsiElementId = DescriptionByAnotherPsiElementService.getInstance(myProject).getRegisteredPsiElementId(file); - if(registeredPsiElementId == null) - { - EditorNotificationBuilder panel = supplier.get(); - panel.withText(LocalizeValue.localizeTODO(StringUtil.SINGLE_QUOTER.apply(myProvider.getId()) + " model description is available for this file")); - panel.withAction(LocalizeValue.localizeTODO("Choose " + myProvider.getPsiElementName()), new Consumer>() - { - @Override - @RequiredUIAccess - public void accept(UIEvent uiEvent) - { - T chooseElement = myProvider.chooseElement(myProject); - if(chooseElement == null) - { - return; - } - - DescriptionByAnotherPsiElementService.getInstance(myProject).registerFile(file, chooseElement, myProvider); - - wantUpdate(psiFile); - } - }); - return panel; - } - else - { - EditorNotificationBuilder panel = supplier.get(); - panel.withText(LocalizeValue.localizeTODO(StringUtil.SINGLE_QUOTER.apply(myProvider.getId()) + " model description is registered for this file. " + myProvider.getPsiElementName() + ": " - + registeredPsiElementId)); - panel.withAction(LocalizeValue.localizeTODO("Cancel"), new Consumer>() - { - @Override - @RequiredUIAccess - public void accept(UIEvent uiEvent) - { - if(DescriptionByAnotherPsiElementService.getInstance(myProject).removeFile(file)) - { - wantUpdate(psiFile); - } - } - }); - return panel; - } - } - - private void wantUpdate(PsiFile psiFile) - { - PsiModificationTracker.getInstance(myProject).incCounter(); - - DaemonCodeAnalyzer.getInstance(myProject).restart(psiFile); - - EditorNotifications.getInstance(psiFile.getProject()).updateNotifications(psiFile.getVirtualFile()); - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/descriptionByAnotherPsiElement/DescriptionByAnotherPsiElementJsonDescriptionProvider.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/descriptionByAnotherPsiElement/DescriptionByAnotherPsiElementJsonDescriptionProvider.java deleted file mode 100644 index 792e0dcf..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/descriptionByAnotherPsiElement/DescriptionByAnotherPsiElementJsonDescriptionProvider.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2013-2015 must-be.org - * - * 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 consulo.json.validation.descriptionByAnotherPsiElement; - -import consulo.annotation.access.RequiredReadAction; -import consulo.annotation.component.ExtensionImpl; -import consulo.json.validation.JsonFileDescriptorProvider; -import consulo.json.validation.descriptor.JsonObjectDescriptor; -import consulo.language.psi.PsiElement; -import consulo.language.psi.PsiFile; -import consulo.language.psi.PsiUtilCore; -import consulo.util.lang.Pair; -import consulo.virtualFileSystem.VirtualFile; - -import javax.annotation.Nonnull; - -/** - * @author VISTALL - * @since 12.11.2015 - */ -@ExtensionImpl -public class DescriptionByAnotherPsiElementJsonDescriptionProvider implements JsonFileDescriptorProvider -{ - @RequiredReadAction - @Override - public boolean isMyFile(@Nonnull PsiFile file) - { - VirtualFile virtualFile = PsiUtilCore.getVirtualFile(file); - if(virtualFile == null) - { - return false; - } - return DescriptionByAnotherPsiElementService.getInstance(file.getProject()).getRegisteredPsiElementId(virtualFile) != null; - } - - @RequiredReadAction - @Override - public void fillRootObject(@Nonnull JsonObjectDescriptor root, @Nonnull PsiFile file) - { - VirtualFile virtualFile = PsiUtilCore.getVirtualFile(file); - if(virtualFile == null) - { - return; - } - - Pair, PsiElement> pair = DescriptionByAnotherPsiElementService.getInstance(file.getProject()) - .getRegisteredPsiElementInfo(virtualFile); - - PsiElement psiElement = pair.getSecond(); - if(psiElement == null) - { - return; - } - - pair.getFirst().fillRootObject(psiElement, root); - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/descriptionByAnotherPsiElement/DescriptionByAnotherPsiElementProvider.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/descriptionByAnotherPsiElement/DescriptionByAnotherPsiElementProvider.java deleted file mode 100644 index 317daf99..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/descriptionByAnotherPsiElement/DescriptionByAnotherPsiElementProvider.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2013-2015 must-be.org - * - * 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 consulo.json.validation.descriptionByAnotherPsiElement; - -import consulo.annotation.access.RequiredReadAction; -import consulo.annotation.component.ComponentScope; -import consulo.annotation.component.ExtensionAPI; -import consulo.json.validation.descriptor.JsonObjectDescriptor; -import consulo.language.psi.PsiElement; -import consulo.project.Project; -import consulo.ui.annotation.RequiredUIAccess; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * @author VISTALL - * @since 12.11.2015 - */ -@ExtensionAPI(ComponentScope.APPLICATION) -public interface DescriptionByAnotherPsiElementProvider -{ - @Nonnull - String getId(); - - @Nonnull - String getPsiElementName(); - - @Nonnull - @RequiredReadAction - String getIdFromPsiElement(@Nonnull T element); - - @Nullable - @RequiredReadAction - T getPsiElementById(@Nonnull String id, @Nonnull Project project); - - @RequiredUIAccess - @Nullable - T chooseElement(@Nonnull Project project); - - @RequiredReadAction - boolean isAvailable(@Nonnull Project project); - - void fillRootObject(@Nonnull T psiElement, @Nonnull JsonObjectDescriptor root); -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/descriptionByAnotherPsiElement/DescriptionByAnotherPsiElementRegistrar.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/descriptionByAnotherPsiElement/DescriptionByAnotherPsiElementRegistrar.java deleted file mode 100644 index c40377d2..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/descriptionByAnotherPsiElement/DescriptionByAnotherPsiElementRegistrar.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2013-2015 must-be.org - * - * 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 consulo.json.validation.descriptionByAnotherPsiElement; - -import consulo.annotation.component.ExtensionImpl; -import consulo.component.ComponentManager; -import consulo.component.extension.ExtensionExtender; -import consulo.fileEditor.EditorNotificationProvider; -import consulo.project.Project; - -import javax.annotation.Nonnull; -import java.util.function.Consumer; - -/** - * @author VISTALL - * @since 12.11.2015 - */ -@ExtensionImpl -@SuppressWarnings("unchecked") -public class DescriptionByAnotherPsiElementRegistrar implements ExtensionExtender -{ - @Override - public void extend(@Nonnull ComponentManager componentManager, @Nonnull Consumer consumer) - { - for(final DescriptionByAnotherPsiElementProvider provider : componentManager.getExtensionPoint(DescriptionByAnotherPsiElementProvider.class)) - { - consumer.accept(new DescriptionByAnotherPsiElementEditorNotification((Project) componentManager, provider)); - } - } - - @Nonnull - @Override - public Class getExtensionClass() - { - return EditorNotificationProvider.class; - } - - @Override - public boolean hasAnyExtensions(ComponentManager componentManager) - { - return componentManager.getExtensionPoint(DescriptionByAnotherPsiElementProvider.class).hasAnyExtensions(); - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/descriptionByAnotherPsiElement/DescriptionByAnotherPsiElementService.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/descriptionByAnotherPsiElement/DescriptionByAnotherPsiElementService.java deleted file mode 100644 index 4e31d177..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/descriptionByAnotherPsiElement/DescriptionByAnotherPsiElementService.java +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright 2013-2015 must-be.org - * - * 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 consulo.json.validation.descriptionByAnotherPsiElement; - -import consulo.annotation.component.ComponentScope; -import consulo.annotation.component.ServiceAPI; -import consulo.annotation.component.ServiceImpl; -import consulo.application.ApplicationManager; -import consulo.application.util.function.Computable; -import consulo.component.persist.PersistentStateComponent; -import consulo.component.persist.State; -import consulo.component.persist.Storage; -import consulo.component.persist.StoragePathMacros; -import consulo.disposer.Disposable; -import consulo.disposer.Disposer; -import consulo.ide.ServiceManager; -import consulo.language.psi.PsiElement; -import consulo.language.psi.SmartPointerManager; -import consulo.language.psi.SmartPsiElementPointer; -import consulo.project.Project; -import consulo.util.collection.ContainerUtil; -import consulo.util.lang.Pair; -import consulo.virtualFileSystem.VirtualFile; -import consulo.virtualFileSystem.pointer.VirtualFilePointer; -import consulo.virtualFileSystem.pointer.VirtualFilePointerManager; -import jakarta.inject.Inject; -import jakarta.inject.Singleton; -import org.jdom.Element; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -/** - * @author VISTALL - * @since 12.11.2015 - */ -@Singleton -@State(name = "JSONDescriptionByAnotherPsiElementService", storages = @Storage(StoragePathMacros.WORKSPACE_FILE)) -@ServiceAPI(ComponentScope.PROJECT) -@ServiceImpl -public class DescriptionByAnotherPsiElementService implements PersistentStateComponent, Disposable -{ - private static class Info implements Disposable - { - private final VirtualFilePointer myVirtualFilePointer; - private SmartPsiElementPointer myElementPointer; - private final DescriptionByAnotherPsiElementProvider myProvider; - - private final String myId; - private String myPsiElementId; - private Project myProject; - - public Info(@Nonnull Project project, @Nonnull VirtualFile virtualFile, @Nonnull PsiElement element, @Nonnull DescriptionByAnotherPsiElementProvider provider) - { - myProject = project; - myId = provider.getId(); - myProvider = provider; - myVirtualFilePointer = VirtualFilePointerManager.getInstance().create(virtualFile, this, null); - myElementPointer = SmartPointerManager.getInstance(element.getProject()).createSmartPsiElementPointer(element); - } - - public Info(@Nonnull Project project, @Nonnull String url, @Nonnull final String providerId, @Nonnull String psiElementId) - { - myProject = project; - myVirtualFilePointer = VirtualFilePointerManager.getInstance().create(url, this, null); - - myProvider = ContainerUtil.find(ApplicationManager.getApplication().getExtensionList(DescriptionByAnotherPsiElementProvider.class), it -> it.getId().equals(providerId)); - - myId = providerId; - myPsiElementId = psiElementId; - } - - public void tryToInit() - { - if(myProvider == null || myElementPointer != null) - { - return; - } - - ApplicationManager.getApplication().runReadAction(new Runnable() - { - @Override - public void run() - { - PsiElement psiElementById = myProvider.getPsiElementById(myPsiElementId, myProject); - if(psiElementById == null) - { - return; - } - myElementPointer = SmartPointerManager.getInstance(myProject).createSmartPsiElementPointer(psiElementById); - } - }); - } - - @Nonnull - public String getId() - { - if(myId != null) - { - return myId; - } - return myProvider.getId(); - } - - @Nonnull - public String getUrl() - { - return myVirtualFilePointer.getUrl(); - } - - @Nullable - @SuppressWarnings("unchecked") - public String getPsiElementId() - { - if(myPsiElementId != null) - { - return myPsiElementId; - } - - return ApplicationManager.getApplication().runReadAction(new Computable() - { - @Override - public String compute() - { - PsiElement element = myElementPointer.getElement(); - if(element == null) - { - return null; - } - return myProvider.getIdFromPsiElement(element); - } - }); - } - - @Nullable - public PsiElement getPsiElement() - { - if(myElementPointer == null) - { - if(myProvider == null) - { - return null; - } - return ApplicationManager.getApplication().runReadAction(new Computable() - { - @Override - public PsiElement compute() - { - PsiElement element = myElementPointer == null ? null : myElementPointer.getElement(); - if(element == null) - { - return null; - } - return myProvider.getPsiElementById(myPsiElementId, myProject); - } - }); - } - else - { - return myElementPointer.getElement(); - } - } - - @Override - public void dispose() - { - } - } - - @Nonnull - public static DescriptionByAnotherPsiElementService getInstance(@Nonnull Project project) - { - return ServiceManager.getService(project, DescriptionByAnotherPsiElementService.class); - } - - private final Project myProject; - private final List myRegisteredFiles = new ArrayList(); - - @Inject - public DescriptionByAnotherPsiElementService(Project project) - { - myProject = project; - } - - public void registerFile(@Nonnull VirtualFile virtualFile, @Nonnull T element, @Nonnull DescriptionByAnotherPsiElementProvider provider) - { - Info info = new Info(myProject, virtualFile, element, provider); - Disposer.register(this, info); - myRegisteredFiles.add(info); - } - - - public boolean removeFile(@Nonnull VirtualFile file) - { - Iterator iterator = myRegisteredFiles.iterator(); - while(iterator.hasNext()) - { - Info info = iterator.next(); - if(file.equals(info.myVirtualFilePointer.getFile())) - { - iterator.remove(); - Disposer.dispose(info); - return true; - } - } - return false; - } - - @Nullable - public String getRegisteredPsiElementId(@Nonnull VirtualFile virtualFile) - { - for(Info registeredFile : myRegisteredFiles) - { - VirtualFile file = registeredFile.myVirtualFilePointer.getFile(); - if(virtualFile.equals(file)) - { - return registeredFile.getPsiElementId(); - } - } - return null; - } - - @Nonnull - @SuppressWarnings("unchecked") - public Pair, T> getRegisteredPsiElementInfo(@Nonnull VirtualFile virtualFile) - { - for(Info info : myRegisteredFiles) - { - VirtualFile file = info.myVirtualFilePointer.getFile(); - if(virtualFile.equals(file)) - { - PsiElement psiElement = info.getPsiElement(); - if(psiElement == null) - { - return Pair.empty(); - } - return new Pair.NonNull(info.myProvider, psiElement); - } - } - return Pair.empty(); - } - - @Nullable - @Override - public Element getState() - { - Element stateElement = new Element("state"); - for(final Info registeredFile : myRegisteredFiles) - { - String psiElementId = registeredFile.getPsiElementId(); - if(psiElementId == null) - { - continue; - } - - Element fileElement = new Element("file"); - fileElement.setAttribute("id", registeredFile.getId()); - fileElement.setAttribute("url", registeredFile.getUrl()); - fileElement.setAttribute("psiElementId", psiElementId); - stateElement.addContent(fileElement); - } - return stateElement; - } - - @Override - public void loadState(Element state) - { - if(!myRegisteredFiles.isEmpty()) - { - for(Info registeredFile : myRegisteredFiles) - { - Disposer.dispose(registeredFile); - } - myRegisteredFiles.clear(); - } - - for(Element element : state.getChildren("file")) - { - String id = element.getAttributeValue("id"); - String url = element.getAttributeValue("url"); - String psiElementId = element.getAttributeValue("psiElementId"); - - final Info info = new Info(myProject, url, id, psiElementId); - ApplicationManager.getApplication().runReadAction(new Runnable() - { - @Override - public void run() - { - info.tryToInit(); - } - }); - Disposer.register(this, info); - myRegisteredFiles.add(info); - } - } - - @Override - public void dispose() - { - myRegisteredFiles.clear(); - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/descriptor/JsonObjectDescriptor.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/descriptor/JsonObjectDescriptor.java deleted file mode 100644 index edca4c39..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/descriptor/JsonObjectDescriptor.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2013-2015 must-be.org - * - * 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 consulo.json.validation.descriptor; - -import java.util.HashMap; -import java.util.Map; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import consulo.json.validation.NativeArray; -import consulo.util.collection.ContainerUtil; -import consulo.language.impl.ast.Factory; -import consulo.util.collection.Maps; - -/** - * @author VISTALL - * @since 10.11.2015 - */ -public class JsonObjectDescriptor -{ - private Map myProperties = new HashMap(); - - @Nonnull - public JsonPropertyDescriptor addProperty(@Nullable final String propertyName, @Nonnull final Class value) - { - if(value == Object.class) - { - throw new IllegalArgumentException("We cant add object type, use JsonObjectDescriptor as parameter"); - } - - return myProperties.computeIfAbsent(propertyName, p -> new JsonPropertyDescriptor(p, value)); - } - - @Nonnull - public JsonPropertyDescriptor addProperty(@Nullable final String propertyName, @Nonnull final JsonObjectDescriptor value) - { - return myProperties.computeIfAbsent(propertyName, p -> new JsonPropertyDescriptor(p, value)); - } - - @Nonnull - public JsonPropertyDescriptor addProperty(@Nullable final String propertyName, @Nonnull final NativeArray value) - { - return myProperties.computeIfAbsent(propertyName, p -> new JsonPropertyDescriptor(p, value)); - } - - @Nullable - public JsonPropertyDescriptor getProperty(@Nonnull final String propertyName) - { - JsonPropertyDescriptor propertyDescriptor = myProperties.get(propertyName); - if(propertyDescriptor != null) - { - return propertyDescriptor; - } - - return myProperties.get(null); - } - - public Map getProperties() - { - return myProperties; - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/descriptor/JsonPropertyDescriptor.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/descriptor/JsonPropertyDescriptor.java deleted file mode 100644 index c1278419..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/descriptor/JsonPropertyDescriptor.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2013-2015 must-be.org - * - * 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 consulo.json.validation.descriptor; - -import consulo.language.psi.SmartPointerManager; -import consulo.annotation.UsedInPlugin; -import consulo.language.psi.PsiElement; -import consulo.language.psi.SmartPsiElementPointer; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * @author VISTALL - * @since 10.11.2015 - */ -public class JsonPropertyDescriptor -{ - private SmartPsiElementPointer myNavigationElement; - - private String myName; - private Object myValue; - private boolean myDeprecated; - private boolean myNullable = true; - - public JsonPropertyDescriptor(@Nullable String name, @Nonnull Object value) - { - myName = name; - myValue = value; - } - - public boolean isNullable() - { - return myNullable; - } - - public boolean isDeprecated() - { - return myDeprecated; - } - - @Nonnull - public JsonPropertyDescriptor deprecated() - { - myDeprecated = true; - return this; - } - - @Nonnull - public JsonPropertyDescriptor notNull() - { - myNullable = false; - return this; - } - - @Nonnull - public Object getValue() - { - return myValue; - } - - @Nullable - public String getName() - { - return myName; - } - - @UsedInPlugin - public void setNavigationElement(@Nonnull PsiElement element) - { - myNavigationElement = SmartPointerManager.getInstance(element.getProject()).createSmartPsiElementPointer(element); - } - - @Nullable - public PsiElement getNavigationElement() - { - return myNavigationElement == null ? null : myNavigationElement.getElement(); - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/inspections/PropertyValidationInspection.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/inspections/PropertyValidationInspection.java deleted file mode 100644 index 7653958b..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/inspections/PropertyValidationInspection.java +++ /dev/null @@ -1,419 +0,0 @@ -/* - * Copyright 2013-2015 must-be.org - * - * 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 consulo.json.validation.inspections; - -import com.intellij.lang.javascript.JSTokenTypes; -import com.intellij.lang.javascript.psi.*; -import consulo.annotation.access.RequiredReadAction; -import consulo.annotation.component.ExtensionImpl; -import consulo.application.util.CachedValueProvider; -import consulo.application.util.CachedValuesManager; -import consulo.javascript.lang.JavaScriptTokenSets; -import consulo.javascript.psi.JSSimpleLiteralExpression; -import consulo.json.validation.JsonFileDescriptorProviders; -import consulo.json.validation.NativeArray; -import consulo.json.validation.descriptor.JsonObjectDescriptor; -import consulo.json.validation.descriptor.JsonPropertyDescriptor; -import consulo.language.ast.IElementType; -import consulo.language.editor.inspection.LocalInspectionTool; -import consulo.language.editor.inspection.ProblemHighlightType; -import consulo.language.editor.inspection.ProblemsHolder; -import consulo.language.editor.rawHighlight.HighlightDisplayLevel; -import consulo.language.psi.PsiElement; -import consulo.language.psi.PsiElementVisitor; -import consulo.language.psi.PsiModificationTracker; -import consulo.language.psi.PsiUtilCore; -import consulo.language.psi.util.PsiTreeUtil; -import consulo.util.collection.ContainerUtil; -import consulo.util.lang.StringUtil; -import consulo.util.lang.function.PairProcessor; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.*; - -/** - * @author VISTALL - * @since 10.11.2015 - */ -@ExtensionImpl -public class PropertyValidationInspection extends LocalInspectionTool -{ - @Nonnull - @Override - public PsiElementVisitor buildVisitor(@Nonnull final ProblemsHolder holder, boolean isOnTheFly) - { - return new JSElementVisitor() - { - @Override - @RequiredReadAction - public void visitJSLiteralExpression(JSSimpleLiteralExpression node) - { - validateValue(node, holder); - } - - @Override - @RequiredReadAction - public void visitJSPrefixExpression(JSPrefixExpression expression) - { - validateValue(expression, holder); - } - - @Override - @RequiredReadAction - public void visitJSObjectLiteralExpression(JSObjectLiteralExpression node) - { - validateValue(node, holder); - } - - @Override - @RequiredReadAction - public void visitJSArrayLiteralExpression(JSArrayLiteralExpression node) - { - validateValue(node, holder); - } - - @Override - @RequiredReadAction - public void visitJSProperty(JSProperty node) - { - JsonObjectDescriptor rootDescriptor = JsonFileDescriptorProviders.getRootDescriptor(node.getContainingFile()); - if(rootDescriptor == null) - { - return; - } - - Collection jsProperties = buildPropertiesAsTree(node, rootDescriptor); - if(jsProperties.isEmpty()) - { - return; - } - - JsonObjectDescriptor currentObject = rootDescriptor; - for(JSProperty property : jsProperties) - { - String name = property.getName(); - if(name == null) - { - return; - } - - JsonPropertyDescriptor propertyDescriptor = currentObject.getProperty(name); - if(propertyDescriptor == null) - { - if(node == property) - { - PsiElement nameIdentifier = node.getNameIdentifier(); - assert nameIdentifier != null; - - holder.registerProblem(nameIdentifier, "Undefined property", ProblemHighlightType.ERROR); - } - return; - } - else if(propertyDescriptor.getValue() instanceof JsonObjectDescriptor) - { - currentObject = (JsonObjectDescriptor) propertyDescriptor.getValue(); - } - else - { - return; - } - } - } - }; - } - - @RequiredReadAction - public static Collection buildPropertiesAsTree(PsiElement element, @Nullable JsonObjectDescriptor objectDescriptor) - { - JsonObjectDescriptor rootDescriptor = objectDescriptor == null ? JsonFileDescriptorProviders.getRootDescriptor(element.getContainingFile()) : objectDescriptor; - if(rootDescriptor == null) - { - return Collections.emptyList(); - } - - final Deque queue = new ArrayDeque<>(); - PsiTreeUtil.treeWalkUp(element, null, new PairProcessor() - { - @Override - public boolean process(PsiElement element, PsiElement element2) - { - if(element instanceof JSProperty) - { - queue.addFirst((JSProperty) element); - } - return true; - } - }); - return queue; - } - - @Nullable - @RequiredReadAction - private static Object getTypeOfExpression(@Nonnull PsiElement node) - { - if(node instanceof JSLiteralExpression) - { - PsiElement firstChild = node.getFirstChild(); - IElementType elementType = PsiUtilCore.getElementType(firstChild); - if(elementType == null) - { - return null; - } - - Class propertyType = null; - if(elementType == JSTokenTypes.NUMERIC_LITERAL) - { - propertyType = Number.class; - } - else if(JavaScriptTokenSets.STRING_LITERALS.contains(elementType)) - { - propertyType = String.class; - } - else if(elementType == JSTokenTypes.NULL_KEYWORD) - { - propertyType = Void.class; - } - else if(elementType == JSTokenTypes.TRUE_KEYWORD || elementType == JSTokenTypes.FALSE_KEYWORD) - { - propertyType = Boolean.class; - } - - if(propertyType == null) - { - return null; - } - return propertyType; - } - else if(node instanceof JSPrefixExpression) - { - return Number.class; - } - else if(node instanceof JSObjectLiteralExpression) - { - return Object.class; - } - else if(node instanceof JSArrayLiteralExpression) - { - Set types = new HashSet<>(); - JSExpression[] expressions = ((JSArrayLiteralExpression) node).getExpressions(); - for(JSExpression expression : expressions) - { - if(expression == null) - { - continue; - } - - Object typeOfExpression = getTypeOfExpression(expression); - ContainerUtil.addIfNotNull(types, typeOfExpression); - } - - int size = types.size(); - switch(size) - { - case 0: - return null; - case 1: - Object firstItem = ContainerUtil.getFirstItem(types); - assert firstItem != null; - return new NativeArray(firstItem); - default: - return new NativeArray(Object.class); - } - } - return null; - } - - @Nullable - @RequiredReadAction - public static JsonPropertyDescriptor findPropertyDescriptor(@Nonnull final JSProperty jsProperty) - { - return CachedValuesManager.getManager(jsProperty.getProject()).createCachedValue(new CachedValueProvider() - { - @Nullable - @Override - @RequiredReadAction - public Result compute() - { - return Result.create(findPropertyDescriptorImpl(jsProperty), jsProperty, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT); - } - }, false).getValue(); - } - - @Nullable - @RequiredReadAction - private static JsonPropertyDescriptor findPropertyDescriptorImpl(@Nonnull JSProperty jsProperty) - { - JsonObjectDescriptor rootDescriptor = JsonFileDescriptorProviders.getRootDescriptor(jsProperty.getContainingFile()); - if(rootDescriptor == null) - { - return null; - } - - Collection jsProperties = buildPropertiesAsTree(jsProperty, rootDescriptor); - if(jsProperties.isEmpty()) - { - return null; - } - - JsonPropertyDescriptor currentProperty = null; - JsonObjectDescriptor currentObject = rootDescriptor; - for(JSProperty property : jsProperties) - { - String name = property.getName(); - if(name == null) - { - return null; - } - - currentProperty = currentObject.getProperty(name); - if(currentProperty == null) - { - return null; - } - - Object value = currentProperty.getValue(); - if(value instanceof JsonObjectDescriptor) - { - currentObject = (JsonObjectDescriptor) value; - } - else if(value instanceof NativeArray) - { - Object componentType = ((NativeArray) value).getComponentType(); - if(componentType instanceof JsonObjectDescriptor) - { - currentObject = (JsonObjectDescriptor) componentType; - } - } - else - { - break; - } - } - - return currentProperty; - } - - @RequiredReadAction - private static void validateValue(@Nonnull PsiElement value, @Nonnull ProblemsHolder holder) - { - Object actualType = getTypeOfExpression(value); - if(actualType == null) - { - return; - } - PsiElement parent = value.getParent(); - if(!(parent instanceof JSProperty)) - { - return; - } - - JsonPropertyDescriptor currentProperty = findPropertyDescriptor((JSProperty) parent); - if(currentProperty == null) - { - return; - } - - Object expectedValue = currentProperty.getValue(); - if(!isInheritable(currentProperty, expectedValue, actualType)) - { - holder.registerProblem(value, "Wrong property value. Expected: " + getSimpleName(expectedValue) + ", actual: " + getSimpleName(actualType), ProblemHighlightType.GENERIC_ERROR); - } - - if(currentProperty.isDeprecated()) - { - PsiElement nameIdentifier = ((JSProperty) parent).getNameIdentifier(); - assert nameIdentifier != null; - holder.registerProblem(nameIdentifier, "Deprecated property", ProblemHighlightType.LIKE_DEPRECATED); - } - } - - public static boolean isInheritable(JsonPropertyDescriptor currentProperty, Object expected, Object actual) - { - // null value - if(currentProperty.isNullable() && actual == Void.class) - { - return true; - } - - if(expected instanceof Class && actual instanceof Class) - { - return expected == actual; - } - - if(expected instanceof JsonObjectDescriptor && actual == Object.class) - { - return true; - } - - if(expected instanceof NativeArray && actual instanceof NativeArray) - { - return isInheritable(currentProperty, ((NativeArray) expected).getComponentType(), ((NativeArray) actual).getComponentType()); - } - return false; - } - - @Nonnull - private static String getSimpleName(Object o) - { - if(o instanceof Class) - { - if(o == Void.class) - { - return "null"; - } - return StringUtil.decapitalize(((Class) o).getSimpleName()); - } - else if(o instanceof JsonObjectDescriptor) - { - return getSimpleName(Object.class); - } - else if(o instanceof NativeArray) - { - return getSimpleName(((NativeArray) o).getComponentType()) + "[]"; - } - return "null"; - } - - @Nonnull - @Override - public String[] getGroupPath() - { - return new String[]{"JSON"}; - } - - @Nonnull - @Override - public String getGroupDisplayName() - { - throw new UnsupportedOperationException(); - } - - @Nonnull - @Override - public String getDisplayName() - { - return "Property validation"; - } - - @Nonnull - @Override - public HighlightDisplayLevel getDefaultLevel() - { - return HighlightDisplayLevel.ERROR; - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/psi/reference/JsonPropertyNameReference.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/psi/reference/JsonPropertyNameReference.java deleted file mode 100644 index 0df3f52a..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/psi/reference/JsonPropertyNameReference.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2013-2015 must-be.org - * - * 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 consulo.json.validation.psi.reference; - -import javax.annotation.Nullable; - -import consulo.annotation.access.RequiredReadAction; -import consulo.json.validation.descriptor.JsonPropertyDescriptor; -import consulo.json.validation.inspections.PropertyValidationInspection; -import com.intellij.lang.javascript.psi.JSProperty; -import com.intellij.lang.javascript.psi.impl.reference.JSPropertyNameReference; -import consulo.language.psi.PsiElement; - -/** - * @author VISTALL - * @since 02.12.2015 - */ -public class JsonPropertyNameReference extends JSPropertyNameReference -{ - private JsonPropertyDescriptor myPropertyDescriptor; - - public JsonPropertyNameReference(JSProperty property, PsiElement nameIdentifier, JsonPropertyDescriptor propertyDescriptor) - { - super(property, nameIdentifier); - myPropertyDescriptor = propertyDescriptor; - } - - @Nullable - @Override - @RequiredReadAction - public PsiElement resolve() - { - PsiElement navigationElement = myPropertyDescriptor.getNavigationElement(); - if(navigationElement != null) - { - return navigationElement; - } - return super.resolve(); - } - - @RequiredReadAction - @Override - public boolean isReferenceTo(PsiElement element) - { - if(element instanceof JSProperty) - { - JsonPropertyDescriptor propertyDescriptor = PropertyValidationInspection.findPropertyDescriptor((JSProperty) element); - return myPropertyDescriptor == propertyDescriptor; - } - else if(element == myPropertyDescriptor.getNavigationElement()) - { - return true; - } - return false; - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/psi/reference/JsonPropertyNameReferenceProvider.java b/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/psi/reference/JsonPropertyNameReferenceProvider.java deleted file mode 100644 index 96b280f7..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/consulo/json/validation/psi/reference/JsonPropertyNameReferenceProvider.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2013-2015 must-be.org - * - * 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 consulo.json.validation.psi.reference; - -import com.intellij.lang.javascript.psi.JSProperty; -import consulo.annotation.access.RequiredReadAction; -import consulo.annotation.component.ExtensionImpl; -import consulo.javascript.psi.impl.reference.JSPropertyNameReferenceProvider; -import consulo.json.validation.descriptor.JsonPropertyDescriptor; -import consulo.json.validation.inspections.PropertyValidationInspection; -import consulo.language.psi.PsiElement; -import consulo.language.psi.PsiReference; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * @author VISTALL - * @since 02.12.2015 - */ -@ExtensionImpl(order = "before default") -public class JsonPropertyNameReferenceProvider implements JSPropertyNameReferenceProvider -{ - @RequiredReadAction - @Nullable - @Override - public PsiReference getReference(@Nonnull JSProperty property) - { - JsonPropertyDescriptor propertyDescriptor = PropertyValidationInspection.findPropertyDescriptor(property); - if(propertyDescriptor == null) - { - return null; - } - - PsiElement nameIdentifier = property.getNameIdentifier(); - assert nameIdentifier != null; - return new JsonPropertyNameReference(property, nameIdentifier, propertyDescriptor); - } -} diff --git a/lang-version-impl/json-javascript-impl/src/main/java/module-info.java b/lang-version-impl/json-javascript-impl/src/main/java/module-info.java deleted file mode 100644 index 7efd96d2..00000000 --- a/lang-version-impl/json-javascript-impl/src/main/java/module-info.java +++ /dev/null @@ -1,24 +0,0 @@ -/** - * @author VISTALL - * @since 29-Aug-22 - */ -module consulo.javascript.json.javascript.impl -{ - // TODO remove in future - requires java.desktop; - - requires consulo.javascript.base.impl; - - exports consulo.json; - exports consulo.json.jom; - exports consulo.json.jom.proxy; - exports consulo.json.jom.proxy.impl; - exports consulo.json.lang; - exports consulo.json.lang.lexer; - exports consulo.json.validation; - exports consulo.json.validation.completion; - exports consulo.json.validation.descriptionByAnotherPsiElement; - exports consulo.json.validation.descriptor; - exports consulo.json.validation.inspections; - exports consulo.json.validation.psi.reference; -} \ No newline at end of file diff --git a/lang-version-impl/typescript-impl/pom.xml b/lang-version-impl/typescript-impl/pom.xml index 680b80d6..18e4bbab 100644 --- a/lang-version-impl/typescript-impl/pom.xml +++ b/lang-version-impl/typescript-impl/pom.xml @@ -32,7 +32,7 @@ consulo - https://maven.consulo.io/repository/snapshots/ + https://maven.consulo.dev/repository/snapshots/ true interval:60 diff --git a/lang-version-impl/typescript-impl/src/main/java/consulo/typescript/TypeScriptFileType.java b/lang-version-impl/typescript-impl/src/main/java/consulo/typescript/TypeScriptFileType.java index 5be239f6..ead84fcc 100644 --- a/lang-version-impl/typescript-impl/src/main/java/consulo/typescript/TypeScriptFileType.java +++ b/lang-version-impl/typescript-impl/src/main/java/consulo/typescript/TypeScriptFileType.java @@ -29,55 +29,48 @@ import consulo.typescript.version.TypeScriptLanguageVersion; import consulo.ui.image.Image; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL * @since 03.03.2016 */ -public class TypeScriptFileType extends LanguageFileType implements JavaScriptFileTypeWithVersion -{ - public static final TypeScriptFileType INSTANCE = new TypeScriptFileType(); +public class TypeScriptFileType extends LanguageFileType implements JavaScriptFileTypeWithVersion { + public static final TypeScriptFileType INSTANCE = new TypeScriptFileType(); - private TypeScriptFileType() - { - super(JavaScriptLanguage.INSTANCE); - } + private TypeScriptFileType() { + super(JavaScriptLanguage.INSTANCE); + } - @Nonnull - @Override - public String getId() - { - return "TypeScript"; - } + @Nonnull + @Override + public String getId() { + return "TypeScript"; + } - @Nonnull - @Override - public LocalizeValue getDescription() - { - return JavaScriptLocalize.typescriptFiletypeDescription(); - } + @Nonnull + @Override + public LocalizeValue getDescription() { + return JavaScriptLocalize.typescriptFiletypeDescription(); + } - @Nonnull - @Override - public String getDefaultExtension() - { - return "ts"; - } + @Nonnull + @Override + public String getDefaultExtension() { + return "ts"; + } - @Nullable - @Override - public Image getIcon() - { - return JavaScriptIconGroup.typescript(); - } + @Nullable + @Override + public Image getIcon() { + return JavaScriptIconGroup.typescript(); + } - @RequiredReadAction - @Nonnull - @Override - public LanguageVersion getLanguageVersion(@Nullable Module module, @Nullable VirtualFile virtualFile) - { - return TypeScriptLanguageVersion.getInstance(); - } + @RequiredReadAction + @Nonnull + @Override + public LanguageVersion getLanguageVersion(@Nullable Module module, @Nullable VirtualFile virtualFile) { + return TypeScriptLanguageVersion.getInstance(); + } } diff --git a/lang-version-impl/typescript-impl/src/main/java/consulo/typescript/TypeScriptFileTypeFactory.java b/lang-version-impl/typescript-impl/src/main/java/consulo/typescript/TypeScriptFileTypeFactory.java index b529295c..e74068ec 100644 --- a/lang-version-impl/typescript-impl/src/main/java/consulo/typescript/TypeScriptFileTypeFactory.java +++ b/lang-version-impl/typescript-impl/src/main/java/consulo/typescript/TypeScriptFileTypeFactory.java @@ -19,19 +19,16 @@ import consulo.annotation.component.ExtensionImpl; import consulo.virtualFileSystem.fileType.FileTypeConsumer; import consulo.virtualFileSystem.fileType.FileTypeFactory; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 03.03.2016 */ @ExtensionImpl -public class TypeScriptFileTypeFactory extends FileTypeFactory -{ - @Override - public void createFileTypes(@Nonnull FileTypeConsumer consumer) - { - consumer.consume(TypeScriptFileType.INSTANCE); - } +public class TypeScriptFileTypeFactory extends FileTypeFactory { + @Override + public void createFileTypes(@Nonnull FileTypeConsumer consumer) { + consumer.consume(TypeScriptFileType.INSTANCE); + } } diff --git a/lang-version-impl/typescript-impl/src/main/java/consulo/typescript/version/TypeScriptLanguageVersion.java b/lang-version-impl/typescript-impl/src/main/java/consulo/typescript/version/TypeScriptLanguageVersion.java index c16c9fdb..f6259a92 100644 --- a/lang-version-impl/typescript-impl/src/main/java/consulo/typescript/version/TypeScriptLanguageVersion.java +++ b/lang-version-impl/typescript-impl/src/main/java/consulo/typescript/version/TypeScriptLanguageVersion.java @@ -5,36 +5,32 @@ import consulo.javascript.language.JavaScriptFeature; import consulo.javascript.language.JavaScriptLanguage; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 20-Jul-22 */ @ExtensionImpl -public class TypeScriptLanguageVersion extends BaseEcmaScriptJavaScriptVersion -{ - @Nonnull - public static TypeScriptLanguageVersion getInstance() - { - return JavaScriptLanguage.INSTANCE.findVersionByClass(TypeScriptLanguageVersion.class); - } +public class TypeScriptLanguageVersion extends BaseEcmaScriptJavaScriptVersion { + @Nonnull + public static TypeScriptLanguageVersion getInstance() { + return JavaScriptLanguage.INSTANCE.findVersionByClass(TypeScriptLanguageVersion.class); + } - public TypeScriptLanguageVersion() - { - super("TYPESCRIPT", "application/typescript"); - addFeature(JavaScriptFeature.CLASS); - addFeature(JavaScriptFeature.BINARY_LITERAL); - addFeature(JavaScriptFeature.OCTAL_LITERAL); - addFeature(JavaScriptFeature.PARAMETER_DEFAULT_VALUE); - addFeature(JavaScriptFeature.REST_PARAMETER); - addFeature(JavaScriptFeature.FUNCTION_PROPERTY); - } + public TypeScriptLanguageVersion() { + super("TYPESCRIPT", "application/typescript"); + addFeature(JavaScriptFeature.CLASS); + addFeature(JavaScriptFeature.BINARY_LITERAL); + addFeature(JavaScriptFeature.OCTAL_LITERAL); + addFeature(JavaScriptFeature.PARAMETER_DEFAULT_VALUE); + addFeature(JavaScriptFeature.REST_PARAMETER); + addFeature(JavaScriptFeature.FUNCTION_PROPERTY); + } - @Nonnull - @Override - public String getPresentableName() - { - return "TypeScript"; - } + @Nonnull + @Override + public String getPresentableName() { + return "TypeScript"; + } } diff --git a/lang-version-impl/typescript-impl/src/main/java/module-info.java b/lang-version-impl/typescript-impl/src/main/java/module-info.java index f74cc481..35176754 100644 --- a/lang-version-impl/typescript-impl/src/main/java/module-info.java +++ b/lang-version-impl/typescript-impl/src/main/java/module-info.java @@ -2,11 +2,10 @@ * @author VISTALL * @since 29-Aug-22 */ -module consulo.javascript.typescript.impl -{ - requires consulo.javascript.base.impl; - requires consulo.javascript.ecmascript.impl; +module consulo.javascript.typescript.impl { + requires consulo.javascript.base.impl; + requires consulo.javascript.ecmascript.impl; - exports consulo.typescript; - exports consulo.typescript.version; + exports consulo.typescript; + exports consulo.typescript.version; } \ No newline at end of file diff --git a/plugin/pom.xml b/plugin/pom.xml index 49ca2107..74fc1fb3 100644 --- a/plugin/pom.xml +++ b/plugin/pom.xml @@ -15,175 +15,205 @@ - limitations under the License. --> - 4.0.0 - - consulo - arch.ide-api-provided - 3-SNAPSHOT - - - - consulo.plugin - consulo.javascript - 3-SNAPSHOT - consulo-plugin - - - - consulo - https://maven.consulo.io/repository/snapshots/ - - true - interval:60 - - - - - - - - consulo.maven - maven-consulo-plugin - true - - valhalla - - com.intellij.xml - com.intellij.regexp - - - ${dev.mode} - ${build.number} - - - - - package - - workspace - - - - - - - - - - ${project.groupId} - consulo.javascript-base.api - ${project.version} - - - - ${project.groupId} - consulo.javascript-base.impl - ${project.version} - - - - ${project.groupId} - consulo.javascript-web.browser.impl - ${project.version} - - - - ${project.groupId} - consulo.javascript-actionscript.impl - ${project.version} - - - - ${project.groupId} - consulo.javascript-ecmascript4.impl - ${project.version} - - - - ${project.groupId} - consulo.javascript-ecmascript.impl - ${project.version} - - - - ${project.groupId} - consulo.javascript-javascript16.impl - ${project.version} - - - - ${project.groupId} - consulo.javascript-javascript17.impl - ${project.version} - - - - ${project.groupId} - consulo.javascript-javascript18.impl - ${project.version} - - - - ${project.groupId} - consulo.javascript-json.javascript.impl - ${project.version} - - - - ${project.groupId} - consulo.javascript-typescript.impl - ${project.version} - - - - ${project.groupId} - consulo.javascript-inspections - ${project.version} - - - - ${project.groupId} - consulo.javascript-intentions - ${project.version} - - - - com.googlecode.json-simple - json-simple - 1.1.1 - - - - ${project.groupId} - consulo.javascript-debugger.impl - ${project.version} - - - - ${project.groupId} - consulo.javascript-v8.debugger.impl - ${project.version} - - - - ${project.groupId} - consulo.javascript-regexp.impl - ${project.version} - - - - consulo.internal - lib.org.chromium.sdk - 1.0-SNAPSHOT - - - - - ${project.groupId} - com.intellij.xml - ${project.version} - provided - - + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + + consulo + arch.ide-api-provided + 3-SNAPSHOT + + + + consulo.plugin + consulo.javascript + 3-SNAPSHOT + consulo-plugin + + + + consulo + https://maven.consulo.dev/repository/snapshots/ + + true + interval:60 + + + + + + + + consulo.maven + maven-consulo-plugin + true + + nightly + + com.intellij.xml + com.intellij.regexp + + + ${dev.mode} + ${build.number} + + + + + package + + workspace + + + + + + + + + + ${project.groupId} + consulo.javascript-base.api + ${project.version} + + + + ${project.groupId} + consulo.javascript-base.impl + ${project.version} + + + + ${project.groupId} + consulo.javascript-web.browser.impl + ${project.version} + + + + ${project.groupId} + consulo.javascript-actionscript.impl + ${project.version} + + + + ${project.groupId} + consulo.javascript-ecmascript4.impl + ${project.version} + + + + ${project.groupId} + consulo.javascript-ecmascript.impl + ${project.version} + + + + ${project.groupId} + consulo.javascript-javascript16.impl + ${project.version} + + + + ${project.groupId} + consulo.javascript-javascript17.impl + ${project.version} + + + + ${project.groupId} + consulo.javascript-javascript18.impl + ${project.version} + + + + ${project.groupId} + consulo.javascript-typescript.impl + ${project.version} + + + + ${project.groupId} + consulo.javascript-inspections + ${project.version} + + + + ${project.groupId} + consulo.javascript-intentions + ${project.version} + + + + ${project.groupId} + consulo.javascript-debugger.impl + ${project.version} + + + + ${project.groupId} + consulo.javascript-regexp.impl + ${project.version} + + + + ${project.groupId} + consulo.javascript-browser.debugger.impl + ${project.version} + + + + ${project.groupId} + consulo.javascript-cdt.debugger.impl + ${project.version} + + + + consulo.internal.com.github.kklisura.cdt + cdt-java-client + 4.0.2 + + + org.javassist + javassist + + + + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.core + jackson-annotations + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + + consulo.internal + lib.org.chromium.sdk + 1.0-SNAPSHOT + + + + consulo.internal + forms_rt + provided + true + + + + + ${project.groupId} + com.intellij.xml + ${project.version} + provided + + \ No newline at end of file diff --git a/plugin/src/main/dist/sdk/clientAny/AJAX.js b/plugin/src/main/dist/sdk/clientAny/AJAX.js index e5af177a..bee9584d 100644 --- a/plugin/src/main/dist/sdk/clientAny/AJAX.js +++ b/plugin/src/main/dist/sdk/clientAny/AJAX.js @@ -1,22 +1,19 @@ -window.ActiveXObject = function() {};//XMLHttpRequest -window.XmlHttpRequest = function() {};//XMLHttpRequest -window.prototype = new Object(); +window.ActiveXObject = function () { return {}; }; //XMLHttpRequest +window.XmlHttpRequest = function () { return {}; }; //XMLHttpRequest var XMLHttpRequest = { - onreadystatechange: function () {} + abort: function () {}, //Object + constructor: {}, + getAllResponseHeaders: function () { return ""; }, + getResponseHeader: function (headerName) { return ""; }, + readyState: 0, + responseText: "", + responseXML: "", + onreadystatechange: function () {}, + open: function (method, url, async, username, password) { return {}; }, + overrideMimeType: function (mimeType) { return {}; }, //Gecko + send: function (content) {}, + setRequestHeader: function (label, value) {}, + statusText: "", + status: 0, }; -XMLHttpRequest.constructor = 0;//Object -XMLHttpRequest.readyState = 0;//Number -XMLHttpRequest.responseText = 0;//String -XMLHttpRequest.statusText = 0;//String -XMLHttpRequest.status = 0;//Number -XMLHttpRequest.responseXML = 0;//String -XMLHttpRequest.abort = function() {};//Object -XMLHttpRequest.getAllResponseHeaders = function() {};//String -XMLHttpRequest.getResponseHeader = function(headerName) {};//String -XMLHttpRequest.overrideMimeType = function(mimeType) {};//Gecko,Object -XMLHttpRequest.open = function(method,url,async,username,password) {};//Object -XMLHttpRequest.send = function(content) {};//void -XMLHttpRequest.setRequestHeader = function(label,value) {};//void - -XMLHttpRequest.prototype = new Object(); diff --git a/plugin/src/main/dist/sdk/clientAny/DHTML.js b/plugin/src/main/dist/sdk/clientAny/DHTML.js index eb9d5d0b..60651c8c 100644 --- a/plugin/src/main/dist/sdk/clientAny/DHTML.js +++ b/plugin/src/main/dist/sdk/clientAny/DHTML.js @@ -1,868 +1,922 @@ -Object.__defineGetter__ = function(propertyName,func) {};//Gecko,Object -Object.__defineSetter__ = function(propertyName,func) {};//Gecko,Object -Object.__lookupGetter__ = function(propertyName) {};//Gecko,Function -Object.__lookupSetter__ = function(propertyName) {};//Gecko,Function -Object.__proto__ = function(propertyName) {};//Gecko,Function - -Image = function() {}; -Image.constructor = 0;//Object -Image.naturalWidth = 0;//Gecko,Object -Image.naturalHeight = 0;//Gecko,Object +__defineGetter__ = function (propertyName, func) { return {}; }; //Gecko +__defineSetter__ = function (propertyName, func) { return {}; }; //Gecko +__lookupGetter__ = function (propertyName) { return {}; }; //Gecko,Function +__lookupSetter__ = function (propertyName) { return {}; }; //Gecko,Function +__proto__ = function (propertyName) { return {}; }; //Gecko,Function + +var Image = function () {}; Image.prototype = new HTMLImageElement(); +Image.constructor = {}; +Image.naturalWidth = {}; //Gecko +Image.naturalHeight = {}; //Gecko + +var Navigator = { + appCodeName: "", + appName: "", + appVersion: "", + javaEnabled: function () { return false; }, + language: "", + mimeTypes: [], + platform: [], + plugins: "", + preference: function (prefName, prefValue) { return ""; }, + product: "", + systemLanguage: "", //IE + taintEnabled: function () { return false; }, + userAgent: "", + userLanguage: "", //IE +}; + +var Screen = { + availHeight: 0, + availWidth: 0, + colorDepth: 0, + height: 0, + pixelDepth: 0, + width: 0, +}; + +var location = { + href: "", + hash: "", + host: "", + hostname: "", + pathname: "", + port: "", + protocol: "", + reload: function () {}, + replace: function (url) {}, + search: "", + target: "", +}; -Navigator.userAgent = 0;//String -Navigator.product = 0;//String -Navigator.appVersion = 0;//String -Navigator.appName = 0;//String -Navigator.appCodeName = 0;//String -Navigator.language = 0;//String -Navigator.systemLanguage = 0;//IE,String -Navigator.userLanguage = 0;//IE,String -Navigator.mimeTypes = 0;//Array -Navigator.platform = 0;//Array -Navigator.plugins = 0;//String -Navigator = {}; -Navigator.taintEnabled = function() {};//Boolean -Navigator.javaEnabled = function() {};//Boolean -Navigator.preference = function(prefName,prefValue) {};//String -Navigator.prototype = new Object(); - -Screen.width = 0;//Number -Screen.height = 0;//Number -Screen.availHeight = 0;//Number -Screen.availWidth = 0;//Number -Screen.pixelDepth = 0;//Number -Screen.colorDepth = 0;//Number -Screen = {}; -Screen.prototype = new Object(); - -location.href = 0;//String -location.hash = 0;//String -location.port = 0;//String -location.host = 0;//String -location.hostname = 0;//String -location.pathname = 0;//String -location.protocol = 0;//String -location.port = 0;//String -location.search = 0;//String -location.target = 0;//String -location = {}; -location.reload = function() {};//void -location.replace = function(url) {};//void -location.prototype = new Object(); - -XSLTProcessor = function() {}; -XSLTProcessor.constructor = 0;//Gecko,Object -XSLTProcessor.importStylesheet = function(domNode) {};//Gecko,Object -XSLTProcessor.transformToDocument = function(domNode) {};//Gecko,Document -XSLTProcessor.transformToFragment = function(domToBeTransformed,ownerDocument) {};//Gecko,DocumentFragment +var XSLTProcessor = function () {}; XSLTProcessor.prototype = new Object(); +XSLTProcessor.constructor = {}; //Gecko +XSLTProcessor.importStylesheet = function (domNode) { return {}; }; //Gecko +XSLTProcessor.transformToDocument = function (domNode) { return {}; }; //Gecko,Document +XSLTProcessor.transformToFragment = function (domToBeTransformed, ownerDocument) { return {}; }; //Gecko,DocumentFragment -DOMParser = function() {}; -DOMParser.constructor = 0;//Gecko,Object -DOMParser.parseFromString = function(stringToParse,contentType) {};//Gecko,Document +var DOMParser = function () {}; DOMParser.prototype = new Object(); +DOMParser.constructor = {}; //Gecko +DOMParser.parseFromString = function (stringToParse, contentType) { return {}; }; //Gecko,Document -XMLSerializer = function() {}; -XMLSerializer.constructor = 0;//Gecko,Object -XMLSerializer.serializeToStream = function(domNode,stream,encoding) {};//Gecko,Object -XMLSerializer.serializeToString = function(domNode) {};//Gecko,String +var XMLSerializer = function () {}; XMLSerializer.prototype = new Object(); +XMLSerializer.constructor = 0; //Gecko,Object +XMLSerializer.serializeToStream = function (domNode, stream, encoding) { return {}; }; //Gecko +XMLSerializer.serializeToString = function (domNode) { return ""; }; //Gecko + +var Event = { + altKey: false, + button: false, + cancelBubble: false, //IE + charCode: "", //Gecko + clientX: 0, + clientY: 0, + ctrlKey: false, + data: {}, + height: 0, + fromElement: {}, //IE + keyCode: 0, + layerX: 0, //Gecko + layerY: 0, //Gecko + modifiers: 0, + offsetX: 0, //IE + offsetY: 0, //IE + pageX: 0, + pageY: 0, + repeat: false, //IE + returnValue: false, //IE + screenX: 0, + screenY: 0, + shiftKey: false, + srcElement: {}, //IE + toElement: {}, //IE + type: "", + wheelDelta: 0, //IE + which: {}, + width: 0, + x: 0, //IE + y: 0, //IE + // deprecated + ABORT: "", //Gecko,deprecated + BLUR: "", //Gecko,deprecated + CLICK: "", //Gecko,deprecated + CHANGE: "", //Gecko,deprecated + DBLCLICK: "", //Gecko,deprecated + DRAGDROP: "", //Gecko,deprecated + ERROR: "", //Gecko,deprecated + FOCUS: "", //Gecko,deprecated + KEYDOWN: "", //Gecko,deprecated + KEYPRESS: "", //Gecko,deprecated + KEYUP: "", //Gecko,deprecated + LOAD: "", //Gecko,deprecated + MOUSEDOWN: "", //Gecko,deprecated + MOUSEMOVE: "", //Gecko,deprecated + MOUSEOUT: "", //Gecko,deprecated + MOUSEOVER: "", //Gecko,deprecated + MOUSEUP: "", //Gecko,deprecated + MOVE: "", //Gecko,deprecated + RESET: "", //Gecko,deprecated + RESIZE: "", //Gecko,deprecated + SELECT: "", //Gecko,deprecated + SUBMIT: "", //Gecko,deprecated + UNLOAD: "", //Gecko,deprecated +}; + +var Selection = { + addRange: function (range) {}, //Gecko,void + anchorNode: {}, //Gecko,Node + anchorOffset: 0, //Gecko + clear: function () {}, //IE,Boolean + collapse: function (parentNode, offset) {}, //Gecko + collapseToStart: function () {}, //Gecko + collapseToEnd: function () {}, //Gecko + containsNode: function (node, partlyContained) { return false; }, //Gecko + createRange: function () { return {}; }, //IE,TextRange + empty: function () { return true; }, //IE + extend: function (parentNode, offset) {}, //Gecko + focusNode: {}, //Gecko,Node + focusOffset: 0, //Gecko + getRangeAt: function (index) { return {}; }, //Gecko,Range + isCollapsed: false, //Gecko + rangeCount: 0, //Gecko + removeRange: function (range) {}, //Gecko + removeAllRanges: function () {}, //Gecko + selectAllChildren: function (parentNode) {}, //Gecko + type: {}, //IE +}; + +var TextRange = { + boundingHeight: 0, //IE + boundingLeft: 0, //IE + boundingTop: 0, //IE + boundingWidth: 0, //IE + collapse: function (start) {}, //IE,void + compareEndPoint: function (type, range) {}, //IE + compareEndPoints: function (sType, oRange) { return 0; }, //IE + duplicate: function () { return {}; }, //IE,TextRange + expand: function (unit) {}, //IE + htmlText: "", //IE + inRange: function (other) { return false; }, //IE + isEqual: function (other) { return false; }, //IE + move: function (unit, count) {}, //IE + moveEnd: function (unit, count) {}, //IE + moveStart: function (unit, count) {}, //IE + moveToElementText: function (element) {}, //IE + offsetLeft: 0, //IE + offsetTop: 0, //IE + parentElement: function () { return {}; }, //IE,Node + pasteHTML: function (htmlText) {}, //IE + scrollIntoView: function (start) {}, //IE + select: function () {}, //IE + setEndPoint: function (type, range) {}, //IE + text: "", //IE +}; + +var document = { + all: 0, //IE,All + execCommand: function (sCommand, bUserInterface, vValue) { return false; }, //IE + namespaces: [], //IE + selection: {}, //IE,Selection + styleSheets: [], //Stylesheet[] +}; + +var CssRule = { + selectorText: "", +}; + +var Stylesheet = { + addRule: function (selector, style) {}, //IE + cssRules: [], //Gecko,CssRule[] + deleteRule: function (index) {}, //Gecko + insertRule: function (ruleText, index) {}, //Gecko + owningElement: {}, //IE,HtmlElement + removeRule: function (index) {}, //IE + rules: 0, //IE,CssRule[] +}; + +var MozillaSideBar = { + addPanel: function (title, url, param3) {}, //Gecko +}; + +var IEExternal = { + AddFavorite: function (title, url) {}, //IE +}; -Event.data = 0;//Object[] -Event.height = 0;//Number -Event.x = 0;//IE,Number -Event.screenX = 0;//Number -Event.clientX = 0;//Number -Event.offsetX = 0;//IE,Number -Event.layerX = 0;//Gecko,Number -Event.fromElement = 0;//IE,Object -Event.wheelDelta = 0;//IE,Number -Event.repeat = 0;//IE,Boolean -Event.pageX = 0;//Number -Event.y = 0;//IE,Number -Event.screenY = 0;//Number -Event.clientY = 0;//Number -Event.offsetY = 0;//IE,Number -Event.layerY = 0;//Gecko,Number -Event.pageY = 0;//Number -Event.width = 0;//Number -Event.modifiers = 0;//Number -Event.keyCode = 0;//Number -Event.type = 0;//String -Event.which = 0;//Object -Event.srcElement = 0;//IE,Object -Event.toElement = 0;//IE,Object -Event.cancelBubble = 0;//IE,Boolean -Event.returnValue = 0;//IE,Boolean -Event.altKey = 0;//Boolean -Event.ctrlKey = 0;//Boolean -Event.shiftKey = 0;//Boolean -Event.button = 0;//Boolean -Event.charCode = 0;//Gecko,String -Event.ABORT = 0;//Gecko,String,deprecated -Event.BLUR = 0;//Gecko,String,deprecated -Event.CLICK = 0;//Gecko,String,deprecated -Event.CHANGE = 0;//Gecko,String,deprecated -Event.DBLCLICK = 0;//Gecko,String,deprecated -Event.DRAGDROP = 0;//Gecko,String,deprecated -Event.ERROR = 0;//Gecko,String,deprecated -Event.FOCUS = 0;//Gecko,String,deprecated -Event.KEYDOWN = 0;//Gecko,String,deprecated -Event.KEYPRESS = 0;//Gecko,String,deprecated -Event.KEYUP = 0;//Gecko,String,deprecated -Event.LOAD = 0;//Gecko,String,deprecated -Event.MOUSEDOWN = 0;//Gecko,String,deprecated -Event.MOUSEMOVE = 0;//Gecko,String,deprecated -Event.MOUSEOUT = 0;//Gecko,String,deprecated -Event.MOUSEOVER = 0;//Gecko,String,deprecated -Event.MOUSEUP = 0;//Gecko,String,deprecated -Event.MOVE = 0;//Gecko,String,deprecated -Event.RESET = 0;//Gecko,String,deprecated -Event.RESIZE = 0;//Gecko,String,deprecated -Event.SELECT = 0;//Gecko,String,deprecated -Event.SUBMIT = 0;//Gecko,String,deprecated -Event.UNLOAD = 0;//Gecko,String,deprecated -Event = {}; -Event.prototype = new Object(); - -Selection.anchorNode = 0;//Gecko,Node -Selection.anchorOffset = 0;//Gecko,Number -Selection.focusNode = 0;//Gecko,Node -Selection.focusOffset = 0;//Gecko,Number -Selection.isCollapsed = 0;//Gecko,Boolean -Selection.rangeCount = 0;//Gecko,Number -Selection.type = 0;//IE,Object -Selection = {}; -Selection.getRangeAt = function(index) {};//Gecko,Range -Selection.collapse = function(parentNode,offset) {};//Gecko,void -Selection.extend = function(parentNode,offset) {};//Gecko,void -Selection.collapseToStart = function() {};//Gecko,void -Selection.collapseToEnd = function() {};//Gecko,void -Selection.selectAllChildren = function(parentNode) {};//Gecko,void -Selection.addRange = function(range) {};//Gecko,void -Selection.removeRange = function(range) {};//Gecko,void -Selection.removeAllRanges = function() {};//Gecko,void -Selection.containsNode = function(node,partlyContained) {};//Gecko,Boolean -Selection.clear = function() {};//IE,Boolean -Selection.empty = function() {};//IE,Boolean -Selection.createRange = function() {};//IE,TextRange -Selection.prototype = new Object(); - -TextRange.htmlText = 0;//IE,String -TextRange.text = 0;//IE,String -TextRange.boundingWidth = 0;//IE,Number -TextRange.boundingHeight = 0;//IE,Number -TextRange.boundingLeft = 0;//IE,Number -TextRange.offsetLeft = 0;//IE,Number -TextRange.boundingTop = 0;//IE,Number -TextRange.offsetTop = 0;//IE,Number -TextRange = {}; -TextRange.collapse = function(start) {};//IE,void -TextRange.expand = function(unit) {};//IE,void -TextRange.duplicate = function() {};//IE,TextRange -TextRange.select = function() {};//IE,void -TextRange.parentElement = function() {};//IE,Node -TextRange.inRange = function(other) {};//IE,boolean -TextRange.isEqual = function(other) {};//IE,boolean -TextRange.scrollIntoView = function(start) {};//IE,void -TextRange.setEndPoint = function(type,range) {};//IE,void -TextRange.compareEndPoint = function(type,range) {};//IE,void -TextRange.move = function(unit,count) {};//IE,void -TextRange.moveStart = function(unit,count) {};//IE,void -TextRange.moveEnd = function(unit,count) {};//IE,void -TextRange.pasteHTML = function(htmlText) {};//IE,void -TextRange.moveToElementText = function(element) {};//IE,void -TextRange.compareEndPoints = function(sType,oRange) {};//IE,Number -TextRange.prototype = new Object(); - -document.selection = 0;//IE,Selection -document.namespaces = 0;//IE,Array -document.all = 0;//IE,All -document.styleSheets = 0;//Stylesheet[] -document = {}; -document.execCommand = function(sCommand,bUserInterface,vValue) {};//IE,Boolean -document.prototype = new Object(); - -CssRule.selectorText = 0;//String -CssRule = {}; -CssRule.prototype = new Object(); - -Stylesheet.cssRules = 0;//Gecko,CssRule[] -Stylesheet.rules = 0;//IE,CssRule[] -Stylesheet.owningElement = 0;//IE,HtmlElement -Stylesheet = {}; -Stylesheet.addRule = function(selector,style) {};//IE,void -Stylesheet.insertRule = function(ruleText,index) {};//Gecko,void -Stylesheet.removeRule = function(index) {};//IE,void -Stylesheet.deleteRule = function(index) {};//Gecko,void -Stylesheet.prototype = new Object(); - -MozillaSideBar.addPanel = function(title,url,param3) {};//Gecko,void -MozillaSideBar.prototype = new Object(); - -IEExternal.AddFavorite = function(title,url) {};//IE,void -IEExternal.prototype = new Object(); - -history.back = function() {};//void -history.forward = function() {};//void -history.go = function(count) {};//void -history.prototype = new Object(); - -window.document = 0;//HTMLDocument -window.event = 0;//Event -window.navigator = 0;//Navigator -window.screen = 0;//Screen -window.location = 0;//Location -window.frameElement = 0;//Object -window.opener = 0;//window -window.window = 0;//window -window.parent = 0;//window -window.top = 0;//window -window.self = 0;//Object -window.frames = 0;//Array -window.innerHeight = 0;//Number -window.innerWidth = 0;//Number -window.outerHeight = 0;//Number -window.outerWidth = 0;//Number -window.screenLeft = 0;//IE,Number -window.screenTop = 0;//IE,Number -window.scrollX = 0;//Number -window.scrollY = 0;//Number -window.pageXOffset = 0;//Number -window.pageYOffset = 0;//Number -window.scrollMaxX = 0;//Number -window.scrollMaxY = 0;//Number -window.status = 0;//String -window.defaultStatus = 0;//String -window.toolbar = 0;//Object -window.menubar = 0;//Object -window.scrollbars = 0;//Object -window.directories = 0;//Object -window.history = 0;//history -window.sidebar = 0;//Gecko,MozillaSideBar -window.external = 0;//IE,IEExternal -window.opera = 0;//Opera,Boolean -window = {}; -window.getSelection = function() {};//Gecko,Selection -window.print = function() {};//void -window.alert = function(sMesssage) {};//Object -window.confirm = function(sMesssage) {};//Object -window.prompt = function(sMessage,sDefaultValue) {};//Object -window.clearInterval = function(intervalId) {};//Object -window.clearTimeout = function(intervalId) {};//Object -window.setInterval = function(vCode,iMillis) {};//Number -window.setTimeout = function(vCode,iMillis) {};//Number -window.captureEvents = function(eventType) {};//Gecko,void,deprecated -window.releaseEvents = function(eventType) {};//Gecko,void,deprecated -window.routeEvent = function(event) {};//Gecko,void,deprecated -window.preventBubble = function(event) {};//Gecko,void,deprecated -window.GetObject = function(classOrPath,class) {};//IE,Object,deprecated -window.ScriptEngine = function() {};//IE,String -window.ScriptEngineBuildVersion = function() {};//IE,String -window.ScriptEngineMajorVersion = function() {};//IE,String -window.ScriptEngineMinorVersion = function() {};//IE,String -window.scrollTo = function(x,y) {};//Object -window.scrollBy = function(xDelta,yDelta) {};//Object -window.moveTo = function(x,y) {};//Object -window.moveBy = function(xDelta,yDelta) {};//Object -window.resizeTo = function(width,height) {};//Object -window.resizeBy = function(widthDelta,heightDelta) {};//Object -window.getComputedStyle = function(element,pseudoElt) {};//Gecko,style -window.showModalDialog = function(sUrl,vArguments,sFeatures) {};//IE,style -window.attachEvent = function(type,listener) {};//IE,Object -window.detachEvent = function(type,listener) {};//IE,Object -window.addEventListener = function(type,listener,useCapture) {};//Gecko,Object -window.removeEventListener = function(type,listener,useCapture) {};//Gecko,Object -window.execScript = function(sScript) {};//IE,Object -window.CollectGarbage = function() {};//IE,Object -window.prototype = new Object(); - -window = 0;//window -escape = function() {};//Object,deprecated -unescape = function() {};//Object,deprecated - -HTMLCollection.length = 0;//Number -HTMLCollection = {}; -HTMLCollection.item = function(index) {};//Node -HTMLCollection.namedItem = function(name) {};//Node -HTMLCollection.prototype = new Object(); - -HTMLOptionsCollection.length = 0;//Number -HTMLOptionsCollection = {}; -HTMLOptionsCollection.item = function(index) {};//Node -HTMLOptionsCollection.namedItem = function(name) {};//Node -HTMLOptionsCollection.prototype = new Object(); - -HTMLDocument.title = 0;//String -HTMLDocument.referrer = 0;//String -HTMLDocument.domain = 0;//String -HTMLDocument.URL = 0;//String -HTMLDocument.body = 0;//HTMLElement -HTMLDocument.images = 0;//HTMLCollection -HTMLDocument.applets = 0;//HTMLCollection -HTMLDocument.links = 0;//HTMLCollection -HTMLDocument.forms = 0;//HTMLCollection -HTMLDocument.anchors = 0;//HTMLCollection -HTMLDocument.cookie = 0;//HTMLCollection -HTMLDocument.defaultView = 0;//Gecko,DocumentView -HTMLDocument.activeElement = 0;//IE,DocumentView -HTMLDocument.compatMode = 0;//String -HTMLDocument.parentWindow = 0;//IE,window -HTMLDocument.commandDispatcher = 0;//Gecko,CommandDispatcher -HTMLDocument = {}; -HTMLDocument.open = function() {};//Object -HTMLDocument.close = function() {};//Object -HTMLDocument.write = function(text) {};//Object -HTMLDocument.writeln = function(text) {};//Object -HTMLDocument.getElementsByName = function(elementName) {};//NodeList -HTMLDocument.getElementsByClassName = function(className) {};//Gecko,NodeList -HTMLDocument.createStyleSheet = function() {};//IE,Stylesheet -HTMLDocument.getBoxObjectFor = function(element) {};//Gecko,Node -HTMLDocument.querySelectorAll = function(string) {};//Gecko,NodeList -HTMLDocument.querySelector = function(string) {};//Gecko,Node -HTMLDocument.getAnonymousNodes = function(node) {};//Gecko,Node[] -HTMLDocument.getAnonymousElementByAttribute = function(node,attrName,attrValue) {};//Gecko,NodeList -HTMLDocument.elementFromPoint = function(iX,iY) {};//IE,HTMLElement -HTMLDocument.createEventObject = function(oExistingEvent) {};//IE,Even +var history = { + back: function () {}, + forward: function () {}, + go: function (count) {}, +}; + +var window = { + addEventListener: function (type, listener, useCapture) { return {}; }, //Gecko + alert: function (sMesssage) { return {}; }, + attachEvent: function (type, listener) { return {}; }, //IE + captureEvents: function (eventType) {}, //Gecko,deprecated + clearInterval: function (intervalId) { return {}; }, + clearTimeout: function (intervalId) { return {}; }, + CollectGarbage: function () { return {}; }, //IE + confirm: function (sMesssage) { return {}; }, + defaultStatus: "", + detachEvent: function (type, listener) { return {}; }, //IE + directories: {}, + document: {}, //HTMLDocument + external: {}, //IE,IEExternal + event: {}, //Event + execScript: function (sScript) { return {}; }, //IE + frameElement: {}, + frames: [], + getComputedStyle: function (element, pseudoElt) { return {}; }, //Gecko,style + GetObject: function (classOrPath, clazz) { return {}; }, //IE,deprecated + getSelection: function () { return {}; }, //Gecko,Selection + history: {}, //history + innerHeight: 0, + innerWidth: 0, + location: {}, //Location + menubar: {}, + moveBy: function (xDelta, yDelta) { return {}; }, + moveTo: function (x, y) { return {}; }, + navigator: {}, //Navigator + opener: {}, //window + opera: false, //Opera + outerHeight: 0, + outerWidth: 0, + pageXOffset: 0, + pageYOffset: 0, + parent: {}, //window + preventBubble: function (event) {}, //Gecko,deprecated + print: function () {}, + prompt: function (sMessage, sDefaultValue) { return {}; }, + releaseEvents: function (eventType) {}, //Gecko,deprecated + removeEventListener: function (type, listener, useCapture) { return {}; }, //Gecko + resizeBy: function (widthDelta, heightDelta) { return {}; }, + resizeTo: function (width, height) { return {}; }, + routeEvent: function (event) {}, //Gecko,deprecated + screen: {}, //Screen + screenLeft: 0, //IE + screenTop: 0, //IE + ScriptEngine: function () { return ""; }, //IE + ScriptEngineBuildVersion: function () { return ""; }, //IE + ScriptEngineMajorVersion: function () { return ""; }, //IE + ScriptEngineMinorVersion: function () { return ""; }, //IE + scrollbars: {}, + scrollBy: function (xDelta, yDelta) { return {}; }, + scrollMaxX: 0, + scrollMaxY: 0, + scrollTo: function (x, y) { return {}; }, + scrollX: 0, + scrollY: 0, + self: {}, + setInterval: function (vCode, iMillis) { return 0; }, + setTimeout: function (vCode, iMillis) { return 0; }, + showModalDialog: function (sUrl, vArguments, sFeatures) { return {}; }, //IE,style + sidebar: {}, //Gecko,MozillaSideBar + status: "", + toolbar: {}, + top: {}, //window + window: {}, //window +}; + +var escape = function () { return {}; }; //deprecated +var unescape = function () { return {}; }; //deprecated + +var HTMLCollection = { + length: 0, + item: function (index) { return {}; }, //Node + namedItem: function (name) { return {}; }, //Node +}; + +var HTMLOptionsCollection = { + item: function (index) { return {}; }, //Node + length: 0, + namedItem: function (name) { return {}; }, //Node +}; + +var HTMLDocument = { + activeElement: {}, //IE,DocumentView + anchors: {}, //HTMLCollection + applets: {}, //HTMLCollection + body: {}, //HTMLElement + close: function () { return {}; }, + commandDispatcher: {}, //Gecko,CommandDispatcher + compatMode: "", + cookie: {}, //HTMLCollection + createEventObject: function (oExistingEvent) { return {}; }, //IE,Event + createStyleSheet: function () { return {}; }, //IE,Stylesheet + defaultView: {}, //Gecko,DocumentView + domain: "", + elementFromPoint: function (iX, iY) { return {}; }, //IE,HTMLElement + forms: {}, //HTMLCollection + getAnonymousElementByAttribute: function (node, attrName, attrValue) { return {}; }, //Gecko,NodeList + getAnonymousNodes: function (node) { return []; }, //Gecko,Node[] + getBoxObjectFor: function (element) { return {}; }, //Gecko,Node + getElementsByName: function (elementName) { return {}; }, //NodeList + getElementsByClassName: function (className) { return {}; }, //Gecko,NodeList + images: {}, //HTMLCollection + links: {}, //HTMLCollection + open: function () { return {}; }, + parentWindow: {}, //IE,window + querySelector: function (string) { return {}; }, //Gecko,Node + querySelectorAll: function (string) { return {}; }, //Gecko,NodeList + referrer: "", + title: "", + URL: "", + write: function (text) {}, + writeln: function (text) {}, +}; HTMLDocument.prototype = new Document(); -CommandDispatcher.focusedElement = 0;//Gecko,HTMLElement -CommandDispatcher = {}; -CommandDispatcher.prototype = new Object(); - -DocumentView.getComputedStyle = function(element,type) {};//Gecko,CssStyle -DocumentView.prototype = new Object(); - -CssStyle.getPropertyValue = function(propertyName) {};//Gecko,String -CssStyle.prototype = new Object(); - -HTMLElement.id = 0;//String -HTMLElement.title = 0;//String -HTMLElement.lang = 0;//String -HTMLElement.dir = 0;//String -HTMLElement.className = 0;//String -HTMLElement.children = 0;//IE,HTMLElement[] -HTMLElement.style = 0;//style -HTMLElement.clientWidth = 0;//Number -HTMLElement.clientHeight = 0;//Number -HTMLElement.clientTop = 0;//Number -HTMLElement.clientLeft = 0;//Number -HTMLElement.innerHTML = 0;//String -HTMLElement.innerText = 0;//IE,String -HTMLElement.offsetWidth = 0;//Number -HTMLElement.offsetHeight = 0;//Number -HTMLElement.offsetTop = 0;//Number -HTMLElement.offsetLeft = 0;//Number -HTMLElement.offsetParent = 0;//Number -HTMLElement.scrollWidth = 0;//Number -HTMLElement.scrollHeight = 0;//Number -HTMLElement.scrollTop = 0;//Number -HTMLElement.scrollLeft = 0;//Number -HTMLElement.stylesheet = 0;//Stylesheet -HTMLElement.currentStyle = 0;//IE,IEElementStyle -HTMLElement.runtimeStyle = 0;//IE,IEElementStyle -HTMLElement.filters = 0;//IE,Array -HTMLElement.boxObject = 0;//Gecko,HTMLElement -HTMLElement.propertyName = 0;//IE,String -HTMLElement.isDisabled = 0;//IE,Boolean -HTMLElement = {}; -HTMLElement.insertAdjacentHTML = function(position,htmlContent) {};//IE,Object -HTMLElement.insertAdjacentText = function(position,textContent) {};//IE,Object -HTMLElement.attachEvent = function(type,listener) {};//IE,Object -HTMLElement.detachEvent = function(type,listener) {};//IE,Object -HTMLElement.fireEvent = function(type,event) {};//IE,Object -HTMLElement.addBehavior = function(sUrl) {};//IE,Number -HTMLElement.removeBehavior = function(sID) {};//IE,Boolean -HTMLElement.getBoundingClientRect = function() {};//IE,TextRange -HTMLElement.showPopup = function() {};//Gecko,Object -HTMLElement.hidePopup = function() {};//Gecko,Object -HTMLElement.setCapture = function(bContainerCapture) {};//IE,Object -HTMLElement.releaseCapture = function() {};//IE,Object -HTMLElement.clearAttributes = function() {};//IE,Object -HTMLElement.mergeAttributes = function(oSource,bPreserve) {};//IE,Object -var HTMLElement = { - onblur: function () {}, - onclick: function () {}, - ondblclick: function () {}, - onfocus: function () {}, - onkeydown: function () {}, - onkeyup: function () {}, - onmouseup: function () {}, - onmousedown: function () {}, - onmouseout: function () {}, - onmouseover: function () {}, - onmousemove: function () {}, - onresize: function () {} +var CommandDispatcher = { + focusedElement: {}, //Gecko,HTMLElement }; -HTMLElement.prototype = new Element(); -IEElementStyle.hasLayout = 0;//IE,Boolean -IEElementStyle = {}; -IEElementStyle.prototype = new style(); +var DocumentView = { + getComputedStyle: function (element, type) { return {}; }, //Gecko,CssStyle +}; -HTMLHtmlElement.version = 0;//String -HTMLHtmlElement = {}; -HTMLHtmlElement.prototype = new HTMLElement(); +var CssStyle = { + getPropertyValue: function (propertyName) { return {}; }, //Gecko,String +}; -HTMLHeadElement.profile = 0;//String -HTMLHeadElement = {}; -HTMLHeadElement.prototype = new HTMLElement(); +var HTMLElement = { + addBehavior: function (sUrl) { return 0; }, //IE + attachEvent: function (type, listener) { return {}; }, //IE + boxObject: {}, //Gecko,HTMLElement + children: [], //IE,HTMLElement[] + className: "", + clearAttributes: function () { return {}; }, //IE + clientHeight: 0, + clientLeft: 0, + clientTop: 0, + clientWidth: 0, + currentStyle: {}, //IE,IEElementStyle + detachEvent: function (type, listener) { return {}; }, //IE + dir: "", + filters: [], //IE + fireEvent: function (type, event) { return {}; }, //IE + getBoundingClientRect: function () {}, //IE,TextRange + hidePopup: function () {}, //Gecko,Object + id: "", + innerHTML: "", + innerText: "", //IE + insertAdjacentHTML: function (position, htmlContent) { return {}; }, //IE + insertAdjacentText: function (position, textContent) { return {}; }, //IE + isDisabled: false, //IE + lang: "", + mergeAttributes: function (oSource, bPreserve) { return {}; }, //IE + offsetHeight: 0, + offsetLeft: 0, + offsetParent: 0, + offsetTop: 0, + offsetWidth: 0, + onblur: function () {}, + onclick: function () {}, + ondblclick: function () {}, + onfocus: function () {}, + onkeydown: function () {}, + onkeyup: function () {}, + onmouseup: function () {}, + onmousedown: function () {}, + onmouseout: function () {}, + onmouseover: function () {}, + onmousemove: function () {}, + onresize: function () {}, + propertyName: "", //IE + releaseCapture: function () { return {}; }, //IE + removeBehavior: function (sID) { return false; }, //IE + runtimeStyle: {}, //IE,IEElementStyle + setCapture: function (bContainerCapture) { return {}; }, //IE + scrollWidth: 0, + scrollHeight: 0, + scrollTop: 0, + scrollLeft: 0, + showPopup: function () { return {}; }, //Gecko + style: {}, //style + stylesheet: {}, //Stylesheet + title: "", +}; +HTMLElement.prototype = new Element(); -HTMLLinkElement.disabled = 0;//Boolean -HTMLLinkElement.charset = 0;//String -HTMLLinkElement.href = 0;//String -HTMLLinkElement.hreflang = 0;//String -HTMLLinkElement.media = 0;//String -HTMLLinkElement.rel = 0;//String -HTMLLinkElement.rev = 0;//String -HTMLLinkElement.target = 0;//String -HTMLLinkElement.type = 0;//String -HTMLLinkElement = {}; -HTMLLinkElement.prototype = new HTMLElement(); +var HTMLAnchorElement = { + accessKey: "", + charset: "", + coords: "", + blur: function () { return {}; }, + focus: function () { return {}; }, + href: "", + hreflang: "", + name: "", + rel: "", + rev: "", + shape: "", + tabIndex: 0, + target: "", + type: "", +}; +HTMLAnchorElement.prototype = new HTMLElement(); -HTMLTitleElement.text = 0;//String -HTMLTitleElement = {}; -HTMLTitleElement.prototype = new HTMLElement(); +var HTMLAppletElement = { + align: "", + alt: "", + archive: "", + code: "", + codeBase: "", + height: "", + hspace: 0, + name: "", + object: "", + vspace: 0, + width: "", +}; +HTMLAppletElement.prototype = new HTMLElement(); -HTMLMetaElement.content = 0;//String -HTMLMetaElement.httpEquiv = 0;//String -HTMLMetaElement.name = 0;//String -HTMLMetaElement.scheme = 0;//String -HTMLMetaElement = {}; -HTMLMetaElement.prototype = new HTMLElement(); +var HTMLAreaElement = { + accessKey: "", + alt: "", + coords: "", + href: "", + noHref: false, + shape: "", + tabIndex: 0, + target: "", +}; +HTMLAreaElement.prototype = new HTMLElement(); -HTMLBaseElement.href = 0;//String -HTMLBaseElement.target = 0;//String -HTMLBaseElement = {}; +var HTMLBaseElement = { + href: "", + target: "", +}; HTMLBaseElement.prototype = new HTMLElement(); -HTMLIsIndexElement.form = 0;//HTMLFormElement -HTMLIsIndexElement.prompt = 0;//String -HTMLIsIndexElement = {}; -HTMLIsIndexElement.prototype = new HTMLElement(); - -HTMLStyleElement.disabled = 0;//Boolean -HTMLStyleElement.media = 0;//String -HTMLStyleElement.type = 0;//String -HTMLStyleElement.styleSheet = 0;//IE,Stylesheet -HTMLStyleElement = {}; -HTMLStyleElement.prototype = new HTMLElement(); +var HTMLBaseFontElement = { + color: "", + face: "", + size: 0, +}; +HTMLBaseFontElement.prototype = new HTMLElement(); -HTMLBodyElement.aLink = 0;//String -HTMLBodyElement.background = 0;//String -HTMLBodyElement.bgColor = 0;//String -HTMLBodyElement.link = 0;//String -HTMLBodyElement.text = 0;//String -HTMLBodyElement.vLink = 0;//String -HTMLBodyElement = {}; var HTMLBodyElement = { - onload: function () {}, - onunload: function () {} + aLink: "", + background: "", + bgColor: "", + link: "", + onload: function () {}, + onunload: function () {}, + text: "", + vLink: "", }; HTMLBodyElement.prototype = new HTMLElement(); -HTMLFormElement.elements = 0;//HTMLCollection -HTMLFormElement.length = 0;//Number -HTMLFormElement.name = 0;//String -HTMLFormElement.acceptCharset = 0;//String -HTMLFormElement.action = 0;//String -HTMLFormElement.enctype = 0;//String -HTMLFormElement.method = 0;//String -HTMLFormElement.target = 0;//String -HTMLFormElement = {}; -HTMLFormElement.submit = function() {};//Object -HTMLFormElement.reset = function() {};//Object -HTMLFormElement.prototype = new Object(); - -HTMLSelectElement.type = 0;//String -HTMLSelectElement.selectedIndex = 0;//Number -HTMLSelectElement.value = 0;//String -HTMLSelectElement.length = 0;//Number -HTMLSelectElement.form = 0;//HTMLFormElement -HTMLSelectElement.options = 0;//HTMLOptionsCollection -HTMLSelectElement.disabled = 0;//Boolean -HTMLSelectElement.multiple = 0;//Boolean -HTMLSelectElement.name = 0;//String -HTMLSelectElement.size = 0;//Number -HTMLSelectElement.tabIndex = 0;//Number -HTMLSelectElement = {}; -HTMLSelectElement.add = function(element,before) {};//Object -HTMLSelectElement.remove = function(index) {};//Object -HTMLSelectElement.blur = function() {};//Object -HTMLSelectElement.focus = function() {};//Object -HTMLSelectElement.prototype = new HTMLElement(); +var HTMLBRElement = { + clear: "", +}; +HTMLBRElement.prototype = new HTMLElement(); -HTMLOptGroupElement.disabled = 0;//Boolean -HTMLOptGroupElement.label = 0;//String -HTMLOptGroupElement = {}; -HTMLOptGroupElement.prototype = new HTMLElement(); +var HTMLButtonElement = { + accessKey: "", + disabled: false, + form: {}, //HTMLFormElement + name: "", + tabIndex: 0, + type: "", + value: "", +}; +HTMLButtonElement.prototype = new HTMLElement(); -HTMLOptionElement.form = 0;//HTMLFormElement -HTMLOptionElement.defaultSelected = 0;//Boolean -HTMLOptionElement.text = 0;//String -HTMLOptionElement.index = 0;//Number -HTMLOptionElement.disabled = 0;//Boolean -HTMLOptionElement.label = 0;//String -HTMLOptionElement.selected = 0;//Boolean -HTMLOptionElement.value = 0;//String -HTMLOptionElement = {}; -HTMLOptionElement.prototype = new HTMLElement(); +var HTMLDirectoryElement = { + compact: false, +}; +HTMLDirectoryElement.prototype = new HTMLElement(); -HTMLInputElement.defaultValue = 0;//String -HTMLInputElement.defaultChecked = 0;//Boolean -HTMLInputElement.form = 0;//HTMLFormElement -HTMLInputElement.accept = 0;//String -HTMLInputElement.accessKey = 0;//String -HTMLInputElement.align = 0;//String -HTMLInputElement.alt = 0;//String -HTMLInputElement.checked = 0;//Boolean -HTMLInputElement.disabled = 0;//Boolean -HTMLInputElement.maxLength = 0;//Number -HTMLInputElement.name = 0;//String -HTMLInputElement.readOnly = 0;//Boolean -HTMLInputElement.size = 0;//Number -HTMLInputElement.src = 0;//String -HTMLInputElement.tabIndex = 0;//Number -HTMLInputElement.type = 0;//String -HTMLInputElement.useMap = 0;//String -HTMLInputElement.value = 0;//String -HTMLInputElement = {}; -HTMLInputElement.blur = function() {};//Object -HTMLInputElement.focus = function() {};//Object -HTMLInputElement.select = function() {};//Object -HTMLInputElement.click = function() {};//Object -HTMLInputElement.setSelectionRange = function(start,end) {};//Gecko,Object -HTMLInputElement.createTextRange = function() {};//IE,TextRange -HTMLInputElement.prototype = new HTMLElement(); +var HTMLDivElement = { + align: "", +}; +HTMLDivElement.prototype = new HTMLElement(); -HTMLTextAreaElement.defaultValue = 0;//String -HTMLTextAreaElement.form = 0;//HTMLFormElement -HTMLTextAreaElement.accessKey = 0;//String -HTMLTextAreaElement.cols = 0;//Number -HTMLTextAreaElement.disabled = 0;//Boolean -HTMLTextAreaElement.name = 0;//String -HTMLTextAreaElement.readOnly = 0;//Boolean -HTMLTextAreaElement.rows = 0;//Number -HTMLTextAreaElement.tabIndex = 0;//Number -HTMLTextAreaElement.type = 0;//String -HTMLTextAreaElement.value = 0;//String -HTMLTextAreaElement = {}; -HTMLTextAreaElement.blur = function() {};//Object -HTMLTextAreaElement.focus = function() {};//Object -HTMLTextAreaElement.select = function() {};//Object -HTMLTextAreaElement.prototype = new HTMLElement(); +var HTMLDListElement = { + compact: false, +}; +HTMLDListElement.prototype = new HTMLElement(); -HTMLButtonElement.form = 0;//HTMLFormElement -HTMLButtonElement.accessKey = 0;//String -HTMLButtonElement.disabled = 0;//Boolean -HTMLButtonElement.name = 0;//String -HTMLButtonElement.tabIndex = 0;//Number -HTMLButtonElement.type = 0;//String -HTMLButtonElement.value = 0;//String -HTMLButtonElement = {}; -HTMLButtonElement.prototype = new HTMLElement(); +var HTMLFieldSetElement = { + form: {}, //HTMLFormElement +}; +HTMLFieldSetElement.prototype = new HTMLElement(); -HTMLLabelElement.form = 0;//HTMLFormElement -HTMLLabelElement.accessKey = 0;//String -HTMLLabelElement.htmlFor = 0;// -HTMLLabelElement = {}; -HTMLLabelElement.prototype = new HTMLElement(); +var HTMLFontElement = { + color: "", + face: "", + size: "", +}; +HTMLFontElement.prototype = new HTMLElement(); -HTMLFieldSetElement.form = 0;//HTMLFormElement -HTMLFieldSetElement = {}; -HTMLFieldSetElement.prototype = new HTMLElement(); +var HTMLFormElement = { + acceptCharset: "", + action: "", + elements: {}, //HTMLCollection + enctype: "", + length: 0, + method: "", + name: "", + reset: function () { return {}; }, + submit: function () { return {}; }, + target: "", +}; -HTMLLegendElement.form = 0;//HTMLFormElement -HTMLLegendElement.accessKey = 0;//String -HTMLLegendElement.align = 0;//String -HTMLLegendElement = {}; -HTMLLegendElement.prototype = new HTMLElement(); +var HTMLFrameElement = { + contentDocument: {}, //Gecko,Document + frameBorder: "", + longDesc: "", + marginHeight: "", + marginWidth: "", + name: "", + noResize: false, + scrolling: "", + src: "", +}; +HTMLFrameElement.prototype = new HTMLElement(); -HTMLUListElement.compact = 0;//Boolean -HTMLUListElement.type = 0;//String -HTMLUListElement = {}; -HTMLUListElement.prototype = new HTMLElement(); +var HTMLFrameSetElement = { + cols: "", + rows: "", +}; +HTMLFrameSetElement.prototype = new HTMLElement(); -HTMLOListElement.compact = 0;//Boolean -HTMLOListElement.start = 0;//Number -HTMLOListElement.type = 0;//String -HTMLOListElement = {}; -HTMLOListElement.prototype = new HTMLElement(); +var HTMLHeadElement = { + profile: "", +}; +HTMLHeadElement.prototype = new HTMLElement(); -HTMLDListElement.compact = 0;//Boolean -HTMLDListElement = {}; -HTMLDListElement.prototype = new HTMLElement(); +var HTMLHeadingElement = { + align: "", +}; +HTMLHeadingElement.prototype = new HTMLElement(); -HTMLDirectoryElement.compact = 0;//Boolean -HTMLDirectoryElement = {}; -HTMLDirectoryElement.prototype = new HTMLElement(); +var HTMLHtmlElement = { + version: "", +}; +HTMLHtmlElement.prototype = new HTMLElement(); -HTMLMenuElement.compact = 0;//Boolean -HTMLMenuElement = {}; -HTMLMenuElement.prototype = new HTMLElement(); +var HTMLInputElement = { + accept: "", + accessKey: "", + align: "", + alt: "", + blur: function () { return {}; }, + checked: false, + click: function () { return {}; }, + createTextRange: function () { return {}; }, //IE,TextRange + defaultChecked: false, + defaultValue: "", + disabled: false, + focus: function () { return {}; }, + form: {}, //HTMLFormElement + maxLength: 0, + name: "", + readOnly: false, + select: function () { return {}; }, + setSelectionRange: function (start, end) { return {}; }, //Gecko + size: 0, + src: "", + tabIndex: 0, + type: "", + useMap: "", + value: "", +}; +HTMLInputElement.prototype = new HTMLElement(); -HTMLLIElement.type = 0;//String -HTMLLIElement.value = 0;//Number -HTMLLIElement = {}; -HTMLLIElement.prototype = new HTMLElement(); +var HTMLIsIndexElement = { + form: {}, //HTMLFormElement + prompt: "", +}; +HTMLIsIndexElement.prototype = new HTMLElement(); -HTMLDivElement.align = 0;//String -HTMLDivElement = {}; -HTMLDivElement.prototype = new HTMLElement(); +var HTMLHRElement = { + align: "", + noShade: false, + size: "", + width: "", +}; +HTMLHRElement.prototype = new HTMLElement(); -HTMLParagraphElement.align = 0;//String -HTMLParagraphElement = {}; -HTMLParagraphElement.prototype = new HTMLElement(); +var HTMLIFrameElement = { + align: "", + contentDocument: {}, //Document + contentWindow: {}, //window + frameBorder: "", + height: "", + longDesc: "", + marginHeight: "", + marginWidth: "", + name: "", + scrolling: "", + src: "", + width: "", +}; +HTMLIFrameElement.prototype = new HTMLElement(); -HTMLHeadingElement.align = 0;//String -HTMLHeadingElement = {}; -HTMLHeadingElement.prototype = new HTMLElement(); +var HTMLImageElement = { + align: "", + alt: "", + border: "", + height: 0, + hspace: 0, + isMap: false, + longDesc: "", + name: "", + src: "", + useMap: "", + vspace: 0, + width: 0, +}; +HTMLImageElement.prototype = new HTMLElement(); -HTMLQuoteElement.cite = 0;//String -HTMLQuoteElement = {}; -HTMLQuoteElement.prototype = new HTMLElement(); +var HTMLLabelElement = { + accessKey: "", + form: {}, //HTMLFormElement + htmlFor: 0, +}; +HTMLLabelElement.prototype = new HTMLElement(); -HTMLPreElement.width = 0;//Number -HTMLPreElement = {}; -HTMLPreElement.prototype = new HTMLElement(); +var HTMLLegendElement = { + accessKey: "", + align: "", + form: {}, //HTMLFormElement +}; +HTMLLegendElement.prototype = new HTMLElement(); -HTMLBRElement.clear = 0;//String -HTMLBRElement = {}; -HTMLBRElement.prototype = new HTMLElement(); +var HTMLLIElement = { + type: "", + value: 0, +}; +HTMLLIElement.prototype = new HTMLElement(); -HTMLBaseFontElement.color = 0;//String -HTMLBaseFontElement.face = 0;//String -HTMLBaseFontElement.size = 0;//Number -HTMLBaseFontElement = {}; -HTMLBaseFontElement.prototype = new HTMLElement(); +var HTMLLinkElement = { + charset: "", + disabled: false, + href: "", + hreflang: "", + media: "", + rel: "", + rev: "", + target: "", + type: "", +}; +HTMLLinkElement.prototype = new HTMLElement(); -HTMLFontElement.color = 0;//String -HTMLFontElement.face = 0;//String -HTMLFontElement.size = 0;//String -HTMLFontElement = {}; -HTMLFontElement.prototype = new HTMLElement(); +var HTMLMapElement = { + areas: {}, //HTMLCollection + name: "", +}; +HTMLMapElement.prototype = new HTMLElement(); -HTMLHRElement.align = 0;//String -HTMLHRElement.noShade = 0;//Boolean -HTMLHRElement.size = 0;//String -HTMLHRElement.width = 0;//String -HTMLHRElement = {}; -HTMLHRElement.prototype = new HTMLElement(); +var HTMLMenuElement = { + compact: false, +}; +HTMLMenuElement.prototype = new HTMLElement(); -HTMLModElement.cite = 0;//String -HTMLModElement.dateTime = 0;//String -HTMLModElement = {}; +var HTMLMetaElement = { + content: "", + httpEquiv: "", + name: "", + scheme: "", +}; +HTMLMetaElement.prototype = new HTMLElement(); + +var HTMLModElement = { + cite: "", + dateTime: "", +}; HTMLModElement.prototype = new HTMLElement(); -HTMLAnchorElement.accessKey = 0;//String -HTMLAnchorElement.charset = 0;//String -HTMLAnchorElement.coords = 0;//String -HTMLAnchorElement.href = 0;//String -HTMLAnchorElement.hreflang = 0;//String -HTMLAnchorElement.name = 0;//String -HTMLAnchorElement.rel = 0;//String -HTMLAnchorElement.rev = 0;//String -HTMLAnchorElement.shape = 0;//String -HTMLAnchorElement.tabIndex = 0;//Number -HTMLAnchorElement.target = 0;//String -HTMLAnchorElement.type = 0;//String -HTMLAnchorElement = {}; -HTMLAnchorElement.blur = function() {};//Object -HTMLAnchorElement.focus = function() {};//Object -HTMLAnchorElement.prototype = new HTMLElement(); +var HTMLObjectElement = { + align: "", + archive: "", + border: "", + code: "", + codeBase: "", + codeType: "", + contentDocument: {}, //Document + data: "", + declare: false, + form: {}, //HTMLFormElement + height: "", + hspace: 0, + name: "", + standby: "", + tabIndex: 0, + type: "", + useMap: "", + vspace: 0, + width: "", +}; +HTMLObjectElement.prototype = new HTMLElement(); -HTMLImageElement.name = 0;//String -HTMLImageElement.align = 0;//String -HTMLImageElement.alt = 0;//String -HTMLImageElement.border = 0;//String -HTMLImageElement.height = 0;//Number -HTMLImageElement.hspace = 0;//Number -HTMLImageElement.isMap = 0;//Boolean -HTMLImageElement.longDesc = 0;//String -HTMLImageElement.src = 0;//String -HTMLImageElement.useMap = 0;//String -HTMLImageElement.vspace = 0;//Number -HTMLImageElement.width = 0;//Number -HTMLImageElement = {}; -HTMLImageElement.prototype = new HTMLElement(); +var HTMLOListElement = { + compact: false, + start: 0, + type: "", +}; +HTMLOListElement.prototype = new HTMLElement(); -HTMLObjectElement.form = 0;//HTMLFormElement -HTMLObjectElement.code = 0;//String -HTMLObjectElement.align = 0;//String -HTMLObjectElement.archive = 0;//String -HTMLObjectElement.border = 0;//String -HTMLObjectElement.codeBase = 0;//String -HTMLObjectElement.codeType = 0;//String -HTMLObjectElement.data = 0;//String -HTMLObjectElement.declare = 0;//Boolean -HTMLObjectElement.height = 0;//String -HTMLObjectElement.hspace = 0;//Number -HTMLObjectElement.name = 0;//String -HTMLObjectElement.standby = 0;//String -HTMLObjectElement.tabIndex = 0;//Number -HTMLObjectElement.type = 0;//String -HTMLObjectElement.useMap = 0;//String -HTMLObjectElement.vspace = 0;//Number -HTMLObjectElement.width = 0;//String -HTMLObjectElement.contentDocument = 0;//Document -HTMLObjectElement = {}; -HTMLObjectElement.prototype = new HTMLElement(); +var HTMLOptGroupElement = { + disabled: false, + label: "", +}; +HTMLOptGroupElement.prototype = new HTMLElement(); -HTMLParamElement.name = 0;//String -HTMLParamElement.type = 0;//String -HTMLParamElement.value = 0;//String -HTMLParamElement.valueType = 0;//String -HTMLParamElement = {}; -HTMLParamElement.prototype = new HTMLElement(); +var HTMLOptionElement = { + defaultSelected: false, + disabled: false, + text: "", + form: {}, //HTMLFormElement + index: 0, + label: "", + selected: false, + value: "", +}; +HTMLOptionElement.prototype = new HTMLElement(); -HTMLAppletElement.align = 0;//String -HTMLAppletElement.alt = 0;//String -HTMLAppletElement.archive = 0;//String -HTMLAppletElement.code = 0;//String -HTMLAppletElement.codeBase = 0;//String -HTMLAppletElement.height = 0;//String -HTMLAppletElement.hspace = 0;//Number -HTMLAppletElement.name = 0;//String -HTMLAppletElement.object = 0;//String -HTMLAppletElement.vspace = 0;//Number -HTMLAppletElement.width = 0;//String -HTMLAppletElement = {}; -HTMLAppletElement.prototype = new HTMLElement(); +var HTMLParagraphElement = { + align: "", +}; +HTMLParagraphElement.prototype = new HTMLElement(); -HTMLMapElement.areas = 0;//HTMLCollection -HTMLMapElement.name = 0;//String -HTMLMapElement = {}; -HTMLMapElement.prototype = new HTMLElement(); +var HTMLParamElement = { + name: "", + type: "", + value: "", + valueType: "", +}; +HTMLParamElement.prototype = new HTMLElement(); -HTMLAreaElement.accessKey = 0;//String -HTMLAreaElement.alt = 0;//String -HTMLAreaElement.coords = 0;//String -HTMLAreaElement.href = 0;//String -HTMLAreaElement.noHref = 0;//Boolean -HTMLAreaElement.shape = 0;//String -HTMLAreaElement.tabIndex = 0;//Number -HTMLAreaElement.target = 0;//String -HTMLAreaElement = {}; -HTMLAreaElement.prototype = new HTMLElement(); +var HTMLPreElement = { + width: 0, +}; +HTMLPreElement.prototype = new HTMLElement(); -HTMLScriptElement.text = 0;//String -HTMLScriptElement.htmlFor = 0;//String -HTMLScriptElement.event = 0;//String -HTMLScriptElement.charset = 0;//String -HTMLScriptElement.defer = 0;//Boolean -HTMLScriptElement.src = 0;//String -HTMLScriptElement.type = 0;//String -HTMLScriptElement = {}; +var HTMLQuoteElement = { + cite: "", +}; +HTMLQuoteElement.prototype = new HTMLElement(); + +var HTMLScriptElement = { + charset: "", + defer: false, + event: "", + htmlFor: "", + src: "", + text: "", + type: "", +}; HTMLScriptElement.prototype = new HTMLElement(); -HTMLTableElement.caption = 0;//HTMLTableCaptionElement -HTMLTableElement.tHead = 0;//HTMLTableSectionElement -HTMLTableElement.tFoot = 0;//HTMLTableSectionElement -HTMLTableElement.rows = 0;//HTMLCollection -HTMLTableElement.tBodies = 0;//HTMLCollection -HTMLTableElement.align = 0;//String -HTMLTableElement.bgColor = 0;//String -HTMLTableElement.border = 0;//String -HTMLTableElement.cellPadding = 0;//String -HTMLTableElement.cellSpacing = 0;//String -HTMLTableElement.frame = 0;//String -HTMLTableElement.rules = 0;//String -HTMLTableElement.summary = 0;//String -HTMLTableElement.width = 0;//String -HTMLTableElement = {}; -HTMLTableElement.createTHead = function() {};//HTMLElement -HTMLTableElement.deleteTHead = function() {};//Object -HTMLTableElement.createTFoot = function() {};//HTMLElement -HTMLTableElement.deleteTFoot = function() {};//Object -HTMLTableElement.createCaption = function() {};//HTMLElement -HTMLTableElement.deleteCaption = function() {};//Object -HTMLTableElement.insertRow = function(index) {};//HTMLElement -HTMLTableElement.deleteRow = function(index) {};//Object -HTMLTableElement.prototype = new HTMLElement(); +var HTMLSelectElement = { + add: function (element, before) { return {}; }, + blur: function () { return {}; }, + disabled: false, + focus: function () { return {}; }, + form: {}, //HTMLFormElement + length: 0, + multiple: false, + name: "", + options: {}, //HTMLOptionsCollection + remove: function (index) { return {}; }, + selectedIndex: 0, + size: 0, + tabIndex: 0, + type: "", + value: "", +}; +HTMLSelectElement.prototype = new HTMLElement(); -HTMLTableCaptionElement.align = 0;//String -HTMLTableCaptionElement = {}; +var HTMLStyleElement = { + disabled: false, + media: "", + type: "", + styleSheet: {}, //IE,Stylesheet +}; +HTMLStyleElement.prototype = new HTMLElement(); + +var HTMLTableCaptionElement = { + align: "", +}; HTMLTableCaptionElement.prototype = new HTMLElement(); -HTMLTableColElement.align = 0;//String -HTMLTableColElement.ch = 0;//String -HTMLTableColElement.chOff = 0;//String -HTMLTableColElement.span = 0;//Number -HTMLTableColElement.vAlign = 0;//String -HTMLTableColElement.width = 0;//String -HTMLTableColElement = {}; +var HTMLTableColElement = { + align: "", + ch: "", + chOff: "", + span: 0, + vAlign: "", + width: "", +}; HTMLTableColElement.prototype = new HTMLElement(); -HTMLTableSectionElement.align = 0;//String -HTMLTableSectionElement.ch = 0;//String -HTMLTableSectionElement.chOff = 0;//String -HTMLTableSectionElement.vAlign = 0;//String -HTMLTableSectionElement.rows = 0;//HTMLCollection -HTMLTableSectionElement = {}; -HTMLTableSectionElement.insertRow = function(index) {};//HTMLElement -HTMLTableSectionElement.deleteRow = function(index) {};//Object -HTMLTableSectionElement.prototype = new HTMLElement(); +var HTMLTableCellElement = { + abbr: "", + align: "", + axis: "", + bgColor: "", + cellIndex: 0, + ch: "", + chOff: "", + colSpan: 0, + headers: "", + height: "", + noWrap: false, + rowSpan: 0, + scope: "", + vAlign: "", + width: "", +}; +HTMLTableCellElement.prototype = new HTMLElement(); + +var HTMLTableElement = { + align: "", + bgColor: "", + border: "", + caption: {}, //HTMLTableCaptionElement + cellPadding: "", + cellSpacing: "", + createCaption: function () { return {}; }, //HTMLElement + createTFoot: function () { return {}; }, //HTMLElement + createTHead: function () { return {}; }, //HTMLElement + deleteCaption: function () { return {}; }, + deleteRow: function (index) { return {}; }, + deleteTHead: function () { return {}; }, + deleteTFoot: function () { return {}; }, + frame: "", + insertRow: function (index) { return {}; }, //HTMLElement + rows: {}, //HTMLCollection + rules: "", + summary: "", + tBodies: {}, //HTMLCollection + tHead: {}, //HTMLTableSectionElement + tFoot: {}, //HTMLTableSectionElement + width: "", +}; +HTMLTableElement.prototype = new HTMLElement(); -HTMLTableRowElement.rowIndex = 0;//Number -HTMLTableRowElement.sectionRowIndex = 0;//Number -HTMLTableRowElement.cells = 0;//HTMLCollection -HTMLTableRowElement.align = 0;//String -HTMLTableRowElement.bgColor = 0;//String -HTMLTableRowElement.ch = 0;//String -HTMLTableRowElement.chOff = 0;//String -HTMLTableRowElement.vAlign = 0;//String -HTMLTableRowElement = {}; -HTMLTableRowElement.insertCell = function(index) {};//HTMLElement -HTMLTableRowElement.deleteCell = function(index) {};//Object +var HTMLTableRowElement = { + align: "", + bgColor: "", + cells: {}, //HTMLCollection + ch: "", + chOff: "", + deleteCell: function (index) { return {}; }, + insertCell: function (index) { return {}; }, //HTMLElement + rowIndex: 0, + sectionRowIndex: 0, + vAlign: "", +}; HTMLTableRowElement.prototype = new HTMLElement(); -HTMLTableCellElement.cellIndex = 0;//Number -HTMLTableCellElement.abbr = 0;//String -HTMLTableCellElement.align = 0;//String -HTMLTableCellElement.axis = 0;//String -HTMLTableCellElement.bgColor = 0;//String -HTMLTableCellElement.ch = 0;//String -HTMLTableCellElement.chOff = 0;//String -HTMLTableCellElement.colSpan = 0;//Number -HTMLTableCellElement.headers = 0;//String -HTMLTableCellElement.height = 0;//String -HTMLTableCellElement.noWrap = 0;//Boolean -HTMLTableCellElement.rowSpan = 0;//Number -HTMLTableCellElement.scope = 0;//String -HTMLTableCellElement.vAlign = 0;//String -HTMLTableCellElement.width = 0;//String -HTMLTableCellElement = {}; -HTMLTableCellElement.prototype = new HTMLElement(); +var HTMLTableSectionElement = { + align: "", + ch: "", + chOff: "", + deleteRow: function (index) { return {}; }, + insertRow: function (index) { return {}; }, //HTMLElement + rows: {}, //HTMLCollection + vAlign: "", +}; +HTMLTableSectionElement.prototype = new HTMLElement(); -HTMLFrameSetElement.cols = 0;//String -HTMLFrameSetElement.rows = 0;//String -HTMLFrameSetElement = {}; -HTMLFrameSetElement.prototype = new HTMLElement(); +var HTMLTextAreaElement = { + accessKey: "", + blur: function () { return {}; }, + cols: 0, + defaultValue: "", + disabled: false, + focus: function () { return {}; }, + form: {}, //HTMLFormElement + name: "", + readOnly: false, + rows: 0, + select: function () { return {}; }, + tabIndex: 0, + type: "", + value: "", +}; +HTMLTextAreaElement.prototype = new HTMLElement(); -HTMLFrameElement.frameBorder = 0;//String -HTMLFrameElement.longDesc = 0;//String -HTMLFrameElement.marginHeight = 0;//String -HTMLFrameElement.marginWidth = 0;//String -HTMLFrameElement.name = 0;//String -HTMLFrameElement.noResize = 0;//Boolean -HTMLFrameElement.scrolling = 0;//String -HTMLFrameElement.src = 0;//String -HTMLFrameElement.contentDocument = 0;//Gecko,Document -HTMLFrameElement = {}; -HTMLFrameElement.prototype = new HTMLElement(); +var HTMLTitleElement = { + text: "", +}; +HTMLTitleElement.prototype = new HTMLElement(); -HTMLIFrameElement.align = 0;//String -HTMLIFrameElement.frameBorder = 0;//String -HTMLIFrameElement.height = 0;//String -HTMLIFrameElement.longDesc = 0;//String -HTMLIFrameElement.marginHeight = 0;//String -HTMLIFrameElement.marginWidth = 0;//String -HTMLIFrameElement.name = 0;//String -HTMLIFrameElement.scrolling = 0;//String -HTMLIFrameElement.src = 0;//String -HTMLIFrameElement.width = 0;//String -HTMLIFrameElement.contentDocument = 0;//Document -HTMLIFrameElement.contentWindow = 0;//window -HTMLIFrameElement = {}; -HTMLIFrameElement.prototype = new HTMLElement(); +var HTMLUListElement = { + compact: false, + type: "", +}; +HTMLUListElement.prototype = new HTMLElement(); + +var IEElementStyle = { + hasLayout: false, //IE +}; +IEElementStyle.prototype = new style(); diff --git a/plugin/src/main/dist/sdk/clientAny/DOMCore.js b/plugin/src/main/dist/sdk/clientAny/DOMCore.js index 8b9c4a8c..84bae637 100644 --- a/plugin/src/main/dist/sdk/clientAny/DOMCore.js +++ b/plugin/src/main/dist/sdk/clientAny/DOMCore.js @@ -1,253 +1,271 @@ -DOMImplementationRegistry.getDOMImplementation = function(features) {};//Object -DOMImplementationRegistry.getDOMImplementationList = function(features) {};//Object -DOMImplementationRegistry.prototype = new Object(); - -DOMException.code = 0;//Number -DOMException = {}; -DOMException.prototype = new Object(); - -DOMStringList.length = 0;//Number -DOMStringList = {}; -DOMStringList.item = function(index) {};//String -DOMStringList.contains = function(str) {};//Boolean -DOMStringList.prototype = new Object(); - -NameList.length = 0;//Number -NameList = {}; -NameList.getName = function(index) {};//String -NameList.getNamespaceURI = function(index) {};//String -NameList.contains = function(str) {};//Boolean -NameList.containsNS = function(namespaceURI,name) {};//Boolean -NameList.prototype = new Object(); - -DOMImplementationList.length = 0;//Number -DOMImplementationList = {}; -DOMImplementationList.item = function(index) {};//DOMImplementation -DOMImplementationList.prototype = new Object(); - -DOMImplementationSource.getDOMImplementation = function(features) {};//DOMImplementation -DOMImplementationSource.getDOMImplementationList = function(features) {};//DOMImplementationList -DOMImplementationSource.prototype = new Object(); - -DOMImplementation.hasFeature = function(feature,version) {};//Boolean -DOMImplementation.createDocumentType = function(qualifiedName,publicId,systemId) {};//DocumentType -DOMImplementation.createDocument = function(namespaceURI,qualifiedName,doctype) {};//Document -DOMImplementation.getFeature = function(feature,version) {};//Object -DOMImplementation.prototype = new Object(); +var DOMImplementationRegistry = { + getDOMImplementation: function (features) { return {}; }, + getDOMImplementationList: function (features) { return {}; }, +}; +var DOMException = { + code: 0, +}; + +var DOMStringList = { + contains: function (str) { return false; }, + item: function (index) { return ""; }, + length: 0, +}; + +var NameList = { + contains: function (str) { return false; }, + containsNS: function (namespaceURI, name) { return false; }, + getName: function (index) { return ""; }, + getNamespaceURI: function (index) { return ""; }, + length: 0, +}; + +var DOMImplementationList = { + item: function (index) {}, //DOMImplementation + length: 0, +}; + +var DOMImplementationSource = { + getDOMImplementation: function (features) { return {}; }, //DOMImplementation + getDOMImplementationList: function (features) { return {}; }, //DOMImplementationList +}; + +var DOMImplementation = { + createDocument: function (namespaceURI, qualifiedName, doctype) { return {}; }, //Document + createDocumentType: function (qualifiedName, publicId, systemId) { return {}; }, //DocumentType + getFeature: function (feature, version) { return {}; }, + hasFeature: function (feature, version) { return false; }, +}; + +var DocumentFragment = {}; DocumentFragment.prototype = new Node(); -Document.doctype = 0;//DocumentType -Document.implementation = 0;//DOMImplementation -Document.documentElement = 0;//Element -Document.inputEncoding = 0;//String -Document.xmlEncoding = 0;//String -Document.xmlStandalone = 0;//Boolean -Document.xmlVersion = 0;//String -Document.strictErrorChecking = 0;//Boolean -Document.documentURI = 0;//String -Document.domConfig = 0;//DOMConfiguration -Document.parseError = 0;//IE,IXMLDOMParseError -Document = {}; -Document.createElement = function(tagName) {};//Element -Document.createDocumentFragment = function() {};//DocumentFragment -Document.createTextNode = function(data) {};//Text -Document.createComment = function(data) {};//Comment -Document.createCDATASection = function(data) {};//CDATASection -Document.createProcessingInstruction = function(target,data) {};//ProcessingInstruction -Document.createAttribute = function(name) {};//Attr -Document.createEntityReference = function(name) {};//EntityReference -Document.getElementsByTagName = function(tagname) {};//NodeList -Document.importNode = function(importedNode,deep) {};//Node -Document.createElementNS = function(namespaceURI,qualifiedName) {};//Element -Document.createAttributeNS = function(namespaceURI,qualifiedName) {};//Attr -Document.getElementsByTagNameNS = function(namespaceURI,localName) {};//NodeList -Document.getElementById = function(elementId) {};//Element -Document.adoptNode = function(source) {};//Node -Document.normalizeDocument = function() {};//Object -Document.renameNode = function(n,namespaceURI,qualifiedName) {};//Node -Document.load = function(filename) {};//IE,Object -Document.loadXML = function(xmlString) {};//IE,Object -Document.save = function(filename) {};//IE,Object -Document.setProperty = function(name,value) {};//IE,Object -Document.selectSingleNode = function(xpathExpression) {};//IE,Object -Document.selectNodes = function(xpathExpression) {};//IE,Object +var Document = { + adoptNode: function (source) { return {}; }, //Node + createAttribute: function (name) { return {}; }, //Attr + createAttributeNS: function (namespaceURI, qualifiedName) { return {}; }, //Attr + createCDATASection: function (data) { return {}; }, //CDATASection + createComment: function (data) { return {}; }, //Comment + createDocumentFragment: function () { return {}; }, //DocumentFragment + createElement: function (tagName) { return {}; }, //Element + createElementNS: function (namespaceURI, qualifiedName) { return {}; }, //Element + createProcessingInstruction: function (target, data) { return {}; }, //ProcessingInstruction + createTextNode: function (data) { return {}; }, //Text + createEntityReference: function (name) { return {}; }, //EntityReference + doctype: {}, //DocumentType + documentElement: {}, //Element + documentURI: "", + domConfig: {}, //DOMConfiguration + getElementById: function (elementId) { return {}; }, //Element + getElementsByTagName: function (tagname) { return {}; }, //NodeList + getElementsByTagNameNS: function (namespaceURI, localName) { return {}; }, //NodeList + implementation: {}, //DOMImplementation + importNode: function (importedNode, deep) { return {}; }, //Node + inputEncoding: "", + parseError: {}, //IE,IXMLDOMParseError + load: function (filename) { return {}; }, //IE + loadXML: function (xmlString) { return {}; }, //IE + normalizeDocument: function () { return {}; }, + renameNode: function (n, namespaceURI, qualifiedName) { return {}; }, //Node + save: function (filename) { return {}; }, //IE + setProperty: function (name, value) { return {}; }, //IE + selectSingleNode: function (xpathExpression) { return {}; }, //IE + selectNodes: function (xpathExpression) { return {}; }, //IE + strictErrorChecking: false, + xmlEncoding: "", + xmlStandalone: false, + xmlVersion: "", +}; Document.prototype = new Node(); -IXMLDOMParseError.reason = 0;//IE,String -IXMLDOMParseError.errorCode = 0;//IE,Number -IXMLDOMParseError = {}; -IXMLDOMParseError.prototype = new Object(); - -Node.nodeName = 0;//String -Node.nodeValue = 0;//String -Node.nodeType = 0;//Number -Node.parentNode = 0;//Node -Node.childNodes = 0;//NodeList -Node.firstChild = 0;//Node -Node.lastChild = 0;//Node -Node.previousSibling = 0;//Node -Node.nextSibling = 0;//Node -Node.attributes = 0;//NamedNodeMap -Node.ownerDocument = 0;//Document -Node.namespaceURI = 0;//String -Node.prefix = 0;//String -Node.localName = 0;//String -Node.baseURI = 0;//String -Node.textContent = 0;//String -Node = {}; -Node.insertBefore = function(newChild,refChild) {};//Node -Node.replaceChild = function(newChild,refChild) {};//Node -Node.removeChild = function(oldChild) {};//Node -Node.appendChild = function(newChild) {};//Node -Node.hasChildNodes = function() {};//Boolean -Node.cloneNode = function(deep) {};//Node -Node.normalize = function() {};//Object -Node.isSupported = function(feature,version) {};//Boolean -Node.hasAttributes = function() {};//Boolean -Node.compareDocumentPosition = function(other) {};//Node -Node.isSameNode = function(other) {};//Boolean -Node.lookupPrefix = function(namespaceURI) {};//String -Node.isDefaultNamespace = function(namespaceURI) {};//String -Node.lookupNamespaceURI = function(prefix) {};//String -Node.isEqualNode = function(arg) {};//Boolean -Node.getFeature = function(feature,version) {};//Object -Node.setUserData = function(key,data,handler) {};//Object -Node.getUserData = function(key) {};//Object -Node.prototype = new Object(); - -NodeList.length = 0;//Number -NodeList = {}; -NodeList.item = function(index) {};//Node -NodeList.prototype = new Object(); - -NamedNodeMap.length = 0;//Number -NamedNodeMap = {}; -NamedNodeMap.getNamedItem = function(name) {};//Node -NamedNodeMap.setNamedItem = function(arg) {};//Node -NamedNodeMap.removeNamedItem = function(name) {};//Node -NamedNodeMap.item = function(index) {};//Node -NamedNodeMap.getNamedItemNS = function(namespaceURI,localName) {};//Node -NamedNodeMap.setNamedItemNS = function(arg) {};//Node -NamedNodeMap.removeNamedItemNS = function(namespaceURI,localName) {};//Node -NamedNodeMap.prototype = new Object(); - -CharacterData.data = 0;//String -CharacterData.length = 0;//Number -CharacterData = {}; -CharacterData.substringData = function(offset,count) {};//String -CharacterData.appendData = function(arg) {};//Object -CharacterData.insertData = function(offset,arg) {};//Object -CharacterData.deleteData = function(offset,count) {};//Object -CharacterData.replaceData = function(offset,count,arg) {};//Object +var IXMLDOMParseError = { + errorCode: 0, //IE + reason: "", //IE +}; + +var Node = { + appendChild: function (newChild) {}, //Node + attributes: {}, //NamedNodeMap + baseURI: "", + childNodes: {}, //NodeList + cloneNode: function (deep) {}, //Node + compareDocumentPosition: function (other) {}, //Node + firstChild: {}, //Node + getFeature: function (feature, version) { return {}; }, + getUserData: function (key) { return {}; }, + hasAttributes: function () { return false; }, + hasChildNodes: function () { return false; }, + isDefaultNamespace: function (namespaceURI) { return ""; }, + isEqualNode: function (arg) { return false; }, + isSameNode: function (other) { return false; }, + isSupported: function (feature, version) { return false; }, + lookupNamespaceURI: function (prefix) { return ""; }, + lookupPrefix: function (namespaceURI) { return ""; }, + insertBefore: function (newChild, refChild) { return {}; }, //Node + lastChild: {}, //Node + localName: "", + nodeName: "", + nodeValue: "", + nodeType: 0, + namespaceURI: "", + nextSibling: {}, //Node + normalize: function () { return {}; }, + ownerDocument: {}, //Document + parentNode: {}, //Node + prefix: "", + previousSibling: {}, //Node + replaceChild: function (newChild, refChild) { return {}; }, //Node + removeChild: function (oldChild) { return {}; }, //Node + setUserData: function (key, data, handler) { return {}; }, + textContent: "", +}; + +var NodeList = { + length: 0, + item: function (index) {}, //Node +}; + +var NamedNodeMap = { + length: 0, + getNamedItem: function (name) { return {}; }, //Node + setNamedItem: function (arg) { return {}; }, //Node + removeNamedItem: function (name) { return {}; }, //Node + item: function (index) { return {}; }, //Node + getNamedItemNS: function (namespaceURI, localName) { return {}; }, //Node + setNamedItemNS: function (arg) { return {}; }, //Node + removeNamedItemNS: function (namespaceURI, localName) { return {}; }, //Node +}; + +var CharacterData = { + data: "", + length: 0, + substringData: function (offset,count) { return ""; }, + appendData: function (arg) { return {}; }, + insertData: function (offset,arg) { return {}; }, + deleteData: function (offset,count) { return {}; }, + replaceData: function (offset,count,arg) { return {}; }, +}; CharacterData.prototype = new Node(); -Attr.name = 0;//String -Attr.specified = 0;//Boolean -Attr.value = 0;//String -Attr.ownerElement = 0;//Element -Attr.schemaTypeInfo = 0;//TypeInfo -Attr.isId = 0;//Boolean -Attr = {}; +var Attr = { + name: "", + specified: false, + value: "", + ownerElement: {}, //Element + schemaTypeInfo: {}, //TypeInfo + isId: false, +}; Attr.prototype = new Node(); -Element.tagName = 0;//String -Element.schemaTypeInfo = 0;//TypeInfo -Element = {}; -Element.getAttribute = function(name) {};//String -Element.setAttribute = function(name,value) {};//Object -Element.removeAttribute = function(name) {};//Object -Element.getAttributeNode = function(name) {};//Attr -Element.setAttributeNode = function(newAttr) {};//Attr -Element.removeAttributeNode = function(oldAttr) {};//Attr -Element.getElementsByTagName = function(name) {};//NodeList -Element.getAttributeNS = function(namespaceURI,localName) {};//String -Element.setAttributeNS = function(namespaceURI,qualifiedName,value) {};//Object -Element.removeAttributeNS = function(namespaceURI,localName) {};//Object -Element.getAttributeNodeNS = function(namespaceURI,localName) {};//Object -Element.setAttributeNodeNS = function(newAttr) {};//Object -Element.getElementsByTagNameNS = function(namespaceURI,localName) {};//NodeList -Element.hasAttribute = function(name) {};//Boolean -Element.hasAttributeNS = function(namespaceURI,localName) {};//Boolean -Element.setIdAttribute = function(name,isId) {};//Object -Element.setIdAttributeNS = function(namespaceURI,localName,isId) {};//Object -Element.setIdAttributeNode = function(idAttr,isId) {};//Object +var Element = { + getAttribute: function (name) { return ""; }, + getAttributeNode: function (name) { return {}; }, //Attr + getAttributeNodeNS: function (namespaceURI, localName) { return {}; }, + getAttributeNS: function (namespaceURI, localName) { return ""; }, + getElementsByTagName: function (name) { return {}; }, //NodeList + getElementsByTagNameNS: function (namespaceURI, localName) { return {}; }, //NodeList + hasAttribute: function (name) { return false; }, + hasAttributeNS: function (namespaceURI, localName) { return false; }, + removeAttribute: function (name) { return {}; }, + removeAttributeNode: function (oldAttr) {}, //Attr + removeAttributeNS: function (namespaceURI, localName) { return {}; }, + schemaTypeInfo: {}, //TypeInfo + setAttribute: function (name,value) { return {}; }, + setAttributeNode: function (newAttr) { return {}; }, //Attr + setAttributeNodeNS: function (newAttr) { return {}; }, + setAttributeNS: function (namespaceURI, qualifiedName, value) { return {}; }, + setIdAttribute: function (name, isId) { return {}; }, + setIdAttributeNode: function (idAttr, isId) { return {}; }, + setIdAttributeNS: function (namespaceURI, localName, isId) { return {}; }, + tagName: "", +}; Element.prototype = new Node(); -Text.isElementContentWhitespace = 0;//Boolean -Text.wholeText = 0;//String -Text = {}; -Text.splitText = function(offset) {};//Text -Text.replaceWholeText = function(content) {};//Text +var Text = { + isElementContentWhitespace: false, + replaceWholeText: function (content) { return {}; }, //Text + splitText: function (offset) { return {}; }, //Text + wholeText: "", +}; Text.prototype = new CharacterData(); +var Comment = {}; Comment.prototype = new CharacterData(); -TypeInfo.typeName = 0;//String -TypeInfo.typeNamespace = 0;//String -TypeInfo = {}; -TypeInfo.isDerivedFrom = function(typeNamespaceArg,typeNameArg,derivationMethod) {};//Boolean -TypeInfo.prototype = new Object(); - -UserDataHandler.handle = function(param1,param2,param3,param4,param5) {};//Object -UserDataHandler.prototype = new Object(); - -DOMError.severity = 0;//Number -DOMError.message = 0;//String -DOMError.type = 0;//String -DOMError.relatedException = 0;//Object -DOMError.relatedData = 0;//Object -DOMError.location = 0;//DOMLocator -DOMError = {}; -DOMError.prototype = new Object(); - -DOMErrorHandler.handler = function(error) {};//Boolean -DOMErrorHandler.prototype = new Object(); - -DOMLocator.lineNumber = 0;//Number -DOMLocator.columnNumber = 0;//Number -DOMLocator.byteOffset = 0;//Number -DOMLocator.utf16Offset = 0;//Number -DOMLocator.relatedNode = 0;//Node -DOMLocator.uri = 0;//String -DOMLocator = {}; -DOMLocator.prototype = new Object(); - -DOMConfiguration.parameterNames = 0;//DOMStringList -DOMConfiguration = {}; -DOMConfiguration.setParameter = function(name,value) {};//Object -DOMConfiguration.getParameter = function(name) {};//Object -DOMConfiguration.canSetParameter = function(name,value) {};//Boolean -DOMConfiguration.prototype = new Object(); +var TypeInfo = { + isDerivedFrom: function (typeNamespaceArg, typeNameArg, derivationMethod) { return false; }, + typeName: "", + typeNamespace: "", +}; + +var UserDataHandler = { + handle: function (param1, param2, param3, param4, param5) { return {}; }, +}; + +var DOMError = { + location: {}, //DOMLocator + message: "", + relatedData: {}, //Object + relatedException: {}, //Object + severity: 0, + type: "", +}; + +var DOMErrorHandler = { + handler: function (error) { return false; }, +}; + +var DOMLocator = { + byteOffset: 0, + columnNumber: 0, + lineNumber: 0, + relatedNode: 0, //Node + uri: "", + utf16Offset: 0, +}; + +var DOMConfiguration = { + canSetParameter: function (name, value) { return false; }, + getParameter: function (name) { return {}; }, + parameterNames: 0, //DOMStringList + setParameter: function (name, value) { return {}; }, +}; +var CDATASection = {}; CDATASection.prototype = new Text(); -DocumentType.name = 0;//String -DocumentType.entities = 0;//NamedNodeMap -DocumentType.notations = 0;//NamedNodeMap -DocumentType.publicId = 0;//String -DocumentType.systemId = 0;//String -DocumentType.internalSubset = 0;//String -DocumentType = {}; +var DocumentType = { + entities: {}, //NamedNodeMap + internalSubset: "", + name: "", + notations: {}, //NamedNodeMap + publicId: "", + systemId: "", +}; DocumentType.prototype = new Node(); -Notation.publicId = 0;//String -Notation.systemId = 0;//String -Notation = {}; +var Notation = { + publicId: "", + systemId: "", +}; Notation.prototype = new Node(); -Entity.publicId = 0;//String -Entity.systemId = 0;//String -Entity.notationName = 0;//String -Entity.inputEncoding = 0;//String -Entity.xmlEncoding = 0;//String -Entity.xmlVersion = 0;//String -Entity = {}; +var Entity = { + inputEncoding: "", + notationName: "", + publicId: "", + systemId: "", + xmlEncoding: "", + xmlVersion: "", +}; Entity.prototype = new Node(); +var EntityReference = {}; EntityReference.prototype = new Node(); -ProcessingInstruction.target = 0;//String -ProcessingInstruction.data = 0;//String -ProcessingInstruction = {}; +var ProcessingInstruction = { + data: "", + target: "", +}; ProcessingInstruction.prototype = new Node(); diff --git a/plugin/src/main/dist/sdk/clientAny/DOMEvents.js b/plugin/src/main/dist/sdk/clientAny/DOMEvents.js index 42afa09f..157cea18 100644 --- a/plugin/src/main/dist/sdk/clientAny/DOMEvents.js +++ b/plugin/src/main/dist/sdk/clientAny/DOMEvents.js @@ -1,100 +1,111 @@ -Event.type = 0;//Gecko,String -Event.target = 0;//Gecko,EventTarget -Event.currentTarget = 0;//Gecko,EventTarget -Event.eventPhase = 0;//Gecko,Number -Event.bubbles = 0;//Gecko,Boolean -Event.cancelable = 0;//Gecko,Boolean -Event.timeStamp = 0;//Gecko,Number -Event.namespaceURI = 0;//Gecko,String -Event = {}; -Event.stopPropagation = function() {};//Gecko,Object -Event.preventDefault = function() {};//Gecko,Object -Event.initEvent = function(eventTypeArg,canBubbleArg,cancelableArg) {};//Gecko,Object -Event.isCustom = function() {};//Gecko,Boolean -Event.stopImmediatePropagation = function() {};//Gecko,Object -Event.isDefaultPrevented = function() {};//Gecko,Boolean -Event.initEventNS = function(namespaceURIArg,eventTypeArg,canBubbleArg,cancelableArg) {};//Gecko,Object -Event.prototype = new Object(); +var Event = { + currentTarget: {}, //Gecko,EventTarget + bubbles: false, //Gecko + cancelable: false, //Gecko + eventPhase: 0, //Gecko + initEvent: function (eventTypeArg, canBubbleArg, cancelableArg) { return {}; }, //Gecko + initEventNS: function (namespaceURIArg, eventTypeArg, canBubbleArg, cancelableArg) { return {}; }, //Gecko + isCustom: function () { return false; }, //Gecko + isDefaultPrevented: function () { return false; }, //Gecko + namespaceURI: "", //Gecko + preventDefault: function () { return {}; }, //Gecko + stopImmediatePropagation: function () { return {}; }, //Gecko + stopPropagation: function () { return {}; }, //Gecko + target: {}, //Gecko,EventTarget + timeStamp: 0, //Gecko + type: "", //Gecko +}; -EventTarget.addEventListener = function(type,listener,useCapture) {};//Gecko,Object -EventTarget.removeEventListener = function(type,listener,useCapture) {};//Gecko,Object -EventTarget.dispatchEvent = function(evt) {};//Gecko,Boolean -EventTarget.addEventListenerNS = function(namespaceURI,type,listener,useCapture,evtGroup) {};//Gecko,Object -EventTarget.removeEventListenerNS = function(namespaceURI,type,listener,useCapture) {};//Gecko,Object -EventTarget.willTriggerNS = function(namespaceURI,type) {};//Gecko,Boolean -EventTarget.hasEventListenerNS = function(namespaceURI,type) {};//Gecko,Boolean -EventTarget.prototype = new Object(); +var EventTarget = { + addEventListener: function (type,listener,useCapture) { return {}; }, //Gecko + addEventListenerNS: function (namespaceURI, type, listener, useCapture, evtGroup) { return {}; }, //Gecko + dispatchEvent: function (evt) { return false; }, //Gecko + hasEventListenerNS: function (namespaceURI, type) { return false; }, //Gecko + removeEventListener: function (type,listener,useCapture) { return {}; }, //Gecko + removeEventListenerNS: function (namespaceURI, type, listener, useCapture) { return {}; }, //Gecko + willTriggerNS: function (namespaceURI, type) { return false; }, //Gecko +}; -EventListener.handleEvent = function(evt) {};//Gecko,Object -EventListener.prototype = new Object(); +var EventListener = { + handleEvent: function (evt) { return {}; }, //Gecko +}; -EventException.code = 0;//Gecko,Number -EventException = {}; -EventException.prototype = new Object(); +var EventException = { + code: 0, //Gecko +}; -DocumentEvent.createEvent = function(eventType) {};//Gecko,Event -DocumentEvent.canDispatch = function(namespaceURI,type) {};//Gecko,String -DocumentEvent.prototype = new Object(); +var DocumentEvent = { + canDispatch: function (namespaceURI, type) { return ""; }, //Gecko + createEvent: function (eventType) { return {}; }, //Gecko,Event +}; -CustomEvent.setDispatchState = function(target,phase) {};//Gecko,Object -CustomEvent.isPropagationStopped = function() {};//Gecko,Boolean -CustomEvent.isImmediatePropagationStopped = function() {};//Gecko,Boolean +var CustomEvent = { + isImmediatePropagationStopped: function () { return false; }, //Gecko + isPropagationStopped: function () { return false; }, //Gecko + setDispatchState: function (target, phase) { return {}; }, //Gecko +}; CustomEvent.prototype = new Event(); -UIEvent.view = 0;//Gecko,AbstractView -UIEvent.detail = 0;//Gecko,Number -UIEvent = {}; -UIEvent.initUIEvent = function(typeArg,canBubbleArg,cancelableArg,viewArg,detailArg) {};//Gecko,Object -UIEvent.initUIEventNS = function(namespaceURI,typeArg,canBubbleArg,cancelableArg,viewArg,detailArg) {};//Gecko,Object +var UIEvent = { + detail: 0, //Gecko + initUIEvent: function (typeArg, canBubbleArg, cancelableArg, viewArg, detailArg) { return {}; }, //Gecko + initUIEventNS: function (namespaceURI, typeArg, canBubbleArg, cancelableArg, viewArg, detailArg) { return {}; }, //Gecko + view: {}, //Gecko,AbstractView +}; UIEvent.prototype = new Event(); -TextEvent.data = 0;//Gecko,String -TextEvent = {}; -TextEvent.initTextEvent = function(typeArg,canBubbleArg,cancelableArg,viewArg,dataArg) {};//Gecko,Object -TextEvent.initTextEventNS = function(namespaceURI,typeArg,canBubbleArg,cancelableArg,viewArg,dataArg) {};//Gecko,Object +var TextEvent = { + data: "", //Gecko + initTextEvent: function (typeArg, canBubbleArg, cancelableArg, viewArg, dataArg) { return {}; }, //Gecko + initTextEventNS: function (namespaceURI, typeArg, canBubbleArg, cancelableArg, viewArg, dataArg) { return {}; }, //Gecko +}; TextEvent.prototype = new UIEvent(); -MouseEvent.screenX = 0;//Gecko,Number -MouseEvent.screenY = 0;//Gecko,Number -MouseEvent.clientX = 0;//Gecko,Number -MouseEvent.clientY = 0;//Gecko,Number -MouseEvent.ctrlKey = 0;//Gecko,Boolean -MouseEvent.shiftKey = 0;//Gecko,Boolean -MouseEvent.altKey = 0;//Gecko,Boolean -MouseEvent.metaKey = 0;//Gecko,Boolean -MouseEvent.button = 0;//Gecko,Number -MouseEvent.relatedTarget = 0;//Gecko,EventTarget -MouseEvent = {}; -MouseEvent.getModifierState = function(keyIdentifierArg) {};//Gecko,Boolean -MouseEvent.initMouseEvent = function(typeArg,canBubbleArg,cancelableArg,viewArg,detailArg,screenXArg,screenYArg,clientXArg,clientYArg,ctrlKeyArg,altKeyArg,shiftKeyArg,metaKeyArg,buttonArg,relatedTargetArg) {};//Gecko,Object -MouseEvent.initMouseEventNS = function(namespaceURI,typeArg,canBubbleArg,cancelableArg,viewArg,detailArg,screenXArg,screenYArg,clientXArg,clientYArg,ctrlKeyArg,altKeyArg,shiftKeyArg,metaKeyArg,buttonArg,relatedTargetArg) {};//Gecko,Object +var MouseEvent = { + altKey: false, //Gecko + button: 0, //Gecko + clientX: 0, //Gecko + clientY: 0, //Gecko + ctrlKey: false, //Gecko + getModifierState: function (keyIdentifierArg) { return false; }, //Gecko + initMouseEvent: function (typeArg, canBubbleArg, cancelableArg, viewArg, detailArg, screenXArg, screenYArg, clientXArg, clientYArg, ctrlKeyArg, altKeyArg, shiftKeyArg, metaKeyArg, buttonArg, relatedTargetArg) { return {}; }, //Gecko + initMouseEventNS: function (namespaceURI, typeArg, canBubbleArg, cancelableArg, viewArg, detailArg, screenXArg, screenYArg, clientXArg, clientYArg, ctrlKeyArg, altKeyArg, shiftKeyArg, metaKeyArg, buttonArg, relatedTargetArg) { return {}; }, //Gecko + metaKey: false, //Gecko + screenX: 0, //Gecko + screenY: 0, //Gecko + shiftKey: false, //Gecko + relatedTarget: {}, //Gecko,EventTarget +}; MouseEvent.prototype = new UIEvent(); -KeyboardEvent.keyIdentifier = 0;//Gecko,String -KeyboardEvent.keyLocation = 0;//Gecko,Number -KeyboardEvent.ctrlKey = 0;//Gecko,Boolean -KeyboardEvent.shiftKey = 0;//Gecko,Boolean -KeyboardEvent.altKey = 0;//Gecko,Boolean -KeyboardEvent.metaKey = 0;//Gecko,Boolean -KeyboardEvent = {}; -KeyboardEvent.getModifierState = function(keyIdentifierArg) {};//Gecko,Boolean -KeyboardEvent.initKeyboardEvent = function(typeArg,canBubbleArg,cancelableArg,viewArg,keyIdentifierArg,keyLocationArg,modifiersList) {};//Gecko,Object -KeyboardEvent.initKeyboardEventNS = function(namespaceURI,typeArg,canBubbleArg,cancelableArg,viewArg,keyIdentifierArg,keyLocationArg,modifiersList) {};//Gecko,Object +var KeyboardEvent = { + altKey: false, //Gecko + ctrlKey: false, //Gecko + getModifierState: function (keyIdentifierArg) { return false; }, //Gecko + initKeyboardEvent: function (typeArg, canBubbleArg, cancelableArg, viewArg, keyIdentifierArg, keyLocationArg, modifiersList) { return {}; }, //Gecko + initKeyboardEventNS: function (namespaceURI, typeArg, canBubbleArg, cancelableArg, viewArg, keyIdentifierArg, keyLocationArg, modifiersList) { return {}; }, //Gecko + keyIdentifier: "", //Gecko + keyLocation: 0, //Gecko + metaKey: false, //Gecko + shiftKey: false, //Gecko +}; KeyboardEvent.prototype = new UIEvent(); -MutationEvent.relatedNode = 0;//Gecko,Node -MutationEvent.prevValue = 0;//Gecko,String -MutationEvent.newValue = 0;//Gecko,String -MutationEvent.attrName = 0;//Gecko,String -MutationEvent.attrChange = 0;//Gecko,Number -MutationEvent = {}; -MutationEvent.initMutationEvent = function(typeArg,canBubbleArg,cancelableArg,relatedNodeArg,prevValueArg,newValueArg,attrNameArg,attrChangeArg) {};//Gecko,Object -MutationEvent.initMutationEventNS = function(namespaceURI,typeArg,canBubbleArg,cancelableArg,relatedNodeArg,prevValueArg,newValueArg,attrNameArg,attrChangeArg) {};//Gecko,Object +var MutationEvent = { + attrChange: 0, //Gecko + attrName: "", //Gecko + initMutationEvent: function (typeArg, canBubbleArg, cancelableArg, relatedNodeArg, prevValueArg, newValueArg, attrNameArg, attrChangeArg) { return {}; }, //Gecko + initMutationEventNS: function (namespaceURI, typeArg, canBubbleArg, cancelableArg, relatedNodeArg, prevValueArg, newValueArg, attrNameArg, attrChangeArg) { return {}; }, //Gecko + newValue: "", //Gecko + prevValue: "", //Gecko + relatedNode: {}, //Gecko,Node +}; MutationEvent.prototype = new UIEvent(); -MutationNameEvent.prevNamespaceURI = 0;//Gecko,String -MutationNameEvent.prevNodeName = 0;//Gecko,String -MutationNameEvent = {}; -MutationNameEvent.initMutationNameEvent = function(typeArg,canBubbleArg,cancelableArg,relatedNodeArg,prevNamespaceURIArg,prevNodeNameArg) {};//Gecko,Object -MutationNameEvent.initMutationNameEventNS = function(namespaceURI,typeArg,canBubbleArg,cancelableArg,relatedNodeArg,prevNamespaceURIArg,prevNodeNameArg) {};//Gecko,Object +var MutationNameEvent = { + initMutationNameEvent: function (typeArg, canBubbleArg, cancelableArg, relatedNodeArg, prevNamespaceURIArg, prevNodeNameArg) { return {}; }, //Gecko + initMutationNameEventNS: function (namespaceURI, typeArg, canBubbleArg, cancelableArg, relatedNodeArg, prevNamespaceURIArg, prevNodeNameArg) { return {}; }, //Gecko + prevNamespaceURI: "", //Gecko + prevNodeName: "", //Gecko +}; MutationNameEvent.prototype = new MutationEvent(); diff --git a/plugin/src/main/dist/sdk/clientAny/DOMTraversalAndRange.js b/plugin/src/main/dist/sdk/clientAny/DOMTraversalAndRange.js index 68cd2ae2..3b4d4e53 100644 --- a/plugin/src/main/dist/sdk/clientAny/DOMTraversalAndRange.js +++ b/plugin/src/main/dist/sdk/clientAny/DOMTraversalAndRange.js @@ -1,60 +1,64 @@ -NodeIterator.root = 0;//Node -NodeIterator.whatToShow = 0;//Number -NodeIterator.filter = 0;//NodeFilter -NodeIterator.expandEntityReferences = 0;//Boolean -NodeIterator = {}; -NodeIterator.nextNode = function() {};//Node -NodeIterator.previousNode = function() {};//Node -NodeIterator.detach = function() {};//Object -NodeIterator.prototype = new Object(); +var NodeIterator = { + detach: function () { return {}; }, + expandEntityReferences: false, + filter: {}, //NodeFilter + nextNode: function () { return {}; }, //Node + previousNode: function () { return {}; }, //Node + root: {}, //Node + whatToShow: 0, +}; -NodeFilter.NodeFilter = function(param) {};//Number -NodeFilter.prototype = new Object(); +var NodeFilter = { + NodeFilter: function (param) { return 0; }, +}; -TreeWalker.parentNode = function() {};//Node -TreeWalker.firstChild = function() {};//Node -TreeWalker.lastChild = function() {};//Node -TreeWalker.previousSibling = function() {};//Node -TreeWalker.nextSibling = function() {};//Node -TreeWalker.previousNode = function() {};//Node -TreeWalker.nextNode = function() {};//Node -TreeWalker.prototype = new Object(); +var TreeWalker = { + firstChild: function () { return {}; }, //Node + lastChild: function () { return {}; }, //Node + nextNode: function () { return {}; }, //Node + nextSibling: function () { return {}; }, //Node + parentNode: function () { return {}; }, //Node + previousNode: function () { return {}; }, //Node + previousSibling: function () { return {}; }, //Node +}; -DocumentTraversal.createNodeIterator = function(root,whatToShow,filter,entityReferenceExpansion) {};//NodeIterator -DocumentTraversal.createTreeWalker = function(root,whatToShow,filter,entityReferenceExpansion) {};//TreeWalker -DocumentTraversal.prototype = new Object(); +var DocumentTraversal = { + createNodeIterator: function (root, whatToShow, filter, entityReferenceExpansion) { return {}; }, //NodeIterator + createTreeWalker: function (root, whatToShow, filter, entityReferenceExpansion) { return {}; }, //TreeWalker +}; -Range.startContainer = 0;//Node -Range.startOffset = 0;//long -Range.endContainer = 0;//Node -Range.endOffset = 0;//long -Range.collapsed = 0;//Boolean -Range.commonAncestorContainer = 0;//Node -Range = {}; -Range.setStart = function(refNode,offset) {};//Object -Range.setEnd = function(refNode,offset) {};//Object -Range.setStartBefore = function(refNode) {};//Object -Range.setStartAfter = function(refNode) {};//Object -Range.setEndBefore = function(refNode) {};//Object -Range.setEndAfter = function(refNode) {};//Object -Range.collapse = function(toStart) {};//Object -Range.selectNode = function(refNode) {};//Object -Range.selectNodeContents = function(refNode) {};//Object -Range.compareBoundaryPoints = function(how,sourceRange) {};//short -Range.deleteContents = function() {};//Object -Range.extractContents = function() {};//DocumentFragment -Range.cloneContents = function() {};//DocumentFragment -Range.insertNode = function(newNode) {};//Object -Range.surroundContents = function(newParent) {};//Object -Range.cloneRange = function() {};//Range -Range.toString = function() {};//String -Range.detach = function() {};//Object -Range.createContextualFragment = function(tagString) {};//Gecko,Object -Range.prototype = new Object(); +var Range = { + cloneContents: function () { return {}; }, //DocumentFragment + cloneRange: function () { return {}; }, //Range + collapse: function (toStart) { return {}; }, + collapsed: false, + commonAncestorContainer: {}, //Node + compareBoundaryPoints: function (how, sourceRange) { return 0; }, + createContextualFragment: function (tagString) { return {}; }, //Gecko + deleteContents: function () { return {}; }, + detach: function () { return {}; }, + endContainer: {}, //Node + endOffset: 0, + extractContents: function () { return {}; }, //DocumentFragment + insertNode: function (newNode) { return {}; }, + selectNode: function (refNode) { return {}; }, + selectNodeContents: function (refNode) { return {}; }, + setEnd: function (refNode,offset) { return {}; }, + setEndAfter: function (refNode) { return {}; }, + setEndBefore: function (refNode) { return {}; }, + setStart: function (refNode, offset) { return {}; }, + setStartAfter: function (refNode) { return {}; }, + setStartBefore: function (refNode) { return {}; }, + startContainer: {}, //Node + startOffset: 0, + surroundContents: function (newParent) { return {}; }, + toString: function () { return ""; }, +}; -DocumentRange.createRange = function() {};//Range -DocumentRange.prototype = new Object(); +var DocumentRange = { + createRange: function () { return {}; }, //Range +}; -RangeException.code = 0;//Number -RangeException = {}; -RangeException.prototype = new Object(); +var RangeException = { + code: 0, +}; diff --git a/plugin/src/main/dist/sdk/clientAny/DOMXPath.js b/plugin/src/main/dist/sdk/clientAny/DOMXPath.js index 0deec4e7..94f70458 100644 --- a/plugin/src/main/dist/sdk/clientAny/DOMXPath.js +++ b/plugin/src/main/dist/sdk/clientAny/DOMXPath.js @@ -1,40 +1,44 @@ -XPathException.code = 0;//Gecko,Number -XPathException = {}; -XPathException.prototype = new Object(); +var XPathException = { + code: 0, //Gecko +}; -XPathEvaluator.createExpression = function(expression,resolver) {};//Gecko,XPathExpression -XPathEvaluator.createNSResolver = function(nodeResolver) {};//Gecko,XPathNSResolver -XPathEvaluator.evaluate = function(expression,contextNode,resolver,type,result) {};//Gecko,Object -XPathEvaluator.prototype = new Object(); +var XPathEvaluator = { + createExpression: function (expression, resolver) { return {}; }, //Gecko,XPathExpression + createNSResolver: function (nodeResolver) { return {}; }, //Gecko,XPathNSResolver + evaluate: function (expression, contextNode, resolver, type, result) { return {}; }, //Gecko +}; -XPathExpression.evaluate = function(contextNode,type,result) {};//Gecko,Object -XPathExpression.prototype = new Object(); +var XPathExpression = { + evaluate: function (contextNode, type, result) { return {}; }, //Gecko +}; -XPathNSResolver.lookupNamespaceURI = function(prefix) {};//Gecko,String -XPathNSResolver.prototype = new Object(); +var XPathNSResolver = { + lookupNamespaceURI: function (prefix) { return ""; }, //Gecko +}; -XPathResult.resultType = 0;//Gecko,Number -XPathResult.numberValue = 0;//Gecko,Number -XPathResult.stringValue = 0;//Gecko,String -XPathResult.booleanValue = 0;//Gecko,Boolean -XPathResult.singleNodeValue = 0;//Gecko,Node -XPathResult.invalidIteratorState = 0;//Gecko,Boolean -XPathResult.snapshotLength = 0;//Gecko,Number -XPathResult.ORDERED_NODE_SNAPSHOT_TYPE = 0;//Gecko,Number -XPathResult.ORDERED_NODE_ITERATOR_TYPE = 0;//Gecko,Number -XPathResult.ANY_TYPE = 0;//Gecko,Number -XPathResult.BOOLEAN_TYPE = 0;//Gecko,Number -XPathResult.NUMBER_TYPE = 0;//Gecko,Number -XPathResult.STRING_TYPE = 0;//Gecko,Number -XPathResult.FIRST_ORDERED_NODE_TYPE = 0;//Gecko,Number -XPathResult.ANY_UNORDERED_NODE_TYPE = 0;//Gecko,Number -XPathResult.UNORDERED_NODE_ITERATOR_TYPE = 0;//Gecko,Number -XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE = 0;//Gecko,Number -XPathResult = {}; -XPathResult.iterateNext = function() {};//Gecko,Node -XPathResult.snapshotItem = function(index) {};//Gecko,Node -XPathResult.prototype = new Object(); +var XPathResult = { + ANY_TYPE: 0, //Gecko + ANY_UNORDERED_NODE_TYPE: 0, //Gecko + BOOLEAN_TYPE: 0, //Gecko + booleanValue: false, //Gecko + FIRST_ORDERED_NODE_TYPE: 0, //Gecko + invalidIteratorState: false, //Gecko + iterateNext: function () { return {}; }, //Gecko,Node + NUMBER_TYPE: 0, //Gecko + numberValue: 0, //Gecko + ORDERED_NODE_ITERATOR_TYPE: 0, //Gecko + ORDERED_NODE_SNAPSHOT_TYPE: 0, //Gecko + resultType: 0, //Gecko + singleNodeValue: {}, //Gecko,Node + snapshotItem: function (index) { return {}; }, //Gecko,Node + snapshotLength: 0, //Gecko + STRING_TYPE: 0, //Gecko + stringValue: "", //Gecko + UNORDERED_NODE_ITERATOR_TYPE: 0, //Gecko + UNORDERED_NODE_SNAPSHOT_TYPE: 0, //Gecko +}; -XPathNamespace.ownerElement = 0;//Gecko,Element -XPathNamespace = {}; +var XPathNamespace = { + ownerElement: {}, //Gecko,Element +}; XPathNamespace.prototype = new Node(); diff --git a/plugin/src/main/java/com/intellij/javascript/JSClassNameMacro.java b/plugin/src/main/java/com/intellij/javascript/JSClassNameMacro.java index 7921b5fe..30823044 100644 --- a/plugin/src/main/java/com/intellij/javascript/JSClassNameMacro.java +++ b/plugin/src/main/java/com/intellij/javascript/JSClassNameMacro.java @@ -19,7 +19,7 @@ import com.intellij.lang.javascript.psi.JSFunction; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; import consulo.annotation.component.ExtensionImpl; -import consulo.javascript.language.JavaScriptBundle; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.editor.completion.lookup.LookupElement; import consulo.language.editor.template.Expression; import consulo.language.editor.template.ExpressionContext; @@ -33,77 +33,66 @@ import consulo.project.Project; import org.jetbrains.annotations.NonNls; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; @ExtensionImpl -public class JSClassNameMacro extends Macro -{ - @Override - @NonNls - public String getName() - { - return "jsClassName"; - } - - @Override - public String getPresentableName() - { - return JavaScriptBundle.message("js.classname.macro.description"); - } - - @Override - @NonNls - public String getDefaultValue() - { - return ""; - } - - @Override - public Result calculateResult(@Nonnull final Expression[] params, final ExpressionContext context) - { - final PsiElement elementAtCaret = findElementAtCaret(context); - final JSResolveUtil.ContextResolver resolver = new JSResolveUtil.ContextResolver(elementAtCaret); - - String text = resolver.getQualifierAsString(); - if(text == null) - { - final JSFunction previousFunction = PsiTreeUtil.getPrevSiblingOfType(elementAtCaret, JSFunction.class); - - if(previousFunction != null) - { - text = previousFunction.getName(); - } - } - - if(text != null) - { - return new TextResult(text); - } - - return null; - } - - public static PsiElement findElementAtCaret(final ExpressionContext context) - { - Project project = context.getProject(); - int templateStartOffset = context.getTemplateStartOffset(); - int offset = templateStartOffset > 0 ? context.getTemplateStartOffset() - 1 : context.getTemplateStartOffset(); - - PsiDocumentManager.getInstance(project).commitAllDocuments(); - - PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(context.getEditor().getDocument()); - return file.findElementAt(offset); - } - - @Override - public Result calculateQuickResult(@Nonnull final Expression[] params, final ExpressionContext context) - { - return null; - } - - @Override - public LookupElement[] calculateLookupItems(@Nonnull final Expression[] params, final ExpressionContext context) - { - return null; - } +public class JSClassNameMacro extends Macro { + @Override + @NonNls + public String getName() { + return "jsClassName"; + } + + @Override + public String getPresentableName() { + return JavaScriptLocalize.jsClassnameMacroDescription().get(); + } + + @Override + @NonNls + public String getDefaultValue() { + return ""; + } + + @Override + public Result calculateResult(@Nonnull Expression[] params, ExpressionContext context) { + PsiElement elementAtCaret = findElementAtCaret(context); + JSResolveUtil.ContextResolver resolver = new JSResolveUtil.ContextResolver(elementAtCaret); + + String text = resolver.getQualifierAsString(); + if (text == null) { + JSFunction previousFunction = PsiTreeUtil.getPrevSiblingOfType(elementAtCaret, JSFunction.class); + + if (previousFunction != null) { + text = previousFunction.getName(); + } + } + + if (text != null) { + return new TextResult(text); + } + + return null; + } + + public static PsiElement findElementAtCaret(ExpressionContext context) { + Project project = context.getProject(); + int templateStartOffset = context.getTemplateStartOffset(); + int offset = templateStartOffset > 0 ? context.getTemplateStartOffset() - 1 : context.getTemplateStartOffset(); + + PsiDocumentManager.getInstance(project).commitAllDocuments(); + + PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(context.getEditor().getDocument()); + return file.findElementAt(offset); + } + + @Override + public Result calculateQuickResult(@Nonnull Expression[] params, ExpressionContext context) { + return null; + } + + @Override + public LookupElement[] calculateLookupItems(@Nonnull Expression[] params, ExpressionContext context) { + return null; + } } diff --git a/plugin/src/main/java/com/intellij/javascript/JSImplementationTextSelectioner.java b/plugin/src/main/java/com/intellij/javascript/JSImplementationTextSelectioner.java index 1ddba26c..3f80953a 100644 --- a/plugin/src/main/java/com/intellij/javascript/JSImplementationTextSelectioner.java +++ b/plugin/src/main/java/com/intellij/javascript/JSImplementationTextSelectioner.java @@ -30,33 +30,28 @@ import consulo.language.psi.PsiElement; import consulo.language.psi.util.PsiTreeUtil; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; @ExtensionImpl -public class JSImplementationTextSelectioner implements ImplementationTextSelectioner -{ - @RequiredReadAction - @Override - public int getTextStartOffset(@Nonnull PsiElement element) - { - return element.getTextOffset(); - } +public class JSImplementationTextSelectioner implements ImplementationTextSelectioner { + @RequiredReadAction + @Override + public int getTextStartOffset(@Nonnull PsiElement element) { + return element.getTextOffset(); + } - @RequiredReadAction - @Override - public int getTextEndOffset(@Nonnull PsiElement element) - { - if(element instanceof JSDefinitionExpression) - { - element = PsiTreeUtil.getParentOfType(element, JSExpressionStatement.class); - } - return element.getTextRange().getEndOffset(); - } + @RequiredReadAction + @Override + public int getTextEndOffset(@Nonnull PsiElement element) { + if (element instanceof JSDefinitionExpression) { + element = PsiTreeUtil.getParentOfType(element, JSExpressionStatement.class); + } + return element.getTextRange().getEndOffset(); + } - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/javascript/JSMethodNameMacro.java b/plugin/src/main/java/com/intellij/javascript/JSMethodNameMacro.java index 9cf4300b..19c845e8 100644 --- a/plugin/src/main/java/com/intellij/javascript/JSMethodNameMacro.java +++ b/plugin/src/main/java/com/intellij/javascript/JSMethodNameMacro.java @@ -19,7 +19,7 @@ import com.intellij.lang.javascript.psi.JSFunction; import com.intellij.lang.javascript.psi.JSFunctionExpression; import consulo.annotation.component.ExtensionImpl; -import consulo.javascript.language.JavaScriptBundle; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.editor.completion.lookup.LookupElement; import consulo.language.editor.template.Expression; import consulo.language.editor.template.ExpressionContext; @@ -29,62 +29,51 @@ import consulo.language.psi.PsiElement; import consulo.language.psi.util.PsiTreeUtil; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; @ExtensionImpl -public class JSMethodNameMacro extends Macro -{ - @Override - public String getName() - { - return "jsMethodName"; - } +public class JSMethodNameMacro extends Macro { + @Override + public String getName() { + return "jsMethodName"; + } - @Override - public String getPresentableName() - { - return JavaScriptBundle.message("js.methodname.macro.description"); - } + @Override + public String getPresentableName() { + return JavaScriptLocalize.jsMethodnameMacroDescription().get(); + } - @Override - public String getDefaultValue() - { - return ""; - } + @Override + public String getDefaultValue() { + return ""; + } - @Override - public Result calculateResult(@Nonnull Expression[] params, ExpressionContext context) - { - final PsiElement elementAtCaret = JSClassNameMacro.findElementAtCaret(context); - if(elementAtCaret != null) - { - JSFunction function = PsiTreeUtil.getParentOfType(elementAtCaret, JSFunction.class); - if(function instanceof JSFunctionExpression) - { - function = ((JSFunctionExpression) function).getFunction(); - } + @Override + public Result calculateResult(@Nonnull Expression[] params, ExpressionContext context) { + PsiElement elementAtCaret = JSClassNameMacro.findElementAtCaret(context); + if (elementAtCaret != null) { + JSFunction function = PsiTreeUtil.getParentOfType(elementAtCaret, JSFunction.class); + if (function instanceof JSFunctionExpression functionExpression) { + function = functionExpression.getFunction(); + } - if(function != null) - { - final String name = function.getName(); - if(name != null) - { - return new TextResult(name); - } - } - } - return null; - } + if (function != null) { + String name = function.getName(); + if (name != null) { + return new TextResult(name); + } + } + } + return null; + } - @Override - public Result calculateQuickResult(@Nonnull Expression[] params, ExpressionContext context) - { - return null; - } + @Override + public Result calculateQuickResult(@Nonnull Expression[] params, ExpressionContext context) { + return null; + } - @Override - public LookupElement[] calculateLookupItems(@Nonnull Expression[] params, ExpressionContext context) - { - return null; - } + @Override + public LookupElement[] calculateLookupItems(@Nonnull Expression[] params, ExpressionContext context) { + return null; + } } diff --git a/plugin/src/main/java/com/intellij/javascript/JSParameterInfoHandler.java b/plugin/src/main/java/com/intellij/javascript/JSParameterInfoHandler.java index b6eaf6fd..ee3290e9 100644 --- a/plugin/src/main/java/com/intellij/javascript/JSParameterInfoHandler.java +++ b/plugin/src/main/java/com/intellij/javascript/JSParameterInfoHandler.java @@ -23,319 +23,271 @@ import consulo.javascript.language.JavaScriptLanguage; import consulo.language.Language; import consulo.language.ast.IElementType; -import consulo.language.editor.CodeInsightBundle; import consulo.language.editor.completion.lookup.LookupElement; import consulo.language.editor.completion.lookup.MutableLookupElement; +import consulo.language.editor.localize.CodeInsightLocalize; import consulo.language.editor.parameterInfo.*; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiFile; import consulo.language.psi.ResolveResult; import consulo.language.psi.search.DefinitionsScopedSearch; import consulo.util.collection.ArrayUtil; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.*; /** * @author Maxim.Mossienko */ @ExtensionImpl -public class JSParameterInfoHandler implements ParameterInfoHandlerWithTabActionSupport -{ - private static final Set> ourArgumentListAllowedParentClassesSet = Set.of(JSCallExpression.class); - - @Override - public boolean couldShowInLookup() - { - return true; - } - - @Override - public Object[] getParametersForLookup(final LookupElement item, final ParameterInfoContext context) - { - if(!(item instanceof MutableLookupElement)) - { - return null; - } - - PsiElement element = item.getPsiElement(); - if(element instanceof JSFunction) - { - final JSFunction originalFunction = (JSFunction) element; - final List lookupItems = new ArrayList(); - Set availableSignatures = new HashSet(); - - for(PsiElement el : DefinitionsScopedSearch.search(originalFunction)) - { - doAddSignature(lookupItems, availableSignatures, el); - } - - if(lookupItems.size() == 0) - { - lookupItems.add(originalFunction); - } - - return lookupItems.toArray(new Object[lookupItems.size()]); - } - - return ArrayUtil.EMPTY_OBJECT_ARRAY; - } - - private static void doAddSignature(final List lookupItems, final Set availableSignatures, final PsiElement el) - { - if(el instanceof JSFunction) - { - final JSFunction function = (JSFunction) el; - final JSParameterList parameterList = function.getParameterList(); - - if(parameterList != null) - { - final String typedSignature = buildSignature(parameterList.getParameters(), false, -1).text; - final String untypedSignature = buildSignature(parameterList.getParameters(), true, -1).text; - - if(!availableSignatures.contains(typedSignature) && !availableSignatures.contains(untypedSignature)) - { - lookupItems.add(function); - availableSignatures.add(typedSignature); - availableSignatures.add(untypedSignature); - } - } - } - } - - @Override - public JSArgumentList findElementForParameterInfo(final CreateParameterInfoContext context) - { - JSArgumentList argList = findArgumentList(context.getFile(), context.getOffset()); - - if(argList != null) - { - return fillSignaturesForArgumentList(context, argList); - } - return argList; - } - - @Nullable - public static JSArgumentList findArgumentList(final PsiFile file, final int offset) - { - JSArgumentList argList = ParameterInfoUtils.findParentOfType(file, offset, JSArgumentList.class); - if(argList == null) - { - final JSCallExpression callExpression = ParameterInfoUtils.findParentOfType(file, offset, JSCallExpression.class); - if(callExpression != null) - { - argList = callExpression.getArgumentList(); - } - } - return argList; - } - - @Nullable - private static JSArgumentList fillSignaturesForArgumentList(final CreateParameterInfoContext context, final @Nonnull JSArgumentList argList) - { - final PsiElement psiElement = argList.getParent(); - if(!(psiElement instanceof JSCallExpression)) - { - return null; - } - - final JSCallExpression parent = (JSCallExpression) psiElement; - final JSExpression methodExpression = parent.getMethodExpression(); - - if(methodExpression instanceof JSReferenceExpression) - { - final ResolveResult[] resolveResults = ((JSReferenceExpression) methodExpression).multiResolve(true); - - if(resolveResults.length > 0) - { - List items = new ArrayList(resolveResults.length); - Set availableSignatures = new HashSet(); - - for(ResolveResult r : resolveResults) - { - PsiElement element = r.getElement(); - if(element instanceof JSProperty) - { - element = ((JSProperty) element).getValue(); - } - - doAddSignature(items, availableSignatures, element); - } - - context.setItemsToShow(ArrayUtil.toObjectArray(items)); - return argList; - } - } - else if(methodExpression instanceof JSSuperExpression) - { - final PsiElement clazz = methodExpression.getReference().resolve(); - if(clazz instanceof JSFunction) - { - context.setItemsToShow(new Object[]{clazz}); - return argList; - } - } - return null; - } - - @Override - public void showParameterInfo(@Nonnull final JSArgumentList element, final CreateParameterInfoContext context) - { - context.showHint(element, element.getTextOffset(), this); - } - - @Override - public JSArgumentList findElementForUpdatingParameterInfo(final UpdateParameterInfoContext context) - { - return findArgumentList(context.getFile(), context.getOffset()); - } - - @Override - public void updateParameterInfo(@Nonnull final JSArgumentList o, final UpdateParameterInfoContext context) - { - if(context.getParameterOwner() != o) - { - context.removeHint(); - return; - } - final int currentParameterIndex = ParameterInfoUtils.getCurrentParameterIndex(o.getNode(), context.getOffset(), JSTokenTypes.COMMA); - context.setCurrentParameter(currentParameterIndex); - } - - @Override - public void updateUI(final JSFunction p, final ParameterInfoUIContext context) - { - final JSParameterList parameterList = p.getParameterList(); - final JSParameter[] params = parameterList != null ? parameterList.getParameters() : new JSParameter[0]; - final int currentParameterIndex = context.getCurrentParameterIndex() >= 0 ? context.getCurrentParameterIndex() : params.length; - final JSParameter parameter = currentParameterIndex < params.length ? params[currentParameterIndex] : null; - - final SignatureInfo signatureInfo = buildSignature(params, false, currentParameterIndex); - final String name = signatureInfo.text; - - final String currentParameterSignature = parameter != null ? getSignatureForParameter(parameter, false) : null; - int highlightStart = parameter != null ? signatureInfo.selectedParameterStart : 0; - int highlightEnd = parameter != null ? highlightStart + currentParameterSignature.length() : 0; - context.setupUIComponentPresentation(name, highlightStart, highlightEnd, false, false, false, context.getDefaultParameterColor()); - } - - private static class SignatureInfo - { - String text; - int selectedParameterStart = -1; - } - - private static - @Nonnull - SignatureInfo buildSignature(final JSParameter[] params, final boolean skipType, int selectedParameterIndex) - { - SignatureInfo info = new SignatureInfo(); - if(params.length > 0) - { - StringBuilder result = new StringBuilder(); - for(int i = 0; i < params.length; ++i) - { - if(result.length() > 0) - { - result.append(", "); - } - if(selectedParameterIndex == i) - { - info.selectedParameterStart = result.length(); - } - result.append(getSignatureForParameter(params[i], skipType)); - } - - info.text = result.toString(); - } - else - { - info.text = CodeInsightBundle.message("parameter.info.no.parameters"); - } - return info; - } - - public static String getSignatureForParameter(final JSParameter p, boolean skipType) - { - final String s = skipType ? null : p.getTypeString(); - - if(s != null && s.length() > 0) - { - final boolean ecmal4 = p.getContainingFile().getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4; - String result; - - if(ecmal4) - { - if(p.isRest()) - { - result = "..."; - } - else - { - result = p.getName() + ":" + s; - } - } - else - { - result = "[" + s + "] " + p.getName(); - } - final String initializerText = p.getInitializerText(); - if(initializerText != null) - { - result += " = " + initializerText; - } - return result; - } - return p.getName(); - } - - @Override - @Nonnull - public JSExpression[] getActualParameters(@Nonnull final JSArgumentList jsArgumentList) - { - return jsArgumentList.getArguments(); - } - - @Override - @Nonnull - public IElementType getActualParameterDelimiterType() - { - return JSTokenTypes.COMMA; - } - - @Override - @Nonnull - public IElementType getActualParametersRBraceType() - { - return JSTokenTypes.RBRACE; - } - - @Override - @Nonnull - public Set> getArgumentListAllowedParentClasses() - { - return ourArgumentListAllowedParentClassesSet; - } - - @Nonnull - @Override - public Set> getArgListStopSearchClasses() - { - return Collections.emptySet(); - } - - @Override - @Nonnull - public Class getArgumentListClass() - { - return JSArgumentList.class; - } - - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } +public class JSParameterInfoHandler implements ParameterInfoHandlerWithTabActionSupport { + private static final Set> ourArgumentListAllowedParentClassesSet = Set.of(JSCallExpression.class); + + @Override + public boolean couldShowInLookup() { + return true; + } + + @Override + public Object[] getParametersForLookup(LookupElement item, ParameterInfoContext context) { + if (!(item instanceof MutableLookupElement)) { + return null; + } + + PsiElement element = item.getPsiElement(); + if (element instanceof JSFunction) { + JSFunction originalFunction = (JSFunction)element; + List lookupItems = new ArrayList<>(); + Set availableSignatures = new HashSet<>(); + + for (PsiElement el : DefinitionsScopedSearch.search(originalFunction)) { + doAddSignature(lookupItems, availableSignatures, el); + } + + if (lookupItems.size() == 0) { + lookupItems.add(originalFunction); + } + + return lookupItems.toArray(new Object[lookupItems.size()]); + } + + return ArrayUtil.EMPTY_OBJECT_ARRAY; + } + + private static void doAddSignature(List lookupItems, Set availableSignatures, PsiElement el) { + if (el instanceof JSFunction function) { + JSParameterList parameterList = function.getParameterList(); + + if (parameterList != null) { + String typedSignature = buildSignature(parameterList.getParameters(), false, -1).text; + String untypedSignature = buildSignature(parameterList.getParameters(), true, -1).text; + + if (!availableSignatures.contains(typedSignature) && !availableSignatures.contains(untypedSignature)) { + lookupItems.add(function); + availableSignatures.add(typedSignature); + availableSignatures.add(untypedSignature); + } + } + } + } + + @Override + public JSArgumentList findElementForParameterInfo(CreateParameterInfoContext context) { + JSArgumentList argList = findArgumentList(context.getFile(), context.getOffset()); + + if (argList != null) { + return fillSignaturesForArgumentList(context, argList); + } + return argList; + } + + @Nullable + public static JSArgumentList findArgumentList(PsiFile file, int offset) { + JSArgumentList argList = ParameterInfoUtils.findParentOfType(file, offset, JSArgumentList.class); + if (argList == null) { + JSCallExpression callExpression = ParameterInfoUtils.findParentOfType(file, offset, JSCallExpression.class); + if (callExpression != null) { + argList = callExpression.getArgumentList(); + } + } + return argList; + } + + @Nullable + private static JSArgumentList fillSignaturesForArgumentList( + CreateParameterInfoContext context, + @Nonnull JSArgumentList argList + ) { + PsiElement psiElement = argList.getParent(); + if (!(psiElement instanceof JSCallExpression)) { + return null; + } + + JSCallExpression parent = (JSCallExpression)psiElement; + JSExpression methodExpression = parent.getMethodExpression(); + + if (methodExpression instanceof JSReferenceExpression referenceExpression) { + ResolveResult[] resolveResults = referenceExpression.multiResolve(true); + + if (resolveResults.length > 0) { + List items = new ArrayList(resolveResults.length); + Set availableSignatures = new HashSet(); + + for (ResolveResult r : resolveResults) { + PsiElement element = r.getElement(); + if (element instanceof JSProperty property) { + element = property.getValue(); + } + + doAddSignature(items, availableSignatures, element); + } + + context.setItemsToShow(ArrayUtil.toObjectArray(items)); + return argList; + } + } + else if (methodExpression instanceof JSSuperExpression) { + PsiElement clazz = methodExpression.getReference().resolve(); + if (clazz instanceof JSFunction) { + context.setItemsToShow(new Object[]{clazz}); + return argList; + } + } + return null; + } + + @Override + public void showParameterInfo(@Nonnull JSArgumentList element, CreateParameterInfoContext context) { + context.showHint(element, element.getTextOffset(), this); + } + + @Override + public JSArgumentList findElementForUpdatingParameterInfo(UpdateParameterInfoContext context) { + return findArgumentList(context.getFile(), context.getOffset()); + } + + @Override + public void updateParameterInfo(@Nonnull JSArgumentList o, UpdateParameterInfoContext context) { + if (context.getParameterOwner() != o) { + context.removeHint(); + return; + } + int currentParameterIndex = ParameterInfoUtils.getCurrentParameterIndex(o.getNode(), context.getOffset(), JSTokenTypes.COMMA); + context.setCurrentParameter(currentParameterIndex); + } + + @Override + public void updateUI(JSFunction p, ParameterInfoUIContext context) { + JSParameterList parameterList = p.getParameterList(); + JSParameter[] params = parameterList != null ? parameterList.getParameters() : new JSParameter[0]; + int currentParameterIndex = context.getCurrentParameterIndex() >= 0 ? context.getCurrentParameterIndex() : params.length; + JSParameter parameter = currentParameterIndex < params.length ? params[currentParameterIndex] : null; + + SignatureInfo signatureInfo = buildSignature(params, false, currentParameterIndex); + String name = signatureInfo.text; + + String currentParameterSignature = parameter != null ? getSignatureForParameter(parameter, false) : null; + int highlightStart = parameter != null ? signatureInfo.selectedParameterStart : 0; + int highlightEnd = parameter != null ? highlightStart + currentParameterSignature.length() : 0; + context.setupUIComponentPresentation(name, highlightStart, highlightEnd, false, false, false, context.getDefaultParameterColor()); + } + + private static class SignatureInfo { + String text; + int selectedParameterStart = -1; + } + + private static + @Nonnull + SignatureInfo buildSignature(JSParameter[] params, boolean skipType, int selectedParameterIndex) { + SignatureInfo info = new SignatureInfo(); + if (params.length > 0) { + StringBuilder result = new StringBuilder(); + for (int i = 0; i < params.length; ++i) { + if (result.length() > 0) { + result.append(", "); + } + if (selectedParameterIndex == i) { + info.selectedParameterStart = result.length(); + } + result.append(getSignatureForParameter(params[i], skipType)); + } + + info.text = result.toString(); + } + else { + info.text = CodeInsightLocalize.parameterInfoNoParameters().get(); + } + return info; + } + + public static String getSignatureForParameter(JSParameter p, boolean skipType) { + String s = skipType ? null : p.getTypeString(); + + if (s != null && s.length() > 0) { + boolean ecmal4 = p.getContainingFile().getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4; + String result; + + if (ecmal4) { + if (p.isRest()) { + result = "..."; + } + else { + result = p.getName() + ":" + s; + } + } + else { + result = "[" + s + "] " + p.getName(); + } + String initializerText = p.getInitializerText(); + if (initializerText != null) { + result += " = " + initializerText; + } + return result; + } + return p.getName(); + } + + @Override + @Nonnull + public JSExpression[] getActualParameters(@Nonnull JSArgumentList jsArgumentList) { + return jsArgumentList.getArguments(); + } + + @Override + @Nonnull + public IElementType getActualParameterDelimiterType() { + return JSTokenTypes.COMMA; + } + + @Override + @Nonnull + public IElementType getActualParametersRBraceType() { + return JSTokenTypes.RBRACE; + } + + @Override + @Nonnull + public Set> getArgumentListAllowedParentClasses() { + return ourArgumentListAllowedParentClassesSet; + } + + @Nonnull + @Override + public Set> getArgListStopSearchClasses() { + return Collections.emptySet(); + } + + @Override + @Nonnull + public Class getArgumentListClass() { + return JSArgumentList.class; + } + + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } } diff --git a/plugin/src/main/java/com/intellij/javascript/manipulators/JSAbstractElementManipulator.java b/plugin/src/main/java/com/intellij/javascript/manipulators/JSAbstractElementManipulator.java index b3b21f06..551e93c9 100644 --- a/plugin/src/main/java/com/intellij/javascript/manipulators/JSAbstractElementManipulator.java +++ b/plugin/src/main/java/com/intellij/javascript/manipulators/JSAbstractElementManipulator.java @@ -25,17 +25,15 @@ /** * @author peter */ -abstract class JSAbstractElementManipulator extends AbstractElementManipulator -{ - @Override - public T handleContentChange(final T element, final TextRange range, String newContent) throws IncorrectOperationException - { - String oldText = element.getText(); - newContent = StringUtil.escapeStringCharacters(newContent); - String newText = oldText.substring(0, range.getStartOffset()) + newContent + oldText.substring(range.getEndOffset()); +abstract class JSAbstractElementManipulator extends AbstractElementManipulator { + @Override + public T handleContentChange(T element, TextRange range, String newContent) throws IncorrectOperationException { + String oldText = element.getText(); + newContent = StringUtil.escapeStringCharacters(newContent); + String newText = oldText.substring(0, range.getStartOffset()) + newContent + oldText.substring(range.getEndOffset()); - return (T) element.replace(createTree(newText, element.getProject())); - } + return (T)element.replace(createTree(newText, element.getProject())); + } - protected abstract T createTree(final String newText, final Project project); + protected abstract T createTree(String newText, Project project); } diff --git a/plugin/src/main/java/com/intellij/javascript/manipulators/JSAttributeNameValuePairManipulator.java b/plugin/src/main/java/com/intellij/javascript/manipulators/JSAttributeNameValuePairManipulator.java index 5ec6c534..463eb7b7 100644 --- a/plugin/src/main/java/com/intellij/javascript/manipulators/JSAttributeNameValuePairManipulator.java +++ b/plugin/src/main/java/com/intellij/javascript/manipulators/JSAttributeNameValuePairManipulator.java @@ -23,26 +23,23 @@ import com.intellij.lang.javascript.psi.impl.JSChangeUtil; import consulo.project.Project; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author peter */ @ExtensionImpl -public class JSAttributeNameValuePairManipulator extends JSAbstractElementManipulator -{ - @Override - protected JSAttributeNameValuePair createTree(final String newText, final Project project) - { - @NonNls String ToCreate = "[A(" + newText + ")] class C {}"; - final PsiElement element = JSChangeUtil.createStatementFromText(project, ToCreate).getPsi(); - return ((JSClass) element).getAttributeList().getAttributes()[0].getValues()[0]; - } +public class JSAttributeNameValuePairManipulator extends JSAbstractElementManipulator { + @Override + protected JSAttributeNameValuePair createTree(String newText, Project project) { + @NonNls String ToCreate = "[A(" + newText + ")] class C {}"; + PsiElement element = JSChangeUtil.createStatementFromText(project, ToCreate).getPsi(); + return ((JSClass)element).getAttributeList().getAttributes()[0].getValues()[0]; + } - @Nonnull - @Override - public Class getElementClass() - { - return JSAttributeNameValuePair.class; - } + @Nonnull + @Override + public Class getElementClass() { + return JSAttributeNameValuePair.class; + } } diff --git a/plugin/src/main/java/com/intellij/javascript/manipulators/JSDocTagManipulator.java b/plugin/src/main/java/com/intellij/javascript/manipulators/JSDocTagManipulator.java index 8bf64619..21cb5543 100644 --- a/plugin/src/main/java/com/intellij/javascript/manipulators/JSDocTagManipulator.java +++ b/plugin/src/main/java/com/intellij/javascript/manipulators/JSDocTagManipulator.java @@ -21,24 +21,20 @@ import consulo.annotation.component.ExtensionImpl; import consulo.language.psi.PsiElement; import consulo.project.Project; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; @ExtensionImpl -public class JSDocTagManipulator extends JSAbstractElementManipulator -{ - @Override - protected JSDocTag createTree(final String newText, final Project project) - { - String ToCreate = "/** " + newText + " */"; - final PsiElement element = JSChangeUtil.createJSTreeFromText(project, ToCreate).getPsi(); - return ((JSDocComment) element).getTags()[0]; - } +public class JSDocTagManipulator extends JSAbstractElementManipulator { + @Override + protected JSDocTag createTree(String newText, Project project) { + String ToCreate = "/** " + newText + " */"; + PsiElement element = JSChangeUtil.createJSTreeFromText(project, ToCreate).getPsi(); + return ((JSDocComment)element).getTags()[0]; + } - @Nonnull - @Override - public Class getElementClass() - { - return JSDocTag.class; - } + @Nonnull + @Override + public Class getElementClass() { + return JSDocTag.class; + } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/javascript/manipulators/JSIncludeDirectiveManipulator.java b/plugin/src/main/java/com/intellij/javascript/manipulators/JSIncludeDirectiveManipulator.java index f9a9f2da..a66bc687 100644 --- a/plugin/src/main/java/com/intellij/javascript/manipulators/JSIncludeDirectiveManipulator.java +++ b/plugin/src/main/java/com/intellij/javascript/manipulators/JSIncludeDirectiveManipulator.java @@ -20,24 +20,21 @@ import consulo.annotation.component.ExtensionImpl; import consulo.project.Project; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author peter */ @ExtensionImpl -public class JSIncludeDirectiveManipulator extends JSAbstractElementManipulator -{ - @Override - protected JSIncludeDirectiveImpl createTree(final String newText, final Project project) - { - return (JSIncludeDirectiveImpl) JSChangeUtil.createStatementFromText(project, newText).getPsi(); - } +public class JSIncludeDirectiveManipulator extends JSAbstractElementManipulator { + @Override + protected JSIncludeDirectiveImpl createTree(String newText, Project project) { + return (JSIncludeDirectiveImpl)JSChangeUtil.createStatementFromText(project, newText).getPsi(); + } - @Nonnull - @Override - public Class getElementClass() - { - return JSIncludeDirectiveImpl.class; - } + @Nonnull + @Override + public Class getElementClass() { + return JSIncludeDirectiveImpl.class; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/JSNodeVisitor.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/JSNodeVisitor.java index b9c93c9d..7e03efd3 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/JSNodeVisitor.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/JSNodeVisitor.java @@ -23,485 +23,375 @@ import consulo.language.ast.IElementType; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Feb 1, 2005 - * Time: 7:13:40 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-02-01 */ -public abstract class JSNodeVisitor -{ - public final void visit(ASTNode node) - { - final IElementType type = node.getElementType(); - if(type instanceof JSFileElementType) - { - visitFile(node); - } - else if(type == JSElementTypes.FUNCTION_DECLARATION) - { - visitFunctionDeclaration(node); - } - else if(type == JSElementTypes.PARAMETER_LIST) - { - visitParameterList(node); - } - else if(type == JSElementTypes.VARIABLE) - { - visitVariable(node); - } - else if(type == JSElementTypes.FORMAL_PARAMETER) - { - visitParameter(node); - } - else if(type == JSElementTypes.ARGUMENT_LIST) - { - visitArgumentList(node); - } - else if(type == JSElementTypes.BLOCK_STATEMENT) - { - visitBlock(node); - } - else if(type == JSElementTypes.LABELED_STATEMENT) - { - visitLabeledStatement(node); - } - else if(type == JSElementTypes.EXPRESSION_STATEMENT) - { - visitExpressionStatement(node); - } - else if(type == JSElementTypes.VAR_STATEMENT) - { - visitVarStatement(node); - } - else if(type == JSElementTypes.EMPTY_STATEMENT) - { - visitEmptyStatement(node); - } - else if(type == JSElementTypes.IF_STATEMENT) - { - visitIfStatement(node); - } - else if(type == JSElementTypes.CONTINUE_STATEMENT) - { - visitContinueStatement(node); - } - else if(type == JSElementTypes.BREAK_STATEMENT) - { - visitBreakStatement(node); - } - else if(type == JSElementTypes.WITH_STATEMENT) - { - visitWithStatement(node); - } - else if(type == JSElementTypes.RETURN_STATEMENT) - { - visitReturnStatement(node); - } - else if(type == JSElementTypes.THROW_STATEMENT) - { - visitThrowStatement(node); - } - else if(type == JSElementTypes.TRY_STATEMENT) - { - visitTryStatement(node); - } - else if(type == JSElementTypes.CATCH_BLOCK) - { - visitCatchBlock(node); - } - else if(type == JSElementTypes.SWITCH_STATEMENT) - { - visitSwitchStatement(node); - } - else if(type == JSElementTypes.CASE_CLAUSE) - { - visitCaseClause(node); - } - else if(type == JSElementTypes.WHILE_STATEMENT) - { - visitWhileStatement(node); - } - else if(type == JSElementTypes.DOWHILE_STATEMENT) - { - visitDoWhileStatement(node); - } - else if(type == JSElementTypes.FOR_STATEMENT) - { - visitForStatement(node); - } - else if(type == JSElementTypes.FOR_IN_STATEMENT) - { - visitForInStatement(node); - } - else if(type == JSElementTypes.THIS_EXPRESSION) - { - visitThisExpression(node); - } - else if(type == JSElementTypes.LITERAL_EXPRESSION) - { - visitLiteralExpression(node); - } - else if(type == JSElementTypes.REGEXP_LITERAL_EXPRESSION) - { - visitLiteralExpression(node); - } - else if(type == JSElementTypes.REFERENCE_EXPRESSION) - { - visitReferenceExpression(node); - } - else if(type == JSElementTypes.PARENTHESIZED_EXPRESSION) - { - visitParenthesizedExpression(node); - } - else if(type == JSElementTypes.ARRAY_LITERAL_EXPRESSION) - { - visitArrayLiteralExpression(node); - } - else if(type == JSElementTypes.OBJECT_LITERAL_EXPRESSION) - { - visitObjectLiteralExpression(node); - } - else if(type == JSElementTypes.PROPERTY) - { - visitProperty(node); - } - else if(type == JSElementTypes.BINARY_EXPRESSION) - { - visitBinaryExpression(node); - } - else if(type == JSElementTypes.ASSIGNMENT_EXPRESSION) - { - visitAssignmentExpression(node); - } - else if(type == JSElementTypes.COMMA_EXPRESSION) - { - visitCommaExpression(node); - } - else if(type == JSElementTypes.CONDITIONAL_EXPRESSION) - { - visitConditionalExpression(node); - } - else if(type == JSElementTypes.POSTFIX_EXPRESSION) - { - visitPostfixExpression(node); - } - else if(type == JSElementTypes.PREFIX_EXPRESSION) - { - visitPrefixExpression(node); - } - else if(type == JSElementTypes.FUNCTION_EXPRESSION) - { - visitFunctionExpression(node); - } - else if(type == JSElementTypes.NEW_EXPRESSION) - { - visitNewExpression(node); - } - else if(type == JSElementTypes.INDEXED_PROPERTY_ACCESS_EXPRESSION) - { - visitIndexedPropertyAccessExpression(node); - } - else if(type == JSElementTypes.ATTRIBUTE_LIST) - { - visitAttributeList(node); - } - else if(type == JSElementTypes.CALL_EXPRESSION) - { - visitCallExpression(node); - } - else if(type == JSTokenTypes.C_STYLE_COMMENT) - { - visitComment(node); - } - else if(type == JSTokenTypes.DOC_COMMENT) - { - visitDocComment(node); - } - else if(type == JSElementTypes.EMBEDDED_CONTENT) - { - visitEmbeddedContent(node); - } - else if(type == JSElementTypes.PACKAGE_STATEMENT) - { - visitPackageStatement(node); - } - else if(type == JSElementTypes.CLASS) - { - visitClass(node); - } - else if(type == JSElementTypes.XML_LITERAL_EXPRESSION) - { - visitXmlLiteralExpression(node); - } - else - { - visitElement(node); - } - } - - public void visitXmlLiteralExpression(ASTNode node) - { - visitExpression(node); - } - - public void visitAttributeList(final ASTNode node) - { - visitElement(node); - } - - public void visitPackageStatement(final ASTNode node) - { - visitElement(node); - } - - public void visitClass(final ASTNode node) - { - visitElement(node); - } - - public void visitFile(final ASTNode node) - { - visitElement(node); - } - - public void visitCallExpression(final ASTNode node) - { - visitExpression(node); - } - - public void visitIndexedPropertyAccessExpression(final ASTNode node) - { - visitExpression(node); - } - - public void visitNewExpression(final ASTNode node) - { - visitExpression(node); - } - - public void visitFunctionExpression(final ASTNode node) - { - visitExpression(node); - } - - public void visitPrefixExpression(final ASTNode node) - { - visitExpression(node); - } - - public void visitPostfixExpression(final ASTNode node) - { - visitExpression(node); - } - - public void visitConditionalExpression(final ASTNode node) - { - visitExpression(node); - } - - public void visitCommaExpression(final ASTNode node) - { - visitBinaryExpression(node); - } - - public void visitAssignmentExpression(final ASTNode node) - { - visitBinaryExpression(node); - } - - public void visitBinaryExpression(final ASTNode node) - { - visitExpression(node); - } - - public void visitProperty(final ASTNode node) - { - visitElement(node); - } - - public void visitObjectLiteralExpression(final ASTNode node) - { - visitExpression(node); - } - - public void visitArrayLiteralExpression(final ASTNode node) - { - visitExpression(node); - } - - public void visitParenthesizedExpression(final ASTNode node) - { - visitExpression(node); - } - - public void visitReferenceExpression(final ASTNode node) - { - visitExpression(node); - } - - public void visitLiteralExpression(final ASTNode node) - { - visitExpression(node); - } - - public void visitThisExpression(final ASTNode node) - { - visitExpression(node); - } - - public void visitForInStatement(final ASTNode node) - { - visitStatement(node); - } - - public void visitForStatement(final ASTNode node) - { - visitStatement(node); - } - - public void visitDoWhileStatement(final ASTNode node) - { - visitStatement(node); - } - - public void visitWhileStatement(final ASTNode node) - { - visitStatement(node); - } - - public void visitCaseClause(final ASTNode node) - { - visitElement(node); - } - - public void visitSwitchStatement(final ASTNode node) - { - visitStatement(node); - } - - public void visitCatchBlock(final ASTNode node) - { - visitElement(node); - } - - public void visitTryStatement(final ASTNode node) - { - visitStatement(node); - } - - public void visitThrowStatement(final ASTNode node) - { - visitStatement(node); - } - - public void visitReturnStatement(final ASTNode node) - { - visitStatement(node); - } - - public void visitWithStatement(final ASTNode node) - { - visitStatement(node); - } - - public void visitBreakStatement(final ASTNode node) - { - visitStatement(node); - } - - public void visitContinueStatement(final ASTNode node) - { - visitStatement(node); - } - - public void visitIfStatement(final ASTNode node) - { - visitStatement(node); - } - - public void visitEmptyStatement(final ASTNode node) - { - visitStatement(node); - } - - public void visitVarStatement(final ASTNode node) - { - visitStatement(node); - } - - public void visitExpressionStatement(final ASTNode node) - { - visitStatement(node); - } - - public void visitLabeledStatement(final ASTNode node) - { - visitStatement(node); - } - - public void visitBlock(final ASTNode node) - { - visitStatement(node); - } - - public void visitArgumentList(final ASTNode node) - { - visitElement(node); - } - - public void visitParameter(final ASTNode node) - { - visitVariable(node); - } - - public void visitVariable(final ASTNode node) - { - visitElement(node); - } - - public void visitParameterList(final ASTNode node) - { - visitElement(node); - } - - public void visitEmbeddedContent(final ASTNode node) - { - visitElement(node); - } - - public void visitElement(final ASTNode node) - { - - } - - public void visitSourceElement(final ASTNode node) - { - visitElement(node); - } - - public void visitFunctionDeclaration(final ASTNode node) - { - visitSourceElement(node); - } - - public void visitStatement(final ASTNode node) - { - visitSourceElement(node); - } - - public void visitExpression(final ASTNode node) - { - visitElement(node); - } - - public void visitDocComment(final ASTNode node) - { - visitElement(node); - } - - public void visitComment(final ASTNode node) - { - visitElement(node); - } +public abstract class JSNodeVisitor { + public final void visit(ASTNode node) { + IElementType type = node.getElementType(); + if (type instanceof JSFileElementType) { + visitFile(node); + } + else if (type == JSElementTypes.FUNCTION_DECLARATION) { + visitFunctionDeclaration(node); + } + else if (type == JSElementTypes.PARAMETER_LIST) { + visitParameterList(node); + } + else if (type == JSElementTypes.VARIABLE) { + visitVariable(node); + } + else if (type == JSElementTypes.FORMAL_PARAMETER) { + visitParameter(node); + } + else if (type == JSElementTypes.ARGUMENT_LIST) { + visitArgumentList(node); + } + else if (type == JSElementTypes.BLOCK_STATEMENT) { + visitBlock(node); + } + else if (type == JSElementTypes.LABELED_STATEMENT) { + visitLabeledStatement(node); + } + else if (type == JSElementTypes.EXPRESSION_STATEMENT) { + visitExpressionStatement(node); + } + else if (type == JSElementTypes.VAR_STATEMENT) { + visitVarStatement(node); + } + else if (type == JSElementTypes.EMPTY_STATEMENT) { + visitEmptyStatement(node); + } + else if (type == JSElementTypes.IF_STATEMENT) { + visitIfStatement(node); + } + else if (type == JSElementTypes.CONTINUE_STATEMENT) { + visitContinueStatement(node); + } + else if (type == JSElementTypes.BREAK_STATEMENT) { + visitBreakStatement(node); + } + else if (type == JSElementTypes.WITH_STATEMENT) { + visitWithStatement(node); + } + else if (type == JSElementTypes.RETURN_STATEMENT) { + visitReturnStatement(node); + } + else if (type == JSElementTypes.THROW_STATEMENT) { + visitThrowStatement(node); + } + else if (type == JSElementTypes.TRY_STATEMENT) { + visitTryStatement(node); + } + else if (type == JSElementTypes.CATCH_BLOCK) { + visitCatchBlock(node); + } + else if (type == JSElementTypes.SWITCH_STATEMENT) { + visitSwitchStatement(node); + } + else if (type == JSElementTypes.CASE_CLAUSE) { + visitCaseClause(node); + } + else if (type == JSElementTypes.WHILE_STATEMENT) { + visitWhileStatement(node); + } + else if (type == JSElementTypes.DOWHILE_STATEMENT) { + visitDoWhileStatement(node); + } + else if (type == JSElementTypes.FOR_STATEMENT) { + visitForStatement(node); + } + else if (type == JSElementTypes.FOR_IN_STATEMENT) { + visitForInStatement(node); + } + else if (type == JSElementTypes.THIS_EXPRESSION) { + visitThisExpression(node); + } + else if (type == JSElementTypes.LITERAL_EXPRESSION) { + visitLiteralExpression(node); + } + else if (type == JSElementTypes.REGEXP_LITERAL_EXPRESSION) { + visitLiteralExpression(node); + } + else if (type == JSElementTypes.REFERENCE_EXPRESSION) { + visitReferenceExpression(node); + } + else if (type == JSElementTypes.PARENTHESIZED_EXPRESSION) { + visitParenthesizedExpression(node); + } + else if (type == JSElementTypes.ARRAY_LITERAL_EXPRESSION) { + visitArrayLiteralExpression(node); + } + else if (type == JSElementTypes.OBJECT_LITERAL_EXPRESSION) { + visitObjectLiteralExpression(node); + } + else if (type == JSElementTypes.PROPERTY) { + visitProperty(node); + } + else if (type == JSElementTypes.BINARY_EXPRESSION) { + visitBinaryExpression(node); + } + else if (type == JSElementTypes.ASSIGNMENT_EXPRESSION) { + visitAssignmentExpression(node); + } + else if (type == JSElementTypes.COMMA_EXPRESSION) { + visitCommaExpression(node); + } + else if (type == JSElementTypes.CONDITIONAL_EXPRESSION) { + visitConditionalExpression(node); + } + else if (type == JSElementTypes.POSTFIX_EXPRESSION) { + visitPostfixExpression(node); + } + else if (type == JSElementTypes.PREFIX_EXPRESSION) { + visitPrefixExpression(node); + } + else if (type == JSElementTypes.FUNCTION_EXPRESSION) { + visitFunctionExpression(node); + } + else if (type == JSElementTypes.NEW_EXPRESSION) { + visitNewExpression(node); + } + else if (type == JSElementTypes.INDEXED_PROPERTY_ACCESS_EXPRESSION) { + visitIndexedPropertyAccessExpression(node); + } + else if (type == JSElementTypes.ATTRIBUTE_LIST) { + visitAttributeList(node); + } + else if (type == JSElementTypes.CALL_EXPRESSION) { + visitCallExpression(node); + } + else if (type == JSTokenTypes.C_STYLE_COMMENT) { + visitComment(node); + } + else if (type == JSTokenTypes.DOC_COMMENT) { + visitDocComment(node); + } + else if (type == JSElementTypes.EMBEDDED_CONTENT) { + visitEmbeddedContent(node); + } + else if (type == JSElementTypes.PACKAGE_STATEMENT) { + visitPackageStatement(node); + } + else if (type == JSElementTypes.CLASS) { + visitClass(node); + } + else if (type == JSElementTypes.XML_LITERAL_EXPRESSION) { + visitXmlLiteralExpression(node); + } + else { + visitElement(node); + } + } + + public void visitXmlLiteralExpression(ASTNode node) { + visitExpression(node); + } + + public void visitAttributeList(ASTNode node) { + visitElement(node); + } + + public void visitPackageStatement(ASTNode node) { + visitElement(node); + } + + public void visitClass(ASTNode node) { + visitElement(node); + } + + public void visitFile(ASTNode node) { + visitElement(node); + } + + public void visitCallExpression(ASTNode node) { + visitExpression(node); + } + + public void visitIndexedPropertyAccessExpression(ASTNode node) { + visitExpression(node); + } + + public void visitNewExpression(ASTNode node) { + visitExpression(node); + } + + public void visitFunctionExpression(ASTNode node) { + visitExpression(node); + } + + public void visitPrefixExpression(ASTNode node) { + visitExpression(node); + } + + public void visitPostfixExpression(ASTNode node) { + visitExpression(node); + } + + public void visitConditionalExpression(ASTNode node) { + visitExpression(node); + } + + public void visitCommaExpression(ASTNode node) { + visitBinaryExpression(node); + } + + public void visitAssignmentExpression(ASTNode node) { + visitBinaryExpression(node); + } + + public void visitBinaryExpression(ASTNode node) { + visitExpression(node); + } + + public void visitProperty(ASTNode node) { + visitElement(node); + } + + public void visitObjectLiteralExpression(ASTNode node) { + visitExpression(node); + } + + public void visitArrayLiteralExpression(ASTNode node) { + visitExpression(node); + } + + public void visitParenthesizedExpression(ASTNode node) { + visitExpression(node); + } + + public void visitReferenceExpression(ASTNode node) { + visitExpression(node); + } + + public void visitLiteralExpression(ASTNode node) { + visitExpression(node); + } + + public void visitThisExpression(ASTNode node) { + visitExpression(node); + } + + public void visitForInStatement(ASTNode node) { + visitStatement(node); + } + + public void visitForStatement(ASTNode node) { + visitStatement(node); + } + + public void visitDoWhileStatement(ASTNode node) { + visitStatement(node); + } + + public void visitWhileStatement(ASTNode node) { + visitStatement(node); + } + + public void visitCaseClause(ASTNode node) { + visitElement(node); + } + + public void visitSwitchStatement(ASTNode node) { + visitStatement(node); + } + + public void visitCatchBlock(ASTNode node) { + visitElement(node); + } + + public void visitTryStatement(ASTNode node) { + visitStatement(node); + } + + public void visitThrowStatement(ASTNode node) { + visitStatement(node); + } + + public void visitReturnStatement(ASTNode node) { + visitStatement(node); + } + + public void visitWithStatement(ASTNode node) { + visitStatement(node); + } + + public void visitBreakStatement(ASTNode node) { + visitStatement(node); + } + + public void visitContinueStatement(ASTNode node) { + visitStatement(node); + } + + public void visitIfStatement(ASTNode node) { + visitStatement(node); + } + + public void visitEmptyStatement(ASTNode node) { + visitStatement(node); + } + + public void visitVarStatement(ASTNode node) { + visitStatement(node); + } + + public void visitExpressionStatement(ASTNode node) { + visitStatement(node); + } + + public void visitLabeledStatement(ASTNode node) { + visitStatement(node); + } + + public void visitBlock(ASTNode node) { + visitStatement(node); + } + + public void visitArgumentList(ASTNode node) { + visitElement(node); + } + + public void visitParameter(ASTNode node) { + visitVariable(node); + } + + public void visitVariable(ASTNode node) { + visitElement(node); + } + + public void visitParameterList(ASTNode node) { + visitElement(node); + } + + public void visitEmbeddedContent(ASTNode node) { + visitElement(node); + } + + public void visitElement(ASTNode node) { + } + + public void visitSourceElement(ASTNode node) { + visitElement(node); + } + + public void visitFunctionDeclaration(ASTNode node) { + visitSourceElement(node); + } + + public void visitStatement(ASTNode node) { + visitSourceElement(node); + } + + public void visitExpression(ASTNode node) { + visitElement(node); + } + + public void visitDocComment(ASTNode node) { + visitElement(node); + } + + public void visitComment(ASTNode node) { + visitElement(node); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/JSSmartEnterProcessor.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/JSSmartEnterProcessor.java index af445809..a318e0db 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/JSSmartEnterProcessor.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/JSSmartEnterProcessor.java @@ -20,159 +20,148 @@ import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.impl.JSChangeUtil; import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.annotation.component.ExtensionImpl; import consulo.codeEditor.Editor; import consulo.javascript.language.JavaScriptLanguage; -import consulo.javascript.language.JavaScriptBundle; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.Language; import consulo.language.codeStyle.CodeStyleManager; import consulo.language.editor.action.SmartEnterProcessor; import consulo.language.psi.*; import consulo.language.psi.util.PsiTreeUtil; +import consulo.localize.LocalizeValue; import consulo.project.Project; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author Maxim.Mossienko - * Date: Jul 25, 2008 - * Time: 11:38:15 PM + * @since 2008-07-25 */ @ExtensionImpl -public class JSSmartEnterProcessor extends SmartEnterProcessor -{ - @Override - @RequiredReadAction - public boolean process(@Nonnull final Project project, @Nonnull final Editor editor, @Nonnull final PsiFile psiFile) - { - int offset = editor.getCaretModel().getOffset(); - PsiElement at = psiFile.findElementAt(offset); - if(at == null && offset > 0) - { - at = psiFile.findElementAt(offset - 1); - } - if(at == null) - { - return false; - } - - PsiElement element = at instanceof PsiWhiteSpace ? PsiTreeUtil.prevLeaf(at) : at; - - if(element != null && !(element instanceof PsiErrorElement)) - { - final PsiElement nextMeaningfulElement = evalMeaningfulElement(at, true); - if(nextMeaningfulElement instanceof PsiErrorElement) - { - element = nextMeaningfulElement; - offset = element.getTextOffset(); - } - } - - JSStatement statement = PsiTreeUtil.getParentOfType(element, JSStatement.class); - - if(!(element instanceof PsiErrorElement) && statement != null && statement.getLastChild().getNode().getElementType() != JSTokenTypes.SEMICOLON) - { - offset = statement.getTextRange().getEndOffset(); - String semicolon = JSChangeUtil.getSemicolon(project); - int shiftOffset = semicolon.length(); - - if(element.getParent() instanceof JSReferenceExpression && PsiTreeUtil.lastChild(statement).getNode().getElementType() != JSTokenTypes.RPAR) - { - ResolveResult[] results = ((JSReferenceExpression) element.getParent()).multiResolve(true); - - if(results.length > 0) - { - if(results[0].getElement() instanceof JSFunction) - { - semicolon = "()" + semicolon; - shiftOffset = semicolon.length(); - - if(((JSFunction) results[0].getElement()).getParameterList().getParameters().length > 0) - { - shiftOffset = 1; - } - } - } - } - if(!semicolon.isEmpty()) - { - insertCommitReformat(project, editor, psiFile, offset, semicolon, shiftOffset, false); - return true; - } - } - - final PsiElement prevMeaningfulElement = evalMeaningfulElement(element, false); - String errorDescription = null; - if(element != null && !(element instanceof PsiErrorElement) && prevMeaningfulElement != null) - { - element = prevMeaningfulElement; - } - - if(element instanceof PsiErrorElement && (JavaScriptBundle.message("javascript.parser.message.expected.lbrace").equals(errorDescription = ( - (PsiErrorElement) element).getErrorDescription()) || JavaScriptBundle.message("javascript.parser.message.expected.statement").equals(errorDescription))) - { - String semicolon = ""; - - if(element.getParent() instanceof JSFunctionExpression) - { - final JSElement base = PsiTreeUtil.getParentOfType(element, JSArgumentList.class, JSIndexedPropertyAccessExpression.class, JSStatement.class); - if(base instanceof JSStatement && base.getLastChild().getNode().getElementType() != JSTokenTypes.SEMICOLON) - { - semicolon = JSChangeUtil.getSemicolon(project); - } - } - insertCommitReformat(project, editor, psiFile, offset, "{\n\n}" + semicolon, 2, true); - return true; - } - else if(JavaScriptBundle.message("javascript.parser.message.expected.lparen").equals(errorDescription) || JavaScriptBundle.message("javascript.parser.message" + - ".expected.function.name").equals(errorDescription)) - { - insertCommitReformat(project, editor, psiFile, offset, "()", 1, false); - return true; - } - return false; - } - - @RequiredReadAction - private void insertCommitReformat(final Project project, final Editor editor, final PsiFile psiFile, final int offset, final String str, - final int shiftOffset, boolean adjustLineIndent) - { - editor.getDocument().insertString(offset, str); - editor.getCaretModel().moveToOffset(offset + shiftOffset); - commit(editor); - - PsiElement at = psiFile.findElementAt(offset + shiftOffset - 1); - final PsiElement parentOfType = PsiTreeUtil.getParentOfType(at, JSStatement.class, JSFunction.class, JSClass.class, JSFile.class); - - reformat(parentOfType); - if(adjustLineIndent) - { - CodeStyleManager.getInstance(project).adjustLineIndent(psiFile, editor.getCaretModel().getOffset()); - } - } - - private static PsiElement evalMeaningfulElement(final PsiElement element, boolean forward) - { - if(element == null) - { - return null; - } - PsiElement prev = forward ? PsiTreeUtil.nextLeaf(element) : PsiTreeUtil.prevLeaf(element); - if(prev == null) - { - return null; - } - if(prev instanceof PsiWhiteSpace) - { - prev = forward ? PsiTreeUtil.nextLeaf(prev) : PsiTreeUtil.prevLeaf(prev); - } - return prev; - } - - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } +public class JSSmartEnterProcessor extends SmartEnterProcessor { + @Override + @RequiredWriteAction + public boolean process(@Nonnull Project project, @Nonnull Editor editor, @Nonnull PsiFile psiFile) { + int offset = editor.getCaretModel().getOffset(); + PsiElement at = psiFile.findElementAt(offset); + if (at == null && offset > 0) { + at = psiFile.findElementAt(offset - 1); + } + if (at == null) { + return false; + } + + PsiElement element = at instanceof PsiWhiteSpace whiteSpace ? PsiTreeUtil.prevLeaf(whiteSpace) : at; + + if (element != null && !(element instanceof PsiErrorElement)) { + PsiElement nextMeaningfulElement = evalMeaningfulElement(at, true); + if (nextMeaningfulElement instanceof PsiErrorElement errorElement) { + element = errorElement; + offset = errorElement.getTextOffset(); + } + } + + JSStatement statement = PsiTreeUtil.getParentOfType(element, JSStatement.class); + + if (!(element instanceof PsiErrorElement) && statement != null + && statement.getLastChild().getNode().getElementType() != JSTokenTypes.SEMICOLON) { + offset = statement.getTextRange().getEndOffset(); + String semicolon = JSChangeUtil.getSemicolon(project); + int shiftOffset = semicolon.length(); + + if (element.getParent() instanceof JSReferenceExpression refExpr + && PsiTreeUtil.lastChild(statement).getNode().getElementType() != JSTokenTypes.RPAR) { + ResolveResult[] results = refExpr.multiResolve(true); + + if (results.length > 0 && results[0].getElement() instanceof JSFunction function) { + semicolon = "()" + semicolon; + shiftOffset = semicolon.length(); + + if (function.getParameterList().getParameters().length > 0) { + shiftOffset = 1; + } + } + } + if (!semicolon.isEmpty()) { + insertCommitReformat(project, editor, psiFile, offset, semicolon, shiftOffset, false); + return true; + } + } + + PsiElement prevMeaningfulElement = evalMeaningfulElement(element, false); + if (element != null && !(element instanceof PsiErrorElement) && prevMeaningfulElement != null) { + element = prevMeaningfulElement; + } + + LocalizeValue errorDescription = element instanceof PsiErrorElement errorElement ? errorElement.getErrorDescriptionValue() : null; + if (JavaScriptLocalize.javascriptParserMessageExpectedLbrace().equals(errorDescription) + || JavaScriptLocalize.javascriptParserMessageExpectedStatement().equals(errorDescription)) { + String semicolon = ""; + + if (element.getParent() instanceof JSFunctionExpression) { + @SuppressWarnings("unchecked") + JSElement base = + PsiTreeUtil.getParentOfType(element, JSArgumentList.class, JSIndexedPropertyAccessExpression.class, JSStatement.class); + if (base instanceof JSStatement baseStatement + && baseStatement.getLastChild().getNode().getElementType() != JSTokenTypes.SEMICOLON) { + semicolon = JSChangeUtil.getSemicolon(project); + } + } + insertCommitReformat(project, editor, psiFile, offset, "{\n\n}" + semicolon, 2, true); + return true; + } + else if (JavaScriptLocalize.javascriptParserMessageExpectedLparen().equals(errorDescription) + || JavaScriptLocalize.javascriptParserMessageExpectedFunctionName().equals(errorDescription)) { + insertCommitReformat(project, editor, psiFile, offset, "()", 1, false); + return true; + } + return false; + } + + @RequiredWriteAction + private void insertCommitReformat( + Project project, + Editor editor, + PsiFile psiFile, + int offset, + String str, + int shiftOffset, + boolean adjustLineIndent + ) { + editor.getDocument().insertString(offset, str); + editor.getCaretModel().moveToOffset(offset + shiftOffset); + commit(editor); + + PsiElement at = psiFile.findElementAt(offset + shiftOffset - 1); + @SuppressWarnings("unchecked") + PsiElement parentOfType = PsiTreeUtil.getParentOfType(at, JSStatement.class, JSFunction.class, JSClass.class, JSFile.class); + + reformat(parentOfType); + if (adjustLineIndent) { + CodeStyleManager.getInstance(project).adjustLineIndent(psiFile, editor.getCaretModel().getOffset()); + } + } + + @RequiredReadAction + private static PsiElement evalMeaningfulElement(PsiElement element, boolean forward) { + if (element == null) { + return null; + } + PsiElement prev = forward ? PsiTreeUtil.nextLeaf(element) : PsiTreeUtil.prevLeaf(element); + if (prev == null) { + return null; + } + if (prev instanceof PsiWhiteSpace) { + prev = forward ? PsiTreeUtil.nextLeaf(prev) : PsiTreeUtil.prevLeaf(prev); + } + return prev; + } + + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/JavaScriptCodeContextType.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/JavaScriptCodeContextType.java index 5f1aecc6..3a6aa70e 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/JavaScriptCodeContextType.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/JavaScriptCodeContextType.java @@ -19,84 +19,74 @@ import com.intellij.lang.javascript.JavaScriptSupportLoader; import com.intellij.lang.javascript.psi.JSFile; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; import consulo.javascript.language.JavaScriptLanguage; -import consulo.javascript.language.JavaScriptBundle; -import consulo.javascript.language.JavaScriptFileType; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.Language; import consulo.language.editor.highlight.SyntaxHighlighter; import consulo.language.editor.highlight.SyntaxHighlighterFactory; -import consulo.language.editor.template.context.TemplateContextType; +import consulo.language.editor.template.context.BaseTemplateContextType; +import consulo.language.editor.template.context.TemplateActionContext; import consulo.language.inject.InjectedLanguageManager; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiFile; import consulo.language.psi.PsiLanguageInjectionHost; import consulo.language.psi.util.PsiTreeUtil; -import consulo.util.lang.ref.Ref; -import consulo.virtualFileSystem.fileType.FileType; +import consulo.util.lang.ref.SimpleReference; import consulo.xml.lang.xml.XMLLanguage; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author Maxim.Mossienko - * Date: Apr 14, 2008 - * Time: 6:01:09 PM + * @since 2008-04-14 */ @ExtensionImpl -public class JavaScriptCodeContextType extends TemplateContextType -{ - private static final String JAVA_SCRIPT = "JAVA_SCRIPT"; +public class JavaScriptCodeContextType extends BaseTemplateContextType { + private static final String JAVA_SCRIPT = "JAVA_SCRIPT"; - public JavaScriptCodeContextType() - { - super(JAVA_SCRIPT, JavaScriptBundle.message("javascript.template.context.type")); - } + public JavaScriptCodeContextType() { + super(JAVA_SCRIPT, JavaScriptLocalize.javascriptTemplateContextType()); + } - @Override - public boolean isInContext(@Nonnull final PsiFile file, final int offset) - { - PsiElement at = file.findElementAt(offset); - if(at == null && offset == file.getTextLength()) - { - at = file.findElementAt(offset - 1); - } - Language language = at != null ? at.getParent().getLanguage() : null; + @Override + @RequiredReadAction + public boolean isInContext(@Nonnull TemplateActionContext context) { + PsiFile file = context.getFile(); + int offset = context.getStartOffset(); - if(language instanceof XMLLanguage) - { - final PsiLanguageInjectionHost host = PsiTreeUtil.getParentOfType(at, PsiLanguageInjectionHost.class, false); + PsiElement at = file.findElementAt(offset); + if (at == null && offset == file.getTextLength()) { + at = file.findElementAt(offset - 1); + } + Language language = at != null ? at.getParent().getLanguage() : null; - if(host != null) - { - final Ref hasJsInjection = new Ref(Boolean.FALSE); + if (language instanceof XMLLanguage) { + PsiLanguageInjectionHost host = PsiTreeUtil.getParentOfType(at, PsiLanguageInjectionHost.class, false); - InjectedLanguageManager.getInstance(at.getProject()).enumerate(host, new JSResolveUtil.JSInjectedFilesVisitor() - { - @Override - protected void process(final JSFile file) - { - hasJsInjection.set(Boolean.TRUE); - } - }); + if (host != null) { + final SimpleReference hasJsInjection = new SimpleReference<>(Boolean.FALSE); - if(hasJsInjection.get()) - { - language = JavaScriptLanguage.INSTANCE; - } - } - } - return language != null && language.isKindOf(JavaScriptLanguage.INSTANCE); - } + InjectedLanguageManager.getInstance(at.getProject()).enumerate( + host, + new JSResolveUtil.JSInjectedFilesVisitor() { + @Override + protected void process(JSFile file) { + hasJsInjection.set(Boolean.TRUE); + } + } + ); - public boolean isInContext(@Nonnull final FileType fileType) - { - return fileType instanceof JavaScriptFileType; - } + if (hasJsInjection.get()) { + language = JavaScriptLanguage.INSTANCE; + } + } + } + return language != null && language.isKindOf(JavaScriptLanguage.INSTANCE); + } - @Override - public SyntaxHighlighter createHighlighter() - { - return SyntaxHighlighterFactory.getSyntaxHighlighter(JavaScriptSupportLoader.ECMA_SCRIPT_L4, null, null); - } + @Override + public SyntaxHighlighter createHighlighter() { + return SyntaxHighlighterFactory.getSyntaxHighlighter(JavaScriptSupportLoader.ECMA_SCRIPT_L4, null, null); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/JavaScriptTargetElementUtilEx.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/JavaScriptTargetElementUtilEx.java index 634bf0f8..48ac5f6d 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/JavaScriptTargetElementUtilEx.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/JavaScriptTargetElementUtilEx.java @@ -22,32 +22,24 @@ import consulo.annotation.component.ExtensionImpl; import consulo.language.editor.TargetElementUtilExtender; import consulo.language.psi.PsiElement; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author Maxim.Mossienko - * Date: Oct 13, 2008 - * Time: 3:53:42 PM + * @since 2008-10-13 */ @ExtensionImpl -public class JavaScriptTargetElementUtilEx implements TargetElementUtilExtender -{ - @Override - public boolean includeSelfInGotoImplementation(@Nonnull final PsiElement element) - { - if(element instanceof JSFunction) - { - final PsiElement parent = JSResolveUtil.findParent(element); - if(parent instanceof JSClass && ((JSClass) parent).isInterface()) - { - return false; - } - } - else if(element instanceof JSClass) - { - return false; - } - return true; - } +public class JavaScriptTargetElementUtilEx implements TargetElementUtilExtender { + @Override + public boolean includeSelfInGotoImplementation(@Nonnull PsiElement element) { + if (element instanceof JSFunction function) { + if (JSResolveUtil.findParent(function) instanceof JSClass jsClass && jsClass.isInterface()) { + return false; + } + } + else if (element instanceof JSClass) { + return false; + } + return true; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/JavascriptCommenter.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/JavascriptCommenter.java index 6800da67..5bd8592c 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/JavascriptCommenter.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/JavascriptCommenter.java @@ -24,96 +24,82 @@ import consulo.language.ast.IElementType; import consulo.language.psi.PsiComment; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author max */ @ExtensionImpl -public class JavascriptCommenter implements CodeDocumentationAwareCommenter -{ - @Override - public String getLineCommentPrefix() - { - return "//"; - } - - @Override - public String getBlockCommentPrefix() - { - return "/*"; - } - - @Override - public String getBlockCommentSuffix() - { - return "*/"; - } - - @Nullable - @Override - public String getCommentedBlockCommentPrefix() - { - return null; - } - - @Nullable - @Override - public String getCommentedBlockCommentSuffix() - { - return null; - } - - @Override - @Nullable - public IElementType getLineCommentTokenType() - { - return JSTokenTypes.END_OF_LINE_COMMENT; - } - - @Override - @Nullable - public IElementType getBlockCommentTokenType() - { - return JSTokenTypes.C_STYLE_COMMENT; - } - - @Override - public String getDocumentationCommentPrefix() - { - return "/**"; - } - - @Override - public String getDocumentationCommentLinePrefix() - { - return "*"; - } - - @Override - public String getDocumentationCommentSuffix() - { - return "*/"; - } - - @Override - public boolean isDocumentationComment(final PsiComment element) - { - return element.getTokenType() == JSTokenTypes.DOC_COMMENT; - } - - @Override - @Nullable - public IElementType getDocumentationCommentTokenType() - { - return JSTokenTypes.DOC_COMMENT; - } - - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } +public class JavascriptCommenter implements CodeDocumentationAwareCommenter { + @Override + public String getLineCommentPrefix() { + return "//"; + } + + @Override + public String getBlockCommentPrefix() { + return "/*"; + } + + @Override + public String getBlockCommentSuffix() { + return "*/"; + } + + @Nullable + @Override + public String getCommentedBlockCommentPrefix() { + return null; + } + + @Nullable + @Override + public String getCommentedBlockCommentSuffix() { + return null; + } + + @Override + @Nullable + public IElementType getLineCommentTokenType() { + return JSTokenTypes.END_OF_LINE_COMMENT; + } + + @Override + @Nullable + public IElementType getBlockCommentTokenType() { + return JSTokenTypes.C_STYLE_COMMENT; + } + + @Override + public String getDocumentationCommentPrefix() { + return "/**"; + } + + @Override + public String getDocumentationCommentLinePrefix() { + return "*"; + } + + @Override + public String getDocumentationCommentSuffix() { + return "*/"; + } + + @Override + public boolean isDocumentationComment(PsiComment element) { + return element.getTokenType() == JSTokenTypes.DOC_COMMENT; + } + + @Override + @Nullable + public IElementType getDocumentationCommentTokenType() { + return JSTokenTypes.DOC_COMMENT; + } + + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/findUsages/JSReadWriteAccessDetector.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/findUsages/JSReadWriteAccessDetector.java index 7777138a..7c403bec 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/findUsages/JSReadWriteAccessDetector.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/findUsages/JSReadWriteAccessDetector.java @@ -23,6 +23,7 @@ import com.intellij.lang.javascript.psi.JSPostfixExpression; import com.intellij.lang.javascript.psi.JSPrefixExpression; import com.intellij.lang.javascript.psi.JSVariable; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; import consulo.language.ast.IElementType; import consulo.language.editor.highlight.ReadWriteAccessDetector; @@ -30,66 +31,57 @@ import consulo.language.psi.PsiReference; /** - * User: Maxim.Mossienko - * Date: 15.04.2009 - * Time: 21:51:25 + * @author Maxim.Mossienko + * @since 2009-04-15 */ @ExtensionImpl -public class JSReadWriteAccessDetector extends ReadWriteAccessDetector -{ - @Override - public boolean isReadWriteAccessible(PsiElement element) - { - return element instanceof JSVariable || - ((element instanceof JSFunction) && (((JSFunction) element).isGetProperty() || ((JSFunction) element).isSetProperty())) || - element instanceof JSDefinitionExpression; - } +public class JSReadWriteAccessDetector extends ReadWriteAccessDetector { + @Override + @RequiredReadAction + public boolean isReadWriteAccessible(PsiElement element) { + return element instanceof JSVariable + || (element instanceof JSFunction function && (function.isGetProperty() || function.isSetProperty())) + || element instanceof JSDefinitionExpression; + } - @Override - public boolean isDeclarationWriteAccess(PsiElement element) - { - return (element instanceof JSVariable && ((JSVariable) element).getInitializer() != null); - } + @Override + @RequiredReadAction + public boolean isDeclarationWriteAccess(PsiElement element) { + return (element instanceof JSVariable variable && variable.getInitializer() != null); + } - @Override - public Access getReferenceAccess(PsiElement referencedElement, PsiReference reference) - { - return getExpressionAccess(reference.getElement()); - } + @Override + @RequiredReadAction + public Access getReferenceAccess(PsiElement referencedElement, PsiReference reference) { + return getExpressionAccess(reference.getElement()); + } - @Override - public Access getExpressionAccess(PsiElement expression) - { - expression = expression.getParent(); - if(expression instanceof JSDefinitionExpression) - { - PsiElement grandParent = expression.getParent(); - if(grandParent instanceof JSAssignmentExpression && ((JSAssignmentExpression) grandParent).getOperationSign() == JSTokenTypes.EQ) - { - return Access.Write; - } + @Override + @RequiredReadAction + public Access getExpressionAccess(PsiElement expression) { + expression = expression.getParent(); + if (expression instanceof JSDefinitionExpression definition) { + if (definition.getParent() instanceof JSAssignmentExpression assignment + && assignment.getOperationSign() == JSTokenTypes.EQ) { + return Access.Write; + } - return Access.ReadWrite; - } - if(expression instanceof JSPrefixExpression) - { - if(isIncrementOrDecrement(((JSPrefixExpression) expression).getOperationSign())) - { - return Access.ReadWrite; - } - } - else if(expression instanceof JSPostfixExpression) - { - if(isIncrementOrDecrement(((JSPostfixExpression) expression).getOperationSign())) - { - return Access.ReadWrite; - } - } - return Access.Read; - } + return Access.ReadWrite; + } + if (expression instanceof JSPrefixExpression prefixExpression) { + if (isIncrementOrDecrement(prefixExpression.getOperationSign())) { + return Access.ReadWrite; + } + } + else if (expression instanceof JSPostfixExpression postfixExpression) { + if (isIncrementOrDecrement(postfixExpression.getOperationSign())) { + return Access.ReadWrite; + } + } + return Access.Read; + } - private static boolean isIncrementOrDecrement(IElementType sign) - { - return sign == JSTokenTypes.PLUSPLUS || sign == JSTokenTypes.MINUSMINUS; - } + private static boolean isIncrementOrDecrement(IElementType sign) { + return sign == JSTokenTypes.PLUSPLUS || sign == JSTokenTypes.MINUSMINUS; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/findUsages/JSWordsScanner.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/findUsages/JSWordsScanner.java index acc35dbc..b26a1f68 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/findUsages/JSWordsScanner.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/findUsages/JSWordsScanner.java @@ -23,17 +23,17 @@ import consulo.language.cacheBuilder.DefaultWordsScanner; /** - * Created by IntelliJ IDEA. - * User: max - * Date: Jan 31, 2005 - * Time: 9:34:58 PM - * To change this template use File | Settings | File Templates. + * @author max + * @since 2005-01-31 */ -public class JSWordsScanner extends DefaultWordsScanner -{ - public JSWordsScanner() - { - super(new JSFlexAdapter(false, DialectOptionHolder.dummy()), JSTokenTypes.IDENTIFIER_TOKENS_SET, JSTokenTypes.COMMENTS, JavaScriptTokenSets.STRING_LITERALS); - setMayHaveFileRefsInLiterals(true); - } +public class JSWordsScanner extends DefaultWordsScanner { + public JSWordsScanner() { + super( + new JSFlexAdapter(false, DialectOptionHolder.dummy()), + JSTokenTypes.IDENTIFIER_TOKENS_SET, + JSTokenTypes.COMMENTS, + JavaScriptTokenSets.STRING_LITERALS + ); + setMayHaveFileRefsInLiterals(true); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/findUsages/JavaScriptClassGroupRuleProvider.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/findUsages/JavaScriptClassGroupRuleProvider.java index 219047d9..58d08e6e 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/findUsages/JavaScriptClassGroupRuleProvider.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/findUsages/JavaScriptClassGroupRuleProvider.java @@ -22,38 +22,31 @@ import consulo.annotation.component.ExtensionImpl; import consulo.application.AllIcons; import consulo.usage.UsageGroup; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author Maxim.Mossienko */ @ExtensionImpl -public class JavaScriptClassGroupRuleProvider extends JavaScriptGroupRuleProviderBase -{ - @Override - protected Class getUsageClass() - { - return JSClass.class; - } +public class JavaScriptClassGroupRuleProvider extends JavaScriptGroupRuleProviderBase { + @Override + protected Class getUsageClass() { + return JSClass.class; + } - @Override - protected UsageGroup createUsageGroup(final JSClass clazz) - { - return new ClassUsageGroup(clazz); - } + @Override + protected UsageGroup createUsageGroup(JSClass clazz) { + return new ClassUsageGroup(clazz); + } - @Override - protected boolean isAcceptableElement(JSNamedElement element) - { - return super.isAcceptableElement(element) && !JSResolveUtil.isArtificialClassUsedForReferenceList((JSClass) element); - } + @Override + protected boolean isAcceptableElement(JSNamedElement element) { + return super.isAcceptableElement(element) && !JSResolveUtil.isArtificialClassUsedForReferenceList((JSClass)element); + } - private static class ClassUsageGroup extends JavaScriptGroupRuleProviderBase.PsiNamedElementUsageGroupBase - { - public ClassUsageGroup(@Nonnull JSClass clazz) - { - super(clazz, AllIcons.Nodes.Class); - } - } + private static class ClassUsageGroup extends JavaScriptGroupRuleProviderBase.PsiNamedElementUsageGroupBase { + public ClassUsageGroup(@Nonnull JSClass clazz) { + super(clazz, AllIcons.Nodes.Class); + } + } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/findUsages/JavaScriptFindUsagesProvider.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/findUsages/JavaScriptFindUsagesProvider.java index 4b0b1ff3..93a87a93 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/findUsages/JavaScriptFindUsagesProvider.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/findUsages/JavaScriptFindUsagesProvider.java @@ -16,10 +16,10 @@ package com.intellij.lang.javascript.impl.findUsages; -import consulo.annotation.component.ExtensionImpl; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.psi.*; +import consulo.annotation.component.ExtensionImpl; import consulo.javascript.language.JavaScriptLanguage; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.Language; import consulo.language.cacheBuilder.WordsScanner; import consulo.language.findUsage.FindUsagesProvider; @@ -28,98 +28,79 @@ import consulo.xml.psi.xml.XmlTag; import consulo.xml.psi.xml.XmlToken; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * User: max - * Date: Feb 14, 2005 - * Time: 6:44:02 PM + * @author max + * @since 2005-02-14 */ @ExtensionImpl -public class JavaScriptFindUsagesProvider implements FindUsagesProvider -{ - @Override - public boolean canFindUsagesFor(@Nonnull PsiElement psiElement) - { - return psiElement instanceof PsiNamedElement; - } +public class JavaScriptFindUsagesProvider implements FindUsagesProvider { + @Override + public boolean canFindUsagesFor(@Nonnull PsiElement psiElement) { + return psiElement instanceof PsiNamedElement; + } - @Override - @Nonnull - public String getType(@Nonnull PsiElement element) - { - if(element instanceof JSFunction) - { - return JavaScriptBundle.message("javascript.language.term.function"); - } - if(element instanceof JSClass) - { - return JavaScriptBundle.message("javascript.language.term.class"); - } - if(element instanceof JSNamespaceDeclaration) - { - return JavaScriptBundle.message("javascript.language.term.namespace"); - } - if(element instanceof JSParameter) - { - return JavaScriptBundle.message("javascript.language.term.parameter"); - } - if(element instanceof JSProperty) - { - return JavaScriptBundle.message("javascript.language.term.property"); - } - if(element instanceof JSVariable) - { - return JavaScriptBundle.message("javascript.language.term.variable"); - } - if(element instanceof JSLabeledStatement) - { - return JavaScriptBundle.message("javascript.language.term.label"); - } - if(element instanceof JSDefinitionExpression) - { - return JavaScriptBundle.message("javascript.language.term.value"); - } - if(element instanceof XmlTag) - { - return JavaScriptBundle.message("javascript.language.term.tag"); - } - if(element instanceof XmlToken) - { - return JavaScriptBundle.message("javascript.language.term.attribute.value"); - } - if(element instanceof JSPackageStatement) - { - return JavaScriptBundle.message("javascript.language.term.package"); - } - return ""; - } + @Override + @Nonnull + public String getType(@Nonnull PsiElement element) { + if (element instanceof JSFunction) { + return JavaScriptLocalize.javascriptLanguageTermFunction().get(); + } + if (element instanceof JSClass) { + return JavaScriptLocalize.javascriptLanguageTermClass().get(); + } + if (element instanceof JSNamespaceDeclaration) { + return JavaScriptLocalize.javascriptLanguageTermNamespace().get(); + } + if (element instanceof JSParameter) { + return JavaScriptLocalize.javascriptLanguageTermParameter().get(); + } + if (element instanceof JSProperty) { + return JavaScriptLocalize.javascriptLanguageTermProperty().get(); + } + if (element instanceof JSVariable) { + return JavaScriptLocalize.javascriptLanguageTermVariable().get(); + } + if (element instanceof JSLabeledStatement) { + return JavaScriptLocalize.javascriptLanguageTermLabel().get(); + } + if (element instanceof JSDefinitionExpression) { + return JavaScriptLocalize.javascriptLanguageTermValue().get(); + } + if (element instanceof XmlTag) { + return JavaScriptLocalize.javascriptLanguageTermTag().get(); + } + if (element instanceof XmlToken) { + return JavaScriptLocalize.javascriptLanguageTermAttributeValue().get(); + } + if (element instanceof JSPackageStatement) { + return JavaScriptLocalize.javascriptLanguageTermPackage().get(); + } + return ""; + } - @Override - @Nonnull - public String getDescriptiveName(@Nonnull PsiElement element) - { - String name = ((PsiNamedElement) element).getName(); - return name != null ? name : ""; - } + @Override + @Nonnull + public String getDescriptiveName(@Nonnull PsiElement element) { + String name = ((PsiNamedElement)element).getName(); + return name != null ? name : ""; + } - @Override - @Nonnull - public String getNodeText(@Nonnull PsiElement element, boolean useFullName) - { - return getDescriptiveName(element); - } + @Override + @Nonnull + public String getNodeText(@Nonnull PsiElement element, boolean useFullName) { + return getDescriptiveName(element); + } - @Override - public WordsScanner getWordsScanner() - { - return new JSWordsScanner(); - } + @Override + public WordsScanner getWordsScanner() { + return new JSWordsScanner(); + } - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/findUsages/JavaScriptFunctionGroupRuleProvider.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/findUsages/JavaScriptFunctionGroupRuleProvider.java index c2bfac95..4f37ea46 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/findUsages/JavaScriptFunctionGroupRuleProvider.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/findUsages/JavaScriptFunctionGroupRuleProvider.java @@ -21,32 +21,26 @@ import consulo.annotation.component.ExtensionImpl; import consulo.application.AllIcons; import consulo.usage.UsageGroup; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author Maxim.Mossienko */ @ExtensionImpl -public class JavaScriptFunctionGroupRuleProvider extends JavaScriptGroupRuleProviderBase -{ - @Override - protected Class getUsageClass() - { - return JSFunction.class; - } +public class JavaScriptFunctionGroupRuleProvider extends JavaScriptGroupRuleProviderBase { + @Override + protected Class getUsageClass() { + return JSFunction.class; + } - @Override - protected UsageGroup createUsageGroup(final JSFunction jsFunction) - { - return new FunctionUsageGroup(jsFunction); - } + @Override + protected UsageGroup createUsageGroup(JSFunction jsFunction) { + return new FunctionUsageGroup(jsFunction); + } - private static class FunctionUsageGroup extends JavaScriptGroupRuleProviderBase.PsiNamedElementUsageGroupBase - { - public FunctionUsageGroup(@Nonnull JSFunction function) - { - super(function, AllIcons.Nodes.Function); - } - } + private static class FunctionUsageGroup extends JavaScriptGroupRuleProviderBase.PsiNamedElementUsageGroupBase { + public FunctionUsageGroup(@Nonnull JSFunction function) { + super(function, AllIcons.Nodes.Function); + } + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/findUsages/JavaScriptGroupRuleProviderBase.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/findUsages/JavaScriptGroupRuleProviderBase.java index b2b33dcb..19158a11 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/findUsages/JavaScriptGroupRuleProviderBase.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/findUsages/JavaScriptGroupRuleProviderBase.java @@ -17,6 +17,7 @@ package com.intellij.lang.javascript.impl.findUsages; import com.intellij.lang.javascript.psi.JSNamedElement; +import consulo.annotation.access.RequiredReadAction; import consulo.dataContext.DataSink; import consulo.dataContext.TypeSafeDataProvider; import consulo.language.editor.LangDataKeys; @@ -39,178 +40,150 @@ import consulo.util.dataholder.Key; import consulo.util.lang.Comparing; import consulo.virtualFileSystem.status.FileStatus; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author Maxim.Mossienko */ -abstract class JavaScriptGroupRuleProviderBase implements FileStructureGroupRuleProvider -{ - @Override - @Nullable - public UsageGroupingRule getUsageGroupingRule(final Project project) - { - return new UsageGroupingRule() - { - @Override - @Nullable - public UsageGroup groupUsage(final Usage usage) - { - if(usage instanceof PsiElementUsage) - { - PsiElement psiElement = ((PsiElementUsage) usage).getElement(); - - if(!psiElement.getLanguage().isKindOf(JavaScriptLanguage.INSTANCE)) - { - return null; - } - final JSNamedElement element = PsiTreeUtil.getParentOfType(psiElement, getUsageClass()); - - if(isAcceptableElement(element)) - { - return createUsageGroup((T) element); - } - } - return null; - } - }; - } - - protected boolean isAcceptableElement(JSNamedElement element) - { - return element != null; - } - - protected abstract Class getUsageClass(); - - protected abstract UsageGroup createUsageGroup(final T t); - - /** - * @author Maxim.Mossienko - */ - abstract static class PsiNamedElementUsageGroupBase implements UsageGroup, TypeSafeDataProvider - { - private SmartPsiElementPointer myElementPointer; - private String myName; - private Image myIcon; - - PsiNamedElementUsageGroupBase(@Nonnull T element, Image icon) - { - myIcon = icon; - - myName = element.getName(); - if(myName == null) - { - myName = ""; - } - myElementPointer = SmartPointerManager.getInstance(element.getProject()).createLazyPointer(element); - } - - @Override - public Image getIcon() - { - return myIcon; - } - - public T getElement() - { - return (T) myElementPointer.getElement(); - } - - @Override - @Nonnull - public String getText(UsageView view) - { - return myName; - } - - @Override - public FileStatus getFileStatus() - { - return isValid() ? FileStatusManager.getInstance(getElement().getProject()).getStatus(getElement().getContainingFile().getVirtualFile()) : null; - } - - @Override - public boolean isValid() - { - final T element = getElement(); - return element != null && element.isValid(); - } - - @Override - public void navigate(boolean focus) throws UnsupportedOperationException - { - if(canNavigate()) - { - getElement().navigate(focus); - } - } - - @Override - public boolean canNavigate() - { - return isValid(); - } - - @Override - public boolean canNavigateToSource() - { - return canNavigate(); - } - - @Override - public void update() - { - } - - @Override - public int compareTo(final UsageGroup o) - { - return myName.compareTo(((PsiNamedElementUsageGroupBase) o).myName); - } - - @Override - public boolean equals(final Object obj) - { - if(!(obj instanceof PsiNamedElementUsageGroupBase)) - { - return false; - } - PsiNamedElementUsageGroupBase group = (PsiNamedElementUsageGroupBase) obj; - if(isValid() && group.isValid()) - { - return getElement().getManager().areElementsEquivalent(getElement(), group.getElement()); - } - return Comparing.equal(myName, ((PsiNamedElementUsageGroupBase) obj).myName); - } - - @Override - public int hashCode() - { - return myName.hashCode(); - } - - @Override - public void calcData(final Key key, final DataSink sink) - { - if(!isValid()) - { - return; - } - if(LangDataKeys.PSI_ELEMENT == key) - { - sink.put(LangDataKeys.PSI_ELEMENT, getElement()); - } - if(UsageView.USAGE_INFO_KEY == key) - { - T element = getElement(); - if(element != null) - { - sink.put(UsageView.USAGE_INFO_KEY, new UsageInfo(element)); - } - } - } - } +abstract class JavaScriptGroupRuleProviderBase implements FileStructureGroupRuleProvider { + @Nullable + @Override + public UsageGroupingRule getUsageGroupingRule(Project project) { + return new UsageGroupingRule() { + @Nullable + @Override + @RequiredReadAction + @SuppressWarnings("unchecked") + public UsageGroup groupUsage(@Nonnull Usage usage) { + if (usage instanceof PsiElementUsage elementUsage) { + PsiElement psiElement = elementUsage.getElement(); + + if (!psiElement.getLanguage().isKindOf(JavaScriptLanguage.INSTANCE)) { + return null; + } + JSNamedElement element = PsiTreeUtil.getParentOfType(psiElement, getUsageClass()); + + if (isAcceptableElement(element)) { + return createUsageGroup((T)element); + } + } + return null; + } + }; + } + + protected boolean isAcceptableElement(JSNamedElement element) { + return element != null; + } + + protected abstract Class getUsageClass(); + + protected abstract UsageGroup createUsageGroup(T t); + + /** + * @author Maxim.Mossienko + */ + abstract static class PsiNamedElementUsageGroupBase + implements UsageGroup, TypeSafeDataProvider { + + private SmartPsiElementPointer myElementPointer; + private String myName; + private Image myIcon; + + PsiNamedElementUsageGroupBase(@Nonnull T element, Image icon) { + myIcon = icon; + + myName = element.getName(); + if (myName == null) { + myName = ""; + } + myElementPointer = SmartPointerManager.getInstance(element.getProject()).createLazyPointer(element); + } + + @Override + public Image getIcon() { + return myIcon; + } + + public T getElement() { + return (T)myElementPointer.getElement(); + } + + @Override + @Nonnull + public String getText(UsageView view) { + return myName; + } + + @Override + public FileStatus getFileStatus() { + return isValid() ? FileStatusManager.getInstance(getElement().getProject()) + .getStatus(getElement().getContainingFile().getVirtualFile()) : null; + } + + @Override + public boolean isValid() { + T element = getElement(); + return element != null && element.isValid(); + } + + @Override + public void navigate(boolean focus) throws UnsupportedOperationException { + if (canNavigate()) { + getElement().navigate(focus); + } + } + + @Override + public boolean canNavigate() { + return isValid(); + } + + @Override + public boolean canNavigateToSource() { + return canNavigate(); + } + + @Override + public void update() { + } + + @Override + public int compareTo(UsageGroup o) { + return myName.compareTo(((PsiNamedElementUsageGroupBase)o).myName); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof PsiNamedElementUsageGroupBase group) { + if (isValid() && group.isValid()) { + return getElement().getManager().areElementsEquivalent(getElement(), group.getElement()); + } + return Comparing.equal(myName, group.myName); + } + return false; + } + + @Override + public int hashCode() { + return myName.hashCode(); + } + + @Override + public void calcData(Key key, DataSink sink) { + if (!isValid()) { + return; + } + if (LangDataKeys.PSI_ELEMENT == key) { + sink.put(LangDataKeys.PSI_ELEMENT, getElement()); + } + if (UsageView.USAGE_INFO_KEY == key) { + T element = getElement(); + if (element != null) { + sink.put(UsageView.USAGE_INFO_KEY, new UsageInfo(element)); + } + } + } + } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/AddImportECMAScriptClassOrFunctionAction.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/AddImportECMAScriptClassOrFunctionAction.java index 1528eb69..406641e6 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/AddImportECMAScriptClassOrFunctionAction.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/AddImportECMAScriptClassOrFunctionAction.java @@ -13,19 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.lang.javascript.impl.flex; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.psi.JSFunction; import com.intellij.lang.javascript.psi.JSQualifiedNamedElement; import com.intellij.lang.javascript.psi.JSReferenceExpression; import com.intellij.lang.javascript.psi.impl.JSPsiImplUtils; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; -import consulo.application.ApplicationManager; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; +import consulo.application.Application; import consulo.codeEditor.Editor; import consulo.codeEditor.EditorPopupHelper; import consulo.document.util.TextRange; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.editor.hint.HintManager; import consulo.language.editor.hint.QuestionAction; import consulo.language.editor.inspection.LocalQuickFix; @@ -41,285 +42,248 @@ import consulo.language.psi.resolve.PsiElementProcessor; import consulo.language.psi.scope.GlobalSearchScope; import consulo.language.util.ModuleUtilCore; +import consulo.localize.LocalizeValue; import consulo.module.Module; import consulo.project.Project; +import consulo.ui.annotation.RequiredUIAccess; import consulo.ui.ex.popup.JBPopup; import consulo.undoRedo.CommandProcessor; import consulo.util.collection.Sets; import consulo.util.collection.SmartList; -import org.jetbrains.annotations.NonNls; +import consulo.util.lang.StringUtil; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; import java.util.Collection; import java.util.Collections; import java.util.Iterator; /** * @author Maxim.Mossienko - * Date: Apr 25, 2008 - * Time: 8:36:38 PM + * @since 2008-04-25 */ -public class AddImportECMAScriptClassOrFunctionAction implements HintAction, QuestionAction, LocalQuickFix -{ - private final PsiPolyVariantReference myReference; - private Editor myEditor; - private boolean isAvailable; - private boolean isAvailableCalculated; - private long modificationCount = -1; - private String calculatedClass; - @NonNls - private static final String HAS_MORE_SUFFIX = ", ..."; - private boolean isFunction; - - public AddImportECMAScriptClassOrFunctionAction(Editor editor, final PsiPolyVariantReference psiReference) - { - myReference = psiReference; - myEditor = editor; - } - - @Override - public boolean showHint(final Editor editor) - { - myEditor = editor; - final PsiElement element = myReference.getElement(); - TextRange textRange = InjectedLanguageManager.getInstance(element.getProject()).injectedToHost(element, element.getTextRange()); - HintManager.getInstance().showQuestionHint(editor, getText(), textRange.getStartOffset(), textRange.getEndOffset(), this); - return true; - } - - @Override - @Nonnull - public String getText() - { - return JavaScriptBundle.message(isFunction ? "flex.import.function" : "flex.import.class", calculatedClass); - } - - @Override - @Nonnull - public String getName() - { - return getText(); - } - - @Override - @Nonnull - public String getFamilyName() - { - return getText(); - } - - @Override - public void applyFix(@Nonnull final Project project, @Nonnull final ProblemDescriptor descriptor) - { - invoke(project, myEditor, descriptor.getPsiElement().getContainingFile()); - } - - @Override - public boolean isAvailable(@Nonnull final Project project, final Editor editor, final PsiFile file) - { - if(!myReference.getElement().isValid()) - { - return false; - } - final long modL = myReference.getElement().getManager().getModificationTracker().getModificationCount(); - - if(!isAvailableCalculated || modL != modificationCount) - { - final ResolveResult[] results = myReference.multiResolve(false); - boolean hasValidResult = false; - - for(ResolveResult r : results) - { - if(r.isValidResult()) - { - hasValidResult = true; - break; - } - } - - if(!hasValidResult) - { - final Collection candidates = getCandidates(editor, file); - - isAvailableCalculated = true; - isAvailable = candidates.size() > 0; - if(isAvailable) - { - final JSQualifiedNamedElement element = candidates.iterator().next(); - calculatedClass = element.getQualifiedName(); - isFunction = element instanceof JSFunction; - if(candidates.size() > 1) - { - calculatedClass += HAS_MORE_SUFFIX; - } - } - else - { - calculatedClass = ""; - } - } - else - { - isAvailableCalculated = true; - isAvailable = false; - } - - modificationCount = modL; - } - - return isAvailable; - } - - private Collection getCandidates(Editor editor, PsiFile file) - { - final Collection candidates; - - if(myReference instanceof JSReferenceExpression && ((JSReferenceExpression) myReference).getQualifier() == null) - { - Collection c = getCandidates(editor, file, myReference.getCanonicalText()); - filterDefaultPackage(c); - candidates = Sets.newHashSet(c, JSPsiImplUtils.QUALIFIED_NAME_HASHING_STRATEGY); - } - else - { - JSQualifiedNamedElement invalidResult = null; - - for(ResolveResult r : myReference.multiResolve(false)) - { - PsiElement element = r.getElement(); - if(element instanceof JSQualifiedNamedElement) - { - invalidResult = (JSQualifiedNamedElement) element; - } - } - if(invalidResult != null) - { - candidates = new SmartList(); - candidates.add(invalidResult); - } - else - { - candidates = Collections.emptyList(); - } - } - return candidates; - } - - public static Collection getCandidates(final Editor editor, final PsiFile file, final String name) - { - final Module element = ModuleUtilCore.findModuleForPsiElement(file); - if(element != null) - { - return JSResolveUtil.findElementsByName(name, editor.getProject(), GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(element, false)); - } - else - { - return Collections.emptyList(); - } - } - - @Override - public void invoke(@Nonnull final Project project, final Editor editor, final PsiFile file) - { - final Collection candidates = getCandidates(editor, file); - - if(candidates.size() > 0) - { - if(candidates.size() > 1) - { - JBPopup popup = PopupNavigationUtil.getPsiElementPopup(candidates.toArray(new JSQualifiedNamedElement[candidates.size()]), - new PsiElementListCellRenderer() - { - @Override - public String getElementText(final JSQualifiedNamedElement element) - { - return element.getName(); - } - - @Override - protected String getContainerText(final JSQualifiedNamedElement element, final String name) - { - final String qName = element.getQualifiedName(); - final String elementName = element.getName(); - String s = qName.equals(elementName) ? "" : qName.substring(0, qName.length() - elementName.length() - 1); - if("".equals(s)) - { - s = element.getContainingFile().getName(); - } - return "( " + s + " )"; - } - - @Override - protected int getIconFlags() - { - return 0; - } - }, JavaScriptBundle.message("choose.class.title"), new PsiElementProcessor() - { - @Override - public boolean execute(final JSQualifiedNamedElement element) - { - CommandProcessor.getInstance().executeCommand(project, new Runnable() - { - @Override - public void run() - { - doImport(editor, element.getQualifiedName()); - } - }, getClass().getName(), this); - - return false; - } - } - ); - - EditorPopupHelper.getInstance().showPopupInBestPositionFor(editor, popup); - } - else - { - doImport(editor, candidates.iterator().next().getQualifiedName()); - } - } - } - - private void doImport(final Editor editor, final String qName) - { - ApplicationManager.getApplication().runWriteAction(new Runnable() - { - @Override - public void run() - { - final PsiElement element = myReference.getElement(); - ImportUtils.doImport(element, qName); - } - }); - } - - @Override - public boolean startInWriteAction() - { - return false; - } - - @Override - public boolean execute() - { - final PsiFile containingFile = myReference.getElement().getContainingFile(); - invoke(containingFile.getProject(), myEditor, containingFile); - - return true; - } - - private static void filterDefaultPackage(Collection candidates) - { - for(Iterator i = candidates.iterator(); i.hasNext(); ) - { - if(!i.next().getQualifiedName().contains(".")) - { - i.remove(); - } - } - } - - +public class AddImportECMAScriptClassOrFunctionAction implements HintAction, QuestionAction, LocalQuickFix { + private final PsiPolyVariantReference myReference; + private Editor myEditor; + private boolean isAvailable; + private boolean isAvailableCalculated; + private long modificationCount = -1; + private String calculatedClass; + private static final String HAS_MORE_SUFFIX = ", ..."; + private boolean isFunction; + + public AddImportECMAScriptClassOrFunctionAction(Editor editor, PsiPolyVariantReference psiReference) { + myReference = psiReference; + myEditor = editor; + } + + @Override + @RequiredUIAccess + public boolean showHint(@Nonnull Editor editor) { + myEditor = editor; + PsiElement element = myReference.getElement(); + TextRange textRange = InjectedLanguageManager.getInstance(element.getProject()).injectedToHost(element, element.getTextRange()); + HintManager.getInstance().showQuestionHint(editor, getText(), textRange.getStartOffset(), textRange.getEndOffset(), this); + return true; + } + + @Override + @Nonnull + public LocalizeValue getText() { + String className = StringUtil.notNullize(calculatedClass); + return isFunction + ? JavaScriptLocalize.flexImportFunction(className) + : JavaScriptLocalize.flexImportClass(className); + } + + @Override + @Nonnull + public LocalizeValue getName() { + return getText(); + } + + @Override + @RequiredWriteAction + public void applyFix(@Nonnull Project project, @Nonnull ProblemDescriptor descriptor) { + invoke(project, myEditor, descriptor.getPsiElement().getContainingFile()); + } + + @Override + @RequiredReadAction + public boolean isAvailable(@Nonnull Project project, Editor editor, PsiFile file) { + if (!myReference.getElement().isValid()) { + return false; + } + long modL = myReference.getElement().getManager().getModificationTracker().getModificationCount(); + + if (!isAvailableCalculated || modL != modificationCount) { + ResolveResult[] results = myReference.multiResolve(false); + boolean hasValidResult = false; + + for (ResolveResult r : results) { + if (r.isValidResult()) { + hasValidResult = true; + break; + } + } + + if (!hasValidResult) { + Collection candidates = getCandidates(editor, file); + + isAvailableCalculated = true; + isAvailable = candidates.size() > 0; + if (isAvailable) { + JSQualifiedNamedElement element = candidates.iterator().next(); + calculatedClass = element.getQualifiedName(); + isFunction = element instanceof JSFunction; + if (candidates.size() > 1) { + calculatedClass += HAS_MORE_SUFFIX; + } + } + else { + calculatedClass = ""; + } + } + else { + isAvailableCalculated = true; + isAvailable = false; + } + + modificationCount = modL; + } + + return isAvailable; + } + + @RequiredReadAction + private Collection getCandidates(Editor editor, PsiFile file) { + Collection candidates; + + if (myReference instanceof JSReferenceExpression referenceExpression && referenceExpression.getQualifier() == null) { + Collection c = getCandidates(editor, file, myReference.getCanonicalText()); + filterDefaultPackage(c); + candidates = Sets.newHashSet(c, JSPsiImplUtils.QUALIFIED_NAME_HASHING_STRATEGY); + } + else { + JSQualifiedNamedElement invalidResult = null; + + for (ResolveResult r : myReference.multiResolve(false)) { + PsiElement element = r.getElement(); + if (element instanceof JSQualifiedNamedElement qualifiedNamedElement) { + invalidResult = qualifiedNamedElement; + } + } + if (invalidResult != null) { + candidates = new SmartList<>(); + candidates.add(invalidResult); + } + else { + candidates = Collections.emptyList(); + } + } + return candidates; + } + + @RequiredReadAction + public static Collection getCandidates(Editor editor, PsiFile file, String name) { + Module element = ModuleUtilCore.findModuleForPsiElement(file); + if (element != null) { + return JSResolveUtil.findElementsByName( + name, + editor.getProject(), + GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(element, false) + ); + } + else { + return Collections.emptyList(); + } + } + + @Override + @RequiredWriteAction + public void invoke(@Nonnull final Project project, final Editor editor, PsiFile file) { + Collection candidates = getCandidates(editor, file); + + if (candidates.size() > 0) { + if (candidates.size() > 1) { + JBPopup popup = PopupNavigationUtil.getPsiElementPopup( + candidates.toArray(new JSQualifiedNamedElement[candidates.size()]), + new PsiElementListCellRenderer<>() { + @Override + @RequiredReadAction + public String getElementText(JSQualifiedNamedElement element) { + return element.getName(); + } + + @Override + @RequiredReadAction + protected String getContainerText(JSQualifiedNamedElement element, String name) { + String qName = element.getQualifiedName(); + String elementName = element.getName(); + String s = qName.equals(elementName) + ? "" + : qName.substring(0, qName.length() - elementName.length() - 1); + if ("".equals(s)) { + s = element.getContainingFile().getName(); + } + return "( " + s + " )"; + } + + @Override + protected int getIconFlags() { + return 0; + } + }, + JavaScriptLocalize.chooseClassTitle().get(), + new PsiElementProcessor<>() { + @Override + public boolean execute(@Nonnull JSQualifiedNamedElement element) { + CommandProcessor.getInstance().newCommand() + .project(project) + .name(LocalizeValue.ofNullable(getClass().getName())) + .groupId(this) + .run(() -> doImport(editor, element.getQualifiedName())); + + return false; + } + } + ); + + EditorPopupHelper.getInstance().showPopupInBestPositionFor(editor, popup); + } + else { + doImport(editor, candidates.iterator().next().getQualifiedName()); + } + } + } + + @RequiredWriteAction + private void doImport(Editor editor, String qName) { + Application.get().runWriteAction(() -> { + PsiElement element = myReference.getElement(); + ImportUtils.doImport(element, qName); + }); + } + + @Override + public boolean startInWriteAction() { + return false; + } + + @Override + @RequiredWriteAction + public boolean execute() { + PsiFile containingFile = myReference.getElement().getContainingFile(); + invoke(containingFile.getProject(), myEditor, containingFile); + + return true; + } + + @RequiredReadAction + private static void filterDefaultPackage(Collection candidates) { + for (Iterator i = candidates.iterator(); i.hasNext(); ) { + if (!i.next().getQualifiedName().contains(".")) { + i.remove(); + } + } + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/ECMAScriptImportOptimizer.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/ECMAScriptImportOptimizer.java index bfec99bb..5e6a6f71 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/ECMAScriptImportOptimizer.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/ECMAScriptImportOptimizer.java @@ -23,6 +23,7 @@ import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; import com.intellij.lang.javascript.validation.JSUnusedImportsHelper; import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.annotation.component.ExtensionImpl; import consulo.document.util.TextRange; import consulo.javascript.language.JavaScriptLanguage; @@ -34,312 +35,279 @@ import consulo.language.psi.*; import consulo.project.Project; import consulo.util.collection.MultiMap; +import consulo.util.lang.Couple; import consulo.util.lang.EmptyRunnable; import consulo.util.lang.Pair; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; + import java.util.*; /** * @author Maxim.Mossienko - * Date: Jul 23, 2008 - * Time: 12:10:44 AM + * @since 2008-07-23 */ @ExtensionImpl -public class ECMAScriptImportOptimizer implements ImportOptimizer -{ - @Override - public boolean supports(PsiFile file) - { - return file.getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4 || JavaScriptSupportLoader.isFlexMxmFile(file); - } - - @Override - @Nonnull - public Runnable processFile(final PsiFile file) - { - if(!FileModificationService.getInstance().prepareFileForWrite(file)) - { - return EmptyRunnable.INSTANCE; - } - - return new Runnable() - { - @Override - @RequiredReadAction - public void run() - { - final JSUnusedImportsHelper.Results unusedImportsResults = JSUnusedImportsHelper.getUnusedImports(file); - - MultiMap importsByHolder = new MultiMap() - { - @Override - protected Collection createCollection() - { - return new HashSet(); - } - }; - - Project project = file.getProject(); - final SmartPointerManager pointerManager = SmartPointerManager.getInstance(project); - final List oldImportsPointers = new ArrayList(unusedImportsResults.allImports.size()); - for(JSImportStatement anImport : unusedImportsResults.allImports) - { - oldImportsPointers.add(pointerManager.createSmartPsiElementPointer(anImport)); - if(unusedImportsResults.unusedImports.contains(anImport)) - { - continue; - } - - JSElement importHolder = ImportUtils.getImportHolder(anImport, JSFunction.class, JSPackageStatement.class, JSFile.class); - assert importHolder != null : "Import holder not found for " + anImport.getText(); - importsByHolder.putValue(importHolder, anImport.getImportText()); - } - - final List replaceWithShortName = new ArrayList(); - for(Map.Entry e : unusedImportsResults.fqnsToReplaceWithImport.entrySet()) - { - final Collection importsInScope; - final Collection importsInEnclosingScope; - final JSElement importHolder; - - JSElement enclosingFunction = ImportUtils.getImportHolder(e.getKey(), JSFunction.class); - JSElement enclosingPackage = ImportUtils.getImportHolder(e.getKey(), JSPackageStatement.class); - - if(enclosingFunction != null && !importsByHolder.get(enclosingFunction).isEmpty()) - { - importHolder = enclosingFunction; - importsInScope = importsByHolder.get(enclosingFunction); - importsInEnclosingScope = importsByHolder.get(enclosingPackage); - } - else if(enclosingPackage != null) - { - importHolder = enclosingPackage; - importsInScope = importsByHolder.get(enclosingPackage); - importsInEnclosingScope = Collections.emptyList(); - } - else - { - importHolder = ImportUtils.getImportHolder(e.getKey(), JSFile.class); - importsInScope = importsByHolder.get(importHolder); - importsInEnclosingScope = Collections.emptyList(); - } - - String fqn = e.getValue(); - - ResolveResult resolve = resolveUsingImports(importsInScope, fqn, file); - ResolveResult implicitResolve = resolveUsingImports(importsInEnclosingScope, fqn, file); - - if(resolve == ResolveResult.None && implicitResolve == ResolveResult.None) - { - importsByHolder.putValue(importHolder, fqn); - replaceWithShortName.add(pointerManager.createSmartPsiElementPointer(e.getKey())); - } - else if((resolve == ResolveResult.ThisOne || resolve == ResolveResult.None) && (implicitResolve == ResolveResult.ThisOne || implicitResolve == - ResolveResult.None)) - { - replaceWithShortName.add(pointerManager.createSmartPsiElementPointer(e.getKey())); - } - } - - final Collection, Collection>> importsByHolderPointer = new - ArrayList, Collection>>(importsByHolder.size()); - for(JSElement holder : importsByHolder.keySet()) - { - importsByHolderPointer.add(Pair.create(pointerManager.createSmartPsiElementPointer(holder), importsByHolder.get(holder))); - } - - for(Pair, Collection> entry : importsByHolderPointer) - { - JSElement holder = entry.getFirst().getElement(); - assert holder != null && holder.isValid(); - - Pair defaultInsertionPlace = ImportUtils.getImportInsertionPlace(holder); - boolean before = defaultInsertionPlace.second; - PsiElement insertionPlace = defaultInsertionPlace.first; - - PsiElement earlyImport = ImportUtils.findEarlyImport(before ? insertionPlace : insertionPlace.getNextSibling()); - Pair elementToDelete = null; - if(earlyImport != null) - { - for(PsiElement e = (before ? insertionPlace : insertionPlace.getNextSibling()); e != earlyImport; e = e.getNextSibling()) - { - if(!(e instanceof PsiWhiteSpace)) - { - break; - } - } - insertionPlace = earlyImport; - before = true; - PsiElement deleteTo = earlyImport; - while(deleteTo.getNextSibling() instanceof PsiWhiteSpace || deleteTo.getNextSibling() instanceof JSImportStatement) - { - deleteTo = deleteTo.getNextSibling(); - } - elementToDelete = Pair.create(insertionPlace, deleteTo); - } - else if(before && insertionPlace instanceof PsiWhiteSpace) - { - insertionPlace = insertionPlace.replace(JSChangeUtil.createJSTreeFromText(insertionPlace.getProject(), " ").getPsi()); - } - else if(insertionPlace.getNextSibling() instanceof PsiWhiteSpace) - { - insertionPlace.getNextSibling().replace(JSChangeUtil.createJSTreeFromText(insertionPlace.getProject(), " ").getPsi()); - } - - String importBlock = ImportUtils.createImportBlock(project, entry.getSecond()); - PsiElement newImports = PsiFileFactory.getInstance(project).createFileFromText("dummy.js", JavaScriptLanguage.INSTANCE, importBlock); - - PsiElement firstAdded; - if(before) - { - firstAdded = insertionPlace.getParent().addRangeBefore(newImports.getFirstChild(), newImports.getLastChild(), insertionPlace); - } - else - { - firstAdded = insertionPlace.getParent().addRangeAfter(newImports.getFirstChild(), newImports.getLastChild(), insertionPlace); - } - - if(elementToDelete != null) - { - deleteRange(elementToDelete.first, elementToDelete.second); - } - - PsiElement lastAdded = firstAdded; - final String lastImportText = newImports.getLastChild().getText(); - while(!lastImportText.equals(lastAdded.getText())) - { - lastAdded = lastAdded.getNextSibling(); - } - - PsiElement formatFrom = firstAdded.getPrevSibling() instanceof PsiWhiteSpace ? firstAdded.getPrevSibling() : firstAdded; - PsiElement formatTo = lastAdded.getNextSibling() instanceof PsiWhiteSpace ? lastAdded.getNextSibling() : lastAdded; - - PsiFile realFile = file.getContext() != null ? file.getContext().getContainingFile() : file; - - TextRange textRange = InjectedLanguageManager.getInstance(file.getProject()).injectedToHost(firstAdded, firstAdded.getTextRange()); - CodeStyleManager.getInstance(project).reformatText(realFile, textRange.getStartOffset(), textRange.getEndOffset()); - } - - for(SmartPsiElementPointer pointer : oldImportsPointers) - { - final JSImportStatement statement = (JSImportStatement) pointer.getElement(); - if(statement != null) - { - deleteImport(statement); - } - } - - for(SmartPsiElementPointer pointer : replaceWithShortName) - { - final JSReferenceExpression fqn = (JSReferenceExpression) pointer.getElement(); - if(fqn == null || !fqn.isValid()) - { - continue; - } - String name = fqn.getReferencedName().substring(fqn.getReferencedName().lastIndexOf('.') + 1); - fqn.replace(JSChangeUtil.createExpressionFromText(project, name)); - } - } - }; - } - - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } - - private enum ResolveResult - { - None, ThisOne, OtherOne - } - - private static ResolveResult resolveUsingImports(Collection imports, String fqnToCheck, PsiElement context) - { - String shortName = fqnToCheck.substring(fqnToCheck.lastIndexOf('.') + 1); - String firstOneResolved = null; - for(String anImport : imports) - { - String name = anImport.substring(anImport.lastIndexOf('.') + 1); - String resolvedFqn = null; - if(name.equals(shortName)) - { - resolvedFqn = anImport; - } - else if("*".equals(name)) - { - String qualifier = anImport.substring(0, anImport.lastIndexOf('.')); - if(JSResolveUtil.findClassByQName(qualifier + "." + shortName, context) != null) - { - resolvedFqn = qualifier + "." + shortName; - } - } - if(resolvedFqn != null) - { - if(firstOneResolved == null) - { - firstOneResolved = resolvedFqn; - } - else - { - assert !firstOneResolved.equals(resolvedFqn); - return ResolveResult.OtherOne; - } - } - } - - if(firstOneResolved == null) - { - return ResolveResult.None; - } - else - { - return fqnToCheck.equals(firstOneResolved) ? ResolveResult.ThisOne : ResolveResult.OtherOne; - } - } - - private static void deleteImport(final JSImportStatement anImport) - { - if(!anImport.isValid()) - { - return; - } - PsiElement nextSibling = anImport.getNextSibling(); - if(nextSibling instanceof PsiWhiteSpace) - { - // remove with the following whitespace - String whitespace = nextSibling.getText(); - if(whitespace.contains("]]>")) - { - nextSibling.replace(JSChangeUtil.createJSTreeFromText(anImport.getProject(), "]]>").getPsi()); - } - // don't remove trailing line break if it is an injection suffix - else if(nextSibling.getNextSibling() == null || nextSibling.getNextSibling().getNode().getElementType() != JSTokenTypes.RBRACE || - !(nextSibling.getParent() instanceof JSBlockStatement) || - !ImportUtils.isAnonymousEventHandler((JSBlockStatement) nextSibling.getParent())) - { - nextSibling.delete(); - } - } - anImport.delete(); - } - - private static void deleteRange(PsiElement first, PsiElement last) - { - PsiElement e = first; - while(true) - { - PsiElement next = e.getNextSibling(); - e.delete(); - if(e == last) - { - break; - } - assert next != null; - e = next; - } - } - +public class ECMAScriptImportOptimizer implements ImportOptimizer { + @Override + @RequiredReadAction + public boolean supports(PsiFile file) { + return file.getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4 || JavaScriptSupportLoader.isFlexMxmFile(file); + } + + @Override + @Nonnull + public Runnable processFile(final PsiFile file) { + if (!FileModificationService.getInstance().prepareFileForWrite(file)) { + return EmptyRunnable.INSTANCE; + } + + return new Runnable() { + @Override + @RequiredWriteAction + public void run() { + JSUnusedImportsHelper.Results unusedImportsResults = JSUnusedImportsHelper.getUnusedImports(file); + + MultiMap importsByHolder = new MultiMap<>() { + @Override + protected Collection createCollection() { + return new HashSet<>(); + } + }; + + Project project = file.getProject(); + SmartPointerManager pointerManager = SmartPointerManager.getInstance(project); + List oldImportsPointers = + new ArrayList<>(unusedImportsResults.allImports.size()); + for (JSImportStatement anImport : unusedImportsResults.allImports) { + oldImportsPointers.add(pointerManager.createSmartPsiElementPointer(anImport)); + if (unusedImportsResults.unusedImports.contains(anImport)) { + continue; + } + + JSElement importHolder = + ImportUtils.getImportHolder(anImport, JSFunction.class, JSPackageStatement.class, JSFile.class); + assert importHolder != null : "Import holder not found for " + anImport.getText(); + importsByHolder.putValue(importHolder, anImport.getImportText()); + } + + List replaceWithShortName = new ArrayList<>(); + for (Map.Entry e : unusedImportsResults.fqnsToReplaceWithImport.entrySet()) { + Collection importsInScope; + Collection importsInEnclosingScope; + JSElement importHolder; + + JSElement enclosingFunction = ImportUtils.getImportHolder(e.getKey(), JSFunction.class); + JSElement enclosingPackage = ImportUtils.getImportHolder(e.getKey(), JSPackageStatement.class); + + if (enclosingFunction != null && !importsByHolder.get(enclosingFunction).isEmpty()) { + importHolder = enclosingFunction; + importsInScope = importsByHolder.get(enclosingFunction); + importsInEnclosingScope = importsByHolder.get(enclosingPackage); + } + else if (enclosingPackage != null) { + importHolder = enclosingPackage; + importsInScope = importsByHolder.get(enclosingPackage); + importsInEnclosingScope = Collections.emptyList(); + } + else { + importHolder = ImportUtils.getImportHolder(e.getKey(), JSFile.class); + importsInScope = importsByHolder.get(importHolder); + importsInEnclosingScope = Collections.emptyList(); + } + + String fqn = e.getValue(); + + ResolveResult resolve = resolveUsingImports(importsInScope, fqn, file); + ResolveResult implicitResolve = resolveUsingImports(importsInEnclosingScope, fqn, file); + + if (resolve == ResolveResult.None && implicitResolve == ResolveResult.None) { + importsByHolder.putValue(importHolder, fqn); + replaceWithShortName.add(pointerManager.createSmartPsiElementPointer(e.getKey())); + } + else if ((resolve == ResolveResult.ThisOne || resolve == ResolveResult.None) + && (implicitResolve == ResolveResult.ThisOne || implicitResolve == ResolveResult.None)) { + replaceWithShortName.add(pointerManager.createSmartPsiElementPointer(e.getKey())); + } + } + + Collection, Collection>> importsByHolderPointer = + new ArrayList<>(importsByHolder.size()); + for (JSElement holder : importsByHolder.keySet()) { + importsByHolderPointer.add(Pair.create( + pointerManager.createSmartPsiElementPointer(holder), + importsByHolder.get(holder) + )); + } + + for (Pair, Collection> entry : importsByHolderPointer) { + JSElement holder = entry.getFirst().getElement(); + assert holder != null && holder.isValid(); + + Pair defaultInsertionPlace = ImportUtils.getImportInsertionPlace(holder); + boolean before = defaultInsertionPlace.second; + PsiElement insertionPlace = defaultInsertionPlace.first; + + PsiElement earlyImport = ImportUtils.findEarlyImport(before ? insertionPlace : insertionPlace.getNextSibling()); + Couple elementToDelete = null; + if (earlyImport != null) { + for (PsiElement e = (before ? insertionPlace : insertionPlace.getNextSibling()); e != earlyImport; + e = e.getNextSibling()) { + if (!(e instanceof PsiWhiteSpace)) { + break; + } + } + insertionPlace = earlyImport; + before = true; + PsiElement deleteTo = earlyImport; + while (deleteTo.getNextSibling() instanceof PsiWhiteSpace + || deleteTo.getNextSibling() instanceof JSImportStatement) { + deleteTo = deleteTo.getNextSibling(); + } + elementToDelete = Couple.of(insertionPlace, deleteTo); + } + else if (before && insertionPlace instanceof PsiWhiteSpace) { + insertionPlace = + insertionPlace.replace(JSChangeUtil.createJSTreeFromText(insertionPlace.getProject(), " ").getPsi()); + } + else if (insertionPlace.getNextSibling() instanceof PsiWhiteSpace whiteSpace) { + whiteSpace.replace(JSChangeUtil.createJSTreeFromText(insertionPlace.getProject(), " ").getPsi()); + } + + String importBlock = ImportUtils.createImportBlock(project, entry.getSecond()); + PsiElement newImports = + PsiFileFactory.getInstance(project).createFileFromText("dummy.js", JavaScriptLanguage.INSTANCE, importBlock); + + PsiElement firstAdded; + if (before) { + firstAdded = insertionPlace.getParent() + .addRangeBefore(newImports.getFirstChild(), newImports.getLastChild(), insertionPlace); + } + else { + firstAdded = + insertionPlace.getParent().addRangeAfter(newImports.getFirstChild(), newImports.getLastChild(), insertionPlace); + } + + if (elementToDelete != null) { + deleteRange(elementToDelete.first, elementToDelete.second); + } + + PsiElement lastAdded = firstAdded; + String lastImportText = newImports.getLastChild().getText(); + while (!lastImportText.equals(lastAdded.getText())) { + lastAdded = lastAdded.getNextSibling(); + } + + PsiElement formatFrom = firstAdded.getPrevSibling() instanceof PsiWhiteSpace ? firstAdded.getPrevSibling() : firstAdded; + PsiElement formatTo = lastAdded.getNextSibling() instanceof PsiWhiteSpace ? lastAdded.getNextSibling() : lastAdded; + + PsiFile realFile = file.getContext() != null ? file.getContext().getContainingFile() : file; + + TextRange textRange = + InjectedLanguageManager.getInstance(file.getProject()).injectedToHost(firstAdded, firstAdded.getTextRange()); + CodeStyleManager.getInstance(project).reformatText(realFile, textRange.getStartOffset(), textRange.getEndOffset()); + } + + for (SmartPsiElementPointer pointer : oldImportsPointers) { + JSImportStatement statement = (JSImportStatement)pointer.getElement(); + if (statement != null) { + deleteImport(statement); + } + } + + for (SmartPsiElementPointer pointer : replaceWithShortName) { + JSReferenceExpression fqn = (JSReferenceExpression)pointer.getElement(); + if (fqn == null || !fqn.isValid()) { + continue; + } + String name = fqn.getReferencedName().substring(fqn.getReferencedName().lastIndexOf('.') + 1); + fqn.replace(JSChangeUtil.createExpressionFromText(project, name)); + } + } + }; + } + + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } + + private enum ResolveResult { + None, + ThisOne, + OtherOne + } + + @RequiredReadAction + private static ResolveResult resolveUsingImports(Collection imports, String fqnToCheck, PsiElement context) { + String shortName = fqnToCheck.substring(fqnToCheck.lastIndexOf('.') + 1); + String firstOneResolved = null; + for (String anImport : imports) { + String name = anImport.substring(anImport.lastIndexOf('.') + 1); + String resolvedFqn = null; + if (name.equals(shortName)) { + resolvedFqn = anImport; + } + else if ("*".equals(name)) { + String qualifier = anImport.substring(0, anImport.lastIndexOf('.')); + if (JSResolveUtil.findClassByQName(qualifier + "." + shortName, context) != null) { + resolvedFqn = qualifier + "." + shortName; + } + } + if (resolvedFqn != null) { + if (firstOneResolved == null) { + firstOneResolved = resolvedFqn; + } + else { + assert !firstOneResolved.equals(resolvedFqn); + return ResolveResult.OtherOne; + } + } + } + + if (firstOneResolved == null) { + return ResolveResult.None; + } + else { + return fqnToCheck.equals(firstOneResolved) ? ResolveResult.ThisOne : ResolveResult.OtherOne; + } + } + + @RequiredWriteAction + private static void deleteImport(JSImportStatement anImport) { + if (!anImport.isValid()) { + return; + } + PsiElement nextSibling = anImport.getNextSibling(); + if (nextSibling instanceof PsiWhiteSpace whiteSpace) { + // remove with the following whitespace + String whitespace = whiteSpace.getText(); + if (whitespace.contains("]]>")) { + whiteSpace.replace(JSChangeUtil.createJSTreeFromText(anImport.getProject(), "]]>").getPsi()); + } + // don't remove trailing line break if it is an injection suffix + else if (whiteSpace.getNextSibling() == null + || whiteSpace.getNextSibling().getNode().getElementType() != JSTokenTypes.RBRACE + || !(whiteSpace.getParent() instanceof JSBlockStatement block) + || !ImportUtils.isAnonymousEventHandler(block)) { + nextSibling.delete(); + } + } + anImport.delete(); + } + + @RequiredReadAction + private static void deleteRange(PsiElement first, PsiElement last) { + PsiElement e = first; + while (true) { + PsiElement next = e.getNextSibling(); + e.delete(); + if (e == last) { + break; + } + assert next != null; + e = next; + } + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/ImportUtils.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/ImportUtils.java index 4c8cc091..b372684c 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/ImportUtils.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/ImportUtils.java @@ -21,6 +21,8 @@ import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.impl.JSChangeUtil; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.document.Document; import consulo.document.util.TextRange; import consulo.language.codeStyle.CodeStyleManager; @@ -40,347 +42,282 @@ import consulo.xml.psi.xml.XmlAttributeValue; import consulo.xml.psi.xml.XmlTag; import consulo.xml.psi.xml.XmlText; -import org.jetbrains.annotations.NonNls; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.*; /** * @author Maxim.Mossienko - * Date: May 3, 2008 - * Time: 8:35:33 PM + * @since 2008-03-03 */ -public class ImportUtils -{ - @NonNls - private static final String CDATA = "> ANONYMOUS_EVENT_LISTENER_CLASSES = Arrays.asList(JSBlockStatement.class, - JSFunctionExpression.class, JSParenthesizedExpression.class, JSCallExpression.class, JSExpressionStatement.class, JSFile.class); - - @Nullable - private static PsiElement findLBrace(final JSElement holder) - { - for(PsiElement child = holder.getFirstChild(); child != null; child = child.getNextSibling()) - { - if(child.getNode().getElementType() == JSTokenTypes.LBRACE) - { - return child; - } - } - return null; - } - - private static PsiElement specifyInsertionPlace(PsiElement insertBefore, String fqn) - { - JSImportStatement earlyImport = findEarlyImport(insertBefore); - if(earlyImport == null) - { - return insertBefore; - } - - while(compareImports(fqn, earlyImport.getImportText()) > 0) - { - if(earlyImport.getNextSibling() instanceof JSImportStatement) - { - earlyImport = (JSImportStatement) earlyImport.getNextSibling(); - } - else if(earlyImport.getNextSibling() instanceof PsiWhiteSpace && earlyImport.getNextSibling().getNextSibling() instanceof JSImportStatement) - { - earlyImport = (JSImportStatement) earlyImport.getNextSibling().getNextSibling(); - } - else - { - return earlyImport.getNextSibling(); - } - } - return earlyImport; - } - - public static void doImport(@Nonnull PsiElement subject, final @Nonnull String fqn) - { - assert fqn.contains(".") : "Qualified name belongs to default package: " + fqn; - - if(!FileModificationService.getInstance().prepareFileForWrite(subject.getContainingFile())) - { - return; - } - Project project = subject.getProject(); - - final JSReferenceExpression refExpr = PsiTreeUtil.getNonStrictParentOfType(subject, JSReferenceExpression.class); - if(refExpr != null && JSResolveUtil.referenceExpressionShouldBeQualified(refExpr)) - { - refExpr.replace(JSChangeUtil.createExpressionFromText(project, fqn)); // TODO should commit corresponding document before? - return; - } - - JSElement importHolder = getImportHolder(subject, JSPackageStatement.class, JSFile.class); - if(importHolder == null) - { // importHolder is null when completing js2 class name from js code - return; - } - - PsiFile file = importHolder.getContainingFile(); - Document document = PsiDocumentManager.getInstance(project).getDocument(file); - PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(document); - - String textToInsert = createImportBlock(project, Collections.singletonList(fqn)); - - Pair insertionPlace = getImportInsertionPlace(importHolder); - if(!insertionPlace.second && insertionPlace.first.getNextSibling() != null) - { - insertionPlace = Pair.create(insertionPlace.first.getNextSibling(), true); - } - - final int offset; - final String prefix; - final String suffix; - if(insertionPlace.second) - { - PsiElement insertBefore = specifyInsertionPlace(insertionPlace.first, fqn); - offset = insertBefore.getTextRange().getStartOffset(); - prefix = (insertBefore.getPrevSibling() == null && file.getContext() == null) || insertBefore.getPrevSibling() instanceof PsiWhiteSpace ? "" : - "\n"; - suffix = insertBefore instanceof PsiWhiteSpace ? "" : " "; - } - else - { - offset = insertionPlace.first.getTextRange().getEndOffset(); - prefix = insertionPlace.first instanceof PsiWhiteSpace ? "" : "\n"; - suffix = ""; - } - - document.insertString(offset, prefix + textToInsert + suffix); - PsiDocumentManager.getInstance(project).commitDocument(document); - - PsiElement inserted = file.findElementAt(offset); - if(prefix.length() > 0) - { - if(inserted.getNextSibling() instanceof JSImportStatement) - { - inserted = inserted.getNextSibling(); - } - } - else - { - JSImportStatement importStatement = PsiTreeUtil.getParentOfType(inserted, JSImportStatement.class); - if(importStatement != null) - { - inserted = importStatement; - } - } - PsiElement formatFrom = inserted.getPrevSibling() instanceof PsiWhiteSpace ? inserted.getPrevSibling() : inserted; - PsiElement formatTo = inserted.getNextSibling() instanceof PsiWhiteSpace ? inserted.getNextSibling() : inserted; - - PsiFile realFile = file.getContext() != null ? file.getContext().getContainingFile() : file; - final TextRange injectionOffset = InjectedLanguageManager.getInstance(project).injectedToHost(inserted, inserted.getTextRange()); - - CodeStyleManager.getInstance(project).reformatText(realFile, injectionOffset.getStartOffset() + formatFrom.getTextRange().getStartOffset(), - injectionOffset.getEndOffset() + formatTo.getTextRange().getEndOffset()); - } - - private static JSElement getAnonymousEventHandlerBody(JSFile injectedFile) - { - // TODO more elegant way?! - if(injectedFile.getFirstChild() instanceof JSExpressionStatement) - { - JSExpressionStatement expressionStatement = (JSExpressionStatement) injectedFile.getFirstChild(); - if(expressionStatement.getExpression() instanceof JSCallExpression) - { - JSCallExpression callExpression = (JSCallExpression) expressionStatement.getExpression(); - if(callExpression.getMethodExpression() instanceof JSParenthesizedExpression) - { - JSParenthesizedExpression parenthesizedExpression = (JSParenthesizedExpression) callExpression.getMethodExpression(); - if(parenthesizedExpression.getInnerExpression() instanceof JSFunctionExpression) - { - JSFunctionExpression functionExpression = (JSFunctionExpression) parenthesizedExpression.getInnerExpression(); - JSFunction function = functionExpression.getFunction(); - if(function.getBody().length > 0) - { - return function.getBody()[0]; - } - } - } - } - } - assert false : "Couldn't find anonymous event handler body: " + injectedFile; - return null; - } - - private static boolean isAnonymousEventHandlerTag(JSFile jsFile) - { - PsiElement context = jsFile.getContext(); - return context instanceof XmlText && !SCRIPT_TAG_NAME.equals(((XmlTag) context.getParent()).getLocalName()); - } - - private static boolean isAnonymousEventHandlerAttribute(JSFile jsFile) - { - PsiElement context = jsFile.getContext(); - return context instanceof XmlAttributeValue; - } - - public static boolean isAnonymousEventHandler(JSBlockStatement block) - { - JSFile file = (JSFile) iterateUp(block, ANONYMOUS_EVENT_LISTENER_CLASSES); - return file != null && (isAnonymousEventHandlerTag(file) || isAnonymousEventHandlerAttribute(file)); - } - - @Nullable - private static PsiElement iterateUp(PsiElement element, List> classes) - { - Iterator> i = classes.iterator(); - while(i.hasNext()) - { - if(element == null || !i.next().isInstance(element)) - { - return null; - } - if(i.hasNext()) - { - element = element.getParent(); - } - } - return element; - } - - @Nullable - private static JSElement getImportHolderFromXmlBackedClass(final XmlBackedJSClassImpl jsClass) - { - try - { - return jsClass.createOrGetFirstScriptTag(); - } - catch(IncorrectOperationException ex) - { - Logger.getInstance(ImportUtils.class.getName()).error(ex); - } - return null; - } - - - private static int compareImports(String qname1, String qname2) - { - // TODO keep certain classes at the top - return Comparing.compare(qname1, qname2); - } - - public static Pair getImportInsertionPlace(JSElement holder) - { - PsiElement insertionPlace; - final boolean before; - if(holder instanceof JSPackageStatement) - { - insertionPlace = findLBrace(holder); - assert insertionPlace != null : "LBrace not found"; - before = false; - } - else if(holder instanceof JSFunction) - { - final JSBlockStatement block = PsiTreeUtil.getChildOfType(holder, JSBlockStatement.class); - assert block != null : "Function block not found"; - insertionPlace = findLBrace(block); - before = false; - } - else - { //JSFile - if(isAnonymousEventHandlerTag((JSFile) holder)) - { - holder = getAnonymousEventHandlerBody((JSFile) holder); - insertionPlace = findLBrace(holder); - if(hasCDATA(insertionPlace.getNextSibling())) - { - insertionPlace = insertionPlace.getNextSibling(); - } - before = false; - } - else - { - JSPackageStatement aPackage = PsiTreeUtil.getChildOfType(holder, JSPackageStatement.class); - if(aPackage != null) - { - insertionPlace = aPackage; - before = false; - } - else - { - insertionPlace = holder.getFirstChild(); - before = !hasCDATA(insertionPlace); - } - } - } - return Pair.create(insertionPlace, before); - } - - private static boolean hasCDATA(@Nullable PsiElement element) - { - return element instanceof PsiWhiteSpace && element.getText().contains(CDATA); - } - - @Nullable - public static JSElement getImportHolder(PsiElement origin, Class... classes) - { - if(origin instanceof XmlBackedJSClassImpl) - { - return getImportHolderFromXmlBackedClass((XmlBackedJSClassImpl) origin); - } - - JSElement importHolder = PsiTreeUtil.getParentOfType(origin, classes); - if(importHolder instanceof JSFunctionExpression && (isAnonymousEventHandlerTag((JSFile) importHolder.getContainingFile()) || - isAnonymousEventHandlerAttribute((JSFile) importHolder.getContainingFile()))) - { - importHolder = ArrayUtil.contains(JSFile.class, classes) ? (JSElement) importHolder.getContainingFile() : null; - } - - if(importHolder instanceof JSFile) - { - if(isAnonymousEventHandlerAttribute((JSFile) importHolder)) - { - XmlBackedJSClassImpl jsClass = JSResolveUtil.getXmlBackedClass((JSFile) importHolder); - assert jsClass != null; - importHolder = getImportHolderFromXmlBackedClass(jsClass); - } - } - return importHolder; - } - - public static String createImportBlock(Project project, Collection fqns) - { - List sorted = new ArrayList(fqns); - Collections.sort(sorted, new Comparator() - { - @Override - public int compare(final String o1, final String o2) - { - return compareImports(o1, o2); - } - }); - - final String semicolon = JSChangeUtil.getSemicolon(project); - StringBuilder s = new StringBuilder(); - for(String fqn : sorted) - { - s.append("import ").append(fqn).append(semicolon); - } - return s.toString(); - } - - @Nullable - public static JSImportStatement findEarlyImport(@Nullable PsiElement startFrom) - { - for(PsiElement element = startFrom; element != null; element = element.getNextSibling()) - { - if(element instanceof JSImportStatement) - { - return (JSImportStatement) element; - } - if(element instanceof JSClass || element instanceof JSStatement || element instanceof JSFunction) - { - break; - } - } - return null; - } +public class ImportUtils { + private static final String CDATA = "> ANONYMOUS_EVENT_LISTENER_CLASSES = Arrays.asList(JSBlockStatement.class, + JSFunctionExpression.class, JSParenthesizedExpression.class, JSCallExpression.class, JSExpressionStatement.class, JSFile.class + ); + + @Nullable + @RequiredReadAction + private static PsiElement findLBrace(JSElement holder) { + for (PsiElement child = holder.getFirstChild(); child != null; child = child.getNextSibling()) { + if (child.getNode().getElementType() == JSTokenTypes.LBRACE) { + return child; + } + } + return null; + } + + @RequiredReadAction + private static PsiElement specifyInsertionPlace(PsiElement insertBefore, String fqn) { + JSImportStatement earlyImport = findEarlyImport(insertBefore); + if (earlyImport == null) { + return insertBefore; + } + + while (compareImports(fqn, earlyImport.getImportText()) > 0) { + if (earlyImport.getNextSibling() instanceof JSImportStatement importStatement) { + earlyImport = importStatement; + } + else if (earlyImport.getNextSibling() instanceof PsiWhiteSpace whiteSpace + && whiteSpace.getNextSibling() instanceof JSImportStatement importStatement) { + earlyImport = importStatement; + } + else { + return earlyImport.getNextSibling(); + } + } + return earlyImport; + } + + @RequiredWriteAction + public static void doImport(@Nonnull PsiElement subject, @Nonnull String fqn) { + assert fqn.contains(".") : "Qualified name belongs to default package: " + fqn; + + if (!FileModificationService.getInstance().prepareFileForWrite(subject.getContainingFile())) { + return; + } + Project project = subject.getProject(); + + JSReferenceExpression refExpr = PsiTreeUtil.getNonStrictParentOfType(subject, JSReferenceExpression.class); + if (refExpr != null && JSResolveUtil.referenceExpressionShouldBeQualified(refExpr)) { + refExpr.replace(JSChangeUtil.createExpressionFromText(project, fqn)); // TODO should commit corresponding document before? + return; + } + + JSElement importHolder = getImportHolder(subject, JSPackageStatement.class, JSFile.class); + if (importHolder == null) { // importHolder is null when completing js2 class name from js code + return; + } + + PsiFile file = importHolder.getContainingFile(); + Document document = PsiDocumentManager.getInstance(project).getDocument(file); + PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(document); + + String textToInsert = createImportBlock(project, Collections.singletonList(fqn)); + + Pair insertionPlace = getImportInsertionPlace(importHolder); + if (!insertionPlace.second && insertionPlace.first.getNextSibling() != null) { + insertionPlace = Pair.create(insertionPlace.first.getNextSibling(), true); + } + + int offset; + String prefix; + String suffix; + if (insertionPlace.second) { + PsiElement insertBefore = specifyInsertionPlace(insertionPlace.first, fqn); + offset = insertBefore.getTextRange().getStartOffset(); + prefix = (insertBefore.getPrevSibling() == null && file.getContext() == null) + || insertBefore.getPrevSibling() instanceof PsiWhiteSpace ? "" : "\n"; + suffix = insertBefore instanceof PsiWhiteSpace ? "" : " "; + } + else { + offset = insertionPlace.first.getTextRange().getEndOffset(); + prefix = insertionPlace.first instanceof PsiWhiteSpace ? "" : "\n"; + suffix = ""; + } + + document.insertString(offset, prefix + textToInsert + suffix); + PsiDocumentManager.getInstance(project).commitDocument(document); + + PsiElement inserted = file.findElementAt(offset); + if (prefix.length() > 0) { + if (inserted.getNextSibling() instanceof JSImportStatement importStatement) { + inserted = importStatement; + } + } + else { + JSImportStatement importStatement = PsiTreeUtil.getParentOfType(inserted, JSImportStatement.class); + if (importStatement != null) { + inserted = importStatement; + } + } + PsiElement formatFrom = inserted.getPrevSibling() instanceof PsiWhiteSpace prevWhiteSpace ? prevWhiteSpace : inserted; + PsiElement formatTo = inserted.getNextSibling() instanceof PsiWhiteSpace nextWhiteSpace ? nextWhiteSpace : inserted; + + PsiFile realFile = file.getContext() != null ? file.getContext().getContainingFile() : file; + TextRange injectionOffset = InjectedLanguageManager.getInstance(project).injectedToHost(inserted, inserted.getTextRange()); + + CodeStyleManager.getInstance(project).reformatText( + realFile, + injectionOffset.getStartOffset() + formatFrom.getTextRange().getStartOffset(), + injectionOffset.getEndOffset() + formatTo.getTextRange().getEndOffset() + ); + } + + @RequiredReadAction + private static JSElement getAnonymousEventHandlerBody(JSFile injectedFile) { + if (injectedFile.getFirstChild() instanceof JSExpressionStatement expression + && expression.getExpression() instanceof JSCallExpression call + && call.getMethodExpression() instanceof JSParenthesizedExpression parenthesized + && parenthesized.getInnerExpression() instanceof JSFunctionExpression functionExpr) { + + JSFunction function = functionExpr.getFunction(); + if (function.getBody().length > 0) { + return function.getBody()[0]; + } + } + assert false : "Couldn't find anonymous event handler body: " + injectedFile; + return null; + } + + private static boolean isAnonymousEventHandlerTag(JSFile jsFile) { + PsiElement context = jsFile.getContext(); + return context instanceof XmlText xmlText && !SCRIPT_TAG_NAME.equals(((XmlTag)xmlText.getParent()).getLocalName()); + } + + private static boolean isAnonymousEventHandlerAttribute(JSFile jsFile) { + PsiElement context = jsFile.getContext(); + return context instanceof XmlAttributeValue; + } + + public static boolean isAnonymousEventHandler(JSBlockStatement block) { + JSFile file = (JSFile)iterateUp(block, ANONYMOUS_EVENT_LISTENER_CLASSES); + return file != null && (isAnonymousEventHandlerTag(file) || isAnonymousEventHandlerAttribute(file)); + } + + @Nullable + private static PsiElement iterateUp(PsiElement element, List> classes) { + Iterator> i = classes.iterator(); + while (i.hasNext()) { + if (element == null || !i.next().isInstance(element)) { + return null; + } + if (i.hasNext()) { + element = element.getParent(); + } + } + return element; + } + + @Nullable + @RequiredReadAction + private static JSElement getImportHolderFromXmlBackedClass(XmlBackedJSClassImpl jsClass) { + try { + return jsClass.createOrGetFirstScriptTag(); + } + catch (IncorrectOperationException ex) { + Logger.getInstance(ImportUtils.class).error(ex); + } + return null; + } + + + private static int compareImports(String qname1, String qname2) { + // TODO keep certain classes at the top + return Comparing.compare(qname1, qname2); + } + + @RequiredReadAction + public static Pair getImportInsertionPlace(JSElement holder) { + PsiElement insertionPlace; + boolean before; + if (holder instanceof JSPackageStatement packageStatement) { + insertionPlace = findLBrace(packageStatement); + assert insertionPlace != null : "LBrace not found"; + before = false; + } + else if (holder instanceof JSFunction function) { + JSBlockStatement block = PsiTreeUtil.getChildOfType(function, JSBlockStatement.class); + assert block != null : "Function block not found"; + insertionPlace = findLBrace(block); + before = false; + } + else if (holder instanceof JSFile jsFile && isAnonymousEventHandlerTag(jsFile)) { + holder = getAnonymousEventHandlerBody(jsFile); + insertionPlace = findLBrace(holder); + if (hasCDATA(insertionPlace.getNextSibling())) { + insertionPlace = insertionPlace.getNextSibling(); + } + before = false; + } + else { + JSPackageStatement aPackage = PsiTreeUtil.getChildOfType(holder, JSPackageStatement.class); + if (aPackage != null) { + insertionPlace = aPackage; + before = false; + } + else { + insertionPlace = holder.getFirstChild(); + before = !hasCDATA(insertionPlace); + } + } + return Pair.create(insertionPlace, before); + } + + @RequiredReadAction + private static boolean hasCDATA(@Nullable PsiElement element) { + return element instanceof PsiWhiteSpace whiteSpace && whiteSpace.getText().contains(CDATA); + } + + @Nullable + @RequiredReadAction + @SafeVarargs + public static JSElement getImportHolder(PsiElement origin, Class... classes) { + if (origin instanceof XmlBackedJSClassImpl xmlBackedJSClass) { + return getImportHolderFromXmlBackedClass(xmlBackedJSClass); + } + + JSElement importHolder = PsiTreeUtil.getParentOfType(origin, classes); + if (importHolder instanceof JSFunctionExpression functionExpr + && functionExpr.getContainingFile() instanceof JSFile jsFile + && (isAnonymousEventHandlerTag(jsFile) || isAnonymousEventHandlerAttribute(jsFile))) { + importHolder = ArrayUtil.contains(JSFile.class, classes) ? jsFile : null; + } + + if (importHolder instanceof JSFile jsFile && isAnonymousEventHandlerAttribute(jsFile)) { + XmlBackedJSClassImpl jsClass = JSResolveUtil.getXmlBackedClass(jsFile); + assert jsClass != null; + importHolder = getImportHolderFromXmlBackedClass(jsClass); + } + return importHolder; + } + + public static String createImportBlock(Project project, Collection fqns) { + List sorted = new ArrayList<>(fqns); + Collections.sort(sorted, ImportUtils::compareImports); + + String semicolon = JSChangeUtil.getSemicolon(project); + StringBuilder s = new StringBuilder(); + for (String fqn : sorted) { + s.append("import ").append(fqn).append(semicolon); + } + return s.toString(); + } + + @Nullable + @RequiredReadAction + public static JSImportStatement findEarlyImport(@Nullable PsiElement startFrom) { + for (PsiElement element = startFrom; element != null; element = element.getNextSibling()) { + if (element instanceof JSImportStatement importStatement) { + return importStatement; + } + if (element instanceof JSClass || element instanceof JSStatement || element instanceof JSFunction) { + break; + } + } + return null; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/AS3InterfaceDumper.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/AS3InterfaceDumper.java index 5297d6a7..e0d2f1f1 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/AS3InterfaceDumper.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/AS3InterfaceDumper.java @@ -16,261 +16,215 @@ package com.intellij.lang.javascript.impl.flex.importer; -import org.jetbrains.annotations.NonNls; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.Set; /** * @author Maxim.Mossienko - * Date: Oct 20, 2008 - * Time: 7:02:29 PM + * @since 2008-10-20 */ -class AS3InterfaceDumper extends AbstractDumpProcessor -{ - private int memberCount; - private boolean isInterface; - - @Override - public void dumpStat(@Nonnull final String stat) - { - } - - @Override - public void dumpToplevelAnonymousMethod(final @Nonnull Abc abc, final @Nonnull MethodInfo m) - { - } - - @Override - public void dumpTopLevelTraits(final Abc abc, final @Nonnull Traits t, final String indent) - { - t.dump(abc, indent, "", this); - } - - @Override - public boolean doDumpMember(final @Nonnull MemberInfo memberInfo) - { - if(memberInfo.name == null) - { - return false; - } - if(memberInfo.name.name != null && memberInfo.name.name.indexOf(Abc.$CINIT) >= 0) - { - return false; - } - return true; - } - - @Override - public void appendMethodSeparator() - { - append((++memberCount % 5) == 0 ? "\n" : ""); - } - - @Override - public void appendFieldSeparator() - { - appendMethodSeparator(); - } - - @Override - public String getAbcInSwfIndent() - { - return ""; - } - - @Override - public void processValue(final Multiname typeName, final Object valueObject) - { - append(" = "); - append(getValueRepr(valueObject)); - } - - protected static String getValueRepr(Object valueObject) - { - if(valueObject == null) - { - return null; - } - @NonNls String value = valueObject.toString(); - char ch; - - if(needsQuoting(value)) - { - boolean doQoute = true; - - if(value.indexOf('.') != -1) - { - try - { - Double.parseDouble(value); - doQoute = false; - } - catch(NumberFormatException ex) - { - } - } - else if(value.length() > 0 && (Character.isDigit(ch = value.charAt(0)) || (ch == '-' && value.length() > 1 && Character.isDigit(value.charAt(1) - )))) - { - try - { - Integer.parseInt(value); - doQoute = false; - } - catch(NumberFormatException ex) - { - } - } - - if(doQoute) - { - value = "\"" + quote(value) + "\""; - } - } - return value; - } - - private static - @NonNls - Set doNotNeedQoting = Set.of("null", "NaN", "undefined", "true", "false", "Infinity", "-Infinity"); - - private static boolean needsQuoting(final String value) - { - return !doNotNeedQoting.contains(value); - } - - @Override - public boolean doDumpMetaData(final @Nonnull MetaData md) - { - return md.name.indexOf("__") == -1; - } - - @Override - public void processParameter(@Nonnull String name, @Nullable Multiname type, String parentName, @Nullable Multiname value, boolean rest) - { - if(rest) - { - append("... "); - append(name); - } - else - { - append(name); - append(":"); - processMultinameAsPackageName(type, parentName, true); - if(value != null) - { - processValue(type, value); - } - } - } - - @Override - public boolean doStarTypeDumpInExtends() - { - return false; - } - - @Override - public boolean doStarMetaAttrNameDump() - { - return false; - } - - @Override - public void setProcessingInterface(final boolean anInterface) - { - isInterface = anInterface; - } - - @Override - public void hasError(@Nonnull final String error) - { - sb.append("/*" + error + "*/"); - } - - @Override - public void processMultinameAsPackageName(Multiname name, String parentName, boolean verbose) - { - append(getMultinameAsPackageName(name, parentName, verbose)); - } - - protected static String getMultinameAsPackageName(Multiname name, String parentName, boolean verbose) - { - if(name.hasNotEmptyNs()) - { - if(name.hasNamespace() || (!verbose && parentName != null && - (parentName.equals(name.nsset[0].replaceAll(":", "::"))) || (parentName != null && parentName.equals(name.toString())))) - { - return name.name; - } - - return name.nsset[0] + "." + name.name; - } - - return name.toString(); - } - - @Override - protected String appendModifiers(MemberInfo member, String attr) - { - @NonNls String s = attr; - - s += "native "; - boolean hasNs = false; - if(member.name != null && member.name.hasNotEmptyNs() && member.name.hasNamespace()) - { - hasNs = true; - s += member.name.getNsName() + " "; - } - - if(s.indexOf("private") == -1 && !hasNs && !isInterface) - { - @NonNls String parentName; - - if(member.isPublic || - member.name.nsset[0].length() == 0 || - (member.parentTraits != null && ((parentName = member.parentTraits.name.toString()).equals(member.name.toString()) || parentName.startsWith - ("script")))) - { - s += "public "; - } - else - { - s += "protected "; - } - } - - if(member.isFinal) - { - s += "final "; - } - if(member.isOverride) - { - s += "override "; - } - return s; - } - - @Override - public void processFunction(MethodInfo methodInfo, boolean referenceNameRequested, Abc abc, String indent, String attr) - { - super.processFunction(methodInfo, referenceNameRequested, abc, indent, attr); - append(";\n"); - } - - @Override - public void processVariable(SlotInfo info, String indent, String attr) - { - super.processVariable(info, indent, attr); - append(";\n"); - } - - @Override - protected boolean dumpRestParameter() - { - return true; - } +class AS3InterfaceDumper extends AbstractDumpProcessor { + private int memberCount; + private boolean isInterface; + + @Override + public void dumpStat(@Nonnull String stat) { + } + + @Override + public void dumpToplevelAnonymousMethod(@Nonnull Abc abc, @Nonnull MethodInfo m) { + } + + @Override + public void dumpTopLevelTraits(@Nonnull Abc abc, @Nonnull Traits t, String indent) { + t.dump(abc, indent, "", this); + } + + @Override + public boolean doDumpMember(@Nonnull MemberInfo memberInfo) { + return memberInfo.name != null && (memberInfo.name.name == null || !memberInfo.name.name.contains(Abc.$CINIT)); + } + + @Override + public void appendMethodSeparator() { + append((++memberCount % 5) == 0 ? "\n" : ""); + } + + @Override + public void appendFieldSeparator() { + appendMethodSeparator(); + } + + @Override + public String getAbcInSwfIndent() { + return ""; + } + + @Override + public void processValue(Multiname typeName, Object valueObject) { + append(" = "); + append(getValueRepr(valueObject)); + } + + protected static String getValueRepr(Object valueObject) { + if (valueObject == null) { + return null; + } + String value = valueObject.toString(); + char ch; + + if (needsQuoting(value)) { + boolean doQoute = true; + + if (value.indexOf('.') != -1) { + try { + Double.parseDouble(value); + doQoute = false; + } + catch (NumberFormatException ignored) { + } + } + else if (value.length() > 0 && (Character.isDigit( + ch = value.charAt(0)) || (ch == '-' && value.length() > 1 && Character.isDigit(value.charAt(1) + )))) { + try { + Integer.parseInt(value); + doQoute = false; + } + catch (NumberFormatException ignored) { + } + } + + if (doQoute) { + value = "\"" + quote(value) + "\""; + } + } + return value; + } + + private static final Set DO_NOT_NEED_QOTING = + Set.of("null", "NaN", "undefined", "true", "false", "Infinity", "-Infinity"); + + private static boolean needsQuoting(String value) { + return !DO_NOT_NEED_QOTING.contains(value); + } + + @Override + public boolean doDumpMetaData(@Nonnull MetaData md) { + return !md.name.contains("__"); + } + + @Override + public void processParameter( + @Nonnull String name, + @Nullable Multiname type, + String parentName, + @Nullable Multiname value, + boolean rest + ) { + if (rest) { + append("... "); + append(name); + } + else { + append(name); + append(":"); + processMultinameAsPackageName(type, parentName, true); + if (value != null) { + processValue(type, value); + } + } + } + + @Override + public boolean doStarTypeDumpInExtends() { + return false; + } + + @Override + public boolean doStarMetaAttrNameDump() { + return false; + } + + @Override + public void setProcessingInterface(boolean anInterface) { + isInterface = anInterface; + } + + @Override + public void hasError(@Nonnull String error) { + sb.append("/*").append(error).append("*/"); + } + + @Override + public void processMultinameAsPackageName(@Nonnull Multiname name, String parentName, boolean verbose) { + append(getMultinameAsPackageName(name, parentName, verbose)); + } + + protected static String getMultinameAsPackageName(Multiname name, String parentName, boolean verbose) { + if (name.hasNotEmptyNs()) { + if (name.hasNamespace() || (!verbose && parentName != null && + (parentName.equals(name.nsset[0].replaceAll(":", "::"))) || (parentName != null && parentName.equals(name.toString())))) { + return name.name; + } + + return name.nsset[0] + "." + name.name; + } + + return name.toString(); + } + + @Override + protected String appendModifiers(MemberInfo member, String attr) { + String s = attr; + + s += "native "; + boolean hasNs = false; + if (member.name != null && member.name.hasNotEmptyNs() && member.name.hasNamespace()) { + hasNs = true; + s += member.name.getNsName() + " "; + } + + if (!s.contains("private") && !hasNs && !isInterface) { + String parentName; + + if (member.isPublic || + member.name.nsset[0].length() == 0 || + (member.parentTraits != null && ((parentName = + member.parentTraits.name.toString()).equals(member.name.toString()) || parentName.startsWith + ("script")))) { + s += "public "; + } + else { + s += "protected "; + } + } + + if (member.isFinal) { + s += "final "; + } + if (member.isOverride) { + s += "override "; + } + return s; + } + + @Override + public void processFunction(MethodInfo methodInfo, boolean referenceNameRequested, Abc abc, String indent, String attr) { + super.processFunction(methodInfo, referenceNameRequested, abc, indent, attr); + append(";\n"); + } + + @Override + public void processVariable(SlotInfo info, String indent, String attr) { + super.processVariable(info, indent, attr); + append(";\n"); + } + + @Override + protected boolean dumpRestParameter() { + return true; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/AS3InterfaceStubDumper.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/AS3InterfaceStubDumper.java index 4ce5b526..b9f2e711 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/AS3InterfaceStubDumper.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/AS3InterfaceStubDumper.java @@ -16,172 +16,187 @@ package com.intellij.lang.javascript.impl.flex.importer; -import java.util.LinkedList; - -import org.jetbrains.annotations.NonNls; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import com.intellij.lang.javascript.JSElementTypes; import com.intellij.lang.javascript.psi.stubs.impl.JSAttributeNameValuePairStubImpl; import com.intellij.lang.javascript.psi.stubs.impl.JSReferenceListStubImpl; -import consulo.util.lang.StringUtil; import consulo.language.psi.stub.StubElement; +import consulo.util.lang.StringUtil; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; + +import java.util.LinkedList; /** - * Created by IntelliJ IDEA. - * User: Maxim.Mossienko - * Date: 05.03.2009 - * Time: 0:43:37 - * To change this template use File | Settings | File Templates. + * @author Maxim.Mossienko + * @since 2009-03-05 */ -class AS3InterfaceStubDumper extends AS3InterfaceDumper -{ - final LinkedList parents; - - public AS3InterfaceStubDumper(StubElement parent) - { - parents = new LinkedList(); - parents.add(parent); - } - - @Override - public void processMetadata(MetaData metaData) - { - /*parents.addLast(new JSAttributeStubImpl(metaData.name, parents.getLast())); - super.processMetadata(metaData); - parents.removeLast(); */ - } - - @Override - public void addMetaDataValue(String s, String s1) - { - new JSAttributeNameValuePairStubImpl(s, StringUtil.stripQuotesAroundValue(s1), parents.getLast()); - } - - @Override - protected void processArgumentList(MethodInfo methodInfo, String parentName) - { - /*parents.add(new JSParameterListStubImpl(parents.getLast())); - super.processArgumentList(methodInfo, parentName); - parents.removeLast(); */ - } - - @Override - public void processParameter(@Nonnull String name, @Nullable Multiname type, String parentName, @Nullable Multiname value, boolean rest) - { - /*new JSParameterStubImpl(name, rest ? JSParameterStubImpl.REST_MASK : 0, getMultinameAsPackageName(type, parentName, true), - getValueRepr(value), - parents.getLast());*/ - } - - @Override - public void append(@Nonnull @NonNls String str) - { - } - - @Override - public void processFunction(MethodInfo methodInfo, boolean referenceNameRequested, Abc abc, String indent, String attr) - { - /*parents.add(new JSFunctionStubImpl(methodInfo.name.name, methodInfo.isGetMethod() ? JSFunctionStubImpl.GET_PROPERTY_MASK : methodInfo - .isSetMethod - () ? JSFunctionStubImpl.SET_PROPERTY_MASK : methodInfo.parentTraits != null && methodInfo.parentTraits.name == methodInfo.name ? - JSFunctionStubImpl.CONSTRUCTOR_MASK : 0, getMultinameAsPackageName(methodInfo.name, methodInfo.parentTraits != null ? methodInfo.parentTraits - .getClassName() : null, referenceNameRequested), getMultinameAsPackageName(methodInfo.returnType, methodInfo.getParentName(), - referenceNameRequested), parents.getLast())); - super.processFunction(methodInfo, referenceNameRequested, abc, indent, attr); - parents.removeLast(); */ - } - - @Override - public void processVariable(SlotInfo info, String indent, String attr) - { - /*parents.add(new JSVarStatementStubImpl(parents.getLast())); - super.processVariable(info, indent, attr); - String parentName = info.getParentName(); - String qName = getMultinameAsPackageName(info.name, parentName, false); - new JSVariableStubImpl(qName.substring(qName.lastIndexOf('.') + 1), info.isConst() ? JSVariableStubImpl.CONST_MASK : 0, - getMultinameAsPackageName(info.type, parentName, false), getValueRepr(info.value), qName, parents.getLast()); - parents.removeLast(); */ - } - - @Override - public void processClass(SlotInfo slotInfo, Abc abc, String attr, String indent) - { - /*parents.add(new JSClassStubImpl(slotInfo.name.name, slotInfo.isInterfaceClass() ? JSClassStubImpl.INTERFACE_MASK : 0, - getMultinameAsPackageName(slotInfo.name, null, false), parents.getLast())); - super.processClass(slotInfo, abc, attr, indent); - parents.removeLast(); */ - } - - @Override - protected void processModifierList(MemberInfo memberInfo, String attr, String indent) - { - /*StringTokenizer tokenizer = new StringTokenizer(attr, " "); - List modifiers = new SmartList(); - JSAttributeList.AccessType accessType = null; - String ns = null; - - while(tokenizer.hasMoreTokens()) - { - String next = tokenizer.nextToken(); - boolean foundModifier = false; - - for(JSAttributeList.AccessType type : JSAttributeList.AccessType.values()) - { - if(next.equalsIgnoreCase(type.name())) - { - accessType = type; - foundModifier = true; - break; - } - } - - if(!foundModifier) - { - for(JSAttributeList.ModifierType type : JSAttributeList.ModifierType.values()) - { - if(next.equalsIgnoreCase(type.name())) - { - modifiers.add(type); - foundModifier = true; - break; - } - } - } - - if(!foundModifier) - { - ns = next; - } - } - parents.add(new JSAttributeListStubImpl(parents.getLast(), ns, accessType, modifiers.toArray(new JSAttributeList.ModifierType[modifiers.size()]))); - super.processModifierList(memberInfo, attr, indent); - parents.removeLast(); */ - } - - @Override - protected void dumpExtendsList(Traits it) - { - if(!it.base.isStarReference()) - { - new JSReferenceListStubImpl(new String[]{getMultinameAsPackageName(it.base, null, true)}, parents.getLast(), JSElementTypes.EXTENDS_LIST); - } - } - - @Override - protected void dumpInterfacesList(String indent, Traits it, boolean anInterface) - { - String[] interfaces; - if(it.interfaces.length > 0) - { - interfaces = new String[it.interfaces.length]; - - int i = 0; - for(Multiname name : it.interfaces) - { - interfaces[i++] = getMultinameAsPackageName(name, null, true); - } - new JSReferenceListStubImpl(interfaces, parents.getLast(), anInterface ? JSElementTypes.EXTENDS_LIST : JSElementTypes.IMPLEMENTS_LIST); - } - } +class AS3InterfaceStubDumper extends AS3InterfaceDumper { + final LinkedList parents; + + public AS3InterfaceStubDumper(StubElement parent) { + parents = new LinkedList<>(); + parents.add(parent); + } + + @Override + public void processMetadata(MetaData metaData) { + /*parents.addLast(new JSAttributeStubImpl(metaData.name, parents.getLast())); + super.processMetadata(metaData); + parents.removeLast();*/ + } + + @Override + public void addMetaDataValue(String s, String s1) { + new JSAttributeNameValuePairStubImpl(s, StringUtil.stripQuotesAroundValue(s1), parents.getLast()); + } + + @Override + protected void processArgumentList(MethodInfo methodInfo, String parentName) { + /*parents.add(new JSParameterListStubImpl(parents.getLast())); + super.processArgumentList(methodInfo, parentName); + parents.removeLast();*/ + } + + @Override + public void processParameter( + @Nonnull String name, + @Nullable Multiname type, + String parentName, + @Nullable Multiname value, + boolean rest + ) { + /*new JSParameterStubImpl( + name, + rest ? JSParameterStubImpl.REST_MASK : 0, + getMultinameAsPackageName(type, parentName, true), + getValueRepr(value), + parents.getLast() + );*/ + } + + @Override + public void append(@Nonnull String str) { + } + + @Override + public void processFunction(MethodInfo methodInfo, boolean referenceNameRequested, Abc abc, String indent, String attr) { + /*parents.add(new JSFunctionStubImpl( + methodInfo.name.name, + methodInfo.isGetMethod() + ? JSFunctionStubImpl.GET_PROPERTY_MASK + : methodInfo.isSetMethod() + ? JSFunctionStubImpl.SET_PROPERTY_MASK + : methodInfo.parentTraits != null && methodInfo.parentTraits.name == methodInfo.name + ? JSFunctionStubImpl.CONSTRUCTOR_MASK + : 0, + getMultinameAsPackageName( + methodInfo.name, + methodInfo.parentTraits != null ? methodInfo.parentTraits.getClassName() : null, + referenceNameRequested + ), + getMultinameAsPackageName( + methodInfo.returnType, + methodInfo.getParentName(), + referenceNameRequested + ), + parents.getLast() + )); + super.processFunction(methodInfo, referenceNameRequested, abc, indent, attr); + parents.removeLast();*/ + } + + @Override + public void processVariable(SlotInfo info, String indent, String attr) { + /*parents.add(new JSVarStatementStubImpl(parents.getLast())); + super.processVariable(info, indent, attr); + String parentName = info.getParentName(); + String qName = getMultinameAsPackageName(info.name, parentName, false); + new JSVariableStubImpl( + qName.substring(qName.lastIndexOf('.') + 1), info.isConst() ? JSVariableStubImpl.CONST_MASK : 0, + getMultinameAsPackageName(info.type, parentName, false), getValueRepr(info.value), qName, parents.getLast() + ); + parents.removeLast();*/ + } + + @Override + public void processClass(SlotInfo slotInfo, Abc abc, String attr, String indent) { + /*parents.add( + new JSClassStubImpl(slotInfo.name.name, slotInfo.isInterfaceClass() ? JSClassStubImpl.INTERFACE_MASK : 0, + getMultinameAsPackageName(slotInfo.name, null, false), parents.getLast()) + ); + super.processClass(slotInfo, abc, attr, indent); + parents.removeLast();*/ + } + + @Override + protected void processModifierList(MemberInfo memberInfo, String attr, String indent) { + /*StringTokenizer tokenizer = new StringTokenizer(attr, " "); + List modifiers = new SmartList(); + JSAttributeList.AccessType accessType = null; + String ns = null; + + while(tokenizer.hasMoreTokens()) { + String next = tokenizer.nextToken(); + boolean foundModifier = false; + + for (JSAttributeList.AccessType type : JSAttributeList.AccessType.values()) { + if (next.equalsIgnoreCase(type.name())) { + accessType = type; + foundModifier = true; + break; + } + } + + if (!foundModifier) { + for (JSAttributeList.ModifierType type : JSAttributeList.ModifierType.values()) { + if (next.equalsIgnoreCase(type.name())) { + modifiers.add(type); + foundModifier = true; + break; + } + } + } + + if(!foundModifier) { + ns = next; + } + } + parents.add(new JSAttributeListStubImpl( + parents.getLast(), + ns, + accessType, + modifiers.toArray(new JSAttributeList.ModifierType[modifiers.size()]) + )); + super.processModifierList(memberInfo, attr, indent); + parents.removeLast();*/ + } + + @Override + protected void dumpExtendsList(Traits it) { + if (!it.base.isStarReference()) { + new JSReferenceListStubImpl( + new String[]{getMultinameAsPackageName(it.base, null, true)}, + parents.getLast(), + JSElementTypes.EXTENDS_LIST + ); + } + } + + @Override + protected void dumpInterfacesList(String indent, Traits it, boolean anInterface) { + String[] interfaces; + if (it.interfaces.length > 0) { + interfaces = new String[it.interfaces.length]; + + int i = 0; + for (Multiname name : it.interfaces) { + interfaces[i++] = getMultinameAsPackageName(name, null, true); + } + new JSReferenceListStubImpl( + interfaces, + parents.getLast(), + anInterface ? JSElementTypes.EXTENDS_LIST : JSElementTypes.IMPLEMENTS_LIST + ); + } + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/Abc.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/Abc.java index 38f3c2d6..e80c423c 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/Abc.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/Abc.java @@ -16,1172 +16,1079 @@ package com.intellij.lang.javascript.impl.flex.importer; -import java.util.HashSet; -import java.util.Set; - import consulo.util.collection.ArrayUtil; -import org.jetbrains.annotations.NonNls; -import javax.annotation.Nonnull; import consulo.util.lang.StringUtil; +import jakarta.annotation.Nonnull; + +import java.util.HashSet; +import java.util.Set; /** * @author Maxim.Mossienko - * Date: Oct 20, 2008 - * Time: 7:01:16 PM + * @since 2008-10-20 */ -class Abc -{ - static final - @NonNls - String TAB = " "; - @NonNls - static final String $CINIT = "$cinit"; - @NonNls - static final String $ = "$"; - - private static final int ATTR_final = 0x01; // 1=final, 0=virtual - private static final int ATTR_override = 0x02; // 1=override, 0=new - private static final int ATTR_metadata = 0x04; // 1=has metadata, 0=no metadata - private static final int ATTR_public = 0x08; // 1=add public namespace - - static final int CLASS_FLAG_sealed = 0x01; - static final int CLASS_FLAG_final = 0x02; - static final int CLASS_FLAG_interface = 0x04; - static final int CLASS_FLAG_protected = 0x08; - - - // method flags - private static final int NEED_ARGUMENTS = 0x01; - static final int NEED_ACTIVATION = 0x02; - private static final int NEED_REST = 0x04; - private static final int HAS_OPTIONAL = 0x08; - private static final int IGNORE_REST = 0x10; - static final int NATIVE = 0x20; - private static final int HAS_ParamNames = 0x80; - - private static final int CONSTANT_Utf8 = 0x01; - private static final int CONSTANT_Int = 0x03; - private static final int CONSTANT_UInt = 0x04; - private static final int CONSTANT_PrivateNs = 0x05; // non-shared namespace - private static final int CONSTANT_Double = 0x06; - private static final int CONSTANT_Qname = 0x07; // o.ns::name, ct ns, ct name - private static final int CONSTANT_Namespace = 0x08; - private static final int CONSTANT_Multiname = 0x09; // o.name, ct nsset, ct name - private static final int CONSTANT_False = 0x0A; - private static final int CONSTANT_True = 0x0B; - private static final int CONSTANT_Null = 0x0C; - private static final int CONSTANT_QnameA = 0x0D; // o.@ns::name, ct ns, ct attr-name - private static final int CONSTANT_MultinameA = 0x0E; // o.@name, ct attr-name - private static final int CONSTANT_RTQname = 0x0F; // o.ns::name, rt ns, ct name - private static final int CONSTANT_RTQnameA = 0x10; // o.@ns::name, rt ns, ct attr-name - private static final int CONSTANT_RTQnameL = 0x11; // o.ns::[name], rt ns, rt name - private static final int CONSTANT_RTQnameLA = 0x12; // o.@ns::[name], rt ns, rt attr-name - private static final int CONSTANT_NameL = 0x13; // o.[], ns=public implied, rt name - private static final int CONSTANT_NameLA = 0x14; // o.@[], ns=public implied, rt attr-name - private static final int CONSTANT_NamespaceSet = 0x15; - private static final int CONSTANT_PackageNs = 0x16; - private static final int CONSTANT_PackageInternalNs = 0x17; - private static final int CONSTANT_ProtectedNs = 0x18; - private static final int CONSTANT_StaticProtectedNs = 0x19; - private static final int CONSTANT_StaticProtectedNs2 = 0x1a; - private static final int CONSTANT_MultinameL = 0x1B; - private static final int CONSTANT_MultinameLA = 0x1C; - private static final int CONSTANT_TypeName = 0x1D; - - static final - @NonNls - String[] constantKinds = { - "0", - "utf8", - "2", - "int", - "uint", - "private", - "double", - "qname", - "namespace", - "multiname", - "false", - "true", - "null", - "@qname", - "@multiname", - "rtqname", - "@rtqname", - "[qname]", - "@[qname]", - "[name]", - "@[name]", - "nsset" - }; - - static final int TRAIT_Slot = 0x00; - private static final int TRAIT_Method = 0x01; - private static final int TRAIT_Getter = 0x02; - private static final int TRAIT_Setter = 0x03; - private static final int TRAIT_Class = 0x04; - private static final int TRAIT_Function = 0x05; - static final int TRAIT_Const = 0x06; - - static final - @NonNls - String[] traitKinds = { - "var", - "function", - "function get", - "function set", - "class", - "function", - "const" - }; - - private static final int OP_bkpt = 0x01; - private static final int OP_nop = 0x02; - private static final int OP_throw = 0x03; - static final int OP_getsuper = 0x04; - static final int OP_setsuper = 0x05; - private static final int OP_dxns = 0x06; - private static final int OP_dxnslate = 0x07; - static final int OP_kill = 0x08; - static final int OP_label = 0x09; - static final int OP_ifnlt = 0x0C; - static final int OP_ifnle = 0x0D; - static final int OP_ifngt = 0x0E; - static final int OP_ifnge = 0x0F; - static final int OP_jump = 0x10; - static final int OP_iftrue = 0x11; - static final int OP_iffalse = 0x12; - static final int OP_ifeq = 0x13; - static final int OP_ifne = 0x14; - static final int OP_iflt = 0x15; - static final int OP_ifle = 0x16; - static final int OP_ifgt = 0x17; - static final int OP_ifge = 0x18; - static final int OP_ifstricteq = 0x19; - static final int OP_ifstrictne = 0x1A; - static final int OP_lookupswitch = 0x1B; - private static final int OP_pushwith = 0x1C; - private static final int OP_popscope = 0x1D; - private static final int OP_nextname = 0x1E; - private static final int OP_hasnext = 0x1F; - private static final int OP_pushnull = 0x20; - private static final int OP_pushundefined = 0x21; - private static final int OP_pushconstant = 0x22; - private static final int OP_nextvalue = 0x23; - static final int OP_pushbyte = 0x24; - static final int OP_pushshort = 0x25; - private static final int OP_pushtrue = 0x26; - private static final int OP_pushfalse = 0x27; - private static final int OP_pushnan = 0x28; - private static final int OP_pop = 0x29; - private static final int OP_dup = 0x2A; - private static final int OP_swap = 0x2B; - static final int OP_pushstring = 0x2C; - static final int OP_pushint = 0x2D; - static final int OP_pushuint = 0x2E; - static final int OP_pushdouble = 0x2F; - private static final int OP_pushscope = 0x30; - static final int OP_pushnamespace = 0x31; - static final int OP_hasnext2 = 0x32; - static final int OP_newfunction = 0x40; - static final int OP_call = 0x41; - static final int OP_construct = 0x42; - private static final int OP_callmethod = 0x43; - static final int OP_callstatic = 0x44; - static final int OP_callsuper = 0x45; - static final int OP_callproperty = 0x46; - private static final int OP_returnvoid = 0x47; - private static final int OP_returnvalue = 0x48; - static final int OP_constructsuper = 0x49; - static final int OP_constructprop = 0x4A; - private static final int OP_callsuperid = 0x4B; - static final int OP_callproplex = 0x4C; - private static final int OP_callinterface = 0x4D; - static final int OP_callsupervoid = 0x4E; - static final int OP_callpropvoid = 0x4F; - private static final int OP_applytype = 0x53; - static final int OP_newobject = 0x55; - static final int OP_newarray = 0x56; - private static final int OP_newactivation = 0x57; - static final int OP_newclass = 0x58; - static final int OP_getdescendants = 0x59; - static final int OP_newcatch = 0x5A; - static final int OP_findpropstrict = 0x5D; - static final int OP_findproperty = 0x5E; - static final int OP_finddef = 0x5F; - static final int OP_getlex = 0x60; - static final int OP_setproperty = 0x61; - static final int OP_getlocal = 0x62; - static final int OP_setlocal = 0x63; - private static final int OP_getglobalscope = 0x64; - static final int OP_getscopeobject = 0x65; - static final int OP_getproperty = 0x66; - private static final int OP_getouterscope = 0x67; - static final int OP_initproperty = 0x68; - private static final int OP_setpropertylate = 0x69; - static final int OP_deleteproperty = 0x6A; - private static final int OP_deletepropertylate = 0x6B; - static final int OP_getslot = 0x6C; - static final int OP_setslot = 0x6D; - static final int OP_getglobalslot = 0x6E; - static final int OP_setglobalslot = 0x6F; - private static final int OP_convert_s = 0x70; - private static final int OP_esc_xelem = 0x71; - private static final int OP_esc_xattr = 0x72; - private static final int OP_convert_i = 0x73; - private static final int OP_convert_u = 0x74; - private static final int OP_convert_d = 0x75; - private static final int OP_convert_b = 0x76; - private static final int OP_convert_o = 0x77; - static final int OP_coerce = 0x80; - private static final int OP_coerce_b = 0x81; - private static final int OP_coerce_a = 0x82; - private static final int OP_coerce_i = 0x83; - private static final int OP_coerce_d = 0x84; - private static final int OP_coerce_s = 0x85; - static final int OP_astype = 0x86; - private static final int OP_astypelate = 0x87; - private static final int OP_coerce_u = 0x88; - private static final int OP_coerce_o = 0x89; - private static final int OP_negate = 0x90; - private static final int OP_increment = 0x91; - static final int OP_inclocal = 0x92; - private static final int OP_decrement = 0x93; - static final int OP_declocal = 0x94; - private static final int OP_typeof = 0x95; - private static final int OP_not = 0x96; - private static final int OP_bitnot = 0x97; - private static final int OP_concat = 0x9A; - private static final int OP_add_d = 0x9B; - private static final int OP_add = 0xA0; - private static final int OP_subtract = 0xA1; - private static final int OP_multiply = 0xA2; - private static final int OP_divide = 0xA3; - private static final int OP_modulo = 0xA4; - private static final int OP_lshift = 0xA5; - private static final int OP_rshift = 0xA6; - private static final int OP_urshift = 0xA7; - private static final int OP_bitand = 0xA8; - private static final int OP_bitor = 0xA9; - private static final int OP_bitxor = 0xAA; - private static final int OP_equals = 0xAB; - private static final int OP_strictequals = 0xAC; - private static final int OP_lessthan = 0xAD; - private static final int OP_lessequals = 0xAE; - private static final int OP_greaterthan = 0xAF; - private static final int OP_greaterequals = 0xB0; - private static final int OP_instanceof = 0xB1; - static final int OP_istype = 0xB2; - private static final int OP_istypelate = 0xB3; - private static final int OP_in = 0xB4; - private static final int OP_increment_i = 0xC0; - private static final int OP_decrement_i = 0xC1; - static final int OP_inclocal_i = 0xC2; - static final int OP_declocal_i = 0xC3; - private static final int OP_negate_i = 0xC4; - private static final int OP_add_i = 0xC5; - private static final int OP_subtract_i = 0xC6; - private static final int OP_multiply_i = 0xC7; - private static final int OP_getlocal0 = 0xD0; - private static final int OP_getlocal1 = 0xD1; - private static final int OP_getlocal2 = 0xD2; - private static final int OP_getlocal3 = 0xD3; - private static final int OP_setlocal0 = 0xD4; - private static final int OP_setlocal1 = 0xD5; - private static final int OP_setlocal2 = 0xD6; - private static final int OP_setlocal3 = 0xD7; - static final int OP_debug = 0xEF; - static final int OP_debugline = 0xF0; - static final int OP_debugfile = 0xF1; - private static final int OP_bkptline = 0xF2; - - static final - @NonNls - String[] opNames = { - "OP_0x00 ", - "bkpt ", - "nop ", - "throw ", - "getsuper ", - "setsuper ", - "dxns ", - "dxnslate ", - "kill ", - "label ", - "OP_0x0A ", - "OP_0x0B ", - "ifnlt ", - "ifnle ", - "ifngt ", - "ifnge ", - "jump ", - "iftrue ", - "iffalse ", - "ifeq ", - "ifne ", - "iflt ", - "ifle ", - "ifgt ", - "ifge ", - "ifstricteq ", - "ifstrictne ", - "lookupswitch ", - "pushwith ", - "popscope ", - "nextname ", - "hasnext ", - "pushnull ", - "pushundefined ", - "pushconstant ", - "nextvalue ", - "pushbyte ", - "pushshort ", - "pushtrue ", - "pushfalse ", - "pushnan ", - "pop ", - "dup ", - "swap ", - "pushstring ", - "pushint ", - "pushuint ", - "pushdouble ", - "pushscope ", - "pushnamespace ", - "hasnext2 ", - "OP_0x33 ", - "OP_0x34 ", - "OP_0x35 ", - "OP_0x36 ", - "OP_0x37 ", - "OP_0x38 ", - "OP_0x39 ", - "OP_0x3A ", - "OP_0x3B ", - "OP_0x3C ", - "OP_0x3D ", - "OP_0x3E ", - "OP_0x3F ", - "newfunction ", - "call ", - "construct ", - "callmethod ", - "callstatic ", - "callsuper ", - "callproperty ", - "returnvoid ", - "returnvalue ", - "constructsuper", - "constructprop ", - "callsuperid ", - "callproplex ", - "callinterface ", - "callsupervoid ", - "callpropvoid ", - "OP_0x50 ", - "OP_0x51 ", - "OP_0x52 ", - "applytype ", - "OP_0x54 ", - "newobject ", - "newarray ", - "newactivation ", - "newclass ", - "getdescendants", - "newcatch ", - "OP_0x5B ", - "OP_0x5C ", - "findpropstrict", - "findproperty ", - "finddef ", - "getlex ", - "setproperty ", - "getlocal ", - "setlocal ", - "getglobalscope", - "getscopeobject", - "getproperty ", - "getouterscope ", - "initproperty ", - "OP_0x69 ", - "deleteproperty", - "OP_0x6A ", - "getslot ", - "setslot ", - "getglobalslot ", - "setglobalslot ", - "convert_s ", - "esc_xelem ", - "esc_xattr ", - "convert_i ", - "convert_u ", - "convert_d ", - "convert_b ", - "convert_o ", - "checkfilter ", - "OP_0x79 ", - "OP_0x7A ", - "OP_0x7B ", - "OP_0x7C ", - "OP_0x7D ", - "OP_0x7E ", - "OP_0x7F ", - "coerce ", - "coerce_b ", - "coerce_a ", - "coerce_i ", - "coerce_d ", - "coerce_s ", - "astype ", - "astypelate ", - "coerce_u ", - "coerce_o ", - "OP_0x8A ", - "OP_0x8B ", - "OP_0x8C ", - "OP_0x8D ", - "OP_0x8E ", - "OP_0x8F ", - "negate ", - "increment ", - "inclocal ", - "decrement ", - "declocal ", - "typeof ", - "not ", - "bitnot ", - "OP_0x98 ", - "OP_0x99 ", - "concat ", - "add_d ", - "OP_0x9C ", - "OP_0x9D ", - "OP_0x9E ", - "OP_0x9F ", - "add ", - "subtract ", - "multiply ", - "divide ", - "modulo ", - "lshift ", - "rshift ", - "urshift ", - "bitand ", - "bitor ", - "bitxor ", - "equals ", - "strictequals ", - "lessthan ", - "lessequals ", - "greaterthan ", - "greaterequals ", - "instanceof ", - "istype ", - "istypelate ", - "in ", - "OP_0xB5 ", - "OP_0xB6 ", - "OP_0xB7 ", - "OP_0xB8 ", - "OP_0xB9 ", - "OP_0xBA ", - "OP_0xBB ", - "OP_0xBC ", - "OP_0xBD ", - "OP_0xBE ", - "OP_0xBF ", - "increment_i ", - "decrement_i ", - "inclocal_i ", - "declocal_i ", - "negate_i ", - "add_i ", - "subtract_i ", - "multiply_i ", - "OP_0xC8 ", - "OP_0xC9 ", - "OP_0xCA ", - "OP_0xCB ", - "OP_0xCC ", - "OP_0xCD ", - "OP_0xCE ", - "OP_0xCF ", - "getlocal0 ", - "getlocal1 ", - "getlocal2 ", - "getlocal3 ", - "setlocal0 ", - "setlocal1 ", - "setlocal2 ", - "setlocal3 ", - "OP_0xD8 ", - "OP_0xD9 ", - "OP_0xDA ", - "OP_0xDB ", - "OP_0xDC ", - "OP_0xDD ", - "OP_0xDE ", - "OP_0xDF ", - "OP_0xE0 ", - "OP_0xE1 ", - "OP_0xE2 ", - "OP_0xE3 ", - "OP_0xE4 ", - "OP_0xE5 ", - "OP_0xE6 ", - "OP_0xE7 ", - "OP_0xE8 ", - "OP_0xE9 ", - "OP_0xEA ", - "OP_0xEB ", - "OP_0xEC ", - "OP_0xED ", - "OP_0xEE ", - "debug ", - "debugline ", - "debugfile ", - "bkptline ", - "timestamp ", - "OP_0xF4 ", - "verifypass ", - "alloc ", - "mark ", - "wb ", - "prologue ", - "sendenter ", - "doubletoatom ", - "sweep ", - "codegenop ", - "verifyop ", - "decode " - }; - - private FlexByteCodeInformationProcessor processor; - int totalSize; - final int opSizes[] = new int[256]; - - public Abc(final @Nonnull ByteBuffer _data, @Nonnull FlexByteCodeInformationProcessor _processor) - { - data = _data; - processor = _processor; - - data.setPosition(0); - magic = data.readInt(); - - _processor.dumpStat("magic " + Integer.toString(magic, 16) + "\n"); - - if(magic != (46 << 16 | 14) && magic != (46 << 16 | 15) && magic != (46 << 16 | 16)) - { - throw new Error("not an abc file. magic=" + Integer.toString(magic, 16)); - } - - parseCpool(); - - defaults[CONSTANT_Utf8] = strings; - defaults[CONSTANT_Int] = ints; - defaults[CONSTANT_UInt] = uints; - defaults[CONSTANT_Double] = doubles; - defaults[CONSTANT_Int] = ints; - defaults[CONSTANT_False] = buildSparseArray(10, "false"); - defaults[CONSTANT_True] = buildSparseArray(11, "true"); - defaults[CONSTANT_Namespace] = namespaces; - defaults[CONSTANT_PrivateNs] = namespaces; - defaults[CONSTANT_PackageNs] = namespaces; - defaults[CONSTANT_PackageInternalNs] = namespaces; - defaults[CONSTANT_ProtectedNs] = namespaces; - defaults[CONSTANT_StaticProtectedNs] = namespaces; - defaults[CONSTANT_StaticProtectedNs2] = namespaces; - defaults[CONSTANT_Null] = buildSparseArray(12, "null"); - - parseMethodInfos(); - parseMetadataInfos(); - parseInstanceInfos(); - parseClassInfos(); - parseScriptInfos(); - parseMethodBodies(); - } - - private static Object[] buildSparseArray(int index, @NonNls String s1) - { - final Object[] result = new Object[index + 1]; - result[index] = s1; - return result; - } - - public void dump(String indent) - { - for(Traits t : scripts) - { - processor.dumpTopLevelTraits(this, t, indent); - } - - for(MethodInfo m : methods) - { - if(m.anon) - { - processor.dumpToplevelAnonymousMethod(this, m); - } - } - - processor.dumpStat("OPCODE\tSIZE\t% OF " + totalSize + "\n"); - final Set done = new HashSet(); - while(true) - { - int max = -1; - int maxsize = 0; - for(int i = 0; i < 256; i++) - { - if(opSizes[i] > maxsize && !done.contains(i)) - { - max = i; - maxsize = opSizes[i]; - } - } - if(max == -1) - { - break; - } - done.add(max); - processor.dumpStat(opNames[max] + "\t" + opSizes[max] + "\t" + (int) (100f * opSizes[max] / totalSize) + "%\n"); - } - } - - private final ByteBuffer data; - int major; - int minor; - - Integer[] ints; - Integer[] uints; - Double[] doubles; - @NonNls - String[] strings; - @NonNls - String[] namespaces; - @NonNls - String[][] nssets; - Multiname[] names; - - final Object[][] defaults = new Object[Math.max(constantKinds.length, CONSTANT_MultinameLA + 1)][]; - - MethodInfo methods[]; - Traits instances[]; - Traits classes[]; - Traits[] scripts; - MetaData metadata[]; - - @NonNls - String publicNs = ""; - @NonNls - String anyNs = "*"; - - final int magic; - - int readU32() - { - return data.readU32(); - } - - void parseCpool() - { - int i, j; - int n; - int start = data.getPosition(); - - // ints - n = readU32(); - ints = new Integer[n > 0 ? n : 1]; - ints[0] = 0; - for(i = 1; i < n; i++) - { - ints[i] = readU32(); - } - - // uints - n = readU32(); - uints = new Integer[n > 0 ? n : 1]; - uints[0] = 0; - for(i = 1; i < n; i++) - { - uints[i] = readU32(); - } - - // doubles - n = readU32(); - doubles = new Double[n > 0 ? n : 1]; - doubles[0] = Double.NaN; - for(i = 1; i < n; i++) - { - doubles[i] = data.readDouble(); - } - - reportAboutPercentage("Cpool numbers size ", data, start, processor); - start = data.getPosition(); - - // strings - n = readU32(); - strings = new String[n]; - strings[0] = ""; - for(i = 1; i < n; i++) - { - strings[i] = data.readUTFBytes(readU32()); - } - - reportAboutPercentage("Cpool strings count " + n + " size ", data, start, processor); - start = data.getPosition(); - - // namespaces - n = readU32(); - namespaces = new String[n]; - namespaces[0] = publicNs; - for(i = 1; i < n; i++) - { - switch(data.readByte()) - { - case CONSTANT_Namespace: - case CONSTANT_PackageNs: - case CONSTANT_PackageInternalNs: - case CONSTANT_ProtectedNs: - case CONSTANT_StaticProtectedNs: - case CONSTANT_StaticProtectedNs2: - { - namespaces[i] = strings[readU32()]; - // todo mark kind of namespace. - break; - } - case CONSTANT_PrivateNs: - readU32(); - namespaces[i] = "private"; - break; - } - } - - reportAboutPercentage("Cpool namespaces count " + n + " size ", data, start, processor); - start = data.getPosition(); - - // namespace sets - n = readU32(); - nssets = new String[n][]; - for(i = 1; i < n; i++) - { - int count = readU32(); - String[] nsset = nssets[i] = new String[count]; - for(j = 0; j < count; j++) - { - nsset[j] = namespaces[readU32()]; - } - } - - reportAboutPercentage("Cpool nssets count " + n + " size ", data, start, processor); - start = data.getPosition(); - - // multinames - n = readU32(); - names = new Multiname[n]; - namespaces[0] = anyNs; - strings[0] = "*"; // any name - for(i = 1; i < n; i++) - { - switch(data.readByte()) - { - case CONSTANT_Qname: - case CONSTANT_QnameA: - names[i] = new Multiname(new String[]{namespaces[readU32()]}, strings[readU32()]); - break; - - case CONSTANT_RTQname: - case CONSTANT_RTQnameA: - names[i] = new Multiname(new String[]{strings[readU32()]}, null); - break; - - case CONSTANT_RTQnameL: - case CONSTANT_RTQnameLA: - names[i] = null; - break; - - case CONSTANT_NameL: - case CONSTANT_NameLA: - names[i] = new Multiname(new String[]{""}, null); - break; - - case CONSTANT_Multiname: - case CONSTANT_MultinameA: - String name = strings[readU32()]; - names[i] = new Multiname(nssets[readU32()], name); - break; - - case CONSTANT_MultinameL: - case CONSTANT_MultinameLA: - names[i] = new Multiname(nssets[readU32()], null); - break; - - case CONSTANT_TypeName: - // TODO: - int nameId = readU32(); - String nsName = names[nameId].toString(); - - int count = readU32(); - - if(count > 0) - { - nsName += "<"; - for(int k = 0; k < count; k++) - { - if(k != 0) - { - nsName += ","; - } - nameId = readU32(); - final Multiname typeArgName = names[nameId]; - String typeArgNameString; - - if(processor instanceof AS3InterfaceDumper) - { - final boolean vector = typeArgName.hasNotEmptyNs() && typeArgName.nsset[0].equals("__AS3__.vec"); - typeArgNameString = vector ? typeArgName.name : typeArgName.toString(); - typeArgNameString = typeArgNameString.replaceAll("::", ".") + (vector ? " " : ""); - } - else - { - typeArgNameString = typeArgName.toString(); - } - nsName += typeArgNameString; - } - - nsName += ">"; - } - - final int index = nsName.indexOf("::"); - - names[i] = new Multiname(new String[]{index != -1 ? nsName.substring(0, index) : ""}, index != -1 ? nsName.substring(index + 2) : nsName); - break; - - default: - throw new Error("invalid kind " + data.getByte(data.getPosition() - 1)); - } - } - - reportAboutPercentage("Cpool names count " + n + " size ", data, start, processor); - start = data.getPosition(); - - namespaces[0] = publicNs; - strings[0] = "*"; - } - - void parseMethodInfos() - { - int start = data.getPosition(); - names[0] = new Multiname(new String[]{publicNs}, "*"); - int method_count = readU32(); - methods = new MethodInfo[method_count]; - - for(int i = 0; i < method_count; i++) - { - MethodInfo m = methods[i] = new MethodInfo(); - int param_count = readU32(); - m.returnType = names[readU32()]; - m.paramTypes = new Multiname[param_count]; - for(int j = 0; j < param_count; j++) - { - m.paramTypes[j] = names[readU32()]; - } - m.debugName = strings[readU32()]; - m.flags = data.readByte(); - - if((m.flags & HAS_OPTIONAL) != 0) - { - // has_optional - int optional_count = readU32(); - m.optionalValues = new Multiname[param_count]; - for(int k = param_count - optional_count; k < param_count; ++k) - { - int index = readU32(); // optional value index - int kind = data.readByte(); // kind byte for each default value - - if(index == 0) - { - // kind is ignored, default value is based on type - @NonNls String value; - final @NonNls String type = m.paramTypes[k].toString(); - - if("Number".equals(type) || "decimal".equals(type)) - { - value = "0"; - } - else if("*".equals(type)) - { - value = "null"; - } - else if("String".equals(type)) - { - value = ""; - } - else - { - value = "null"; - } - m.optionalValues[k] = new Multiname(null, value); - } - else - { - if(defaults[kind] == null) - { - processor.hasError("ERROR kind=" + kind + " method_id " + i + "\n"); - } - else - { - m.optionalValues[k] = new Multiname(null, defaults[kind][index].toString()); - } - } - } - } - if((m.flags & HAS_ParamNames) != 0) - { - m.paramNames = new String[param_count]; - for(int k = 0; k < param_count; ++k) - { - final int index = readU32(); - final String name = strings[index]; - m.paramNames[k] = StringUtil.isJavaIdentifier(name) ? name : "_" + index; - } - } - - if((m.flags & NEED_REST) != 0) - { - m.paramTypes = ArrayUtil.append(m.paramTypes, new Multiname(null, "...")); - - if(m.paramNames != null) - { - m.paramNames = ArrayUtil.append(m.paramNames, "__rest"); - } - } - } - - reportAboutPercentage("MethodInfo count " + method_count + " size ", data, start, processor); - } - - void parseMetadataInfos() - { - int count = readU32(); - metadata = new MetaData[count]; - for(int i = 0; i < count; i++) - { - // MetadataInfo - MetaData m = metadata[i] = new MetaData(); - m.name = strings[readU32()]; - int values_count = readU32(); - String names[] = new String[values_count]; - - for(int q = 0; q < values_count; ++q) - { - names[q] = strings[readU32()]; // name - } - for(int q = 0; q < values_count; ++q) - { - m.put(names[q], strings[readU32()]); // value - } - } - } - - void parseInstanceInfos() - { - int start = data.getPosition(); - int count = readU32(); - instances = new Traits[count]; - for(int i = 0; i < count; i++) - { - Traits t = instances[i] = new Traits(); - t.name = names[readU32()]; - t.base = names[readU32()]; - t.flags = data.readByte(); - - if((t.flags & CLASS_FLAG_protected) != 0) - { - t.protectedNs = namespaces[readU32()]; - } - - int interface_count = readU32(); - t.interfaces = new Multiname[interface_count]; - for(int j = 0; j < interface_count; j++) - { - t.interfaces[j] = names[readU32()]; - } - MethodInfo m = t.init = methods[readU32()]; - m.name = ((Multiname) t.name); - m.kind = TRAIT_Method; - m.id = -1; - m.parentTraits = t; - parseTraits(t); - } - - reportAboutPercentage("InstanceInfo size ", data, start, processor); - } - - void parseTraits(Traits t) - { - int namecount = readU32(); - for(int i = 0; i < namecount; i++) - { - Multiname name = names[readU32()]; - int tag = data.readByte(); - int kind = tag & 0xf; - MemberInfo member = null; - - switch(kind) - { - case TRAIT_Slot: - case TRAIT_Const: - case TRAIT_Class: - SlotInfo slot = new SlotInfo(); - member = slot; - slot.id = readU32(); - t.slots.put(slot.id, slot); - if(kind == TRAIT_Slot || kind == TRAIT_Const) - { - slot.type = names[readU32()]; - int index = readU32(); - if(index > 0) - { - slot.value = defaults[data.readByte()][index]; - } - } - else // (kind == TRAIT_Class) - { - slot.value = classes[readU32()]; - } - break; - case TRAIT_Method: - case TRAIT_Getter: - case TRAIT_Setter: - int disp_id = readU32(); - MethodInfo method = methods[readU32()]; - member = method; - t.methods.put(disp_id, method); - method.id = disp_id; - //sb.append("\t",traitKinds[kind],name,disp_id,method,"// disp_id", disp_id) - break; - } - if(member == null) - { - processor.hasError("error trait kind " + kind + "\n"); - } - member.kind = kind; - member.name = name; - t.members.put(i, member); - t.names.put(name.toString(), member); - member.parentTraits = t; - - final int val = tag >> 4; - if((val & ATTR_metadata) != 0) - { - int mdCount = readU32(); - member.metadata = new MetaData[mdCount]; - for(int j = 0; j < mdCount; ++j) - { - member.metadata[j] = metadata[readU32()]; - } - } - - if((val & ATTR_final) != 0) - { - member.isFinal = true; - } - - if((val & ATTR_public) != 0) - { - member.isPublic = true; - } - - if((val & ATTR_override) != 0) - { - member.isOverride = true; - } - } - } - - void parseClassInfos() - { - int start = data.getPosition(); - int count = instances.length; - classes = new Traits[count]; - for(int i = 0; i < count; i++) - { - Traits t = classes[i] = new Traits(); - t.init = methods[readU32()]; - t.base = new Multiname(null, "Class"); - t.itraits = instances[i]; - t.name = t.itraits.name + $; - t.init.parentTraits = t; - t.init.name = new Multiname(null, t.itraits.name + $CINIT); - t.init.kind = TRAIT_Method; - parseTraits(t); - } - reportAboutPercentage("ClassInfo size ", data, start, processor); - } - - void parseScriptInfos() - { - int start = data.getPosition(); - int count = readU32(); - scripts = new Traits[count]; - - for(int i = 0; i < count; i++) - { - Traits t = new Traits(); - scripts[i] = t; - t.name = "script" + i; - t.base = names[0]; // Object - t.init = methods[readU32()]; - t.init.name = new Multiname(null, t.name + "$init"); - t.init.kind = TRAIT_Method; - t.init.parentTraits = t; - parseTraits(t); - } - - reportAboutPercentage("ScriptInfo size ", data, start, processor); - } - - void parseMethodBodies() - { - int start = data.getPosition(); - int count = readU32(); - - for(int i = 0; i < count; i++) - { - MethodInfo m = methods[readU32()]; - m.max_stack = readU32(); - m.local_count = readU32(); - int initScopeDepth = readU32(); - int maxScopeDepth = readU32(); - m.max_scope = maxScopeDepth - initScopeDepth; - int code_length = readU32(); - m.code = new ByteBuffer(); - m.code.setLittleEndian(); - - if(code_length > 0) - { - data.readBytes(m.code, code_length); - } - - int ex_count = readU32(); - for(int j = 0; j < ex_count; j++) - { - int from = readU32(); - int to = readU32(); - int target = readU32(); - Multiname type = names[readU32()]; - //sb.append("magic " + magic.toString(16)) - //if (magic >= (46<<16|16)) - Multiname name = names[readU32()]; - } - parseTraits(m.activation = new Traits()); - } - - reportAboutPercentage("MethodBodies size ", data, start, processor); - } - - private static void reportAboutPercentage(String s, ByteBuffer data, int start, @Nonnull FlexByteCodeInformationProcessor processor) - { - processor.dumpStat(s + (data.getPosition() - start) + " " + (int) 100f * (data.getPosition() - start) / data.bytesSize() + " %\n"); - } - +class Abc { + static final String TAB = " "; + static final String $CINIT = "$cinit"; + static final String $ = "$"; + + private static final int ATTR_final = 0x01; // 1=final, 0=virtual + private static final int ATTR_override = 0x02; // 1=override, 0=new + private static final int ATTR_metadata = 0x04; // 1=has metadata, 0=no metadata + private static final int ATTR_public = 0x08; // 1=add public namespace + + static final int CLASS_FLAG_sealed = 0x01; + static final int CLASS_FLAG_final = 0x02; + static final int CLASS_FLAG_interface = 0x04; + static final int CLASS_FLAG_protected = 0x08; + + // method flags + private static final int NEED_ARGUMENTS = 0x01; + static final int NEED_ACTIVATION = 0x02; + private static final int NEED_REST = 0x04; + private static final int HAS_OPTIONAL = 0x08; + private static final int IGNORE_REST = 0x10; + static final int NATIVE = 0x20; + private static final int HAS_ParamNames = 0x80; + + private static final int CONSTANT_Utf8 = 0x01; + private static final int CONSTANT_Int = 0x03; + private static final int CONSTANT_UInt = 0x04; + private static final int CONSTANT_PrivateNs = 0x05; // non-shared namespace + private static final int CONSTANT_Double = 0x06; + private static final int CONSTANT_Qname = 0x07; // o.ns::name, ct ns, ct name + private static final int CONSTANT_Namespace = 0x08; + private static final int CONSTANT_Multiname = 0x09; // o.name, ct nsset, ct name + private static final int CONSTANT_False = 0x0A; + private static final int CONSTANT_True = 0x0B; + private static final int CONSTANT_Null = 0x0C; + private static final int CONSTANT_QnameA = 0x0D; // o.@ns::name, ct ns, ct attr-name + private static final int CONSTANT_MultinameA = 0x0E; // o.@name, ct attr-name + private static final int CONSTANT_RTQname = 0x0F; // o.ns::name, rt ns, ct name + private static final int CONSTANT_RTQnameA = 0x10; // o.@ns::name, rt ns, ct attr-name + private static final int CONSTANT_RTQnameL = 0x11; // o.ns::[name], rt ns, rt name + private static final int CONSTANT_RTQnameLA = 0x12; // o.@ns::[name], rt ns, rt attr-name + private static final int CONSTANT_NameL = 0x13; // o.[], ns=public implied, rt name + private static final int CONSTANT_NameLA = 0x14; // o.@[], ns=public implied, rt attr-name + private static final int CONSTANT_NamespaceSet = 0x15; + private static final int CONSTANT_PackageNs = 0x16; + private static final int CONSTANT_PackageInternalNs = 0x17; + private static final int CONSTANT_ProtectedNs = 0x18; + private static final int CONSTANT_StaticProtectedNs = 0x19; + private static final int CONSTANT_StaticProtectedNs2 = 0x1a; + private static final int CONSTANT_MultinameL = 0x1B; + private static final int CONSTANT_MultinameLA = 0x1C; + private static final int CONSTANT_TypeName = 0x1D; + + static final String[] constantKinds = { + "0", + "utf8", + "2", + "int", + "uint", + "private", + "double", + "qname", + "namespace", + "multiname", + "false", + "true", + "null", + "@qname", + "@multiname", + "rtqname", + "@rtqname", + "[qname]", + "@[qname]", + "[name]", + "@[name]", + "nsset" + }; + + static final int TRAIT_Slot = 0x00; + private static final int TRAIT_Method = 0x01; + private static final int TRAIT_Getter = 0x02; + private static final int TRAIT_Setter = 0x03; + private static final int TRAIT_Class = 0x04; + private static final int TRAIT_Function = 0x05; + static final int TRAIT_Const = 0x06; + + static final String[] traitKinds = { + "var", + "function", + "function get", + "function set", + "class", + "function", + "const" + }; + + private static final int OP_bkpt = 0x01; + private static final int OP_nop = 0x02; + private static final int OP_throw = 0x03; + static final int OP_getsuper = 0x04; + static final int OP_setsuper = 0x05; + private static final int OP_dxns = 0x06; + private static final int OP_dxnslate = 0x07; + static final int OP_kill = 0x08; + static final int OP_label = 0x09; + static final int OP_ifnlt = 0x0C; + static final int OP_ifnle = 0x0D; + static final int OP_ifngt = 0x0E; + static final int OP_ifnge = 0x0F; + static final int OP_jump = 0x10; + static final int OP_iftrue = 0x11; + static final int OP_iffalse = 0x12; + static final int OP_ifeq = 0x13; + static final int OP_ifne = 0x14; + static final int OP_iflt = 0x15; + static final int OP_ifle = 0x16; + static final int OP_ifgt = 0x17; + static final int OP_ifge = 0x18; + static final int OP_ifstricteq = 0x19; + static final int OP_ifstrictne = 0x1A; + static final int OP_lookupswitch = 0x1B; + private static final int OP_pushwith = 0x1C; + private static final int OP_popscope = 0x1D; + private static final int OP_nextname = 0x1E; + private static final int OP_hasnext = 0x1F; + private static final int OP_pushnull = 0x20; + private static final int OP_pushundefined = 0x21; + private static final int OP_pushconstant = 0x22; + private static final int OP_nextvalue = 0x23; + static final int OP_pushbyte = 0x24; + static final int OP_pushshort = 0x25; + private static final int OP_pushtrue = 0x26; + private static final int OP_pushfalse = 0x27; + private static final int OP_pushnan = 0x28; + private static final int OP_pop = 0x29; + private static final int OP_dup = 0x2A; + private static final int OP_swap = 0x2B; + static final int OP_pushstring = 0x2C; + static final int OP_pushint = 0x2D; + static final int OP_pushuint = 0x2E; + static final int OP_pushdouble = 0x2F; + private static final int OP_pushscope = 0x30; + static final int OP_pushnamespace = 0x31; + static final int OP_hasnext2 = 0x32; + static final int OP_newfunction = 0x40; + static final int OP_call = 0x41; + static final int OP_construct = 0x42; + private static final int OP_callmethod = 0x43; + static final int OP_callstatic = 0x44; + static final int OP_callsuper = 0x45; + static final int OP_callproperty = 0x46; + private static final int OP_returnvoid = 0x47; + private static final int OP_returnvalue = 0x48; + static final int OP_constructsuper = 0x49; + static final int OP_constructprop = 0x4A; + private static final int OP_callsuperid = 0x4B; + static final int OP_callproplex = 0x4C; + private static final int OP_callinterface = 0x4D; + static final int OP_callsupervoid = 0x4E; + static final int OP_callpropvoid = 0x4F; + private static final int OP_applytype = 0x53; + static final int OP_newobject = 0x55; + static final int OP_newarray = 0x56; + private static final int OP_newactivation = 0x57; + static final int OP_newclass = 0x58; + static final int OP_getdescendants = 0x59; + static final int OP_newcatch = 0x5A; + static final int OP_findpropstrict = 0x5D; + static final int OP_findproperty = 0x5E; + static final int OP_finddef = 0x5F; + static final int OP_getlex = 0x60; + static final int OP_setproperty = 0x61; + static final int OP_getlocal = 0x62; + static final int OP_setlocal = 0x63; + private static final int OP_getglobalscope = 0x64; + static final int OP_getscopeobject = 0x65; + static final int OP_getproperty = 0x66; + private static final int OP_getouterscope = 0x67; + static final int OP_initproperty = 0x68; + private static final int OP_setpropertylate = 0x69; + static final int OP_deleteproperty = 0x6A; + private static final int OP_deletepropertylate = 0x6B; + static final int OP_getslot = 0x6C; + static final int OP_setslot = 0x6D; + static final int OP_getglobalslot = 0x6E; + static final int OP_setglobalslot = 0x6F; + private static final int OP_convert_s = 0x70; + private static final int OP_esc_xelem = 0x71; + private static final int OP_esc_xattr = 0x72; + private static final int OP_convert_i = 0x73; + private static final int OP_convert_u = 0x74; + private static final int OP_convert_d = 0x75; + private static final int OP_convert_b = 0x76; + private static final int OP_convert_o = 0x77; + static final int OP_coerce = 0x80; + private static final int OP_coerce_b = 0x81; + private static final int OP_coerce_a = 0x82; + private static final int OP_coerce_i = 0x83; + private static final int OP_coerce_d = 0x84; + private static final int OP_coerce_s = 0x85; + static final int OP_astype = 0x86; + private static final int OP_astypelate = 0x87; + private static final int OP_coerce_u = 0x88; + private static final int OP_coerce_o = 0x89; + private static final int OP_negate = 0x90; + private static final int OP_increment = 0x91; + static final int OP_inclocal = 0x92; + private static final int OP_decrement = 0x93; + static final int OP_declocal = 0x94; + private static final int OP_typeof = 0x95; + private static final int OP_not = 0x96; + private static final int OP_bitnot = 0x97; + private static final int OP_concat = 0x9A; + private static final int OP_add_d = 0x9B; + private static final int OP_add = 0xA0; + private static final int OP_subtract = 0xA1; + private static final int OP_multiply = 0xA2; + private static final int OP_divide = 0xA3; + private static final int OP_modulo = 0xA4; + private static final int OP_lshift = 0xA5; + private static final int OP_rshift = 0xA6; + private static final int OP_urshift = 0xA7; + private static final int OP_bitand = 0xA8; + private static final int OP_bitor = 0xA9; + private static final int OP_bitxor = 0xAA; + private static final int OP_equals = 0xAB; + private static final int OP_strictequals = 0xAC; + private static final int OP_lessthan = 0xAD; + private static final int OP_lessequals = 0xAE; + private static final int OP_greaterthan = 0xAF; + private static final int OP_greaterequals = 0xB0; + private static final int OP_instanceof = 0xB1; + static final int OP_istype = 0xB2; + private static final int OP_istypelate = 0xB3; + private static final int OP_in = 0xB4; + private static final int OP_increment_i = 0xC0; + private static final int OP_decrement_i = 0xC1; + static final int OP_inclocal_i = 0xC2; + static final int OP_declocal_i = 0xC3; + private static final int OP_negate_i = 0xC4; + private static final int OP_add_i = 0xC5; + private static final int OP_subtract_i = 0xC6; + private static final int OP_multiply_i = 0xC7; + private static final int OP_getlocal0 = 0xD0; + private static final int OP_getlocal1 = 0xD1; + private static final int OP_getlocal2 = 0xD2; + private static final int OP_getlocal3 = 0xD3; + private static final int OP_setlocal0 = 0xD4; + private static final int OP_setlocal1 = 0xD5; + private static final int OP_setlocal2 = 0xD6; + private static final int OP_setlocal3 = 0xD7; + static final int OP_debug = 0xEF; + static final int OP_debugline = 0xF0; + static final int OP_debugfile = 0xF1; + private static final int OP_bkptline = 0xF2; + + static final String[] opNames = { + "OP_0x00 ", + "bkpt ", + "nop ", + "throw ", + "getsuper ", + "setsuper ", + "dxns ", + "dxnslate ", + "kill ", + "label ", + "OP_0x0A ", + "OP_0x0B ", + "ifnlt ", + "ifnle ", + "ifngt ", + "ifnge ", + "jump ", + "iftrue ", + "iffalse ", + "ifeq ", + "ifne ", + "iflt ", + "ifle ", + "ifgt ", + "ifge ", + "ifstricteq ", + "ifstrictne ", + "lookupswitch ", + "pushwith ", + "popscope ", + "nextname ", + "hasnext ", + "pushnull ", + "pushundefined ", + "pushconstant ", + "nextvalue ", + "pushbyte ", + "pushshort ", + "pushtrue ", + "pushfalse ", + "pushnan ", + "pop ", + "dup ", + "swap ", + "pushstring ", + "pushint ", + "pushuint ", + "pushdouble ", + "pushscope ", + "pushnamespace ", + "hasnext2 ", + "OP_0x33 ", + "OP_0x34 ", + "OP_0x35 ", + "OP_0x36 ", + "OP_0x37 ", + "OP_0x38 ", + "OP_0x39 ", + "OP_0x3A ", + "OP_0x3B ", + "OP_0x3C ", + "OP_0x3D ", + "OP_0x3E ", + "OP_0x3F ", + "newfunction ", + "call ", + "construct ", + "callmethod ", + "callstatic ", + "callsuper ", + "callproperty ", + "returnvoid ", + "returnvalue ", + "constructsuper", + "constructprop ", + "callsuperid ", + "callproplex ", + "callinterface ", + "callsupervoid ", + "callpropvoid ", + "OP_0x50 ", + "OP_0x51 ", + "OP_0x52 ", + "applytype ", + "OP_0x54 ", + "newobject ", + "newarray ", + "newactivation ", + "newclass ", + "getdescendants", + "newcatch ", + "OP_0x5B ", + "OP_0x5C ", + "findpropstrict", + "findproperty ", + "finddef ", + "getlex ", + "setproperty ", + "getlocal ", + "setlocal ", + "getglobalscope", + "getscopeobject", + "getproperty ", + "getouterscope ", + "initproperty ", + "OP_0x69 ", + "deleteproperty", + "OP_0x6A ", + "getslot ", + "setslot ", + "getglobalslot ", + "setglobalslot ", + "convert_s ", + "esc_xelem ", + "esc_xattr ", + "convert_i ", + "convert_u ", + "convert_d ", + "convert_b ", + "convert_o ", + "checkfilter ", + "OP_0x79 ", + "OP_0x7A ", + "OP_0x7B ", + "OP_0x7C ", + "OP_0x7D ", + "OP_0x7E ", + "OP_0x7F ", + "coerce ", + "coerce_b ", + "coerce_a ", + "coerce_i ", + "coerce_d ", + "coerce_s ", + "astype ", + "astypelate ", + "coerce_u ", + "coerce_o ", + "OP_0x8A ", + "OP_0x8B ", + "OP_0x8C ", + "OP_0x8D ", + "OP_0x8E ", + "OP_0x8F ", + "negate ", + "increment ", + "inclocal ", + "decrement ", + "declocal ", + "typeof ", + "not ", + "bitnot ", + "OP_0x98 ", + "OP_0x99 ", + "concat ", + "add_d ", + "OP_0x9C ", + "OP_0x9D ", + "OP_0x9E ", + "OP_0x9F ", + "add ", + "subtract ", + "multiply ", + "divide ", + "modulo ", + "lshift ", + "rshift ", + "urshift ", + "bitand ", + "bitor ", + "bitxor ", + "equals ", + "strictequals ", + "lessthan ", + "lessequals ", + "greaterthan ", + "greaterequals ", + "instanceof ", + "istype ", + "istypelate ", + "in ", + "OP_0xB5 ", + "OP_0xB6 ", + "OP_0xB7 ", + "OP_0xB8 ", + "OP_0xB9 ", + "OP_0xBA ", + "OP_0xBB ", + "OP_0xBC ", + "OP_0xBD ", + "OP_0xBE ", + "OP_0xBF ", + "increment_i ", + "decrement_i ", + "inclocal_i ", + "declocal_i ", + "negate_i ", + "add_i ", + "subtract_i ", + "multiply_i ", + "OP_0xC8 ", + "OP_0xC9 ", + "OP_0xCA ", + "OP_0xCB ", + "OP_0xCC ", + "OP_0xCD ", + "OP_0xCE ", + "OP_0xCF ", + "getlocal0 ", + "getlocal1 ", + "getlocal2 ", + "getlocal3 ", + "setlocal0 ", + "setlocal1 ", + "setlocal2 ", + "setlocal3 ", + "OP_0xD8 ", + "OP_0xD9 ", + "OP_0xDA ", + "OP_0xDB ", + "OP_0xDC ", + "OP_0xDD ", + "OP_0xDE ", + "OP_0xDF ", + "OP_0xE0 ", + "OP_0xE1 ", + "OP_0xE2 ", + "OP_0xE3 ", + "OP_0xE4 ", + "OP_0xE5 ", + "OP_0xE6 ", + "OP_0xE7 ", + "OP_0xE8 ", + "OP_0xE9 ", + "OP_0xEA ", + "OP_0xEB ", + "OP_0xEC ", + "OP_0xED ", + "OP_0xEE ", + "debug ", + "debugline ", + "debugfile ", + "bkptline ", + "timestamp ", + "OP_0xF4 ", + "verifypass ", + "alloc ", + "mark ", + "wb ", + "prologue ", + "sendenter ", + "doubletoatom ", + "sweep ", + "codegenop ", + "verifyop ", + "decode " + }; + + private FlexByteCodeInformationProcessor processor; + int totalSize; + final int opSizes[] = new int[256]; + + public Abc(@Nonnull ByteBuffer _data, @Nonnull FlexByteCodeInformationProcessor _processor) { + data = _data; + processor = _processor; + + data.setPosition(0); + magic = data.readInt(); + + _processor.dumpStat("magic " + Integer.toString(magic, 16) + "\n"); + + if (magic != (46 << 16 | 14) && magic != (46 << 16 | 15) && magic != (46 << 16 | 16)) { + throw new Error("not an abc file. magic=" + Integer.toString(magic, 16)); + } + + parseCpool(); + + defaults[CONSTANT_Utf8] = strings; + defaults[CONSTANT_Int] = ints; + defaults[CONSTANT_UInt] = uints; + defaults[CONSTANT_Double] = doubles; + defaults[CONSTANT_Int] = ints; + defaults[CONSTANT_False] = buildSparseArray(10, "false"); + defaults[CONSTANT_True] = buildSparseArray(11, "true"); + defaults[CONSTANT_Namespace] = namespaces; + defaults[CONSTANT_PrivateNs] = namespaces; + defaults[CONSTANT_PackageNs] = namespaces; + defaults[CONSTANT_PackageInternalNs] = namespaces; + defaults[CONSTANT_ProtectedNs] = namespaces; + defaults[CONSTANT_StaticProtectedNs] = namespaces; + defaults[CONSTANT_StaticProtectedNs2] = namespaces; + defaults[CONSTANT_Null] = buildSparseArray(12, "null"); + + parseMethodInfos(); + parseMetadataInfos(); + parseInstanceInfos(); + parseClassInfos(); + parseScriptInfos(); + parseMethodBodies(); + } + + private static Object[] buildSparseArray(int index, String s1) { + Object[] result = new Object[index + 1]; + result[index] = s1; + return result; + } + + public void dump(String indent) { + for (Traits t : scripts) { + processor.dumpTopLevelTraits(this, t, indent); + } + + for (MethodInfo m : methods) { + if (m.anon) { + processor.dumpToplevelAnonymousMethod(this, m); + } + } + + processor.dumpStat("OPCODE\tSIZE\t% OF " + totalSize + "\n"); + Set done = new HashSet<>(); + while (true) { + int max = -1; + int maxsize = 0; + for (int i = 0; i < 256; i++) { + if (opSizes[i] > maxsize && !done.contains(i)) { + max = i; + maxsize = opSizes[i]; + } + } + if (max == -1) { + break; + } + done.add(max); + processor.dumpStat(opNames[max] + "\t" + opSizes[max] + "\t" + (int)(100f * opSizes[max] / totalSize) + "%\n"); + } + } + + private final ByteBuffer data; + int major; + int minor; + + Integer[] ints; + Integer[] uints; + Double[] doubles; + String[] strings; + String[] namespaces; + String[][] nssets; + Multiname[] names; + + final Object[][] defaults = new Object[Math.max(constantKinds.length, CONSTANT_MultinameLA + 1)][]; + + MethodInfo methods[]; + Traits instances[]; + Traits classes[]; + Traits[] scripts; + MetaData metadata[]; + + String publicNs = ""; + String anyNs = "*"; + + final int magic; + + int readU32() { + return data.readU32(); + } + + void parseCpool() { + int i, j; + int n; + int start = data.getPosition(); + + // ints + n = readU32(); + ints = new Integer[n > 0 ? n : 1]; + ints[0] = 0; + for (i = 1; i < n; i++) { + ints[i] = readU32(); + } + + // uints + n = readU32(); + uints = new Integer[n > 0 ? n : 1]; + uints[0] = 0; + for (i = 1; i < n; i++) { + uints[i] = readU32(); + } + + // doubles + n = readU32(); + doubles = new Double[n > 0 ? n : 1]; + doubles[0] = Double.NaN; + for (i = 1; i < n; i++) { + doubles[i] = data.readDouble(); + } + + reportAboutPercentage("Cpool numbers size ", data, start, processor); + start = data.getPosition(); + + // strings + n = readU32(); + strings = new String[n]; + strings[0] = ""; + for (i = 1; i < n; i++) { + strings[i] = data.readUTFBytes(readU32()); + } + + reportAboutPercentage("Cpool strings count " + n + " size ", data, start, processor); + start = data.getPosition(); + + // namespaces + n = readU32(); + namespaces = new String[n]; + namespaces[0] = publicNs; + for (i = 1; i < n; i++) { + switch (data.readByte()) { + case CONSTANT_Namespace: + case CONSTANT_PackageNs: + case CONSTANT_PackageInternalNs: + case CONSTANT_ProtectedNs: + case CONSTANT_StaticProtectedNs: + case CONSTANT_StaticProtectedNs2: { + namespaces[i] = strings[readU32()]; + // todo mark kind of namespace. + break; + } + case CONSTANT_PrivateNs: + readU32(); + namespaces[i] = "private"; + break; + } + } + + reportAboutPercentage("Cpool namespaces count " + n + " size ", data, start, processor); + start = data.getPosition(); + + // namespace sets + n = readU32(); + nssets = new String[n][]; + for (i = 1; i < n; i++) { + int count = readU32(); + String[] nsset = nssets[i] = new String[count]; + for (j = 0; j < count; j++) { + nsset[j] = namespaces[readU32()]; + } + } + + reportAboutPercentage("Cpool nssets count " + n + " size ", data, start, processor); + start = data.getPosition(); + + // multinames + n = readU32(); + names = new Multiname[n]; + namespaces[0] = anyNs; + strings[0] = "*"; // any name + for (i = 1; i < n; i++) { + switch (data.readByte()) { + case CONSTANT_Qname: + case CONSTANT_QnameA: + names[i] = new Multiname(new String[]{namespaces[readU32()]}, strings[readU32()]); + break; + + case CONSTANT_RTQname: + case CONSTANT_RTQnameA: + names[i] = new Multiname(new String[]{strings[readU32()]}, null); + break; + + case CONSTANT_RTQnameL: + case CONSTANT_RTQnameLA: + names[i] = null; + break; + + case CONSTANT_NameL: + case CONSTANT_NameLA: + names[i] = new Multiname(new String[]{""}, null); + break; + + case CONSTANT_Multiname: + case CONSTANT_MultinameA: + String name = strings[readU32()]; + names[i] = new Multiname(nssets[readU32()], name); + break; + + case CONSTANT_MultinameL: + case CONSTANT_MultinameLA: + names[i] = new Multiname(nssets[readU32()], null); + break; + + case CONSTANT_TypeName: + // TODO: + int nameId = readU32(); + String nsName = names[nameId].toString(); + + int count = readU32(); + + if (count > 0) { + nsName += "<"; + for (int k = 0; k < count; k++) { + if (k != 0) { + nsName += ","; + } + nameId = readU32(); + Multiname typeArgName = names[nameId]; + String typeArgNameString; + + if (processor instanceof AS3InterfaceDumper) { + boolean vector = typeArgName.hasNotEmptyNs() && typeArgName.nsset[0].equals("__AS3__.vec"); + typeArgNameString = vector ? typeArgName.name : typeArgName.toString(); + typeArgNameString = typeArgNameString.replaceAll("::", ".") + (vector ? " " : ""); + } + else { + typeArgNameString = typeArgName.toString(); + } + nsName += typeArgNameString; + } + + nsName += ">"; + } + + int index = nsName.indexOf("::"); + + names[i] = new Multiname( + new String[]{index != -1 ? nsName.substring(0, index) : ""}, + index != -1 ? nsName.substring(index + 2) : nsName + ); + break; + + default: + throw new Error("invalid kind " + data.getByte(data.getPosition() - 1)); + } + } + + reportAboutPercentage("Cpool names count " + n + " size ", data, start, processor); + start = data.getPosition(); + + namespaces[0] = publicNs; + strings[0] = "*"; + } + + void parseMethodInfos() { + int start = data.getPosition(); + names[0] = new Multiname(new String[]{publicNs}, "*"); + int method_count = readU32(); + methods = new MethodInfo[method_count]; + + for (int i = 0; i < method_count; i++) { + MethodInfo m = methods[i] = new MethodInfo(); + int param_count = readU32(); + m.returnType = names[readU32()]; + m.paramTypes = new Multiname[param_count]; + for (int j = 0; j < param_count; j++) { + m.paramTypes[j] = names[readU32()]; + } + m.debugName = strings[readU32()]; + m.flags = data.readByte(); + + if ((m.flags & HAS_OPTIONAL) != 0) { + // has_optional + int optional_count = readU32(); + m.optionalValues = new Multiname[param_count]; + for (int k = param_count - optional_count; k < param_count; ++k) { + int index = readU32(); // optional value index + int kind = data.readByte(); // kind byte for each default value + + if (index == 0) { + // kind is ignored, default value is based on type + String value; + String type = m.paramTypes[k].toString(); + + if ("Number".equals(type) || "decimal".equals(type)) { + value = "0"; + } + else if ("*".equals(type)) { + value = "null"; + } + else if ("String".equals(type)) { + value = ""; + } + else { + value = "null"; + } + m.optionalValues[k] = new Multiname(null, value); + } + else if (defaults[kind] == null) { + processor.hasError("ERROR kind=" + kind + " method_id " + i + "\n"); + } + else { + m.optionalValues[k] = new Multiname(null, defaults[kind][index].toString()); + } + } + } + if ((m.flags & HAS_ParamNames) != 0) { + m.paramNames = new String[param_count]; + for (int k = 0; k < param_count; ++k) { + int index = readU32(); + String name = strings[index]; + m.paramNames[k] = StringUtil.isJavaIdentifier(name) ? name : "_" + index; + } + } + + if ((m.flags & NEED_REST) != 0) { + m.paramTypes = ArrayUtil.append(m.paramTypes, new Multiname(null, "...")); + + if (m.paramNames != null) { + m.paramNames = ArrayUtil.append(m.paramNames, "__rest"); + } + } + } + + reportAboutPercentage("MethodInfo count " + method_count + " size ", data, start, processor); + } + + void parseMetadataInfos() { + int count = readU32(); + metadata = new MetaData[count]; + for (int i = 0; i < count; i++) { + // MetadataInfo + MetaData m = metadata[i] = new MetaData(); + m.name = strings[readU32()]; + int values_count = readU32(); + String names[] = new String[values_count]; + + for (int q = 0; q < values_count; ++q) { + names[q] = strings[readU32()]; // name + } + for (int q = 0; q < values_count; ++q) { + m.put(names[q], strings[readU32()]); // value + } + } + } + + void parseInstanceInfos() { + int start = data.getPosition(); + int count = readU32(); + instances = new Traits[count]; + for (int i = 0; i < count; i++) { + Traits t = instances[i] = new Traits(); + t.name = names[readU32()]; + t.base = names[readU32()]; + t.flags = data.readByte(); + + if ((t.flags & CLASS_FLAG_protected) != 0) { + t.protectedNs = namespaces[readU32()]; + } + + int interface_count = readU32(); + t.interfaces = new Multiname[interface_count]; + for (int j = 0; j < interface_count; j++) { + t.interfaces[j] = names[readU32()]; + } + MethodInfo m = t.init = methods[readU32()]; + m.name = ((Multiname)t.name); + m.kind = TRAIT_Method; + m.id = -1; + m.parentTraits = t; + parseTraits(t); + } + + reportAboutPercentage("InstanceInfo size ", data, start, processor); + } + + void parseTraits(Traits t) { + int namecount = readU32(); + for (int i = 0; i < namecount; i++) { + Multiname name = names[readU32()]; + int tag = data.readByte(); + int kind = tag & 0xf; + MemberInfo member = null; + + switch (kind) { + case TRAIT_Slot: + case TRAIT_Const: + case TRAIT_Class: + SlotInfo slot = new SlotInfo(); + member = slot; + slot.id = readU32(); + t.slots.put(slot.id, slot); + if (kind == TRAIT_Slot || kind == TRAIT_Const) { + slot.type = names[readU32()]; + int index = readU32(); + if (index > 0) { + slot.value = defaults[data.readByte()][index]; + } + } + else // (kind == TRAIT_Class) + { + slot.value = classes[readU32()]; + } + break; + case TRAIT_Method: + case TRAIT_Getter: + case TRAIT_Setter: + int disp_id = readU32(); + MethodInfo method = methods[readU32()]; + member = method; + t.methods.put(disp_id, method); + method.id = disp_id; + //sb.append("\t",traitKinds[kind],name,disp_id,method,"// disp_id", disp_id) + break; + } + if (member == null) { + processor.hasError("error trait kind " + kind + "\n"); + } + member.kind = kind; + member.name = name; + t.members.put(i, member); + t.names.put(name.toString(), member); + member.parentTraits = t; + + int val = tag >> 4; + if ((val & ATTR_metadata) != 0) { + int mdCount = readU32(); + member.metadata = new MetaData[mdCount]; + for (int j = 0; j < mdCount; ++j) { + member.metadata[j] = metadata[readU32()]; + } + } + + if ((val & ATTR_final) != 0) { + member.isFinal = true; + } + + if ((val & ATTR_public) != 0) { + member.isPublic = true; + } + + if ((val & ATTR_override) != 0) { + member.isOverride = true; + } + } + } + + void parseClassInfos() { + int start = data.getPosition(); + int count = instances.length; + classes = new Traits[count]; + for (int i = 0; i < count; i++) { + Traits t = classes[i] = new Traits(); + t.init = methods[readU32()]; + t.base = new Multiname(null, "Class"); + t.itraits = instances[i]; + t.name = t.itraits.name + $; + t.init.parentTraits = t; + t.init.name = new Multiname(null, t.itraits.name + $CINIT); + t.init.kind = TRAIT_Method; + parseTraits(t); + } + reportAboutPercentage("ClassInfo size ", data, start, processor); + } + + void parseScriptInfos() { + int start = data.getPosition(); + int count = readU32(); + scripts = new Traits[count]; + + for (int i = 0; i < count; i++) { + Traits t = new Traits(); + scripts[i] = t; + t.name = "script" + i; + t.base = names[0]; // Object + t.init = methods[readU32()]; + t.init.name = new Multiname(null, t.name + "$init"); + t.init.kind = TRAIT_Method; + t.init.parentTraits = t; + parseTraits(t); + } + + reportAboutPercentage("ScriptInfo size ", data, start, processor); + } + + void parseMethodBodies() { + int start = data.getPosition(); + int count = readU32(); + + for (int i = 0; i < count; i++) { + MethodInfo m = methods[readU32()]; + m.max_stack = readU32(); + m.local_count = readU32(); + int initScopeDepth = readU32(); + int maxScopeDepth = readU32(); + m.max_scope = maxScopeDepth - initScopeDepth; + int code_length = readU32(); + m.code = new ByteBuffer(); + m.code.setLittleEndian(); + + if (code_length > 0) { + data.readBytes(m.code, code_length); + } + + int ex_count = readU32(); + for (int j = 0; j < ex_count; j++) { + int from = readU32(); + int to = readU32(); + int target = readU32(); + Multiname type = names[readU32()]; + //sb.append("magic " + magic.toString(16)) + //if (magic >= (46<<16|16)) + Multiname name = names[readU32()]; + } + parseTraits(m.activation = new Traits()); + } + + reportAboutPercentage("MethodBodies size ", data, start, processor); + } + + private static void reportAboutPercentage(String s, ByteBuffer data, int start, @Nonnull FlexByteCodeInformationProcessor processor) { + processor.dumpStat(s + (data.getPosition() - start) + " " + (int)100f * (data.getPosition() - start) / data.bytesSize() + " %\n"); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/AbcDumper.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/AbcDumper.java index c23677c8..6bcbbf2d 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/AbcDumper.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/AbcDumper.java @@ -16,147 +16,133 @@ package com.intellij.lang.javascript.impl.flex.importer; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author Maxim.Mossienko - * Date: Oct 20, 2008 - * Time: 7:02:22 PM + * @since 2008-10-20 */ -class AbcDumper extends AbstractDumpProcessor -{ - private boolean dumpCode; - - public AbcDumper(final boolean _dumpCode) - { - dumpCode = _dumpCode; - } - - @Override - public void dumpStat(@Nonnull final String stat) - { - sb.append(stat); - } - - @Override - public void hasError(@Nonnull final String error) - { - sb.append(error); - } - - @Override - protected String appendModifiers(MemberInfo member, String attr) - { - attr += (member instanceof MethodInfo && (((MethodInfo) member).flags & Abc.NATIVE) != 0 ? "native " : ""); - return attr; - } - - @Override - public void processMultinameAsPackageName(@Nonnull final Multiname name, @Nullable final String parentName, final boolean referenceNameRequested) - { - append(name.toString()); - } - - @Override - public void dumpToplevelAnonymousMethod(final @Nonnull Abc abc, final @Nonnull MethodInfo m) - { - m.dump(abc, "", "", this); - } - - @Override - public void dumpTopLevelTraits(final Abc abc, final @Nonnull Traits t, final String indent) - { - sb.append(indent + t.name + "\n"); - t.dump(abc, indent, "", this); - t.init.dump(abc, indent, "", this); - } - - @Override - public boolean doDumpMember(final @Nonnull MemberInfo memberInfo) - { - return true; - } - - @Override - public void appendMethodSeparator() - { - append("\n"); - } - - @Override - public void appendFieldSeparator() - { - append(""); - } - - @Override - public String getAbcInSwfIndent() - { - return " "; - } - - @Override - public void processValue(final Multiname type, final Object value) - { - append(" = " + String.valueOf(value instanceof String ? ('"' + value.toString() + '"') : value)); - } - - @Override - public boolean doDumpMetaData(final @Nonnull MetaData md) - { - return true; - } - - @Override - public void processParameter(@Nonnull String name, @Nullable Multiname type, String parentName, @Nullable Multiname value, boolean rest) - { - processMultinameAsPackageName(type, parentName, true); - } - - @Override - public boolean doStarTypeDumpInExtends() - { - return true; - } - - @Override - public boolean doStarMetaAttrNameDump() - { - return true; - } - - @Override - public void setProcessingInterface(final boolean anInterface) - { - } - - @Override - protected boolean dumpRestParameter() - { - return false; - } - - @Override - public void processFunction(MethodInfo methodInfo, boolean referenceNameRequested, Abc abc, String indent, String attr) - { - super.processFunction(methodInfo, referenceNameRequested, abc, indent, attr); - append("\t/* disp_id " + methodInfo.id + "*/"); - - if(!referenceNameRequested) - { // !verbose -> anonymouse - append("\n"); - if(dumpCode && methodInfo.code != null) - { - methodInfo.dumpCode(abc, indent, this); - } - } - } - - @Override - public void processVariable(SlotInfo info, String indent, String attr) - { - super.processVariable(info, indent, attr); - append("\t/* slot_id " + info.id + " */\n"); - } +class AbcDumper extends AbstractDumpProcessor { + private boolean dumpCode; + + public AbcDumper(boolean _dumpCode) { + dumpCode = _dumpCode; + } + + @Override + public void dumpStat(@Nonnull String stat) { + sb.append(stat); + } + + @Override + public void hasError(@Nonnull String error) { + sb.append(error); + } + + @Override + protected String appendModifiers(MemberInfo member, String attr) { + attr += member instanceof MethodInfo methodInfo && (methodInfo.flags & Abc.NATIVE) != 0 ? "native " : ""; + return attr; + } + + @Override + public void processMultinameAsPackageName( + @Nonnull Multiname name, + @Nullable String parentName, + boolean referenceNameRequested + ) { + append(name.toString()); + } + + @Override + public void dumpToplevelAnonymousMethod(@Nonnull Abc abc, @Nonnull MethodInfo m) { + m.dump(abc, "", "", this); + } + + @Override + public void dumpTopLevelTraits(@Nonnull Abc abc, @Nonnull Traits t, String indent) { + sb.append(indent).append(t.name).append("\n"); + t.dump(abc, indent, "", this); + t.init.dump(abc, indent, "", this); + } + + @Override + public boolean doDumpMember(@Nonnull MemberInfo memberInfo) { + return true; + } + + @Override + public void appendMethodSeparator() { + append("\n"); + } + + @Override + public void appendFieldSeparator() { + append(""); + } + + @Override + public String getAbcInSwfIndent() { + return " "; + } + + @Override + public void processValue(Multiname type, Object value) { + append(" = " + String.valueOf(value instanceof String ? ('"' + value.toString() + '"') : value)); + } + + @Override + public boolean doDumpMetaData(@Nonnull MetaData md) { + return true; + } + + @Override + public void processParameter( + @Nonnull String name, + @Nullable Multiname type, + String parentName, + @Nullable Multiname value, + boolean rest + ) { + processMultinameAsPackageName(type, parentName, true); + } + + @Override + public boolean doStarTypeDumpInExtends() { + return true; + } + + @Override + public boolean doStarMetaAttrNameDump() { + return true; + } + + @Override + public void setProcessingInterface(boolean anInterface) { + } + + @Override + protected boolean dumpRestParameter() { + return false; + } + + @Override + public void processFunction(MethodInfo methodInfo, boolean referenceNameRequested, Abc abc, String indent, String attr) { + super.processFunction(methodInfo, referenceNameRequested, abc, indent, attr); + append("\t/* disp_id " + methodInfo.id + "*/"); + + if (!referenceNameRequested) { // !verbose -> anonymouse + append("\n"); + if (dumpCode && methodInfo.code != null) { + methodInfo.dumpCode(abc, indent, this); + } + } + } + + @Override + public void processVariable(SlotInfo info, String indent, String attr) { + super.processVariable(info, indent, attr); + append("\t/* slot_id " + info.id + " */\n"); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/AbstractDumpProcessor.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/AbstractDumpProcessor.java index e49008ed..7eecd220 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/AbstractDumpProcessor.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/AbstractDumpProcessor.java @@ -16,300 +16,250 @@ package com.intellij.lang.javascript.impl.flex.importer; -import javax.annotation.Nonnull; - -import org.jetbrains.annotations.NonNls; +import jakarta.annotation.Nonnull; /** * @author Maxim.Mossienko - * Date: Oct 20, 2008 - * Time: 7:02:13 PM + * @since 2008-10-20 */ -abstract class AbstractDumpProcessor implements FlexByteCodeInformationProcessor -{ - protected - @NonNls - StringBuilder sb = new StringBuilder(); - private boolean firstMetaDataMember; - - String getResult() - { - return sb.toString(); - } - - @Override - public void append(@Nonnull @NonNls String str) - { - sb.append(str); - } - - @Override - public String getParentName(final MemberInfo member) - { - String parentName = null; - - if(member.parentTraits != null) - { - if(member.parentTraits.name instanceof Multiname) - { - final Multiname multiname = (Multiname) member.parentTraits.name; - - if(multiname.hasNamespace()) - { - parentName = multiname.name; - } - } - if(parentName == null) - { - parentName = member.parentTraits.name.toString().replaceAll("::", "."); - } - } - return parentName; - } - - public void addMetaDataValue(String s, String s1) - { - append(firstMetaDataMember ? "(" : ","); - firstMetaDataMember = false; - if(s != null) - { - append(s); - append("="); - } - append(s1); - } - - @Override - public void processVariable(SlotInfo info, String indent, String attr) - { - appendFieldSeparator(); - - attr = appendModifiers(info, attr); - processModifierList(info, attr, indent); - append(indent + attr); - processMemberKindAndName(info); - - append(":"); - processMultinameAsPackageName(info.type, info.parentTraits.getClassName(), true); - if(info.value != null) - { - processValue(info.type, info.value); - } - } - - @Override - public void processFunction(MethodInfo methodInfo, boolean referenceNameRequested, Abc abc, String indent, String attr) - { - if(!referenceNameRequested) - { - appendMethodSeparator(); - } - - attr = appendModifiers(methodInfo, attr); - processModifierList(methodInfo, attr, indent); - - append(indent + attr); - - processMemberKindAndName(methodInfo); - final String parentName = methodInfo.getParentName(); - processArgumentList(methodInfo, parentName); - append(":"); - processMultinameAsPackageName(methodInfo.returnType, parentName, referenceNameRequested); - } - - protected void processMemberKindAndName(@Nonnull final MemberInfo member) - { - append(Abc.traitKinds[member.kind]); - append(" "); - - if(member.name != null) - { - processMultinameAsPackageName(member.name, member.parentTraits.getClassName(), false); - } - else - { - append("undefined"); - } - } - - protected abstract String appendModifiers(MemberInfo methodInfo, String attr); - - protected abstract void processValue(Multiname type, Object value); - - protected void processArgumentList(MethodInfo methodInfo, String parentName) - { - append("("); - - for(int i = 0; i < methodInfo.paramTypes.length; ++i) - { - final Multiname paramType = methodInfo.paramTypes[i]; - final boolean restParameter = FlexByteCodeInformationProcessor.REST_PARAMETER_TYPE.equals(paramType.name); - if(restParameter && !dumpRestParameter()) - { - break; // original one do not dump - } - if(i > 0) - { - append(","); - } - - processParameter(methodInfo.paramNames != null ? methodInfo.paramNames[i] : "a" + (i > 0 ? "" + (i + 1) : ""), methodInfo.paramTypes[i], - parentName, methodInfo.optionalValues != null && i < methodInfo.optionalValues.length ? methodInfo.optionalValues[i] : null, restParameter); - } - - append(")"); - } - - protected abstract boolean dumpRestParameter(); - - @Override - public void processMetadata(MetaData metaData) - { - append("["); - append(metaData.name); - firstMetaDataMember = true; - - for(String n : metaData.keySet()) - { - addMetaDataValue(!"*".equals(n) || doStarMetaAttrNameDump() ? n : null, '"' + metaData.get(n) + '"'); - } - - if(!firstMetaDataMember) - { - append(")"); - } - append("]"); - } - - @Override - public void processClass(SlotInfo slotInfo, Abc abc, String attr, String indent) - { - append("\n"); - - @NonNls String def; - final boolean isInterface = slotInfo.isInterfaceClass(); - if(isInterface) - { - def = "interface"; - } - else - { - def = "class"; - } - - if(!doStarTypeDumpInExtends()) - { - final String ns = slotInfo.name.hasNamespace() ? slotInfo.name.getNsName() : null; - - if(ns != null && ns.length() > 0) - { - attr += ns; - } - else - { - attr += "public"; - } - attr += " "; - } - - Traits ct = (Traits) slotInfo.value; - Traits it = ct.itraits; - if(!isInterface) - { - if((it.flags & Abc.CLASS_FLAG_final) != 0) - { - attr += "final "; - } - if((it.flags & Abc.CLASS_FLAG_sealed) == 0) - { - attr += "dynamic "; - } - } - - processModifierList(slotInfo, attr, indent); - - append(indent + attr + def + " "); - processMultinameAsPackageName(slotInfo.name, null, true); - dumpExtendsList(it); - - append("\n"); - String oldindent = indent; - indent += Abc.TAB; - - dumpInterfacesList(indent, it, isInterface); - append(oldindent + "{\n"); - setProcessingInterface(isInterface); - - it.init.dump(abc, indent, "", this); - it.dump(abc, indent, "", this); - ct.dump(abc, indent, "static ", this); - ct.init.dump(abc, indent, "static ", this); - append(oldindent + "}\n"); - setProcessingInterface(false); - } - - protected void processModifierList(MemberInfo memberInfo, String attr, String indent) - { - memberInfo.dumpMetaData(indent, this); - } - - protected void dumpExtendsList(Traits it) - { - if(!it.base.isStarReference() || doStarTypeDumpInExtends()) - { - append(" extends "); - processMultinameAsPackageName(it.base, null, true); - } - } - - protected void dumpInterfacesList(String indent, Traits it, boolean anInterface) - { - if(it.interfaces.length > 0) - { - append(indent + (anInterface && this instanceof AS3InterfaceDumper ? "extends " : "implements ")); - boolean first = true; - - for(Multiname name : it.interfaces) - { - if(!first) - { - append(","); - } - first = false; - processMultinameAsPackageName(name, null, true); - } - append("\n"); - } - } - - protected static String quote(final String s) - { - if(s.length() == 0) - { - return s; - } - final StringBuilder b = new StringBuilder(s.length()); - - for(int i = 0; i < s.length(); ++i) - { - final char ch = s.charAt(i); - - if(ch == '\\' || ch == '"') - { - b.append('\\'); - } - else if(ch == '\n') - { - b.append("\\n"); - continue; - } - else if(ch == '\r') - { - b.append("\\r"); - continue; - } - b.append(ch); - } - return b.toString(); - } +abstract class AbstractDumpProcessor implements FlexByteCodeInformationProcessor { + protected StringBuilder sb = new StringBuilder(); + private boolean firstMetaDataMember; + + String getResult() { + return sb.toString(); + } + + @Override + public void append(@Nonnull String str) { + sb.append(str); + } + + @Override + public String getParentName(MemberInfo member) { + String parentName = null; + + if (member.parentTraits != null) { + if (member.parentTraits.name instanceof Multiname multiname && multiname.hasNamespace()) { + parentName = multiname.name; + } + if (parentName == null) { + parentName = member.parentTraits.name.toString().replaceAll("::", "."); + } + } + return parentName; + } + + public void addMetaDataValue(String s, String s1) { + append(firstMetaDataMember ? "(" : ","); + firstMetaDataMember = false; + if (s != null) { + append(s); + append("="); + } + append(s1); + } + + @Override + public void processVariable(SlotInfo info, String indent, String attr) { + appendFieldSeparator(); + + attr = appendModifiers(info, attr); + processModifierList(info, attr, indent); + append(indent + attr); + processMemberKindAndName(info); + + append(":"); + processMultinameAsPackageName(info.type, info.parentTraits.getClassName(), true); + if (info.value != null) { + processValue(info.type, info.value); + } + } + + @Override + public void processFunction(MethodInfo methodInfo, boolean referenceNameRequested, Abc abc, String indent, String attr) { + if (!referenceNameRequested) { + appendMethodSeparator(); + } + + attr = appendModifiers(methodInfo, attr); + processModifierList(methodInfo, attr, indent); + + append(indent + attr); + + processMemberKindAndName(methodInfo); + String parentName = methodInfo.getParentName(); + processArgumentList(methodInfo, parentName); + append(":"); + processMultinameAsPackageName(methodInfo.returnType, parentName, referenceNameRequested); + } + + protected void processMemberKindAndName(@Nonnull MemberInfo member) { + append(Abc.traitKinds[member.kind]); + append(" "); + + if (member.name != null) { + processMultinameAsPackageName(member.name, member.parentTraits.getClassName(), false); + } + else { + append("undefined"); + } + } + + protected abstract String appendModifiers(MemberInfo methodInfo, String attr); + + protected abstract void processValue(Multiname type, Object value); + + protected void processArgumentList(MethodInfo methodInfo, String parentName) { + append("("); + + for (int i = 0; i < methodInfo.paramTypes.length; ++i) { + Multiname paramType = methodInfo.paramTypes[i]; + boolean restParameter = FlexByteCodeInformationProcessor.REST_PARAMETER_TYPE.equals(paramType.name); + if (restParameter && !dumpRestParameter()) { + break; // original one do not dump + } + if (i > 0) { + append(","); + } + + processParameter( + methodInfo.paramNames != null ? methodInfo.paramNames[i] : "a" + (i > 0 ? "" + (i + 1) : ""), + methodInfo.paramTypes[i], + parentName, + methodInfo.optionalValues != null && i < methodInfo.optionalValues.length ? methodInfo.optionalValues[i] : null, + restParameter + ); + } + + append(")"); + } + + protected abstract boolean dumpRestParameter(); + + @Override + public void processMetadata(MetaData metaData) { + append("["); + append(metaData.name); + firstMetaDataMember = true; + + for (String n : metaData.keySet()) { + addMetaDataValue(!"*".equals(n) || doStarMetaAttrNameDump() ? n : null, '"' + metaData.get(n) + '"'); + } + + if (!firstMetaDataMember) { + append(")"); + } + append("]"); + } + + @Override + public void processClass(SlotInfo slotInfo, Abc abc, String attr, String indent) { + append("\n"); + + String def; + boolean isInterface = slotInfo.isInterfaceClass(); + if (isInterface) { + def = "interface"; + } + else { + def = "class"; + } + + if (!doStarTypeDumpInExtends()) { + String ns = slotInfo.name.hasNamespace() ? slotInfo.name.getNsName() : null; + + if (ns != null && ns.length() > 0) { + attr += ns; + } + else { + attr += "public"; + } + attr += " "; + } + + Traits ct = (Traits)slotInfo.value; + Traits it = ct.itraits; + if (!isInterface) { + if ((it.flags & Abc.CLASS_FLAG_final) != 0) { + attr += "final "; + } + if ((it.flags & Abc.CLASS_FLAG_sealed) == 0) { + attr += "dynamic "; + } + } + + processModifierList(slotInfo, attr, indent); + + append(indent + attr + def + " "); + processMultinameAsPackageName(slotInfo.name, null, true); + dumpExtendsList(it); + + append("\n"); + String oldindent = indent; + indent += Abc.TAB; + + dumpInterfacesList(indent, it, isInterface); + append(oldindent + "{\n"); + setProcessingInterface(isInterface); + + it.init.dump(abc, indent, "", this); + it.dump(abc, indent, "", this); + ct.dump(abc, indent, "static ", this); + ct.init.dump(abc, indent, "static ", this); + append(oldindent + "}\n"); + setProcessingInterface(false); + } + + protected void processModifierList(MemberInfo memberInfo, String attr, String indent) { + memberInfo.dumpMetaData(indent, this); + } + + protected void dumpExtendsList(Traits it) { + if (!it.base.isStarReference() || doStarTypeDumpInExtends()) { + append(" extends "); + processMultinameAsPackageName(it.base, null, true); + } + } + + protected void dumpInterfacesList(String indent, Traits it, boolean anInterface) { + if (it.interfaces.length > 0) { + append(indent + (anInterface && this instanceof AS3InterfaceDumper ? "extends " : "implements ")); + boolean first = true; + + for (Multiname name : it.interfaces) { + if (!first) { + append(","); + } + first = false; + processMultinameAsPackageName(name, null, true); + } + append("\n"); + } + } + + protected static String quote(String s) { + if (s.length() == 0) { + return s; + } + StringBuilder b = new StringBuilder(s.length()); + + for (int i = 0; i < s.length(); ++i) { + char ch = s.charAt(i); + + if (ch == '\\' || ch == '"') { + b.append('\\'); + } + else if (ch == '\n') { + b.append("\\n"); + continue; + } + else if (ch == '\r') { + b.append("\\r"); + continue; + } + b.append(ch); + } + return b.toString(); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/ByteBuffer.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/ByteBuffer.java index 888d0417..2a250b8e 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/ByteBuffer.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/ByteBuffer.java @@ -22,208 +22,172 @@ import java.io.UnsupportedEncodingException; import java.util.zip.InflaterInputStream; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author Maxim.Mossienko - * Date: Oct 20, 2008 - * Time: 7:02:53 PM + * @since 2008-10-20 */ -class ByteBuffer -{ - private byte[] bytes; - private int position; - private boolean littleEndian; - - void read(@Nonnull InputStream inputStream) throws IOException - { - try - { - bytes = readStream(inputStream); - } - finally - { - if(inputStream != null) - { - inputStream.close(); - } - } - } - - void setLittleEndian() - { - littleEndian = true; - } - - int readInt() - { - int result; - if(littleEndian) - { - result = (((bytes[position + 3] & 0xFF) << 8 | (bytes[position + 2] & 0xFF)) << 16) + ((bytes[position + 1] & 0xFF) << 8) | (bytes[position] & - 0xFF); - } - else - { - result = (((bytes[position] & 0xFF) << 8 | (bytes[position + 1] & 0xFF)) << 16) + ((bytes[position + 2] & 0xFF) << 8) | (bytes[position + 3] & - 0xFF); - } - position += 4; - return result; - } - - public int readUnsignedInt() - { - return readInt(); - } - - public void setPosition(final int i) - { - position = i; - } - - public int bytesSize() - { - return bytes.length; - } - - public void uncompress() throws IOException - { - final InflaterInputStream zipInputStream = new InflaterInputStream(new ByteArrayInputStream(bytes)); - - bytes = readStream(zipInputStream); - - zipInputStream.close(); - } - - private static byte[] readStream(final InputStream zipInputStream) throws IOException - { - final byte[] buf = new byte[8192]; - byte[] result = new byte[8192]; - int total = 0; - - while(true) - { - int read = zipInputStream.read(buf); - if(read == -1) - { - break; - } - if(total + read >= result.length) - { - byte[] newresult = new byte[result.length * 2]; - System.arraycopy(result, 0, newresult, 0, total); - result = newresult; - } - - System.arraycopy(buf, 0, result, total, read); - total += read; - } - - final byte[] realResult = new byte[total]; - System.arraycopy(result, 0, realResult, 0, total); - return realResult; - } - - public int readUnsignedByte() - { - return bytes[position++] & 0xFF; - } - - public int readByte() - { - return bytes[position++]; - } - - public int readUnsignedShort() - { - int result; - if(littleEndian) - { - result = (bytes[position + 1] & 0xFF) << 8 | (bytes[position] & 0xFF); - } - else - { - result = (bytes[position] & 0xFF) << 8 | (bytes[position + 1] & 0xFF); - } - position += 2; - return result; - } - - public void readBytes(ByteBuffer data2, int length) - { - data2.bytes = new byte[length]; - System.arraycopy(bytes, position, data2.bytes, 0, length); - position += length; - } - - public boolean eof() - { - return position >= bytes.length; - } - - public String readUTFBytes(int i) - { - try - { - final byte[] buf = new byte[i]; - while(i > 0) - { - buf[buf.length - i] = (byte) readByte(); - --i; - } - return new String(buf, "utf-8"); - } - catch(UnsupportedEncodingException e) - { - throw new RuntimeException(e); - } - } - - public double readDouble() - { - int first = readInt(); - int second = readInt(); - return Double.longBitsToDouble(((long) second << 32) | first); - } - - public int readU32() - { - int result = readUnsignedByte(); - if((result & 0x00000080) == 0) - { - return result; - } - result = result & 0x0000007f | readUnsignedByte() << 7; - if((result & 0x00004000) == 0) - { - return result; - } - result = result & 0x00003fff | readUnsignedByte() << 14; - if((result & 0x00200000) == 0) - { - return result; - } - result = result & 0x001fffff | readUnsignedByte() << 21; - if((result & 0x10000000) == 0) - { - return result; - } - return result & 0x0fffffff | readUnsignedByte() << 28; - } - - public byte getByte(int i) - { - return bytes[i]; - } - - public int getPosition() - { - return position; - } - - public void incPosition(final int length) - { - position += length; - } +class ByteBuffer { + private byte[] bytes; + private int position; + private boolean littleEndian; + + void read(@Nonnull InputStream inputStream) throws IOException { + try { + bytes = readStream(inputStream); + } + finally { + if (inputStream != null) { + inputStream.close(); + } + } + } + + void setLittleEndian() { + littleEndian = true; + } + + int readInt() { + int result; + if (littleEndian) { + result = + (((bytes[position + 3] & 0xFF) << 8 | (bytes[position + 2] & 0xFF)) << 16) + ((bytes[position + 1] & 0xFF) << 8) | (bytes[position] & + 0xFF); + } + else { + result = + (((bytes[position] & 0xFF) << 8 | (bytes[position + 1] & 0xFF)) << 16) + ((bytes[position + 2] & 0xFF) << 8) | (bytes[position + 3] & + 0xFF); + } + position += 4; + return result; + } + + public int readUnsignedInt() { + return readInt(); + } + + public void setPosition(int i) { + position = i; + } + + public int bytesSize() { + return bytes.length; + } + + public void uncompress() throws IOException { + InflaterInputStream zipInputStream = new InflaterInputStream(new ByteArrayInputStream(bytes)); + + bytes = readStream(zipInputStream); + + zipInputStream.close(); + } + + private static byte[] readStream(InputStream zipInputStream) throws IOException { + byte[] buf = new byte[8192]; + byte[] result = new byte[8192]; + int total = 0; + + while (true) { + int read = zipInputStream.read(buf); + if (read == -1) { + break; + } + if (total + read >= result.length) { + byte[] newresult = new byte[result.length * 2]; + System.arraycopy(result, 0, newresult, 0, total); + result = newresult; + } + + System.arraycopy(buf, 0, result, total, read); + total += read; + } + + byte[] realResult = new byte[total]; + System.arraycopy(result, 0, realResult, 0, total); + return realResult; + } + + public int readUnsignedByte() { + return bytes[position++] & 0xFF; + } + + public int readByte() { + return bytes[position++]; + } + + public int readUnsignedShort() { + int result; + if (littleEndian) { + result = (bytes[position + 1] & 0xFF) << 8 | (bytes[position] & 0xFF); + } + else { + result = (bytes[position] & 0xFF) << 8 | (bytes[position + 1] & 0xFF); + } + position += 2; + return result; + } + + public void readBytes(ByteBuffer data2, int length) { + data2.bytes = new byte[length]; + System.arraycopy(bytes, position, data2.bytes, 0, length); + position += length; + } + + public boolean eof() { + return position >= bytes.length; + } + + public String readUTFBytes(int i) { + try { + byte[] buf = new byte[i]; + while (i > 0) { + buf[buf.length - i] = (byte)readByte(); + --i; + } + return new String(buf, "utf-8"); + } + catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + public double readDouble() { + int first = readInt(); + int second = readInt(); + return Double.longBitsToDouble(((long)second << 32) | first); + } + + public int readU32() { + int result = readUnsignedByte(); + if ((result & 0x00000080) == 0) { + return result; + } + result = result & 0x0000007f | readUnsignedByte() << 7; + if ((result & 0x00004000) == 0) { + return result; + } + result = result & 0x00003fff | readUnsignedByte() << 14; + if ((result & 0x00200000) == 0) { + return result; + } + result = result & 0x001fffff | readUnsignedByte() << 21; + if ((result & 0x10000000) == 0) { + return result; + } + return result & 0x0fffffff | readUnsignedByte() << 28; + } + + public byte getByte(int i) { + return bytes[i]; + } + + public int getPosition() { + return position; + } + + public void incPosition(int length) { + position += length; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/FlexByteCodeInformationProcessor.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/FlexByteCodeInformationProcessor.java index 0e768417..247e7cef 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/FlexByteCodeInformationProcessor.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/FlexByteCodeInformationProcessor.java @@ -16,56 +16,53 @@ package com.intellij.lang.javascript.impl.flex.importer; -import org.jetbrains.annotations.NonNls; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author Maxim.Mossienko - * Date: Oct 20, 2008 - * Time: 7:02:07 PM + * @since 2008-10-20 */ -interface FlexByteCodeInformationProcessor -{ - void dumpStat(@Nonnull @NonNls String stat); +interface FlexByteCodeInformationProcessor { + void dumpStat(@Nonnull String stat); - void hasError(@Nonnull String error); + void hasError(@Nonnull String error); - void append(@Nonnull @NonNls String str); + void append(@Nonnull String str); - void processMultinameAsPackageName(@Nonnull Multiname name, @Nullable String parentName, boolean referenceNameRequested); + void processMultinameAsPackageName(@Nonnull Multiname name, @Nullable String parentName, boolean referenceNameRequested); - void dumpToplevelAnonymousMethod(final @Nonnull Abc abc, final @Nonnull MethodInfo m); + void dumpToplevelAnonymousMethod(@Nonnull Abc abc, @Nonnull MethodInfo m); - void dumpTopLevelTraits(final @Nonnull Abc abc, final @Nonnull Traits t, final String indent); + void dumpTopLevelTraits(@Nonnull Abc abc, @Nonnull Traits t, String indent); - boolean doDumpMember(final @Nonnull MemberInfo memberInfo); + boolean doDumpMember(@Nonnull MemberInfo memberInfo); - void appendMethodSeparator(); + void appendMethodSeparator(); - void appendFieldSeparator(); + void appendFieldSeparator(); - String getAbcInSwfIndent(); + String getAbcInSwfIndent(); - boolean doDumpMetaData(final @Nonnull MetaData md); + boolean doDumpMetaData(@Nonnull MetaData md); - String REST_PARAMETER_TYPE = "..."; + String REST_PARAMETER_TYPE = "..."; - void processParameter(final @Nonnull String name, @Nullable Multiname type, String parentName, @Nullable Multiname value, boolean rest); + void processParameter(@Nonnull String name, @Nullable Multiname type, String parentName, @Nullable Multiname value, boolean rest); - boolean doStarTypeDumpInExtends(); + boolean doStarTypeDumpInExtends(); - boolean doStarMetaAttrNameDump(); + boolean doStarMetaAttrNameDump(); - void setProcessingInterface(final boolean anInterface); + void setProcessingInterface(boolean anInterface); - String getParentName(final MemberInfo member); + String getParentName(MemberInfo member); - void processVariable(SlotInfo info, String indent, String attr); + void processVariable(SlotInfo info, String indent, String attr); - void processFunction(MethodInfo methodInfo, boolean referenceNameRequested, Abc abc, String indent, String attr); + void processFunction(MethodInfo methodInfo, boolean referenceNameRequested, Abc abc, String indent, String attr); - void processMetadata(MetaData metaData); + void processMetadata(MetaData metaData); - void processClass(SlotInfo slotInfo, Abc abc, String attr, String indent); + void processClass(SlotInfo slotInfo, Abc abc, String attr, String indent); } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/FlexImporter.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/FlexImporter.java index b9e9a12a..be190018 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/FlexImporter.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/FlexImporter.java @@ -16,141 +16,113 @@ package com.intellij.lang.javascript.impl.flex.importer; -import java.io.BufferedInputStream; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; - -import javax.annotation.Nonnull; - import consulo.language.psi.stub.StubElement; -import org.jetbrains.annotations.NonNls; +import jakarta.annotation.Nonnull; + +import java.io.*; /** * Produced from abcdump.as */ -public class FlexImporter -{ - public static void main(String[] args) throws IOException - { - if(args.length < 1) - { - System.out.print("FlexImporter\nusage:\nFlexImporter "); - } - else - { - long started = System.currentTimeMillis(); - - for(String file : args) - { - try - { - String result = dumpContentsFromStream(new BufferedInputStream(new FileInputStream(file)), true); +public class FlexImporter { + public static void main(String[] args) throws IOException { + if (args.length < 1) { + System.out.print("FlexImporter\nusage:\nFlexImporter "); + } + else { + long started = System.currentTimeMillis(); - saveStringAsFile(result, file + ".il"); - } - finally - { - long total = System.currentTimeMillis() - started; - System.out.println("File created... " + total + "ms"); - } - } - } - } + for (String file : args) { + try { + String result = dumpContentsFromStream(new BufferedInputStream(new FileInputStream(file)), true); - private static void saveStringAsFile(final String result, final String fileName) throws IOException - { - final FileOutputStream fileOutputStream = new FileOutputStream(fileName); - try - { - fileOutputStream.write(result.getBytes()); - } - finally - { - fileOutputStream.close(); - } - } + saveStringAsFile(result, file + ".il"); + } + finally { + long total = System.currentTimeMillis() - started; + System.out.println("File created... " + total + "ms"); + } + } + } + } - public static String dumpContentsFromStream(final InputStream in, boolean _dumpCode) throws IOException - { - final AbstractDumpProcessor abcDumper = new AbcDumper(_dumpCode); - processFlexByteCode(in, abcDumper); - return abcDumper.getResult(); - } + private static void saveStringAsFile(String result, String fileName) throws IOException { + try (FileOutputStream fileOutputStream = new FileOutputStream(fileName)) { + fileOutputStream.write(result.getBytes()); + } + } - @NonNls - public static String buildInterfaceFromStream(final InputStream in) - { - try - { - final AbstractDumpProcessor abcDumper = new AS3InterfaceDumper(); - processFlexByteCode(in, abcDumper); - final String s = abcDumper.getResult(); - //saveStringAsFile(s, File.createTempFile("fleximport", ".as").getPath()); - return s; - } - catch(IOException ex) - { - return "/* " + ex.getLocalizedMessage() + " */"; - } - catch(ArrayIndexOutOfBoundsException ex) - { - return "/* Invalid format */"; - } - } + public static String dumpContentsFromStream(InputStream in, boolean _dumpCode) throws IOException { + AbstractDumpProcessor abcDumper = new AbcDumper(_dumpCode); + processFlexByteCode(in, abcDumper); + return abcDumper.getResult(); + } - @NonNls - public static void buildStubsInterfaceFromStream(final InputStream in, final StubElement parent) throws Exception - { - processFlexByteCode(in, new AS3InterfaceStubDumper(parent)); - } + public static String buildInterfaceFromStream(InputStream in) { + try { + AbstractDumpProcessor abcDumper = new AS3InterfaceDumper(); + processFlexByteCode(in, abcDumper); + String s = abcDumper.getResult(); + //saveStringAsFile(s, File.createTempFile("fleximport", ".as").getPath()); + return s; + } + catch (IOException ex) { + return "/* " + ex.getLocalizedMessage() + " */"; + } + catch (ArrayIndexOutOfBoundsException ex) { + return "/* Invalid format */"; + } + } - private static void processFlexByteCode(@Nonnull final InputStream in, @Nonnull FlexByteCodeInformationProcessor processor) throws IOException - { - ByteBuffer data = new ByteBuffer(); - data.read(in); - data.setLittleEndian(); - int version = data.readUnsignedInt(); + public static void buildStubsInterfaceFromStream(InputStream in, StubElement parent) throws Exception { + processFlexByteCode(in, new AS3InterfaceStubDumper(parent)); + } - switch(version) - { - case 46 << 16 | 14: - case 46 << 16 | 15: - case 46 << 16 | 16: - Abc abc = new Abc(data, processor); - abc.dump(""); - break; - case 67 | 87 << 8 | 83 << 16 | 10 << 24: // needed for airglobal.swc - case 67 | 87 << 8 | 83 << 16 | 9 << 24: // SWC9 - case 67 | 87 << 8 | 83 << 16 | 8 << 24: // SWC8 - case 67 | 87 << 8 | 83 << 16 | 7 << 24: // SWC7 - case 67 | 87 << 8 | 83 << 16 | 6 << 24: // SWC6 - final int delta = 8; - data.setPosition(delta); - ByteBuffer udata = new ByteBuffer(); - udata.setLittleEndian(); - data.readBytes(udata, data.bytesSize() - delta); - int csize = udata.bytesSize(); - udata.uncompress(); - processor.dumpStat("decompressed swf " + csize + " -> " + udata.bytesSize() + "\n"); - udata.setPosition(0); - new Swf(udata, processor); - break; - case 70 | 87 << 8 | 83 << 16 | 9 << 24: // SWC9 - case 70 | 87 << 8 | 83 << 16 | 8 << 24: // SWC8 - case 70 | 87 << 8 | 83 << 16 | 7 << 24: // SWC7 - case 70 | 87 << 8 | 83 << 16 | 6 << 24: // SWC6 - case 70 | 87 << 8 | 83 << 16 | 5 << 24: // SWC5 - case 70 | 87 << 8 | 83 << 16 | 4 << 24: // SWC4 - data.setPosition(8); // skip header and length - new Swf(data, processor); - break; - default: - processor.hasError("unknown format " + version + "\n"); - break; - } - in.close(); - } + private static void processFlexByteCode( + @Nonnull InputStream in, + @Nonnull FlexByteCodeInformationProcessor processor + ) throws IOException { + ByteBuffer data = new ByteBuffer(); + data.read(in); + data.setLittleEndian(); + int version = data.readUnsignedInt(); + switch (version) { + case 46 << 16 | 14: + case 46 << 16 | 15: + case 46 << 16 | 16: + Abc abc = new Abc(data, processor); + abc.dump(""); + break; + case 67 | 87 << 8 | 83 << 16 | 10 << 24: // needed for airglobal.swc + case 67 | 87 << 8 | 83 << 16 | 9 << 24: // SWC9 + case 67 | 87 << 8 | 83 << 16 | 8 << 24: // SWC8 + case 67 | 87 << 8 | 83 << 16 | 7 << 24: // SWC7 + case 67 | 87 << 8 | 83 << 16 | 6 << 24: // SWC6 + int delta = 8; + data.setPosition(delta); + ByteBuffer udata = new ByteBuffer(); + udata.setLittleEndian(); + data.readBytes(udata, data.bytesSize() - delta); + int csize = udata.bytesSize(); + udata.uncompress(); + processor.dumpStat("decompressed swf " + csize + " -> " + udata.bytesSize() + "\n"); + udata.setPosition(0); + new Swf(udata, processor); + break; + case 70 | 87 << 8 | 83 << 16 | 9 << 24: // SWC9 + case 70 | 87 << 8 | 83 << 16 | 8 << 24: // SWC8 + case 70 | 87 << 8 | 83 << 16 | 7 << 24: // SWC7 + case 70 | 87 << 8 | 83 << 16 | 6 << 24: // SWC6 + case 70 | 87 << 8 | 83 << 16 | 5 << 24: // SWC5 + case 70 | 87 << 8 | 83 << 16 | 4 << 24: // SWC4 + data.setPosition(8); // skip header and length + new Swf(data, processor); + break; + default: + processor.hasError("unknown format " + version + "\n"); + break; + } + in.close(); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/LabelInfo.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/LabelInfo.java index 06e3c7fb..769a0609 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/LabelInfo.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/LabelInfo.java @@ -20,21 +20,17 @@ /** * @author Maxim.Mossienko - * Date: Oct 20, 2008 - * Time: 7:00:45 PM + * @since 2008-10-20 */ -class LabelInfo extends LinkedHashMap -{ - int count; +class LabelInfo extends LinkedHashMap { + int count; - String labelFor(int target) - { - if(containsKey(target)) - { - return get(target); - } - final String s = "L" + (++count); - put(target, s); - return s; - } + String labelFor(int target) { + if (containsKey(target)) { + return get(target); + } + String s = "L" + (++count); + put(target, s); + return s; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/MemberInfo.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/MemberInfo.java index c9763a86..12b910a3 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/MemberInfo.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/MemberInfo.java @@ -16,44 +16,37 @@ package com.intellij.lang.javascript.impl.flex.importer; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author Maxim.Mossienko - * Date: Oct 20, 2008 - * Time: 7:00:39 PM + * @since 2008-10-20 */ -abstract class MemberInfo -{ - Traits parentTraits; - int id; - int kind; - Multiname name; - MetaData[] metadata; - boolean isOverride; - boolean isPublic; - boolean isFinal; +abstract class MemberInfo { + Traits parentTraits; + int id; + int kind; + Multiname name; + MetaData[] metadata; + boolean isOverride; + boolean isPublic; + boolean isFinal; - abstract void dump(Abc abc, String indent, String attr, final @Nonnull FlexByteCodeInformationProcessor processor); + abstract void dump(Abc abc, String indent, String attr, @Nonnull FlexByteCodeInformationProcessor processor); - protected void dumpMetaData(String indent, final @Nonnull FlexByteCodeInformationProcessor processor) - { - if(metadata != null) - { - for(MetaData md : metadata) - { - if(processor.doDumpMetaData(md)) - { - processor.append(indent); - processor.processMetadata(md); - processor.append("\n"); - } - } - } - } + protected void dumpMetaData(String indent, @Nonnull FlexByteCodeInformationProcessor processor) { + if (metadata != null) { + for (MetaData md : metadata) { + if (processor.doDumpMetaData(md)) { + processor.append(indent); + processor.processMetadata(md); + processor.append("\n"); + } + } + } + } - String getParentName() - { - return parentTraits != null ? parentTraits.getClassName() : null; - } + String getParentName() { + return parentTraits != null ? parentTraits.getClassName() : null; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/MetaData.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/MetaData.java index 13edac7a..9daf422e 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/MetaData.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/MetaData.java @@ -20,10 +20,8 @@ /** * @author Maxim.Mossienko - * Date: Oct 20, 2008 - * Time: 7:00:50 PM + * @since 2008-10-20 */ -class MetaData extends LinkedHashMap -{ - String name; +class MetaData extends LinkedHashMap { + String name; } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/MethodInfo.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/MethodInfo.java index cfe00ebb..ec270bd3 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/MethodInfo.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/MethodInfo.java @@ -20,250 +20,233 @@ /** * @author Maxim.Mossienko - * Date: Oct 20, 2008 - * Time: 7:00:56 PM + * @since 2008-10-20 */ -class MethodInfo extends MemberInfo -{ - int flags; - String debugName; - Multiname paramTypes[]; - String paramNames[]; - Multiname optionalValues[]; - Multiname returnType; - int local_count; - int max_scope; - int max_stack; - int code_length; - ByteBuffer code; - Traits activation; - boolean anon; - - @Override - void dump(Abc abc, String indent, String attr, final FlexByteCodeInformationProcessor processor) - { - if(!processor.doDumpMember(this)) - { - return; - } - - processor.processFunction(this, false, abc, indent, attr); - } - - protected void dumpCode(Abc abc, String indent, FlexByteCodeInformationProcessor processor) - { - processor.append(indent + "{\n"); - String oldindent = indent; - indent += TAB; - - if((flags & NEED_ACTIVATION) != 0) - { - processor.append(indent + "activation {\n"); - activation.dump(abc, indent + TAB, "", processor); - processor.append(indent + "}\n"); - } - processor.append(indent + - "// local_count=" + - local_count + - " max_scope=" + - max_scope + - " max_stack=" + - max_stack + - " code_len=" + - code.bytesSize() + - "\n"); - code.setPosition(0); - LabelInfo labels = new LabelInfo(); - - while(!code.eof()) - { - int start = code.getPosition(); - int opcode = code.readUnsignedByte(); - - if(opcode == OP_label || (labels.containsKey(start))) - { - processor.append(indent + "\n"); - processor.append(indent + labels.labelFor(start) + ": \n"); - } - - String str = indent + start; - processor.append(str); - for(int i = str.length(); i < 12; ++i) - { - processor.append(" "); - } - - processor.append(opNames[opcode]); - processor.append(opNames[opcode].length() < 8 ? "\t\t" : "\t"); - - switch(opcode) - { - case OP_debugfile: - case OP_pushstring: - processor.append('"' + abc.strings[readU32()].replaceAll("/\n/g", "\\n").replaceAll("/\t/g", "\\t") + '"'); - break; - case OP_pushnamespace: - processor.append(abc.namespaces[readU32()]); - break; - case OP_pushint: - int i = abc.ints[readU32()]; - processor.append(i + "\t// 0x" + Integer.toString(i, 16)); - break; - case OP_pushuint: - int u = abc.uints[readU32()]; - processor.append(u + "\t// 0x" + Integer.toString(u, 16)); - break; - case OP_pushdouble: - processor.append(abc.doubles[readU32()].toString()); - break; - case OP_getsuper: - case OP_setsuper: - case OP_getproperty: - case OP_initproperty: - case OP_setproperty: - case OP_getlex: - case OP_findpropstrict: - case OP_findproperty: - case OP_finddef: - case OP_deleteproperty: - case OP_istype: - case OP_coerce: - case OP_astype: - case OP_getdescendants: - processor.append(abc.names[readU32()].toString()); - break; - case OP_constructprop: - case OP_callproperty: - case OP_callproplex: - case OP_callsuper: - case OP_callsupervoid: - case OP_callpropvoid: - processor.append(abc.names[readU32()].toString()); - processor.append(" (" + readU32() + ")"); - break; - case OP_newfunction: - { - int method_id = readU32(); - processor.processFunction(abc.methods[method_id], true, abc, "", ""); - abc.methods[method_id].anon = true; - break; - } - case OP_callstatic: - processor.processFunction(abc.methods[readU32()], true, abc, "", ""); - processor.append(" (" + readU32() + ")"); - break; - case OP_newclass: - processor.append(abc.instances[readU32()].toString()); - break; - case OP_lookupswitch: - int pos = start; - int target = pos + readS24(); - int maxindex = readU32(); - processor.append("default:" + labels.labelFor(target)); // target + "("+(target-pos)+")" - processor.append(" maxcase:" + maxindex); - for(i = 0; i <= maxindex; i++) - { - target = pos + readS24(); - processor.append(" " + labels.labelFor(target)); // target + "("+(target-pos)+")" - } - break; - case OP_jump: - case OP_iftrue: - case OP_iffalse: - case OP_ifeq: - case OP_ifne: - case OP_ifge: - case OP_ifnge: - case OP_ifgt: - case OP_ifngt: - case OP_ifle: - case OP_ifnle: - case OP_iflt: - case OP_ifnlt: - case OP_ifstricteq: - case OP_ifstrictne: - int offset = readS24(); - target = code.getPosition() + offset; - //s += target + " ("+offset+")" - processor.append(labels.labelFor(target)); - if(!(labels.containsKey(code.getPosition()))) - { - processor.append("\n"); - } - break; - case OP_inclocal: - case OP_declocal: - case OP_inclocal_i: - case OP_declocal_i: - case OP_getlocal: - case OP_kill: - case OP_setlocal: - case OP_debugline: - case OP_getglobalslot: - case OP_getslot: - case OP_setglobalslot: - case OP_setslot: - case OP_pushshort: - case OP_newcatch: - processor.append("" + readU32()); - break; - case OP_debug: - processor.append("" + code.readUnsignedByte()); - processor.append(" " + readU32()); - processor.append(" " + code.readUnsignedByte()); - processor.append(" " + readU32()); - break; - case OP_newobject: - processor.append("{" + readU32() + "}"); - break; - case OP_newarray: - processor.append("[" + readU32() + "]"); - break; - case OP_call: - case OP_construct: - case OP_constructsuper: - processor.append("(" + readU32() + ")"); - break; - case OP_pushbyte: - case OP_getscopeobject: - processor.append("" + code.readByte()); - break; - case OP_hasnext2: - processor.append(readU32() + " " + readU32()); - default: - /*if (opNames[opcode] == ("0x"+opcode.toString(16).toUpperCase())) +class MethodInfo extends MemberInfo { + int flags; + String debugName; + Multiname paramTypes[]; + String paramNames[]; + Multiname optionalValues[]; + Multiname returnType; + int local_count; + int max_scope; + int max_stack; + int code_length; + ByteBuffer code; + Traits activation; + boolean anon; + + @Override + void dump(Abc abc, String indent, String attr, FlexByteCodeInformationProcessor processor) { + if (!processor.doDumpMember(this)) { + return; + } + + processor.processFunction(this, false, abc, indent, attr); + } + + protected void dumpCode(Abc abc, String indent, FlexByteCodeInformationProcessor processor) { + processor.append(indent + "{\n"); + String oldindent = indent; + indent += TAB; + + if ((flags & NEED_ACTIVATION) != 0) { + processor.append(indent + "activation {\n"); + activation.dump(abc, indent + TAB, "", processor); + processor.append(indent + "}\n"); + } + processor.append(indent + + "// local_count=" + + local_count + + " max_scope=" + + max_scope + + " max_stack=" + + max_stack + + " code_len=" + + code.bytesSize() + + "\n"); + code.setPosition(0); + LabelInfo labels = new LabelInfo(); + + while (!code.eof()) { + int start = code.getPosition(); + int opcode = code.readUnsignedByte(); + + if (opcode == OP_label || (labels.containsKey(start))) { + processor.append(indent + "\n"); + processor.append(indent + labels.labelFor(start) + ": \n"); + } + + String str = indent + start; + processor.append(str); + for (int i = str.length(); i < 12; ++i) { + processor.append(" "); + } + + processor.append(opNames[opcode]); + processor.append(opNames[opcode].length() < 8 ? "\t\t" : "\t"); + + switch (opcode) { + case OP_debugfile: + case OP_pushstring: + processor.append('"' + abc.strings[readU32()].replaceAll("/\n/g", "\\n").replaceAll("/\t/g", "\\t") + '"'); + break; + case OP_pushnamespace: + processor.append(abc.namespaces[readU32()]); + break; + case OP_pushint: + int i = abc.ints[readU32()]; + processor.append(i + "\t// 0x" + Integer.toString(i, 16)); + break; + case OP_pushuint: + int u = abc.uints[readU32()]; + processor.append(u + "\t// 0x" + Integer.toString(u, 16)); + break; + case OP_pushdouble: + processor.append(abc.doubles[readU32()].toString()); + break; + case OP_getsuper: + case OP_setsuper: + case OP_getproperty: + case OP_initproperty: + case OP_setproperty: + case OP_getlex: + case OP_findpropstrict: + case OP_findproperty: + case OP_finddef: + case OP_deleteproperty: + case OP_istype: + case OP_coerce: + case OP_astype: + case OP_getdescendants: + processor.append(abc.names[readU32()].toString()); + break; + case OP_constructprop: + case OP_callproperty: + case OP_callproplex: + case OP_callsuper: + case OP_callsupervoid: + case OP_callpropvoid: + processor.append(abc.names[readU32()].toString()); + processor.append(" (" + readU32() + ")"); + break; + case OP_newfunction: { + int method_id = readU32(); + processor.processFunction(abc.methods[method_id], true, abc, "", ""); + abc.methods[method_id].anon = true; + break; + } + case OP_callstatic: + processor.processFunction(abc.methods[readU32()], true, abc, "", ""); + processor.append(" (" + readU32() + ")"); + break; + case OP_newclass: + processor.append(abc.instances[readU32()].toString()); + break; + case OP_lookupswitch: + int pos = start; + int target = pos + readS24(); + int maxindex = readU32(); + processor.append("default:" + labels.labelFor(target)); // target + "("+(target-pos)+")" + processor.append(" maxcase:" + maxindex); + for (i = 0; i <= maxindex; i++) { + target = pos + readS24(); + processor.append(" " + labels.labelFor(target)); // target + "("+(target-pos)+")" + } + break; + case OP_jump: + case OP_iftrue: + case OP_iffalse: + case OP_ifeq: + case OP_ifne: + case OP_ifge: + case OP_ifnge: + case OP_ifgt: + case OP_ifngt: + case OP_ifle: + case OP_ifnle: + case OP_iflt: + case OP_ifnlt: + case OP_ifstricteq: + case OP_ifstrictne: + int offset = readS24(); + target = code.getPosition() + offset; + //s += target + " ("+offset+")" + processor.append(labels.labelFor(target)); + if (!(labels.containsKey(code.getPosition()))) { + processor.append("\n"); + } + break; + case OP_inclocal: + case OP_declocal: + case OP_inclocal_i: + case OP_declocal_i: + case OP_getlocal: + case OP_kill: + case OP_setlocal: + case OP_debugline: + case OP_getglobalslot: + case OP_getslot: + case OP_setglobalslot: + case OP_setslot: + case OP_pushshort: + case OP_newcatch: + processor.append("" + readU32()); + break; + case OP_debug: + processor.append("" + code.readUnsignedByte()); + processor.append(" " + readU32()); + processor.append(" " + code.readUnsignedByte()); + processor.append(" " + readU32()); + break; + case OP_newobject: + processor.append("{" + readU32() + "}"); + break; + case OP_newarray: + processor.append("[" + readU32() + "]"); + break; + case OP_call: + case OP_construct: + case OP_constructsuper: + processor.append("(" + readU32() + ")"); + break; + case OP_pushbyte: + case OP_getscopeobject: + processor.append("" + code.readByte()); + break; + case OP_hasnext2: + processor.append(readU32() + " " + readU32()); + default: + /*if (opNames[opcode] == ("0x"+opcode.toString(16).toUpperCase())) s += " UNKNOWN OPCODE"*/ - break; - } - - int size = code.getPosition() - start; - abc.totalSize += size; - abc.opSizes[opcode] += size; - processor.append("\n"); - } - processor.append(oldindent + "}\n"); - } - - int readU32() - { - return code.readU32(); - } - - int readS24() - { - int b = code.readUnsignedByte(); - b |= code.readUnsignedByte() << 8; - b |= code.readByte() << 16; - return b; - } - - boolean isGetMethod() - { - return traitKinds[kind].indexOf(" get") != -1; - } - - boolean isSetMethod() - { - return traitKinds[kind].indexOf(" set") != -1; - } + break; + } + + int size = code.getPosition() - start; + abc.totalSize += size; + abc.opSizes[opcode] += size; + processor.append("\n"); + } + processor.append(oldindent + "}\n"); + } + + int readU32() { + return code.readU32(); + } + + int readS24() { + int b = code.readUnsignedByte(); + b |= code.readUnsignedByte() << 8; + b |= code.readByte() << 16; + return b; + } + + boolean isGetMethod() { + return traitKinds[kind].contains(" get"); + } + + boolean isSetMethod() { + return traitKinds[kind].contains(" set"); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/Multiname.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/Multiname.java index ce9577d1..8f5b4a5e 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/Multiname.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/Multiname.java @@ -18,75 +18,64 @@ /** * @author Maxim.Mossienko - * Date: Oct 20, 2008 - * Time: 7:03:18 PM + * @since 2008-10-20 */ -class Multiname -{ - String[] nsset; - String name; +class Multiname { + String[] nsset; + String name; - Multiname(String[] nsset, String name) - { - this.nsset = nsset; - this.name = name; - } + Multiname(String[] nsset, String name) { + this.nsset = nsset; + this.name = name; + } - @Override - public String toString() - { - String s = ""; - if(hasNotEmptyNs()) - { - s += nsset[0] + "::"; - } - s += name; + @Override + public String toString() { + String s = ""; + if (hasNotEmptyNs()) { + s += nsset[0] + "::"; + } + s += name; - return s; - } + return s; + } - boolean hasNotEmptyNs() - { - return nsset != null && nsset.length > 0 && nsset[0] != null && nsset[0].length() > 0; - } + boolean hasNotEmptyNs() { + return nsset != null && nsset.length > 0 && nsset[0] != null && nsset[0].length() > 0; + } - public boolean hasNamespace() - { - return hasNotEmptyNs() && (nsset[0].startsWith("http://") || nsset[0].equals("private") || nsset[0].equals("__AS3__.vec") || - nsset[0].indexOf('$') != -1 || nsset[0].indexOf("/private:") != -1); - } + public boolean hasNamespace() { + return hasNotEmptyNs() && (nsset[0].startsWith("http://") || nsset[0].equals("private") || nsset[0].equals("__AS3__.vec") || + nsset[0].indexOf('$') != -1 || nsset[0].contains("/private:")); + } - public String getNsName() - { - // TODO: would be nice to pickup namespace var names automatically - return nsset[0].equals("http://adobe.com/AS3/2006/builtin") ? "AS3" : nsset[0].equals("http://www.adobe.com/2006/flex/mx/internal") ? - "mx_internal" : nsset[0].equals("__AS3__.vec") ? "__AS3__$vec" : nsset[0].equals("http://www.adobe.com/2008/actionscript/Flash10/") ? "flash10" - : nsset[0].equals("http://www.adobe.com/2006/actionscript/flash/objectproxy") ? "object_proxy" : nsset[0].equals("http://www.adobe" + - ".com/2006/actionscript/flash/proxy") ? "flash_proxy" : getValidNsName(); - } + public String getNsName() { + // TODO: would be nice to pickup namespace var names automatically + return nsset[0].equals("http://adobe.com/AS3/2006/builtin") ? "AS3" : nsset[0].equals("http://www.adobe.com/2006/flex/mx/internal") ? + "mx_internal" : nsset[0].equals("__AS3__.vec") ? "__AS3__$vec" : nsset[0].equals( + "http://www.adobe.com/2008/actionscript/Flash10/") ? "flash10" + : nsset[0].equals("http://www.adobe.com/2006/actionscript/flash/objectproxy") ? "object_proxy" : nsset[0].equals( + "http://www.adobe" + + ".com/2006/actionscript/flash/proxy") ? "flash_proxy" : getValidNsName(); + } - public String getValidNsName() - { - return makeIdentifier(nsset[0]); - } + public String getValidNsName() { + return makeIdentifier(nsset[0]); + } - private static String makeIdentifier(String s) - { - StringBuilder builder = new StringBuilder(s.length()); - for(int i = 0; i < s.length(); ++i) - { - char ch = s.charAt(i); - if(!Character.isJavaIdentifierPart(ch)) - { - ch = '_'; - } - builder.append(ch); - } - return builder.toString(); - } + private static String makeIdentifier(String s) { + StringBuilder builder = new StringBuilder(s.length()); + for (int i = 0; i < s.length(); ++i) { + char ch = s.charAt(i); + if (!Character.isJavaIdentifierPart(ch)) { + ch = '_'; + } + builder.append(ch); + } + return builder.toString(); + } - public boolean isStarReference() - { - return "*".equals(name); - } + public boolean isStarReference() { + return "*".equals(name); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/SlotInfo.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/SlotInfo.java index b99711fa..8caea010 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/SlotInfo.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/SlotInfo.java @@ -18,42 +18,31 @@ /** * @author Maxim.Mossienko - * Date: Oct 20, 2008 - * Time: 7:01:03 PM + * @since 2008-10-20 */ -class SlotInfo extends MemberInfo -{ - Multiname type; - Object value; +class SlotInfo extends MemberInfo { + Multiname type; + Object value; - @Override - void dump(Abc abc, String indent, String attr, final FlexByteCodeInformationProcessor processor) - { - if(!processor.doDumpMember(this)) - { - return; - } + @Override + void dump(Abc abc, String indent, String attr, FlexByteCodeInformationProcessor processor) { + if (!processor.doDumpMember(this)) { + return; + } - if(kind == Abc.TRAIT_Const || kind == Abc.TRAIT_Slot) - { - processor.processVariable(this, indent, attr); - return; - } + if (kind == Abc.TRAIT_Const || kind == Abc.TRAIT_Slot) { + processor.processVariable(this, indent, attr); + return; + } - processor.processClass(this, abc, attr, indent); - } + processor.processClass(this, abc, attr, indent); + } - boolean isInterfaceClass() - { - if(!(value instanceof Traits)) - { - return false; - } - return (((Traits) value).itraits.flags & Abc.CLASS_FLAG_interface) != 0; - } + boolean isInterfaceClass() { + return value instanceof Traits traits && (traits.itraits.flags & Abc.CLASS_FLAG_interface) != 0; + } - public boolean isConst() - { - return Abc.traitKinds[kind].indexOf("const") != -1; - } + public boolean isConst() { + return Abc.traitKinds[kind].contains("const"); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/Swf.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/Swf.java index ce407aa2..477b4bca 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/Swf.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/Swf.java @@ -16,398 +16,370 @@ package com.intellij.lang.javascript.impl.flex.importer; -import org.jetbrains.annotations.NonNls; - /** * @author Maxim.Mossienko - * Date: Oct 20, 2008 - * Time: 7:01:59 PM + * @since 2008-10-20 */ -class Swf -{ - private static class Rect - { - int nBits; - int xMin, xMax; - int yMin, yMax; - - @Override - public - @NonNls - String toString() - { - return "[Rect " + xMin + " " + yMin + " " + xMax + " " + yMax + "]"; - } - } - - private FlexByteCodeInformationProcessor processor; - private int bitPos; - private int bitBuf; - - private ByteBuffer data; - - private static final int stagDoABC = 72; // embedded .abc (AVM+) bytecode - private static final int stagDoABC2 = 82; // revised ABC version with a name - - private static final - @NonNls - String[] tagNames = { - "End", - // 00 - "ShowFrame", - // 01 - "DefineShape", - // 02 - "FreeCharacter", - // 03 - "PlaceObject", - // 04 - "RemoveObject", - // 05 - "DefineBits", - // 06 - "DefineButton", - // 07 - "JPEGTables", - // 08 - "SetBackgroundColor", - // 09 - - "DefineFont", - // 10 - "DefineText", - // 11 - "DoAction", - // 12 - "DefineFontInfo", - // 13 - - "DefineSound", - // 14 - "StartSound", - // 15 - "StopSound", - // 16 - - "DefineButtonSound", - // 17 - - "SoundStreamHead", - // 18 - "SoundStreamBlock", - // 19 - - "DefineBitsLossless", - // 20 - "DefineBitsJPEG2", - // 21 - - "DefineShape2", - // 22 - "DefineButtonCxform", - // 23 - - "Protect", - // 24 - - "PathsArePostScript", - // 25 - - "PlaceObject2", - // 26 - "27 (invalid)", - // 27 - "RemoveObject2", - // 28 - - "SyncFrame", - // 29 - "30 (invalid)", - // 30 - "FreeAll", - // 31 - - "DefineShape3", - // 32 - "DefineText2", - // 33 - "DefineButton2", - // 34 - "DefineBitsJPEG3", - // 35 - "DefineBitsLossless2", - // 36 - "DefineEditText", - // 37 - - "DefineVideo", - // 38 - - "DefineSprite", - // 39 - "NameCharacter", - // 40 - "ProductInfo", - // 41 - "DefineTextFormat", - // 42 - "FrameLabel", - // 43 - "DefineBehavior", - // 44 - "SoundStreamHead2", - // 45 - "DefineMorphShape", - // 46 - "FrameTag", - // 47 - "DefineFont2", - // 48 - "GenCommand", - // 49 - "DefineCommandObj", - // 50 - "CharacterSet", - // 51 - "FontRef", - // 52 - - "DefineFunction", - // 53 - "PlaceFunction", - // 54 - - "GenTagObject", - // 55 - - "ExportAssets", - // 56 - "ImportAssets", - // 57 - - "EnableDebugger", - // 58 - - "DoInitAction", - // 59 - "DefineVideoStream", - // 60 - "VideoFrame", - // 61 - - "DefineFontInfo2", - // 62 - "DebugID", - // 63 - "EnableDebugger2", - // 64 - "ScriptLimits", - // 65 - - "SetTabIndex", - // 66 - - "DefineShape4", - // 67 - "68 (invalid)", - // 68 - - "FileAttributes", - // 69 - - "PlaceObject3", - // 70 - "ImportAssets2", - // 71 - - "DoABC", - // 72 - "DefineFontAlignZones", - // 73 - "CSMTextSettings", - // 74 - "DefineFont3", - // 75 - "SymbolClass", - // 76 - "Metadata", - // 77 - "ScalingGrid", - // 78 - "79 (invalid)", - // 79 - "80 (invalid)", - // 80 - "81 (invalid)", - // 81 - "DoABC2", - // 82 - "DefineShape4", - // 83 - "DefineMorphShape2", - // 84 - "85 (invalid)", - // 85 - "DefineSceneAndFrameLabelData", - // 86 - "DefineBinaryData", - // 87 - "DefineFontName", - // 88 - "89 (unknown) ", - // 89 - "90 (unknown) ", - // 90 - "DefineFont4", - // 91 - "(invalid)" - // end - }; - - - public Swf(final ByteBuffer _data, final FlexByteCodeInformationProcessor _processor) - { - data = _data; - processor = _processor; - - final Rect rect = decodeRect(); - final int rate = data.readUnsignedByte() << 8 | data.readUnsignedByte(); - final int count = data.readUnsignedShort(); - - processor.dumpStat("size " + rect + "\n"); - processor.dumpStat("frame rate " + rate + "\n"); - processor.dumpStat("frame count " + count + "\n"); - - decodeTags(); - } - - private void decodeTags() - { - int type, h, length; - - while(data.getPosition() < data.bytesSize()) - { - type = (h = data.readUnsignedShort()) >> 6; - - if(((length = h & 0x3F) == 0x3F)) - { - length = data.readInt(); - } - - processor.dumpStat((type < tagNames.length ? tagNames[type] : "undefined") + " " + length + "b " + ((int) 100f * length / data.bytesSize()) + - "%\n"); - - switch(type) - { - case 0: - return; - case stagDoABC2: - int pos1 = data.getPosition(); - data.readInt(); - final String abcName = readString(); - processor.dumpStat("\nabc name " + abcName + "\n"); - length -= (data.getPosition() - pos1); - // fall through - case stagDoABC: - ByteBuffer data2 = new ByteBuffer(); - data2.setLittleEndian(); - data.readBytes(data2, length); - new Abc(data2, processor).dump(processor.getAbcInSwfIndent()); - processor.append("\n"); - break; - default: - data.incPosition(length); - } - } - } - - private String readString() - { - String s = ""; - int c; - - while((c = data.readUnsignedByte()) != 0) - { - s += (char) c; - } - - return s; - } - - private void syncBits() - { - bitPos = 0; - } - - private Rect decodeRect() - - { - syncBits(); - - Rect rect = new Rect(); - - int nBits = readUBits(5); - rect.xMin = readSBits(nBits); - rect.xMax = readSBits(nBits); - rect.yMin = readSBits(nBits); - rect.yMax = readSBits(nBits); - - return rect; - } - - int readSBits(int numBits) - { - if(numBits > 32) - { - throw new Error("Number of bits > 32"); - } - - int num = readUBits(numBits); - int shift = 32 - numBits; - // sign extension - num = (num << shift) >> shift; - return num; - } - - int readUBits(int numBits) - { - if(numBits == 0) - { - return 0; - } - - int bitsLeft = numBits; - int result = 0; - - if(bitPos == 0) //no value in the buffer - read a byte - { - bitBuf = data.readUnsignedByte(); - bitPos = 8; - } - - while(true) - { - int shift = bitsLeft - bitPos; - if(shift > 0) - { - // Consume the entire buffer - result |= bitBuf << shift; - bitsLeft -= bitPos; - - // Get the next byte from the input stream - bitBuf = data.readUnsignedByte(); - bitPos = 8; - } - else - { - // Consume a portion of the buffer - result |= bitBuf >> -shift; - bitPos -= bitsLeft; - bitBuf &= 0xff >> (8 - bitPos); // mask off the consumed bits - - // if (sb.append) System.out.sb.appendln(" read"+numBits+" " + result); - return result; - } - } - } +class Swf { + private static class Rect { + int nBits; + int xMin, xMax; + int yMin, yMax; + + @Override + public String toString() { + return "[Rect " + xMin + " " + yMin + " " + xMax + " " + yMax + "]"; + } + } + + private FlexByteCodeInformationProcessor processor; + private int bitPos; + private int bitBuf; + + private ByteBuffer data; + + private static final int STAG_DO_ABC = 72; // embedded .abc (AVM+) bytecode + private static final int STAG_DO_ABC_2 = 82; // revised ABC version with a name + + private static final String[] TAG_NAMES = { + "End", + // 00 + "ShowFrame", + // 01 + "DefineShape", + // 02 + "FreeCharacter", + // 03 + "PlaceObject", + // 04 + "RemoveObject", + // 05 + "DefineBits", + // 06 + "DefineButton", + // 07 + "JPEGTables", + // 08 + "SetBackgroundColor", + // 09 + + "DefineFont", + // 10 + "DefineText", + // 11 + "DoAction", + // 12 + "DefineFontInfo", + // 13 + + "DefineSound", + // 14 + "StartSound", + // 15 + "StopSound", + // 16 + + "DefineButtonSound", + // 17 + + "SoundStreamHead", + // 18 + "SoundStreamBlock", + // 19 + + "DefineBitsLossless", + // 20 + "DefineBitsJPEG2", + // 21 + + "DefineShape2", + // 22 + "DefineButtonCxform", + // 23 + + "Protect", + // 24 + + "PathsArePostScript", + // 25 + + "PlaceObject2", + // 26 + "27 (invalid)", + // 27 + "RemoveObject2", + // 28 + + "SyncFrame", + // 29 + "30 (invalid)", + // 30 + "FreeAll", + // 31 + + "DefineShape3", + // 32 + "DefineText2", + // 33 + "DefineButton2", + // 34 + "DefineBitsJPEG3", + // 35 + "DefineBitsLossless2", + // 36 + "DefineEditText", + // 37 + + "DefineVideo", + // 38 + + "DefineSprite", + // 39 + "NameCharacter", + // 40 + "ProductInfo", + // 41 + "DefineTextFormat", + // 42 + "FrameLabel", + // 43 + "DefineBehavior", + // 44 + "SoundStreamHead2", + // 45 + "DefineMorphShape", + // 46 + "FrameTag", + // 47 + "DefineFont2", + // 48 + "GenCommand", + // 49 + "DefineCommandObj", + // 50 + "CharacterSet", + // 51 + "FontRef", + // 52 + + "DefineFunction", + // 53 + "PlaceFunction", + // 54 + + "GenTagObject", + // 55 + + "ExportAssets", + // 56 + "ImportAssets", + // 57 + + "EnableDebugger", + // 58 + + "DoInitAction", + // 59 + "DefineVideoStream", + // 60 + "VideoFrame", + // 61 + + "DefineFontInfo2", + // 62 + "DebugID", + // 63 + "EnableDebugger2", + // 64 + "ScriptLimits", + // 65 + + "SetTabIndex", + // 66 + + "DefineShape4", + // 67 + "68 (invalid)", + // 68 + + "FileAttributes", + // 69 + + "PlaceObject3", + // 70 + "ImportAssets2", + // 71 + + "DoABC", + // 72 + "DefineFontAlignZones", + // 73 + "CSMTextSettings", + // 74 + "DefineFont3", + // 75 + "SymbolClass", + // 76 + "Metadata", + // 77 + "ScalingGrid", + // 78 + "79 (invalid)", + // 79 + "80 (invalid)", + // 80 + "81 (invalid)", + // 81 + "DoABC2", + // 82 + "DefineShape4", + // 83 + "DefineMorphShape2", + // 84 + "85 (invalid)", + // 85 + "DefineSceneAndFrameLabelData", + // 86 + "DefineBinaryData", + // 87 + "DefineFontName", + // 88 + "89 (unknown) ", + // 89 + "90 (unknown) ", + // 90 + "DefineFont4", + // 91 + "(invalid)" + // end + }; + + public Swf(ByteBuffer _data, FlexByteCodeInformationProcessor _processor) { + data = _data; + processor = _processor; + + Rect rect = decodeRect(); + int rate = data.readUnsignedByte() << 8 | data.readUnsignedByte(); + int count = data.readUnsignedShort(); + + processor.dumpStat("size " + rect + "\n"); + processor.dumpStat("frame rate " + rate + "\n"); + processor.dumpStat("frame count " + count + "\n"); + + decodeTags(); + } + + private void decodeTags() { + int type, h, length; + + while (data.getPosition() < data.bytesSize()) { + type = (h = data.readUnsignedShort()) >> 6; + + if (((length = h & 0x3F) == 0x3F)) { + length = data.readInt(); + } + + processor.dumpStat((type < TAG_NAMES.length ? TAG_NAMES[type] : "undefined") + " " + length + "b " + ((int)100f * length / data.bytesSize()) + + "%\n"); + + switch (type) { + case 0: + return; + case STAG_DO_ABC_2: + int pos1 = data.getPosition(); + data.readInt(); + String abcName = readString(); + processor.dumpStat("\nabc name " + abcName + "\n"); + length -= (data.getPosition() - pos1); + // fall through + case STAG_DO_ABC: + ByteBuffer data2 = new ByteBuffer(); + data2.setLittleEndian(); + data.readBytes(data2, length); + new Abc(data2, processor).dump(processor.getAbcInSwfIndent()); + processor.append("\n"); + break; + default: + data.incPosition(length); + } + } + } + + private String readString() { + String s = ""; + int c; + + while ((c = data.readUnsignedByte()) != 0) { + s += (char)c; + } + + return s; + } + + private void syncBits() { + bitPos = 0; + } + + private Rect decodeRect() { + syncBits(); + + Rect rect = new Rect(); + + int nBits = readUBits(5); + rect.xMin = readSBits(nBits); + rect.xMax = readSBits(nBits); + rect.yMin = readSBits(nBits); + rect.yMax = readSBits(nBits); + + return rect; + } + + int readSBits(int numBits) { + if (numBits > 32) { + throw new Error("Number of bits > 32"); + } + + int num = readUBits(numBits); + int shift = 32 - numBits; + // sign extension + num = (num << shift) >> shift; + return num; + } + + int readUBits(int numBits) { + if (numBits == 0) { + return 0; + } + + int bitsLeft = numBits; + int result = 0; + + if (bitPos == 0) //no value in the buffer - read a byte + { + bitBuf = data.readUnsignedByte(); + bitPos = 8; + } + + while (true) { + int shift = bitsLeft - bitPos; + if (shift > 0) { + // Consume the entire buffer + result |= bitBuf << shift; + bitsLeft -= bitPos; + + // Get the next byte from the input stream + bitBuf = data.readUnsignedByte(); + bitPos = 8; + } + else { + // Consume a portion of the buffer + result |= bitBuf >> -shift; + bitPos -= bitsLeft; + bitBuf &= 0xff >> (8 - bitPos); // mask off the consumed bits + + // if (sb.append) System.out.sb.appendln(" read"+numBits+" " + result); + return result; + } + } + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/Traits.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/Traits.java index ca4f3dff..d399cde7 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/Traits.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/flex/importer/Traits.java @@ -21,44 +21,37 @@ /** * @author Maxim.Mossienko - * Date: Oct 20, 2008 - * Time: 7:01:09 PM + * @since 2008-10-20 */ -class Traits -{ - Object name; - MethodInfo init; - Traits itraits; - Multiname base; - int flags; - String protectedNs; - Multiname interfaces[]; - Map names = new LinkedHashMap(); - Map slots = new LinkedHashMap(); - Map methods = new LinkedHashMap(); - Map members = new LinkedHashMap(); +class Traits { + Object name; + MethodInfo init; + Traits itraits; + Multiname base; + int flags; + String protectedNs; + Multiname interfaces[]; + Map names = new LinkedHashMap<>(); + Map slots = new LinkedHashMap<>(); + Map methods = new LinkedHashMap<>(); + Map members = new LinkedHashMap<>(); - @Override - public String toString() - { - return name.toString(); - } + @Override + public String toString() { + return name.toString(); + } - public void dump(Abc abc, String indent, String attr, final FlexByteCodeInformationProcessor processor) - { - for(MemberInfo m : members.values()) - { - m.dump(abc, indent, attr, processor); - } - } + public void dump(Abc abc, String indent, String attr, FlexByteCodeInformationProcessor processor) { + for (MemberInfo m : members.values()) { + m.dump(abc, indent, attr, processor); + } + } - String getClassName() - { - final String s = name.toString(); - if(s.endsWith(Abc.$)) - { - return s.substring(0, s.length() - 1); - } - return s; - } + String getClassName() { + String s = name.toString(); + if (s.endsWith(Abc.$)) { + return s.substring(0, s.length() - 1); + } + return s; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/folding/JavaScriptFoldingBuilder.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/folding/JavaScriptFoldingBuilder.java index 8a5040d7..800aa297 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/folding/JavaScriptFoldingBuilder.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/folding/JavaScriptFoldingBuilder.java @@ -36,7 +36,8 @@ import consulo.language.editor.folding.FoldingBuilder; import consulo.language.psi.PsiWhiteSpace; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; + import java.util.ArrayList; import java.util.List; @@ -44,179 +45,154 @@ * @author max */ @ExtensionImpl -public class JavaScriptFoldingBuilder implements FoldingBuilder -{ - @RequiredReadAction - @Nonnull - @Override - public FoldingDescriptor[] buildFoldRegions(@Nonnull ASTNode node, @Nonnull Document document) - { - List descriptors = new ArrayList<>(); - appendDescriptors(node, document, descriptors); - return descriptors.toArray(new FoldingDescriptor[descriptors.size()]); - } - - @RequiredReadAction - private static ASTNode appendDescriptors(final ASTNode node, final Document document, final List descriptors) - { - final IElementType type = node.getElementType(); - if(type == JSElementTypes.BLOCK_STATEMENT || - type == JSElementTypes.OBJECT_LITERAL_EXPRESSION || - type == JSElementTypes.ARRAY_LITERAL_EXPRESSION || - type == JSElementTypes.XML_LITERAL_EXPRESSION) - { - TextRange textRange = node.getTextRange(); - if(textRange.getEndOffset() < document.getTextLength() && document.getLineNumber(textRange.getStartOffset()) != document.getLineNumber(textRange - .getEndOffset())) - { - addDescriptorForNode(node, descriptors); - } - } - else if(type == JSTokenTypes.DOC_COMMENT) - { - addDescriptorForNode(node, descriptors); - } - else if(type == JSTokenTypes.C_STYLE_COMMENT) - { - addDescriptorForNode(node, descriptors); - } - else if(type == JSTokenTypes.END_OF_LINE_COMMENT) - { - return collapseConsequentNodesOfSpecifiedType(node, descriptors, JSTokenTypes.END_OF_LINE_COMMENT); - } - else if(node.getPsi() instanceof JavaScriptImportStatementBase) - { - return collapseConsequentNodesOfSpecifiedType(node, descriptors, PsiUtilCore.getElementType(node)); - } - else if(type == JSElementTypes.CLASS || type == JSElementTypes.PACKAGE_STATEMENT) - { - ASTNode lbrace = node.findChildByType(JSTokenTypes.LBRACE); - - if(lbrace != null) - { - addDescriptorForRange(node, descriptors, new TextRange(lbrace.getStartOffset(), node.getTextRange().getEndOffset())); - } - } - - if(type instanceof JSFileElementType) - { - // expand chameleon - node.getPsi().getFirstChild(); - } - - ASTNode child = node.getFirstChildNode(); - while(child != null) - { - child = appendDescriptors(child, document, descriptors).getTreeNext(); - } - - return node; - } - - private static void addDescriptorForRange(ASTNode node, List descriptors, TextRange range) - { - if(range.getLength() > 1) - { - descriptors.add(new FoldingDescriptor(node, range)); - } - } - - private static void addDescriptorForNode(ASTNode node, List descriptors) - { - TextRange range = node.getTextRange(); - addDescriptorForRange(node, descriptors, range); - } - - @RequiredReadAction - private static ASTNode collapseConsequentNodesOfSpecifiedType(final ASTNode node, final List descriptors, final IElementType endOfLineComment) - { - PsiElement lastEoLComment = node.getPsi(); - PsiElement current = lastEoLComment.getNextSibling(); - - while(current != null) - { - if(!(current instanceof PsiWhiteSpace)) - { - break; - } - current = current.getNextSibling(); - if(current != null && current.getNode().getElementType() == endOfLineComment) - { - lastEoLComment = current; - current = current.getNextSibling(); - } - } - - if(lastEoLComment != node) - { - addDescriptorForRange(node, descriptors, new TextRange(node.getStartOffset(), lastEoLComment.getTextOffset() + lastEoLComment.getTextLength())); - return lastEoLComment.getNode(); - } - else - { - return node; - } - } - - @RequiredReadAction - @Override - public String getPlaceholderText(ASTNode node) - { - final IElementType type = node.getElementType(); - if(type == JSTokenTypes.DOC_COMMENT) - { - return "/**...*/"; - } - else if(type == JSTokenTypes.C_STYLE_COMMENT) - { - return "/*...*/"; - } - else if(type == JSTokenTypes.END_OF_LINE_COMMENT) - { - return "//..."; - } - else if(node.getPsi() instanceof JavaScriptImportStatementBase) - { - return "import ..."; - } - else if(type == JSElementTypes.BLOCK_STATEMENT || - type == JSElementTypes.OBJECT_LITERAL_EXPRESSION || - type == JSElementTypes.CLASS || - type == JSElementTypes.PACKAGE_STATEMENT) - { - return "{...}"; - } - else if(type == JSElementTypes.ARRAY_LITERAL_EXPRESSION) - { - return "[...]"; - } - else if(type == JSElementTypes.XML_LITERAL_EXPRESSION) - { - return ""; - } - return null; - } - - @RequiredReadAction - @Override - public boolean isCollapsedByDefault(ASTNode node) - { - if(node.getTreeParent().getElementType() instanceof JSFileElementType && node.getTreePrev() == null && - node.getPsi() instanceof PsiComment) - { - return CodeFoldingSettings.getInstance().COLLAPSE_FILE_HEADER; - } - if(node.getPsi() instanceof JavaScriptImportStatementBase) - { - return CodeFoldingSettings.getInstance().COLLAPSE_IMPORTS; - } - return CodeFoldingSettings.getInstance().COLLAPSE_DOC_COMMENTS && node.getElementType() == JSTokenTypes.DOC_COMMENT; - } - - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } +public class JavaScriptFoldingBuilder implements FoldingBuilder { + @Nonnull + @Override + @RequiredReadAction + public FoldingDescriptor[] buildFoldRegions(@Nonnull ASTNode node, @Nonnull Document document) { + List descriptors = new ArrayList<>(); + appendDescriptors(node, document, descriptors); + return descriptors.toArray(new FoldingDescriptor[descriptors.size()]); + } + + @RequiredReadAction + private static ASTNode appendDescriptors(ASTNode node, Document document, List descriptors) { + IElementType type = node.getElementType(); + if (type == JSElementTypes.BLOCK_STATEMENT + || type == JSElementTypes.OBJECT_LITERAL_EXPRESSION + || type == JSElementTypes.ARRAY_LITERAL_EXPRESSION + || type == JSElementTypes.XML_LITERAL_EXPRESSION) { + TextRange textRange = node.getTextRange(); + if (textRange.getEndOffset() < document.getTextLength() + && document.getLineNumber(textRange.getStartOffset()) != document.getLineNumber(textRange.getEndOffset())) { + addDescriptorForNode(node, descriptors); + } + } + else if (type == JSTokenTypes.DOC_COMMENT) { + addDescriptorForNode(node, descriptors); + } + else if (type == JSTokenTypes.C_STYLE_COMMENT) { + addDescriptorForNode(node, descriptors); + } + else if (type == JSTokenTypes.END_OF_LINE_COMMENT) { + return collapseConsequentNodesOfSpecifiedType(node, descriptors, JSTokenTypes.END_OF_LINE_COMMENT); + } + else if (node.getPsi() instanceof JavaScriptImportStatementBase) { + return collapseConsequentNodesOfSpecifiedType(node, descriptors, PsiUtilCore.getElementType(node)); + } + else if (type == JSElementTypes.CLASS || type == JSElementTypes.PACKAGE_STATEMENT) { + ASTNode lbrace = node.findChildByType(JSTokenTypes.LBRACE); + + if (lbrace != null) { + addDescriptorForRange(node, descriptors, new TextRange(lbrace.getStartOffset(), node.getTextRange().getEndOffset())); + } + } + + if (type instanceof JSFileElementType) { + // expand chameleon + node.getPsi().getFirstChild(); + } + + ASTNode child = node.getFirstChildNode(); + while (child != null) { + child = appendDescriptors(child, document, descriptors).getTreeNext(); + } + + return node; + } + + private static void addDescriptorForRange(ASTNode node, List descriptors, TextRange range) { + if (range.getLength() > 1) { + descriptors.add(new FoldingDescriptor(node, range)); + } + } + + private static void addDescriptorForNode(ASTNode node, List descriptors) { + TextRange range = node.getTextRange(); + addDescriptorForRange(node, descriptors, range); + } + + @RequiredReadAction + private static ASTNode collapseConsequentNodesOfSpecifiedType( + ASTNode node, + List descriptors, + IElementType endOfLineComment + ) { + PsiElement lastEoLComment = node.getPsi(); + PsiElement current = lastEoLComment.getNextSibling(); + + while (current != null) { + if (!(current instanceof PsiWhiteSpace)) { + break; + } + current = current.getNextSibling(); + if (current != null && current.getNode().getElementType() == endOfLineComment) { + lastEoLComment = current; + current = current.getNextSibling(); + } + } + + if (lastEoLComment != node) { + addDescriptorForRange( + node, + descriptors, + new TextRange(node.getStartOffset(), lastEoLComment.getTextOffset() + lastEoLComment.getTextLength()) + ); + return lastEoLComment.getNode(); + } + else { + return node; + } + } + + @RequiredReadAction + @Override + public String getPlaceholderText(ASTNode node) { + IElementType type = node.getElementType(); + if (type == JSTokenTypes.DOC_COMMENT) { + return "/**...*/"; + } + else if (type == JSTokenTypes.C_STYLE_COMMENT) { + return "/*...*/"; + } + else if (type == JSTokenTypes.END_OF_LINE_COMMENT) { + return "//..."; + } + else if (node.getPsi() instanceof JavaScriptImportStatementBase) { + return "import ..."; + } + else if (type == JSElementTypes.BLOCK_STATEMENT + || type == JSElementTypes.OBJECT_LITERAL_EXPRESSION + || type == JSElementTypes.CLASS + || type == JSElementTypes.PACKAGE_STATEMENT) { + return "{...}"; + } + else if (type == JSElementTypes.ARRAY_LITERAL_EXPRESSION) { + return "[...]"; + } + else if (type == JSElementTypes.XML_LITERAL_EXPRESSION) { + return ""; + } + return null; + } + + @RequiredReadAction + @Override + public boolean isCollapsedByDefault(ASTNode node) { + if (node.getTreeParent().getElementType() instanceof JSFileElementType + && node.getTreePrev() == null + && node.getPsi() instanceof PsiComment) { + return CodeFoldingSettings.getInstance().COLLAPSE_FILE_HEADER; + } + if (node.getPsi() instanceof JavaScriptImportStatementBase) { + return CodeFoldingSettings.getInstance().COLLAPSE_IMPORTS; + } + return CodeFoldingSettings.getInstance().COLLAPSE_DOC_COMMENTS && node.getElementType() == JSTokenTypes.DOC_COMMENT; + } + + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JSCodeStylePanel.form b/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JSCodeStylePanel.form index a0967b44..600734de 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JSCodeStylePanel.form +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JSCodeStylePanel.form @@ -14,14 +14,14 @@ - + - + @@ -37,7 +37,7 @@ - + @@ -102,7 +102,7 @@ - + diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JSCodeStylePanel.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JSCodeStylePanel.java index 389b6515..65eb68cf 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JSCodeStylePanel.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JSCodeStylePanel.java @@ -25,156 +25,137 @@ import consulo.language.editor.highlight.EditorHighlighterFactory; import consulo.language.file.light.LightVirtualFile; import consulo.language.psi.PsiFile; +import consulo.ui.annotation.RequiredUIAccess; import consulo.ui.ex.awt.event.DocumentAdapter; import consulo.virtualFileSystem.fileType.FileType; -import org.jetbrains.annotations.NonNls; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; import javax.swing.*; import javax.swing.event.DocumentEvent; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; /** * @author Maxim.Mossienko - * Date: Mar 12, 2008 - * Time: 10:39:21 PM + * @since 2008-03-12 */ -public class JSCodeStylePanel extends CodeStyleAbstractPanel -{ - private JPanel myPanel; - private JCheckBox myIndentPackageChildren; - private JPanel myPreviewPanel; - private JTextField myFieldPrefixTextField; - private JTextField myPropertyPrefixTextField; - private JCheckBox myUseSemicolon; - private boolean myInsideUpdate = false; - - public JSCodeStylePanel(final CodeStyleSettings settings) - { - super(settings); - - installPreviewPanel(myPreviewPanel); - addPanelToWatch(myPanel); - - myUseSemicolon.addItemListener(new ItemListener() - { - @Override - public void itemStateChanged(final ItemEvent e) - { - if(!myInsideUpdate) - { - //updatePreviewEditor(); - somethingChanged(); - } - } - }); - - final DocumentAdapter adapter = new DocumentAdapter() - { - @Override - protected void textChanged(final DocumentEvent e) - { - if(!myInsideUpdate) - { - //updatePreviewEditor(); - somethingChanged(); - } - } - }; - - myFieldPrefixTextField.getDocument().addDocumentListener(adapter); - myPropertyPrefixTextField.getDocument().addDocumentListener(adapter); - } - - @Override - protected EditorHighlighter createHighlighter(final EditorColorsScheme scheme) - { - return EditorHighlighterFactory.getInstance().createEditorHighlighter(new LightVirtualFile("a.as"), scheme, null); - } - - @Override - protected int getRightMargin() - { - return 60; - } - - @Override - protected void prepareForReformat(final PsiFile psiFile) - { - } - - @Override - @Nonnull - protected FileType getFileType() - { - return JavaScriptFileType.INSTANCE; - } - - @Override - protected String getPreviewText() - { - final JSCodeStyleSettings jsCodeStyleSettings = getSettings().getCustomSettings(JSCodeStyleSettings.class); - @NonNls String baseName = "field"; - @NonNls String propertyName = (myPropertyPrefixTextField != null ? myPropertyPrefixTextField.getText() : jsCodeStyleSettings.PROPERTY_PREFIX) + - baseName; - @NonNls String varName = (myFieldPrefixTextField != null ? myFieldPrefixTextField.getText() : jsCodeStyleSettings.FIELD_PREFIX) + baseName; - @NonNls String semiColon = (myUseSemicolon != null ? myUseSemicolon.isSelected() : jsCodeStyleSettings.USE_SEMICOLON_AFTER_STATEMENT) ? ";" : ""; - - return "package aaa {\nclass XXX {\n" + - "private var " + varName + semiColon + "\n" + - "function get " + propertyName + "() {\nreturn " + varName + semiColon + "\n" + - "}\n}\n}"; - } - - @Override - public void apply(final CodeStyleSettings settings) - { - final JSCodeStyleSettings jsCodeStyleSettings = settings.getCustomSettings(JSCodeStyleSettings.class); - jsCodeStyleSettings.INDENT_PACKAGE_CHILDREN = myIndentPackageChildren.isSelected() ? JSCodeStyleSettings.INDENT : JSCodeStyleSettings - .DO_NOT_INDENT; - jsCodeStyleSettings.FIELD_PREFIX = myFieldPrefixTextField.getText(); - jsCodeStyleSettings.PROPERTY_PREFIX = myPropertyPrefixTextField.getText(); - jsCodeStyleSettings.USE_SEMICOLON_AFTER_STATEMENT = myUseSemicolon.isSelected(); - } - - @Override - public boolean isModified(final CodeStyleSettings settings) - { - final JSCodeStyleSettings jsCodeStyleSettings = settings.getCustomSettings(JSCodeStyleSettings.class); - return (jsCodeStyleSettings.INDENT_PACKAGE_CHILDREN == JSCodeStyleSettings.INDENT) != myIndentPackageChildren.isSelected() || - !jsCodeStyleSettings.FIELD_PREFIX.equals(myFieldPrefixTextField.getText()) || - !jsCodeStyleSettings.PROPERTY_PREFIX.equals(myPropertyPrefixTextField.getText()) || - jsCodeStyleSettings.USE_SEMICOLON_AFTER_STATEMENT != (myUseSemicolon.isSelected()); - } - - @Override - public JComponent getPanel() - { - return myPanel; - } - - @Override - protected void resetImpl(final CodeStyleSettings settings) - { - try - { - myInsideUpdate = true; - final JSCodeStyleSettings jsCodeStyleSettings = settings.getCustomSettings(JSCodeStyleSettings.class); - myIndentPackageChildren.setSelected(jsCodeStyleSettings.INDENT_PACKAGE_CHILDREN == JSCodeStyleSettings.INDENT); - myFieldPrefixTextField.setText(jsCodeStyleSettings.FIELD_PREFIX); - myPropertyPrefixTextField.setText(jsCodeStyleSettings.PROPERTY_PREFIX); - myUseSemicolon.setSelected(jsCodeStyleSettings.USE_SEMICOLON_AFTER_STATEMENT); - } - finally - { - myInsideUpdate = false; - } - } - - @Override - protected String getFileTypeExtension(final FileType fileType) - { - return "js2"; - } +public class JSCodeStylePanel extends CodeStyleAbstractPanel { + private JPanel myPanel; + private JCheckBox myIndentPackageChildren; + private JPanel myPreviewPanel; + private JTextField myFieldPrefixTextField; + private JTextField myPropertyPrefixTextField; + private JCheckBox myUseSemicolon; + private boolean myInsideUpdate = false; + + @RequiredUIAccess + public JSCodeStylePanel(CodeStyleSettings settings) { + super(settings); + + installPreviewPanel(myPreviewPanel); + addPanelToWatch(myPanel); + + myUseSemicolon.addItemListener(e -> { + if (!myInsideUpdate) { + //updatePreviewEditor(); + somethingChanged(); + } + }); + + DocumentAdapter adapter = new DocumentAdapter() { + @Override + protected void textChanged(DocumentEvent e) { + if (!myInsideUpdate) { + //updatePreviewEditor(); + somethingChanged(); + } + } + }; + + myFieldPrefixTextField.getDocument().addDocumentListener(adapter); + myPropertyPrefixTextField.getDocument().addDocumentListener(adapter); + } + + @Override + protected EditorHighlighter createHighlighter(EditorColorsScheme scheme) { + return EditorHighlighterFactory.getInstance().createEditorHighlighter(new LightVirtualFile("a.as"), scheme, null); + } + + @Override + protected int getRightMargin() { + return 60; + } + + @Override + protected void prepareForReformat(PsiFile psiFile) { + } + + @Override + @Nonnull + protected FileType getFileType() { + return JavaScriptFileType.INSTANCE; + } + + @Override + protected String getPreviewText() { + JSCodeStyleSettings jsCodeStyleSettings = getSettings().getCustomSettings(JSCodeStyleSettings.class); + String baseName = "field"; + String propertyName = + (myPropertyPrefixTextField != null ? myPropertyPrefixTextField.getText() : jsCodeStyleSettings.PROPERTY_PREFIX) + + baseName; + String varName = + (myFieldPrefixTextField != null ? myFieldPrefixTextField.getText() : jsCodeStyleSettings.FIELD_PREFIX) + baseName; + String semiColon = + (myUseSemicolon != null ? myUseSemicolon.isSelected() : jsCodeStyleSettings.USE_SEMICOLON_AFTER_STATEMENT) ? ";" : ""; + + return "package aaa {\n" + + "class XXX {\n" + + "private var " + varName + semiColon + "\n" + + "function get " + propertyName + "() {\n" + + "return " + varName + semiColon + "\n" + + "}\n}\n}"; + } + + @Override + public void apply(CodeStyleSettings settings) { + JSCodeStyleSettings jsCodeStyleSettings = settings.getCustomSettings(JSCodeStyleSettings.class); + jsCodeStyleSettings.INDENT_PACKAGE_CHILDREN = myIndentPackageChildren.isSelected() + ? JSCodeStyleSettings.INDENT + : JSCodeStyleSettings.DO_NOT_INDENT; + jsCodeStyleSettings.FIELD_PREFIX = myFieldPrefixTextField.getText(); + jsCodeStyleSettings.PROPERTY_PREFIX = myPropertyPrefixTextField.getText(); + jsCodeStyleSettings.USE_SEMICOLON_AFTER_STATEMENT = myUseSemicolon.isSelected(); + } + + @Override + public boolean isModified(CodeStyleSettings settings) { + JSCodeStyleSettings jsCodeStyleSettings = settings.getCustomSettings(JSCodeStyleSettings.class); + return (jsCodeStyleSettings.INDENT_PACKAGE_CHILDREN == JSCodeStyleSettings.INDENT) != myIndentPackageChildren.isSelected() + || !jsCodeStyleSettings.FIELD_PREFIX.equals(myFieldPrefixTextField.getText()) + || !jsCodeStyleSettings.PROPERTY_PREFIX.equals(myPropertyPrefixTextField.getText()) + || jsCodeStyleSettings.USE_SEMICOLON_AFTER_STATEMENT != (myUseSemicolon.isSelected()); + } + + @Override + public JComponent getPanel() { + return myPanel; + } + + @Override + protected void resetImpl(CodeStyleSettings settings) { + try { + myInsideUpdate = true; + JSCodeStyleSettings jsCodeStyleSettings = settings.getCustomSettings(JSCodeStyleSettings.class); + myIndentPackageChildren.setSelected(jsCodeStyleSettings.INDENT_PACKAGE_CHILDREN == JSCodeStyleSettings.INDENT); + myFieldPrefixTextField.setText(jsCodeStyleSettings.FIELD_PREFIX); + myPropertyPrefixTextField.setText(jsCodeStyleSettings.PROPERTY_PREFIX); + myUseSemicolon.setSelected(jsCodeStyleSettings.USE_SEMICOLON_AFTER_STATEMENT); + } + finally { + myInsideUpdate = false; + } + } + + @Override + protected String getFileTypeExtension(FileType fileType) { + return "js2"; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JSCodeStyleSettingsProvider.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JSCodeStyleSettingsProvider.java index 24abcc8d..74f7eba2 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JSCodeStyleSettingsProvider.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JSCodeStyleSettingsProvider.java @@ -25,35 +25,29 @@ import consulo.language.codeStyle.CodeStyleSettings; import consulo.language.codeStyle.CustomCodeStyleSettings; import consulo.language.codeStyle.setting.CodeStyleSettingsProvider; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author Maxim.Mossienko - * Date: Mar 12, 2008 - * Time: 10:32:33 PM + * @since 2008-03-12 */ @ExtensionImpl -public class JSCodeStyleSettingsProvider extends CodeStyleSettingsProvider -{ - @Override - public CustomCodeStyleSettings createCustomSettings(final CodeStyleSettings settings) - { - return new JSCodeStyleSettings(settings); - } +public class JSCodeStyleSettingsProvider extends CodeStyleSettingsProvider { + @Override + public CustomCodeStyleSettings createCustomSettings(CodeStyleSettings settings) { + return new JSCodeStyleSettings(settings); + } - @Nullable - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } + @Nullable + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } - @Override - @Nonnull - public Configurable createSettingsPage(final CodeStyleSettings settings, final CodeStyleSettings originalSettings) - { - return new JavaScriptCodeStyleConfigurable(settings, originalSettings); - } + @Override + @Nonnull + public Configurable createSettingsPage(CodeStyleSettings settings, CodeStyleSettings originalSettings) { + return new JavaScriptCodeStyleConfigurable(settings, originalSettings); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JSFormattingModel.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JSFormattingModel.java index 373b3e13..958cd10e 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JSFormattingModel.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JSFormattingModel.java @@ -16,8 +16,6 @@ package com.intellij.lang.javascript.impl.formatter; -import javax.annotation.Nonnull; - import consulo.language.codeStyle.FormattingModel; import consulo.language.codeStyle.FormattingModelProvider; import consulo.language.ast.ASTNode; @@ -26,48 +24,42 @@ import consulo.language.codeStyle.Block; import consulo.language.codeStyle.FormattingDocumentModel; import consulo.language.psi.PsiFile; +import jakarta.annotation.Nonnull; /** * @author ven */ -public class JSFormattingModel implements FormattingModel -{ - private FormattingModel myModel; +public class JSFormattingModel implements FormattingModel { + private FormattingModel myModel; - public JSFormattingModel(final PsiFile file, CodeStyleSettings settings, final Block rootBlock) - { - myModel = FormattingModelProvider.createFormattingModelForPsiFile(file, rootBlock, settings); - } + public JSFormattingModel(PsiFile file, CodeStyleSettings settings, Block rootBlock) { + myModel = FormattingModelProvider.createFormattingModelForPsiFile(file, rootBlock, settings); + } - @Override - @Nonnull - public Block getRootBlock() - { - return myModel.getRootBlock(); - } + @Override + @Nonnull + public Block getRootBlock() { + return myModel.getRootBlock(); + } - @Override - @Nonnull - public FormattingDocumentModel getDocumentModel() - { - return myModel.getDocumentModel(); - } + @Override + @Nonnull + public FormattingDocumentModel getDocumentModel() { + return myModel.getDocumentModel(); + } - @Override - public TextRange replaceWhiteSpace(TextRange textRange, String whiteSpace) - { - return myModel.replaceWhiteSpace(textRange, whiteSpace); - } + @Override + public TextRange replaceWhiteSpace(TextRange textRange, String whiteSpace) { + return myModel.replaceWhiteSpace(textRange, whiteSpace); + } - @Override - public TextRange shiftIndentInsideRange(ASTNode node, TextRange range, int indent) - { - return myModel.shiftIndentInsideRange(node, range, indent); - } + @Override + public TextRange shiftIndentInsideRange(ASTNode node, TextRange range, int indent) { + return myModel.shiftIndentInsideRange(node, range, indent); + } - @Override - public void commitChanges() - { - myModel.commitChanges(); - } + @Override + public void commitChanges() { + myModel.commitChanges(); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JSSpacingProcessor.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JSSpacingProcessor.java index 39a4c720..6073d735 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JSSpacingProcessor.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JSSpacingProcessor.java @@ -22,6 +22,7 @@ import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.JSFunction; import com.intellij.lang.javascript.psi.JSImportStatement; +import consulo.annotation.access.RequiredReadAction; import consulo.document.util.TextRange; import consulo.language.ast.ASTNode; import consulo.language.ast.IElementType; @@ -37,715 +38,678 @@ /** * @author ven */ -public class JSSpacingProcessor extends JSNodeVisitor -{ - private ASTNode myParent; - private ASTNode myChild1; - private ASTNode myChild2; - private final CommonCodeStyleSettings mySettings; - private Spacing myResult; - private final IElementType type1; - private final IElementType type2; - - public JSSpacingProcessor(final ASTNode parent, final ASTNode child1, final ASTNode child2, final CommonCodeStyleSettings settings) - { - myParent = parent; - myChild1 = child1; - myChild2 = child2; - mySettings = settings; - type1 = child1.getElementType(); - type2 = child2.getElementType(); - visit(parent); - } - - public Spacing getResult() - { - return myResult; - } - - @Override - public void visitObjectLiteralExpression(final ASTNode node) - { - if(((type1 == JSTokenTypes.LBRACE && type2 != JSTokenTypes.RBRACE) || - type1 == JSTokenTypes.COMMA || - (type1 != JSTokenTypes.LBRACE && type2 == JSTokenTypes.RBRACE)) && shouldFormatObjectLiteralExpression()) - { - myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); - } - } - - private boolean shouldFormatObjectLiteralExpression() - { - IElementType grandParentType = myParent.getTreeParent().getElementType(); - if(grandParentType == JSElementTypes.ARRAY_LITERAL_EXPRESSION) - { - return true; - } - - return false; - } - - @Override - public void visitArrayLiteralExpression(final ASTNode node) - { - if(((type1 == JSTokenTypes.LBRACKET && type2 != JSTokenTypes.RBRACKET) || - type1 == JSTokenTypes.COMMA || - (type1 != JSTokenTypes.LBRACKET && type2 == JSTokenTypes.RBRACKET)) && shouldFormatArrayLiteralExpression()) - { - myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); - } - } - - private boolean shouldFormatArrayLiteralExpression() - { - JSExpression jsExpression = PsiTreeUtil.findChildOfType(myParent.getPsi(), JSExpression.class); - if(jsExpression != null) - { - IElementType type = PsiUtilCore.getElementType(jsExpression); - return type == JSElementTypes.ARRAY_LITERAL_EXPRESSION || type == JSElementTypes.OBJECT_LITERAL_EXPRESSION; - } - return false; - } - - @Override - public void visitXmlLiteralExpression(ASTNode node) - { - if((type2 == JSElementTypes.XML_LITERAL_EXPRESSION || - type1 == JSTokenTypes.XML_START_TAG_LIST && type2 != JSTokenTypes.XML_END_TAG_LIST || - type1 == JSElementTypes.XML_LITERAL_EXPRESSION) && shouldFormatXmlLiteralExpression()) - { - myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); - } - } - - private boolean shouldFormatXmlLiteralExpression() - { - return true; - } - - @Override - public void visitAttributeList(final ASTNode node) - { - if(type1 == JSElementTypes.ATTRIBUTE || type2 == JSElementTypes.ATTRIBUTE) - { - myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); - } - else - { - myResult = Spacing.createSpacing(1, 1, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); - } - } - - @Override - public void visitEmbeddedContent(final ASTNode node) - { - if(type2 == JSTokenTypes.END_OF_LINE_COMMENT) - { - myResult = Spacing.createSpacing(0, Integer.MAX_VALUE, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); - } - else if(JSElementTypes.SOURCE_ELEMENTS.contains(type1) || - JSElementTypes.SOURCE_ELEMENTS.contains(type2) && type1 != JSTokenTypes.DOT || - type2 == JSTokenTypes.RBRACE) - { - myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); - } - } - - @Override - public void visitParameterList(final ASTNode node) - { - if(type1 == JSTokenTypes.LPAR && type2 == JSTokenTypes.RPAR) - { - setSingleSpace(false); - } - else if(type1 == JSTokenTypes.LPAR || type2 == JSTokenTypes.RPAR) - { - setSingleSpace(mySettings.SPACE_WITHIN_METHOD_PARENTHESES); - } - else if(type1 == JSTokenTypes.COMMA) - { - setSingleSpace(mySettings.SPACE_AFTER_COMMA); - } - else if(type2 == JSTokenTypes.COMMA) - { - setSingleSpace(mySettings.SPACE_BEFORE_COMMA); - } - } - - @Override - public void visitPackageStatement(final ASTNode node) - { - if(shouldMakeLBraceOnNextLine()) - { - myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); - return; - } - processBlock(node); - } - - @Override - public void visitClass(final ASTNode node) - { - if(shouldMakeLBraceOnNextLine()) - { - myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); - return; - } - processBlock(node); - } - - private boolean shouldMakeLBraceOnNextLine() - { - return type2 == JSTokenTypes.LBRACE && mySettings.CLASS_BRACE_STYLE == CodeStyleSettings.NEXT_LINE; - } - - @Override - public void visitBlock(final ASTNode node) - { - processBlock(node); - } - - private void processBlock(final ASTNode node) - { - if(JSElementTypes.SOURCE_ELEMENTS.contains(type1) || JSElementTypes.SOURCE_ELEMENTS.contains(type2) || - type2 == JSTokenTypes.RBRACE) - { - if(isInjectedJSHack(type1, type2) || - isInjectedJSHack(type2, type1) || - (type2 == JSTokenTypes.END_OF_LINE_COMMENT && isInlineEndOfLineCommentOnLeft() && type1 != JSElementTypes.ES4_IMPORT_STATEMENT)) - { - myResult = Spacing.getReadOnlySpacing(); - } - else - { - final boolean keepOneLine = myParent.getPsi() instanceof JSFunction ? mySettings.KEEP_SIMPLE_METHODS_IN_ONE_LINE : mySettings - .KEEP_SIMPLE_BLOCKS_IN_ONE_LINE; - - if(keepOneLine && (type1 == JSTokenTypes.LBRACE || type2 == JSTokenTypes.RBRACE)) - { - myResult = Spacing.createDependentLFSpacing(0, 1, node.getTextRange(), mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); - } - else - { - if((JSElementTypes.ES4_IMPORT_STATEMENT == type1 && JSElementTypes.ES4_IMPORT_STATEMENT != type2 && JSTokenTypes.RBRACE != type2) || (JSElementTypes - .ES4_IMPORT_STATEMENT != type1 && JSTokenTypes.LBRACE != type1 && JSElementTypes.ES4_IMPORT_STATEMENT == type2)) - { - myResult = Spacing.createSpacing(0, 0, 2, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); - } - else if(JSElementTypes.ES4_IMPORT_STATEMENT == type1 && JSElementTypes.ES4_IMPORT_STATEMENT == type2) - { - myResult = getSpacingBetweenImports(); - } - else - { - if(shouldPlaceExtraLinesAroundMethod()) - { - myResult = Spacing.createSpacing(0, 0, 1 + mySettings.BLANK_LINES_AROUND_METHOD, mySettings.KEEP_LINE_BREAKS, - mySettings.KEEP_BLANK_LINES_IN_CODE); - } - else - { - myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); - } - } - } - } - } - } - - private boolean shouldPlaceExtraLinesAroundMethod() - { - return (type1 == JSElementTypes.FUNCTION_DECLARATION && type2 != JSTokenTypes.RBRACE) || (type1 == JSElementTypes.VAR_STATEMENT && type2 == - JSElementTypes.FUNCTION_DECLARATION); - } - - private Spacing getSpacingBetweenImports() - { - String fqn1 = ((JSImportStatement) myChild1.getPsi()).getImportText(); - String fqn2 = ((JSImportStatement) myChild2.getPsi()).getImportText(); - String rootPackage1 = fqn1 != null && fqn1.contains(".") ? fqn1.substring(0, fqn1.indexOf(".")) : null; - String rootPackage2 = fqn2 != null && fqn2.contains(".") ? fqn2.substring(0, fqn2.indexOf(".")) : null; - boolean lineBreak = rootPackage1 != null && rootPackage2 != null && !rootPackage1.equals(rootPackage2); - return Spacing.createSpacing(0, 0, lineBreak ? 2 : 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); - } - - private static boolean isInjectedJSHack(final IElementType type1, final IElementType type2) - { - // Following code attempts NOT to reformat '@xxx:bbb.ccc' in var initializers - return type1 == JSTokenTypes.BAD_CHARACTER && JSElementTypes.SOURCE_ELEMENTS.contains(type2); - } - - @Override - public void visitFile(final ASTNode node) - { - if(JSElementTypes.SOURCE_ELEMENTS.contains(type1) || JSElementTypes.SOURCE_ELEMENTS.contains(type2)) - { - if(type2 == JSTokenTypes.END_OF_LINE_COMMENT && isInlineEndOfLineCommentOnLeft() && type1 != JSElementTypes.ES4_IMPORT_STATEMENT) - { - myResult = Spacing.getReadOnlySpacing(); - } - else - { - if((JSElementTypes.ES4_IMPORT_STATEMENT == type1 && JSElementTypes.ES4_IMPORT_STATEMENT != type2) || (JSElementTypes.ES4_IMPORT_STATEMENT != type1 && - JSElementTypes.ES4_IMPORT_STATEMENT == type2)) - { - myResult = Spacing.createSpacing(0, 0, 2, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); - } - else if(JSElementTypes.ES4_IMPORT_STATEMENT == type1 && JSElementTypes.ES4_IMPORT_STATEMENT == type2) - { - myResult = getSpacingBetweenImports(); - } - else - { - if(shouldPlaceExtraLinesAroundMethod() && node.getPsi().getContext() instanceof XmlText) - { - myResult = Spacing.createSpacing(0, 0, 1 + mySettings.BLANK_LINES_AROUND_METHOD, mySettings.KEEP_LINE_BREAKS, - mySettings.KEEP_BLANK_LINES_IN_CODE); - } - else - { - myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); - } - } - } - } - } - - private boolean isInlineEndOfLineCommentOnLeft() - { - final ASTNode prev = myChild2.getTreePrev(); - if(prev == myChild1) - { - return true; - } - if(prev != null && prev.getPsi() instanceof PsiWhiteSpace) - { - return !prev.textContains('\n'); - } - return false; - } - - @Override - public void visitFunctionDeclaration(final ASTNode node) - { - if(type1 == JSTokenTypes.FUNCTION_KEYWORD && type2 == JSElementTypes.REFERENCE_EXPRESSION) - { - setSingleSpace(true); - } - else if(type1 == JSElementTypes.REFERENCE_EXPRESSION && type2 == JSElementTypes.PARAMETER_LIST) - { - setSingleSpace(mySettings.SPACE_BEFORE_METHOD_PARENTHESES); - } - else if(type2 == JSElementTypes.BLOCK_STATEMENT) - { - setBraceSpace(mySettings.SPACE_BEFORE_METHOD_LBRACE, mySettings.METHOD_BRACE_STYLE, myChild1.getTextRange()); - } - else if(type1 == JSElementTypes.ATTRIBUTE_LIST && type2 == JSTokenTypes.FUNCTION_KEYWORD) - { - setSingleSpace(true); - } - } - - - @Override - public void visitFunctionExpression(final ASTNode node) - { - visitFunctionDeclaration(node); - } - - @Override - public void visitReferenceExpression(final ASTNode node) - { - if(type1 == JSTokenTypes.NEW_KEYWORD) - { - setSingleSpace(true); - } - else - { - setSingleSpace(false); // a.b should not have spaces before and after dot - } - } - - @Override - public void visitDocComment(final ASTNode node) - { - //myResult = Spacing.createKeepingFirstColumnSpacing(0, Integer.MAX_VALUE, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); - } - - @Override - public void visitIfStatement(final ASTNode node) - { - if(type1 == JSTokenTypes.IF_KEYWORD && type2 == JSTokenTypes.LPAR) - { - setSingleSpace(mySettings.SPACE_BEFORE_IF_PARENTHESES); - } - else if(type1 == JSTokenTypes.LPAR || type2 == JSTokenTypes.RPAR) - { - setSingleSpace(mySettings.SPACE_WITHIN_IF_PARENTHESES); - } - else if(type1 == JSTokenTypes.RPAR && type2 == JSElementTypes.BLOCK_STATEMENT) - { - TextRange dependentRange = new TextRange(myParent.getStartOffset(), myChild1.getTextRange().getEndOffset()); - setBraceSpace(mySettings.SPACE_BEFORE_IF_LBRACE, mySettings.BRACE_STYLE, dependentRange); - } - else if(type2 == JSTokenTypes.ELSE_KEYWORD) - { - setLineBreakSpace(mySettings.ELSE_ON_NEW_LINE); - } - else if(type1 == JSTokenTypes.ELSE_KEYWORD && type2 == JSElementTypes.BLOCK_STATEMENT) - { - setBraceSpace(mySettings.SPACE_BEFORE_ELSE_LBRACE, mySettings.BRACE_STYLE, null); - } - } - - @Override - public void visitCallExpression(final ASTNode node) - { - if(type2 == JSElementTypes.ARGUMENT_LIST) - { - setSingleSpace(mySettings.SPACE_BEFORE_METHOD_CALL_PARENTHESES); - } - } - - @Override - public void visitNewExpression(final ASTNode node) - { - if(type1 == JSTokenTypes.NEW_KEYWORD) - { - setSingleSpace(true); - } - else if(type2 == JSElementTypes.ARGUMENT_LIST) - { - setSingleSpace(mySettings.SPACE_BEFORE_METHOD_CALL_PARENTHESES); - } - } - - @Override - public void visitForStatement(final ASTNode node) - { - if(type1 == JSTokenTypes.SEMICOLON) - { - setSingleSpace(true); - } - else if(type2 == JSTokenTypes.SEMICOLON) - { - setSingleSpace(mySettings.SPACE_BEFORE_SEMICOLON); - } - - if(type1 == JSTokenTypes.FOR_KEYWORD && type2 == JSTokenTypes.LPAR) - { - setSingleSpace(mySettings.SPACE_BEFORE_FOR_PARENTHESES); - } - else if(type1 == JSTokenTypes.RPAR && type2 == JSElementTypes.BLOCK_STATEMENT) - { - TextRange dependentRange = new TextRange(myParent.getStartOffset(), myChild1.getTextRange().getEndOffset()); - setBraceSpace(mySettings.SPACE_BEFORE_FOR_LBRACE, mySettings.BRACE_STYLE, dependentRange); - } - else if(type1 == JSTokenTypes.LPAR || type2 == JSTokenTypes.RPAR) - { - setSingleSpace(mySettings.SPACE_WITHIN_FOR_PARENTHESES); - } - } - - @Override - public void visitDoWhileStatement(final ASTNode node) - { - if(type2 == JSTokenTypes.WHILE_KEYWORD) - { - if(mySettings.WHILE_ON_NEW_LINE) - { - myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); - } - else - { - myResult = Spacing.createSpacing(1, 1, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); - } - } - else if(type2 == JSTokenTypes.LPAR) - { - setSingleSpace(mySettings.SPACE_BEFORE_WHILE_PARENTHESES); - } - else if(type1 == JSTokenTypes.LPAR || type2 == JSTokenTypes.RPAR) - { - setSingleSpace(mySettings.SPACE_WITHIN_WHILE_PARENTHESES); - } - - if(type1 == JSTokenTypes.DO_KEYWORD && type2 == JSElementTypes.BLOCK_STATEMENT) - { - setBraceSpace(true, mySettings.BRACE_STYLE, null); - } - } - - @Override - public void visitForInStatement(final ASTNode node) - { - if(type1 == JSTokenTypes.VAR_KEYWORD || type2 == JSTokenTypes.VAR_KEYWORD) - { - setSingleSpace(true); - } - else if(type1 == JSTokenTypes.FOR_KEYWORD && type2 == JSTokenTypes.LPAR) - { - setSingleSpace(mySettings.SPACE_BEFORE_FOR_PARENTHESES); - } - else if(type1 == JSTokenTypes.RPAR && type2 == JSElementTypes.BLOCK_STATEMENT) - { - TextRange dependentRange = new TextRange(myParent.getStartOffset(), myChild1.getTextRange().getEndOffset()); - setBraceSpace(mySettings.SPACE_BEFORE_FOR_LBRACE, mySettings.BRACE_STYLE, dependentRange); - } - else if(type1 == JSTokenTypes.LPAR || type2 == JSTokenTypes.RPAR) - { - setSingleSpace(mySettings.SPACE_WITHIN_FOR_PARENTHESES); - } - } - - @Override - public void visitWhileStatement(final ASTNode node) - { - if(type1 == JSTokenTypes.WHILE_KEYWORD && type2 == JSTokenTypes.LPAR) - { - setSingleSpace(mySettings.SPACE_BEFORE_WHILE_PARENTHESES); - } - else if(type1 == JSTokenTypes.RPAR && type2 == JSElementTypes.BLOCK_STATEMENT) - { - TextRange dependentRange = new TextRange(myParent.getStartOffset(), myChild1.getTextRange().getEndOffset()); - setBraceSpace(mySettings.SPACE_BEFORE_WHILE_LBRACE, mySettings.BRACE_STYLE, dependentRange); - } - else if(type1 == JSTokenTypes.LPAR || type2 == JSTokenTypes.RPAR) - { - setSingleSpace(mySettings.SPACE_WITHIN_WHILE_PARENTHESES); - } - } - - @Override - public void visitWithStatement(final ASTNode node) - { - if(type1 == JSTokenTypes.WITH_KEYWORD && type2 == JSTokenTypes.LPAR) - { - setSingleSpace(mySettings.SPACE_BEFORE_WHILE_PARENTHESES); - } - else if(type1 == JSTokenTypes.RPAR && type2 == JSElementTypes.BLOCK_STATEMENT) - { - TextRange dependentRange = new TextRange(myParent.getStartOffset(), myChild1.getTextRange().getEndOffset()); - setBraceSpace(mySettings.SPACE_BEFORE_WHILE_LBRACE, mySettings.BRACE_STYLE, dependentRange); - } - else if(type1 == JSTokenTypes.LPAR || type2 == JSTokenTypes.RPAR) - { - setSingleSpace(mySettings.SPACE_WITHIN_WHILE_PARENTHESES); - } - } - - public static TokenSet NOT_A_PACKAGE_CONTENT = TokenSet.create(JSTokenTypes.PACKAGE_KEYWORD, JSElementTypes.REFERENCE_EXPRESSION, - JSTokenTypes.LBRACE, JSTokenTypes.RBRACE); - - @Override - public void visitTryStatement(final ASTNode node) - { - if(type1 == JSTokenTypes.TRY_KEYWORD && type2 == JSElementTypes.BLOCK_STATEMENT) - { - setBraceSpace(mySettings.SPACE_BEFORE_TRY_LBRACE, mySettings.BRACE_STYLE, null); - } - else if(type2 == JSElementTypes.CATCH_BLOCK) - { - setLineBreakSpace(mySettings.CATCH_ON_NEW_LINE); - } - else if(type2 == JSTokenTypes.FINALLY_KEYWORD) - { - setLineBreakSpace(mySettings.FINALLY_ON_NEW_LINE); - } - else if(type1 == JSTokenTypes.FINALLY_KEYWORD) - { - setBraceSpace(mySettings.SPACE_BEFORE_FINALLY_LBRACE, mySettings.BRACE_STYLE, null); - } - } - - @Override - public void visitCatchBlock(final ASTNode node) - { - if(type1 == JSTokenTypes.LPAR || type2 == JSTokenTypes.RPAR) - { - setSingleSpace(mySettings.SPACE_WITHIN_CATCH_PARENTHESES); - } - - if(type1 == JSTokenTypes.CATCH_KEYWORD && type2 == JSTokenTypes.LPAR) - { - setSingleSpace(mySettings.SPACE_BEFORE_CATCH_PARENTHESES); - } - - if(type2 == JSElementTypes.BLOCK_STATEMENT) - { - TextRange dependentRange = new TextRange(myParent.getStartOffset(), myChild2.getTextRange().getStartOffset()); - setBraceSpace(mySettings.SPACE_BEFORE_CATCH_LBRACE, mySettings.BRACE_STYLE, dependentRange); - } - } - - @Override - public void visitSwitchStatement(final ASTNode node) - { - if(type1 == JSTokenTypes.SWITCH_KEYWORD && type2 == JSTokenTypes.LPAR) - { - setSingleSpace(mySettings.SPACE_BEFORE_SWITCH_PARENTHESES); - } - else if(type1 == JSTokenTypes.RPAR) - { - TextRange dependentRange = new TextRange(myParent.getStartOffset(), myChild1.getTextRange().getEndOffset()); - setBraceSpace(mySettings.SPACE_BEFORE_SWITCH_LBRACE, mySettings.BRACE_STYLE, dependentRange); - } - else if(type1 == JSTokenTypes.LPAR || type2 == JSTokenTypes.RPAR) - { - setSingleSpace(mySettings.SPACE_WITHIN_SWITCH_PARENTHESES); - } - } - - @Override - public void visitArgumentList(final ASTNode node) - { - if(type1 == JSTokenTypes.LPAR || type2 == JSTokenTypes.RPAR) - { - setSingleSpace(false); - } - else if(type1 == JSTokenTypes.COMMA) - { - setSingleSpace(mySettings.SPACE_AFTER_COMMA); - } - else if(type2 == JSTokenTypes.COMMA) - { - setSingleSpace(mySettings.SPACE_BEFORE_COMMA); - } - } - - @Override - public void visitStatement(final ASTNode node) - { - if(type2 == JSTokenTypes.SEMICOLON) - { - setSingleSpace(false); - } - } - - @Override - public void visitVarStatement(final ASTNode node) - { - if(type1 == JSTokenTypes.VAR_KEYWORD) - { - setSingleSpace(true); - } - } - - @Override - public void visitVariable(final ASTNode node) - { - if(type1 == JSTokenTypes.EQ || type2 == JSTokenTypes.EQ) - { // Initializer - setSingleSpace(mySettings.SPACE_AROUND_ASSIGNMENT_OPERATORS); - } - } - - @Override - public void visitBinaryExpression(final ASTNode node) - { - IElementType opSign = null; - if(JSTokenTypes.OPERATIONS.contains(type1)) - { - opSign = type1; - } - else if(JSTokenTypes.OPERATIONS.contains(type2)) - { - opSign = type2; - } - - if(opSign != null) - { - setSingleSpace(getSpaceAroundOption(opSign)); - } - } - - @Override - public void visitConditionalExpression(final ASTNode node) - { - if(type1 == JSTokenTypes.QUEST) - { - setSingleSpace(mySettings.SPACE_AFTER_QUEST); - } - else if(type2 == JSTokenTypes.QUEST) - { - setSingleSpace(mySettings.SPACE_BEFORE_QUEST); - } - else if(type1 == JSTokenTypes.COLON) - { - setSingleSpace(mySettings.SPACE_AFTER_COLON); - } - else if(type2 == JSTokenTypes.COLON) - { - setSingleSpace(mySettings.SPACE_BEFORE_COLON); - } - } - - private boolean getSpaceAroundOption(final IElementType opSign) - { - boolean option = false; - if(JSTokenTypes.ADDITIVE_OPERATIONS.contains(opSign)) - { - option = mySettings.SPACE_AROUND_ADDITIVE_OPERATORS; - } - else if(JSTokenTypes.MULTIPLICATIVE_OPERATIONS.contains(opSign)) - { - option = mySettings.SPACE_AROUND_MULTIPLICATIVE_OPERATORS; - } - else if(JSTokenTypes.ASSIGNMENT_OPERATIONS.contains(opSign)) - { - option = mySettings.SPACE_AROUND_ASSIGNMENT_OPERATORS; - } - else if(JSTokenTypes.EQUALITY_OPERATIONS.contains(opSign)) - { - option = mySettings.SPACE_AROUND_EQUALITY_OPERATORS; - } - else if(JSTokenTypes.RELATIONAL_OPERATIONS.contains(opSign)) - { - option = mySettings.SPACE_AROUND_RELATIONAL_OPERATORS; - } - else if(JSTokenTypes.SHIFT_OPERATIONS.contains(opSign)) - { - option = mySettings.SPACE_AROUND_BITWISE_OPERATORS; - } - else if(opSign == JSTokenTypes.ANDAND || opSign == JSTokenTypes.OROR) - { - option = mySettings.SPACE_AROUND_LOGICAL_OPERATORS; - } - else if(opSign == JSTokenTypes.OR || opSign == JSTokenTypes.AND || opSign == JSTokenTypes.XOR) - { - option = mySettings.SPACE_AROUND_BITWISE_OPERATORS; - } - else if(opSign == JSTokenTypes.IS_KEYWORD || opSign == JSTokenTypes.AS_KEYWORD) - { - option = true; - } - return option; - } - - private void setSingleSpace(boolean needSpace) - { - final int spaces = needSpace ? 1 : 0; - myResult = Spacing.createSpacing(spaces, spaces, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); - } - - private void setBraceSpace(boolean needSpaceSetting, int braceStyleSetting, TextRange textRange) - { - int spaces = needSpaceSetting ? 1 : 0; - if(braceStyleSetting == CodeStyleSettings.NEXT_LINE_IF_WRAPPED && textRange != null) - { - myResult = Spacing.createDependentLFSpacing(spaces, spaces, textRange, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); - } - else - { - int lineBreaks = braceStyleSetting == CodeStyleSettings.END_OF_LINE ? 0 : 1; - myResult = Spacing.createSpacing(spaces, spaces, lineBreaks, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); - } - } - - private void setLineBreakSpace(final boolean needLineBreak) - { - final int breaks = needLineBreak || myChild1.getElementType() == JSTokenTypes.END_OF_LINE_COMMENT ? 1 : 0; - myResult = Spacing.createSpacing(1, 1, breaks, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); - } - +public class JSSpacingProcessor extends JSNodeVisitor { + private ASTNode myParent; + private ASTNode myChild1; + private ASTNode myChild2; + private final CommonCodeStyleSettings mySettings; + private Spacing myResult; + private final IElementType type1; + private final IElementType type2; + + public JSSpacingProcessor(ASTNode parent, ASTNode child1, ASTNode child2, CommonCodeStyleSettings settings) { + myParent = parent; + myChild1 = child1; + myChild2 = child2; + mySettings = settings; + type1 = child1.getElementType(); + type2 = child2.getElementType(); + visit(parent); + } + + public Spacing getResult() { + return myResult; + } + + @Override + public void visitObjectLiteralExpression(ASTNode node) { + if (((type1 == JSTokenTypes.LBRACE && type2 != JSTokenTypes.RBRACE) + || type1 == JSTokenTypes.COMMA + || (type1 != JSTokenTypes.LBRACE && type2 == JSTokenTypes.RBRACE)) + && shouldFormatObjectLiteralExpression()) { + myResult = Spacing.createSpacing( + 0, + 0, + 1, + mySettings.KEEP_LINE_BREAKS, + mySettings.KEEP_BLANK_LINES_IN_CODE + ); + } + } + + private boolean shouldFormatObjectLiteralExpression() { + IElementType grandParentType = myParent.getTreeParent().getElementType(); + return grandParentType == JSElementTypes.ARRAY_LITERAL_EXPRESSION; + } + + @Override + @RequiredReadAction + public void visitArrayLiteralExpression(ASTNode node) { + if (((type1 == JSTokenTypes.LBRACKET && type2 != JSTokenTypes.RBRACKET) + || type1 == JSTokenTypes.COMMA + || (type1 != JSTokenTypes.LBRACKET && type2 == JSTokenTypes.RBRACKET)) + && shouldFormatArrayLiteralExpression()) { + myResult = Spacing.createSpacing( + 0, + 0, + 1, + mySettings.KEEP_LINE_BREAKS, + mySettings.KEEP_BLANK_LINES_IN_CODE + ); + } + } + + @RequiredReadAction + private boolean shouldFormatArrayLiteralExpression() { + JSExpression jsExpression = PsiTreeUtil.findChildOfType(myParent.getPsi(), JSExpression.class); + if (jsExpression != null) { + IElementType type = PsiUtilCore.getElementType(jsExpression); + return type == JSElementTypes.ARRAY_LITERAL_EXPRESSION || type == JSElementTypes.OBJECT_LITERAL_EXPRESSION; + } + return false; + } + + @Override + public void visitXmlLiteralExpression(ASTNode node) { + if ((type2 == JSElementTypes.XML_LITERAL_EXPRESSION + || type1 == JSTokenTypes.XML_START_TAG_LIST && type2 != JSTokenTypes.XML_END_TAG_LIST + || type1 == JSElementTypes.XML_LITERAL_EXPRESSION) + && shouldFormatXmlLiteralExpression()) { + myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); + } + } + + private boolean shouldFormatXmlLiteralExpression() { + return true; + } + + @Override + public void visitAttributeList(ASTNode node) { + if (type1 == JSElementTypes.ATTRIBUTE || type2 == JSElementTypes.ATTRIBUTE) { + myResult = Spacing.createSpacing( + 0, + 0, + 1, + mySettings.KEEP_LINE_BREAKS, + mySettings.KEEP_BLANK_LINES_IN_CODE + ); + } + else { + myResult = Spacing.createSpacing( + 1, + 1, + 0, + mySettings.KEEP_LINE_BREAKS, + mySettings.KEEP_BLANK_LINES_IN_CODE + ); + } + } + + @Override + public void visitEmbeddedContent(ASTNode node) { + if (type2 == JSTokenTypes.END_OF_LINE_COMMENT) { + myResult = Spacing.createSpacing( + 0, + Integer.MAX_VALUE, + 0, + mySettings.KEEP_LINE_BREAKS, + mySettings.KEEP_BLANK_LINES_IN_CODE + ); + } + else if (JSElementTypes.SOURCE_ELEMENTS.contains(type1) + || JSElementTypes.SOURCE_ELEMENTS.contains(type2) && type1 != JSTokenTypes.DOT + || type2 == JSTokenTypes.RBRACE) { + myResult = Spacing.createSpacing( + 0, + 0, + 1, + mySettings.KEEP_LINE_BREAKS, + mySettings.KEEP_BLANK_LINES_IN_CODE + ); + } + } + + @Override + public void visitParameterList(ASTNode node) { + if (type1 == JSTokenTypes.LPAR && type2 == JSTokenTypes.RPAR) { + setSingleSpace(false); + } + else if (type1 == JSTokenTypes.LPAR || type2 == JSTokenTypes.RPAR) { + setSingleSpace(mySettings.SPACE_WITHIN_METHOD_PARENTHESES); + } + else if (type1 == JSTokenTypes.COMMA) { + setSingleSpace(mySettings.SPACE_AFTER_COMMA); + } + else if (type2 == JSTokenTypes.COMMA) { + setSingleSpace(mySettings.SPACE_BEFORE_COMMA); + } + } + + @Override + @RequiredReadAction + public void visitPackageStatement(ASTNode node) { + if (shouldMakeLBraceOnNextLine()) { + myResult = Spacing.createSpacing( + 0, + 0, + 1, + mySettings.KEEP_LINE_BREAKS, + mySettings.KEEP_BLANK_LINES_IN_CODE + ); + return; + } + processBlock(node); + } + + @Override + @RequiredReadAction + public void visitClass(ASTNode node) { + if (shouldMakeLBraceOnNextLine()) { + myResult = Spacing.createSpacing( + 0, + 0, + 1, + mySettings.KEEP_LINE_BREAKS, + mySettings.KEEP_BLANK_LINES_IN_CODE + ); + return; + } + processBlock(node); + } + + private boolean shouldMakeLBraceOnNextLine() { + return type2 == JSTokenTypes.LBRACE && mySettings.CLASS_BRACE_STYLE == CodeStyleSettings.NEXT_LINE; + } + + @Override + @RequiredReadAction + public void visitBlock(ASTNode node) { + processBlock(node); + } + + @RequiredReadAction + private void processBlock(ASTNode node) { + if (JSElementTypes.SOURCE_ELEMENTS.contains(type1) || JSElementTypes.SOURCE_ELEMENTS.contains(type2) || + type2 == JSTokenTypes.RBRACE) { + if (isInjectedJSHack(type1, type2) || isInjectedJSHack(type2, type1) + || (type2 == JSTokenTypes.END_OF_LINE_COMMENT + && isInlineEndOfLineCommentOnLeft() && type1 != JSElementTypes.ES4_IMPORT_STATEMENT)) { + myResult = Spacing.getReadOnlySpacing(); + } + else { + boolean keepOneLine = myParent.getPsi() instanceof JSFunction + ? mySettings.KEEP_SIMPLE_METHODS_IN_ONE_LINE + : mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE; + + if (keepOneLine && (type1 == JSTokenTypes.LBRACE || type2 == JSTokenTypes.RBRACE)) { + myResult = Spacing.createDependentLFSpacing(0, + 1, + node.getTextRange(), + mySettings.KEEP_LINE_BREAKS, + mySettings.KEEP_BLANK_LINES_IN_CODE + ); + } + else if ((JSElementTypes.ES4_IMPORT_STATEMENT == type1 && JSElementTypes.ES4_IMPORT_STATEMENT != type2 + && JSTokenTypes.RBRACE != type2) + || (JSElementTypes.ES4_IMPORT_STATEMENT != type1 && JSTokenTypes.LBRACE != type1 + && JSElementTypes.ES4_IMPORT_STATEMENT == type2)) { + myResult = Spacing.createSpacing( + 0, + 0, + 2, + mySettings.KEEP_LINE_BREAKS, + mySettings.KEEP_BLANK_LINES_IN_CODE + ); + } + else if (JSElementTypes.ES4_IMPORT_STATEMENT == type1 && JSElementTypes.ES4_IMPORT_STATEMENT == type2) { + myResult = getSpacingBetweenImports(); + } + else if (shouldPlaceExtraLinesAroundMethod()) { + myResult = Spacing.createSpacing( + 0, + 0, + 1 + mySettings.BLANK_LINES_AROUND_METHOD, + mySettings.KEEP_LINE_BREAKS, + mySettings.KEEP_BLANK_LINES_IN_CODE + ); + } + else { + myResult = Spacing.createSpacing( + 0, + 0, + 1, + mySettings.KEEP_LINE_BREAKS, + mySettings.KEEP_BLANK_LINES_IN_CODE + ); + } + } + } + } + + private boolean shouldPlaceExtraLinesAroundMethod() { + return (type1 == JSElementTypes.FUNCTION_DECLARATION && type2 != JSTokenTypes.RBRACE) + || (type1 == JSElementTypes.VAR_STATEMENT && type2 == JSElementTypes.FUNCTION_DECLARATION); + } + + @RequiredReadAction + private Spacing getSpacingBetweenImports() { + String fqn1 = ((JSImportStatement)myChild1.getPsi()).getImportText(); + String fqn2 = ((JSImportStatement)myChild2.getPsi()).getImportText(); + String rootPackage1 = fqn1 != null && fqn1.contains(".") ? fqn1.substring(0, fqn1.indexOf(".")) : null; + String rootPackage2 = fqn2 != null && fqn2.contains(".") ? fqn2.substring(0, fqn2.indexOf(".")) : null; + boolean lineBreak = rootPackage1 != null && rootPackage2 != null && !rootPackage1.equals(rootPackage2); + return Spacing.createSpacing( + 0, + 0, + lineBreak ? 2 : 1, + mySettings.KEEP_LINE_BREAKS, + mySettings.KEEP_BLANK_LINES_IN_CODE + ); + } + + private static boolean isInjectedJSHack(IElementType type1, IElementType type2) { + // Following code attempts NOT to reformat '@xxx:bbb.ccc' in var initializers + return type1 == JSTokenTypes.BAD_CHARACTER && JSElementTypes.SOURCE_ELEMENTS.contains(type2); + } + + @Override + @RequiredReadAction + public void visitFile(ASTNode node) { + if (JSElementTypes.SOURCE_ELEMENTS.contains(type1) || JSElementTypes.SOURCE_ELEMENTS.contains(type2)) { + if (type2 == JSTokenTypes.END_OF_LINE_COMMENT + && isInlineEndOfLineCommentOnLeft() + && type1 != JSElementTypes.ES4_IMPORT_STATEMENT) { + myResult = Spacing.getReadOnlySpacing(); + } + else if ((JSElementTypes.ES4_IMPORT_STATEMENT == type1 && JSElementTypes.ES4_IMPORT_STATEMENT != type2) + || (JSElementTypes.ES4_IMPORT_STATEMENT != type1 && JSElementTypes.ES4_IMPORT_STATEMENT == type2)) { + myResult = Spacing.createSpacing( + 0, + 0, + 2, + mySettings.KEEP_LINE_BREAKS, + mySettings.KEEP_BLANK_LINES_IN_CODE + ); + } + else if (JSElementTypes.ES4_IMPORT_STATEMENT == type1 && JSElementTypes.ES4_IMPORT_STATEMENT == type2) { + myResult = getSpacingBetweenImports(); + } + else if (shouldPlaceExtraLinesAroundMethod() && node.getPsi().getContext() instanceof XmlText) { + myResult = Spacing.createSpacing( + 0, + 0, + 1 + mySettings.BLANK_LINES_AROUND_METHOD, + mySettings.KEEP_LINE_BREAKS, + mySettings.KEEP_BLANK_LINES_IN_CODE + ); + } + else { + myResult = Spacing.createSpacing( + 0, + 0, + 1, + mySettings.KEEP_LINE_BREAKS, + mySettings.KEEP_BLANK_LINES_IN_CODE + ); + } + } + } + + private boolean isInlineEndOfLineCommentOnLeft() { + ASTNode prev = myChild2.getTreePrev(); + return prev == myChild1 + || prev != null && prev.getPsi() instanceof PsiWhiteSpace && !prev.textContains('\n'); + } + + @Override + public void visitFunctionDeclaration(ASTNode node) { + if (type1 == JSTokenTypes.FUNCTION_KEYWORD && type2 == JSElementTypes.REFERENCE_EXPRESSION) { + setSingleSpace(true); + } + else if (type1 == JSElementTypes.REFERENCE_EXPRESSION && type2 == JSElementTypes.PARAMETER_LIST) { + setSingleSpace(mySettings.SPACE_BEFORE_METHOD_PARENTHESES); + } + else if (type2 == JSElementTypes.BLOCK_STATEMENT) { + setBraceSpace(mySettings.SPACE_BEFORE_METHOD_LBRACE, mySettings.METHOD_BRACE_STYLE, myChild1.getTextRange()); + } + else if (type1 == JSElementTypes.ATTRIBUTE_LIST && type2 == JSTokenTypes.FUNCTION_KEYWORD) { + setSingleSpace(true); + } + } + + @Override + public void visitFunctionExpression(ASTNode node) { + visitFunctionDeclaration(node); + } + + @Override + public void visitReferenceExpression(ASTNode node) { + if (type1 == JSTokenTypes.NEW_KEYWORD) { + setSingleSpace(true); + } + else { + setSingleSpace(false); // a.b should not have spaces before and after dot + } + } + + @Override + public void visitDocComment(ASTNode node) { + //myResult = Spacing.createKeepingFirstColumnSpacing( + // 0, + // Integer.MAX_VALUE, + // mySettings.KEEP_LINE_BREAKS, + // mySettings.KEEP_BLANK_LINES_IN_CODE + //); + } + + @Override + public void visitIfStatement(ASTNode node) { + if (type1 == JSTokenTypes.IF_KEYWORD && type2 == JSTokenTypes.LPAR) { + setSingleSpace(mySettings.SPACE_BEFORE_IF_PARENTHESES); + } + else if (type1 == JSTokenTypes.LPAR || type2 == JSTokenTypes.RPAR) { + setSingleSpace(mySettings.SPACE_WITHIN_IF_PARENTHESES); + } + else if (type1 == JSTokenTypes.RPAR && type2 == JSElementTypes.BLOCK_STATEMENT) { + TextRange dependentRange = new TextRange(myParent.getStartOffset(), myChild1.getTextRange().getEndOffset()); + setBraceSpace(mySettings.SPACE_BEFORE_IF_LBRACE, mySettings.BRACE_STYLE, dependentRange); + } + else if (type2 == JSTokenTypes.ELSE_KEYWORD) { + setLineBreakSpace(mySettings.ELSE_ON_NEW_LINE); + } + else if (type1 == JSTokenTypes.ELSE_KEYWORD && type2 == JSElementTypes.BLOCK_STATEMENT) { + setBraceSpace(mySettings.SPACE_BEFORE_ELSE_LBRACE, mySettings.BRACE_STYLE, null); + } + } + + @Override + public void visitCallExpression(ASTNode node) { + if (type2 == JSElementTypes.ARGUMENT_LIST) { + setSingleSpace(mySettings.SPACE_BEFORE_METHOD_CALL_PARENTHESES); + } + } + + @Override + public void visitNewExpression(ASTNode node) { + if (type1 == JSTokenTypes.NEW_KEYWORD) { + setSingleSpace(true); + } + else if (type2 == JSElementTypes.ARGUMENT_LIST) { + setSingleSpace(mySettings.SPACE_BEFORE_METHOD_CALL_PARENTHESES); + } + } + + @Override + public void visitForStatement(ASTNode node) { + if (type1 == JSTokenTypes.SEMICOLON) { + setSingleSpace(true); + } + else if (type2 == JSTokenTypes.SEMICOLON) { + setSingleSpace(mySettings.SPACE_BEFORE_SEMICOLON); + } + + if (type1 == JSTokenTypes.FOR_KEYWORD && type2 == JSTokenTypes.LPAR) { + setSingleSpace(mySettings.SPACE_BEFORE_FOR_PARENTHESES); + } + else if (type1 == JSTokenTypes.RPAR && type2 == JSElementTypes.BLOCK_STATEMENT) { + TextRange dependentRange = new TextRange(myParent.getStartOffset(), myChild1.getTextRange().getEndOffset()); + setBraceSpace(mySettings.SPACE_BEFORE_FOR_LBRACE, mySettings.BRACE_STYLE, dependentRange); + } + else if (type1 == JSTokenTypes.LPAR || type2 == JSTokenTypes.RPAR) { + setSingleSpace(mySettings.SPACE_WITHIN_FOR_PARENTHESES); + } + } + + @Override + public void visitDoWhileStatement(ASTNode node) { + if (type2 == JSTokenTypes.WHILE_KEYWORD) { + if (mySettings.WHILE_ON_NEW_LINE) { + myResult = Spacing.createSpacing( + 0, + 0, + 1, + mySettings.KEEP_LINE_BREAKS, + mySettings.KEEP_BLANK_LINES_IN_CODE + ); + } + else { + myResult = Spacing.createSpacing( + 1, + 1, + 0, + mySettings.KEEP_LINE_BREAKS, + mySettings.KEEP_BLANK_LINES_IN_CODE + ); + } + } + else if (type2 == JSTokenTypes.LPAR) { + setSingleSpace(mySettings.SPACE_BEFORE_WHILE_PARENTHESES); + } + else if (type1 == JSTokenTypes.LPAR || type2 == JSTokenTypes.RPAR) { + setSingleSpace(mySettings.SPACE_WITHIN_WHILE_PARENTHESES); + } + + if (type1 == JSTokenTypes.DO_KEYWORD && type2 == JSElementTypes.BLOCK_STATEMENT) { + setBraceSpace(true, mySettings.BRACE_STYLE, null); + } + } + + @Override + public void visitForInStatement(ASTNode node) { + if (type1 == JSTokenTypes.VAR_KEYWORD || type2 == JSTokenTypes.VAR_KEYWORD) { + setSingleSpace(true); + } + else if (type1 == JSTokenTypes.FOR_KEYWORD && type2 == JSTokenTypes.LPAR) { + setSingleSpace(mySettings.SPACE_BEFORE_FOR_PARENTHESES); + } + else if (type1 == JSTokenTypes.RPAR && type2 == JSElementTypes.BLOCK_STATEMENT) { + TextRange dependentRange = new TextRange(myParent.getStartOffset(), myChild1.getTextRange().getEndOffset()); + setBraceSpace(mySettings.SPACE_BEFORE_FOR_LBRACE, mySettings.BRACE_STYLE, dependentRange); + } + else if (type1 == JSTokenTypes.LPAR || type2 == JSTokenTypes.RPAR) { + setSingleSpace(mySettings.SPACE_WITHIN_FOR_PARENTHESES); + } + } + + @Override + public void visitWhileStatement(ASTNode node) { + if (type1 == JSTokenTypes.WHILE_KEYWORD && type2 == JSTokenTypes.LPAR) { + setSingleSpace(mySettings.SPACE_BEFORE_WHILE_PARENTHESES); + } + else if (type1 == JSTokenTypes.RPAR && type2 == JSElementTypes.BLOCK_STATEMENT) { + TextRange dependentRange = new TextRange(myParent.getStartOffset(), myChild1.getTextRange().getEndOffset()); + setBraceSpace(mySettings.SPACE_BEFORE_WHILE_LBRACE, mySettings.BRACE_STYLE, dependentRange); + } + else if (type1 == JSTokenTypes.LPAR || type2 == JSTokenTypes.RPAR) { + setSingleSpace(mySettings.SPACE_WITHIN_WHILE_PARENTHESES); + } + } + + @Override + public void visitWithStatement(ASTNode node) { + if (type1 == JSTokenTypes.WITH_KEYWORD && type2 == JSTokenTypes.LPAR) { + setSingleSpace(mySettings.SPACE_BEFORE_WHILE_PARENTHESES); + } + else if (type1 == JSTokenTypes.RPAR && type2 == JSElementTypes.BLOCK_STATEMENT) { + TextRange dependentRange = new TextRange(myParent.getStartOffset(), myChild1.getTextRange().getEndOffset()); + setBraceSpace(mySettings.SPACE_BEFORE_WHILE_LBRACE, mySettings.BRACE_STYLE, dependentRange); + } + else if (type1 == JSTokenTypes.LPAR || type2 == JSTokenTypes.RPAR) { + setSingleSpace(mySettings.SPACE_WITHIN_WHILE_PARENTHESES); + } + } + + public static TokenSet NOT_A_PACKAGE_CONTENT = TokenSet.create(JSTokenTypes.PACKAGE_KEYWORD, JSElementTypes.REFERENCE_EXPRESSION, + JSTokenTypes.LBRACE, JSTokenTypes.RBRACE + ); + + @Override + public void visitTryStatement(ASTNode node) { + if (type1 == JSTokenTypes.TRY_KEYWORD && type2 == JSElementTypes.BLOCK_STATEMENT) { + setBraceSpace(mySettings.SPACE_BEFORE_TRY_LBRACE, mySettings.BRACE_STYLE, null); + } + else if (type2 == JSElementTypes.CATCH_BLOCK) { + setLineBreakSpace(mySettings.CATCH_ON_NEW_LINE); + } + else if (type2 == JSTokenTypes.FINALLY_KEYWORD) { + setLineBreakSpace(mySettings.FINALLY_ON_NEW_LINE); + } + else if (type1 == JSTokenTypes.FINALLY_KEYWORD) { + setBraceSpace(mySettings.SPACE_BEFORE_FINALLY_LBRACE, mySettings.BRACE_STYLE, null); + } + } + + @Override + public void visitCatchBlock(ASTNode node) { + if (type1 == JSTokenTypes.LPAR || type2 == JSTokenTypes.RPAR) { + setSingleSpace(mySettings.SPACE_WITHIN_CATCH_PARENTHESES); + } + + if (type1 == JSTokenTypes.CATCH_KEYWORD && type2 == JSTokenTypes.LPAR) { + setSingleSpace(mySettings.SPACE_BEFORE_CATCH_PARENTHESES); + } + + if (type2 == JSElementTypes.BLOCK_STATEMENT) { + TextRange dependentRange = new TextRange(myParent.getStartOffset(), myChild2.getTextRange().getStartOffset()); + setBraceSpace(mySettings.SPACE_BEFORE_CATCH_LBRACE, mySettings.BRACE_STYLE, dependentRange); + } + } + + @Override + public void visitSwitchStatement(ASTNode node) { + if (type1 == JSTokenTypes.SWITCH_KEYWORD && type2 == JSTokenTypes.LPAR) { + setSingleSpace(mySettings.SPACE_BEFORE_SWITCH_PARENTHESES); + } + else if (type1 == JSTokenTypes.RPAR) { + TextRange dependentRange = new TextRange(myParent.getStartOffset(), myChild1.getTextRange().getEndOffset()); + setBraceSpace(mySettings.SPACE_BEFORE_SWITCH_LBRACE, mySettings.BRACE_STYLE, dependentRange); + } + else if (type1 == JSTokenTypes.LPAR || type2 == JSTokenTypes.RPAR) { + setSingleSpace(mySettings.SPACE_WITHIN_SWITCH_PARENTHESES); + } + } + + @Override + public void visitArgumentList(ASTNode node) { + if (type1 == JSTokenTypes.LPAR || type2 == JSTokenTypes.RPAR) { + setSingleSpace(false); + } + else if (type1 == JSTokenTypes.COMMA) { + setSingleSpace(mySettings.SPACE_AFTER_COMMA); + } + else if (type2 == JSTokenTypes.COMMA) { + setSingleSpace(mySettings.SPACE_BEFORE_COMMA); + } + } + + @Override + public void visitStatement(ASTNode node) { + if (type2 == JSTokenTypes.SEMICOLON) { + setSingleSpace(false); + } + } + + @Override + public void visitVarStatement(ASTNode node) { + if (type1 == JSTokenTypes.VAR_KEYWORD) { + setSingleSpace(true); + } + } + + @Override + public void visitVariable(ASTNode node) { + if (type1 == JSTokenTypes.EQ || type2 == JSTokenTypes.EQ) { // Initializer + setSingleSpace(mySettings.SPACE_AROUND_ASSIGNMENT_OPERATORS); + } + } + + @Override + public void visitBinaryExpression(ASTNode node) { + IElementType opSign = null; + if (JSTokenTypes.OPERATIONS.contains(type1)) { + opSign = type1; + } + else if (JSTokenTypes.OPERATIONS.contains(type2)) { + opSign = type2; + } + + if (opSign != null) { + setSingleSpace(getSpaceAroundOption(opSign)); + } + } + + @Override + public void visitConditionalExpression(ASTNode node) { + if (type1 == JSTokenTypes.QUEST) { + setSingleSpace(mySettings.SPACE_AFTER_QUEST); + } + else if (type2 == JSTokenTypes.QUEST) { + setSingleSpace(mySettings.SPACE_BEFORE_QUEST); + } + else if (type1 == JSTokenTypes.COLON) { + setSingleSpace(mySettings.SPACE_AFTER_COLON); + } + else if (type2 == JSTokenTypes.COLON) { + setSingleSpace(mySettings.SPACE_BEFORE_COLON); + } + } + + private boolean getSpaceAroundOption(IElementType opSign) { + boolean option = false; + if (JSTokenTypes.ADDITIVE_OPERATIONS.contains(opSign)) { + option = mySettings.SPACE_AROUND_ADDITIVE_OPERATORS; + } + else if (JSTokenTypes.MULTIPLICATIVE_OPERATIONS.contains(opSign)) { + option = mySettings.SPACE_AROUND_MULTIPLICATIVE_OPERATORS; + } + else if (JSTokenTypes.ASSIGNMENT_OPERATIONS.contains(opSign)) { + option = mySettings.SPACE_AROUND_ASSIGNMENT_OPERATORS; + } + else if (JSTokenTypes.EQUALITY_OPERATIONS.contains(opSign)) { + option = mySettings.SPACE_AROUND_EQUALITY_OPERATORS; + } + else if (JSTokenTypes.RELATIONAL_OPERATIONS.contains(opSign)) { + option = mySettings.SPACE_AROUND_RELATIONAL_OPERATORS; + } + else if (JSTokenTypes.SHIFT_OPERATIONS.contains(opSign)) { + option = mySettings.SPACE_AROUND_BITWISE_OPERATORS; + } + else if (opSign == JSTokenTypes.ANDAND || opSign == JSTokenTypes.OROR) { + option = mySettings.SPACE_AROUND_LOGICAL_OPERATORS; + } + else if (opSign == JSTokenTypes.OR || opSign == JSTokenTypes.AND || opSign == JSTokenTypes.XOR) { + option = mySettings.SPACE_AROUND_BITWISE_OPERATORS; + } + else if (opSign == JSTokenTypes.IS_KEYWORD || opSign == JSTokenTypes.AS_KEYWORD) { + option = true; + } + return option; + } + + private void setSingleSpace(boolean needSpace) { + int spaces = needSpace ? 1 : 0; + myResult = Spacing.createSpacing(spaces, spaces, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); + } + + private void setBraceSpace(boolean needSpaceSetting, int braceStyleSetting, TextRange textRange) { + int spaces = needSpaceSetting ? 1 : 0; + if (braceStyleSetting == CodeStyleSettings.NEXT_LINE_IF_WRAPPED && textRange != null) { + myResult = Spacing.createDependentLFSpacing( + spaces, + spaces, + textRange, + mySettings.KEEP_LINE_BREAKS, + mySettings.KEEP_BLANK_LINES_IN_CODE + ); + } + else { + int lineBreaks = braceStyleSetting == CodeStyleSettings.END_OF_LINE ? 0 : 1; + myResult = Spacing.createSpacing(spaces, spaces, lineBreaks, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); + } + } + + private void setLineBreakSpace(boolean needLineBreak) { + int breaks = needLineBreak || myChild1.getElementType() == JSTokenTypes.END_OF_LINE_COMMENT ? 1 : 0; + myResult = Spacing.createSpacing(1, 1, breaks, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JavaScriptIndentOptionsProvider.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JavaScriptIndentOptionsProvider.java index de4f6919..229ede1c 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JavaScriptIndentOptionsProvider.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JavaScriptIndentOptionsProvider.java @@ -24,41 +24,37 @@ import consulo.language.codeStyle.ui.setting.SmartIndentOptionsEditor; import consulo.language.psi.PsiFile; import consulo.virtualFileSystem.fileType.FileType; +import jakarta.annotation.Nonnull; /** * @author yole */ @ExtensionImpl -public class JavaScriptIndentOptionsProvider implements FileTypeIndentOptionsProvider -{ - @Override - public CodeStyleSettings.IndentOptions createIndentOptions() - { - return new CodeStyleSettings.IndentOptions(); - } +public class JavaScriptIndentOptionsProvider implements FileTypeIndentOptionsProvider { + @Override + public CodeStyleSettings.IndentOptions createIndentOptions() { + return new CodeStyleSettings.IndentOptions(); + } - @Override - public FileType getFileType() - { - return JavaScriptFileType.INSTANCE; - } + @Override + public FileType getFileType() { + return JavaScriptFileType.INSTANCE; + } - @Override - public IndentOptionsEditor createOptionsEditor() - { - return new SmartIndentOptionsEditor(); - } + @Override + public IndentOptionsEditor createOptionsEditor() { + return new SmartIndentOptionsEditor(); + } - @Override - public String getPreviewText() - { - return "function a() {\n" + - " alert(\"test\");\n" + - "}"; - } + @Nonnull + @Override + public String getPreviewText() { + return "function a() {\n" + + " alert(\"test\");\n" + + "}"; + } - @Override - public void prepareForReformat(final PsiFile psiFile) - { - } + @Override + public void prepareForReformat(PsiFile psiFile) { + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JavascriptFormattingModelBuilder.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JavascriptFormattingModelBuilder.java index cb573b42..53c0eb3b 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JavascriptFormattingModelBuilder.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/JavascriptFormattingModelBuilder.java @@ -28,30 +28,37 @@ import consulo.language.psi.PsiElement; import consulo.language.psi.PsiFile; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; @ExtensionImpl -public class JavascriptFormattingModelBuilder implements FormattingModelBuilder -{ - @Nonnull - public FormattingModel createModel(@Nonnull FormattingContext formattingContext) - { - PsiElement element = formattingContext.getPsiElement(); +public class JavascriptFormattingModelBuilder implements FormattingModelBuilder { + @Nonnull + @Override + public FormattingModel createModel(@Nonnull FormattingContext formattingContext) { + PsiElement element = formattingContext.getPsiElement(); - CodeStyleSettings settings = formattingContext.getCodeStyleSettings(); + CodeStyleSettings settings = formattingContext.getCodeStyleSettings(); - final PsiFile psiFile = element.getContainingFile(); + PsiFile psiFile = element.getContainingFile(); - CommonCodeStyleSettings commonSettings = settings.getCommonSettings(JavaScriptLanguage.INSTANCE); + CommonCodeStyleSettings commonSettings = settings.getCommonSettings(JavaScriptLanguage.INSTANCE); - return new JSFormattingModel(psiFile, settings, new JSBlock(psiFile instanceof JSFile ? psiFile.getNode() : element.getNode(), null, null, null, commonSettings)); + return new JSFormattingModel( + psiFile, + settings, + new JSBlock( + psiFile instanceof JSFile jsFile ? jsFile.getNode() : element.getNode(), + null, + null, + null, + commonSettings + ) + ); + } - } - - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/blocks/JSBlock.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/blocks/JSBlock.java index c2b7a9d6..66f3a0db 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/blocks/JSBlock.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/blocks/JSBlock.java @@ -16,6 +16,7 @@ package com.intellij.lang.javascript.impl.formatter.blocks; +import consulo.annotation.access.RequiredReadAction; import consulo.document.util.TextRange; import consulo.language.ast.ASTNode; import com.intellij.lang.javascript.JSElementTypes; @@ -28,201 +29,173 @@ import consulo.language.psi.PsiErrorElement; import consulo.language.psi.PsiWhiteSpace; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; + import java.util.List; /** * @author ven */ -public class JSBlock implements Block -{ - private ASTNode myNode; - - private final CommonCodeStyleSettings mySettings; - - private Alignment myAlignment; - private Indent myIndent; - private Wrap myWrap; - private List mySubBlocks = null; - - public JSBlock(final ASTNode node, final Alignment alignment, final Indent indent, final Wrap wrap, final CommonCodeStyleSettings settings) - { - myAlignment = alignment; - myIndent = indent; - myNode = node; - myWrap = wrap; - mySettings = settings; - } - - public ASTNode getNode() - { - return myNode; - } - - @Override - @Nonnull - public TextRange getTextRange() - { - return myNode.getTextRange(); - } - - @Override - @Nonnull - public List getSubBlocks() - { - if(mySubBlocks == null) - { - SubBlockVisitor visitor = new SubBlockVisitor(getSettings()); - visitor.visit(myNode); - mySubBlocks = visitor.getBlocks(); - } - return mySubBlocks; - } - - @Override - @Nullable - public Wrap getWrap() - { - return myWrap; - } - - @Override - @Nullable - public Indent getIndent() - { - return myIndent; - } - - @Override - @Nullable - public Alignment getAlignment() - { - return myAlignment; - } - - @Override - @Nullable - public Spacing getSpacing(Block child1, Block child2) - { - if(child1 instanceof JSDocCommentBlock || child2 instanceof JSDocCommentBlock || child1 == null) - { - return null; - } - return new JSSpacingProcessor(getNode(), ((JSBlock) child1).getNode(), ((JSBlock) child2).getNode(), mySettings).getResult(); - } - - @Override - @Nonnull - public ChildAttributes getChildAttributes(final int newChildIndex) - { - Indent indent = null; - final IElementType blockElementType = myNode.getElementType(); - - if(blockElementType == JSTokenTypes.DOC_COMMENT) - { - return new ChildAttributes(Indent.getSpaceIndent(1), null); - } - - if(blockElementType == JSElementTypes.PACKAGE_STATEMENT) - { - final JSCodeStyleSettings customSettings = CodeStyleSettingsManager.getSettings(myNode.getPsi().getProject()).getCustomSettings - (JSCodeStyleSettings.class); - if(customSettings.INDENT_PACKAGE_CHILDREN == JSCodeStyleSettings.INDENT) - { - indent = Indent.getNormalIndent(); - } - else - { - indent = Indent.getNoneIndent(); - } - } - else if(blockElementType == JSElementTypes.BLOCK_STATEMENT || - blockElementType == JSElementTypes.CLASS || - blockElementType == JSElementTypes.OBJECT_LITERAL_EXPRESSION) - { - indent = Indent.getNormalIndent(); - } - else if(blockElementType instanceof JSFileElementType || blockElementType == JSElementTypes.EMBEDDED_CONTENT) - { - indent = Indent.getNoneIndent(); - } - else if(JSElementTypes.SOURCE_ELEMENTS.contains(blockElementType) || - blockElementType == JSElementTypes.FUNCTION_EXPRESSION || - blockElementType == JSElementTypes.ATTRIBUTE_LIST) - { - indent = Indent.getNoneIndent(); - } - - Alignment alignment = null; - final List subBlocks = getSubBlocks(); - for(int i = 0; i < newChildIndex; i++) - { - if(i == subBlocks.size()) - { - break; - } - final Alignment childAlignment = subBlocks.get(i).getAlignment(); - if(childAlignment != null) - { - alignment = childAlignment; - break; - } - } - - // in for loops, alignment is required only for items within parentheses - if(blockElementType == JSElementTypes.FOR_STATEMENT || blockElementType == JSElementTypes.FOR_IN_STATEMENT) - { - for(int i = 0; i < newChildIndex; i++) - { - if(((JSBlock) subBlocks.get(i)).getNode().getElementType() == JSTokenTypes.RPAR) - { - alignment = null; - break; - } - } - } - - return new ChildAttributes(indent, alignment); - } - - @Override - public boolean isIncomplete() - { - return isIncomplete(myNode); - } - - private boolean isIncomplete(ASTNode node) - { - node.getPsi().getFirstChild(); // expand chameleon - ASTNode lastChild = node.getLastChildNode(); - while(lastChild != null && lastChild.getPsi() instanceof PsiWhiteSpace) - { - lastChild = lastChild.getTreePrev(); - } - if(lastChild == null) - { - return false; - } - if(lastChild.getPsi() instanceof PsiErrorElement) - { - return true; - } - return isIncomplete(lastChild); - } - - public CommonCodeStyleSettings getSettings() - { - return mySettings; - } - - @Override - public boolean isLeaf() - { - if(myNode.getElementType() == JSTokenTypes.DOC_COMMENT) - { - return false; - } - return myNode.getFirstChildNode() == null; - } +public class JSBlock implements Block { + private ASTNode myNode; + + private final CommonCodeStyleSettings mySettings; + + private Alignment myAlignment; + private Indent myIndent; + private Wrap myWrap; + private List mySubBlocks = null; + + public JSBlock( + ASTNode node, + Alignment alignment, + Indent indent, + Wrap wrap, + CommonCodeStyleSettings settings + ) { + myAlignment = alignment; + myIndent = indent; + myNode = node; + myWrap = wrap; + mySettings = settings; + } + + public ASTNode getNode() { + return myNode; + } + + @Override + @Nonnull + public TextRange getTextRange() { + return myNode.getTextRange(); + } + + @Override + @Nonnull + public List getSubBlocks() { + if (mySubBlocks == null) { + SubBlockVisitor visitor = new SubBlockVisitor(getSettings()); + visitor.visit(myNode); + mySubBlocks = visitor.getBlocks(); + } + return mySubBlocks; + } + + @Override + @Nullable + public Wrap getWrap() { + return myWrap; + } + + @Override + @Nullable + public Indent getIndent() { + return myIndent; + } + + @Override + @Nullable + public Alignment getAlignment() { + return myAlignment; + } + + @Override + @Nullable + public Spacing getSpacing(Block child1, Block child2) { + if (child1 instanceof JSDocCommentBlock || child2 instanceof JSDocCommentBlock || child1 == null) { + return null; + } + return new JSSpacingProcessor(getNode(), ((JSBlock)child1).getNode(), ((JSBlock)child2).getNode(), mySettings).getResult(); + } + + @Override + @Nonnull + public ChildAttributes getChildAttributes(int newChildIndex) { + Indent indent = null; + IElementType blockElementType = myNode.getElementType(); + + if (blockElementType == JSTokenTypes.DOC_COMMENT) { + return new ChildAttributes(Indent.getSpaceIndent(1), null); + } + + if (blockElementType == JSElementTypes.PACKAGE_STATEMENT) { + JSCodeStyleSettings customSettings = + CodeStyleSettingsManager.getSettings(myNode.getPsi().getProject()).getCustomSettings(JSCodeStyleSettings.class); + if (customSettings.INDENT_PACKAGE_CHILDREN == JSCodeStyleSettings.INDENT) { + indent = Indent.getNormalIndent(); + } + else { + indent = Indent.getNoneIndent(); + } + } + else if (blockElementType == JSElementTypes.BLOCK_STATEMENT + || blockElementType == JSElementTypes.CLASS + || blockElementType == JSElementTypes.OBJECT_LITERAL_EXPRESSION) { + indent = Indent.getNormalIndent(); + } + else if (blockElementType instanceof JSFileElementType || blockElementType == JSElementTypes.EMBEDDED_CONTENT) { + indent = Indent.getNoneIndent(); + } + else if (JSElementTypes.SOURCE_ELEMENTS.contains(blockElementType) + || blockElementType == JSElementTypes.FUNCTION_EXPRESSION + || blockElementType == JSElementTypes.ATTRIBUTE_LIST) { + indent = Indent.getNoneIndent(); + } + + Alignment alignment = null; + List subBlocks = getSubBlocks(); + for (int i = 0; i < newChildIndex; i++) { + if (i == subBlocks.size()) { + break; + } + Alignment childAlignment = subBlocks.get(i).getAlignment(); + if (childAlignment != null) { + alignment = childAlignment; + break; + } + } + + // in for loops, alignment is required only for items within parentheses + if (blockElementType == JSElementTypes.FOR_STATEMENT || blockElementType == JSElementTypes.FOR_IN_STATEMENT) { + for (int i = 0; i < newChildIndex; i++) { + if (((JSBlock)subBlocks.get(i)).getNode().getElementType() == JSTokenTypes.RPAR) { + alignment = null; + break; + } + } + } + + return new ChildAttributes(indent, alignment); + } + + @Override + @RequiredReadAction + public boolean isIncomplete() { + return isIncomplete(myNode); + } + + @RequiredReadAction + private boolean isIncomplete(ASTNode node) { + node.getPsi().getFirstChild(); // expand chameleon + ASTNode lastChild = node.getLastChildNode(); + while (lastChild != null && lastChild.getPsi() instanceof PsiWhiteSpace) { + lastChild = lastChild.getTreePrev(); + } + + if (lastChild == null) { + return false; + } + + return lastChild.getPsi() instanceof PsiErrorElement || isIncomplete(lastChild); + } + + public CommonCodeStyleSettings getSettings() { + return mySettings; + } + + @Override + public boolean isLeaf() { + return myNode.getElementType() != JSTokenTypes.DOC_COMMENT && myNode.getFirstChildNode() == null; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/blocks/JSDocCommentBlock.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/blocks/JSDocCommentBlock.java index 33247c74..cfb29528 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/blocks/JSDocCommentBlock.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/blocks/JSDocCommentBlock.java @@ -16,97 +16,81 @@ package com.intellij.lang.javascript.impl.formatter.blocks; +import consulo.document.util.TextRange; +import consulo.language.ast.ASTNode; +import consulo.language.codeStyle.*; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; + import java.util.ArrayList; import java.util.List; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import consulo.language.codeStyle.Alignment; -import consulo.language.codeStyle.Block; -import consulo.language.codeStyle.Indent; -import consulo.language.codeStyle.Spacing; -import consulo.language.codeStyle.Wrap; -import consulo.language.ast.ASTNode; -import consulo.document.util.TextRange; -import consulo.language.codeStyle.ChildAttributes; - /** * @author yole */ -public class JSDocCommentBlock implements Block -{ - private ASTNode myNode; - private int myStartOffset; - private int myEndOffset; - private Indent myIndent; - private static final List EMPTY_BLOCK_LIST = new ArrayList(); +public class JSDocCommentBlock implements Block { + private ASTNode myNode; + private int myStartOffset; + private int myEndOffset; + private Indent myIndent; + private static final List EMPTY_BLOCK_LIST = new ArrayList<>(); - public JSDocCommentBlock(final ASTNode node, final int startOffset, final int endOffset, final Indent indent) - { - myNode = node; - myStartOffset = startOffset; - myEndOffset = endOffset; - myIndent = indent; - } + public JSDocCommentBlock(ASTNode node, int startOffset, int endOffset, Indent indent) { + myNode = node; + myStartOffset = startOffset; + myEndOffset = endOffset; + myIndent = indent; + } - @Override - @Nonnull - public TextRange getTextRange() - { - return new TextRange(myNode.getStartOffset() + myStartOffset, myNode.getStartOffset() + myEndOffset); - } + @Nonnull + @Override + public TextRange getTextRange() { + return new TextRange(myNode.getStartOffset() + myStartOffset, myNode.getStartOffset() + myEndOffset); + } - @Override - @Nonnull - public List getSubBlocks() - { - return EMPTY_BLOCK_LIST; - } + @Nonnull + @Override + public List getSubBlocks() { + return EMPTY_BLOCK_LIST; + } - @Override - @Nullable - public Wrap getWrap() - { - return null; - } + @Nullable + @Override + public Wrap getWrap() { + return null; + } - @Override - @Nullable - public Indent getIndent() - { - return myIndent; - } + @Nonnull + @Override + public Indent getIndent() { + return myIndent; + } - @Override - @Nullable - public Alignment getAlignment() - { - return null; - } + @Nullable + @Override + public Alignment getAlignment() { + return null; + } - @Override - @Nullable - public Spacing getSpacing(Block child1, Block child2) - { - return null; - } + @Nullable + @Override + public Spacing getSpacing(Block child1, @Nonnull Block child2) { + return null; + } - @Override - @Nonnull - public ChildAttributes getChildAttributes(final int newChildIndex) - { - return null; - } + @Nonnull + @Override + public ChildAttributes getChildAttributes(int newChildIndex) { + return new ChildAttributes(null, null); + } - @Override - public boolean isIncomplete() - { - return false; - } + @Override + public boolean isIncomplete() { + return false; + } - @Override - public boolean isLeaf() - { - return true; - } + @Override + public boolean isLeaf() { + return true; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/blocks/SubBlockVisitor.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/blocks/SubBlockVisitor.java index 16835acb..18aff29c 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/blocks/SubBlockVisitor.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/formatter/blocks/SubBlockVisitor.java @@ -29,394 +29,320 @@ import consulo.language.ast.IElementType; import consulo.annotation.access.RequiredReadAction; import consulo.language.psi.PsiElement; +import jakarta.annotation.Nullable; -import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; /** * @author ven */ -public class SubBlockVisitor extends JSNodeVisitor -{ - private final List myBlocks = new ArrayList<>(); - private final CommonCodeStyleSettings mySettings; - - public SubBlockVisitor(CommonCodeStyleSettings settings) - { - mySettings = settings; - } - - public List getBlocks() - { - return myBlocks; - } - - @Override - @RequiredReadAction - public void visitElement(final ASTNode node) - { - Alignment alignment = getDefaultAlignment(node); - - PsiElement elt = node.getPsi().getFirstChild(); // expand chameleon - - while(elt != null) - { - final ASTNode child = elt.getNode(); - assert child != null; - - if(child.getElementType() != JSTokenTypes.WHITE_SPACE && child.getTextRange().getLength() > 0) - { - Wrap wrap = getWrap(node, child); - Alignment childAlignment = alignmentProjection(alignment, node, child); - Indent childIndent = getIndent(node, child); - myBlocks.add(new JSBlock(child, childAlignment, childIndent, wrap, mySettings)); - } - - elt = elt.getNextSibling(); // expand chameleon - } - } - - - @Override - public void visitDocComment(final ASTNode node) - { - final ASTNode child = node.getFirstChildNode(); - if(child != null && child.getElementType() == JSTokenTypes.DOC_COMMENT) - { - visit(child); - } - else - { - super.visitDocComment(node); - } - } - - @Override - public void visitComment(final ASTNode node) - { - buildCommentBlocks(node); - } - - private void buildCommentBlocks(final ASTNode node) - { - String commentText = node.getText(); - int pos = 0; - while(pos < commentText.length()) - { - int nextPos = commentText.indexOf('\n', pos); - if(nextPos < 0) - { - nextPos = commentText.length(); - } - - if(pos != nextPos) - { - final Indent childIndent = (pos == 0) ? Indent.getNoneIndent() : Indent.getSpaceIndent(1); - myBlocks.add(new JSDocCommentBlock(node, pos, nextPos, childIndent)); - } - pos = nextPos + 1; - while(pos < commentText.length() && (commentText.charAt(pos) == ' ' || - commentText.charAt(pos) == '\t' || - commentText.charAt(pos) == '\n')) - { - pos++; - } - } - } - - @Nullable - static Alignment getDefaultAlignment(final ASTNode node) - { - if(node.getElementType() == JSElementTypes.FOR_STATEMENT || - node.getElementType() == JSElementTypes.PARAMETER_LIST || - node.getElementType() == JSElementTypes.BINARY_EXPRESSION || - node.getElementType() == JSElementTypes.ASSIGNMENT_EXPRESSION || - node.getElementType() == JSElementTypes.CONDITIONAL_EXPRESSION) - { - return Alignment.createAlignment(); - } - - return null; - } - - @Nullable - private Indent getIndent(final ASTNode node, final ASTNode child) - { - final IElementType nodeElementType = node.getElementType(); - - if(nodeElementType instanceof JSFileElementType || nodeElementType == JSElementTypes.EMBEDDED_CONTENT) - { - return Indent.getNoneIndent(); - } - - if(nodeElementType == JSTokenTypes.DOC_COMMENT) - { - final ASTNode treePrev = child.getTreePrev(); - if(treePrev != null && treePrev.getPsi() instanceof PsiWhiteSpace && treePrev.getText().indexOf("\n") != -1) - { - return Indent.getSpaceIndent(1); - } - return Indent.getNoneIndent(); - } - - final IElementType childElementType = child.getElementType(); - - if(nodeElementType == JSElementTypes.PACKAGE_STATEMENT && !JSSpacingProcessor.NOT_A_PACKAGE_CONTENT.contains(childElementType)) - { - final JSCodeStyleSettings customSettings = CodeStyleSettingsManager.getSettings(node.getPsi().getProject()).getCustomSettings(JSCodeStyleSettings - .class); - if(customSettings.INDENT_PACKAGE_CHILDREN == JSCodeStyleSettings.INDENT) - { - return Indent.getNormalIndent(); - } - return Indent.getNoneIndent(); - } - - if(nodeElementType == JSElementTypes.ATTRIBUTE_LIST) - { - return Indent.getNoneIndent(); - } - - if(childElementType == JSElementTypes.BLOCK_STATEMENT) - { - if(nodeElementType == JSElementTypes.FUNCTION_DECLARATION && (mySettings.METHOD_BRACE_STYLE == CodeStyleSettings.NEXT_LINE_SHIFTED || mySettings - .METHOD_BRACE_STYLE == CodeStyleSettings.NEXT_LINE_SHIFTED2)) - { - return Indent.getNormalIndent(); - } - if(mySettings.BRACE_STYLE == CodeStyleSettings.NEXT_LINE_SHIFTED || mySettings.BRACE_STYLE == CodeStyleSettings.NEXT_LINE_SHIFTED2) - { - return Indent.getNormalIndent(); - } - return Indent.getNoneIndent(); - } - - if(childElementType == JSElementTypes.CATCH_BLOCK) - { - return Indent.getNoneIndent(); - } - - if(childElementType == JSElementTypes.CASE_CLAUSE) - { - return mySettings.INDENT_CASE_FROM_SWITCH ? Indent.getNormalIndent() : Indent.getNoneIndent(); - } - - if(nodeElementType == JSElementTypes.CASE_CLAUSE) - { - if(child.getPsi() instanceof JSStatement || JSTokenTypes.COMMENTS.contains(childElementType)) - { - return Indent.getNormalIndent(); - } - return Indent.getNoneIndent(); - } - - if(nodeElementType == JSElementTypes.SWITCH_STATEMENT && (childElementType == JSTokenTypes.LBRACE || childElementType == JSTokenTypes.RBRACE)) - { - return Indent.getNoneIndent(); - } - - if(nodeElementType == JSElementTypes.IF_STATEMENT) - { - return Indent.getNoneIndent(); - } - - if(nodeElementType == JSElementTypes.WITH_STATEMENT && JSElementTypes.SOURCE_ELEMENTS.contains(childElementType)) - { - return Indent.getNormalIndent(); - } - - if(nodeElementType == JSElementTypes.DOWHILE_STATEMENT && childElementType == JSTokenTypes.WHILE_KEYWORD) - { - return Indent.getNoneIndent(); - } - - if(nodeElementType == JSElementTypes.TRY_STATEMENT && childElementType == JSTokenTypes.FINALLY_KEYWORD) - { - return Indent.getNoneIndent(); - } - - if(nodeElementType == JSElementTypes.BLOCK_STATEMENT || - nodeElementType == JSElementTypes.CLASS || - nodeElementType == JSElementTypes.PACKAGE_STATEMENT) - { - final ASTNode parent = node.getTreeParent(); - if(parent != null && parent.getElementType() == JSElementTypes.FUNCTION_DECLARATION && - mySettings.METHOD_BRACE_STYLE == CodeStyleSettings.NEXT_LINE_SHIFTED) - { - return Indent.getNoneIndent(); - } - if(mySettings.BRACE_STYLE == CodeStyleSettings.NEXT_LINE_SHIFTED) - { - return Indent.getNoneIndent(); - } - if(JSElementTypes.SOURCE_ELEMENTS.contains(childElementType) || JSTokenTypes.COMMENTS.contains(childElementType)) - { - return Indent.getNormalIndent(); - } - return Indent.getNoneIndent(); - } - else if(node.getPsi() instanceof JSLoopStatement) - { - if(child.getPsi() == ((JSLoopStatement) node.getPsi()).getBody()) - { - if(childElementType == JSElementTypes.BLOCK_STATEMENT) - { - return Indent.getNoneIndent(); - } - else - { - return Indent.getNormalIndent(); - } - } - } - - if(JSTokenTypes.COMMENTS.contains(childElementType)) - { - return Indent.getNormalIndent(); - } - if(childElementType == JSElementTypes.OBJECT_LITERAL_EXPRESSION) - { - return nodeElementType == JSElementTypes.ARRAY_LITERAL_EXPRESSION ? Indent.getNormalIndent() : Indent.getNoneIndent(); - } - - if(nodeElementType == JSElementTypes.XML_LITERAL_EXPRESSION) - { - return childElementType == JSElementTypes.XML_LITERAL_EXPRESSION ? Indent.getNormalIndent() : Indent.getNoneIndent(); - } - - if(nodeElementType == JSElementTypes.ARRAY_LITERAL_EXPRESSION) - { - if(childElementType == JSTokenTypes.LBRACKET || childElementType == JSTokenTypes.RBRACKET) - { - return Indent.getNoneIndent(); - } - return Indent.getNormalIndent(); - } - - if(nodeElementType == JSElementTypes.EMBEDDED_EXPRESSION) - { - if(childElementType == JSTokenTypes.LBRACE || childElementType == JSTokenTypes.RBRACE) - { - return Indent.getNoneIndent(); - } - return Indent.getNormalIndent(); - } - - if(nodeElementType == JSElementTypes.OBJECT_LITERAL_EXPRESSION) - { - if(childElementType == JSTokenTypes.LBRACE || childElementType == JSTokenTypes.RBRACE) - { - return Indent.getNoneIndent(); - } - return Indent.getNormalIndent(); - } - return null; - } - - @Nullable - private static Alignment alignmentProjection(final Alignment defaultAlignment, final ASTNode parent, final ASTNode child) - { - if(parent.getElementType() == JSElementTypes.FOR_STATEMENT && (JSElementTypes.EXPRESSIONS.contains(child.getElementType()) || child.getElementType - () == JSElementTypes.VAR_STATEMENT)) - { - return defaultAlignment; - } - else if(parent.getElementType() == JSElementTypes.PARAMETER_LIST && child.getElementType() == JSElementTypes.FORMAL_PARAMETER) - { - return defaultAlignment; - } - else if(parent.getPsi() instanceof JSBinaryExpression && JSElementTypes.EXPRESSIONS.contains(child.getElementType())) - { - return defaultAlignment; - } - else if(parent.getElementType() == JSElementTypes.CONDITIONAL_EXPRESSION && JSElementTypes.EXPRESSIONS.contains(child.getElementType())) - { - return defaultAlignment; - } - - return null; - } - - @Nullable - private Wrap getWrap(final ASTNode node, final ASTNode child) - { - WrapType wrapType = null; - if(node.getElementType() == JSElementTypes.ASSIGNMENT_EXPRESSION) - { - final JSAssignmentExpression assignment = (JSAssignmentExpression) node.getPsi(); - if(child.getElementType() == assignment.getOperationSign() && mySettings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE || child.getPsi() == assignment - .getROperand() && !mySettings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) - { - wrapType = WrapType.byLegacyRepresentation(mySettings.ASSIGNMENT_WRAP); - } - } - else if(node.getElementType() == JSElementTypes.BINARY_EXPRESSION) - { - final JSBinaryExpression binary = (JSBinaryExpression) node.getPsi(); - if(child.getElementType() == binary.getOperationSign() && mySettings.BINARY_OPERATION_SIGN_ON_NEXT_LINE || child.getPsi() == binary.getROperand() - && !mySettings.BINARY_OPERATION_SIGN_ON_NEXT_LINE) - { - wrapType = WrapType.byLegacyRepresentation(mySettings.BINARY_OPERATION_WRAP); - } - } - else if(node.getElementType() == JSElementTypes.PARENTHESIZED_EXPRESSION) - { - if(child == node.findChildByType(JSTokenTypes.LPAR) && mySettings.PARENTHESES_EXPRESSION_LPAREN_WRAP) - { - wrapType = WrapType.NORMAL; - } - else if(child == node.findChildByType(JSTokenTypes.RPAR) && mySettings.PARENTHESES_EXPRESSION_RPAREN_WRAP) - { - wrapType = WrapType.ALWAYS; - } - } - else if(node.getElementType() == JSElementTypes.ARRAY_LITERAL_EXPRESSION) - { - if(child == node.findChildByType(JSTokenTypes.LBRACE) && mySettings.ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE) - { - wrapType = WrapType.NORMAL; - } - else if(child == node.findChildByType(JSTokenTypes.RPAR) && mySettings.ARRAY_INITIALIZER_RBRACE_ON_NEXT_LINE) - { - wrapType = WrapType.ALWAYS; - } - } - else if(node.getElementType() == JSElementTypes.CONDITIONAL_EXPRESSION) - { - final IElementType elementType = child.getElementType(); - if((mySettings.TERNARY_OPERATION_SIGNS_ON_NEXT_LINE && (elementType == JSTokenTypes.QUEST || elementType == JSTokenTypes.COLON)) || (!mySettings - .TERNARY_OPERATION_SIGNS_ON_NEXT_LINE && child.getPsi() instanceof JSExpression)) - { - wrapType = WrapType.byLegacyRepresentation(mySettings.TERNARY_OPERATION_WRAP); - } - } - else if(node.getElementType() == JSElementTypes.CALL_EXPRESSION) - { - if(child == node.findChildByType(JSTokenTypes.LPAR) && mySettings.CALL_PARAMETERS_LPAREN_ON_NEXT_LINE) - { - wrapType = WrapType.NORMAL; - } - else if(child == node.findChildByType(JSTokenTypes.RPAR) && mySettings.CALL_PARAMETERS_RPAREN_ON_NEXT_LINE) - { - wrapType = WrapType.ALWAYS; - } - } - else if(node.getElementType() == JSElementTypes.PARAMETER_LIST) - { - if(child.getElementType() == JSElementTypes.FORMAL_PARAMETER) - { - wrapType = WrapType.byLegacyRepresentation(mySettings.METHOD_PARAMETERS_WRAP); - } - } - else if(node.getElementType() == JSElementTypes.FOR_STATEMENT || node.getElementType() == JSElementTypes.FOR_IN_STATEMENT) - { - if(JSElementTypes.EXPRESSIONS.contains(child.getElementType())) - { - wrapType = WrapType.byLegacyRepresentation(mySettings.FOR_STATEMENT_WRAP); - } - } - - return wrapType == null ? null : Wrap.createWrap(wrapType, false); - } +public class SubBlockVisitor extends JSNodeVisitor { + private final List myBlocks = new ArrayList<>(); + private final CommonCodeStyleSettings mySettings; + + public SubBlockVisitor(CommonCodeStyleSettings settings) { + mySettings = settings; + } + + public List getBlocks() { + return myBlocks; + } + + @Override + @RequiredReadAction + public void visitElement(ASTNode node) { + Alignment alignment = getDefaultAlignment(node); + + PsiElement elt = node.getPsi().getFirstChild(); // expand chameleon + + while (elt != null) { + ASTNode child = elt.getNode(); + assert child != null; + + if (child.getElementType() != JSTokenTypes.WHITE_SPACE && child.getTextRange().getLength() > 0) { + Wrap wrap = getWrap(node, child); + Alignment childAlignment = alignmentProjection(alignment, node, child); + Indent childIndent = getIndent(node, child); + myBlocks.add(new JSBlock(child, childAlignment, childIndent, wrap, mySettings)); + } + + elt = elt.getNextSibling(); // expand chameleon + } + } + + + @Override + public void visitDocComment(ASTNode node) { + ASTNode child = node.getFirstChildNode(); + if (child != null && child.getElementType() == JSTokenTypes.DOC_COMMENT) { + visit(child); + } + else { + super.visitDocComment(node); + } + } + + @Override + public void visitComment(ASTNode node) { + buildCommentBlocks(node); + } + + private void buildCommentBlocks(ASTNode node) { + String commentText = node.getText(); + int pos = 0; + while (pos < commentText.length()) { + int nextPos = commentText.indexOf('\n', pos); + if (nextPos < 0) { + nextPos = commentText.length(); + } + + if (pos != nextPos) { + Indent childIndent = (pos == 0) ? Indent.getNoneIndent() : Indent.getSpaceIndent(1); + myBlocks.add(new JSDocCommentBlock(node, pos, nextPos, childIndent)); + } + pos = nextPos + 1; + while (pos < commentText.length() && (commentText.charAt(pos) == ' ' || + commentText.charAt(pos) == '\t' || + commentText.charAt(pos) == '\n')) { + pos++; + } + } + } + + @Nullable + static Alignment getDefaultAlignment(ASTNode node) { + IElementType elementType = node.getElementType(); + if (elementType == JSElementTypes.FOR_STATEMENT + || elementType == JSElementTypes.PARAMETER_LIST + || elementType == JSElementTypes.BINARY_EXPRESSION + || elementType == JSElementTypes.ASSIGNMENT_EXPRESSION + || elementType == JSElementTypes.CONDITIONAL_EXPRESSION) { + return Alignment.createAlignment(); + } + + return null; + } + + @Nullable + @RequiredReadAction + private Indent getIndent(ASTNode node, ASTNode child) { + IElementType nodeElementType = node.getElementType(); + + if (nodeElementType instanceof JSFileElementType || nodeElementType == JSElementTypes.EMBEDDED_CONTENT) { + return Indent.getNoneIndent(); + } + + if (nodeElementType == JSTokenTypes.DOC_COMMENT) { + ASTNode treePrev = child.getTreePrev(); + if (treePrev != null && treePrev.getPsi() instanceof PsiWhiteSpace && treePrev.getText().contains("\n")) { + return Indent.getSpaceIndent(1); + } + return Indent.getNoneIndent(); + } + + IElementType childElementType = child.getElementType(); + + if (nodeElementType == JSElementTypes.PACKAGE_STATEMENT && !JSSpacingProcessor.NOT_A_PACKAGE_CONTENT.contains(childElementType)) { + JSCodeStyleSettings customSettings = + CodeStyleSettingsManager.getSettings(node.getPsi().getProject()).getCustomSettings(JSCodeStyleSettings.class); + if (customSettings.INDENT_PACKAGE_CHILDREN == JSCodeStyleSettings.INDENT) { + return Indent.getNormalIndent(); + } + return Indent.getNoneIndent(); + } + + if (nodeElementType == JSElementTypes.ATTRIBUTE_LIST) { + return Indent.getNoneIndent(); + } + + if (childElementType == JSElementTypes.BLOCK_STATEMENT) { + if (nodeElementType == JSElementTypes.FUNCTION_DECLARATION + && (mySettings.METHOD_BRACE_STYLE == CodeStyleSettings.NEXT_LINE_SHIFTED + || mySettings.METHOD_BRACE_STYLE == CodeStyleSettings.NEXT_LINE_SHIFTED2)) { + return Indent.getNormalIndent(); + } + if (mySettings.BRACE_STYLE == CodeStyleSettings.NEXT_LINE_SHIFTED + || mySettings.BRACE_STYLE == CodeStyleSettings.NEXT_LINE_SHIFTED2) { + return Indent.getNormalIndent(); + } + return Indent.getNoneIndent(); + } + + if (childElementType == JSElementTypes.CATCH_BLOCK) { + return Indent.getNoneIndent(); + } + + if (childElementType == JSElementTypes.CASE_CLAUSE) { + return mySettings.INDENT_CASE_FROM_SWITCH ? Indent.getNormalIndent() : Indent.getNoneIndent(); + } + + if (nodeElementType == JSElementTypes.CASE_CLAUSE) { + if (child.getPsi() instanceof JSStatement || JSTokenTypes.COMMENTS.contains(childElementType)) { + return Indent.getNormalIndent(); + } + return Indent.getNoneIndent(); + } + + if (nodeElementType == JSElementTypes.SWITCH_STATEMENT + && (childElementType == JSTokenTypes.LBRACE || childElementType == JSTokenTypes.RBRACE)) { + return Indent.getNoneIndent(); + } + + if (nodeElementType == JSElementTypes.IF_STATEMENT) { + return Indent.getNoneIndent(); + } + + if (nodeElementType == JSElementTypes.WITH_STATEMENT && JSElementTypes.SOURCE_ELEMENTS.contains(childElementType)) { + return Indent.getNormalIndent(); + } + + if (nodeElementType == JSElementTypes.DOWHILE_STATEMENT && childElementType == JSTokenTypes.WHILE_KEYWORD) { + return Indent.getNoneIndent(); + } + + if (nodeElementType == JSElementTypes.TRY_STATEMENT && childElementType == JSTokenTypes.FINALLY_KEYWORD) { + return Indent.getNoneIndent(); + } + + if (nodeElementType == JSElementTypes.BLOCK_STATEMENT + || nodeElementType == JSElementTypes.CLASS + || nodeElementType == JSElementTypes.PACKAGE_STATEMENT) { + ASTNode parent = node.getTreeParent(); + if (parent != null && parent.getElementType() == JSElementTypes.FUNCTION_DECLARATION + && mySettings.METHOD_BRACE_STYLE == CodeStyleSettings.NEXT_LINE_SHIFTED) { + return Indent.getNoneIndent(); + } + if (mySettings.BRACE_STYLE == CodeStyleSettings.NEXT_LINE_SHIFTED) { + return Indent.getNoneIndent(); + } + if (JSElementTypes.SOURCE_ELEMENTS.contains(childElementType) || JSTokenTypes.COMMENTS.contains(childElementType)) { + return Indent.getNormalIndent(); + } + return Indent.getNoneIndent(); + } + else if (node.getPsi() instanceof JSLoopStatement loop) { + if (child.getPsi() == loop.getBody()) { + return childElementType == JSElementTypes.BLOCK_STATEMENT ? Indent.getNoneIndent() : Indent.getNormalIndent(); + } + } + + if (JSTokenTypes.COMMENTS.contains(childElementType)) { + return Indent.getNormalIndent(); + } + if (childElementType == JSElementTypes.OBJECT_LITERAL_EXPRESSION) { + return nodeElementType == JSElementTypes.ARRAY_LITERAL_EXPRESSION ? Indent.getNormalIndent() : Indent.getNoneIndent(); + } + + if (nodeElementType == JSElementTypes.XML_LITERAL_EXPRESSION) { + return childElementType == JSElementTypes.XML_LITERAL_EXPRESSION ? Indent.getNormalIndent() : Indent.getNoneIndent(); + } + + if (nodeElementType == JSElementTypes.ARRAY_LITERAL_EXPRESSION) { + if (childElementType == JSTokenTypes.LBRACKET || childElementType == JSTokenTypes.RBRACKET) { + return Indent.getNoneIndent(); + } + return Indent.getNormalIndent(); + } + + if (nodeElementType == JSElementTypes.EMBEDDED_EXPRESSION) { + if (childElementType == JSTokenTypes.LBRACE || childElementType == JSTokenTypes.RBRACE) { + return Indent.getNoneIndent(); + } + return Indent.getNormalIndent(); + } + + if (nodeElementType == JSElementTypes.OBJECT_LITERAL_EXPRESSION) { + if (childElementType == JSTokenTypes.LBRACE || childElementType == JSTokenTypes.RBRACE) { + return Indent.getNoneIndent(); + } + return Indent.getNormalIndent(); + } + return null; + } + + @Nullable + private static Alignment alignmentProjection(Alignment defaultAlignment, ASTNode parent, ASTNode child) { + if (parent.getElementType() == JSElementTypes.FOR_STATEMENT + && (JSElementTypes.EXPRESSIONS.contains(child.getElementType()) + || child.getElementType() == JSElementTypes.VAR_STATEMENT)) { + return defaultAlignment; + } + else if (parent.getElementType() == JSElementTypes.PARAMETER_LIST && child.getElementType() == JSElementTypes.FORMAL_PARAMETER) { + return defaultAlignment; + } + else if (parent.getPsi() instanceof JSBinaryExpression && JSElementTypes.EXPRESSIONS.contains(child.getElementType())) { + return defaultAlignment; + } + else if (parent.getElementType() == JSElementTypes.CONDITIONAL_EXPRESSION + && JSElementTypes.EXPRESSIONS.contains(child.getElementType())) { + return defaultAlignment; + } + + return null; + } + + @Nullable + @RequiredReadAction + private Wrap getWrap(ASTNode node, ASTNode child) { + WrapType wrapType = null; + if (node.getElementType() == JSElementTypes.ASSIGNMENT_EXPRESSION) { + JSAssignmentExpression assignment = (JSAssignmentExpression)node.getPsi(); + if (child.getElementType() == assignment.getOperationSign() && mySettings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE + || child.getPsi() == assignment.getROperand() && !mySettings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) { + wrapType = WrapType.byLegacyRepresentation(mySettings.ASSIGNMENT_WRAP); + } + } + else if (node.getElementType() == JSElementTypes.BINARY_EXPRESSION) { + JSBinaryExpression binary = (JSBinaryExpression)node.getPsi(); + if (child.getElementType() == binary.getOperationSign() && mySettings.BINARY_OPERATION_SIGN_ON_NEXT_LINE + || child.getPsi() == binary.getROperand() && !mySettings.BINARY_OPERATION_SIGN_ON_NEXT_LINE) { + wrapType = WrapType.byLegacyRepresentation(mySettings.BINARY_OPERATION_WRAP); + } + } + else if (node.getElementType() == JSElementTypes.PARENTHESIZED_EXPRESSION) { + if (child == node.findChildByType(JSTokenTypes.LPAR) && mySettings.PARENTHESES_EXPRESSION_LPAREN_WRAP) { + wrapType = WrapType.NORMAL; + } + else if (child == node.findChildByType(JSTokenTypes.RPAR) && mySettings.PARENTHESES_EXPRESSION_RPAREN_WRAP) { + wrapType = WrapType.ALWAYS; + } + } + else if (node.getElementType() == JSElementTypes.ARRAY_LITERAL_EXPRESSION) { + if (child == node.findChildByType(JSTokenTypes.LBRACE) && mySettings.ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE) { + wrapType = WrapType.NORMAL; + } + else if (child == node.findChildByType(JSTokenTypes.RPAR) && mySettings.ARRAY_INITIALIZER_RBRACE_ON_NEXT_LINE) { + wrapType = WrapType.ALWAYS; + } + } + else if (node.getElementType() == JSElementTypes.CONDITIONAL_EXPRESSION) { + IElementType elementType = child.getElementType(); + if ((mySettings.TERNARY_OPERATION_SIGNS_ON_NEXT_LINE + && (elementType == JSTokenTypes.QUEST || elementType == JSTokenTypes.COLON)) + || (!mySettings.TERNARY_OPERATION_SIGNS_ON_NEXT_LINE && child.getPsi() instanceof JSExpression)) { + wrapType = WrapType.byLegacyRepresentation(mySettings.TERNARY_OPERATION_WRAP); + } + } + else if (node.getElementType() == JSElementTypes.CALL_EXPRESSION) { + if (child == node.findChildByType(JSTokenTypes.LPAR) && mySettings.CALL_PARAMETERS_LPAREN_ON_NEXT_LINE) { + wrapType = WrapType.NORMAL; + } + else if (child == node.findChildByType(JSTokenTypes.RPAR) && mySettings.CALL_PARAMETERS_RPAREN_ON_NEXT_LINE) { + wrapType = WrapType.ALWAYS; + } + } + else if (node.getElementType() == JSElementTypes.PARAMETER_LIST) { + if (child.getElementType() == JSElementTypes.FORMAL_PARAMETER) { + wrapType = WrapType.byLegacyRepresentation(mySettings.METHOD_PARAMETERS_WRAP); + } + } + else if (node.getElementType() == JSElementTypes.FOR_STATEMENT || node.getElementType() == JSElementTypes.FOR_IN_STATEMENT) { + if (JSElementTypes.EXPRESSIONS.contains(child.getElementType())) { + wrapType = WrapType.byLegacyRepresentation(mySettings.FOR_STATEMENT_WRAP); + } + } + + return wrapType == null ? null : Wrap.createWrap(wrapType, false); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/BaseJSGenerateAction.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/BaseJSGenerateAction.java index b77000dd..9f4dfb47 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/BaseJSGenerateAction.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/BaseJSGenerateAction.java @@ -25,66 +25,58 @@ import consulo.language.editor.util.PsiUtilBase; import consulo.language.psi.PsiFile; import consulo.project.Project; +import consulo.ui.annotation.RequiredUIAccess; import consulo.ui.ex.action.AnAction; import consulo.ui.ex.action.AnActionEvent; import consulo.virtualFileSystem.VirtualFile; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author Maxim.Mossienko - * Date: Jul 19, 2008 - * Time: 7:04:37 PM + * @since 2008-07-19 */ -abstract class BaseJSGenerateAction extends AnAction -{ - @Override - public void actionPerformed(final AnActionEvent e) - { - Editor editor = e.getData(PlatformDataKeys.EDITOR); - PsiFile psifile = e.getData(LangDataKeys.PSI_FILE); - Project project = e.getData(PlatformDataKeys.PROJECT); +abstract class BaseJSGenerateAction extends AnAction { + @Override + @RequiredUIAccess + public void actionPerformed(AnActionEvent e) { + Editor editor = e.getData(PlatformDataKeys.EDITOR); + PsiFile psifile = e.getData(LangDataKeys.PSI_FILE); + Project project = e.getData(PlatformDataKeys.PROJECT); - final VirtualFile file = e.getData(PlatformDataKeys.VIRTUAL_FILE); - if(JavaScriptSupportLoader.isFlexMxmFile(file)) - { - editor = BaseCodeInsightAction.getInjectedEditor(project, editor); - psifile = PsiUtilBase.getPsiFileInEditor(editor, project); - } + VirtualFile file = e.getData(PlatformDataKeys.VIRTUAL_FILE); + if (JavaScriptSupportLoader.isFlexMxmFile(file)) { + editor = BaseCodeInsightAction.getInjectedEditor(project, editor); + psifile = PsiUtilBase.getPsiFileInEditor(editor, project); + } - new JavaScriptGenerateAccessorHandler(getGenerationMode()).invoke(project, editor, psifile); - } + new JavaScriptGenerateAccessorHandler(getGenerationMode()).invoke(project, editor, psifile); + } - protected abstract - @Nonnull - JavaScriptGenerateAccessorHandler.GenerationMode getGenerationMode(); + @Nonnull + protected abstract JavaScriptGenerateAccessorHandler.GenerationMode getGenerationMode(); - @Override - public void update(final AnActionEvent e) - { - final VirtualFile file = e.getData(PlatformDataKeys.VIRTUAL_FILE); + @Override + @RequiredUIAccess + public void update(AnActionEvent e) { + VirtualFile file = e.getData(PlatformDataKeys.VIRTUAL_FILE); - boolean status = false; + boolean status = false; - if(file != null) - { - if(file.getFileType() == JavaScriptFileType.INSTANCE) - { - final Editor editor = e.getData(PlatformDataKeys.EDITOR); - final PsiFile psifile = e.getData(LangDataKeys.PSI_FILE); + if (file != null) { + if (file.getFileType() == JavaScriptFileType.INSTANCE) { + Editor editor = e.getData(PlatformDataKeys.EDITOR); + PsiFile psifile = e.getData(LangDataKeys.PSI_FILE); - if(editor != null && psifile != null) - { - status = psifile.getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4; - } - } - else if(JavaScriptSupportLoader.isFlexMxmFile(file)) - { - status = true; - } - } + if (editor != null && psifile != null) { + status = psifile.getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4; + } + } + else if (JavaScriptSupportLoader.isFlexMxmFile(file)) { + status = true; + } + } - e.getPresentation().setEnabled(status); - e.getPresentation().setVisible(status); - } + e.getPresentation().setEnabled(status); + e.getPresentation().setVisible(status); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/BaseJSGenerateHandler.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/BaseJSGenerateHandler.java index 7d6f52d2..6d4cf14e 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/BaseJSGenerateHandler.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/BaseJSGenerateHandler.java @@ -19,11 +19,10 @@ */ package com.intellij.lang.javascript.impl.generation; -import consulo.javascript.language.JavaScriptBundle; +import com.intellij.lang.javascript.impl.validation.BaseCreateMethodsFix; import com.intellij.lang.javascript.psi.JSClass; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; -import com.intellij.lang.javascript.impl.validation.BaseCreateMethodsFix; -import consulo.application.ApplicationManager; +import consulo.annotation.access.RequiredReadAction; import consulo.codeEditor.Editor; import consulo.javascript.language.JavaScriptLanguage; import consulo.language.Language; @@ -37,141 +36,128 @@ import consulo.localize.LocalizeValue; import consulo.logging.Logger; import consulo.project.Project; +import consulo.ui.annotation.RequiredUIAccess; import consulo.undoRedo.CommandProcessor; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; import javax.swing.*; import java.util.ArrayList; import java.util.Collection; import java.util.List; -abstract class BaseJSGenerateHandler implements LanguageCodeInsightActionHandler -{ - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } - - @Override - public void invoke(final Project project, final Editor editor, final PsiFile file) - { - JSClass clazz = findClass(file, editor); - - if(clazz == null) - { - return; - } - - final Collection candidates = new ArrayList(); - collectCandidates(clazz, candidates); - - MemberChooserBuilder builder = MemberChooserBuilder.create(candidates.toArray(new JSNamedElementNode[candidates.size()])); - if(canHaveEmptySelectedElements()) - { - builder.withEmptySelection(); - } - - builder.withTitle(LocalizeValue.localizeTODO(JavaScriptBundle.message(getTitleKey()))); - builder.showAsync(project, dataHolder -> - { - List data = dataHolder.getUserData(ClassMember.KEY_OF_LIST); - - run(clazz, data, project, editor, file); - }); - } - - private void run(JSClass clazz, Collection selectedElements, Project project, Editor editor, PsiFile file) - { - final JSClass jsClass = clazz; - final Collection selectedElements1 = selectedElements; - Runnable runnable = new Runnable() - { - @Override - public void run() - { - ApplicationManager.getApplication().runWriteAction(new Runnable() - { - @Override - public void run() - { - try - { - final BaseCreateMethodsFix createMethodsFix = createFix(jsClass); - createMethodsFix.addElementsToProcessFrom(selectedElements1); - createMethodsFix.invoke(project, editor, file); - } - catch(IncorrectOperationException ex) - { - Logger.getInstance(getClass().getName()).error(ex); - } - } - }); - } - }; - - CommandProcessor processor = CommandProcessor.getInstance(); - if(processor.hasCurrentCommand()) - { - processor.executeCommand(project, runnable, getClass().getName(), null); - } - else - { - runnable.run(); - } - } - - protected void appendOwnOptions(List jComponentList) - { - } - - protected boolean canHaveEmptySelectedElements() - { - return false; - } - - static JSClass findClass(PsiFile file, Editor editor) - { - final PsiElement at = file.findElementAt(editor.getCaretModel().getOffset()); - if(at == null) - { - return null; - } - - JSClass clazz = PsiTreeUtil.getParentOfType(at, JSClass.class); - if(clazz == null) - { - final PsiFile containingFile = at.getContainingFile(); - final PsiElement element = JSResolveUtil.getClassReferenceForXmlFromContext(containingFile); - if(element instanceof JSClass) - { - clazz = (JSClass) element; - } - } - else if(JSResolveUtil.isArtificialClassUsedForReferenceList(clazz)) - { - clazz = null; - } - - return clazz; - } - - protected abstract String getTitleKey(); - - protected abstract BaseCreateMethodsFix createFix(JSClass clazz); - - protected abstract void collectCandidates(final JSClass clazz, final Collection candidates); - - @Override - public boolean startInWriteAction() - { - return false; - } - - @Override - public boolean isValidFor(final Editor editor, final PsiFile file) - { - return true; - } +abstract class BaseJSGenerateHandler implements LanguageCodeInsightActionHandler { + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } + + @Override + @RequiredUIAccess + public void invoke(@Nonnull Project project, @Nonnull Editor editor, @Nonnull PsiFile file) { + JSClass clazz = findClass(file, editor); + + if (clazz == null) { + return; + } + + Collection candidates = new ArrayList<>(); + collectCandidates(clazz, candidates); + + MemberChooserBuilder builder = + MemberChooserBuilder.create(candidates.toArray(new JSNamedElementNode[candidates.size()])); + if (canHaveEmptySelectedElements()) { + builder.withEmptySelection(); + } + + builder.withTitle(getTitle()) + .showAsync( + project, + dataHolder -> { + List data = dataHolder.getUserData(ClassMember.KEY_OF_LIST); + + run(clazz, data, project, editor, file); + } + ); + } + + @RequiredUIAccess + private void run(JSClass clazz, final Collection selectedElements, Project project, Editor editor, PsiFile file) { + JSClass jsClass = clazz; + Runnable runnable = new Runnable() { + @Override + @RequiredUIAccess + public void run() { + project.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + try { + BaseCreateMethodsFix createMethodsFix = createFix(jsClass); + createMethodsFix.addElementsToProcessFrom(selectedElements); + createMethodsFix.invoke(project, editor, file); + } + catch (IncorrectOperationException ex) { + Logger.getInstance(getClass().getName()).error(ex); + } + } + }); + } + }; + + CommandProcessor processor = CommandProcessor.getInstance(); + if (processor.hasCurrentCommand()) { + processor.newCommand() + .project(project) + .name(LocalizeValue.of(getClass().getName())) + .run(runnable); + } + else { + runnable.run(); + } + } + + protected void appendOwnOptions(List jComponentList) { + } + + protected boolean canHaveEmptySelectedElements() { + return false; + } + + @RequiredReadAction + static JSClass findClass(PsiFile file, Editor editor) { + PsiElement at = file.findElementAt(editor.getCaretModel().getOffset()); + if (at == null) { + return null; + } + + JSClass clazz = PsiTreeUtil.getParentOfType(at, JSClass.class); + if (clazz == null) { + PsiFile containingFile = at.getContainingFile(); + PsiElement element = JSResolveUtil.getClassReferenceForXmlFromContext(containingFile); + if (element instanceof JSClass jsClass) { + clazz = jsClass; + } + } + else if (JSResolveUtil.isArtificialClassUsedForReferenceList(clazz)) { + clazz = null; + } + + return clazz; + } + + protected abstract LocalizeValue getTitle(); + + protected abstract BaseCreateMethodsFix createFix(JSClass clazz); + + protected abstract void collectCandidates(JSClass clazz, Collection candidates); + + @Override + public boolean startInWriteAction() { + return false; + } + + @Override + public boolean isValidFor(Editor editor, PsiFile file) { + return true; + } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JSNamedElementNode.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JSNamedElementNode.java index 8c498b1a..1e708059 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JSNamedElementNode.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JSNamedElementNode.java @@ -19,105 +19,89 @@ import com.intellij.javascript.JSParameterInfoHandler; import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; -import consulo.application.AllIcons; +import consulo.annotation.access.RequiredReadAction; import consulo.language.editor.generation.ClassMember; import consulo.language.editor.generation.MemberChooserObject; import consulo.language.editor.generation.PsiElementMemberChooserObject; import consulo.language.icon.IconDescriptorUpdaters; import consulo.language.psi.PsiElement; +import consulo.platform.base.icon.PlatformIconGroup; import consulo.ui.image.Image; import consulo.ui.image.ImageEffects; /** * @author Maxim.Mossienko - * Date: Jul 17, 2008 - * Time: 8:55:57 PM + * @since 2008-07-17 */ -public class JSNamedElementNode extends PsiElementMemberChooserObject implements ClassMember -{ - public JSNamedElementNode(JSNamedElement node) - { - super(node, buildTextFor(node), buildIcon(node)); - } +public class JSNamedElementNode extends PsiElementMemberChooserObject implements ClassMember { + @RequiredReadAction + public JSNamedElementNode(JSNamedElement node) { + super(node, buildTextFor(node), buildIcon(node)); + } - private static Image buildIcon(final JSNamedElement node) - { - Image icon = IconDescriptorUpdaters.getIcon(node, 0); + @RequiredReadAction + private static Image buildIcon(JSNamedElement node) { + Image icon = IconDescriptorUpdaters.getIcon(node, 0); - if(node instanceof JSFunction) - { - final JSFunction function = (JSFunction) node; - final Image accessIcon; + if (node instanceof JSFunction function) { + Image accessIcon; - if(function.isGetProperty()) - { - accessIcon = AllIcons.Nodes.Read_access; - } - else if(function.isSetProperty()) - { - accessIcon = AllIcons.Nodes.Write_access; - } - else - { - accessIcon = null; - } + if (function.isGetProperty()) { + accessIcon = PlatformIconGroup.nodesRead_access(); + } + else if (function.isSetProperty()) { + accessIcon = PlatformIconGroup.nodesWrite_access(); + } + else { + accessIcon = null; + } - if(accessIcon != null) - { - icon = ImageEffects.appendRight(icon, accessIcon); - } - } - return icon; - } + if (accessIcon != null) { + icon = ImageEffects.appendRight(icon, accessIcon); + } + } + return icon; + } - private static String buildTextFor(final JSNamedElement node) - { - String text = node.getName(); + @RequiredReadAction + private static String buildTextFor(JSNamedElement node) { + StringBuilder text = new StringBuilder(node.getName()); - if(node instanceof JSFunction) - { - final JSFunction function = (JSFunction) node; - text += "("; - final JSParameterList parameterList = function.getParameterList(); + if (node instanceof JSFunction function) { + text.append("("); + JSParameterList parameterList = function.getParameterList(); - if(parameterList != null) - { - boolean first = true; - for(JSParameter p : parameterList.getParameters()) - { - if(!first) - { - text += ", "; - } - first = false; - text += JSParameterInfoHandler.getSignatureForParameter(p, false); - } - } + if (parameterList != null) { + boolean first = true; + for (JSParameter p : parameterList.getParameters()) { + if (!first) { + text.append(", "); + } + first = false; + text.append(JSParameterInfoHandler.getSignatureForParameter(p, false)); + } + } - text += ")"; - final String typeString = function.getReturnTypeString(); - if(typeString != null) - { - text += ":" + typeString; - } - } - else if(node instanceof JSVariable) - { - final JSVariable var = (JSVariable) node; - final String typeString = var.getTypeString(); - if(typeString != null) - { - text += ":" + typeString; - } - } - return text; - } + text.append(")"); + String typeString = function.getReturnTypeString(); + if (typeString != null) { + text.append(":").append(typeString); + } + } + else if (node instanceof JSVariable var) { + String typeString = var.getTypeString(); + if (typeString != null) { + text.append(":").append(typeString); + } + } + return text.toString(); + } - @Override - public MemberChooserObject getParentNodeDelegate() - { - final PsiElement element = getPsiElement(); - PsiElement parent = JSResolveUtil.findParent(element); - return new JSNamedElementNode((JSNamedElement) parent); - } + @Override + @RequiredReadAction + public MemberChooserObject getParentNodeDelegate() { + PsiElement element = getPsiElement(); + PsiElement parent = JSResolveUtil.findParent(element); + return new JSNamedElementNode((JSNamedElement)parent); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptGenerateAccessorHandler.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptGenerateAccessorHandler.java index b874f9f9..1088f29e 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptGenerateAccessorHandler.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptGenerateAccessorHandler.java @@ -16,400 +16,379 @@ package com.intellij.lang.javascript.impl.generation; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.formatter.JSCodeStyleSettings; +import com.intellij.lang.javascript.impl.validation.BaseCreateMethodsFix; +import com.intellij.lang.javascript.impl.validation.JSAnnotatingVisitor; import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.impl.JSChangeUtil; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; import com.intellij.lang.javascript.psi.resolve.ResolveProcessor; -import com.intellij.lang.javascript.impl.validation.BaseCreateMethodsFix; -import com.intellij.lang.javascript.impl.validation.JSAnnotatingVisitor; -import consulo.application.ApplicationManager; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; +import consulo.application.Application; import consulo.codeEditor.Editor; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.codeStyle.CodeStyleSettingsManager; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiFile; import consulo.language.psi.resolve.ResolveState; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; import consulo.project.Project; +import consulo.ui.annotation.RequiredUIAccess; import consulo.ui.ex.awt.NonFocusableCheckBox; import consulo.util.lang.StringUtil; -import org.jetbrains.annotations.NonNls; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; import javax.swing.*; import java.util.*; /** * @author Maxim.Mossienko - * Date: Jul 19, 2008 - * Time: 1:11:10 AM + * @since 2008-07-19 */ -class JavaScriptGenerateAccessorHandler extends BaseJSGenerateHandler -{ - private GenerationMode mode; - private JCheckBox myCreateBindableProperties; - - static enum GenerationMode - { - GETTERS, - SETTERS, - GETTERS_AND_SETTERS, - CONSTRUCTOR, - TOSTRING - } - - JavaScriptGenerateAccessorHandler(GenerationMode _mode) - { - mode = _mode; - } - - @Override - protected String getTitleKey() - { - return mode == GenerationMode.GETTERS ? "generate.getter.fields.chooser.title" : mode == GenerationMode.SETTERS ? "generate.setter.fields.chooser" + - ".title" : mode == GenerationMode.GETTERS_AND_SETTERS ? "generate.getter.setter.chooser.title" : mode == GenerationMode.TOSTRING ? "generate.to" + - ".string.chooser.title" : "generate.constructor.fields.chooser.title"; - } - - @Override - protected void appendOwnOptions(List jComponentList) - { - super.appendOwnOptions(jComponentList); - if(mode == GenerationMode.GETTERS || mode == GenerationMode.GETTERS_AND_SETTERS || mode == GenerationMode.SETTERS) - { - if(!ApplicationManager.getApplication().isUnitTestMode()) - { - myCreateBindableProperties = new NonFocusableCheckBox(JavaScriptBundle.message("generate.getter.fields.bindable.properties")); - jComponentList.add(myCreateBindableProperties); - } - } - } - - @Override - protected BaseCreateMethodsFix createFix(final JSClass jsClass) - { - if(mode == GenerationMode.GETTERS_AND_SETTERS) - { - return new BaseCreateMethodsFix(jsClass) - { - private boolean toCreateBindableProperties = myCreateBindableProperties != null ? myCreateBindableProperties.isSelected() : ApplicationManager - .getApplication().isUnitTestMode(); - final MyBaseCreateMethodsFix generateGetterFix = new MyBaseCreateMethodsFix(GenerationMode.GETTERS, jsClass, toCreateBindableProperties); - final MyBaseCreateMethodsFix generateSetterFix = new MyBaseCreateMethodsFix(GenerationMode.SETTERS, jsClass, toCreateBindableProperties); - - @Override - public void invoke(@Nonnull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException - { - evalAnchor(editor, file); - - for(JSVariable e : getElementsToProcess()) - { - anchor = doAddOneMethod(project, generateGetterFix.buildFunctionText(e), anchor); - anchor = doAddOneMethod(project, generateSetterFix.buildFunctionText(e), anchor); - } - } - }; - } - else if(mode == GenerationMode.CONSTRUCTOR) - { - return new BaseCreateMethodsFix(jsClass) - { - @Override - public void invoke(@Nonnull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException - { - final JSCodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(project).getCustomSettings(JSCodeStyleSettings.class); - evalAnchor(editor, file); - @NonNls String functionText = "public function " + jsClass.getName() + "("; - @NonNls String initialization = ""; - boolean first = true; - final String semicolon = JSChangeUtil.getSemicolon(project); - - Set toProcess = getElementsToProcess(); - Iterator variableIterator = toProcess.iterator(); - boolean hadSuperClassConstructorInitializationBefore = false; - - while(variableIterator.hasNext()) - { - JSVariable var = variableIterator.next(); - if(!first) - { - functionText += ", "; - } - - first = false; - - final String name = var.getName(); - String parameterName = transformVarNameToAccessorName(name, codeStyleSettings); - - final String typeString = var.getTypeString(); - functionText += parameterName + (typeString != null ? ":" + typeString : ""); - - if(JSResolveUtil.findParent(var) == jsClass) - { - if(hadSuperClassConstructorInitializationBefore) - { - initialization += ")" + semicolon + "\n"; - hadSuperClassConstructorInitializationBefore = false; - } - initialization += (parameterName.equals(name) ? "this." : "") + name + " = " + parameterName + semicolon + "\n"; - } - else - { - if(hadSuperClassConstructorInitializationBefore) - { - initialization += ", "; - } - else - { - initialization += "super("; - } - initialization += parameterName; - hadSuperClassConstructorInitializationBefore = true; - } - } - - if(hadSuperClassConstructorInitializationBefore) - { - initialization += ")" + semicolon + "\n"; - } - functionText += ") {\n"; - functionText += initialization; - functionText += "}"; - doAddOneMethod(project, functionText, anchor); - } - - @Override - public Set getElementsToProcess() - { - LinkedHashSet vars = new LinkedHashSet(); - JSFunction nontrivialSuperClassConstructor = JSAnnotatingVisitor.getNontrivialSuperClassConstructor(jsClass); - - if(nontrivialSuperClassConstructor != null) - { - vars.addAll(Arrays.asList(nontrivialSuperClassConstructor.getParameterList().getParameters())); - } - vars.addAll(super.getElementsToProcess()); - return vars; - } - }; - } - else if(mode == GenerationMode.TOSTRING) - { - return new BaseCreateMethodsFix(jsClass) - { - @Override - public void invoke(@Nonnull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException - { - evalAnchor(editor, file); - - final boolean[] needOverride = new boolean[1]; - JSResolveUtil.processOverrides(jsClass, new JSResolveUtil.OverrideHandler() - { - @Override - public boolean process(final ResolveProcessor processor, final PsiElement scope, final String className) - { - needOverride[0] = !"Object".equals(className); - return false; - } - }, "toString", null, myJsClass); - - @NonNls String functionText = "public " + (needOverride[0] ? "override " : "") + "function toString():String {\nreturn " + - (needOverride[0] ? "super.toString() + \"" : "\"" + jsClass.getName()) + "{"; - final String semicolon = JSChangeUtil.getSemicolon(project); - - boolean first = true; - - for(JSVariable var : getElementsToProcess()) - { - if(!first) - { - functionText += " + \","; - } - first = false; - - functionText += var.getName() + "=\" + String(" + var.getName() + ")"; - } - - functionText += "+\"}\"" + semicolon + "\n}"; - doAddOneMethod(project, functionText, anchor); - } - }; - } - - return new MyBaseCreateMethodsFix(mode, jsClass, myCreateBindableProperties != null ? myCreateBindableProperties.isSelected() : false); - } - - - @Override - protected void collectCandidates(final JSClass clazz, final Collection candidates) - { - final LinkedHashMap candidatesMap = new LinkedHashMap(); - final JSCodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(clazz.getProject()).getCustomSettings(JSCodeStyleSettings - .class); - final ResolveProcessor processor = new ResolveProcessor(null) - { - { - setToProcessMembers(true); - setToProcessHierarchy(false); - setLocalResolve(true); - } - - @Override - public boolean execute(final PsiElement element, final ResolveState state) - { - final JSNamedElement namedElement = (JSNamedElement) element; - if(!(element instanceof JSVariable)) - { - if(element instanceof JSFunction) - { - final JSFunction function = (JSFunction) element; - if(mode == GenerationMode.GETTERS && function.isGetProperty() || mode == GenerationMode.SETTERS && function.isSetProperty()) - { - candidatesMap.put(function.getName(), function); - } - - } - return true; - } - else if(((JSVariable) element).isConst()) - { - return true; - } - - final String name = namedElement.getName(); - final String accessorName = transformVarNameToAccessorName(name, codeStyleSettings); - if(/*!name.equals(accessorName) &&*/ !candidatesMap.containsKey(accessorName)) - { - candidatesMap.put(accessorName, namedElement); - } - return true; - } - }; - - clazz.processDeclarations(processor, ResolveState.initial(), clazz, clazz); - for(JSNamedElement n : candidatesMap.values()) - { - if(n instanceof JSVariable) - { - candidates.add(new JSNamedElementNode(n)); - } - } - } - - private static class MyBaseCreateMethodsFix extends BaseCreateMethodsFix - { - private GenerationMode myMode; - private JSCodeStyleSettings codeStyleSettings; - private boolean bindableProperties; - private static final String PARAMETER_NAME = "value"; - - public MyBaseCreateMethodsFix(final GenerationMode mode, final JSClass jsClass, boolean _bindableProperties) - { - super(jsClass); - this.myMode = mode; - codeStyleSettings = CodeStyleSettingsManager.getSettings(jsClass.getProject()).getCustomSettings(JSCodeStyleSettings.class); - bindableProperties = _bindableProperties; - } - - @Override - protected String buildFunctionBodyText(final String retType, final JSParameterList parameterList, final JSVariable func) - { - final String semicolon = codeStyleSettings.USE_SEMICOLON_AFTER_STATEMENT ? ";" : ""; - String varName = func.getName(); - if(myMode == GenerationMode.SETTERS) - { - String checkNeedEvent = ""; - String dispatchEvent = ""; - if(bindableProperties) - { - String eventName = getEventName(transformVarNameToAccessorName(varName, codeStyleSettings)); - dispatchEvent = "\ndispatchEvent(new Event(\"" + eventName + "\"))" + semicolon; - checkNeedEvent = "if(" + varName + "==" + PARAMETER_NAME + ") return" + semicolon + "\n"; - } - return "{\n" + checkNeedEvent + varName + "=" + PARAMETER_NAME + semicolon + dispatchEvent + "\n}"; - } - else if(myMode == GenerationMode.GETTERS) - { - return "{\nreturn " + varName + semicolon + "\n}"; - } - return " {}"; - } - - @Override - protected String buildFunctionAttrText(final String attrText, final JSAttributeList attributeList, final JSVariable function) - { - String baseText = "public" + (attributeList != null && attributeList.hasModifier(JSAttributeList.ModifierType.STATIC) ? " static" : ""); - - if(bindableProperties && myMode == GenerationMode.GETTERS) - { - baseText = "[Bindable(event=\"" + getEventName(transformVarNameToAccessorName(function.getName(), codeStyleSettings)) + "\")]\n" + baseText; - } - - return baseText; - } - - private static String getEventName(String name) - { - return name + "Changed"; - } - - @Override - protected String buildFunctionKind(final JSVariable fun) - { - if(myMode == GenerationMode.GETTERS) - { - return "get "; - } - if(myMode == GenerationMode.SETTERS) - { - return "set "; - } - return super.buildFunctionKind(fun); - } - - @Override - protected String buildReturnType(final String typeString) - { - if(myMode == GenerationMode.SETTERS) - { - return "void"; - } - return super.buildReturnType(typeString); - } - - @Override - protected String buildName(final JSVariable fun) - { - return transformVarNameToAccessorName(super.buildName(fun), codeStyleSettings); - } - - @Override - protected String buildParameterList(final JSParameterList parameterList, final JSVariable fun) - { - if(myMode == GenerationMode.SETTERS) - { - final String s = fun.getTypeString(); - return "(" + PARAMETER_NAME + (s != null ? ":" + s : "") + ")"; - } - return (parameterList != null ? parameterList.getText() : "()"); - } - } - - private static String transformVarNameToAccessorName(String s, final JSCodeStyleSettings codeStyleSettings) - { - if(StringUtil.startsWith(s, codeStyleSettings.FIELD_PREFIX)) - { - s = s.substring(codeStyleSettings.FIELD_PREFIX.length()); - } - s = codeStyleSettings.PROPERTY_PREFIX + s; - return s; - } - - @Override - protected boolean canHaveEmptySelectedElements() - { - return mode == GenerationMode.CONSTRUCTOR; - } +class JavaScriptGenerateAccessorHandler extends BaseJSGenerateHandler { + private GenerationMode mode; + private JCheckBox myCreateBindableProperties; + + static enum GenerationMode { + GETTERS, + SETTERS, + GETTERS_AND_SETTERS, + CONSTRUCTOR, + TOSTRING + } + + JavaScriptGenerateAccessorHandler(GenerationMode _mode) { + mode = _mode; + } + + @Override + protected LocalizeValue getTitle() { + return mode == GenerationMode.GETTERS + ? JavaScriptLocalize.generateGetterFieldsChooserTitle() + : mode == GenerationMode.SETTERS + ? JavaScriptLocalize.generateSetterFieldsChooserTitle() + : mode == GenerationMode.GETTERS_AND_SETTERS + ? JavaScriptLocalize.generateGetterSetterChooserTitle() + : mode == GenerationMode.TOSTRING + ? JavaScriptLocalize.generateToStringChooserTitle() + : JavaScriptLocalize.generateConstructorFieldsChooserTitle(); + } + + @Override + protected void appendOwnOptions(List jComponentList) { + super.appendOwnOptions(jComponentList); + if (mode == GenerationMode.GETTERS || mode == GenerationMode.GETTERS_AND_SETTERS || mode == GenerationMode.SETTERS) { + if (!Application.get().isUnitTestMode()) { + myCreateBindableProperties = new NonFocusableCheckBox(JavaScriptLocalize.generateGetterFieldsBindableProperties().get()); + jComponentList.add(myCreateBindableProperties); + } + } + } + + @Override + protected BaseCreateMethodsFix createFix(JSClass jsClass) { + if (mode == GenerationMode.GETTERS_AND_SETTERS) { + return new BaseCreateMethodsFix(jsClass) { + private boolean toCreateBindableProperties = myCreateBindableProperties != null + ? myCreateBindableProperties.isSelected() + : jsClass.getApplication().isUnitTestMode(); + final MyBaseCreateMethodsFix generateGetterFix = + new MyBaseCreateMethodsFix(GenerationMode.GETTERS, jsClass, toCreateBindableProperties); + final MyBaseCreateMethodsFix generateSetterFix = + new MyBaseCreateMethodsFix(GenerationMode.SETTERS, jsClass, toCreateBindableProperties); + + @Override + @RequiredUIAccess + @RequiredWriteAction + public void invoke(@Nonnull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + evalAnchor(editor, file); + + for (JSVariable e : getElementsToProcess()) { + anchor = doAddOneMethod(project, generateGetterFix.buildFunctionText(e), anchor); + anchor = doAddOneMethod(project, generateSetterFix.buildFunctionText(e), anchor); + } + } + }; + } + else if (mode == GenerationMode.CONSTRUCTOR) { + return new BaseCreateMethodsFix(jsClass) { + @Override + @RequiredUIAccess + @RequiredWriteAction + public void invoke(@Nonnull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + JSCodeStyleSettings codeStyleSettings = + CodeStyleSettingsManager.getSettings(project).getCustomSettings(JSCodeStyleSettings.class); + evalAnchor(editor, file); + StringBuilder functionText = new StringBuilder("public function ").append(jsClass.getName()).append("("); + StringBuilder initialization = new StringBuilder(); + boolean first = true; + String semicolon = JSChangeUtil.getSemicolon(project); + + Set toProcess = getElementsToProcess(); + Iterator variableIterator = toProcess.iterator(); + boolean hadSuperClassConstructorInitializationBefore = false; + + while (variableIterator.hasNext()) { + JSVariable var = variableIterator.next(); + if (!first) { + functionText.append(", "); + } + + first = false; + + String name = var.getName(); + String parameterName = transformVarNameToAccessorName(name, codeStyleSettings); + + String typeString = var.getTypeString(); + functionText.append(parameterName).append(typeString != null ? ":" + typeString : ""); + + if (JSResolveUtil.findParent(var) == jsClass) { + if (hadSuperClassConstructorInitializationBefore) { + initialization.append(")").append(semicolon).append("\n"); + hadSuperClassConstructorInitializationBefore = false; + } + initialization.append(parameterName.equals(name) ? "this." : "") + .append(name) + .append(" = ") + .append(parameterName) + .append(semicolon) + .append("\n"); + } + else { + if (hadSuperClassConstructorInitializationBefore) { + initialization.append(", "); + } + else { + initialization.append("super("); + } + initialization.append(parameterName); + hadSuperClassConstructorInitializationBefore = true; + } + } + + if (hadSuperClassConstructorInitializationBefore) { + initialization.append(")").append(semicolon).append("\n"); + } + functionText.append(") {\n") + .append(initialization) + .append("}"); + doAddOneMethod(project, functionText.toString(), anchor); + } + + @Override + @RequiredReadAction + public Set getElementsToProcess() { + LinkedHashSet vars = new LinkedHashSet<>(); + JSFunction nontrivialSuperClassConstructor = JSAnnotatingVisitor.getNontrivialSuperClassConstructor(jsClass); + + if (nontrivialSuperClassConstructor != null) { + vars.addAll(Arrays.asList(nontrivialSuperClassConstructor.getParameterList().getParameters())); + } + vars.addAll(super.getElementsToProcess()); + return vars; + } + }; + } + else if (mode == GenerationMode.TOSTRING) { + return new BaseCreateMethodsFix(jsClass) { + @Override + @RequiredUIAccess + @RequiredWriteAction + public void invoke(@Nonnull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + evalAnchor(editor, file); + + boolean[] needOverride = new boolean[1]; + JSResolveUtil.processOverrides( + jsClass, + (processor, scope, className) -> { + needOverride[0] = !"Object".equals(className); + return false; + }, + "toString", + null, + myJsClass + ); + + StringBuilder functionText = new StringBuilder().append("public ") + .append(needOverride[0] ? "override " : "") + .append("function toString():String {\nreturn ") + .append(needOverride[0] ? "super.toString() + \"" : "\"" + jsClass.getName()) + .append("{"); + String semicolon = JSChangeUtil.getSemicolon(project); + + boolean first = true; + + for (JSVariable var : getElementsToProcess()) { + if (!first) { + functionText.append(" + \","); + } + first = false; + + functionText.append(var.getName()).append("=\" + String(").append(var.getName()).append(")"); + } + + functionText.append("+\"}\"").append(semicolon).append("\n}"); + doAddOneMethod(project, functionText.toString(), anchor); + } + }; + } + + return new MyBaseCreateMethodsFix( + mode, + jsClass, + myCreateBindableProperties != null && myCreateBindableProperties.isSelected() + ); + } + + @Override + @RequiredReadAction + protected void collectCandidates(JSClass clazz, Collection candidates) { + final LinkedHashMap candidatesMap = new LinkedHashMap<>(); + final JSCodeStyleSettings codeStyleSettings = + CodeStyleSettingsManager.getSettings(clazz.getProject()).getCustomSettings(JSCodeStyleSettings.class); + ResolveProcessor processor = new ResolveProcessor(null) { + { + setToProcessMembers(true); + setToProcessHierarchy(false); + setLocalResolve(true); + } + + @Override + @RequiredReadAction + public boolean execute(@Nonnull PsiElement element, ResolveState state) { + if (element instanceof JSVariable variable) { + if (variable.isConst()) { + return true; + } + String name = variable.getName(); + String accessorName = transformVarNameToAccessorName(name, codeStyleSettings); + if (/*!name.equals(accessorName) &&*/ !candidatesMap.containsKey(accessorName)) { + candidatesMap.put(accessorName, variable); + } + } + else if (element instanceof JSFunction function + && (mode == GenerationMode.GETTERS && function.isGetProperty() + || mode == GenerationMode.SETTERS && function.isSetProperty())) { + candidatesMap.put(function.getName(), function); + } + return true; + } + }; + + clazz.processDeclarations(processor, ResolveState.initial(), clazz, clazz); + for (JSNamedElement n : candidatesMap.values()) { + if (n instanceof JSVariable variable) { + candidates.add(new JSNamedElementNode(variable)); + } + } + } + + private static class MyBaseCreateMethodsFix extends BaseCreateMethodsFix { + private GenerationMode myMode; + private JSCodeStyleSettings codeStyleSettings; + private boolean bindableProperties; + private static final String PARAMETER_NAME = "value"; + + public MyBaseCreateMethodsFix(GenerationMode mode, JSClass jsClass, boolean _bindableProperties) { + super(jsClass); + this.myMode = mode; + codeStyleSettings = CodeStyleSettingsManager.getSettings(jsClass.getProject()).getCustomSettings(JSCodeStyleSettings.class); + bindableProperties = _bindableProperties; + } + + @Override + @RequiredReadAction + protected String buildFunctionBodyText(String retType, JSParameterList parameterList, JSVariable func) { + String semicolon = codeStyleSettings.USE_SEMICOLON_AFTER_STATEMENT ? ";" : ""; + String varName = func.getName(); + if (myMode == GenerationMode.SETTERS) { + String checkNeedEvent = ""; + String dispatchEvent = ""; + if (bindableProperties) { + String eventName = getEventName(transformVarNameToAccessorName(varName, codeStyleSettings)); + dispatchEvent = "\ndispatchEvent(new Event(\"" + eventName + "\"))" + semicolon; + checkNeedEvent = "if(" + varName + "==" + PARAMETER_NAME + ") return" + semicolon + "\n"; + } + return "{\n" + checkNeedEvent + varName + "=" + PARAMETER_NAME + semicolon + dispatchEvent + "\n}"; + } + else if (myMode == GenerationMode.GETTERS) { + return "{\nreturn " + varName + semicolon + "\n}"; + } + return " {}"; + } + + @Override + @RequiredReadAction + protected String buildFunctionAttrText(String attrText, JSAttributeList attributeList, JSVariable function) { + StringBuilder baseText = new StringBuilder(); + + if (bindableProperties && myMode == GenerationMode.GETTERS) { + baseText.append("[Bindable(event=\"") + .append(getEventName(transformVarNameToAccessorName(function.getName(), codeStyleSettings))) + .append("\")]\n"); + } + + baseText.append("public"); + if (attributeList != null && attributeList.hasModifier(JSAttributeList.ModifierType.STATIC)) { + baseText.append(" static"); + } + + return baseText.toString(); + } + + private static String getEventName(String name) { + return name + "Changed"; + } + + @Override + @RequiredReadAction + protected String buildFunctionKind(JSVariable fun) { + if (myMode == GenerationMode.GETTERS) { + return "get "; + } + if (myMode == GenerationMode.SETTERS) { + return "set "; + } + return super.buildFunctionKind(fun); + } + + @Override + protected String buildReturnType(String typeString) { + if (myMode == GenerationMode.SETTERS) { + return "void"; + } + return super.buildReturnType(typeString); + } + + @Override + @RequiredReadAction + protected String buildName(JSVariable fun) { + return transformVarNameToAccessorName(super.buildName(fun), codeStyleSettings); + } + + @Override + @RequiredReadAction + protected String buildParameterList(JSParameterList parameterList, JSVariable fun) { + if (myMode == GenerationMode.SETTERS) { + String s = fun.getTypeString(); + return "(" + PARAMETER_NAME + (s != null ? ":" + s : "") + ")"; + } + return (parameterList != null ? parameterList.getText() : "()"); + } + } + + private static String transformVarNameToAccessorName(String s, JSCodeStyleSettings codeStyleSettings) { + if (StringUtil.startsWith(s, codeStyleSettings.FIELD_PREFIX)) { + s = s.substring(codeStyleSettings.FIELD_PREFIX.length()); + } + return codeStyleSettings.PROPERTY_PREFIX + s; + } + + @Override + protected boolean canHaveEmptySelectedElements() { + return mode == GenerationMode.CONSTRUCTOR; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptGenerateConstructorAction.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptGenerateConstructorAction.java index b785ad13..2310a447 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptGenerateConstructorAction.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptGenerateConstructorAction.java @@ -16,16 +16,16 @@ package com.intellij.lang.javascript.impl.generation; +import jakarta.annotation.Nonnull; + /** * @author Maxim.Mossienko - * Date: Jul 19, 2008 - * Time: 1:01:05 AM + * @since 2008-07-19 */ -public class JavaScriptGenerateConstructorAction extends BaseJSGenerateAction -{ - @Override - protected JavaScriptGenerateAccessorHandler.GenerationMode getGenerationMode() - { - return JavaScriptGenerateAccessorHandler.GenerationMode.CONSTRUCTOR; - } +public class JavaScriptGenerateConstructorAction extends BaseJSGenerateAction { + @Nonnull + @Override + protected JavaScriptGenerateAccessorHandler.GenerationMode getGenerationMode() { + return JavaScriptGenerateAccessorHandler.GenerationMode.CONSTRUCTOR; + } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptGenerateGetAccessorAction.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptGenerateGetAccessorAction.java index a8f9a99c..f14bc809 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptGenerateGetAccessorAction.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptGenerateGetAccessorAction.java @@ -16,16 +16,16 @@ package com.intellij.lang.javascript.impl.generation; +import jakarta.annotation.Nonnull; + /** * @author Maxim.Mossienko - * Date: Jul 19, 2008 - * Time: 1:01:05 AM + * @since 2008-07-19 */ -public class JavaScriptGenerateGetAccessorAction extends BaseJSGenerateAction -{ - @Override - protected JavaScriptGenerateAccessorHandler.GenerationMode getGenerationMode() - { - return JavaScriptGenerateAccessorHandler.GenerationMode.GETTERS; - } +public class JavaScriptGenerateGetAccessorAction extends BaseJSGenerateAction { + @Nonnull + @Override + protected JavaScriptGenerateAccessorHandler.GenerationMode getGenerationMode() { + return JavaScriptGenerateAccessorHandler.GenerationMode.GETTERS; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptGenerateGetSetAccessorAction.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptGenerateGetSetAccessorAction.java index 7f5a2ad9..024faa37 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptGenerateGetSetAccessorAction.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptGenerateGetSetAccessorAction.java @@ -16,17 +16,16 @@ package com.intellij.lang.javascript.impl.generation; +import jakarta.annotation.Nonnull; + /** * @author Maxim.Mossienko - * Date: Jul 19, 2008 - * Time: 1:01:05 AM + * @since 2008-07-19 */ -public class JavaScriptGenerateGetSetAccessorAction extends BaseJSGenerateAction -{ - - @Override - protected JavaScriptGenerateAccessorHandler.GenerationMode getGenerationMode() - { - return JavaScriptGenerateAccessorHandler.GenerationMode.GETTERS_AND_SETTERS; - } +public class JavaScriptGenerateGetSetAccessorAction extends BaseJSGenerateAction { + @Nonnull + @Override + protected JavaScriptGenerateAccessorHandler.GenerationMode getGenerationMode() { + return JavaScriptGenerateAccessorHandler.GenerationMode.GETTERS_AND_SETTERS; + } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptGenerateSetAccessorAction.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptGenerateSetAccessorAction.java index 84270251..1b16e1b3 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptGenerateSetAccessorAction.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptGenerateSetAccessorAction.java @@ -16,16 +16,16 @@ package com.intellij.lang.javascript.impl.generation; +import jakarta.annotation.Nonnull; + /** * @author Maxim.Mossienko - * Date: Jul 19, 2008 - * Time: 1:01:05 AM + * @since 2008-07-19 */ -public class JavaScriptGenerateSetAccessorAction extends BaseJSGenerateAction -{ - @Override - protected JavaScriptGenerateAccessorHandler.GenerationMode getGenerationMode() - { - return JavaScriptGenerateAccessorHandler.GenerationMode.SETTERS; - } +public class JavaScriptGenerateSetAccessorAction extends BaseJSGenerateAction { + @Nonnull + @Override + protected JavaScriptGenerateAccessorHandler.GenerationMode getGenerationMode() { + return JavaScriptGenerateAccessorHandler.GenerationMode.SETTERS; + } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptGenerateToStringAction.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptGenerateToStringAction.java index e2647571..f3a3b958 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptGenerateToStringAction.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptGenerateToStringAction.java @@ -16,16 +16,16 @@ package com.intellij.lang.javascript.impl.generation; +import jakarta.annotation.Nonnull; + /** * @author Maxim.Mossienko - * Date: Jul 19, 2008 - * Time: 1:01:05 AM + * @since 2008-07-19 */ -public class JavaScriptGenerateToStringAction extends BaseJSGenerateAction -{ - @Override - protected JavaScriptGenerateAccessorHandler.GenerationMode getGenerationMode() - { - return JavaScriptGenerateAccessorHandler.GenerationMode.TOSTRING; - } +public class JavaScriptGenerateToStringAction extends BaseJSGenerateAction { + @Nonnull + @Override + protected JavaScriptGenerateAccessorHandler.GenerationMode getGenerationMode() { + return JavaScriptGenerateAccessorHandler.GenerationMode.TOSTRING; + } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptImplementMethodsHandler.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptImplementMethodsHandler.java index d4c5c491..f915e3db 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptImplementMethodsHandler.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptImplementMethodsHandler.java @@ -19,44 +19,42 @@ */ package com.intellij.lang.javascript.impl.generation; -import com.intellij.lang.javascript.psi.JSClass; -import com.intellij.lang.javascript.psi.JSFunction; -import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; import com.intellij.lang.javascript.impl.validation.BaseCreateMethodsFix; import com.intellij.lang.javascript.impl.validation.ImplementMethodsFix; import com.intellij.lang.javascript.impl.validation.ImplementedMethodProcessor; +import com.intellij.lang.javascript.psi.JSClass; +import com.intellij.lang.javascript.psi.JSFunction; +import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.editor.generation.ImplementMethodHandler; +import consulo.localize.LocalizeValue; import java.util.Collection; @ExtensionImpl -public class JavaScriptImplementMethodsHandler extends BaseJSGenerateHandler implements ImplementMethodHandler -{ - @Override - protected void collectCandidates(final JSClass clazz, final Collection candidates) - { - ImplementedMethodProcessor processor = new ImplementedMethodProcessor(clazz) - { - @Override - protected void addNonimplementedFunction(final JSFunction function) - { - candidates.add(new JSNamedElementNode(function)); - } - }; +public class JavaScriptImplementMethodsHandler extends BaseJSGenerateHandler implements ImplementMethodHandler { + @Override + protected void collectCandidates(JSClass clazz, final Collection candidates) { + ImplementedMethodProcessor processor = new ImplementedMethodProcessor(clazz) { + @Override + @RequiredReadAction + protected void addNonimplementedFunction(JSFunction function) { + candidates.add(new JSNamedElementNode(function)); + } + }; - JSResolveUtil.processInterfaceMethods(clazz, processor); - } + JSResolveUtil.processInterfaceMethods(clazz, processor); + } - @Override - protected String getTitleKey() - { - return "methods.to.implement.chooser.title"; - } + @Override + protected LocalizeValue getTitle() { + return JavaScriptLocalize.methodsToImplementChooserTitle(); + } - @Override - protected BaseCreateMethodsFix createFix(final JSClass clazz) - { - return new ImplementMethodsFix(clazz); - } + @Override + protected BaseCreateMethodsFix createFix(JSClass clazz) { + return new ImplementMethodsFix(clazz); + } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptOverrideMethodsHandler.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptOverrideMethodsHandler.java index 94919eee..b2a900e2 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptOverrideMethodsHandler.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/JavaScriptOverrideMethodsHandler.java @@ -19,114 +19,97 @@ */ package com.intellij.lang.javascript.impl.generation; +import com.intellij.lang.javascript.impl.validation.BaseCreateMethodsFix; +import com.intellij.lang.javascript.impl.validation.ImplementedMethodProcessor; import com.intellij.lang.javascript.psi.JSAttributeList; import com.intellij.lang.javascript.psi.JSClass; import com.intellij.lang.javascript.psi.JSFunction; import com.intellij.lang.javascript.psi.resolve.ResolveProcessor; -import com.intellij.lang.javascript.impl.validation.BaseCreateMethodsFix; -import com.intellij.lang.javascript.impl.validation.ImplementedMethodProcessor; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.editor.generation.OverrideMethodHandler; import consulo.language.psi.PsiElement; import consulo.language.psi.resolve.ResolveState; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; import java.util.Collection; import java.util.Map; import java.util.function.Function; @ExtensionImpl -public class JavaScriptOverrideMethodsHandler extends BaseJSGenerateHandler implements OverrideMethodHandler -{ - @Override - protected String getTitleKey() - { - return "methods.to.override.chooser.title"; - } +public class JavaScriptOverrideMethodsHandler extends BaseJSGenerateHandler implements OverrideMethodHandler { + @Override + protected LocalizeValue getTitle() { + return JavaScriptLocalize.methodsToOverrideChooserTitle(); + } - @Override - protected BaseCreateMethodsFix createFix(final JSClass clazz) - { - return new OverrideMethodsFix(clazz); - } + @Override + protected BaseCreateMethodsFix createFix(JSClass clazz) { + return new OverrideMethodsFix(clazz); + } - @Override - protected void collectCandidates(final JSClass clazz, final Collection candidates) - { - Map _functionsToOverride = null; - final Function functionFilter = new Function() - { - @Override - public Boolean apply(final JSFunction function) - { - final JSAttributeList attributeList = function.getAttributeList(); + @Override + @RequiredReadAction + protected void collectCandidates(JSClass clazz, Collection candidates) { + Map _functionsToOverride = null; + Function functionFilter = function -> { + JSAttributeList attributeList = function.getAttributeList(); - if(attributeList != null && (attributeList.hasModifier(JSAttributeList.ModifierType.STATIC) || attributeList.hasModifier(JSAttributeList - .ModifierType.FINAL))) - { - return Boolean.FALSE; - } - return Boolean.TRUE; - } - }; + if (attributeList != null && (attributeList.hasModifier(JSAttributeList.ModifierType.STATIC) + || attributeList.hasModifier(JSAttributeList.ModifierType.FINAL))) { + return Boolean.FALSE; + } + return Boolean.TRUE; + }; - for(JSClass superClazz : clazz.getSuperClasses()) - { - _functionsToOverride = ImplementedMethodProcessor.collectAllVisibleClassFunctions(superClazz, _functionsToOverride, functionFilter); - } + for (JSClass superClazz : clazz.getSuperClasses()) { + _functionsToOverride = + ImplementedMethodProcessor.collectAllVisibleClassFunctions(superClazz, _functionsToOverride, functionFilter); + } - final Map functionsToOverride = _functionsToOverride; - final ResolveProcessor collectOwnFunctions = new ResolveProcessor(null, clazz) - { - { - setToProcessMembers(true); - setToProcessHierarchy(false); - } + final Map functionsToOverride = _functionsToOverride; + ResolveProcessor collectOwnFunctions = new ResolveProcessor(null, clazz) { + { + setToProcessMembers(true); + setToProcessHierarchy(false); + } - @Override - public boolean execute(final PsiElement element, final ResolveState state) - { - if(element instanceof JSFunction) - { - final JSFunction function = (JSFunction) element; - if(function.isConstructor() || functionsToOverride == null) - { - return true; - } - final String funName = function.getName(); - final Object o = functionsToOverride.get(funName); - if(o instanceof JSFunction && ((JSFunction) o).getKind() == function.getKind()) - { - functionsToOverride.remove(funName); - } - else if(o instanceof JSFunction[]) - { - JSFunction[] functions = (JSFunction[]) o; - functionsToOverride.put(funName, functions[0].getKind() == function.getKind() ? functions[1] : functions[0]); - } - } - return true; - } - }; + @Override + @RequiredReadAction + public boolean execute(@Nonnull PsiElement element, ResolveState state) { + if (element instanceof JSFunction function) { + if (function.isConstructor() || functionsToOverride == null) { + return true; + } + String funName = function.getName(); + Object o = functionsToOverride.get(funName); + if (o instanceof JSFunction oFun && oFun.getKind() == function.getKind()) { + functionsToOverride.remove(funName); + } + else if (o instanceof JSFunction[] oFuns) { + functionsToOverride.put(funName, oFuns[0].getKind() == function.getKind() ? oFuns[1] : oFuns[0]); + } + } + return true; + } + }; - clazz.processDeclarations(collectOwnFunctions, ResolveState.initial(), clazz, clazz); + clazz.processDeclarations(collectOwnFunctions, ResolveState.initial(), clazz, clazz); - if(functionsToOverride != null) - { - for(Map.Entry entry : functionsToOverride.entrySet()) - { - final Object value = entry.getValue(); - if(value instanceof JSFunction[]) - { - for(JSFunction function : (JSFunction[]) value) - { - candidates.add(new JSNamedElementNode(function)); - } - } - else - { - candidates.add(new JSNamedElementNode((JSFunction) value)); - } - } - } - } + if (functionsToOverride != null) { + for (Map.Entry entry : functionsToOverride.entrySet()) { + Object value = entry.getValue(); + if (value instanceof JSFunction[] functions) { + for (JSFunction function : functions) { + candidates.add(new JSNamedElementNode(function)); + } + } + else { + candidates.add(new JSNamedElementNode((JSFunction)value)); + } + } + } + } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/OverrideMethodsFix.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/OverrideMethodsFix.java index a7b8bee4..528c48d7 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/OverrideMethodsFix.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/generation/OverrideMethodsFix.java @@ -16,97 +16,77 @@ package com.intellij.lang.javascript.impl.generation; -import org.jetbrains.annotations.NonNls; -import com.intellij.lang.javascript.psi.JSAttributeList; -import com.intellij.lang.javascript.psi.JSClass; -import com.intellij.lang.javascript.psi.JSFunction; -import com.intellij.lang.javascript.psi.JSParameter; -import com.intellij.lang.javascript.psi.JSParameterList; +import com.intellij.lang.javascript.impl.validation.BaseCreateMethodsFix; +import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.impl.JSChangeUtil; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; -import com.intellij.lang.javascript.impl.validation.BaseCreateMethodsFix; +import consulo.annotation.access.RequiredReadAction; import consulo.language.psi.PsiElement; /** * @author Maxim.Mossienko - * Date: Jul 17, 2008 - * Time: 9:39:02 PM + * @since 2008-07-17 */ -public class OverrideMethodsFix extends BaseCreateMethodsFix -{ - public OverrideMethodsFix(final JSClass jsClass) - { - super(jsClass); - } - - @Override - protected String buildFunctionBodyText(final String retType, final JSParameterList parameterList, final JSFunction func) - { - @NonNls String functionText = ""; - functionText += "{\n"; - - if(!"void".equals(retType)) - { - functionText += " return"; - } - else - { - functionText += " "; - } +public class OverrideMethodsFix extends BaseCreateMethodsFix { + public OverrideMethodsFix(JSClass jsClass) { + super(jsClass); + } - functionText += " super." + func.getName(); + @Override + @RequiredReadAction + protected String buildFunctionBodyText(String retType, JSParameterList parameterList, JSFunction func) { + StringBuilder functionText = new StringBuilder(); + functionText.append("{\n"); - if(func.isGetProperty()) - { + if (!"void".equals(retType)) { + functionText.append(" return"); + } + else { + functionText.append(" "); + } - } - else if(func.isSetProperty()) - { - functionText += " = " + parameterList.getParameters()[0].getName(); - } - else - { - functionText += "("; - boolean first = true; - for(JSParameter param : parameterList.getParameters()) - { - if(!first) - { - functionText += ","; - } - first = false; - functionText += param.getName(); - } - functionText += ")"; - } + functionText.append(" super.").append(func.getName()); - functionText += JSChangeUtil.getSemicolon(func.getProject()) + "\n}"; - return functionText; - } + if (func.isGetProperty()) { + } + else if (func.isSetProperty()) { + functionText.append(" = ").append(parameterList.getParameters()[0].getName()); + } + else { + functionText.append("("); + boolean first = true; + for (JSParameter param : parameterList.getParameters()) { + if (!first) { + functionText.append(","); + } + first = false; + functionText.append(param.getName()); + } + functionText.append(")"); + } - @Override - protected String buildFunctionAttrText(String attrText, final JSAttributeList attributeList, final JSFunction function) - { - attrText = super.buildFunctionAttrText(attrText, attributeList, function); - final PsiElement element = JSResolveUtil.findParent(function); - if(attributeList == null || !attributeList.hasModifier(JSAttributeList.ModifierType.OVERRIDE)) - { + functionText.append(JSChangeUtil.getSemicolon(func.getProject())).append("\n}"); + return functionText.toString(); + } - if(element instanceof JSClass && !"Object".equals(((JSClass) element).getQualifiedName())) - { - final PsiElement typeElement = attributeList != null ? attributeList.findAccessTypeElement() : null; - if(typeElement == null) - { - attrText += " override"; - } - else - { - final int index = attrText.indexOf(typeElement.getText()); - attrText = attrText.substring(0, index) + ((index > 0) ? " " : "") + "override " + attrText.substring(index); - } - } - } + @Override + @RequiredReadAction + protected String buildFunctionAttrText(String attrText, JSAttributeList attributeList, JSFunction function) { + attrText = super.buildFunctionAttrText(attrText, attributeList, function); + PsiElement element = JSResolveUtil.findParent(function); + if (attributeList == null || !attributeList.hasModifier(JSAttributeList.ModifierType.OVERRIDE)) { + if (element instanceof JSClass jsClass && !"Object".equals(jsClass.getQualifiedName())) { + PsiElement typeElement = attributeList != null ? attributeList.findAccessTypeElement() : null; + if (typeElement == null) { + attrText += " override"; + } + else { + int index = attrText.indexOf(typeElement.getText()); + attrText = attrText.substring(0, index) + ((index > 0) ? " " : "") + "override " + attrText.substring(index); + } + } + } - return attrText; - } + return attrText; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/highlighting/JSBraceMatcher.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/highlighting/JSBraceMatcher.java index e57866ee..03950783 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/highlighting/JSBraceMatcher.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/highlighting/JSBraceMatcher.java @@ -23,42 +23,42 @@ import consulo.language.Language; import consulo.language.PairedBraceMatcher; import consulo.language.ast.IElementType; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; /** - * User: max - * Date: Feb 2, 2005 - * Time: 12:10:44 PM + * @author max + * @since 2005-02-02 */ @ExtensionImpl -public class JSBraceMatcher implements PairedBraceMatcher -{ - private static final BracePair[] PAIRS = new BracePair[]{ - new BracePair(JSTokenTypes.LPAR, JSTokenTypes.RPAR, false), - new BracePair(JSTokenTypes.LBRACKET, JSTokenTypes.RBRACKET, false), - new BracePair(JSTokenTypes.LBRACE, JSTokenTypes.RBRACE, true) - }; +public class JSBraceMatcher implements PairedBraceMatcher { + private static final BracePair[] PAIRS = new BracePair[]{ + new BracePair(JSTokenTypes.LPAR, JSTokenTypes.RPAR, false), + new BracePair(JSTokenTypes.LBRACKET, JSTokenTypes.RBRACKET, false), + new BracePair(JSTokenTypes.LBRACE, JSTokenTypes.RBRACE, true) + }; - @Override - public BracePair[] getPairs() - { - return PAIRS; - } + @Override + public BracePair[] getPairs() { + return PAIRS; + } - @Override - public boolean isPairedBracesAllowedBeforeType(@Nonnull final IElementType lbraceType, @Nullable final IElementType tokenType) - { - return JSTokenTypes.WHITE_SPACE == tokenType || JSTokenTypes.COMMENTS.contains(tokenType) || tokenType == JSTokenTypes.SEMICOLON || tokenType == - JSTokenTypes.COMMA || tokenType == JSTokenTypes.RPAR || tokenType == JSTokenTypes.RBRACKET || tokenType == JSTokenTypes.RBRACE || null == - tokenType; - } + @Override + public boolean isPairedBracesAllowedBeforeType(@Nonnull IElementType lbraceType, @Nullable IElementType tokenType) { + return tokenType == JSTokenTypes.WHITE_SPACE + || JSTokenTypes.COMMENTS.contains(tokenType) + || tokenType == JSTokenTypes.SEMICOLON + || tokenType == JSTokenTypes.COMMA + || tokenType == JSTokenTypes.RPAR + || tokenType == JSTokenTypes.RBRACKET + || tokenType == JSTokenTypes.RBRACE + || tokenType == null; + } - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/highlighting/JavaScriptColorsAndFontsPage.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/highlighting/JavaScriptColorsAndFontsPage.java index 3e54999a..296abfcf 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/highlighting/JavaScriptColorsAndFontsPage.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/highlighting/JavaScriptColorsAndFontsPage.java @@ -16,127 +16,128 @@ package com.intellij.lang.javascript.impl.highlighting; -import consulo.javascript.language.JavaScriptBundle; import consulo.annotation.component.ExtensionImpl; import consulo.colorScheme.TextAttributesKey; import consulo.colorScheme.setting.AttributesDescriptor; -import consulo.colorScheme.setting.ColorDescriptor; import consulo.javascript.ide.hightlight.JavaScriptSyntaxHighlightKeys; import consulo.javascript.lang.JavaScript15LanguageVersion; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.editor.colorScheme.setting.ColorSettingsPage; import consulo.language.editor.highlight.SyntaxHighlighter; -import org.jetbrains.annotations.NonNls; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; import java.util.HashMap; import java.util.Map; /** - * User: Maxim.Mossienko - * Date: Nov 2, 2005 - * Time: 10:12:13 PM + * @author Maxim.Mossienko + * @since 2005-11-02 */ @ExtensionImpl -public class JavaScriptColorsAndFontsPage implements ColorSettingsPage -{ - private static final AttributesDescriptor[] ATTRS; +public class JavaScriptColorsAndFontsPage implements ColorSettingsPage { + private static final AttributesDescriptor[] ATTRS; - @NonNls - private static Map ADDITIONAL_HIGHLIGHT_DESCRIPTORS = new HashMap(); + private static Map ADDITIONAL_HIGHLIGHT_DESCRIPTORS = new HashMap<>(); - static - { - ATTRS = new AttributesDescriptor[]{ - new AttributesDescriptor(JavaScriptBundle.message("javascript.keyword"), JavaScriptSyntaxHighlightKeys.JS_KEYWORD), - new AttributesDescriptor(JavaScriptBundle.message("javascript.string"), JavaScriptSyntaxHighlightKeys.JS_STRING), - new AttributesDescriptor(JavaScriptBundle.message("javascript.valid.string.escape"), JavaScriptSyntaxHighlightKeys.JS_VALID_STRING_ESCAPE), - new AttributesDescriptor(JavaScriptBundle.message("javascript.invalid.string.escape"), JavaScriptSyntaxHighlightKeys.JS_INVALID_STRING_ESCAPE), - new AttributesDescriptor(JavaScriptBundle.message("javascript.number"), JavaScriptSyntaxHighlightKeys.JS_NUMBER), - new AttributesDescriptor(JavaScriptBundle.message("javascript.regexp"), JavaScriptSyntaxHighlightKeys.JS_REGEXP), - new AttributesDescriptor(JavaScriptBundle.message("javascript.linecomment"), JavaScriptSyntaxHighlightKeys.JS_LINE_COMMENT), - new AttributesDescriptor(JavaScriptBundle.message("javascript.blockcomment"), JavaScriptSyntaxHighlightKeys.JS_BLOCK_COMMENT), - new AttributesDescriptor(JavaScriptBundle.message("javascript.doccomment"), JavaScriptSyntaxHighlightKeys.JS_DOC_COMMENT), - new AttributesDescriptor(JavaScriptBundle.message("javascript.operation"), JavaScriptSyntaxHighlightKeys.JS_OPERATION_SIGN), - new AttributesDescriptor(JavaScriptBundle.message("javascript.parens"), JavaScriptSyntaxHighlightKeys.JS_PARENTHS), - new AttributesDescriptor(JavaScriptBundle.message("javascript.brackets"), JavaScriptSyntaxHighlightKeys.JS_BRACKETS), - new AttributesDescriptor(JavaScriptBundle.message("javascript.braces"), JavaScriptSyntaxHighlightKeys.JS_BRACES), - new AttributesDescriptor(JavaScriptBundle.message("javascript.comma"), JavaScriptSyntaxHighlightKeys.JS_COMMA), - new AttributesDescriptor(JavaScriptBundle.message("javascript.dot"), JavaScriptSyntaxHighlightKeys.JS_DOT), - new AttributesDescriptor(JavaScriptBundle.message("javascript.semicolon"), JavaScriptSyntaxHighlightKeys.JS_SEMICOLON), - new AttributesDescriptor(JavaScriptBundle.message("javascript.badcharacter"), JavaScriptSyntaxHighlightKeys.JS_BAD_CHARACTER), - new AttributesDescriptor(JavaScriptBundle.message("javascript.docmarkup"), JavaScriptSyntaxHighlightKeys.JS_DOC_MARKUP), - new AttributesDescriptor(JavaScriptBundle.message("javascript.doctag"), JavaScriptSyntaxHighlightKeys.JS_DOC_TAG), - new AttributesDescriptor(JavaScriptBundle.message("javascript.parameter"), JavaScriptSyntaxHighlightKeys.JS_PARAMETER), - new AttributesDescriptor(JavaScriptBundle.message("javascript.local.variable"), JavaScriptSyntaxHighlightKeys.JS_LOCAL_VARIABLE), - new AttributesDescriptor(JavaScriptBundle.message("javascript.global.variable"), JavaScriptSyntaxHighlightKeys.JS_GLOBAL_VARIABLE), - new AttributesDescriptor(JavaScriptBundle.message("javascript.global.function"), JavaScriptSyntaxHighlightKeys.JS_GLOBAL_FUNCTION), - new AttributesDescriptor(JavaScriptBundle.message("javascript.instance.member.function"), JavaScriptSyntaxHighlightKeys.JS_INSTANCE_MEMBER_FUNCTION), - new AttributesDescriptor(JavaScriptBundle.message("javascript.static.member.function"), JavaScriptSyntaxHighlightKeys.JS_STATIC_MEMBER_FUNCTION), - new AttributesDescriptor(JavaScriptBundle.message("javascript.static.member.variable"), JavaScriptSyntaxHighlightKeys.JS_STATIC_MEMBER_VARIABLE), - new AttributesDescriptor(JavaScriptBundle.message("javascript.instance.member.variable"), JavaScriptSyntaxHighlightKeys.JS_INSTANCE_MEMBER_VARIABLE), - new AttributesDescriptor(JavaScriptBundle.message("javascript.metadata"), JavaScriptSyntaxHighlightKeys.JS_METADATA), - }; - ADDITIONAL_HIGHLIGHT_DESCRIPTORS.put("local_variable", JavaScriptSyntaxHighlightKeys.JS_LOCAL_VARIABLE); - ADDITIONAL_HIGHLIGHT_DESCRIPTORS.put("global_variable", JavaScriptSyntaxHighlightKeys.JS_GLOBAL_VARIABLE); - ADDITIONAL_HIGHLIGHT_DESCRIPTORS.put("instance_variable", JavaScriptSyntaxHighlightKeys.JS_INSTANCE_MEMBER_VARIABLE); - ADDITIONAL_HIGHLIGHT_DESCRIPTORS.put("instance_method", JavaScriptSyntaxHighlightKeys.JS_INSTANCE_MEMBER_FUNCTION); - ADDITIONAL_HIGHLIGHT_DESCRIPTORS.put("global_function", JavaScriptSyntaxHighlightKeys.JS_GLOBAL_FUNCTION); - ADDITIONAL_HIGHLIGHT_DESCRIPTORS.put("parameter", JavaScriptSyntaxHighlightKeys.JS_PARAMETER); - } + static { + ATTRS = new AttributesDescriptor[]{ + new AttributesDescriptor(JavaScriptLocalize.javascriptKeyword(), JavaScriptSyntaxHighlightKeys.JS_KEYWORD), + new AttributesDescriptor(JavaScriptLocalize.javascriptString(), JavaScriptSyntaxHighlightKeys.JS_STRING), + new AttributesDescriptor( + JavaScriptLocalize.javascriptValidStringEscape(), + JavaScriptSyntaxHighlightKeys.JS_VALID_STRING_ESCAPE + ), + new AttributesDescriptor( + JavaScriptLocalize.javascriptInvalidStringEscape(), + JavaScriptSyntaxHighlightKeys.JS_INVALID_STRING_ESCAPE + ), + new AttributesDescriptor(JavaScriptLocalize.javascriptNumber(), JavaScriptSyntaxHighlightKeys.JS_NUMBER), + new AttributesDescriptor(JavaScriptLocalize.javascriptRegexp(), JavaScriptSyntaxHighlightKeys.JS_REGEXP), + new AttributesDescriptor(JavaScriptLocalize.javascriptLinecomment(), JavaScriptSyntaxHighlightKeys.JS_LINE_COMMENT), + new AttributesDescriptor(JavaScriptLocalize.javascriptBlockcomment(), JavaScriptSyntaxHighlightKeys.JS_BLOCK_COMMENT), + new AttributesDescriptor(JavaScriptLocalize.javascriptDoccomment(), JavaScriptSyntaxHighlightKeys.JS_DOC_COMMENT), + new AttributesDescriptor(JavaScriptLocalize.javascriptOperation(), JavaScriptSyntaxHighlightKeys.JS_OPERATION_SIGN), + new AttributesDescriptor(JavaScriptLocalize.javascriptParens(), JavaScriptSyntaxHighlightKeys.JS_PARENTHS), + new AttributesDescriptor(JavaScriptLocalize.javascriptBrackets(), JavaScriptSyntaxHighlightKeys.JS_BRACKETS), + new AttributesDescriptor(JavaScriptLocalize.javascriptBraces(), JavaScriptSyntaxHighlightKeys.JS_BRACES), + new AttributesDescriptor(JavaScriptLocalize.javascriptComma(), JavaScriptSyntaxHighlightKeys.JS_COMMA), + new AttributesDescriptor(JavaScriptLocalize.javascriptDot(), JavaScriptSyntaxHighlightKeys.JS_DOT), + new AttributesDescriptor(JavaScriptLocalize.javascriptSemicolon(), JavaScriptSyntaxHighlightKeys.JS_SEMICOLON), + new AttributesDescriptor(JavaScriptLocalize.javascriptBadcharacter(), JavaScriptSyntaxHighlightKeys.JS_BAD_CHARACTER), + new AttributesDescriptor(JavaScriptLocalize.javascriptDocmarkup(), JavaScriptSyntaxHighlightKeys.JS_DOC_MARKUP), + new AttributesDescriptor(JavaScriptLocalize.javascriptDoctag(), JavaScriptSyntaxHighlightKeys.JS_DOC_TAG), + new AttributesDescriptor(JavaScriptLocalize.javascriptParameter(), JavaScriptSyntaxHighlightKeys.JS_PARAMETER), + new AttributesDescriptor(JavaScriptLocalize.javascriptLocalVariable(), JavaScriptSyntaxHighlightKeys.JS_LOCAL_VARIABLE), + new AttributesDescriptor(JavaScriptLocalize.javascriptGlobalVariable(), JavaScriptSyntaxHighlightKeys.JS_GLOBAL_VARIABLE), + new AttributesDescriptor(JavaScriptLocalize.javascriptGlobalFunction(), JavaScriptSyntaxHighlightKeys.JS_GLOBAL_FUNCTION), + new AttributesDescriptor( + JavaScriptLocalize.javascriptInstanceMemberFunction(), + JavaScriptSyntaxHighlightKeys.JS_INSTANCE_MEMBER_FUNCTION + ), + new AttributesDescriptor( + JavaScriptLocalize.javascriptStaticMemberFunction(), + JavaScriptSyntaxHighlightKeys.JS_STATIC_MEMBER_FUNCTION + ), + new AttributesDescriptor( + JavaScriptLocalize.javascriptStaticMemberVariable(), + JavaScriptSyntaxHighlightKeys.JS_STATIC_MEMBER_VARIABLE + ), + new AttributesDescriptor( + JavaScriptLocalize.javascriptInstanceMemberVariable(), + JavaScriptSyntaxHighlightKeys.JS_INSTANCE_MEMBER_VARIABLE + ), + new AttributesDescriptor(JavaScriptLocalize.javascriptMetadata(), JavaScriptSyntaxHighlightKeys.JS_METADATA), + }; + ADDITIONAL_HIGHLIGHT_DESCRIPTORS.put("local_variable", JavaScriptSyntaxHighlightKeys.JS_LOCAL_VARIABLE); + ADDITIONAL_HIGHLIGHT_DESCRIPTORS.put("global_variable", JavaScriptSyntaxHighlightKeys.JS_GLOBAL_VARIABLE); + ADDITIONAL_HIGHLIGHT_DESCRIPTORS.put("instance_variable", JavaScriptSyntaxHighlightKeys.JS_INSTANCE_MEMBER_VARIABLE); + ADDITIONAL_HIGHLIGHT_DESCRIPTORS.put("instance_method", JavaScriptSyntaxHighlightKeys.JS_INSTANCE_MEMBER_FUNCTION); + ADDITIONAL_HIGHLIGHT_DESCRIPTORS.put("global_function", JavaScriptSyntaxHighlightKeys.JS_GLOBAL_FUNCTION); + ADDITIONAL_HIGHLIGHT_DESCRIPTORS.put("parameter", JavaScriptSyntaxHighlightKeys.JS_PARAMETER); + } - @Override - @Nonnull - public String getDisplayName() - { - return "JavaScript"; - } + @Override + @Nonnull + public LocalizeValue getDisplayName() { + return JavaScriptLocalize.javascriptName(); + } - @Override - @Nonnull - public AttributesDescriptor[] getAttributeDescriptors() - { - return ATTRS; - } + @Override + @Nonnull + public AttributesDescriptor[] getAttributeDescriptors() { + return ATTRS; + } - @Override - @Nonnull - public ColorDescriptor[] getColorDescriptors() - { - return ColorDescriptor.EMPTY_ARRAY; - } + @Override + @Nonnull + public SyntaxHighlighter getHighlighter() { + return JavaScript15LanguageVersion.getInstance().getSyntaxHighlighter(); + } - @Override - @Nonnull - public SyntaxHighlighter getHighlighter() - { - return JavaScript15LanguageVersion.getInstance().getSyntaxHighlighter(); - } + @Override + @Nonnull + public String getDemoText() { + return "var globalVar;\n" + + "/**\n" + + " * Constructor for AjaxRequest class\n" + + " * @param url the url for the request

\n" + + " */\n" + + "function AjaxRequest(url) {\n" + + " var urls = [ \"www.cnn.com\", 5, globalVar];\n" + + " this.request = new XMLHttpRequest();\n" + + " url = url.replace(/^\\s*(.*)/, \"$1\"); // skip leading whitespace\n" + + " /* check the url to be in urls */\n" + + " var a = \"\\u1111\\z\\n\\u11\";\n" + + " this.foo = new function() {};\n" + + " foo();\n" + + " #\n" + + "}"; + } - @Override - @Nonnull - public String getDemoText() - { - return "var globalVar;\n" + - "/**\n" + - " * Constructor for AjaxRequest class\n" + - " * @param url the url for the request

\n" + - " */\n" + - "function AjaxRequest(url) {\n" + - " var urls = [ \"www.cnn.com\", 5, globalVar];\n" + - " this.request = new XMLHttpRequest();\n" + - " url = url.replace(/^\\s*(.*)/, \"$1\"); // skip leading whitespace\n" + - " /* check the url to be in urls */\n" + - " var a = \"\\u1111\\z\\n\\u11\";\n" + - " this.foo = new function() {};\n" + - " foo();\n" + - " #\n" + - "}"; - } - - @Override - public Map getAdditionalHighlightingTagToDescriptorMap() - { - return ADDITIONAL_HIGHLIGHT_DESCRIPTORS; - } + @Override + public Map getAdditionalHighlightingTagToDescriptorMap() { + return ADDITIONAL_HIGHLIGHT_DESCRIPTORS; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/highlighting/JavaScriptHighlightVisitor.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/highlighting/JavaScriptHighlightVisitor.java index 5f633b66..6817e0f1 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/highlighting/JavaScriptHighlightVisitor.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/highlighting/JavaScriptHighlightVisitor.java @@ -16,387 +16,325 @@ package com.intellij.lang.javascript.impl.highlighting; -import consulo.annotation.component.ExtensionImpl; -import consulo.codeEditor.DefaultLanguageHighlighterColors; -import consulo.language.editor.rawHighlight.HighlightInfo; -import consulo.language.editor.rawHighlight.HighlightInfoType; -import consulo.language.editor.rawHighlight.HighlightVisitor; -import consulo.language.editor.rawHighlight.HighlightInfoHolder; import com.intellij.lang.javascript.JSTokenTypes; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.psi.*; -import consulo.colorScheme.TextAttributesKey; -import consulo.language.psi.*; -import consulo.language.ast.IElementType; -import consulo.language.psi.util.PsiTreeUtil; import consulo.annotation.access.RequiredReadAction; +import consulo.codeEditor.DefaultLanguageHighlighterColors; +import consulo.colorScheme.TextAttributesKey; import consulo.javascript.ide.hightlight.JavaScriptSyntaxHighlightKeys; import consulo.javascript.lang.JavaScriptContextKeywordElementType; -import consulo.javascript.language.JavaScriptFeature; import consulo.javascript.lang.JavaScriptTokenSets; +import consulo.javascript.language.JavaScriptFeature; import consulo.javascript.language.JavaScriptVersionUtil; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.javascript.psi.JSSimpleLiteralExpression; +import consulo.language.ast.IElementType; +import consulo.language.editor.rawHighlight.HighlightInfo; +import consulo.language.editor.rawHighlight.HighlightInfoHolder; +import consulo.language.editor.rawHighlight.HighlightInfoType; +import consulo.language.editor.rawHighlight.HighlightVisitor; +import consulo.language.psi.*; +import consulo.language.psi.util.PsiTreeUtil; import consulo.util.lang.StringUtil; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -@ExtensionImpl -public class JavaScriptHighlightVisitor extends JSElementVisitor implements HighlightVisitor -{ - private HighlightInfoHolder myHighlightInfoHolder; - - @Override - public boolean suitableForFile(@Nonnull PsiFile psiFile) - { - return psiFile instanceof JSFile; - } - - @Override - @RequiredReadAction - public void visitJSBinaryExpression(JSBinaryExpression node) - { - super.visitJSBinaryExpression(node); - - IElementType operationSign = node.getOperationSign(); - if(operationSign == JSTokenTypes.MULTMULT) - { - reportFeatureUsage(node.getOperationElement(), JavaScriptFeature.EXPONENTIATION_OPERATOR); - } - } - - @Override - @RequiredReadAction - public void visitJSAssignmentExpression(JSAssignmentExpression node) - { - super.visitJSAssignmentExpression(node); - - IElementType operationSign = node.getOperationSign(); - if(operationSign == JSTokenTypes.MULT_MULT_EQ) - { - reportFeatureUsage(node.getOperationElement(), JavaScriptFeature.EXPONENTIATION_OPERATOR); - } - } - - @Override - @RequiredReadAction - public void visitElement(PsiElement element) - { - super.visitElement(element); - - PsiElement parent = element.getParent(); - IElementType elementType = PsiUtilCore.getElementType(element); - if((JavaScriptTokenSets.STRING_LITERALS.contains(elementType) || elementType == JSTokenTypes.IDENTIFIER) && parent instanceof JSProperty && ((JSProperty) parent).getNameIdentifier() == - element) - { - highlightPropertyName((JSProperty) parent, element); - } - else if(elementType == JSTokenTypes.IDENTIFIER) - { - addElementHighlight(parent, element); - } - else if(JavaScriptContextKeywordElementType.containsKeyword(elementType)) - { - myHighlightInfoHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.INFORMATION).textAttributes(JavaScriptSyntaxHighlightKeys.JS_KEYWORD).range(element).create()); - } - } - - @Override - public void visitJSProperty(JSProperty node) - { - super.visitJSProperty(node); - - if(node instanceof JSFunction) - { - reportFeatureUsage(node.getNameIdentifier(), JavaScriptFeature.FUNCTION_PROPERTY); - } - } - - @Override - @RequiredReadAction - public void visitJSLiteralExpression(JSSimpleLiteralExpression node) - { - super.visitJSLiteralExpression(node); - if(node.getLiteralElementType() == JSTokenTypes.NUMERIC_LITERAL) - { - String text = node.getText(); - if(StringUtil.startsWithIgnoreCase(text, "0o")) - { - reportFeatureUsage(node, JavaScriptFeature.OCTAL_LITERAL); - } - else if(StringUtil.startsWithIgnoreCase(text, "0b")) - { - reportFeatureUsage(node, JavaScriptFeature.BINARY_LITERAL); - } - } - } - - @RequiredReadAction - private void highlightPropertyName(@Nonnull JSProperty property, @Nonnull PsiElement nameIdentifier) - { - final JSExpression expression = property.getValue(); - TextAttributesKey type; - - if(expression instanceof JSFunctionExpression) - { - type = JavaScriptSyntaxHighlightKeys.JS_INSTANCE_MEMBER_FUNCTION; - } - else - { - type = JavaScriptSyntaxHighlightKeys.JS_INSTANCE_MEMBER_VARIABLE; - } - myHighlightInfoHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.INFORMATION).needsUpdateOnTyping(false).range(nameIdentifier).textAttributes(type).create()); - } - - @Override - @RequiredReadAction - public void visitJSAttribute(JSAttribute jsAttribute) - { - super.visitJSAttribute(jsAttribute); - - myHighlightInfoHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.INFORMATION).needsUpdateOnTyping(false).range(jsAttribute).textAttributes(JavaScriptSyntaxHighlightKeys - .JS_METADATA).create()); - } - - @Override - @RequiredReadAction - public void visitJSParameter(JSParameter parameter) - { - super.visitJSParameter(parameter); - - JSExpression initializer = parameter.getInitializer(); - if(initializer != null) - { - reportFeatureUsage(initializer, JavaScriptFeature.PARAMETER_DEFAULT_VALUE); - } - - PsiElement restElement = parameter.getRestElement(); - if(restElement != null) - { - reportFeatureUsage(restElement, JavaScriptFeature.REST_PARAMETER); - } - } - - @Override - @RequiredReadAction - public void visitJSReferenceExpression(JSReferenceExpression element) - { - super.visitJSReferenceExpression(element); - - PsiElement parent = element.getParent(); - - if(parent instanceof PsiNameIdentifierOwner && ((PsiNameIdentifierOwner) parent).getNameIdentifier() == element) - { - return; - } - - final ResolveResult[] results = element.multiResolve(false); - - PsiElement validResult = null; - for(ResolveResult result : results) - { - if(result.isValidResult()) - { - validResult = result.getElement(); - break; - } - } - - if(validResult == null) - { - return; - } - - PsiElement referenceNameElement = element.getReferenceNameElement(); - if(referenceNameElement == null) - { - return; - } - addElementHighlight(validResult, referenceNameElement); - } - - @Override - @RequiredReadAction - public void visitJSPrefixExpression(JSPrefixExpression expression) - { - super.visitJSPrefixExpression(expression); - - if(expression.getOperationSign() == JSTokenTypes.DOT_DOT_DOT) - { - PsiElement operatorElement = expression.getOperatorElement(); - assert operatorElement != null; - reportFeatureUsage(operatorElement, JavaScriptFeature.SPREAD_OPERATOR); - } - } - - @RequiredReadAction - private void addElementHighlight(@Nonnull PsiElement resolvedElement, @Nonnull PsiElement targetForHighlight) - { - boolean isStatic = false; - boolean isMethod = false; - boolean isFunction = false; - boolean isField = false; - TextAttributesKey type = null; - - if(resolvedElement instanceof JSAttributeListOwner) - { - if(resolvedElement instanceof JSClass) - { - type = DefaultLanguageHighlighterColors.CLASS_NAME; - } - else - { - final JSAttributeList attributeList = ((JSAttributeListOwner) resolvedElement).getAttributeList(); - - if(attributeList != null) - { - isStatic = attributeList.hasModifier(JSAttributeList.ModifierType.STATIC); - } - - isMethod = resolvedElement instanceof JSFunction; - if(isMethod && !isClass(resolvedElement.getParent())) - { - isMethod = false; - isFunction = true; - } - } - } - else if(resolvedElement instanceof JSDefinitionExpression) - { - final PsiElement parent = resolvedElement.getParent(); - if(parent instanceof JSAssignmentExpression) - { - final JSExpression jsExpression = ((JSAssignmentExpression) parent).getROperand(); - if(jsExpression instanceof JSFunctionExpression) - { - isMethod = true; - } - else - { - isField = true; - } - } - } - else if(resolvedElement instanceof JSProperty) - { - final JSExpression expression = ((JSProperty) resolvedElement).getValue(); - - if(expression instanceof JSFunctionExpression) - { - isMethod = true; - } - else - { - isField = true; - } - } - - if(isMethod) - { - if(isStatic) - { - type = JavaScriptSyntaxHighlightKeys.JS_STATIC_MEMBER_FUNCTION; - } - else - { - type = JavaScriptSyntaxHighlightKeys.JS_INSTANCE_MEMBER_FUNCTION; - } - } - else if(isFunction) - { - type = JavaScriptSyntaxHighlightKeys.JS_GLOBAL_FUNCTION; - } - else if(isField) - { - type = JavaScriptSyntaxHighlightKeys.JS_INSTANCE_MEMBER_VARIABLE; - } - - if(type == null) - { - if(resolvedElement instanceof JSVariable) - { - myHighlightInfoHolder.add(buildHighlightForVariable(resolvedElement, targetForHighlight)); - } - return; - } - - myHighlightInfoHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.INFORMATION).needsUpdateOnTyping(false).range(targetForHighlight).textAttributes(type).create()); - } - - @Nullable - @RequiredReadAction - private static HighlightInfo buildHighlightForVariable(@Nonnull final PsiElement element, @Nonnull final PsiElement markerAddTo) - { - TextAttributesKey type; - - if(element instanceof JSParameter) - { - type = JavaScriptSyntaxHighlightKeys.JS_PARAMETER; - } - else - { - if(isClass(element.getParent().getParent())) - { - final JSAttributeList attributeList = ((JSAttributeListOwner) element).getAttributeList(); - final boolean isStatic = attributeList != null && attributeList.hasModifier(JSAttributeList.ModifierType.STATIC); - type = isStatic ? JavaScriptSyntaxHighlightKeys.JS_STATIC_MEMBER_VARIABLE : JavaScriptSyntaxHighlightKeys.JS_INSTANCE_MEMBER_VARIABLE; - } - else - { - if(PsiTreeUtil.getParentOfType(element, JSFunction.class) != null) - { - type = JavaScriptSyntaxHighlightKeys.JS_LOCAL_VARIABLE; - } - else - { - type = JavaScriptSyntaxHighlightKeys.JS_GLOBAL_VARIABLE; - } - } - } - - if(type == null) - { - return null; - } - - return HighlightInfo.newHighlightInfo(HighlightInfoType.INFORMATION).range(markerAddTo).needsUpdateOnTyping(false).textAttributes(type).create(); - } - - private void reportFeatureUsage(@Nonnull PsiElement element, @Nonnull JavaScriptFeature javaScriptFeature) - { - if(JavaScriptVersionUtil.containsFeature(element, javaScriptFeature)) - { - return; - } - - String message = JavaScriptBundle.message("this.feature.is.not.supported.by.current.language", javaScriptFeature.getName()); - - myHighlightInfoHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(message).create()); - } - - @Override - public void visit(@Nonnull PsiElement element) - { - element.acceptChildren(this); - } - - @Override - public boolean analyze(@Nonnull PsiFile psiFile, boolean b, @Nonnull HighlightInfoHolder highlightInfoHolder, @Nonnull Runnable runnable) - { - myHighlightInfoHolder = highlightInfoHolder; - runnable.run(); - return true; - } - - @Nonnull - @Override - public HighlightVisitor clone() - { - return new JavaScriptHighlightVisitor(); - } - - private static boolean isClass(final PsiElement element) - { - return element instanceof JSClass || element instanceof JSFile && element.getContext() != null; - } +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; + +public class JavaScriptHighlightVisitor extends JSElementVisitor implements HighlightVisitor { + private HighlightInfoHolder myHighlightInfoHolder; + + @Override + @RequiredReadAction + public void visitJSBinaryExpression(@Nonnull JSBinaryExpression node) { + super.visitJSBinaryExpression(node); + + IElementType operationSign = node.getOperationSign(); + if (operationSign == JSTokenTypes.MULTMULT) { + reportFeatureUsage(node.getOperationElement(), JavaScriptFeature.EXPONENTIATION_OPERATOR); + } + } + + @Override + @RequiredReadAction + public void visitJSAssignmentExpression(@Nonnull JSAssignmentExpression node) { + super.visitJSAssignmentExpression(node); + + IElementType operationSign = node.getOperationSign(); + if (operationSign == JSTokenTypes.MULT_MULT_EQ) { + reportFeatureUsage(node.getOperationElement(), JavaScriptFeature.EXPONENTIATION_OPERATOR); + } + } + + @Override + @RequiredReadAction + public void visitElement(PsiElement element) { + super.visitElement(element); + + PsiElement parent = element.getParent(); + IElementType elementType = PsiUtilCore.getElementType(element); + if ((JavaScriptTokenSets.STRING_LITERALS.contains(elementType) || elementType == JSTokenTypes.IDENTIFIER) + && parent instanceof JSProperty property && property.getNameIdentifier() == element) { + highlightPropertyName(property, element); + } + else if (elementType == JSTokenTypes.IDENTIFIER) { + addElementHighlight(parent, element); + } + else if (JavaScriptContextKeywordElementType.containsKeyword(elementType)) { + myHighlightInfoHolder.add( + HighlightInfo.newHighlightInfo(HighlightInfoType.INFORMATION) + .textAttributes(JavaScriptSyntaxHighlightKeys.JS_KEYWORD) + .range(element) + .create() + ); + } + } + + @Override + @RequiredReadAction + public void visitJSProperty(@Nonnull JSProperty node) { + super.visitJSProperty(node); + + if (node instanceof JSFunction function) { + reportFeatureUsage(function.getNameIdentifier(), JavaScriptFeature.FUNCTION_PROPERTY); + } + } + + @Override + @RequiredReadAction + public void visitJSLiteralExpression(@Nonnull JSSimpleLiteralExpression node) { + super.visitJSLiteralExpression(node); + if (node.getLiteralElementType() == JSTokenTypes.NUMERIC_LITERAL) { + String text = node.getText(); + if (StringUtil.startsWithIgnoreCase(text, "0o")) { + reportFeatureUsage(node, JavaScriptFeature.OCTAL_LITERAL); + } + else if (StringUtil.startsWithIgnoreCase(text, "0b")) { + reportFeatureUsage(node, JavaScriptFeature.BINARY_LITERAL); + } + } + } + + @RequiredReadAction + private void highlightPropertyName(@Nonnull JSProperty property, @Nonnull PsiElement nameIdentifier) { + JSExpression expression = property.getValue(); + TextAttributesKey type = expression instanceof JSFunctionExpression + ? JavaScriptSyntaxHighlightKeys.JS_INSTANCE_MEMBER_FUNCTION + : JavaScriptSyntaxHighlightKeys.JS_INSTANCE_MEMBER_VARIABLE; + + myHighlightInfoHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.INFORMATION) + .needsUpdateOnTyping(false) + .range(nameIdentifier) + .textAttributes(type) + .create()); + } + + @Override + @RequiredReadAction + public void visitJSAttribute(@Nonnull JSAttribute jsAttribute) { + super.visitJSAttribute(jsAttribute); + + myHighlightInfoHolder.add( + HighlightInfo.newHighlightInfo(HighlightInfoType.INFORMATION) + .needsUpdateOnTyping(false) + .range(jsAttribute) + .textAttributes(JavaScriptSyntaxHighlightKeys.JS_METADATA) + .create() + ); + } + + @Override + @RequiredReadAction + public void visitJSParameter(@Nonnull JSParameter parameter) { + super.visitJSParameter(parameter); + + JSExpression initializer = parameter.getInitializer(); + if (initializer != null) { + reportFeatureUsage(initializer, JavaScriptFeature.PARAMETER_DEFAULT_VALUE); + } + + PsiElement restElement = parameter.getRestElement(); + if (restElement != null) { + reportFeatureUsage(restElement, JavaScriptFeature.REST_PARAMETER); + } + } + + @Override + @RequiredReadAction + public void visitJSReferenceExpression(@Nonnull JSReferenceExpression element) { + super.visitJSReferenceExpression(element); + + PsiElement parent = element.getParent(); + + if (parent instanceof PsiNameIdentifierOwner nameIdentifierOwner && nameIdentifierOwner.getNameIdentifier() == element) { + return; + } + + ResolveResult[] results = element.multiResolve(false); + + PsiElement validResult = null; + for (ResolveResult result : results) { + if (result.isValidResult()) { + validResult = result.getElement(); + break; + } + } + + if (validResult == null) { + return; + } + + PsiElement referenceNameElement = element.getReferenceNameElement(); + if (referenceNameElement == null) { + return; + } + addElementHighlight(validResult, referenceNameElement); + } + + @Override + @RequiredReadAction + public void visitJSPrefixExpression(@Nonnull JSPrefixExpression expression) { + super.visitJSPrefixExpression(expression); + + if (expression.getOperationSign() == JSTokenTypes.DOT_DOT_DOT) { + PsiElement operatorElement = expression.getOperatorElement(); + assert operatorElement != null; + reportFeatureUsage(operatorElement, JavaScriptFeature.SPREAD_OPERATOR); + } + } + + @RequiredReadAction + private void addElementHighlight(@Nonnull PsiElement resolvedElement, @Nonnull PsiElement targetForHighlight) { + boolean isStatic = false; + boolean isMethod = false; + boolean isFunction = false; + boolean isField = false; + TextAttributesKey type = null; + + if (resolvedElement instanceof JSAttributeListOwner attributeListOwner) { + if (attributeListOwner instanceof JSClass) { + type = DefaultLanguageHighlighterColors.CLASS_NAME; + } + else { + JSAttributeList attributeList = attributeListOwner.getAttributeList(); + + if (attributeList != null) { + isStatic = attributeList.hasModifier(JSAttributeList.ModifierType.STATIC); + } + + isMethod = attributeListOwner instanceof JSFunction; + if (isMethod && !isClass(attributeListOwner.getParent())) { + isMethod = false; + isFunction = true; + } + } + } + else if (resolvedElement instanceof JSDefinitionExpression definition) { + if (definition.getParent() instanceof JSAssignmentExpression assignment) { + if (assignment.getROperand() instanceof JSFunctionExpression) { + isMethod = true; + } + else { + isField = true; + } + } + } + else if (resolvedElement instanceof JSProperty property) { + if (property.getValue() instanceof JSFunctionExpression) { + isMethod = true; + } + else { + isField = true; + } + } + + if (isMethod) { + type = isStatic + ? JavaScriptSyntaxHighlightKeys.JS_STATIC_MEMBER_FUNCTION + : JavaScriptSyntaxHighlightKeys.JS_INSTANCE_MEMBER_FUNCTION; + } + else if (isFunction) { + type = JavaScriptSyntaxHighlightKeys.JS_GLOBAL_FUNCTION; + } + else if (isField) { + type = JavaScriptSyntaxHighlightKeys.JS_INSTANCE_MEMBER_VARIABLE; + } + + if (type == null) { + if (resolvedElement instanceof JSVariable variable) { + myHighlightInfoHolder.add(buildHighlightForVariable(variable, targetForHighlight)); + } + return; + } + + myHighlightInfoHolder.add( + HighlightInfo.newHighlightInfo(HighlightInfoType.INFORMATION) + .needsUpdateOnTyping(false) + .range(targetForHighlight) + .textAttributes(type) + .create() + ); + } + + @Nullable + @RequiredReadAction + private static HighlightInfo buildHighlightForVariable(@Nonnull PsiElement element, @Nonnull PsiElement markerAddTo) { + TextAttributesKey type; + + if (element instanceof JSParameter) { + type = JavaScriptSyntaxHighlightKeys.JS_PARAMETER; + } + else if (isClass(element.getParent().getParent())) { + JSAttributeList attributeList = ((JSAttributeListOwner)element).getAttributeList(); + boolean isStatic = attributeList != null && attributeList.hasModifier(JSAttributeList.ModifierType.STATIC); + type = isStatic + ? JavaScriptSyntaxHighlightKeys.JS_STATIC_MEMBER_VARIABLE + : JavaScriptSyntaxHighlightKeys.JS_INSTANCE_MEMBER_VARIABLE; + } + else if (PsiTreeUtil.getParentOfType(element, JSFunction.class) != null) { + type = JavaScriptSyntaxHighlightKeys.JS_LOCAL_VARIABLE; + } + else { + type = JavaScriptSyntaxHighlightKeys.JS_GLOBAL_VARIABLE; + } + + return HighlightInfo.newHighlightInfo(HighlightInfoType.INFORMATION) + .range(markerAddTo) + .needsUpdateOnTyping(false) + .textAttributes(type) + .create(); + } + + @RequiredReadAction + private void reportFeatureUsage(@Nonnull PsiElement element, @Nonnull JavaScriptFeature javaScriptFeature) { + if (JavaScriptVersionUtil.containsFeature(element, javaScriptFeature)) { + return; + } + + myHighlightInfoHolder.add( + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) + .range(element) + .descriptionAndTooltip(JavaScriptLocalize.thisFeatureIsNotSupportedByCurrentLanguage(javaScriptFeature.getName())) + .create() + ); + } + + @Override + public void visit(@Nonnull PsiElement element) { + element.acceptChildren(this); + } + + @Override + public boolean analyze( + @Nonnull PsiFile psiFile, + boolean b, + @Nonnull HighlightInfoHolder highlightInfoHolder, + @Nonnull Runnable runnable + ) { + myHighlightInfoHolder = highlightInfoHolder; + runnable.run(); + return true; + } + + private static boolean isClass(PsiElement element) { + return element instanceof JSClass || element instanceof JSFile && element.getContext() != null; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/highlighting/JavaScriptHighlightVisitorFactory.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/highlighting/JavaScriptHighlightVisitorFactory.java new file mode 100644 index 00000000..515180c5 --- /dev/null +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/highlighting/JavaScriptHighlightVisitorFactory.java @@ -0,0 +1,27 @@ +package com.intellij.lang.javascript.impl.highlighting; + +import com.intellij.lang.javascript.psi.JSFile; +import consulo.annotation.component.ExtensionImpl; +import consulo.language.editor.rawHighlight.HighlightVisitor; +import consulo.language.editor.rawHighlight.HighlightVisitorFactory; +import consulo.language.psi.PsiFile; + +import jakarta.annotation.Nonnull; + +/** + * @author VISTALL + * @since 2023-03-25 + */ +@ExtensionImpl +public class JavaScriptHighlightVisitorFactory implements HighlightVisitorFactory { + @Override + public boolean suitableForFile(@Nonnull PsiFile psiFile) { + return psiFile instanceof JSFile; + } + + @Nonnull + @Override + public HighlightVisitor createVisitor() { + return new JavaScriptHighlightVisitor(); + } +} diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/highlighting/JavaScriptLineMarkerProvider.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/highlighting/JavaScriptLineMarkerProvider.java index 9d37386a..dc07ca21 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/highlighting/JavaScriptLineMarkerProvider.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/highlighting/JavaScriptLineMarkerProvider.java @@ -21,9 +21,8 @@ import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; import com.intellij.lang.javascript.psi.resolve.ResolveProcessor; import com.intellij.lang.javascript.search.JSClassSearch; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; -import consulo.application.AllIcons; -import consulo.application.ApplicationManager; import consulo.application.progress.ProgressManager; import consulo.application.util.function.Processor; import consulo.application.util.query.CollectionQuery; @@ -40,466 +39,420 @@ import consulo.language.psi.NavigatablePsiElement; import consulo.language.psi.PsiElement; import consulo.navigation.NavigationItem; +import consulo.platform.base.icon.PlatformIconGroup; +import consulo.ui.annotation.RequiredUIAccess; import consulo.ui.ex.RelativePoint; import consulo.util.dataholder.Key; -import consulo.util.lang.ref.Ref; +import consulo.util.lang.ref.SimpleReference; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.awt.event.MouseEvent; import java.util.*; import java.util.function.Function; /** * @author Maxim.Mossienko - * Date: Apr 14, 2008 - * Time: 11:43:47 PM + * @since 2008-04-14 */ @ExtensionImpl -public class JavaScriptLineMarkerProvider implements LineMarkerProvider -{ - private static final String OVERRIDES_METHOD_IN = "overrides method in "; - - private static final Function ourClassInheritorsTooltipProvider = clazz -> "Has subclasses"; - - private static final Function ourImplementedInterfacesTooltipProvider = clazz -> "Has implementations"; - - private static final Function ourOverriddenFunctionsTooltipProvider = psiElement -> "Is overridden"; - - private static final Function ourImplementingFunctionsTooltipProvider = psiElement -> "Is implemented"; - - private static final BasicGutterIconNavigationHandler ourClassInheritorsNavHandler = new BasicGutterIconNavigationHandler() - { - @Override - protected String getTitle(final JSClass elt) - { - return "Choose Subclass of " + elt.getName(); - } - - @Override - protected Query search(final JSClass elt) - { - return JSClassSearch.searchClassInheritors(elt, true); - } - }; - - private static final BasicGutterIconNavigationHandler ourInterfaceImplementationsNavHandler = new - BasicGutterIconNavigationHandler() - { - @Override - protected String getTitle(final JSClass elt) - { - return "Choose Implementation of " + elt.getName(); - } - - @Override - protected Query search(final JSClass elt) - { - return JSClassSearch.searchInterfaceImplementations(elt, true); - } - }; - - private static final BasicGutterIconNavigationHandler ourOverriddenFunctionsNavHandler = new - BasicGutterIconNavigationHandler() - { - @Override - protected String getTitle(final JSFunction elt) - { - return "Choose Overriden Function of " + elt.getName(); - } - - @Override - protected Query search(final JSFunction elt) - { - return doFindOverridenFunctionStatic(elt); - } - }; - private final boolean myUnitTestMode = ApplicationManager.getApplication().isUnitTestMode(); - - - public static Query doFindOverridenFunctionStatic(final JSFunction elt) - { - PsiElement parent = JSResolveUtil.findParent(elt); - if(parent instanceof JSClass) - { - return JSFunctionsSearch.searchOverridingFunctions(elt, true); - } - final String qName = JSResolveUtil.getQNameToStartHierarchySearch(elt); - if(qName != null) - { - final ArrayList result = new ArrayList<>(); - - return new CollectionQuery<>(result); - } - - return new CollectionQuery<>(Collections.emptyList()); - } - - private static final BasicGutterIconNavigationHandler ourImplementingFunctionsNavHandler = new - BasicGutterIconNavigationHandler() - { - @Override - protected String getTitle(final JSFunction elt) - { - return "Choose Implementation of " + elt.getName(); - } - - @Override - protected Query search(final JSFunction elt) - { - return JSFunctionsSearch.searchImplementingFunctions(elt, true); - } - }; - - public static Key ourParticipatesInHierarchyKey = Key.create("js.named.item.participates.in.hierarchy"); - - @Override - public LineMarkerInfo getLineMarkerInfo(@Nonnull final PsiElement element) - { - if(element instanceof JSFunction) - { - final JSFunction function = (JSFunction) element; - function.putUserData(ourParticipatesInHierarchyKey, null); - if(function.getNameIdentifier() == null) - { - return null; - } - final String qName = JSResolveUtil.getQNameToStartHierarchySearch(function); - - if(qName != null) - { - PsiElement parentNode = element.getParent(); - if(parentNode instanceof JSFile) - { - JSClass xmlBackedClass = JSResolveUtil.getXmlBackedClass((JSFile) parentNode); - if(xmlBackedClass != null) - { - parentNode = xmlBackedClass; - } - } - - if(element instanceof JSFunctionExpression) - { - parentNode = element.getContainingFile(); - } - - final MyOverrideHandler overrideHandler = new MyOverrideHandler(); - final String typeName = parentNode instanceof JSClass ? ((JSClass) parentNode).getQualifiedName() : qName; - JSResolveUtil.iterateType(function, parentNode, typeName, overrideHandler); - - if(overrideHandler.className != null) - { - final PsiElement parentNode1 = parentNode; - function.putUserData(ourParticipatesInHierarchyKey, Boolean.TRUE); - - return new LineMarkerInfo<>(function, function.getNameIdentifier().getTextRange().getStartOffset(), AllIcons.Gutter.OverridingMethod, - Pass.UPDATE_ALL, psiElement -> OVERRIDES_METHOD_IN + overrideHandler.className, new GutterIconNavigationHandler() - { - @Override - public void navigate(final MouseEvent e, final JSFunction elt) - { - final Set results = new HashSet<>(); - JSResolveUtil.iterateType(function, parentNode1, typeName, new JSResolveUtil.OverrideHandler() - { - @Override - public boolean process(final ResolveProcessor processor, final PsiElement scope, final String className) - { - for(PsiElement e : processor.getResults()) - { - results.add((NavigationItem) e); - } - return true; - } - }); - - if(results.size() == 1) - { - results.iterator().next().navigate(true); - } - else if(results.size() > 1) - { - PopupNavigationUtil.getPsiElementPopup(results.toArray(new PsiElement[results.size()]), "Choose super class or interface").show(new RelativePoint - (e)); - } - } - } - ); - } - } - } - - return null; - } - - @Override - public void collectSlowLineMarkers(@Nonnull final List elements, @Nonnull final Collection result) - { - final Map> jsFunctionsToProcess = new HashMap<>(); - final Map> jsMethodsToProcess = new HashMap<>(); - - for(final PsiElement el : elements) - { - ProgressManager.getInstance().checkCanceled(); - - if(el instanceof JSFunction) - { - final JSFunction function = (JSFunction) el; - if(isNotApplicableForOverride(function)) - { - continue; - } - - PsiElement parent = function.getParent(); - if(parent instanceof JSFile) - { - parent = JSResolveUtil.getClassReferenceForXmlFromContext(parent); - } - - if(parent instanceof JSClass) - { - final JSClass clazz = (JSClass) parent; - - Set functions = jsMethodsToProcess.get(clazz); - if(functions == null) - { - functions = new HashSet<>(); - jsMethodsToProcess.put(clazz, functions); - } - - functions.add(function); - } - else if(parent instanceof JSFile || function instanceof JSFunctionExpression) - { - final String qName = JSResolveUtil.getQNameToStartHierarchySearch(function); - if(qName != null) - { - Set functions = jsFunctionsToProcess.get(qName); - - if(functions == null) - { - functions = new HashSet<>(); - jsFunctionsToProcess.put(qName, functions); - } - - functions.add(function); - } - } - } - else if(el instanceof JSClass) - { - final JSClass clazz = (JSClass) el; - if(!jsMethodsToProcess.containsKey(clazz)) - { - jsMethodsToProcess.put(clazz, null); - } - } - } - - for(Map.Entry> entry : jsMethodsToProcess.entrySet()) - { - ProgressManager.getInstance().checkCanceled(); - final JSClass clazz = entry.getKey(); - final Set methods = entry.getValue(); - - Query classQuery = JSClassSearch.searchClassInheritors(clazz, methods != null); - - classQuery.forEach(new Processor() - { - boolean addedClassMarker; - final Set methodsClone = methods == null || clazz.isInterface() ? null : new HashSet<>(methods); - - @Override - public boolean process(final JSClass jsClass) - { - if(!addedClassMarker) - { - result.add(new LineMarkerInfo<>(clazz, clazz.getTextOffset(), AllIcons.Gutter.OverridenMethod, Pass.LINE_MARKERS, - ourClassInheritorsTooltipProvider, ourClassInheritorsNavHandler)); - addedClassMarker = true; - } - - if(methodsClone != null) - { - for(final Iterator functionIterator = methodsClone.iterator(); functionIterator.hasNext(); ) - { - final JSFunction function = functionIterator.next(); - - final JSFunction byName = jsClass.findFunctionByNameAndKind(function.getName(), function.getKind()); - if(byName != null && !isNotApplicableForOverride(byName)) - { - // TODO: more correct check for override - function.putUserData(ourParticipatesInHierarchyKey, Boolean.TRUE); - result.add(new LineMarkerInfo<>(function, function.getTextOffset(), AllIcons.Gutter.OverridenMethod, Pass.LINE_MARKERS, - ourOverriddenFunctionsTooltipProvider, ourOverriddenFunctionsNavHandler)); - functionIterator.remove(); - } - } - } - return methodsClone != null && !methodsClone.isEmpty(); - } - }); - - - if(clazz.isInterface()) - { - classQuery = JSClassSearch.searchInterfaceImplementations(clazz, false); - - if(classQuery.findFirst() != null) - { - result.add(new LineMarkerInfo<>(clazz, clazz.getTextOffset(), AllIcons.Gutter.ImplementedMethod, Pass.LINE_MARKERS, - ourImplementedInterfacesTooltipProvider, ourInterfaceImplementationsNavHandler)); - } - } - - if(methods == null) - { - continue; - } - - for(final JSFunction function : methods) - { - - if(clazz.isInterface()) - { - final Query query = JSFunctionsSearch.searchImplementingFunctions(function, false); - if(query.findFirst() != null) - { - function.putUserData(ourParticipatesInHierarchyKey, Boolean.TRUE); - result.add(new LineMarkerInfo<>(function, function.getTextOffset(), AllIcons.Gutter.ImplementedMethod, Pass.LINE_MARKERS, - ourImplementingFunctionsTooltipProvider, ourImplementingFunctionsNavHandler)); - } - } - else - { - final JSAttributeList attributeList = function.getAttributeList(); - if(attributeList != null && attributeList.hasModifier(JSAttributeList.ModifierType.OVERRIDE)) - { - continue; - } - - final JSFunction implementedFunction = findImplementedFunction(function); - if(implementedFunction != null) - { - function.putUserData(ourParticipatesInHierarchyKey, Boolean.TRUE); - - result.add(new LineMarkerInfo<>(function, function.getTextOffset(), AllIcons.Gutter.ImplementingMethod, Pass.LINE_MARKERS, - jsFunction -> "Implementation of " + jsFunction.getName() + " in " + ((NavigationItem) implementedFunction.getParent()).getName(), new - GutterIconNavigationHandler() - { - @Override - public void navigate(final MouseEvent e, final JSFunction elt) - { - final JSFunction implementedFunction = findImplementedFunction(elt); - if(implementedFunction != null) - { - implementedFunction.navigate(true); - } - } - } - )); - } - } - } - } - } - - private static boolean isClass(final PsiElement element) - { - if(element instanceof JSClass) - { - return true; - } - if(element instanceof JSFile && element.getContext() != null) - { - return true; - } - return false; - } - - @Nullable - private static JSFunction findImplementedFunction(JSFunction implementingFunction) - { - PsiElement clazz = implementingFunction.getParent(); - if(!(clazz instanceof JSClass)) - { - clazz = JSResolveUtil.getClassReferenceForXmlFromContext(clazz); - } - if(!(clazz instanceof JSClass)) - { - return null; - } - final Ref result = new Ref<>(); - JSResolveUtil.processInterfaceMethods((JSClass) clazz, new JSResolveUtil.CollectMethodsToImplementProcessor(implementingFunction.getName(), - implementingFunction) - { - @Override - protected boolean process(final ResolveProcessor processor) - { - result.set((JSFunction) processor.getResult()); - return false; - } - }); - return result.get(); - } - - private static boolean isNotApplicableForOverride(final JSFunction function) - { - final JSAttributeList attributeList = function.getAttributeList(); - - return function.isConstructor() || (attributeList != null && (attributeList.getAccessType() == JSAttributeList.AccessType.PRIVATE || - attributeList.hasModifier(JSAttributeList.ModifierType.STATIC) || - attributeList.hasModifier(JSAttributeList.ModifierType.NATIVE))); - } - - static class MyOverrideHandler implements JSResolveUtil.OverrideHandler - { - String className; - - @Override - public boolean process(final ResolveProcessor processor, final PsiElement scope, final String className) - { - this.className = className; - return true; - } - } - - private abstract static class BasicGutterIconNavigationHandler implements GutterIconNavigationHandler - { - @Override - public void navigate(final MouseEvent e, final T elt) - { - final List navElements = new ArrayList<>(); - Query elementQuery = search(elt); - if(elementQuery == null) - { - return; - } - elementQuery.forEach(new Processor() - { - @Override - public boolean process(final T psiElement) - { - if(psiElement instanceof NavigatablePsiElement) - { - navElements.add((NavigatablePsiElement) psiElement); - } - return true; - } - }); - final NavigatablePsiElement[] methods = navElements.toArray(new NavigatablePsiElement[navElements.size()]); - PsiElementListNavigator.openTargets(e, methods, getTitle(elt), "", new DefaultPsiElementCellRenderer()); - } - - protected abstract String getTitle(T elt); - - @Nullable - protected abstract Query search(T elt); - } - - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } +public class JavaScriptLineMarkerProvider implements LineMarkerProvider { + private static final String OVERRIDES_METHOD_IN = "overrides method in "; + + private static final Function CLASS_INHERITORS_TOOLTIP_PROVIDER = clazz -> "Has subclasses"; + + private static final Function IMPLEMENTED_INTERFACES_TOOLTIP_PROVIDER = clazz -> "Has implementations"; + + private static final Function OVERRIDDEN_FUNCTIONS_TOOLTIP_PROVIDER = psiElement -> "Is overridden"; + + private static final Function IMPLEMENTING_FUNCTIONS_TOOLTIP_PROVIDER = psiElement -> "Is implemented"; + + private static final BasicGutterIconNavigationHandler CLASS_INHERITORS_NAV_HANDLER = + new BasicGutterIconNavigationHandler<>() { + @Override + @RequiredReadAction + protected String getTitle(JSClass elt) { + return "Choose Subclass of " + elt.getName(); + } + + @Override + protected Query search(JSClass elt) { + return JSClassSearch.searchClassInheritors(elt, true); + } + }; + + private static final BasicGutterIconNavigationHandler INTERFACE_IMPLEMENTATIONS_NAV_HANDLER = + new BasicGutterIconNavigationHandler<>() { + @Override + @RequiredReadAction + protected String getTitle(JSClass elt) { + return "Choose Implementation of " + elt.getName(); + } + + @Override + protected Query search(JSClass elt) { + return JSClassSearch.searchInterfaceImplementations(elt, true); + } + }; + + private static final BasicGutterIconNavigationHandler OVERRIDDEN_FUNCTIONS_NAV_HANDLER = + new BasicGutterIconNavigationHandler<>() { + @Override + @RequiredReadAction + protected String getTitle(JSFunction elt) { + return "Choose Overriden Function of " + elt.getName(); + } + + @Override + @RequiredReadAction + protected Query search(JSFunction elt) { + return doFindOverridenFunctionStatic(elt); + } + }; + + @RequiredReadAction + public static Query doFindOverridenFunctionStatic(JSFunction elt) { + PsiElement parent = JSResolveUtil.findParent(elt); + if (parent instanceof JSClass) { + return JSFunctionsSearch.searchOverridingFunctions(elt, true); + } + String qName = JSResolveUtil.getQNameToStartHierarchySearch(elt); + if (qName != null) { + ArrayList result = new ArrayList<>(); + + return new CollectionQuery<>(result); + } + + return new CollectionQuery<>(Collections.emptyList()); + } + + private static final BasicGutterIconNavigationHandler IMPLEMENTING_FUNCTIONS_NAV_HANDLER = + new BasicGutterIconNavigationHandler<>() { + @Override + @RequiredReadAction + protected String getTitle(JSFunction elt) { + return "Choose Implementation of " + elt.getName(); + } + + @Override + protected Query search(JSFunction elt) { + return JSFunctionsSearch.searchImplementingFunctions(elt, true); + } + }; + + public static Key ourParticipatesInHierarchyKey = Key.create("js.named.item.participates.in.hierarchy"); + + @Override + @RequiredReadAction + public LineMarkerInfo getLineMarkerInfo(@Nonnull PsiElement element) { + if (element instanceof JSFunction function) { + function.putUserData(ourParticipatesInHierarchyKey, null); + if (function.getNameIdentifier() == null) { + return null; + } + String qName = JSResolveUtil.getQNameToStartHierarchySearch(function); + + if (qName != null) { + PsiElement parentNode = element.getParent(); + if (parentNode instanceof JSFile jsFile) { + JSClass xmlBackedClass = JSResolveUtil.getXmlBackedClass(jsFile); + if (xmlBackedClass != null) { + parentNode = xmlBackedClass; + } + } + + if (element instanceof JSFunctionExpression functionExpr) { + parentNode = functionExpr.getContainingFile(); + } + + MyOverrideHandler overrideHandler = new MyOverrideHandler(); + String typeName = parentNode instanceof JSClass jsClass ? jsClass.getQualifiedName() : qName; + JSResolveUtil.iterateType(function, parentNode, typeName, overrideHandler); + + if (overrideHandler.className != null) { + PsiElement parentNode1 = parentNode; + function.putUserData(ourParticipatesInHierarchyKey, Boolean.TRUE); + + return new LineMarkerInfo<>( + function, + function.getNameIdentifier().getTextRange().getStartOffset(), + PlatformIconGroup.gutterOverridingmethod(), + Pass.UPDATE_ALL, + psiElement -> OVERRIDES_METHOD_IN + overrideHandler.className, + (e, elt) -> { + Set results = new HashSet<>(); + JSResolveUtil.iterateType( + function, + parentNode1, + typeName, + (processor, scope, className) -> { + for (PsiElement e1 : processor.getResults()) { + results.add((NavigationItem)e1); + } + return true; + } + ); + + if (results.size() == 1) { + results.iterator().next().navigate(true); + } + else if (results.size() > 1) { + PopupNavigationUtil.getPsiElementPopup( + results.toArray(new PsiElement[results.size()]), + "Choose super class or interface" + ).show(new RelativePoint(e)); + } + } + ); + } + } + } + + return null; + } + + @Override + @RequiredReadAction + public void collectSlowLineMarkers(@Nonnull List elements, @Nonnull final Collection result) { + Map> jsFunctionsToProcess = new HashMap<>(); + Map> jsMethodsToProcess = new HashMap<>(); + + for (PsiElement el : elements) { + ProgressManager.getInstance().checkCanceled(); + + if (el instanceof JSFunction function) { + if (isNotApplicableForOverride(function)) { + continue; + } + + PsiElement parent = function.getParent(); + if (parent instanceof JSFile jsFile) { + parent = JSResolveUtil.getClassReferenceForXmlFromContext(jsFile); + } + + if (parent instanceof JSClass jsClass) { + Set functions = jsMethodsToProcess.get(jsClass); + if (functions == null) { + functions = new HashSet<>(); + jsMethodsToProcess.put(jsClass, functions); + } + + functions.add(function); + } + else if (parent instanceof JSFile || function instanceof JSFunctionExpression) { + String qName = JSResolveUtil.getQNameToStartHierarchySearch(function); + if (qName != null) { + Set functions = jsFunctionsToProcess.get(qName); + + if (functions == null) { + functions = new HashSet<>(); + jsFunctionsToProcess.put(qName, functions); + } + + functions.add(function); + } + } + } + else if (el instanceof JSClass jsClass) { + if (!jsMethodsToProcess.containsKey(jsClass)) { + jsMethodsToProcess.put(jsClass, null); + } + } + } + + for (Map.Entry> entry : jsMethodsToProcess.entrySet()) { + ProgressManager.getInstance().checkCanceled(); + final JSClass clazz = entry.getKey(); + final Set methods = entry.getValue(); + + Query classQuery = JSClassSearch.searchClassInheritors(clazz, methods != null); + + classQuery.forEach(new Processor<>() { + boolean addedClassMarker; + final Set methodsClone = methods == null || clazz.isInterface() ? null : new HashSet<>(methods); + + @Override + public boolean process(JSClass jsClass) { + if (!addedClassMarker) { + result.add(new LineMarkerInfo<>( + clazz, + clazz.getTextOffset(), + PlatformIconGroup.gutterOverridenmethod(), + Pass.LINE_MARKERS, + CLASS_INHERITORS_TOOLTIP_PROVIDER, + CLASS_INHERITORS_NAV_HANDLER + )); + addedClassMarker = true; + } + + if (methodsClone != null) { + for (Iterator functionIterator = methodsClone.iterator(); functionIterator.hasNext(); ) { + JSFunction function = functionIterator.next(); + + JSFunction byName = jsClass.findFunctionByNameAndKind(function.getName(), function.getKind()); + if (byName != null && !isNotApplicableForOverride(byName)) { + // TODO: more correct check for override + function.putUserData(ourParticipatesInHierarchyKey, Boolean.TRUE); + result.add(new LineMarkerInfo<>( + function, + function.getTextOffset(), + PlatformIconGroup.gutterOverridenmethod(), + Pass.LINE_MARKERS, + OVERRIDDEN_FUNCTIONS_TOOLTIP_PROVIDER, + OVERRIDDEN_FUNCTIONS_NAV_HANDLER + )); + functionIterator.remove(); + } + } + } + return methodsClone != null && !methodsClone.isEmpty(); + } + }); + + + if (clazz.isInterface()) { + classQuery = JSClassSearch.searchInterfaceImplementations(clazz, false); + + if (classQuery.findFirst() != null) { + result.add(new LineMarkerInfo<>( + clazz, + clazz.getTextOffset(), + PlatformIconGroup.gutterImplementedmethod(), + Pass.LINE_MARKERS, + IMPLEMENTED_INTERFACES_TOOLTIP_PROVIDER, + INTERFACE_IMPLEMENTATIONS_NAV_HANDLER + )); + } + } + + if (methods == null) { + continue; + } + + for (JSFunction function : methods) { + if (clazz.isInterface()) { + Query query = JSFunctionsSearch.searchImplementingFunctions(function, false); + if (query.findFirst() != null) { + function.putUserData(ourParticipatesInHierarchyKey, Boolean.TRUE); + result.add(new LineMarkerInfo<>( + function, + function.getTextOffset(), + PlatformIconGroup.gutterImplementedmethod(), + Pass.LINE_MARKERS, + IMPLEMENTING_FUNCTIONS_TOOLTIP_PROVIDER, + IMPLEMENTING_FUNCTIONS_NAV_HANDLER + )); + } + } + else { + JSAttributeList attributeList = function.getAttributeList(); + if (attributeList != null && attributeList.hasModifier(JSAttributeList.ModifierType.OVERRIDE)) { + continue; + } + + JSFunction implementedFunction = findImplementedFunction(function); + if (implementedFunction != null) { + function.putUserData(ourParticipatesInHierarchyKey, Boolean.TRUE); + + result.add(new LineMarkerInfo<>( + function, + function.getTextOffset(), + PlatformIconGroup.gutterImplementingmethod(), + Pass.LINE_MARKERS, + jsFunction -> "Implementation of " + jsFunction.getName() + " in " + + ((NavigationItem)implementedFunction.getParent()).getName(), + (e, elt) -> { + JSFunction implementedFunction1 = findImplementedFunction(elt); + if (implementedFunction1 != null) { + implementedFunction1.navigate(true); + } + } + )); + } + } + } + } + } + + private static boolean isClass(PsiElement element) { + return element instanceof JSClass || element instanceof JSFile jsFile && jsFile.getContext() != null; + } + + @Nullable + @RequiredReadAction + private static JSFunction findImplementedFunction(JSFunction implementingFunction) { + PsiElement clazz = implementingFunction.getParent(); + if (!(clazz instanceof JSClass)) { + clazz = JSResolveUtil.getClassReferenceForXmlFromContext(clazz); + } + if (!(clazz instanceof JSClass)) { + return null; + } + final SimpleReference result = new SimpleReference<>(); + JSResolveUtil.processInterfaceMethods( + (JSClass)clazz, + new JSResolveUtil.CollectMethodsToImplementProcessor( + implementingFunction.getName(), + implementingFunction + ) { + @Override + protected boolean process(ResolveProcessor processor) { + result.set((JSFunction)processor.getResult()); + return false; + } + } + ); + return result.get(); + } + + @RequiredReadAction + private static boolean isNotApplicableForOverride(JSFunction function) { + JSAttributeList attributeList = function.getAttributeList(); + + return function.isConstructor() || (attributeList != null + && (attributeList.getAccessType() == JSAttributeList.AccessType.PRIVATE + || attributeList.hasModifier(JSAttributeList.ModifierType.STATIC) + || attributeList.hasModifier(JSAttributeList.ModifierType.NATIVE))); + } + + static class MyOverrideHandler implements JSResolveUtil.OverrideHandler { + String className; + + @Override + public boolean process(ResolveProcessor processor, PsiElement scope, String className) { + this.className = className; + return true; + } + } + + private abstract static class BasicGutterIconNavigationHandler implements GutterIconNavigationHandler { + @Override + @RequiredUIAccess + public void navigate(MouseEvent e, T elt) { + List navElements = new ArrayList<>(); + Query elementQuery = search(elt); + if (elementQuery == null) { + return; + } + elementQuery.forEach(psiElement -> { + if (psiElement instanceof NavigatablePsiElement navigatablePsiElement) { + navElements.add(navigatablePsiElement); + } + return true; + }); + NavigatablePsiElement[] methods = navElements.toArray(new NavigatablePsiElement[navElements.size()]); + PsiElementListNavigator.openTargets(e, methods, getTitle(elt), "", new DefaultPsiElementCellRenderer()); + } + + protected abstract String getTitle(T elt); + + @Nullable + protected abstract Query search(T elt); + } + + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/index/predefined/Marker.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/index/predefined/Marker.java index 188d0423..aac698b0 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/index/predefined/Marker.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/index/predefined/Marker.java @@ -17,12 +17,8 @@ package com.intellij.lang.javascript.impl.index.predefined; /** - * Created by IntelliJ IDEA. - * User: Maxim.Mossienko - * Date: Apr 22, 2006 - * Time: 8:09:53 PM - * To change this template use File | Settings | File Templates. + * @author Maxim.Mossienko + * @since 2006-04-22 */ -public class Marker -{ +public class Marker { } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/CreateClassDialog.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/CreateClassDialog.java index 393556ef..d3dbd880 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/CreateClassDialog.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/CreateClassDialog.java @@ -16,85 +16,74 @@ package com.intellij.lang.javascript.impl.inspections; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextField; -import javax.swing.event.DocumentEvent; - -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.psi.JSExpressionStatement; import com.intellij.lang.javascript.psi.JSReferenceExpression; import com.intellij.lang.javascript.psi.impl.JSChangeUtil; -import consulo.ui.ex.awt.DialogWrapper; -import consulo.language.psi.PsiElement; +import consulo.annotation.access.RequiredReadAction; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.ast.ASTNode; import consulo.project.Project; +import consulo.ui.annotation.RequiredUIAccess; +import consulo.ui.ex.awt.DialogWrapper; import consulo.ui.ex.awt.event.DocumentAdapter; +import javax.swing.*; +import javax.swing.event.DocumentEvent; + /** * @author Maxim.Mossienko - * Date: Jun 9, 2008 - * Time: 7:36:22 PM + * @since 2008-06-09 */ -class CreateClassDialog extends DialogWrapper -{ - private JPanel myPanel; - private JTextField myPackageName; - private JLabel myClassName; +class CreateClassDialog extends DialogWrapper { + private JPanel myPanel; + private JTextField myPackageName; + private JLabel myClassName; - protected CreateClassDialog(final Project project, String className, String packageName, boolean isInterface) - { - super(project, false); + protected CreateClassDialog(final Project project, String className, String packageName, boolean isInterface) { + super(project, false); - setTitle(JavaScriptBundle.message(isInterface ? "create.interface.dialog.title" : "create.class.dialog.title")); - setModal(true); + setTitle(isInterface ? JavaScriptLocalize.createInterfaceDialogTitle() : JavaScriptLocalize.createClassDialogTitle()); + setModal(true); - myPackageName.getDocument().addDocumentListener(new DocumentAdapter() - { - @Override - protected void textChanged(final DocumentEvent e) - { - String text = getPackageName(); - boolean enabled; - if(text.length() == 0) - { - enabled = true; - } - else - { - ASTNode node = JSChangeUtil.createJSTreeFromText(project, text); - PsiElement elt; - enabled = node != null && - (elt = node.getPsi()) instanceof JSExpressionStatement && - (elt = ((JSExpressionStatement) elt).getExpression()) instanceof JSReferenceExpression && - ((JSReferenceExpression) elt).getReferencedName() != null && - elt.textMatches(text); - } - getOKAction().setEnabled(enabled); - } - }); + myPackageName.getDocument().addDocumentListener(new DocumentAdapter() { + @Override + @RequiredReadAction + protected void textChanged(DocumentEvent e) { + String text = getPackageName(); + boolean enabled; + if (text.length() == 0) { + enabled = true; + } + else { + ASTNode node = JSChangeUtil.createJSTreeFromText(project, text); + enabled = node != null + && node.getPsi() instanceof JSExpressionStatement expressionStatement + && expressionStatement.getExpression() instanceof JSReferenceExpression refExpr + && refExpr.getReferencedName() != null + && refExpr.textMatches(text); + } + getOKAction().setEnabled(enabled); + } + }); - myClassName.setText(className); - myPackageName.setText(packageName); + myClassName.setText(className); + myPackageName.setText(packageName); - init(); - } + init(); + } - @Override - protected JComponent createCenterPanel() - { - return myPanel; - } + @Override + protected JComponent createCenterPanel() { + return myPanel; + } - @Override - public JComponent getPreferredFocusedComponent() - { - return myPackageName; - } + @Override + @RequiredUIAccess + public JComponent getPreferredFocusedComponent() { + return myPackageName; + } - String getPackageName() - { - return myPackageName.getText(); - } + String getPackageName() { + return myPackageName.getText(); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/CreateClassOrInterfaceAction.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/CreateClassOrInterfaceAction.java index f0a60809..a482f32b 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/CreateClassOrInterfaceAction.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/CreateClassOrInterfaceAction.java @@ -16,15 +16,15 @@ package com.intellij.lang.javascript.impl.inspections; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.JavaScriptSupportLoader; import com.intellij.lang.javascript.impl.flex.ImportUtils; import com.intellij.lang.javascript.psi.JSReferenceExpression; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; -import consulo.application.ApplicationManager; +import consulo.application.Application; import consulo.fileTemplate.FileTemplate; import consulo.fileTemplate.FileTemplateManager; import consulo.fileTemplate.FileTemplateUtil; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.editor.inspection.LocalQuickFix; import consulo.language.editor.inspection.ProblemDescriptor; import consulo.language.psi.PsiDirectory; @@ -32,132 +32,112 @@ import consulo.language.psi.PsiFile; import consulo.language.psi.PsiManager; import consulo.language.util.ModuleUtilCore; +import consulo.localize.LocalizeValue; import consulo.logging.Logger; import consulo.module.Module; import consulo.module.content.ModuleRootManager; import consulo.project.Project; +import consulo.ui.annotation.RequiredUIAccess; import consulo.ui.ex.awt.DialogWrapper; import consulo.util.lang.text.StringTokenizer; import consulo.virtualFileSystem.VirtualFile; import consulo.virtualFileSystem.util.VirtualFileUtil; -import org.jetbrains.annotations.NonNls; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; import java.util.Properties; /** - * Created by IntelliJ IDEA. - * User: Maxim.Mossienko - * Date: 11.02.2009 - * Time: 14:01:34 - * To change this template use File | Settings | File Templates. + * @author Maxim.Mossienko + * @since 2009-02-11 */ -class CreateClassOrInterfaceAction implements LocalQuickFix -{ - private final String classNameToCreate; - private final JSReferenceExpression myContext; - private String packageName; - private final boolean myIsInterface; +class CreateClassOrInterfaceAction implements LocalQuickFix { + private final String classNameToCreate; + private final JSReferenceExpression myContext; + private String packageName; + private final boolean myIsInterface; - public CreateClassOrInterfaceAction(JSReferenceExpression context, boolean isInterface) - { - classNameToCreate = context.getReferencedName(); - myContext = context; - myIsInterface = isInterface; - } + public CreateClassOrInterfaceAction(JSReferenceExpression context, boolean isInterface) { + classNameToCreate = context.getReferencedName(); + myContext = context; + myIsInterface = isInterface; + } - @Override - @Nonnull - public String getName() - { - final String key = myIsInterface ? "javascript.create.interface.intention.name" : "javascript.create.class.intention.name"; - return JavaScriptBundle.message(key, classNameToCreate); - } + @Override + @Nonnull + public LocalizeValue getName() { + return myIsInterface + ? JavaScriptLocalize.javascriptCreateInterfaceIntentionName(classNameToCreate) + : JavaScriptLocalize.javascriptCreateClassIntentionName(classNameToCreate); + } - @Override - @Nonnull - public String getFamilyName() - { - return getName(); - } + @Override + @RequiredUIAccess + public void applyFix(@Nonnull Project project, @Nonnull ProblemDescriptor descriptor) { + PsiFile contextFile = myContext.getContainingFile(); + PsiElement context = contextFile.getContext(); + if (context != null) { + contextFile = context.getContainingFile(); + } - @Override - public void applyFix(@Nonnull final Project project, @Nonnull final ProblemDescriptor descriptor) - { - PsiFile contextFile = myContext.getContainingFile(); - final PsiElement context = contextFile.getContext(); - if(context != null) - { - contextFile = context.getContainingFile(); - } + packageName = JSResolveUtil.getExpectedPackageNameFromFile(contextFile.getVirtualFile(), project, false); - packageName = JSResolveUtil.getExpectedPackageNameFromFile(contextFile.getVirtualFile(), project, false); + if (!Application.get().isUnitTestMode()) { + CreateClassDialog dialog = new CreateClassDialog(project, classNameToCreate, packageName, myIsInterface); + dialog.show(); + if (dialog.getExitCode() != DialogWrapper.OK_EXIT_CODE) { + return; + } + packageName = dialog.getPackageName().trim(); + } + else { + packageName = "foo"; + } - if(!ApplicationManager.getApplication().isUnitTestMode()) - { - final CreateClassDialog dialog = new CreateClassDialog(project, classNameToCreate, packageName, myIsInterface); - dialog.show(); - if(dialog.getExitCode() != DialogWrapper.OK_EXIT_CODE) - { - return; - } - packageName = dialog.getPackageName().trim(); - } - else - { - packageName = "foo"; - } + final PsiFile contextFile1 = contextFile; + Application.get().runWriteAction(new Runnable() { + @Override + public void run() { + try { + FileTemplate template = FileTemplateManager.getInstance().getTemplate( + myIsInterface + ? JavaScriptSupportLoader.ACTION_SCRIPT_INTERFACE_TEMPLATE_NAME + : JavaScriptSupportLoader.ACTION_SCRIPT_CLASS_TEMPLATE_NAME + ); + String fileName = classNameToCreate + ".as"; + Properties props = new Properties(); + props.setProperty(FileTemplate.ATTRIBUTE_NAME, classNameToCreate); + Module element = ModuleUtilCore.findModuleForPsiElement(contextFile1); + VirtualFile base = ModuleRootManager.getInstance(element).getSourceRoots()[0]; + VirtualFile relativeFile = VirtualFileUtil.findRelativeFile(packageName, base); - final PsiFile contextFile1 = contextFile; - ApplicationManager.getApplication().runWriteAction(new Runnable() - { - @Override - public void run() - { - try - { - final FileTemplate template = FileTemplateManager.getInstance().getTemplate(myIsInterface ? JavaScriptSupportLoader - .ACTION_SCRIPT_INTERFACE_TEMPLATE_NAME : JavaScriptSupportLoader.ACTION_SCRIPT_CLASS_TEMPLATE_NAME); - @NonNls final String fileName = classNameToCreate + ".as"; - final Properties props = new Properties(); - props.setProperty(FileTemplate.ATTRIBUTE_NAME, classNameToCreate); - final Module element = ModuleUtilCore.findModuleForPsiElement(contextFile1); - VirtualFile base = ModuleRootManager.getInstance(element).getSourceRoots()[0]; - VirtualFile relativeFile = VirtualFileUtil.findRelativeFile(packageName, base); + if (relativeFile == null) { + relativeFile = base; + StringTokenizer tokenizer = new StringTokenizer(packageName, "."); + while (tokenizer.hasMoreTokens()) { + String nextNameSegment = tokenizer.nextToken(); + VirtualFile next = relativeFile.findChild(nextNameSegment); + if (next == null) { + next = relativeFile.createChildDirectory(this, nextNameSegment); + } + relativeFile = next; + } + } - if(relativeFile == null) - { - relativeFile = base; - StringTokenizer tokenizer = new StringTokenizer(packageName, "."); - while(tokenizer.hasMoreTokens()) - { - String nextNameSegment = tokenizer.nextToken(); - VirtualFile next = relativeFile.findChild(nextNameSegment); - if(next == null) - { - next = relativeFile.createChildDirectory(this, nextNameSegment); - } - relativeFile = next; - } - } + assert relativeFile != null; + props.setProperty(FileTemplate.ATTRIBUTE_PACKAGE_NAME, packageName); + PsiDirectory psiDirectory = PsiManager.getInstance(project).findDirectory(relativeFile); + assert psiDirectory != null; + FileTemplateUtil.createFromTemplate(template, fileName, props, psiDirectory); - assert relativeFile != null; - props.setProperty(FileTemplate.ATTRIBUTE_PACKAGE_NAME, packageName); - final PsiDirectory psiDirectory = PsiManager.getInstance(project).findDirectory(relativeFile); - assert psiDirectory != null; - FileTemplateUtil.createFromTemplate(template, fileName, props, psiDirectory); - - String contextPackage = JSResolveUtil.findPackageStatementQualifier(myContext); - if(packageName != null && !packageName.equals(contextPackage) && packageName.length() > 0) - { - ImportUtils.doImport(myContext, packageName + "." + classNameToCreate); - } - } - catch(Exception e) - { - Logger.getInstance(getClass().getName()).error(e); - } - } - }); - } + String contextPackage = JSResolveUtil.findPackageStatementQualifier(myContext); + if (packageName != null && !packageName.equals(contextPackage) && packageName.length() > 0) { + ImportUtils.doImport(myContext, packageName + "." + classNameToCreate); + } + } + catch (Exception e) { + Logger.getInstance(getClass().getName()).error(e); + } + } + }); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSDeprecatedSymbolsInspection.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSDeprecatedSymbolsInspection.java index ccb426c0..90c74e58 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSDeprecatedSymbolsInspection.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSDeprecatedSymbolsInspection.java @@ -17,74 +17,67 @@ package com.intellij.lang.javascript.impl.inspections; import com.intellij.javascript.documentation.JSDocumentationUtils; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.psi.JSAssignmentExpression; import com.intellij.lang.javascript.psi.JSDefinitionExpression; import com.intellij.lang.javascript.psi.JSElementVisitor; import com.intellij.lang.javascript.psi.JSReferenceExpression; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.editor.inspection.ProblemHighlightType; import consulo.language.editor.inspection.ProblemsHolder; +import consulo.language.editor.inspection.localize.InspectionLocalize; import consulo.language.psi.PsiElement; import consulo.language.psi.ResolveResult; -import org.jetbrains.annotations.NonNls; - -import javax.annotation.Nonnull; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; /** - * @by Maxim.Mossienko + * @author Maxim.Mossienko */ @ExtensionImpl -public class JSDeprecatedSymbolsInspection extends JSInspection -{ - @NonNls - private static final String SHORT_NAME = "JSDeprecatedSymbols"; +public class JSDeprecatedSymbolsInspection extends JSInspection { + private static final String SHORT_NAME = "JSDeprecatedSymbols"; - @Override - @Nonnull - public String getGroupDisplayName() - { - return "General"; - } + @Nonnull + @Override + public LocalizeValue getGroupDisplayName() { + return InspectionLocalize.inspectionGeneralToolsGroupName(); + } - @Override - @Nonnull - public String getDisplayName() - { - return JavaScriptBundle.message("js.deprecated.symbols.inspection.name"); - } + @Nonnull + @Override + public LocalizeValue getDisplayName() { + return JavaScriptLocalize.jsDeprecatedSymbolsInspectionName(); + } - @Override - @Nonnull - @NonNls - public String getShortName() - { - return SHORT_NAME; - } + @Nonnull + @Override + public String getShortName() { + return SHORT_NAME; + } - @Override - protected JSElementVisitor createVisitor(final ProblemsHolder holder) - { - return new JSElementVisitor() - { - @Override - public void visitJSReferenceExpression(final JSReferenceExpression node) - { - for(ResolveResult r : node.multiResolve(false)) - { - final PsiElement element = r.getElement(); - if((element instanceof JSDefinitionExpression && element.getParent() instanceof JSAssignmentExpression) || element == node.getParent()) - { - continue; - } - if(JSDocumentationUtils.isDeprecated(element)) - { - holder.registerProblem(node.getReferenceNameElement(), JavaScriptBundle.message("javascript.deprecated.symbol.used.name.message"), - ProblemHighlightType.LIKE_DEPRECATED); - break; - } - } - } - }; - } + @Override + protected JSElementVisitor createVisitor(final ProblemsHolder holder) { + return new JSElementVisitor() { + @Override + @RequiredReadAction + public void visitJSReferenceExpression(@Nonnull JSReferenceExpression node) { + for (ResolveResult r : node.multiResolve(false)) { + PsiElement element = r.getElement(); + if (element instanceof JSDefinitionExpression definition && definition.getParent() instanceof JSAssignmentExpression + || element == node.getParent()) { + continue; + } + if (JSDocumentationUtils.isDeprecated(element)) { + holder.newProblem(JavaScriptLocalize.javascriptDeprecatedSymbolUsedNameMessage()) + .range(node.getReferenceNameElement()) + .highlightType(ProblemHighlightType.LIKE_DEPRECATED) + .create(); + break; + } + } + } + }; + } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSDuplicatedDeclarationInspection.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSDuplicatedDeclarationInspection.java index 958a0ad4..38cd63f8 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSDuplicatedDeclarationInspection.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSDuplicatedDeclarationInspection.java @@ -17,15 +17,17 @@ package com.intellij.lang.javascript.impl.inspections; import com.intellij.lang.javascript.JSElementType; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.JavaScriptSupportLoader; import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.impl.JSEmbeddedContentImpl; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; import com.intellij.lang.javascript.psi.resolve.ResolveProcessor; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.editor.inspection.ProblemHighlightType; import consulo.language.editor.inspection.ProblemsHolder; +import consulo.language.editor.inspection.localize.InspectionLocalize; import consulo.language.editor.rawHighlight.HighlightDisplayLevel; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiFile; @@ -33,207 +35,189 @@ import consulo.language.psi.PsiWhiteSpace; import consulo.language.psi.resolve.ResolveState; import consulo.language.psi.util.PsiTreeUtil; -import org.jetbrains.annotations.NonNls; -import javax.annotation.Nonnull; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; /** * @author Maxim.Mossienko */ @ExtensionImpl -public class JSDuplicatedDeclarationInspection extends JSInspection -{ - @NonNls - private static final String SHORT_NAME = "JSDuplicatedDeclaration"; - - @Override - @Nonnull - public String getGroupDisplayName() - { - return "General"; - } - - @Override - @Nonnull - public String getDisplayName() - { - return JavaScriptBundle.message("js.duplicated.declaration.inspection.name"); - } - - @Override - @Nonnull - @NonNls - public String getShortName() - { - return SHORT_NAME; - } - - @Override - protected JSElementVisitor createVisitor(final ProblemsHolder holder) - { - return new JSElementVisitor() - { - @Override - public void visitJSClass(final JSClass node) - { - final String name = node.getName(); - if(name == null) - { - return; - } - final PsiElement nameIdentifier = node.getNameIdentifier(); - - checkForDuplicateDeclaration(name, node, nameIdentifier); - } - - @Override - public void visitJSFunctionDeclaration(final JSFunction node) - { - final String name = node.getName(); - if(name == null) - { - return; - } - final PsiElement nameIdentifier = node.getNameIdentifier(); - - checkForDuplicateDeclaration(name, node, nameIdentifier); - } - - private void checkForDuplicateDeclaration(final String name, final PsiElement decl, final PsiElement nameIdentifier) - { - PsiElement scope = PsiTreeUtil.getParentOfType(decl, JSFunction.class, JSFile.class, JSEmbeddedContentImpl.class, JSClass.class, - JSObjectLiteralExpression.class, JSPackageStatement.class, PsiFile.class); - if(scope instanceof JSPackageStatement) - { - return; // dedicated inspection - } - final PsiElement originalScope = scope; - if(scope instanceof JSFile && scope.getContext() != null) - { - scope = scope.getContext().getContainingFile(); - } - - final ResolveProcessor processor = new ResolveProcessor(name, scope) - { - @Override - public boolean execute(PsiElement element, ResolveState state) - { - if(element == decl) - { - return true; - } - //if (!decl.getClass().isInstance(element)) return true; - if(decl instanceof JSParameter && decl.getParent() != element.getParent()) - { - return false; - } - - if(element instanceof JSFunction && decl instanceof JSFunction) - { - final JSFunction declFunction = (JSFunction) decl; - final JSFunction elementFunction = (JSFunction) element; - if((declFunction.isGetProperty() && elementFunction.isSetProperty()) || (declFunction.isSetProperty() && elementFunction.isGetProperty())) - { - return true; - } - } - if(element instanceof JSFunction && - decl instanceof JSClass && element.getParent() == decl) - { - return true; - } - - if(element instanceof JSAttributeListOwner && decl instanceof JSAttributeListOwner) - { - JSAttributeList attrList = ((JSAttributeListOwner) element).getAttributeList(); - JSAttributeList attrList2 = ((JSAttributeListOwner) decl).getAttributeList(); - - if(attrList != null && attrList2 != null) - { - final String ns = attrList.getNamespace(); - final String ns2 = attrList2.getNamespace(); - - if((ns != null && !ns.equals(ns2)) || - ns2 != null && !ns2.equals(ns) || - (ns != null && ns2 != null)) - { - return true; - } - } - else if((attrList != null && attrList.getNamespace() != null) || (attrList2 != null && attrList2.getNamespace() != null)) - { - return true; - } - - final boolean notStatic2 = attrList2 == null || !attrList2.hasModifier(JSAttributeList.ModifierType.STATIC); - final boolean notStatic = attrList == null || !attrList.hasModifier(JSAttributeList.ModifierType.STATIC); - if((notStatic2 && !notStatic) || (notStatic && !notStatic2)) - { - return true; - } - } - return super.execute(element, state); - } - }; - - PsiElement parent = JSResolveUtil.findParent(decl); - if(parent instanceof JSClass) - { - processor.configureClassScope((JSClass) parent); - } - - if(decl instanceof JSFunction || decl instanceof JSVariable) - { - JSAttributeList attrList = ((JSAttributeListOwner) decl).getAttributeList(); - processor.setProcessStatics(attrList != null && attrList.hasModifier(JSAttributeList.ModifierType.STATIC)); - } - - processor.setLocalResolve(true); - JSResolveUtil.treeWalkUp(processor, decl, null, decl, scope); - - if(processor.getResult() != null && processor.getResult() != scope) - { - holder.registerProblem(nameIdentifier, JavaScriptBundle.message("javascript.validation.message.duplicate.declaration"), - originalScope.getContainingFile().getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4 ? ProblemHighlightType.ERROR : - ProblemHighlightType - .GENERIC_ERROR_OR_WARNING); - } - } - - @Override - public void visitJSProperty(final JSProperty node) - { - final String name = node.getName(); - if(name == null) - { - return; - } - checkForDuplicateDeclaration(name, node, node.getNameIdentifier()); - } - - @Override - public void visitJSVariable(final JSVariable var) - { - final PsiElement nameIdentifier = var.getNameIdentifier(); - final PsiElement next = nameIdentifier != null ? nameIdentifier.getNextSibling() : null; - final String name = nameIdentifier != null ? nameIdentifier.getText() : null; - - // Actully skip outer language elements - if(name != null && (next == null || - PsiUtilCore.getElementType(next) instanceof JSElementType || - next instanceof PsiWhiteSpace)) - { - checkForDuplicateDeclaration(name, var, nameIdentifier); - } - } - - }; - } - - @Override - @Nonnull - public HighlightDisplayLevel getDefaultLevel() - { - return HighlightDisplayLevel.WARNING; - } +public class JSDuplicatedDeclarationInspection extends JSInspection { + private static final String SHORT_NAME = "JSDuplicatedDeclaration"; + + @Nonnull + @Override + public LocalizeValue getGroupDisplayName() { + return InspectionLocalize.inspectionGeneralToolsGroupName(); + } + + @Nonnull + @Override + public LocalizeValue getDisplayName() { + return JavaScriptLocalize.jsDuplicatedDeclarationInspectionName(); + } + + @Nonnull + @Override + public String getShortName() { + return SHORT_NAME; + } + + @Override + protected JSElementVisitor createVisitor(ProblemsHolder holder) { + return new JSElementVisitor() { + @Override + @RequiredReadAction + public void visitJSClass(@Nonnull JSClass node) { + String name = node.getName(); + if (name == null) { + return; + } + PsiElement nameIdentifier = node.getNameIdentifier(); + + checkForDuplicateDeclaration(name, node, nameIdentifier); + } + + @Override + @RequiredReadAction + public void visitJSFunctionDeclaration(@Nonnull JSFunction node) { + String name = node.getName(); + if (name == null) { + return; + } + PsiElement nameIdentifier = node.getNameIdentifier(); + + checkForDuplicateDeclaration(name, node, nameIdentifier); + } + + @RequiredReadAction + private void checkForDuplicateDeclaration(String name, PsiElement decl, PsiElement nameIdentifier) { + PsiElement scope = PsiTreeUtil.getParentOfType( + decl, + JSFunction.class, + JSFile.class, + JSEmbeddedContentImpl.class, + JSClass.class, + JSObjectLiteralExpression.class, + JSPackageStatement.class, + PsiFile.class + ); + if (scope instanceof JSPackageStatement) { + return; // dedicated inspection + } + PsiElement originalScope = scope; + if (scope instanceof JSFile && scope.getContext() != null) { + scope = scope.getContext().getContainingFile(); + } + + ResolveProcessor processor = new ResolveProcessor(name, scope) { + @Override + @RequiredReadAction + public boolean execute(@Nonnull PsiElement element, ResolveState state) { + if (element == decl) { + return true; + } + //if (!decl.getClass().isInstance(element)) return true; + if (decl instanceof JSParameter && decl.getParent() != element.getParent()) { + return false; + } + + if (element instanceof JSFunction elementFunction && decl instanceof JSFunction declFunction) { + if ((declFunction.isGetProperty() && elementFunction.isSetProperty()) + || (declFunction.isSetProperty() && elementFunction.isGetProperty())) { + return true; + } + } + if (element instanceof JSFunction function && decl instanceof JSClass jsClass && function.getParent() == jsClass) { + return true; + } + + if (element instanceof JSAttributeListOwner elementAttrListOwner + && decl instanceof JSAttributeListOwner declAttrListOwner) { + JSAttributeList attrList = elementAttrListOwner.getAttributeList(); + JSAttributeList attrList2 = declAttrListOwner.getAttributeList(); + + if (attrList != null && attrList2 != null) { + String ns = attrList.getNamespace(); + String ns2 = attrList2.getNamespace(); + + if ((ns != null && !ns.equals(ns2)) || + ns2 != null && !ns2.equals(ns) || + (ns != null && ns2 != null)) { + return true; + } + } + else if ((attrList != null && attrList.getNamespace() != null) + || (attrList2 != null && attrList2.getNamespace() != null)) { + return true; + } + + boolean notStatic2 = attrList2 == null || !attrList2.hasModifier(JSAttributeList.ModifierType.STATIC); + boolean notStatic = attrList == null || !attrList.hasModifier(JSAttributeList.ModifierType.STATIC); + if ((notStatic2 && !notStatic) || (notStatic && !notStatic2)) { + return true; + } + } + return super.execute(element, state); + } + }; + + PsiElement parent = JSResolveUtil.findParent(decl); + if (parent instanceof JSClass jsClass) { + processor.configureClassScope(jsClass); + } + + if (decl instanceof JSFunction function || decl instanceof JSVariable) { + JSAttributeList attrList = ((JSAttributeListOwner)decl).getAttributeList(); + processor.setProcessStatics(attrList != null && attrList.hasModifier(JSAttributeList.ModifierType.STATIC)); + } + + processor.setLocalResolve(true); + JSResolveUtil.treeWalkUp(processor, decl, null, decl, scope); + + if (processor.getResult() != null && processor.getResult() != scope) { + holder.newProblem(JavaScriptLocalize.javascriptValidationMessageDuplicateDeclaration()) + .range(nameIdentifier) + .highlightType( + originalScope.getContainingFile().getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4 + ? ProblemHighlightType.ERROR + : ProblemHighlightType.GENERIC_ERROR_OR_WARNING + ) + .create(); + } + } + + @Override + @RequiredReadAction + public void visitJSProperty(@Nonnull JSProperty node) { + String name = node.getName(); + if (name == null) { + return; + } + checkForDuplicateDeclaration(name, node, node.getNameIdentifier()); + } + + @Override + @RequiredReadAction + public void visitJSVariable(@Nonnull JSVariable var) { + PsiElement nameIdentifier = var.getNameIdentifier(); + PsiElement next = nameIdentifier != null ? nameIdentifier.getNextSibling() : null; + String name = nameIdentifier != null ? nameIdentifier.getText() : null; + + // Actully skip outer language elements + if (name != null && (next == null + || PsiUtilCore.getElementType(next) instanceof JSElementType + || next instanceof PsiWhiteSpace)) { + checkForDuplicateDeclaration(name, var, nameIdentifier); + } + } + }; + } + + @Override + @Nonnull + public HighlightDisplayLevel getDefaultLevel() { + return HighlightDisplayLevel.WARNING; + } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSInspection.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSInspection.java index 8f100336..3e304617 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSInspection.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSInspection.java @@ -32,66 +32,57 @@ import consulo.language.psi.PsiNamedElement; import consulo.language.psi.util.PsiTreeUtil; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** - * User: Maxim.Mossienko - * Date: Apr 18, 2006 - * Time: 7:34:46 PM + * @author Maxim.Mossienko + * @since 2006-08-18 */ -public abstract class JSInspection extends LocalInspectionTool implements CustomSuppressableInspectionTool -{ - protected boolean myOnTheFly; +public abstract class JSInspection extends LocalInspectionTool implements CustomSuppressableInspectionTool { + protected boolean myOnTheFly; - protected abstract JSElementVisitor createVisitor(final ProblemsHolder holder); + protected abstract JSElementVisitor createVisitor(ProblemsHolder holder); - @Override - @Nonnull - public PsiElementVisitor buildVisitor(@Nonnull ProblemsHolder holder, boolean isOnTheFly) - { - myOnTheFly = isOnTheFly; - return createVisitor(holder); - } + @Nonnull + @Override + public PsiElementVisitor buildVisitor(@Nonnull ProblemsHolder holder, boolean isOnTheFly) { + myOnTheFly = isOnTheFly; + return createVisitor(holder); + } - @Override - public boolean isEnabledByDefault() - { - return true; - } + @Override + public boolean isEnabledByDefault() { + return true; + } - @Nullable - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } + @Nullable + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } - @Override - @Nonnull - public HighlightDisplayLevel getDefaultLevel() - { - return HighlightDisplayLevel.WEAK_WARNING; - } + @Nonnull + @Override + public HighlightDisplayLevel getDefaultLevel() { + return HighlightDisplayLevel.WEAK_WARNING; + } - @Override - public PsiNamedElement getProblemElement(final PsiElement psiElement) - { - return PsiTreeUtil.getNonStrictParentOfType(psiElement, JSNamedElement.class); - } + @Override + public PsiNamedElement getProblemElement(PsiElement psiElement) { + return PsiTreeUtil.getNonStrictParentOfType(psiElement, JSNamedElement.class); + } - @Override - @Nullable - public SuppressIntentionAction[] getSuppressActions(final PsiElement element) - { - return new SuppressIntentionAction[]{ - /* new AddNoInspectionCommentFix(HighlightDisplayKey.find(getShortName()), JSSuppressionHolder.class),*/ - }; - } + @Nonnull + @Override + public SuppressIntentionAction[] getSuppressActions(PsiElement element) { + return new SuppressIntentionAction[]{ + /* new AddNoInspectionCommentFix(HighlightDisplayKey.find(getShortName()), JSSuppressionHolder.class),*/ + }; + } - @Override - public boolean isSuppressedFor(final PsiElement element) - { - return SuppressionUtil.isSuppressedInStatement(element, getID(), JSSuppressionHolder.class); - } + @Override + public boolean isSuppressedFor(@Nonnull PsiElement element) { + return SuppressionUtil.isSuppressedInStatement(element, getID(), JSSuppressionHolder.class); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSUndeclaredVariableInspection.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSUndeclaredVariableInspection.java index eb5a836a..1c7d8ce3 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSUndeclaredVariableInspection.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSUndeclaredVariableInspection.java @@ -17,254 +17,211 @@ package com.intellij.lang.javascript.impl.inspections; import com.intellij.lang.javascript.JSTokenTypes; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.util.JSUtils; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; import consulo.document.Document; import consulo.document.util.TextRange; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.codeStyle.CodeStyleManager; import consulo.language.editor.FileModificationService; -import consulo.language.editor.inspection.LocalQuickFix; -import consulo.language.editor.inspection.ProblemDescriptor; -import consulo.language.editor.inspection.ProblemHighlightType; -import consulo.language.editor.inspection.ProblemsHolder; +import consulo.language.editor.inspection.*; +import consulo.language.editor.inspection.localize.InspectionLocalize; import consulo.language.psi.PsiDocumentManager; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiFile; import consulo.language.psi.ResolveResult; import consulo.language.psi.util.PsiTreeUtil; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; import consulo.project.Project; -import org.jetbrains.annotations.NonNls; -import javax.annotation.Nonnull; -import java.util.LinkedList; -import java.util.List; +import jakarta.annotation.Nonnull; /** * @author Maxim.Mossienko */ @ExtensionImpl -public class JSUndeclaredVariableInspection extends JSInspection -{ - @NonNls - public static final String SHORT_NAME = "JSUndeclaredVariable"; - - @Override - @Nonnull - public String getGroupDisplayName() - { - return "General"; - } - - @Override - @Nonnull - public String getDisplayName() - { - return JavaScriptBundle.message("js.undeclared.variable.inspection.name"); - } - - @Override - @Nonnull - @NonNls - public String getShortName() - { - return SHORT_NAME; - } - - @Override - protected JSElementVisitor createVisitor(final ProblemsHolder holder) - { - return new JSElementVisitor() - { - @Override - public void visitJSReferenceExpression(final JSReferenceExpression node) - { - final PsiElement parentElement = node.getParent(); - - if(!(parentElement instanceof JSCallExpression) && node.shouldCheckReferences() && node.getQualifier() == null && parentElement instanceof - JSDefinitionExpression) - { - final JSSourceElement element = PsiTreeUtil.getParentOfType(node, JSWithStatement.class, JSFunction.class); - - if(!(element instanceof JSWithStatement)) - { - boolean varReferenceWithoutVar = true; - final ResolveResult[] resolveResults = node.multiResolve(false); - - for(ResolveResult r : resolveResults) - { - final PsiElement resolveResult = r.getElement(); - if(resolveResult instanceof JSVariable || - resolveResult instanceof JSFunction) - { - varReferenceWithoutVar = false; - break; - } - } - - if(varReferenceWithoutVar) - { - final PsiElement nameIdentifier = node.getReferenceNameElement(); - - if(nameIdentifier != null) - { - final List fixes = new LinkedList(); - - if(myOnTheFly) - { - fixes.add(new DeclareJSVariableIntentionAction(node)); - } - - holder.registerProblem(nameIdentifier, JavaScriptBundle.message("javascript.undeclared.variable.name.message", node.getReferencedName()), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, !fixes.isEmpty() ? fixes.toArray(new LocalQuickFix[fixes.size()]) : null); - } - } - } - } - super.visitJSReferenceExpression(node); - } - }; - } - - private static boolean isImplicitlyDeclared(final JSReferenceExpression node, final PsiElement parentElement) - { - if(parentElement instanceof JSForInStatement) - { - final JSExpression varExpression = ((JSForInStatement) parentElement).getVariableExpression(); - - return PsiTreeUtil.findCommonParent(varExpression, node) == varExpression; - } - else if(parentElement instanceof JSForStatement) - { - final JSExpression varExpression = ((JSForStatement) parentElement).getInitialization(); - - return PsiTreeUtil.findCommonParent(varExpression, node) == varExpression; - } - return false; - } - - private static class DeclareJSVariableIntentionAction implements LocalQuickFix - { - private final JSReferenceExpression myReferenceExpression; - @NonNls - private static final String VAR_STATEMENT_START = "var "; - private final PsiFile myFile; - - DeclareJSVariableIntentionAction(JSReferenceExpression expression) - { - myReferenceExpression = expression; - myFile = expression.getContainingFile(); - } - - @Override - @Nonnull - public String getName() - { - return JavaScriptBundle.message("javascript.declare.variable.intention.name", myReferenceExpression.getReferencedName()); - } - - @Override - @Nonnull - public String getFamilyName() - { - return JavaScriptBundle.message("javascript.create.variable.intention.family"); - } - - @Override - public void applyFix(@Nonnull Project project, @Nonnull ProblemDescriptor descriptor) - { - if(!FileModificationService.getInstance().prepareFileForWrite(myFile)) - { - return; - } - - PsiElement anchor = JSUtils.findStatementAnchor(myReferenceExpression, myFile); - boolean implicitlyDeclared = isImplicitlyDeclared(myReferenceExpression, anchor); - - if(implicitlyDeclared) - { - anchor = myReferenceExpression; - final JSStatement statement = PsiTreeUtil.getParentOfType(anchor, JSForStatement.class, JSStatement.class); - - if(statement instanceof JSForStatement) - { - final JSExpression initialization = ((JSForStatement) statement).getInitialization(); - - if(initialization instanceof JSBinaryExpression && ((JSBinaryExpression) initialization).getOperationSign() == JSTokenTypes.COMMA) - { - anchor = ((JSAssignmentExpression) ((JSBinaryExpression) initialization).getLOperand()).getLOperand(); - } - } - } - - if(anchor != null) - { - boolean anchorChanged = false; - - if(!implicitlyDeclared) - { - PsiElement parent = anchor.getParent(); - - while(parent instanceof JSBlockStatement || parent instanceof JSIfStatement || parent instanceof JSLoopStatement) - { - PsiElement newAnchor = parent.getParent(); - - if(newAnchor instanceof JSIfStatement || newAnchor instanceof JSWithStatement || newAnchor instanceof JSLoopStatement || - newAnchor instanceof JSTryStatement || newAnchor instanceof JSSwitchStatement) - { - anchor = newAnchor; - parent = anchor.getParent(); - anchorChanged = true; - } - else if(newAnchor instanceof JSFile) - { - anchor = parent; - anchorChanged = true; - break; - } - else - { - break; - } - } - } - - final TextRange textRange = anchor.getTextRange(); - final int startOffset = textRange.getStartOffset(); - @NonNls StringBuilder builder = new StringBuilder(); - builder.append(VAR_STATEMENT_START); - - if(anchor instanceof JSExpressionStatement) - { - JSExpression expr = ((JSExpressionStatement) anchor).getExpression(); - if(expr instanceof JSAssignmentExpression && ((JSAssignmentExpression) expr).getOperationSign() != JSTokenTypes.EQ) - { - anchorChanged = true; - } - } - - if((anchorChanged || !(anchor instanceof JSExpressionStatement)) && !implicitlyDeclared) - { - // var statement should be inserted completely - builder.append(myReferenceExpression.getReferencedName()).append(";\n"); - } - - Document document = PsiDocumentManager.getInstance(project).getDocument(myFile); - document.replaceString(startOffset, startOffset, builder); - PsiDocumentManager.getInstance(project).commitDocument(document); - - try - { - CodeStyleManager.getInstance(project).reformatText(myFile, startOffset, textRange.getEndOffset() + builder.length()); - } - catch(IncorrectOperationException e) - { - e.printStackTrace(); - } - myFile.navigate(true); - } - } - } +public class JSUndeclaredVariableInspection extends JSInspection { + public static final String SHORT_NAME = "JSUndeclaredVariable"; + + @Nonnull + @Override + public LocalizeValue getGroupDisplayName() { + return InspectionLocalize.inspectionGeneralToolsGroupName(); + } + + @Nonnull + @Override + public LocalizeValue getDisplayName() { + return JavaScriptLocalize.jsUndeclaredVariableInspectionName(); + } + + @Nonnull + @Override + public String getShortName() { + return SHORT_NAME; + } + + @Override + protected JSElementVisitor createVisitor(ProblemsHolder holder) { + return new JSElementVisitor() { + @Override + public void visitJSReferenceExpression(@Nonnull JSReferenceExpression node) { + PsiElement parentElement = node.getParent(); + + if (!(parentElement instanceof JSCallExpression) && node.shouldCheckReferences() + && node.getQualifier() == null && parentElement instanceof JSDefinitionExpression) { + JSSourceElement element = PsiTreeUtil.getParentOfType(node, JSWithStatement.class, JSFunction.class); + + if (!(element instanceof JSWithStatement)) { + boolean varReferenceWithoutVar = true; + ResolveResult[] resolveResults = node.multiResolve(false); + + for (ResolveResult r : resolveResults) { + PsiElement resolveResult = r.getElement(); + if (resolveResult instanceof JSVariable + || resolveResult instanceof JSFunction) { + varReferenceWithoutVar = false; + break; + } + } + + if (varReferenceWithoutVar) { + PsiElement nameIdentifier = node.getReferenceNameElement(); + + if (nameIdentifier != null) { + ProblemBuilder problemBuilder = + holder.newProblem(JavaScriptLocalize.javascriptUndeclaredVariableNameMessage(node.getReferencedName())) + .range(nameIdentifier) + .highlightType(ProblemHighlightType.GENERIC_ERROR_OR_WARNING); + + if (myOnTheFly) { + problemBuilder.withFixes(new DeclareJSVariableIntentionAction(node)); + } + + problemBuilder.create(); + } + } + } + } + super.visitJSReferenceExpression(node); + } + }; + } + + @RequiredReadAction + private static boolean isImplicitlyDeclared(JSReferenceExpression node, PsiElement parentElement) { + if (parentElement instanceof JSForInStatement forInStatement) { + JSExpression varExpression = forInStatement.getVariableExpression(); + + return PsiTreeUtil.findCommonParent(varExpression, node) == varExpression; + } + else if (parentElement instanceof JSForStatement forStatement) { + JSExpression varExpression = forStatement.getInitialization(); + + return PsiTreeUtil.findCommonParent(varExpression, node) == varExpression; + } + return false; + } + + private static class DeclareJSVariableIntentionAction implements LocalQuickFix { + private final JSReferenceExpression myReferenceExpression; + private static final String VAR_STATEMENT_START = "var "; + private final PsiFile myFile; + + DeclareJSVariableIntentionAction(JSReferenceExpression expression) { + myReferenceExpression = expression; + myFile = expression.getContainingFile(); + } + + @Nonnull + @Override + public LocalizeValue getName() { + return JavaScriptLocalize.javascriptDeclareVariableIntentionName(myReferenceExpression.getReferencedName()); + } + + @Override + @RequiredReadAction + public void applyFix(@Nonnull Project project, @Nonnull ProblemDescriptor descriptor) { + if (!FileModificationService.getInstance().prepareFileForWrite(myFile)) { + return; + } + + PsiElement anchor = JSUtils.findStatementAnchor(myReferenceExpression, myFile); + boolean implicitlyDeclared = isImplicitlyDeclared(myReferenceExpression, anchor); + + if (implicitlyDeclared) { + anchor = myReferenceExpression; + JSStatement statement = PsiTreeUtil.getParentOfType(anchor, JSForStatement.class, JSStatement.class); + + if (statement instanceof JSForStatement forStatement) { + JSExpression initialization = forStatement.getInitialization(); + + if (initialization instanceof JSBinaryExpression binary && binary.getOperationSign() == JSTokenTypes.COMMA) { + anchor = ((JSAssignmentExpression)binary.getLOperand()).getLOperand(); + } + } + } + + if (anchor != null) { + boolean anchorChanged = false; + + if (!implicitlyDeclared) { + PsiElement parent = anchor.getParent(); + + while (parent instanceof JSBlockStatement || parent instanceof JSIfStatement || parent instanceof JSLoopStatement) { + PsiElement newAnchor = parent.getParent(); + + if (newAnchor instanceof JSIfStatement + || newAnchor instanceof JSWithStatement + || newAnchor instanceof JSLoopStatement + || newAnchor instanceof JSTryStatement + || newAnchor instanceof JSSwitchStatement) { + anchor = newAnchor; + parent = anchor.getParent(); + anchorChanged = true; + } + else if (newAnchor instanceof JSFile) { + anchor = parent; + anchorChanged = true; + break; + } + else { + break; + } + } + } + + TextRange textRange = anchor.getTextRange(); + int startOffset = textRange.getStartOffset(); + StringBuilder builder = new StringBuilder(); + builder.append(VAR_STATEMENT_START); + + if (anchor instanceof JSExpressionStatement expressionStatement + && expressionStatement.getExpression() instanceof JSAssignmentExpression assignment + && assignment.getOperationSign() != JSTokenTypes.EQ) { + anchorChanged = true; + } + + if ((anchorChanged || !(anchor instanceof JSExpressionStatement)) && !implicitlyDeclared) { + // var statement should be inserted completely + builder.append(myReferenceExpression.getReferencedName()).append(";\n"); + } + + Document document = PsiDocumentManager.getInstance(project).getDocument(myFile); + document.replaceString(startOffset, startOffset, builder); + PsiDocumentManager.getInstance(project).commitDocument(document); + + try { + CodeStyleManager.getInstance(project).reformatText(myFile, startOffset, textRange.getEndOffset() + builder.length()); + } + catch (IncorrectOperationException e) { + e.printStackTrace(); + } + myFile.navigate(true); + } + } + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSUnresolvedFunctionInspection.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSUnresolvedFunctionInspection.java index 13edeb48..ad97e773 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSUnresolvedFunctionInspection.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSUnresolvedFunctionInspection.java @@ -17,627 +17,601 @@ package com.intellij.lang.javascript.impl.inspections; import com.intellij.lang.javascript.JSTokenTypes; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.JavaScriptSupportLoader; -import com.intellij.lang.javascript.impl.flex.AddImportECMAScriptClassOrFunctionAction; import com.intellij.lang.javascript.flex.XmlBackedJSClassImpl; +import com.intellij.lang.javascript.impl.flex.AddImportECMAScriptClassOrFunctionAction; +import com.intellij.lang.javascript.impl.validation.JSAnnotatingVisitor; import com.intellij.lang.javascript.inspections.qucikFixes.BaseCreateFix; import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.resolve.JSImportHandlingUtil; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; import com.intellij.lang.javascript.psi.util.JSUtils; -import com.intellij.lang.javascript.impl.validation.JSAnnotatingVisitor; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; import consulo.codeEditor.Editor; import consulo.javascript.ide.codeInsight.JavaScriptQuickFixFactory; import consulo.javascript.language.JavaScriptFeature; import consulo.javascript.language.JavaScriptVersionUtil; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.ast.IElementType; import consulo.language.editor.inspection.LocalQuickFix; import consulo.language.editor.inspection.ProblemDescriptor; import consulo.language.editor.inspection.ProblemHighlightType; import consulo.language.editor.inspection.ProblemsHolder; +import consulo.language.editor.inspection.localize.InspectionLocalize; import consulo.language.editor.template.Template; import consulo.language.editor.template.TemplateManager; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiFile; import consulo.language.psi.ResolveResult; import consulo.language.psi.util.PsiTreeUtil; +import consulo.localize.LocalizeValue; import consulo.project.Project; +import consulo.ui.annotation.RequiredUIAccess; import consulo.xml.ide.highlighter.XmlFileType; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.PropertyKey; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.LinkedList; +import java.util.ArrayList; import java.util.List; +import java.util.function.BiFunction; /** * @author Maxim.Mossienko */ @ExtensionImpl -public class JSUnresolvedFunctionInspection extends JSInspection -{ - @NonNls - private static final String SHORT_NAME = "JSUnresolvedFunction"; - - @Override - @Nonnull - public String getGroupDisplayName() - { - return "General"; - } - - @Override - @Nonnull - public String getDisplayName() - { - return JavaScriptBundle.message("js.unresolved.function.inspection.name"); - } - - @Override - @Nonnull - @NonNls - public String getShortName() - { - return SHORT_NAME; - } - - @Override - protected JSElementVisitor createVisitor(final ProblemsHolder holder) - { - return new JSElementVisitor() - { - @Override - public void visitJSCallExpression(final JSCallExpression node) - { - final JSExpression methodExpression = node.getMethodExpression(); - - if(methodExpression instanceof JSReferenceExpression) - { - final JSReferenceExpression referenceExpression = (JSReferenceExpression) methodExpression; - final ResolveResult[] resolveResults = referenceExpression.multiResolve(false); - - boolean noCompleteResolve = true; - - boolean inNewExpression = node instanceof JSNewExpression; - for(ResolveResult r : resolveResults) - { - if(r.isValidResult()) - { - noCompleteResolve = false; - - PsiElement element = r.getElement(); - - if(element instanceof JSVariable) - { - String typeText = ((JSVariable) element).getTypeString(); - - if(typeText != null && !"*".equals(typeText)) - { - if(!allowMemberReference(inNewExpression, typeText)) - { - holder.registerProblem(((JSReferenceExpression) methodExpression).getReferenceNameElement(), JavaScriptBundle.message("javascript.term.does.not" + - ".evaluate.to.function"), getHighlightTypeForTypeOrSignatureProblem(node)); - } - } - } - else if(element instanceof JSFunction && ((JSFunction) element).isGetProperty()) - { - String typeText = ((JSFunction) element).getReturnTypeString(); - - if(!allowMemberReference(inNewExpression, typeText)) - { - JSArgumentList argumentList = node.getArgumentList(); - LocalQuickFix fixes[] = LocalQuickFix.EMPTY_ARRAY; - - if(argumentList != null) - { - fixes = new LocalQuickFix[]{ - new JSAnnotatingVisitor.RemoveASTNodeFix(argumentList.getNode(), "javascript.term.does.not.evaluate.to.function2.fix") - }; - } - - holder.registerProblem(((JSReferenceExpression) methodExpression).getReferenceNameElement(), JavaScriptBundle.message("javascript.term.does.not" + - ".evaluate.to.function2"), getHighlightTypeForTypeOrSignatureProblem(node), fixes); - } - } - break; - } - } - JavaScriptQuickFixFactory javaScriptQuickFixFactory = JavaScriptQuickFixFactory.byElement(referenceExpression); - - if(resolveResults.length == 0 || noCompleteResolve) - { - final JSExpression qualifier = referenceExpression.getQualifier(); - final List quickFixes = new LinkedList(); - final String refName = referenceExpression.getReferencedName(); - - if(myOnTheFly && ((qualifier == null || qualifier instanceof JSThisExpression) || JSUtils.isLHSExpression(qualifier))) - { - if(methodExpression.getParent() instanceof JSCallExpression) - { - boolean simpleJs = !JavaScriptVersionUtil.containsFeature(referenceExpression, JavaScriptFeature.CLASS); - - if(!inNewExpression || simpleJs) - { - quickFixes.add(javaScriptQuickFixFactory.createFunctionOrMethodFix(refName, true)); - } - - if(qualifier == null) - { - if(simpleJs) - { - quickFixes.add(javaScriptQuickFixFactory.createFunctionOrMethodFix(refName, false)); - } - else - { - quickFixes.add(new AddImportECMAScriptClassOrFunctionAction(null, referenceExpression)); - if(inNewExpression) - { - quickFixes.add(new CreateClassOrInterfaceAction(referenceExpression, false)); - } - } - } - } - } - - final PsiElement referenceNameElement = referenceExpression.getReferenceNameElement(); - - if(referenceNameElement != null) - { - holder.registerProblem(referenceNameElement, JavaScriptBundle.message(inNewExpression ? "javascript.unresolved.type.name.message" : "javascript" + - ".unresolved.function.name.message", refName), getUnresolveReferenceHighlightType(qualifier, node), - quickFixes.size() > 0 ? quickFixes.toArray(new LocalQuickFix[quickFixes.size()]) : null); - } - } - else - { - PsiElement element = resolveResults[0].getElement(); - - if(inNewExpression && element instanceof JSClass && ((JSClass) element).isInterface()) - { - final PsiElement referenceNameElement = referenceExpression.getReferenceNameElement(); - - holder.registerProblem(referenceNameElement, JavaScriptBundle.message("javascript.interface.can.not.be.instantiated.message"), - getUnresolveReferenceHighlightType(referenceExpression.getQualifier(), node)); - } - else - { - checkFunction(node, element, holder); - } - } - } - else if(methodExpression instanceof JSSuperExpression) - { - final PsiElement element = (methodExpression.getReference()).resolve(); - - if(element != null) - { - checkFunction(node, element, holder); - } - } - else if(methodExpression instanceof JSNewExpression) - { - JSExpression methodExpr = ((JSNewExpression) methodExpression).getMethodExpression(); - - if(methodExpr instanceof JSReferenceExpression) - { - ResolveResult[] results = ((JSReferenceExpression) methodExpr).multiResolve(false); - PsiElement elt; - - if(results.length > 0 && ((elt = results[0].getElement()) instanceof JSFunction && ((JSFunction) elt).isConstructor() || elt instanceof - JSClass)) - { - holder.registerProblem(methodExpression, JavaScriptBundle.message("javascript.term.does.not.evaluate.to.function"), - getUnresolveReferenceHighlightType(null, node)); - } - } - } - - super.visitJSCallExpression(node); - } - - @Override - public void visitJSAssignmentExpression(final JSAssignmentExpression node) - { - final JSExpression lOperand = node.getLOperand(); - if(lOperand == null) - { - return; - } - final JSExpression rOperand = node.getROperand(); - if(rOperand == null) - { - return; - } - - final PsiFile containingFile = node.getContainingFile(); - if(containingFile.getLanguage() != JavaScriptSupportLoader.ECMA_SCRIPT_L4) - { - return; - } - String expressionType = null; - - if(lOperand instanceof JSDefinitionExpression) - { - JSExpression expression = ((JSDefinitionExpression) lOperand).getExpression(); - if(expression instanceof JSReferenceExpression) - { - PsiElement resolve = JSResolveUtil.unwrapProxy(((JSReferenceExpression) expression).resolve()); - - if(resolve instanceof JSNamedElement) - { - expressionType = JSResolveUtil.getTypeFromSetAccessor((JSNamedElement) resolve); - if(expressionType != null) - { - expressionType = JSImportHandlingUtil.resolveTypeName(expressionType, resolve); - } - } - } - } - - if(expressionType == null) - { - expressionType = JSResolveUtil.getQualifiedExpressionType(lOperand, containingFile); - } - checkExpressionIsAssignableToType(rOperand, expressionType, holder, containingFile, "javascript.assigned.expression.type.mismatch"); - } - - @Override - public void visitJSReturnStatement(final JSReturnStatement node) - { - final JSExpression expression = node.getExpression(); - if(expression == null) - { - return; - } - - final JSFunction fun = PsiTreeUtil.getParentOfType(node, JSFunction.class); - if(fun == null) - { - return; // TODO: complain about it - } - final String typeString = fun.getReturnTypeString(); - if(typeString == null) - { - return; - } - final PsiFile containingFile = fun.getContainingFile(); - if(containingFile.getLanguage() != JavaScriptSupportLoader.ECMA_SCRIPT_L4) - { - return; - } - - checkExpressionIsAssignableToType(expression, JSImportHandlingUtil.resolveTypeName(typeString, fun), holder, containingFile, - "javascript.returned.expression.type.mismatch"); - } - - @Override - public void visitJSVariable(final JSVariable node) - { - final JSExpression initializer = node.getInitializer(); - if(initializer == null) - { - return; - } - checkExpressionIsAssignableToVariable(node, initializer, holder, node.getContainingFile(), "javascript.initializer.type.mismatch"); - } - - @Override - public void visitJSBinaryExpression(JSBinaryExpression node) - { - IElementType sign = node.getOperationSign(); - - if(sign == JSTokenTypes.AS_KEYWORD || sign == JSTokenTypes.IS_KEYWORD) - { - JSExpression rOperand = node.getROperand(); - - if(rOperand instanceof JSReferenceExpression) - { - ResolveResult[] results = ((JSReferenceExpression) rOperand).multiResolve(false); - - if(results.length > 0 && results[0].getElement() instanceof JSVariable) - { - checkTypeIs(rOperand, rOperand, holder, "Class", "javascript.binary.operand.type.mismatch"); - } - } - } - } - - @Override - public void visitJSForInStatement(JSForInStatement node) - { - if(!node.isForEach()) - { - JSVarStatement statement = node.getDeclarationStatement(); - - if(statement != null) - { - String expressionType = JSResolveUtil.getQualifiedExpressionType(node.getCollectionExpression(), node.getContainingFile()); - boolean isDictionary = "flash.utils.Dictionary".equals(expressionType); - - for(JSVariable var : statement.getVariables()) - { - PsiElement typeElement = var.getTypeElement(); - String typeElementText; - - if(typeElement != null && - "Array".equals(expressionType) && - ("Object".equals(typeElementText = typeElement.getText()) || "*".equals(typeElementText))) - { - holder.registerProblem(typeElement, JavaScriptBundle.message("javascript.incorrect.array.type.in.for-in"), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING); - continue; - } - - if(isDictionary && typeElement != null && "Object".equals(typeElement.getText())) - { - continue; - } - checkTypeIs(typeElement, typeElement, holder, "XMLList".equals(expressionType) ? "XML" : "String", - "javascript.incorrect.variable.type.mismatch"); - } - } - } - } - }; - } - - private static boolean allowMemberReference(boolean inNewExpression, String typeText) - { - return ("Class".equals(typeText) && inNewExpression) || "Function".equals(typeText); - } - - private static void checkTypeIs(PsiElement type, PsiElement node, ProblemsHolder holder, String typeName, String key) - { - if(type instanceof JSReferenceExpression) - { - checkTypeIs((JSExpression) type, node, holder, typeName, key); - } - else if(type != null) - { - holder.registerProblem(node, JavaScriptBundle.message(key, typeName, type.getText()), getHighlightTypeForTypeOrSignatureProblem(node)); - } - } - - private static void checkTypeIs(JSExpression rOperand, PsiElement node, ProblemsHolder holder, String typeName, String key) - { - String expressionType = JSResolveUtil.getQualifiedExpressionType(rOperand, rOperand.getContainingFile()); - if(!typeName.equals(expressionType)) - { - holder.registerProblem(node, JavaScriptBundle.message(key, typeName, expressionType), getHighlightTypeForTypeOrSignatureProblem(node)); - } - } - - static ProblemHighlightType getUnresolveReferenceHighlightType(final @Nullable JSExpression qualifier, @Nonnull JSExpression node) - { - JSClass jsClass; - - final PsiFile containingFile = node.getContainingFile(); - if(qualifier != null) - { - jsClass = JSResolveUtil.findClassOfQualifier(qualifier, containingFile); - - if(jsClass == null && (qualifier instanceof JSReferenceExpression)) - { - ResolveResult[] results = ((JSReferenceExpression) qualifier).multiResolve(false); - - if(results.length != 0) - { - PsiElement resultElement = results[0].getElement(); - String type = null; - - if(resultElement instanceof JSVariable) - { - type = ((JSVariable) resultElement).getTypeString(); - } - else if(resultElement instanceof JSFunction) - { - type = ((JSFunction) resultElement).getReturnTypeString(); - } - - if("*".equals(type)) - { - return ProblemHighlightType.LIKE_UNKNOWN_SYMBOL; - } - jsClass = JSResolveUtil.getClassOfContext(resultElement); - } - } - } - else - { - jsClass = JSResolveUtil.getClassOfContext(node); - } - - final boolean ecmaL4File = containingFile.getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4; - - if(jsClass != null && ecmaL4File && - (!(jsClass instanceof XmlBackedJSClassImpl) || jsClass.getContainingFile().getFileType() == XmlFileType.INSTANCE)) - { - final JSAttributeList attributeList = jsClass.getAttributeList(); - if(attributeList == null || !attributeList.hasModifier(JSAttributeList.ModifierType.DYNAMIC)) - { - return ProblemHighlightType.ERROR; - } - } - - if(ecmaL4File && jsClass == null && node.getParent() instanceof JSReferenceList) - { - return ProblemHighlightType.ERROR; - } - return ProblemHighlightType.LIKE_UNKNOWN_SYMBOL; - } - - private static void checkFunction(final JSCallExpression node, final PsiElement element, final ProblemsHolder holder) - { - if(element instanceof JSFunction) - { - final JSFunction function = (JSFunction) element; - if(!function.isGetProperty() || !"Function".equals(function.getReturnTypeString())) - { - final JSParameterList parameterList = function.getParameterList(); - - if(parameterList != null) - { - checkCallParameters(node, parameterList.getParameters(), function.isReferencesArguments(), holder); - } - } - } - else if(element instanceof JSClass) - { - if(node instanceof JSNewExpression || node.getMethodExpression() instanceof JSSuperExpression) - { - checkCallParameters(node, JSParameter.EMPTY_ARRAY, false, holder); - } - else - { - JSArgumentList argumentList = node.getArgumentList(); - if(argumentList == null || argumentList.getArguments().length != 1) - { - holder.registerProblem(argumentList != null ? argumentList : node, JavaScriptBundle.message("javascript.invalid.number.of.parameters", "one"), - getHighlightTypeForTypeOrSignatureProblem(node)); - } - } - } - } - - private static void checkCallParameters(final JSCallExpression node, final JSParameter[] parameters, boolean functionReferencesArguments, - final ProblemsHolder holder) - { - final JSArgumentList argumentList = node.getArgumentList(); - final JSExpression[] expressions = argumentList != null ? argumentList.getArguments() : JSExpression.EMPTY_ARRAY; - - boolean lastIsRest = false; - int minParameterLength = 0; - int maxParameterLength = parameters.length; - - for(int i = 0; i < parameters.length; ++i) - { - final JSParameter parameter = parameters[i]; - if(parameter.isOptional()) - { - break; - } - - if(i == parameters.length - 1 && parameter.isRest()) - { - lastIsRest = true; - maxParameterLength = Integer.MAX_VALUE; - break; - } - minParameterLength++; - } - - if(!lastIsRest && parameters.length > 0 && parameters[parameters.length - 1].isRest()) - { - lastIsRest = true; - maxParameterLength = Integer.MAX_VALUE; - } - - if((expressions.length < minParameterLength || expressions.length > maxParameterLength) && !functionReferencesArguments) - { - final String s = (lastIsRest ? minParameterLength + " or more " : String.valueOf(minParameterLength) + (minParameterLength != maxParameterLength - ? ".." + maxParameterLength : "")); - holder.registerProblem(argumentList != null ? argumentList : node, JavaScriptBundle.message("javascript.invalid.number.of.parameters", s), - getHighlightTypeForTypeOrSignatureProblem(node)); - } - else - { - int i = 0; - final PsiFile containingFile = node.getContainingFile(); - - for(JSParameter p : parameters) - { - if(i == expressions.length) - { - break; - } - if(p.isRest()) - { - break; - } - checkExpressionIsAssignableToVariable(p, expressions[i], holder, containingFile, "javascript.argument.type.mismatch"); - ++i; - } - } - } - - private static void checkExpressionIsAssignableToVariable(final JSVariable p, JSExpression expr, final ProblemsHolder holder, - final PsiFile containingFile, @PropertyKey(resourceBundle = JavaScriptBundle.BUNDLE) String problemKey) - { - final String parameterTypeResolved = JSImportHandlingUtil.resolveTypeName(p.getTypeString(), p); - checkExpressionIsAssignableToType(expr, parameterTypeResolved, holder, containingFile, problemKey); - } - - private static void checkExpressionIsAssignableToType(final JSExpression expr, final String type, final ProblemsHolder holder, - final PsiFile containingFile, final String problemKey) - { - if("*".equals(type) || type == null) - { - return; // optimization - } - final String expressionType = JSResolveUtil.getQualifiedExpressionType(expr, containingFile); - - if(!JSResolveUtil.isAssignableType(type, expressionType, containingFile)) - { - holder.registerProblem(expr, JavaScriptBundle.message(problemKey, type, expressionType), getHighlightTypeForTypeOrSignatureProblem(expr), - new JSInsertCastFix(type)); - } - } - - private static ProblemHighlightType getHighlightTypeForTypeOrSignatureProblem(@Nonnull PsiElement node) - { - if(node.getContainingFile().getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4) - { - return ProblemHighlightType.GENERIC_ERROR; - } - return ProblemHighlightType.GENERIC_ERROR_OR_WARNING; - } - - private static class JSInsertCastFix implements LocalQuickFix - { - private final String type; - - public JSInsertCastFix(final String type) - { - this.type = type; - } - - @Override - @Nonnull - public String getName() - { - return JavaScriptBundle.message("javascript.insert.cast.fix"); - } - - @Override - @Nonnull - public String getFamilyName() - { - return getName(); - } - - @Override - public void applyFix(@Nonnull final Project project, @Nonnull final ProblemDescriptor descriptor) - { - final PsiElement element = descriptor.getPsiElement(); - final Editor editor = BaseCreateFix.getEditor(project, element.getContainingFile()); - if(editor == null) - { - return; - } - - final String shortenedType = JSResolveUtil.getShortenedType(this.type, element); - final TemplateManager templateManager = TemplateManager.getInstance(project); - Template template = templateManager.createTemplate("", "", shortenedType + "($SELECTION$)"); - template.setToReformat(true); - - final int offset = element.getTextOffset(); - editor.getSelectionModel().setSelection(offset, offset + element.getTextLength()); - editor.getCaretModel().moveToOffset(offset); - templateManager.startTemplate(editor, element.getText(), template); - } - } +public class JSUnresolvedFunctionInspection extends JSInspection { + private static final String SHORT_NAME = "JSUnresolvedFunction"; + + @Nonnull + @Override + public LocalizeValue getGroupDisplayName() { + return InspectionLocalize.inspectionGeneralToolsGroupName(); + } + + @Nonnull + @Override + public LocalizeValue getDisplayName() { + return JavaScriptLocalize.jsUnresolvedFunctionInspectionName(); + } + + @Nonnull + @Override + public String getShortName() { + return SHORT_NAME; + } + + @Override + protected JSElementVisitor createVisitor(final ProblemsHolder holder) { + return new JSElementVisitor() { + @Override + @RequiredReadAction + public void visitJSCallExpression(@Nonnull JSCallExpression node) { + if (node.getMethodExpression() instanceof JSReferenceExpression methodRefExpr) { + ResolveResult[] resolveResults = methodRefExpr.multiResolve(false); + + boolean noCompleteResolve = true; + + boolean inNewExpression = node instanceof JSNewExpression; + for (ResolveResult r : resolveResults) { + if (r.isValidResult()) { + noCompleteResolve = false; + + PsiElement element = r.getElement(); + + if (element instanceof JSVariable variable) { + String typeText = variable.getTypeString(); + + if (typeText != null && !"*".equals(typeText) && !allowMemberReference(inNewExpression, typeText)) { + holder.newProblem(JavaScriptLocalize.javascriptTermDoesNotEvaluateToFunction()) + .range(methodRefExpr.getReferenceNameElement()) + .highlightType(getHighlightTypeForTypeOrSignatureProblem(node)) + .create(); + } + } + else if (element instanceof JSFunction function && function.isGetProperty()) { + String typeText = function.getReturnTypeString(); + + if (!allowMemberReference(inNewExpression, typeText)) { + JSArgumentList argumentList = node.getArgumentList(); + LocalQuickFix fixes[] = LocalQuickFix.EMPTY_ARRAY; + + if (argumentList != null) { + fixes = new LocalQuickFix[]{ + new JSAnnotatingVisitor.RemoveASTNodeFix( + argumentList.getNode(), + JavaScriptLocalize.javascriptTermDoesNotEvaluateToFunction2Fix() + ) + }; + } + + holder.newProblem(JavaScriptLocalize.javascriptTermDoesNotEvaluateToFunction2()) + .range(methodRefExpr.getReferenceNameElement()) + .highlightType(getHighlightTypeForTypeOrSignatureProblem(node)) + .withFixes(fixes) + .create(); + } + } + break; + } + } + JavaScriptQuickFixFactory javaScriptQuickFixFactory = JavaScriptQuickFixFactory.byElement(methodRefExpr); + + if (resolveResults.length == 0 || noCompleteResolve) { + JSExpression qualifier = methodRefExpr.getQualifier(); + List quickFixes = new ArrayList<>(); + String refName = methodRefExpr.getReferencedName(); + + if (myOnTheFly + && (qualifier == null || qualifier instanceof JSThisExpression || JSUtils.isLHSExpression(qualifier))) { + if (node.getMethodExpression().getParent() instanceof JSCallExpression) { + boolean simpleJs = !JavaScriptVersionUtil.containsFeature(methodRefExpr, JavaScriptFeature.CLASS); + + if (!inNewExpression || simpleJs) { + quickFixes.add(javaScriptQuickFixFactory.createFunctionOrMethodFix(refName, true)); + } + + if (qualifier == null) { + if (simpleJs) { + quickFixes.add(javaScriptQuickFixFactory.createFunctionOrMethodFix(refName, false)); + } + else { + quickFixes.add(new AddImportECMAScriptClassOrFunctionAction(null, methodRefExpr)); + if (inNewExpression) { + quickFixes.add(new CreateClassOrInterfaceAction(methodRefExpr, false)); + } + } + } + } + } + + PsiElement referenceNameElement = methodRefExpr.getReferenceNameElement(); + + if (referenceNameElement != null) { + holder.newProblem( + inNewExpression + ? JavaScriptLocalize.javascriptUnresolvedTypeNameMessage(refName) + : JavaScriptLocalize.javascriptUnresolvedFunctionNameMessage(refName) + ) + .range(referenceNameElement) + .highlightType(getUnresolveReferenceHighlightType(qualifier, node)) + .withFixes(quickFixes.size() > 0 ? quickFixes.toArray(new LocalQuickFix[quickFixes.size()]) : null) + .create(); + } + } + else { + PsiElement element = resolveResults[0].getElement(); + + if (inNewExpression && element instanceof JSClass jsClass && jsClass.isInterface()) { + holder.newProblem(JavaScriptLocalize.javascriptInterfaceCanNotBeInstantiatedMessage()) + .range(methodRefExpr.getReferenceNameElement()) + .highlightType(getUnresolveReferenceHighlightType(methodRefExpr.getQualifier(), node)) + .create(); + } + else { + checkFunction(node, element, holder); + } + } + } + else if (node.getMethodExpression() instanceof JSSuperExpression superExpression) { + PsiElement element = superExpression.getReference().resolve(); + + if (element != null) { + checkFunction(node, element, holder); + } + } + else if (node.getMethodExpression() instanceof JSNewExpression newExpression) { + if (newExpression.getMethodExpression() instanceof JSReferenceExpression methodRefExpr) { + ResolveResult[] results = methodRefExpr.multiResolve(false); + PsiElement element = results.length > 0 ? results[0].getElement() : null; + if (element instanceof JSFunction function && function.isConstructor() + || element instanceof JSClass) { + + holder.newProblem(JavaScriptLocalize.javascriptTermDoesNotEvaluateToFunction()) + .range(node.getMethodExpression()) + .highlightType(getUnresolveReferenceHighlightType(null, node)) + .create(); + } + } + } + + super.visitJSCallExpression(node); + } + + @Override + @RequiredReadAction + public void visitJSAssignmentExpression(@Nonnull JSAssignmentExpression node) { + JSExpression lOperand = node.getLOperand(); + if (lOperand == null) { + return; + } + + JSExpression rOperand = node.getROperand(); + if (rOperand == null) { + return; + } + + PsiFile containingFile = node.getContainingFile(); + if (containingFile.getLanguage() != JavaScriptSupportLoader.ECMA_SCRIPT_L4) { + return; + } + String expressionType = null; + + if (lOperand instanceof JSDefinitionExpression definition + && definition.getExpression() instanceof JSReferenceExpression refExpr + && JSResolveUtil.unwrapProxy(refExpr.resolve()) instanceof JSNamedElement namedElement) { + + expressionType = JSResolveUtil.getTypeFromSetAccessor(namedElement); + if (expressionType != null) { + expressionType = JSImportHandlingUtil.resolveTypeName(expressionType, namedElement); + } + } + + if (expressionType == null) { + expressionType = JSResolveUtil.getQualifiedExpressionType(lOperand, containingFile); + } + checkExpressionIsAssignableToType( + rOperand, + expressionType, + holder, + containingFile, + JavaScriptLocalize::javascriptAssignedExpressionTypeMismatch + ); + } + + @Override + @RequiredReadAction + public void visitJSReturnStatement(@Nonnull JSReturnStatement node) { + JSExpression expression = node.getExpression(); + if (expression == null) { + return; + } + + JSFunction fun = PsiTreeUtil.getParentOfType(node, JSFunction.class); + if (fun == null) { + return; // TODO: complain about it + } + String typeString = fun.getReturnTypeString(); + if (typeString == null) { + return; + } + PsiFile containingFile = fun.getContainingFile(); + if (containingFile.getLanguage() != JavaScriptSupportLoader.ECMA_SCRIPT_L4) { + return; + } + + checkExpressionIsAssignableToType( + expression, + JSImportHandlingUtil.resolveTypeName(typeString, fun), + holder, + containingFile, + JavaScriptLocalize::javascriptReturnedExpressionTypeMismatch + ); + } + + @Override + @RequiredReadAction + public void visitJSVariable(@Nonnull JSVariable node) { + JSExpression initializer = node.getInitializer(); + if (initializer == null) { + return; + } + checkExpressionIsAssignableToVariable( + node, + initializer, + holder, + node.getContainingFile(), + JavaScriptLocalize::javascriptInitializerTypeMismatch + ); + } + + @Override + @RequiredReadAction + public void visitJSBinaryExpression(@Nonnull JSBinaryExpression node) { + IElementType sign = node.getOperationSign(); + + if (sign == JSTokenTypes.AS_KEYWORD || sign == JSTokenTypes.IS_KEYWORD) { + if (node.getROperand() instanceof JSReferenceExpression refExpr) { + ResolveResult[] results = refExpr.multiResolve(false); + + if (results.length > 0 && results[0].getElement() instanceof JSVariable) { + checkTypeIs(refExpr, refExpr, holder, "Class"); + } + } + } + } + + @Override + @RequiredReadAction + public void visitJSForInStatement(@Nonnull JSForInStatement node) { + if (!node.isForEach()) { + JSVarStatement statement = node.getDeclarationStatement(); + + if (statement != null) { + String expressionType = + JSResolveUtil.getQualifiedExpressionType(node.getCollectionExpression(), node.getContainingFile()); + boolean isDictionary = "flash.utils.Dictionary".equals(expressionType); + + for (JSVariable var : statement.getVariables()) { + PsiElement typeElement = var.getTypeElement(); + String typeElementText; + + if (typeElement != null + && "Array".equals(expressionType) + && ("Object".equals(typeElementText = typeElement.getText()) || "*".equals(typeElementText))) { + holder.newProblem(JavaScriptLocalize.javascriptIncorrectArrayTypeInForin()) + .range(typeElement) + .highlightType(ProblemHighlightType.GENERIC_ERROR_OR_WARNING) + .create(); + continue; + } + + if (isDictionary && typeElement != null && "Object".equals(typeElement.getText())) { + continue; + } + checkTypeIs(typeElement, typeElement, holder, "XMLList".equals(expressionType) ? "XML" : "String"); + } + } + } + } + }; + } + + private static boolean allowMemberReference(boolean inNewExpression, String typeText) { + return ("Class".equals(typeText) && inNewExpression) || "Function".equals(typeText); + } + + @RequiredReadAction + private static void checkTypeIs(PsiElement type, PsiElement node, ProblemsHolder holder, String typeName) { + if (type instanceof JSReferenceExpression refExpr) { + String expressionType = JSResolveUtil.getQualifiedExpressionType(refExpr, refExpr.getContainingFile()); + if (!typeName.equals(expressionType)) { + holder.newProblem(JavaScriptLocalize.javascriptIncorrectVariableTypeMismatch(typeName, expressionType)) + .range(node) + .highlightType(getHighlightTypeForTypeOrSignatureProblem(node)) + .create(); + } + } + else if (type != null) { + holder.newProblem(JavaScriptLocalize.javascriptIncorrectVariableTypeMismatch(typeName, type.getText())) + .range(node) + .highlightType(getHighlightTypeForTypeOrSignatureProblem(node)) + .create(); + } + } + + @RequiredReadAction + private static void checkTypeIs(JSExpression rOperand, PsiElement node, ProblemsHolder holder, String typeName) { + String expressionType = JSResolveUtil.getQualifiedExpressionType(rOperand, rOperand.getContainingFile()); + if (!typeName.equals(expressionType)) { + holder.registerProblem( + node, + JavaScriptLocalize.javascriptBinaryOperandTypeMismatch(typeName, expressionType).get(), + getHighlightTypeForTypeOrSignatureProblem(node) + ); + } + } + + @RequiredReadAction + static ProblemHighlightType getUnresolveReferenceHighlightType(@Nullable JSExpression qualifier, @Nonnull JSExpression node) { + JSClass jsClass; + + PsiFile containingFile = node.getContainingFile(); + if (qualifier != null) { + jsClass = JSResolveUtil.findClassOfQualifier(qualifier, containingFile); + + if (jsClass == null && qualifier instanceof JSReferenceExpression referenceExpression) { + ResolveResult[] results = referenceExpression.multiResolve(false); + + if (results.length != 0) { + PsiElement resultElement = results[0].getElement(); + String type = null; + + if (resultElement instanceof JSVariable variable) { + type = variable.getTypeString(); + } + else if (resultElement instanceof JSFunction function) { + type = function.getReturnTypeString(); + } + + if ("*".equals(type)) { + return ProblemHighlightType.LIKE_UNKNOWN_SYMBOL; + } + jsClass = JSResolveUtil.getClassOfContext(resultElement); + } + } + } + else { + jsClass = JSResolveUtil.getClassOfContext(node); + } + + boolean ecmaL4File = containingFile.getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4; + + if (jsClass != null && ecmaL4File + && (!(jsClass instanceof XmlBackedJSClassImpl) || jsClass.getContainingFile().getFileType() == XmlFileType.INSTANCE)) { + JSAttributeList attributeList = jsClass.getAttributeList(); + if (attributeList == null || !attributeList.hasModifier(JSAttributeList.ModifierType.DYNAMIC)) { + return ProblemHighlightType.ERROR; + } + } + + if (ecmaL4File && jsClass == null && node.getParent() instanceof JSReferenceList) { + return ProblemHighlightType.ERROR; + } + return ProblemHighlightType.LIKE_UNKNOWN_SYMBOL; + } + + @RequiredReadAction + private static void checkFunction(JSCallExpression node, PsiElement element, ProblemsHolder holder) { + if (element instanceof JSFunction function) { + if (!function.isGetProperty() || !"Function".equals(function.getReturnTypeString())) { + JSParameterList parameterList = function.getParameterList(); + + if (parameterList != null) { + checkCallParameters(node, parameterList.getParameters(), function.isReferencesArguments(), holder); + } + } + } + else if (element instanceof JSClass) { + if (node instanceof JSNewExpression || node.getMethodExpression() instanceof JSSuperExpression) { + checkCallParameters(node, JSParameter.EMPTY_ARRAY, false, holder); + } + else { + JSArgumentList argumentList = node.getArgumentList(); + if (argumentList == null || argumentList.getArguments().length != 1) { + holder.newProblem(JavaScriptLocalize.javascriptInvalidNumberOfParameters("one")) + .range(argumentList != null ? argumentList : node) + .highlightType(getHighlightTypeForTypeOrSignatureProblem(node)) + .create(); + } + } + } + } + + @RequiredReadAction + private static void checkCallParameters( + JSCallExpression node, + JSParameter[] parameters, + boolean functionReferencesArguments, + ProblemsHolder holder + ) { + JSArgumentList argumentList = node.getArgumentList(); + JSExpression[] expressions = argumentList != null ? argumentList.getArguments() : JSExpression.EMPTY_ARRAY; + + boolean lastIsRest = false; + int minParameterLength = 0; + int maxParameterLength = parameters.length; + + for (int i = 0; i < parameters.length; ++i) { + JSParameter parameter = parameters[i]; + if (parameter.isOptional()) { + break; + } + + if (i == parameters.length - 1 && parameter.isRest()) { + lastIsRest = true; + maxParameterLength = Integer.MAX_VALUE; + break; + } + minParameterLength++; + } + + if (!lastIsRest && parameters.length > 0 && parameters[parameters.length - 1].isRest()) { + lastIsRest = true; + maxParameterLength = Integer.MAX_VALUE; + } + + if ((expressions.length < minParameterLength || expressions.length > maxParameterLength) && !functionReferencesArguments) { + String s = (lastIsRest ? minParameterLength + " or more " : String.valueOf(minParameterLength) + + (minParameterLength != maxParameterLength ? ".." + maxParameterLength : "")); + holder.registerProblem( + argumentList != null ? argumentList : node, + JavaScriptLocalize.javascriptInvalidNumberOfParameters(s).get(), + getHighlightTypeForTypeOrSignatureProblem(node) + ); + } + else { + int i = 0; + PsiFile containingFile = node.getContainingFile(); + + for (JSParameter p : parameters) { + if (i == expressions.length) { + break; + } + if (p.isRest()) { + break; + } + checkExpressionIsAssignableToVariable( + p, + expressions[i], + holder, + containingFile, + JavaScriptLocalize::javascriptArgumentTypeMismatch + ); + ++i; + } + } + } + + @RequiredReadAction + private static void checkExpressionIsAssignableToVariable( + JSVariable p, + JSExpression expr, + ProblemsHolder holder, + PsiFile containingFile, + BiFunction messageGenerator + ) { + String parameterTypeResolved = JSImportHandlingUtil.resolveTypeName(p.getTypeString(), p); + checkExpressionIsAssignableToType( + expr, + parameterTypeResolved, + holder, + containingFile, + messageGenerator + ); + } + + @RequiredReadAction + private static void checkExpressionIsAssignableToType( + JSExpression expr, + String type, + ProblemsHolder holder, + PsiFile containingFile, + BiFunction messageGenerator + ) { + if ("*".equals(type) || type == null) { + return; // optimization + } + String expressionType = JSResolveUtil.getQualifiedExpressionType(expr, containingFile); + + if (!JSResolveUtil.isAssignableType(type, expressionType, containingFile)) { + holder.newProblem(messageGenerator.apply(type, expressionType)) + .range(expr) + .highlightType(getHighlightTypeForTypeOrSignatureProblem(expr)) + .withFix(new JSInsertCastFix(type)) + .create(); + } + } + + @RequiredReadAction + private static ProblemHighlightType getHighlightTypeForTypeOrSignatureProblem(@Nonnull PsiElement node) { + if (node.getContainingFile().getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4) { + return ProblemHighlightType.GENERIC_ERROR; + } + return ProblemHighlightType.GENERIC_ERROR_OR_WARNING; + } + + private static class JSInsertCastFix implements LocalQuickFix { + private final String type; + + public JSInsertCastFix(String type) { + this.type = type; + } + + @Override + @Nonnull + public LocalizeValue getName() { + return JavaScriptLocalize.javascriptInsertCastFix(); + } + + @Override + @RequiredUIAccess + public void applyFix(@Nonnull Project project, @Nonnull ProblemDescriptor descriptor) { + PsiElement element = descriptor.getPsiElement(); + Editor editor = BaseCreateFix.getEditor(project, element.getContainingFile()); + if (editor == null) { + return; + } + + String shortenedType = JSResolveUtil.getShortenedType(this.type, element); + TemplateManager templateManager = TemplateManager.getInstance(project); + Template template = templateManager.createTemplate("", "", shortenedType + "($SELECTION$)"); + template.setToReformat(true); + + int offset = element.getTextOffset(); + editor.getSelectionModel().setSelection(offset, offset + element.getTextLength()); + editor.getCaretModel().moveToOffset(offset); + templateManager.startTemplate(editor, element.getText(), template); + } + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSUnresolvedVariableInspection.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSUnresolvedVariableInspection.java index 978f1afc..56c6bedf 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSUnresolvedVariableInspection.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSUnresolvedVariableInspection.java @@ -13,13 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.lang.javascript.impl.inspections; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.JavaScriptSupportLoader; -import com.intellij.lang.javascript.impl.flex.AddImportECMAScriptClassOrFunctionAction; import com.intellij.lang.javascript.formatter.JSCodeStyleSettings; +import com.intellij.lang.javascript.impl.flex.AddImportECMAScriptClassOrFunctionAction; import com.intellij.lang.javascript.inspections.qucikFixes.BaseCreateFix; import com.intellij.lang.javascript.inspections.qucikFixes.CreateJSFunctionOrMethodFix; import com.intellij.lang.javascript.psi.*; @@ -29,6 +27,7 @@ import consulo.annotation.component.ExtensionImpl; import consulo.javascript.inspections.qucikFixes.CreateJSFunctionFixBase; import consulo.javascript.language.JavaScriptFeature; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.codeStyle.CodeStyleSettingsManager; import consulo.language.editor.inspection.LocalQuickFix; import consulo.language.editor.inspection.ProblemsHolder; @@ -37,10 +36,10 @@ import consulo.language.psi.PsiFile; import consulo.language.psi.ResolveResult; import consulo.language.psi.util.PsiTreeUtil; +import consulo.localize.LocalizeValue; import consulo.util.lang.StringUtil; -import org.jetbrains.annotations.NonNls; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; import java.util.LinkedList; import java.util.List; import java.util.Set; @@ -49,430 +48,389 @@ * @author Maxim.Mossienko */ @ExtensionImpl -public class JSUnresolvedVariableInspection extends JSInspection -{ - @NonNls - private static final String SHORT_NAME = "JSUnresolvedVariable"; - - @Override - @Nonnull - public String getGroupDisplayName() - { - return "General"; - } - - @Override - @Nonnull - public String getDisplayName() - { - return JavaScriptBundle.message("js.unresolved.variable.inspection.name"); - } - - @Override - @Nonnull - @NonNls - public String getShortName() - { - return SHORT_NAME; - } - - @Override - protected JSElementVisitor createVisitor(final ProblemsHolder holder) - { - return new JSElementVisitor() - { - @Override - public void visitJSReferenceExpression(final JSReferenceExpression node) - { - final PsiElement parentElement = node.getParent(); - - if(node.shouldCheckReferences() && !(parentElement instanceof JSCallExpression)) - { - final ResolveResult[] resolveResults = node.multiResolve(false); - boolean emptyResolve = resolveResults.length == 0; - boolean noCompleteResolve = true; - - for(ResolveResult r : resolveResults) - { - if(r.isValidResult()) - { - noCompleteResolve = false; - break; - } - } - - if(emptyResolve || noCompleteResolve) - { - final PsiElement nameIdentifier = node.getReferenceNameElement(); - - if(nameIdentifier != null) - { - final List fixes = new LinkedList(); - final JSExpression qualifier = node.getQualifier(); - - if(myOnTheFly) - { - final PsiFile containingFile = node.getContainingFile(); - final boolean ecma = containingFile.getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4; - - if((qualifier == null || - JSUtils.isLHSExpression(qualifier) || - qualifier instanceof JSThisExpression) && (!(parentElement instanceof JSDefinitionExpression) || ecma)) - { - final String referencedName = node.getReferencedName(); - boolean isField = qualifier != null; - JSClass contextClass = null; - - if(!isField && ecma) - { - contextClass = JSResolveUtil.getClassOfContext(node); - if(contextClass != null) - { - isField = true; - } - } - - if(!JSResolveUtil.isExprInTypeContext(node)) - { - if(node.getParent() instanceof JSArgumentList) - { - fixes.add(new CreateJSFunctionOrMethodFix(referencedName, !(qualifier == null || (qualifier instanceof - JSThisExpression && ecma))) - { - @Override - protected void addParameters(Template template, JSReferenceExpression referenceExpression, PsiFile file, Set features) - { - JSExpression method = ((JSCallExpression) referenceExpression.getParent().getParent()).getMethodExpression(); - if(method instanceof JSReferenceExpression && "bindSetter".equals(((JSReferenceExpression) method).getReferencedName())) - { - MyExpression expression = new MyExpression("value"); - template.addVariable("value", expression, expression, false); - if(ecma) - { - template.addTextSegment(":int"); - } - } - } - - @Override - protected void addReturnType(Template template, JSReferenceExpression referenceExpression, PsiFile file) - { - template.addTextSegment("void"); - } - }); - } - - boolean suggestCreateVar = true; - - JSClass targetClass = contextClass; - - if(qualifier instanceof JSReferenceExpression) - { - final JSClass clazz = JSResolveUtil.findClassOfQualifier(qualifier, containingFile); - if(clazz != null) - { - targetClass = clazz; - } - } - - if(targetClass != null) - { - suggestCreateVar = !targetClass.isInterface(); - } - - if(suggestCreateVar) - { - fixes.add(new CreateJSVariableIntentionAction(referencedName, isField, false)); - - if(ecma) - { - fixes.add(new CreateJSVariableIntentionAction(referencedName, isField, true)); - } - } - - if(ecma) - { - boolean getter = !(node.getParent() instanceof JSDefinitionExpression); - String invokedName = nameIdentifier.getText(); - fixes.add(new CreateJSPropertyAccessorIntentionAction(invokedName, getter)); - JSCallExpression expression = PsiTreeUtil.getParentOfType(node, JSCallExpression.class); - - if(expression != null) - { - final JSExpression methodExpression = expression.getMethodExpression(); - - if(methodExpression instanceof JSReferenceExpression) - { - final String methodName = ((JSReferenceExpression) methodExpression).getReferencedName(); - - if("addEventListener".equals(methodName) || "removeEventListener".equals(methodName)) - { - final JSArgumentList argumentList = expression.getArgumentList(); - final JSExpression[] params = argumentList != null ? argumentList.getArguments() : JSExpression.EMPTY_ARRAY; - - if(params.length >= 2 && params[0] instanceof JSReferenceExpression) - { - final JSExpression eventNameQualifier = ((JSReferenceExpression) params[0]).getQualifier(); - if(eventNameQualifier != null) - { - fixes.add(new CreateJSEventMethod(invokedName, eventNameQualifier)); - } - } - } - } - } - } - } - if(qualifier != null && !ecma) - { - fixes.add(new CreateJSNamespaceIntentionAction(referencedName)); - } - - if(ecma) - { - if(qualifier == null) - { - fixes.add(new AddImportECMAScriptClassOrFunctionAction(null, node)); - fixes.add(new CreateClassOrInterfaceAction(node, false)); - fixes.add(new CreateClassOrInterfaceAction(node, true)); - } - else - { - fixes.add(new AddImportECMAScriptClassOrFunctionAction(null, node)); - } - } - } - } - - final String key = node.getQualifier() == null ? JSResolveUtil.isExprInTypeContext(node) ? "javascript.unresolved.type.name.message" : - "javascript.unresolved.variable.or.type.name.message" : "javascript.unresolved.variable.name.message"; - - holder.registerProblem(nameIdentifier, JavaScriptBundle.message(key, node.getReferencedName()), - JSUnresolvedFunctionInspection.getUnresolveReferenceHighlightType(qualifier, node), - fixes.size() > 0 ? fixes.toArray(new LocalQuickFix[fixes.size()]) : null); - } - } - } - super.visitJSReferenceExpression(node); - } - }; - } - - private abstract static class BaseCreateJSVariableIntentionAction extends BaseCreateFix - { - protected final String myReferencedName; - - BaseCreateJSVariableIntentionAction(String referencedName) - { - myReferencedName = referencedName; - } - - @Override - @Nonnull - public String getFamilyName() - { - return JavaScriptBundle.message("javascript.create.variable.intention.family"); - } - } - - private static class CreateJSNamespaceIntentionAction extends BaseCreateJSVariableIntentionAction - { - CreateJSNamespaceIntentionAction(String referencedName) - { - super(referencedName); - } - - @Override - @Nonnull - public String getName() - { - return JavaScriptBundle.message("javascript.create.namespace.intention.name", myReferencedName); - } - - @RequiredReadAction - @Override - protected void buildTemplate(final Template template, final JSReferenceExpression referenceExpression, final Set features, boolean staticContext, - final PsiFile file, final PsiElement anchorParent) - { - template.addTextSegment("/** @namespace "); - template.addTextSegment(referenceExpression.getText() + " */"); - template.addEndVariable(); - } - } - - private static class CreateJSVariableIntentionAction extends BaseCreateJSVariableIntentionAction - { - @NonNls - private static final String VAR_STATEMENT_START = "var "; - @NonNls - private static final String CONSTANT_STATEMENT_START = "const "; - private boolean isField; - private boolean isConstant; - - CreateJSVariableIntentionAction(String referencedName, boolean isField, boolean isConstant) - { - super(referencedName); - this.isField = isField; - this.isConstant = isConstant; - } - - @Override - @Nonnull - public String getName() - { - return JavaScriptBundle.message(isField ? isConstant ? "javascript.create.constant.field.intention.name" : "javascript.create.property.intention.name" : - isConstant ? "javascript.create.constant.intention.name" : "javascript.create.variable.intention.name", myReferencedName); - } - - @RequiredReadAction - @Override - protected void buildTemplate(final Template template, final JSReferenceExpression referenceExpression, final Set features, boolean staticContext, - final PsiFile file, final PsiElement anchorParent) - { - boolean classFeature = features.contains(JavaScriptFeature.CLASS); - - final JSExpression qualifier = addAccessModifier(template, referenceExpression, classFeature, staticContext); - if(qualifier == null || classFeature) - { - template.addTextSegment(isConstant ? CONSTANT_STATEMENT_START : VAR_STATEMENT_START); - } - - template.addTextSegment(classFeature ? referenceExpression.getReferencedName() : referenceExpression.getText()); - template.addEndVariable(); - if(classFeature) - { - template.addTextSegment(":"); - } - else - { - template.addTextSegment(" = "); - } - - if(classFeature) - { - guessTypeAndAddTemplateVariable(template, referenceExpression, file); - if(isConstant) - { - template.addTextSegment(" = "); - addCompletionVar(template); - } - } - else - { - addCompletionVar(template); - } - addSemicolonSegment(template, file); - } - - } - - private static class CreateJSPropertyAccessorIntentionAction extends CreateJSFunctionFixBase - { - private final boolean myIsGetter; - - public CreateJSPropertyAccessorIntentionAction(String name, boolean getter) - { - super(name, getter ? "javascript.create.get.property.intention.name" : "javascript.create.set.property.intention.name"); - myIsGetter = getter; - } - - @Override - protected void writeFunctionAndName(Template template, String referencedName, Set features) - { - template.addTextSegment("function "); - template.addTextSegment(myIsGetter ? "get " : "set "); - template.addTextSegment(referencedName); - } - - @Override - protected void addParameters(Template template, JSReferenceExpression refExpr, PsiFile file, Set features) - { - if(!myIsGetter) - { - template.addTextSegment(refExpr.getReferencedName() + ":"); - guessTypeAndAddTemplateVariable(template, refExpr, file); - } - } - - @Override - protected void addReturnType(Template template, JSReferenceExpression referenceExpression, PsiFile file) - { - if(myIsGetter) - { - guessTypeAndAddTemplateVariable(template, referenceExpression, file); - } - else - { - template.addTextSegment("void"); - } - } - - @Override - protected void addBody(Template template, JSReferenceExpression refExpr, PsiFile file) - { - String varName = refExpr.getReferencedName(); - String paramName = varName; - JSCodeStyleSettings settings = CodeStyleSettingsManager.getInstance(file.getProject()).getCurrentSettings().getCustomSettings(JSCodeStyleSettings - .class); - varName = settings.FIELD_PREFIX + varName; - - if(varName.equals(paramName)) - { - varName = StringUtil.fixVariableNameDerivedFromPropertyName(varName); - } - - if(myIsGetter) - { - template.addTextSegment("return "); - - addVarName(template, varName); - template.addEndVariable(); - } - else - { - addVarName(template, varName); - template.addEndVariable(); - template.addTextSegment(" = " + paramName); - } - addSemicolonSegment(template, file); - } - - private static void addVarName(Template template, String varName) - { - MyExpression expression = new MyExpression(varName); - template.addVariable("name", expression, expression, true); - } - - } - - private static class CreateJSEventMethod extends CreateJSFunctionFixBase - { - private JSExpression myEventQualifier; - - public CreateJSEventMethod(String invokedName, JSExpression eventNameQualifier) - { - super(invokedName, "javascript.create.event.handler.intention.name"); - myEventQualifier = eventNameQualifier; - } - - - @Override - protected void addParameters(Template template, JSReferenceExpression refExpr, PsiFile file, Set features) - { - template.addTextSegment("event:"); - template.addTextSegment(myEventQualifier.getText()); - } - - @Override - protected void addReturnType(Template template, JSReferenceExpression referenceExpression, PsiFile psifile) - { - template.addTextSegment("void"); - } - - @Override - protected void addBody(Template template, JSReferenceExpression refExpr, PsiFile file) - { - template.addEndVariable(); - } - } +public class JSUnresolvedVariableInspection extends JSInspection { + private static final String SHORT_NAME = "JSUnresolvedVariable"; + + @Nonnull + @Override + public LocalizeValue getGroupDisplayName() { + return LocalizeValue.localizeTODO("General"); + } + + @Nonnull + @Override + public LocalizeValue getDisplayName() { + return JavaScriptLocalize.jsUnresolvedVariableInspectionName(); + } + + @Nonnull + @Override + public String getShortName() { + return SHORT_NAME; + } + + @Override + protected JSElementVisitor createVisitor(final ProblemsHolder holder) { + return new JSElementVisitor() { + @Override + @RequiredReadAction + public void visitJSReferenceExpression(@Nonnull JSReferenceExpression node) { + PsiElement parentElement = node.getParent(); + + if (node.shouldCheckReferences() && !(parentElement instanceof JSCallExpression)) { + ResolveResult[] resolveResults = node.multiResolve(false); + boolean emptyResolve = resolveResults.length == 0; + boolean noCompleteResolve = true; + + for (ResolveResult r : resolveResults) { + if (r.isValidResult()) { + noCompleteResolve = false; + break; + } + } + + if (emptyResolve || noCompleteResolve) { + PsiElement nameIdentifier = node.getReferenceNameElement(); + + if (nameIdentifier != null) { + List fixes = new LinkedList<>(); + JSExpression qualifier = node.getQualifier(); + + if (myOnTheFly) { + PsiFile containingFile = node.getContainingFile(); + boolean ecma = containingFile.getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4; + + if ((qualifier == null || JSUtils.isLHSExpression(qualifier) || qualifier instanceof JSThisExpression) + && (!(parentElement instanceof JSDefinitionExpression) || ecma)) { + String referencedName = node.getReferencedName(); + boolean isField = qualifier != null; + JSClass contextClass = null; + + if (!isField && ecma) { + contextClass = JSResolveUtil.getClassOfContext(node); + if (contextClass != null) { + isField = true; + } + } + + if (!JSResolveUtil.isExprInTypeContext(node)) { + if (node.getParent() instanceof JSArgumentList) { + fixes.add(new CreateJSFunctionOrMethodFix( + referencedName, + !(qualifier == null || (qualifier instanceof JSThisExpression && ecma)) + ) { + @Override + @RequiredReadAction + protected void addParameters( + Template template, + JSReferenceExpression referenceExpression, + PsiFile file, + Set features + ) { + JSCallExpression call = (JSCallExpression)referenceExpression.getParent().getParent(); + JSExpression method = call.getMethodExpression(); + if (method instanceof JSReferenceExpression methodRefExpr + && "bindSetter".equals(methodRefExpr.getReferencedName())) { + MyExpression expression = new MyExpression("value"); + template.addVariable("value", expression, expression, false); + if (ecma) { + template.addTextSegment(":int"); + } + } + } + + @Override + @RequiredReadAction + protected void addReturnType( + Template template, + JSReferenceExpression referenceExpression, + PsiFile file + ) { + template.addTextSegment("void"); + } + }); + } + + boolean suggestCreateVar = true; + + JSClass targetClass = contextClass; + + if (qualifier instanceof JSReferenceExpression qualifierRefExpr) { + JSClass clazz = JSResolveUtil.findClassOfQualifier(qualifierRefExpr, containingFile); + if (clazz != null) { + targetClass = clazz; + } + } + + if (targetClass != null) { + suggestCreateVar = !targetClass.isInterface(); + } + + if (suggestCreateVar) { + fixes.add(new CreateJSVariableIntentionAction(referencedName, isField, false)); + + if (ecma) { + fixes.add(new CreateJSVariableIntentionAction(referencedName, isField, true)); + } + } + + if (ecma) { + boolean getter = !(node.getParent() instanceof JSDefinitionExpression); + String invokedName = nameIdentifier.getText(); + fixes.add(new CreateJSPropertyAccessorIntentionAction(invokedName, getter)); + JSCallExpression expression = PsiTreeUtil.getParentOfType(node, JSCallExpression.class); + + if (expression != null) { + JSExpression methodExpression = expression.getMethodExpression(); + + if (methodExpression instanceof JSReferenceExpression methodRefExpr) { + String methodName = methodRefExpr.getReferencedName(); + + if ("addEventListener".equals(methodName) || "removeEventListener".equals(methodName)) { + JSArgumentList argumentList = expression.getArgumentList(); + JSExpression[] params = + argumentList != null ? argumentList.getArguments() : JSExpression.EMPTY_ARRAY; + + if (params.length >= 2 && params[0] instanceof JSReferenceExpression paramRefExpr) { + JSExpression eventNameQualifier = paramRefExpr.getQualifier(); + if (eventNameQualifier != null) { + fixes.add(new CreateJSEventMethod(invokedName, eventNameQualifier)); + } + } + } + } + } + } + } + if (qualifier != null && !ecma) { + fixes.add(new CreateJSNamespaceIntentionAction(referencedName)); + } + + if (ecma) { + if (qualifier == null) { + fixes.add(new AddImportECMAScriptClassOrFunctionAction(null, node)); + fixes.add(new CreateClassOrInterfaceAction(node, false)); + fixes.add(new CreateClassOrInterfaceAction(node, true)); + } + else { + fixes.add(new AddImportECMAScriptClassOrFunctionAction(null, node)); + } + } + } + } + + holder.newProblem( + node.getQualifier() == null + ? JSResolveUtil.isExprInTypeContext(node) + ? JavaScriptLocalize.javascriptUnresolvedTypeNameMessage(node.getReferencedName()) + : JavaScriptLocalize.javascriptUnresolvedVariableOrTypeNameMessage(node.getReferencedName()) + : JavaScriptLocalize.javascriptUnresolvedVariableNameMessage(node.getReferencedName()) + ) + .range(nameIdentifier) + .highlightType(JSUnresolvedFunctionInspection.getUnresolveReferenceHighlightType(qualifier, node)) + .withFixes(fixes.size() > 0 ? fixes.toArray(new LocalQuickFix[fixes.size()]) : null) + .create(); + } + } + } + super.visitJSReferenceExpression(node); + } + }; + } + + private abstract static class BaseCreateJSVariableIntentionAction extends BaseCreateFix { + protected final String myReferencedName; + + BaseCreateJSVariableIntentionAction(String referencedName) { + myReferencedName = referencedName; + } + } + + private static class CreateJSNamespaceIntentionAction extends BaseCreateJSVariableIntentionAction { + CreateJSNamespaceIntentionAction(String referencedName) { + super(referencedName); + } + + @Nonnull + @Override + public LocalizeValue getName() { + return JavaScriptLocalize.javascriptCreateNamespaceIntentionName(myReferencedName); + } + + @Override + @RequiredReadAction + protected void buildTemplate( + Template template, + JSReferenceExpression referenceExpression, + Set features, + boolean staticContext, + PsiFile file, + PsiElement anchorParent + ) { + template.addTextSegment("/** @namespace "); + template.addTextSegment(referenceExpression.getText() + " */"); + template.addEndVariable(); + } + } + + private static class CreateJSVariableIntentionAction extends BaseCreateJSVariableIntentionAction { + private static final String VAR_STATEMENT_START = "var "; + private static final String CONSTANT_STATEMENT_START = "const "; + private boolean isField; + private boolean isConstant; + + CreateJSVariableIntentionAction(String referencedName, boolean isField, boolean isConstant) { + super(referencedName); + this.isField = isField; + this.isConstant = isConstant; + } + + @Nonnull + @Override + public LocalizeValue getName() { + return isField + ? isConstant + ? JavaScriptLocalize.javascriptCreateConstantFieldIntentionName(myReferencedName) + : JavaScriptLocalize.javascriptCreatePropertyIntentionName(myReferencedName) + : isConstant + ? JavaScriptLocalize.javascriptCreateConstantIntentionName(myReferencedName) + : JavaScriptLocalize.javascriptCreateVariableIntentionName(myReferencedName); + } + + @Override + @RequiredReadAction + protected void buildTemplate( + Template template, + JSReferenceExpression referenceExpression, + Set features, + boolean staticContext, + PsiFile file, + PsiElement anchorParent + ) { + boolean classFeature = features.contains(JavaScriptFeature.CLASS); + + JSExpression qualifier = addAccessModifier(template, referenceExpression, classFeature, staticContext); + if (qualifier == null || classFeature) { + template.addTextSegment(isConstant ? CONSTANT_STATEMENT_START : VAR_STATEMENT_START); + } + + template.addTextSegment(classFeature ? referenceExpression.getReferencedName() : referenceExpression.getText()); + template.addEndVariable(); + template.addTextSegment(classFeature ? ":" : " = "); + + if (classFeature) { + guessTypeAndAddTemplateVariable(template, referenceExpression, file); + if (isConstant) { + template.addTextSegment(" = "); + addCompletionVar(template); + } + } + else { + addCompletionVar(template); + } + addSemicolonSegment(template, file); + } + + } + + private static class CreateJSPropertyAccessorIntentionAction extends CreateJSFunctionFixBase { + private final boolean myIsGetter; + + public CreateJSPropertyAccessorIntentionAction(String name, boolean getter) { + super( + getter + ? JavaScriptLocalize.javascriptCreateGetPropertyIntentionName(name) + : JavaScriptLocalize.javascriptCreateSetPropertyIntentionName(name) + ); + myIsGetter = getter; + } + + @Override + protected void writeFunctionAndName(Template template, String referencedName, Set features) { + template.addTextSegment("function "); + template.addTextSegment(myIsGetter ? "get " : "set "); + template.addTextSegment(referencedName); + } + + @Override + @RequiredReadAction + protected void addParameters(Template template, JSReferenceExpression refExpr, PsiFile file, Set features) { + if (!myIsGetter) { + template.addTextSegment(refExpr.getReferencedName() + ":"); + guessTypeAndAddTemplateVariable(template, refExpr, file); + } + } + + @Override + @RequiredReadAction + protected void addReturnType(Template template, JSReferenceExpression referenceExpression, PsiFile file) { + if (myIsGetter) { + guessTypeAndAddTemplateVariable(template, referenceExpression, file); + } + else { + template.addTextSegment("void"); + } + } + + @Override + protected void addBody(Template template, JSReferenceExpression refExpr, PsiFile file) { + String varName = refExpr.getReferencedName(); + String paramName = varName; + JSCodeStyleSettings settings = + CodeStyleSettingsManager.getInstance(file.getProject()).getCurrentSettings().getCustomSettings(JSCodeStyleSettings + .class); + varName = settings.FIELD_PREFIX + varName; + + if (varName.equals(paramName)) { + varName = StringUtil.fixVariableNameDerivedFromPropertyName(varName); + } + + if (myIsGetter) { + template.addTextSegment("return "); + + addVarName(template, varName); + template.addEndVariable(); + } + else { + addVarName(template, varName); + template.addEndVariable(); + template.addTextSegment(" = " + paramName); + } + addSemicolonSegment(template, file); + } + + private static void addVarName(Template template, String varName) { + MyExpression expression = new MyExpression(varName); + template.addVariable("name", expression, expression, true); + } + + } + + private static class CreateJSEventMethod extends CreateJSFunctionFixBase { + private JSExpression myEventQualifier; + + public CreateJSEventMethod(String invokedName, JSExpression eventNameQualifier) { + super(JavaScriptLocalize.javascriptCreateEventHandlerIntentionName(invokedName)); + myEventQualifier = eventNameQualifier; + } + + + @Override + @RequiredReadAction + protected void addParameters(Template template, JSReferenceExpression refExpr, PsiFile file, Set features) { + template.addTextSegment("event:"); + template.addTextSegment(myEventQualifier.getText()); + } + + @Override + @RequiredReadAction + protected void addReturnType(Template template, JSReferenceExpression referenceExpression, PsiFile psifile) { + template.addTextSegment("void"); + } + + @Override + protected void addBody(Template template, JSReferenceExpression refExpr, PsiFile file) { + template.addEndVariable(); + } + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSUntypedDeclarationInspection.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSUntypedDeclarationInspection.java index 880e2acf..1ce5743a 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSUntypedDeclarationInspection.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSUntypedDeclarationInspection.java @@ -16,21 +16,23 @@ package com.intellij.lang.javascript.impl.inspections; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.JavaScriptSupportLoader; import com.intellij.lang.javascript.inspections.qucikFixes.BaseCreateFix; import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.impl.JSPsiImplUtils; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; -import consulo.application.ApplicationManager; +import consulo.application.Application; import consulo.codeEditor.Editor; import consulo.fileEditor.FileEditorManager; import consulo.javascript.language.JavaScriptFeature; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.editor.FileModificationService; import consulo.language.editor.inspection.LocalQuickFix; import consulo.language.editor.inspection.ProblemDescriptor; import consulo.language.editor.inspection.ProblemHighlightType; import consulo.language.editor.inspection.ProblemsHolder; +import consulo.language.editor.inspection.localize.InspectionLocalize; import consulo.language.editor.rawHighlight.HighlightDisplayLevel; import consulo.language.editor.template.Template; import consulo.language.editor.template.TemplateManager; @@ -38,165 +40,157 @@ import consulo.language.editor.template.macro.MacroFactory; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiFile; +import consulo.localize.LocalizeValue; import consulo.navigation.OpenFileDescriptor; import consulo.navigation.OpenFileDescriptorFactory; import consulo.project.Project; -import org.jetbrains.annotations.NonNls; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; import java.util.Collections; /** * @author Maxim.Mossienko */ @ExtensionImpl -public class JSUntypedDeclarationInspection extends JSInspection -{ - @NonNls - public static final String SHORT_NAME = "JSUntypedDeclaration"; - - @Override - @Nonnull - public String getGroupDisplayName() - { - return "General"; - } - - @Override - @Nonnull - public String getDisplayName() - { - return JavaScriptBundle.message("js.untyped.declaration.inspection.name"); - } - - @Nonnull - @Override - public HighlightDisplayLevel getDefaultLevel() - { - return HighlightDisplayLevel.WARNING; - } - - @Override - @Nonnull - @NonNls - public String getShortName() - { - return SHORT_NAME; - } - - @Override - protected JSElementVisitor createVisitor(final ProblemsHolder holder) - { - return new JSElementVisitor() - { - @Override - public void visitJSVariable(final JSVariable node) - { - process(node, holder); - } - - @Override - public void visitJSFunctionExpression(final JSFunctionExpression node) - { - process(node.getFunction(), holder); - } - - @Override - public void visitJSFunctionDeclaration(final JSFunction node) - { - if(node.isConstructor() || node.isSetProperty()) - { - return; - } - process(node, holder); - } - }; - } - - private static void process(final JSNamedElement node, final ProblemsHolder holder) - { - if(node.getContainingFile().getLanguage() != JavaScriptSupportLoader.ECMA_SCRIPT_L4) - { - return; - } - PsiElement nameIdentifier = node.getNameIdentifier(); - - if(nameIdentifier != null && - JSPsiImplUtils.getTypeFromDeclaration(node) == null && - (!(node instanceof JSParameter) || !((JSParameter) node).isRest())) - { - holder.registerProblem(nameIdentifier, JavaScriptBundle.message(node instanceof JSFunction ? "js.untyped.function.problem" : "js.untyped" + - ".variable.problem", nameIdentifier.getText()), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new AddTypeToDclFix()); - } - } - - private static class AddTypeToDclFix implements LocalQuickFix - { - - @Override - @Nonnull - public String getName() - { - return JavaScriptBundle.message("js.untyped.declaration.problem.addtype.fix"); - } - - @Override - @Nonnull - public String getFamilyName() - { - return getName(); - } - - @Override - public void applyFix(@Nonnull final Project project, @Nonnull final ProblemDescriptor descriptor) - { - PsiElement anchor = descriptor.getPsiElement(); - PsiFile containingFile = anchor.getContainingFile(); - if(!FileModificationService.getInstance().prepareFileForWrite(containingFile)) - { - return; - } - - if(anchor.getParent() instanceof JSFunction) - { - anchor = ((JSFunction) anchor.getParent()).getParameterList(); - } - - OpenFileDescriptor openDescriptor = OpenFileDescriptorFactory.getInstance(project).builder(containingFile.getVirtualFile()).offset(anchor.getTextRange().getEndOffset()).build(); - openDescriptor.navigate(true); - Editor textEditor = FileEditorManager.getInstance(project).getSelectedTextEditor(); - TemplateManager templateManager = TemplateManager.getInstance(project); - - Template t = templateManager.createTemplate("", ""); - t.addTextSegment(":"); - boolean hasDetectedTypeFromUsage = false; - final PsiElement anchorParent = anchor.getParent(); - - if(anchorParent instanceof JSVariable) - { - final JSExpression expression = ((JSVariable) anchorParent).getInitializer(); - - if(expression != null) - { - BaseCreateFix.guessExprTypeAndAddSuchVariable(expression, t, "a", containingFile, Collections.singleton(JavaScriptFeature.CLASS)); - hasDetectedTypeFromUsage = true; - } - } - - if(!hasDetectedTypeFromUsage) - { - String defaultValue = "uint"; - if(ApplicationManager.getApplication().isUnitTestMode()) - { - t.addTextSegment(defaultValue); - } - else - { - t.addVariable("a", new MacroCallNode(MacroFactory.createMacro("complete")), new BaseCreateFix.MyExpression(defaultValue), true); - } - } - - templateManager.startTemplate(textEditor, t); - } - } +public class JSUntypedDeclarationInspection extends JSInspection { + public static final String SHORT_NAME = "JSUntypedDeclaration"; + + @Nonnull + @Override + public LocalizeValue getGroupDisplayName() { + return InspectionLocalize.inspectionGeneralToolsGroupName(); + } + + @Nonnull + @Override + public LocalizeValue getDisplayName() { + return JavaScriptLocalize.jsUntypedDeclarationInspectionName(); + } + + @Nonnull + @Override + public HighlightDisplayLevel getDefaultLevel() { + return HighlightDisplayLevel.WARNING; + } + + @Override + @Nonnull + public String getShortName() { + return SHORT_NAME; + } + + @Override + protected JSElementVisitor createVisitor(final ProblemsHolder holder) { + return new JSElementVisitor() { + @Override + @RequiredReadAction + public void visitJSVariable(@Nonnull JSVariable node) { + process(node, holder); + } + + @Override + @RequiredReadAction + public void visitJSFunctionExpression(@Nonnull JSFunctionExpression node) { + process(node.getFunction(), holder); + } + + @Override + @RequiredReadAction + public void visitJSFunctionDeclaration(@Nonnull JSFunction node) { + if (node.isConstructor() || node.isSetProperty()) { + return; + } + process(node, holder); + } + }; + } + + @RequiredReadAction + private static void process(JSNamedElement node, ProblemsHolder holder) { + if (node.getContainingFile().getLanguage() != JavaScriptSupportLoader.ECMA_SCRIPT_L4) { + return; + } + PsiElement nameIdentifier = node.getNameIdentifier(); + + if (nameIdentifier != null + && JSPsiImplUtils.getTypeFromDeclaration(node) == null + && !(node instanceof JSParameter parameter && parameter.isRest())) { + LocalizeValue description = node instanceof JSFunction + ? JavaScriptLocalize.jsUntypedFunctionProblem(nameIdentifier.getText()) + : JavaScriptLocalize.jsUntypedVariableProblem(nameIdentifier.getText()); + + holder.newProblem(description) + .range(nameIdentifier) + .highlightType(ProblemHighlightType.GENERIC_ERROR_OR_WARNING) + .withFix(new AddTypeToDclFix()) + .create(); + } + } + + private static class AddTypeToDclFix implements LocalQuickFix { + @Nonnull + @Override + public LocalizeValue getName() { + return JavaScriptLocalize.jsUntypedDeclarationProblemAddtypeFix(); + } + + @Override + @RequiredReadAction + public void applyFix(@Nonnull Project project, @Nonnull ProblemDescriptor descriptor) { + PsiElement anchor = descriptor.getPsiElement(); + PsiFile containingFile = anchor.getContainingFile(); + if (!FileModificationService.getInstance().prepareFileForWrite(containingFile)) { + return; + } + + if (anchor.getParent() instanceof JSFunction function) { + anchor = function.getParameterList(); + } + + OpenFileDescriptor openDescriptor = OpenFileDescriptorFactory.getInstance(project) + .builder(containingFile.getVirtualFile()) + .offset(anchor.getTextRange().getEndOffset()) + .build(); + openDescriptor.navigate(true); + Editor textEditor = FileEditorManager.getInstance(project).getSelectedTextEditor(); + TemplateManager templateManager = TemplateManager.getInstance(project); + + Template t = templateManager.createTemplate("", ""); + t.addTextSegment(":"); + boolean hasDetectedTypeFromUsage = false; + PsiElement anchorParent = anchor.getParent(); + + if (anchorParent instanceof JSVariable variable) { + JSExpression expression = variable.getInitializer(); + + if (expression != null) { + BaseCreateFix.guessExprTypeAndAddSuchVariable( + expression, + t, + "a", + containingFile, + Collections.singleton(JavaScriptFeature.CLASS) + ); + hasDetectedTypeFromUsage = true; + } + } + + if (!hasDetectedTypeFromUsage) { + String defaultValue = "uint"; + if (Application.get().isUnitTestMode()) { + t.addTextSegment(defaultValue); + } + else { + t.addVariable( + "a", + new MacroCallNode(MacroFactory.createMacro("complete")), + new BaseCreateFix.MyExpression(defaultValue), + true + ); + } + } + + templateManager.startTemplate(textEditor, t); + } + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSUnusedLocalSymbolsInspection.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSUnusedLocalSymbolsInspection.java index 12491d71..d0a2bcc9 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSUnusedLocalSymbolsInspection.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/inspections/JSUnusedLocalSymbolsInspection.java @@ -16,35 +16,34 @@ package com.intellij.lang.javascript.impl.inspections; -import consulo.annotation.component.ExtensionImpl; -import consulo.language.editor.inspection.ProblemDescriptor; -import consulo.language.editor.inspection.ProblemHighlightType; -import consulo.language.editor.inspection.ProblemsHolder; -import consulo.language.editor.rawHighlight.HighlightDisplayLevel; -import consulo.language.editor.inspection.LocalQuickFix; import com.intellij.lang.javascript.JSElementTypes; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.JavaScriptSupportLoader; import com.intellij.lang.javascript.impl.highlighting.JavaScriptLineMarkerProvider; import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.impl.JSClassImpl; import com.intellij.lang.javascript.psi.resolve.JSImportHandlingUtil; import com.intellij.lang.javascript.psi.resolve.ResolveProcessor; -import consulo.logging.Logger; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; +import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.localize.JavaScriptLocalize; +import consulo.language.editor.inspection.*; +import consulo.language.editor.inspection.localize.InspectionLocalize; +import consulo.language.editor.rawHighlight.HighlightDisplayLevel; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiFile; import consulo.language.psi.ResolveResult; import consulo.language.psi.resolve.ResolveState; import consulo.language.psi.util.PsiTreeUtil; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import consulo.logging.Logger; import consulo.project.Project; import consulo.util.collection.primitive.objects.ObjectIntMap; import consulo.util.collection.primitive.objects.ObjectMaps; import consulo.util.dataholder.Key; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.PropertyKey; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; import java.util.BitSet; import java.util.Collections; import java.util.HashSet; @@ -54,420 +53,338 @@ * @author Maxim.Mossienko */ @ExtensionImpl -public class JSUnusedLocalSymbolsInspection extends JSInspection -{ - private static final Logger LOG = Logger.getInstance("JSUnusedLocalSymbols"); - @NonNls - public static final String SHORT_NAME = "JSUnusedLocalSymbols"; - - @Override - @Nonnull - public String getGroupDisplayName() - { - return "General"; - } - - @Override - @Nonnull - public String getDisplayName() - { - return JavaScriptBundle.message("js.unused.local.symbol.inspection.name"); - } - - @Override - @Nonnull - @NonNls - public String getShortName() - { - return SHORT_NAME; - } - - private static final Key> ourUnusedLocalDeclarationsSetKey = Key.create("js unused local dcls key"); - private static final Key> ourUsedLocalDeclarationsSetKey = Key.create("js used local functions key"); - - @Override - protected JSElementVisitor createVisitor(final ProblemsHolder holder) - { - return new JSElementVisitor() - { - @Override - public void visitJSVariable(final JSVariable node) - { - handleLocalDeclaration(node); - } - - @Override - public void visitJSParameterList(final JSParameterList node) - { - PsiElement parent = node.getParent(); - final Set set = parent.getUserData(ourUnusedLocalDeclarationsSetKey); - - if(set == null) - { - parent.putUserData(ourUnusedLocalDeclarationsSetKey, Collections.synchronizedSet(new HashSet(3))); - } - else if(node.getParameters().length == 0) - { - set.clear(); - } - } - - @Override - public void visitFile(final PsiFile file) - { - final Set set = file.getUserData(ourUnusedLocalDeclarationsSetKey); - if(set != null) - { - set.clear(); - } - } - - @Override - public void visitJSParameter(final JSParameter node) - { - final PsiElement scopeNode = PsiTreeUtil.getParentOfType(node, JSFunction.class, JSCatchBlock.class); - - if(scopeNode == null || scopeNode instanceof JSCatchBlock) - { - return; - } - // TODO: calculate more accurately right here (we depend in this place for slow marker pass to finish before) - if(scopeNode.getUserData(JavaScriptLineMarkerProvider.ourParticipatesInHierarchyKey) != null) - { - return; - } - if(scopeNode instanceof JSFunction) - { - JSAttributeList attributeList = ((JSFunction) scopeNode).getAttributeList(); - if(attributeList != null && attributeList.hasModifier(JSAttributeList.ModifierType.OVERRIDE)) - { - return; - } - } - - final Set unusedParametersSet; - final PsiElement parameterList = node.getParent(); - - if(parameterList.getNode().findChildByType(JSElementTypes.FORMAL_PARAMETER) == node.getNode()) - { - unusedParametersSet = Collections.synchronizedSet(new HashSet(3)); - scopeNode.putUserData(ourUnusedLocalDeclarationsSetKey, unusedParametersSet); - } - else - { - unusedParametersSet = scopeNode.getUserData(ourUnusedLocalDeclarationsSetKey); - if(unusedParametersSet == null) - { - return; - } - } - unusedParametersSet.add(node); - } - - @Override - public void visitJSReferenceExpression(final JSReferenceExpression node) - { - if(node.getParent() instanceof JSFunction) - { - return; - } - if(node.getQualifier() == null) - { - if("arguments".equals(node.getText())) - { - JSFunction function = PsiTreeUtil.getParentOfType(node, JSFunction.class); - if(function == null) - { - return; - } - Set unusedParametersSet = function.getUserData(ourUnusedLocalDeclarationsSetKey); - if(unusedParametersSet == null) - { - return; - } - for(JSParameter p : function.getParameterList().getParameters()) - { - unusedParametersSet.remove(p); - } - return; - } - - ResolveResult[] results = node.multiResolve(false); - - for(ResolveResult r : results) - { - final PsiElement element = r.getElement(); - - if(element instanceof JSVariable || (element instanceof JSFunction && isSupportedFunction((JSFunction) element))) - { - assert !(element instanceof JSFunctionExpression); - PsiElement scopeHandler = PsiTreeUtil.getParentOfType(element, JSFunction.class); - - if(scopeHandler != null) - { - Set unusedParametersSet = scopeHandler.getUserData(ourUnusedLocalDeclarationsSetKey); - - if(unusedParametersSet != null) - { - final boolean removed = unusedParametersSet.remove(element); - - if(!removed) - { - Set set = scopeHandler.getUserData(ourUsedLocalDeclarationsSetKey); - if(set == null) - { - set = new HashSet(3); - scopeHandler.putUserData(ourUsedLocalDeclarationsSetKey, set); - } - set.add(element); - } - } - } - } - } - } - } - - @Override - public void visitJSFunctionExpression(final JSFunctionExpression node) - { - visitJSFunctionDeclaration((JSFunction) node); - } - - @Override - public void visitJSFunctionDeclaration(final JSFunction node) - { - processDeclarationHost(node, holder); - handleLocalDeclaration(node); - } - }; - } - - private static boolean isSupportedFunction(final JSFunction element) - { - return !(element instanceof JSFunctionExpression || element.getParent() instanceof JSProperty); - } - - private static void processDeclarationHost(final PsiElement node, final ProblemsHolder holder) - { - Set unusedDeclarationsSet = node.getUserData(ourUnusedLocalDeclarationsSetKey); - if(unusedDeclarationsSet == null || node instanceof JSFunction && ((JSFunction) node).getBody().length == 0) - { - return; - } - - try - { - unusedDeclarationsSet = new HashSet(unusedDeclarationsSet); - - final int nonCounted = -2; - int lastUsedParameterIndex = nonCounted; - ObjectIntMap parameterIndexMap = null; - - for(final PsiElement p : unusedDeclarationsSet) - { - if(!p.isValid()) - { - continue; - } - final @NonNls @PropertyKey(resourceBundle = JavaScriptBundle.BUNDLE) String messageId; - final @Nonnull PsiElement highlightedElement; - - if(p instanceof JSParameter) - { - // There are cases of predefined sinatures for which we are not interested in reported unused parameters - final boolean ecma = node.getContainingFile().getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4; - if(ecma && node instanceof JSFunctionExpression) - { - continue; // do not report unused parameters - } - else if(ecma && node instanceof JSFunction) - { - final JSParameter[] params = ((JSFunction) node).getParameterList().getParameters(); - - if(params.length == 1) - { - @NonNls String type = ((JSParameter) p).getTypeString(); - if(type != null) - { - type = JSImportHandlingUtil.resolveTypeName(type, p); - } - - if(type != null) - { - String eventType = "flash.events.Event"; - if(eventType.equals(type)) - { - continue; - } - final PsiElement clazz = JSClassImpl.findClassFromNamespace(type, node); - - if(clazz instanceof JSClass) - { - final ResolveProcessor processor = new ResolveProcessor(eventType) - { - { - setTypeContext(true); - setToProcessMembers(false); - setToProcessHierarchy(true); - } - - @Override - public boolean execute(final PsiElement element, final ResolveState state) - { - if(!(element instanceof JSClass)) - { - return true; - } - return !myName.equals(((JSClass) element).getQualifiedName()); - } - }; - processor.setLocalResolve(true); - final boolean b = clazz.processDeclarations(processor, ResolveState.initial(), clazz, clazz); - if(!b) - { - continue; - } - } - } - } - } - - final JSParameter[] params = ((JSFunction) node).getParameterList().getParameters(); - - if(lastUsedParameterIndex == nonCounted) - { - BitSet unusedSet = new BitSet(params.length); - parameterIndexMap = ObjectMaps.newObjectIntHashMap(); - for(int i = 0; i < params.length; ++i) - { - parameterIndexMap.putInt(params[i], i); - } - - for(PsiElement param : unusedDeclarationsSet) - { - if(!(param instanceof JSParameter)) - { - continue; - } - unusedSet.set(parameterIndexMap.getInt((JSParameter) param)); - } - - lastUsedParameterIndex = -1; - - for(int i = params.length - 1; i >= 0; --i) - { - if(!unusedSet.get(i)) - { - lastUsedParameterIndex = i; - break; - } - } - } - - if(parameterIndexMap.getInt((JSParameter) p) < lastUsedParameterIndex) - { - continue; // no sense to report unused symbol before used since it will change signature - } - - messageId = "js.unused.parameter"; - highlightedElement = ((JSParameter) p).getNameIdentifier(); - } - else if(p instanceof JSFunction) - { - final PsiElement nameIdentifier = ((JSFunction) p).getNameIdentifier(); - if(nameIdentifier == null) - { - continue; - } - highlightedElement = nameIdentifier; - messageId = "js.unused.function.declaration"; - } - else - { - highlightedElement = ((JSVariable) p).getNameIdentifier(); - messageId = "js.unused.local.variable"; - } - - if(p.getParent() instanceof JSCatchBlock) - { - holder.registerProblem(highlightedElement, JavaScriptBundle.message(messageId), ProblemHighlightType.LIKE_UNUSED_SYMBOL); - } - else - { - holder.registerProblem(highlightedElement, JavaScriptBundle.message(messageId), ProblemHighlightType.LIKE_UNUSED_SYMBOL, new RemoveElementLocalQuickFix()); - } - } - } - finally - { - node.putUserData(ourUnusedLocalDeclarationsSetKey, null); - } - } - - private static void handleLocalDeclaration(final JSNamedElement node) - { - if(node instanceof JSFunction && !isSupportedFunction((JSFunction) node)) - { - return; - } - final PsiElement scopeNode = PsiTreeUtil.getParentOfType(node, JSFunction.class, JSCatchBlock.class); - if(scopeNode == null) - { - return; - } - final Set unusedParametersSet = scopeNode.getUserData(ourUnusedLocalDeclarationsSetKey); - final Set usedSet = scopeNode.getUserData(ourUsedLocalDeclarationsSetKey); - if(usedSet != null && usedSet.contains(node)) - { - return; - } - if(unusedParametersSet == null) - { - return; - } - unusedParametersSet.add(node); - } - - @Override - @Nonnull - public HighlightDisplayLevel getDefaultLevel() - { - return HighlightDisplayLevel.WARNING; - } - - private static class RemoveElementLocalQuickFix implements LocalQuickFix - { - @Override - @Nonnull - public String getName() - { - return JavaScriptBundle.message("js.unused.symbol.remove"); - } - - @Override - @Nonnull - public String getFamilyName() - { - return getName(); - } - - @Override - public void applyFix(@Nonnull final Project project, @Nonnull final ProblemDescriptor descriptor) - { - try - { - PsiElement element = descriptor.getPsiElement(); - if(!(element instanceof JSNamedElement)) - { - element = element.getParent(); - } - element.delete(); - } - catch(IncorrectOperationException e) - { - LOG.error(e); - } - } - } +public class JSUnusedLocalSymbolsInspection extends JSInspection { + private static final Logger LOG = Logger.getInstance("JSUnusedLocalSymbols"); + public static final String SHORT_NAME = "JSUnusedLocalSymbols"; + + @Nonnull + @Override + public LocalizeValue getGroupDisplayName() { + return InspectionLocalize.inspectionGeneralToolsGroupName(); + } + + @Nonnull + @Override + public LocalizeValue getDisplayName() { + return JavaScriptLocalize.jsUnusedLocalSymbolInspectionName(); + } + + @Nonnull + @Override + public String getShortName() { + return SHORT_NAME; + } + + private static final Key> UNUSED_LOCAL_DECLARATIONS_SET_KEY = Key.create("js unused local dcls key"); + private static final Key> USED_LOCAL_DECLARATIONS_SET_KEY = Key.create("js used local functions key"); + + @Override + protected JSElementVisitor createVisitor(final ProblemsHolder holder) { + return new JSElementVisitor() { + @Override + public void visitJSVariable(@Nonnull JSVariable node) { + handleLocalDeclaration(node); + } + + @Override + public void visitJSParameterList(@Nonnull JSParameterList node) { + PsiElement parent = node.getParent(); + Set set = parent.getUserData(UNUSED_LOCAL_DECLARATIONS_SET_KEY); + + if (set == null) { + parent.putUserData(UNUSED_LOCAL_DECLARATIONS_SET_KEY, Collections.synchronizedSet(new HashSet<>(3))); + } + else if (node.getParameters().length == 0) { + set.clear(); + } + } + + @Override + public void visitFile(PsiFile file) { + Set set = file.getUserData(UNUSED_LOCAL_DECLARATIONS_SET_KEY); + if (set != null) { + set.clear(); + } + } + + @Override + @RequiredReadAction + public void visitJSParameter(@Nonnull JSParameter node) { + PsiElement scopeNode = PsiTreeUtil.getParentOfType(node, JSFunction.class, JSCatchBlock.class); + + if (scopeNode == null || scopeNode instanceof JSCatchBlock) { + return; + } + // TODO: calculate more accurately right here (we depend in this place for slow marker pass to finish before) + if (scopeNode.getUserData(JavaScriptLineMarkerProvider.ourParticipatesInHierarchyKey) != null) { + return; + } + + if (scopeNode instanceof JSFunction function) { + JSAttributeList attributeList = function.getAttributeList(); + if (attributeList != null && attributeList.hasModifier(JSAttributeList.ModifierType.OVERRIDE)) { + return; + } + } + + Set unusedParametersSet; + PsiElement parameterList = node.getParent(); + + if (parameterList.getNode().findChildByType(JSElementTypes.FORMAL_PARAMETER) == node.getNode()) { + unusedParametersSet = Collections.synchronizedSet(new HashSet(3)); + scopeNode.putUserData(UNUSED_LOCAL_DECLARATIONS_SET_KEY, unusedParametersSet); + } + else { + unusedParametersSet = scopeNode.getUserData(UNUSED_LOCAL_DECLARATIONS_SET_KEY); + if (unusedParametersSet == null) { + return; + } + } + unusedParametersSet.add(node); + } + + @Override + @RequiredReadAction + public void visitJSReferenceExpression(@Nonnull JSReferenceExpression node) { + if (node.getParent() instanceof JSFunction) { + return; + } + if (node.getQualifier() == null) { + if ("arguments".equals(node.getText())) { + JSFunction function = PsiTreeUtil.getParentOfType(node, JSFunction.class); + if (function == null) { + return; + } + Set unusedParametersSet = function.getUserData(UNUSED_LOCAL_DECLARATIONS_SET_KEY); + if (unusedParametersSet == null) { + return; + } + for (JSParameter p : function.getParameterList().getParameters()) { + unusedParametersSet.remove(p); + } + return; + } + + ResolveResult[] results = node.multiResolve(false); + + for (ResolveResult r : results) { + PsiElement element = r.getElement(); + + if (element instanceof JSVariable || (element instanceof JSFunction function && isSupportedFunction(function))) { + assert !(element instanceof JSFunctionExpression); + PsiElement scopeHandler = PsiTreeUtil.getParentOfType(element, JSFunction.class); + + if (scopeHandler != null) { + Set unusedParametersSet = scopeHandler.getUserData(UNUSED_LOCAL_DECLARATIONS_SET_KEY); + + if (unusedParametersSet != null) { + boolean removed = unusedParametersSet.remove(element); + + if (!removed) { + Set set = scopeHandler.getUserData(USED_LOCAL_DECLARATIONS_SET_KEY); + if (set == null) { + set = new HashSet<>(3); + scopeHandler.putUserData(USED_LOCAL_DECLARATIONS_SET_KEY, set); + } + set.add(element); + } + } + } + } + } + } + } + + @Override + @RequiredReadAction + public void visitJSFunctionExpression(@Nonnull JSFunctionExpression node) { + visitJSFunctionDeclaration(node); + } + + @Override + @RequiredReadAction + public void visitJSFunctionDeclaration(@Nonnull JSFunction node) { + processDeclarationHost(node, holder); + handleLocalDeclaration(node); + } + }; + } + + private static boolean isSupportedFunction(JSFunction element) { + return !(element instanceof JSFunctionExpression || element.getParent() instanceof JSProperty); + } + + @RequiredReadAction + private static void processDeclarationHost(PsiElement node, ProblemsHolder holder) { + Set unusedDeclarationsSet = node.getUserData(UNUSED_LOCAL_DECLARATIONS_SET_KEY); + if (unusedDeclarationsSet == null || node instanceof JSFunction function && function.getBody().length == 0) { + return; + } + + try { + unusedDeclarationsSet = new HashSet<>(unusedDeclarationsSet); + + int nonCounted = -2; + int lastUsedParameterIndex = nonCounted; + ObjectIntMap parameterIndexMap = null; + + for (PsiElement p : unusedDeclarationsSet) { + if (!p.isValid()) { + continue; + } + LocalizeValue message; + @Nonnull PsiElement highlightedElement; + + if (p instanceof JSParameter parameter) { + // There are cases of predefined sinatures for which we are not interested in reported unused parameters + boolean ecma = node.getContainingFile().getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4; + if (ecma && node instanceof JSFunctionExpression) { + continue; // do not report unused parameters + } + else if (ecma && node instanceof JSFunction function) { + JSParameter[] params = function.getParameterList().getParameters(); + + if (params.length == 1) { + String type = parameter.getTypeString(); + if (type != null) { + type = JSImportHandlingUtil.resolveTypeName(type, p); + } + + if (type != null) { + String eventType = "flash.events.Event"; + if (eventType.equals(type)) { + continue; + } + + if (JSClassImpl.findClassFromNamespace(type, node) instanceof JSClass jsClass) { + ResolveProcessor processor = new ResolveProcessor(eventType) { + { + setTypeContext(true); + setToProcessMembers(false); + setToProcessHierarchy(true); + } + + @Override + @RequiredReadAction + public boolean execute(@Nonnull PsiElement element, ResolveState state) { + return !(element instanceof JSClass jsClass && myName.equals(jsClass.getQualifiedName())); + } + }; + processor.setLocalResolve(true); + boolean b = jsClass.processDeclarations(processor, ResolveState.initial(), jsClass, jsClass); + if (!b) { + continue; + } + } + } + } + } + + JSParameter[] params = ((JSFunction)node).getParameterList().getParameters(); + + if (lastUsedParameterIndex == nonCounted) { + BitSet unusedSet = new BitSet(params.length); + parameterIndexMap = ObjectMaps.newObjectIntHashMap(); + for (int i = 0; i < params.length; ++i) { + parameterIndexMap.putInt(params[i], i); + } + + for (PsiElement param : unusedDeclarationsSet) { + if (!(param instanceof JSParameter)) { + continue; + } + unusedSet.set(parameterIndexMap.getInt((JSParameter)param)); + } + + lastUsedParameterIndex = -1; + + for (int i = params.length - 1; i >= 0; --i) { + if (!unusedSet.get(i)) { + lastUsedParameterIndex = i; + break; + } + } + } + + if (parameterIndexMap.getInt(parameter) < lastUsedParameterIndex) { + continue; // no sense to report unused symbol before used since it will change signature + } + + message = JavaScriptLocalize.jsUnusedParameter(); + highlightedElement = parameter.getNameIdentifier(); + } + else if (p instanceof JSFunction function) { + PsiElement nameIdentifier = function.getNameIdentifier(); + if (nameIdentifier == null) { + continue; + } + highlightedElement = nameIdentifier; + message = JavaScriptLocalize.jsUnusedFunctionDeclaration(); + } + else { + highlightedElement = ((JSVariable)p).getNameIdentifier(); + message = JavaScriptLocalize.jsUnusedLocalVariable(); + } + + ProblemBuilder problemBuilder = holder.newProblem(message) + .range(highlightedElement) + .highlightType(ProblemHighlightType.LIKE_UNUSED_SYMBOL); + if (!(p.getParent() instanceof JSCatchBlock)) { + problemBuilder.withFix(new RemoveElementLocalQuickFix()); + } + problemBuilder.create(); + } + } + finally { + node.putUserData(UNUSED_LOCAL_DECLARATIONS_SET_KEY, null); + } + } + + private static void handleLocalDeclaration(JSNamedElement node) { + if (node instanceof JSFunction function && !isSupportedFunction(function)) { + return; + } + PsiElement scopeNode = PsiTreeUtil.getParentOfType(node, JSFunction.class, JSCatchBlock.class); + if (scopeNode == null) { + return; + } + Set unusedParametersSet = scopeNode.getUserData(UNUSED_LOCAL_DECLARATIONS_SET_KEY); + Set usedSet = scopeNode.getUserData(USED_LOCAL_DECLARATIONS_SET_KEY); + if (usedSet != null && usedSet.contains(node)) { + return; + } + if (unusedParametersSet == null) { + return; + } + unusedParametersSet.add(node); + } + + @Override + @Nonnull + public HighlightDisplayLevel getDefaultLevel() { + return HighlightDisplayLevel.WARNING; + } + + private static class RemoveElementLocalQuickFix implements LocalQuickFix { + @Nonnull + @Override + public LocalizeValue getName() { + return JavaScriptLocalize.jsUnusedSymbolRemove(); + } + + @Override + @RequiredWriteAction + public void applyFix(@Nonnull Project project, @Nonnull ProblemDescriptor descriptor) { + try { + PsiElement element = descriptor.getPsiElement(); + if (!(element instanceof JSNamedElement)) { + element = element.getParent(); + } + element.delete(); + } + catch (IncorrectOperationException e) { + LOG.error(e); + } + } + } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/navigation/JavaScriptGotoSuperHandler.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/navigation/JavaScriptGotoSuperHandler.java index d57a64e9..72f9a78a 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/navigation/JavaScriptGotoSuperHandler.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/navigation/JavaScriptGotoSuperHandler.java @@ -34,119 +34,99 @@ import consulo.language.psi.util.PsiTreeUtil; import consulo.navigation.NavigationItem; import consulo.project.Project; +import consulo.ui.annotation.RequiredUIAccess; import consulo.ui.ex.popup.JBPopup; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; @ExtensionImpl -public class JavaScriptGotoSuperHandler implements GotoSuperActionHander -{ - @Override - public void invoke(final Project project, final Editor editor, final PsiFile file) - { - final PsiElement at = file.findElementAt(editor.getCaretModel().getOffset()); - if(at == null) - { - return; - } - JSNamedElement namedElement = PsiTreeUtil.getParentOfType(at, JSNamedElement.class); - PsiElement parent = namedElement != null ? namedElement.getParent() : null; +public class JavaScriptGotoSuperHandler implements GotoSuperActionHander { + @Override + @RequiredUIAccess + public void invoke(Project project, Editor editor, PsiFile file) { + PsiElement at = file.findElementAt(editor.getCaretModel().getOffset()); + if (at == null) { + return; + } + JSNamedElement namedElement = PsiTreeUtil.getParentOfType(at, JSNamedElement.class); + + if (namedElement instanceof JSDefinitionExpression definition + && definition.getParent() instanceof JSAssignmentExpression assignment) { + PsiElement rOperand = assignment.getROperand(); + if (rOperand instanceof JSFunctionExpression functionExpr) { + namedElement = functionExpr; + } + } - if(namedElement instanceof JSDefinitionExpression) - { - if(parent instanceof JSAssignmentExpression) - { - PsiElement rOperand = ((JSAssignmentExpression) parent).getROperand(); - if(rOperand instanceof JSFunctionExpression) - { - namedElement = (JSNamedElement) rOperand; - } - } - } + if (namedElement instanceof JSFunction function) { + String qName = JSResolveUtil.getQNameToStartHierarchySearch(function); - if(namedElement instanceof JSFunction) - { - final JSFunction function = (JSFunction) namedElement; - final String qName = JSResolveUtil.getQNameToStartHierarchySearch(function); + PsiElement parent = function.getParent(); - if(qName != null) - { - if(parent instanceof JSFile) - { - JSClass xmlBackedClass = JSResolveUtil.getXmlBackedClass((JSFile) parent); - if(xmlBackedClass != null) - { - parent = xmlBackedClass; - } - } - boolean result = JSResolveUtil.iterateType(function, parent instanceof JSClass ? parent : parent.getContainingFile(), qName, - new JSResolveUtil.OverrideHandler() - { - @Override - public boolean process(final ResolveProcessor processor, final PsiElement scope, final String className) - { - ((NavigationItem) processor.getResult()).navigate(true); - return false; - } - }); + if (qName != null) { + if (parent instanceof JSFile jsFile) { + JSClass xmlBackedClass = JSResolveUtil.getXmlBackedClass(jsFile); + if (xmlBackedClass != null) { + parent = xmlBackedClass; + } + } + boolean result = JSResolveUtil.iterateType( + function, + parent instanceof JSClass jsClass ? jsClass : parent.getContainingFile(), + qName, + (processor, scope, className) -> { + ((NavigationItem)processor.getResult()).navigate(true); + return false; + } + ); - if(!result) - { - return; - } - } + if (!result) { + return; + } + } - if(parent instanceof JSClass) - { - JSResolveUtil.processInterfaceMethods((JSClass) parent, new JSResolveUtil.CollectMethodsToImplementProcessor(function.getName(), function) - { - @Override - protected boolean process(final ResolveProcessor processor) - { - ((NavigationItem) processor.getResult()).navigate(true); - return true; - } - }); - } - } - else if(namedElement instanceof JSClass) - { - final JSClass clazz = (JSClass) namedElement; - final JSClass[] classes = clazz.getSupers(); + if (parent instanceof JSClass jsClass) { + JSResolveUtil.processInterfaceMethods( + jsClass, + new JSResolveUtil.CollectMethodsToImplementProcessor(function.getName(), function) { + @Override + protected boolean process(ResolveProcessor processor) { + ((NavigationItem)processor.getResult()).navigate(true); + return true; + } + } + ); + } + } + else if (namedElement instanceof JSClass jsClass) { + JSClass[] classes = jsClass.getSupers(); - if(classes.length == 0) - { - return; - } - if(classes.length == 1) - { - classes[0].navigate(true); - } - else - { - JBPopup psiElementPopup = PopupNavigationUtil.getPsiElementPopup(classes, "Choose super class or interface"); + if (classes.length == 0) { + return; + } + if (classes.length == 1) { + classes[0].navigate(true); + } + else { + JBPopup psiElementPopup = PopupNavigationUtil.getPsiElementPopup(classes, "Choose super class or interface"); - EditorPopupHelper.getInstance().showPopupInBestPositionFor(editor, psiElementPopup); - } - } - } + EditorPopupHelper.getInstance().showPopupInBestPositionFor(editor, psiElementPopup); + } + } + } - @Override - public boolean startInWriteAction() - { - return false; - } + @Override + public boolean startInWriteAction() { + return false; + } - @Override - public boolean isValidFor(final Editor editor, final PsiFile file) - { - return true; - } + @Override + public boolean isValidFor(Editor editor, PsiFile file) { + return true; + } - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/navigation/JavaScriptSymbolContributor.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/navigation/JavaScriptSymbolContributor.java index 5529826c..ef87fc29 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/navigation/JavaScriptSymbolContributor.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/navigation/JavaScriptSymbolContributor.java @@ -34,50 +34,52 @@ import consulo.project.Project; import consulo.util.io.FileUtil; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; + import java.util.Collection; /** * @author maxim */ @ExtensionImpl -public class JavaScriptSymbolContributor implements GotoSymbolContributor -{ - @Override - public void processNames(@Nonnull Processor processor, @Nonnull SearchScope searchScope, @Nullable IdFilter idFilter) - { - StubIndex.getInstance().processAllKeys(JavaScriptIndexKeys.ELEMENTS_BY_NAME, processor, (GlobalSearchScope) searchScope, idFilter); +public class JavaScriptSymbolContributor implements GotoSymbolContributor { + @Override + public void processNames(@Nonnull Processor processor, @Nonnull SearchScope searchScope, @Nullable IdFilter idFilter) { + StubIndex.getInstance().processAllKeys(JavaScriptIndexKeys.ELEMENTS_BY_NAME, processor, (GlobalSearchScope)searchScope, idFilter); - FileBasedIndex.getInstance().processAllKeys(FilenameIndex.NAME, new Processor() - { - @Override - public boolean process(String s) - { - if(JavaScriptSupportLoader.isFlexMxmFile(s)) - { - return processor.process(FileUtil.getNameWithoutExtension(s)); - } - return true; - } - }, searchScope, idFilter); - } + FileBasedIndex.getInstance().processAllKeys( + FilenameIndex.NAME, + new Processor() { + @Override + public boolean process(String s) { + if (JavaScriptSupportLoader.isFlexMxmFile(s)) { + return processor.process(FileUtil.getNameWithoutExtension(s)); + } + return true; + } + }, + searchScope, + idFilter + ); + } - @Override - public void processElementsWithName(@Nonnull String name, @Nonnull Processor processor, @Nonnull FindSymbolParameters findSymbolParameters) - { - Project project = findSymbolParameters.getProject(); + @Override + public void processElementsWithName( + @Nonnull String name, + @Nonnull Processor processor, + @Nonnull FindSymbolParameters findSymbolParameters + ) { + Project project = findSymbolParameters.getProject(); - GlobalSearchScope scope = (GlobalSearchScope) findSymbolParameters.getSearchScope(); + GlobalSearchScope scope = (GlobalSearchScope)findSymbolParameters.getSearchScope(); - Collection result = JSResolveUtil.findElementsByName(name, project, scope); + Collection result = JSResolveUtil.findElementsByName(name, project, scope); - for(JSQualifiedNamedElement element : result) - { - if(!processor.process(element)) - { - break; - } - } - } + for (JSQualifiedNamedElement element : result) { + if (!processor.process(element)) { + break; + } + } + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/BaseIntroduceSettings.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/BaseIntroduceSettings.java index 383007dd..d74986cb 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/BaseIntroduceSettings.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/BaseIntroduceSettings.java @@ -19,11 +19,10 @@ /** * @author ven */ -public interface BaseIntroduceSettings -{ - boolean isReplaceAllOccurences(); +public interface BaseIntroduceSettings { + boolean isReplaceAllOccurences(); - String getVariableName(); + String getVariableName(); - String getVariableType(); + String getVariableType(); } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/BasicJavascriptNamesValidator.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/BasicJavascriptNamesValidator.java index eae7a968..6a76f98a 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/BasicJavascriptNamesValidator.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/BasicJavascriptNamesValidator.java @@ -23,21 +23,17 @@ import consulo.annotation.component.ExtensionImpl; import consulo.javascript.language.JavaScriptLanguage; import consulo.language.Language; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; @ExtensionImpl -public class BasicJavascriptNamesValidator extends JSNamesValidator -{ - public BasicJavascriptNamesValidator() - { - super(DialectOptionHolder.dummy()); - } +public class BasicJavascriptNamesValidator extends JSNamesValidator { + public BasicJavascriptNamesValidator() { + super(DialectOptionHolder.dummy()); + } - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/JSBaseClassBasedIntroduceDialog.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/JSBaseClassBasedIntroduceDialog.java index da1820f5..288b6575 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/JSBaseClassBasedIntroduceDialog.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/JSBaseClassBasedIntroduceDialog.java @@ -21,78 +21,71 @@ import com.intellij.lang.javascript.psi.JSAttributeList; import com.intellij.lang.javascript.psi.JSExpression; +import consulo.annotation.access.RequiredReadAction; +import consulo.localize.LocalizeValue; import consulo.project.Project; +import consulo.ui.annotation.RequiredUIAccess; /** * @author ven */ -public abstract class JSBaseClassBasedIntroduceDialog extends JSBaseIntroduceDialog -{ - private static JSAttributeList.AccessType lastType; +public abstract class JSBaseClassBasedIntroduceDialog extends JSBaseIntroduceDialog { + private static JSAttributeList.AccessType lastType; - protected JSBaseClassBasedIntroduceDialog(final Project project, final JSExpression[] occurences, final JSExpression mainOccurence, String titleKey) - { - super(project, occurences, mainOccurence, titleKey); - } + @RequiredUIAccess + protected JSBaseClassBasedIntroduceDialog(Project project, JSExpression[] occurences, JSExpression mainOccurence, LocalizeValue title) { + super(project, occurences, mainOccurence, title); + } - @Override - protected void doInit() - { - super.doInit(); + @Override + @RequiredReadAction + protected void doInit() { + super.doInit(); - final ButtonGroup group = new ButtonGroup(); - group.add(getPrivateRadioButton()); - group.add(getPublicRadioButton()); - group.add(getPackageLocalRadioButton()); - group.add(getProtectedRadioButton()); + ButtonGroup group = new ButtonGroup(); + group.add(getPrivateRadioButton()); + group.add(getPublicRadioButton()); + group.add(getPackageLocalRadioButton()); + group.add(getProtectedRadioButton()); - if(lastType == JSAttributeList.AccessType.PRIVATE || lastType == null) - { - getPrivateRadioButton().setSelected(true); - } - else if(lastType == JSAttributeList.AccessType.PROTECTED) - { - getProtectedRadioButton().setSelected(true); - } - else if(lastType == JSAttributeList.AccessType.PACKAGE_LOCAL) - { - getPackageLocalRadioButton().setSelected(true); - } - else if(lastType == JSAttributeList.AccessType.PUBLIC) - { - getPublicRadioButton().setSelected(true); - } - } + if (lastType == JSAttributeList.AccessType.PRIVATE || lastType == null) { + getPrivateRadioButton().setSelected(true); + } + else if (lastType == JSAttributeList.AccessType.PROTECTED) { + getProtectedRadioButton().setSelected(true); + } + else if (lastType == JSAttributeList.AccessType.PACKAGE_LOCAL) { + getPackageLocalRadioButton().setSelected(true); + } + else if (lastType == JSAttributeList.AccessType.PUBLIC) { + getPublicRadioButton().setSelected(true); + } + } - public JSAttributeList.AccessType getAccessType() - { - JSAttributeList.AccessType type = null; - if(getPublicRadioButton().isSelected()) - { - type = JSAttributeList.AccessType.PUBLIC; - } - if(getPrivateRadioButton().isSelected()) - { - type = JSAttributeList.AccessType.PRIVATE; - } - if(getPackageLocalRadioButton().isSelected()) - { - type = JSAttributeList.AccessType.PACKAGE_LOCAL; - } - if(getProtectedRadioButton().isSelected()) - { - type = JSAttributeList.AccessType.PROTECTED; - } - assert type != null; - lastType = type; - return type; - } + public JSAttributeList.AccessType getAccessType() { + JSAttributeList.AccessType type = null; + if (getPublicRadioButton().isSelected()) { + type = JSAttributeList.AccessType.PUBLIC; + } + if (getPrivateRadioButton().isSelected()) { + type = JSAttributeList.AccessType.PRIVATE; + } + if (getPackageLocalRadioButton().isSelected()) { + type = JSAttributeList.AccessType.PACKAGE_LOCAL; + } + if (getProtectedRadioButton().isSelected()) { + type = JSAttributeList.AccessType.PROTECTED; + } + assert type != null; + lastType = type; + return type; + } - protected abstract JRadioButton getPrivateRadioButton(); + protected abstract JRadioButton getPrivateRadioButton(); - protected abstract JRadioButton getPublicRadioButton(); + protected abstract JRadioButton getPublicRadioButton(); - protected abstract JRadioButton getProtectedRadioButton(); + protected abstract JRadioButton getProtectedRadioButton(); - protected abstract JRadioButton getPackageLocalRadioButton(); + protected abstract JRadioButton getPackageLocalRadioButton(); } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/JSBaseIntroduceDialog.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/JSBaseIntroduceDialog.java index 9faec08e..8ab69979 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/JSBaseIntroduceDialog.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/JSBaseIntroduceDialog.java @@ -16,12 +16,13 @@ package com.intellij.lang.javascript.impl.refactoring; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.impl.JSEmbeddedContentImpl; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; import com.intellij.lang.javascript.psi.resolve.ResolveProcessor; +import consulo.annotation.access.RequiredReadAction; import consulo.application.Application; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.Language; import consulo.language.editor.refactoring.NamesValidator; import consulo.language.editor.refactoring.ui.ConflictsDialog; @@ -30,11 +31,14 @@ import consulo.language.psi.PsiFile; import consulo.language.psi.ResolveResult; import consulo.language.psi.util.PsiTreeUtil; +import consulo.localize.LocalizeValue; import consulo.project.Project; +import consulo.ui.annotation.RequiredUIAccess; import consulo.ui.ex.awt.DialogWrapper; import consulo.ui.ex.awt.Messages; import consulo.ui.ex.awt.util.Alarm; -import consulo.util.lang.ref.Ref; +import consulo.util.lang.ref.SimpleReference; +import jakarta.annotation.Nonnull; import javax.swing.*; import java.awt.event.KeyAdapter; @@ -45,280 +49,245 @@ /** * @author ven */ -public abstract class JSBaseIntroduceDialog extends DialogWrapper implements BaseIntroduceSettings -{ - private final Project myProject; - private final JSExpression[] myOccurences; - protected final JSExpression myMainOccurence; - - private Alarm myAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); - - protected JSBaseIntroduceDialog(final Project project, final JSExpression[] occurences, final JSExpression mainOccurence, String titleKey) - { - super(project, false); - - myProject = project; - myOccurences = occurences; - myMainOccurence = mainOccurence; - setTitle(JavaScriptBundle.message(titleKey)); - } - - protected void doInit() - { - JCheckBox replaceAllCheckBox = getReplaceAllCheckBox(); - if(myOccurences.length > 1) - { - replaceAllCheckBox.setText(JavaScriptBundle.message("javascript.introduce.variable.replace.all.occurrences", myOccurences.length)); - } - else - { - replaceAllCheckBox.setVisible(false); - } - - final JTextField nameField = getNameField(); - nameField.setText(suggestCandidateName(myMainOccurence)); - nameField.selectAll(); - - nameField.addKeyListener(new KeyAdapter() - { - @Override - public void keyPressed(KeyEvent e) - { - initiateValidation(); - } - }); - - replaceAllCheckBox.setFocusable(false); - - final JComboBox typeField = getVarTypeField(); - - final List possibleTypes = new ArrayList(); - final String type = JSResolveUtil.getExpressionType(myMainOccurence, myMainOccurence.getContainingFile()); - possibleTypes.add(type); - - typeField.setModel(new DefaultComboBoxModel(possibleTypes.toArray(new Object[possibleTypes.size()]))); - - init(); - - SwingUtilities.invokeLater(new Runnable() - { - @Override - public void run() - { - initiateValidation(); - } - }); - } - - protected String suggestCandidateName(JSExpression mainOccurence) - { - final String s = evaluateCandidate(mainOccurence); - return s != null ? s.replace('.', '_') : null; - } - - private static String evaluateCandidate(JSExpression mainOccurence) - { - if(mainOccurence instanceof JSCallExpression) - { - mainOccurence = ((JSCallExpression) mainOccurence).getMethodExpression(); - } - - if(mainOccurence instanceof JSReferenceExpression) - { - final ResolveResult[] results = ((JSReferenceExpression) mainOccurence).multiResolve(false); - - if(results.length > 0) - { - final PsiElement element = results[0].getElement(); - - if(element instanceof JSFunction) - { - String typeString = ((JSFunction) element).getReturnTypeString(); - if(isValidIdentifier(typeString, mainOccurence)) - { - return typeString; - } - return ((JSFunction) element).getName(); - } - else if(element instanceof JSVariable) - { - String typeString = ((JSVariable) element).getTypeString(); - if(isValidIdentifier(typeString, mainOccurence)) - { - return typeString; - } - return typeString; - } - } - - return ((JSReferenceExpression) mainOccurence).getReferencedName(); - } - else if(mainOccurence.getParent() instanceof JSArgumentList) - { - JSParameter param = JSResolveUtil.findParameterForUsedArgument(mainOccurence, (JSArgumentList) mainOccurence.getParent()); - if(param != null) - { - return param.getName(); - } - } - - return JSResolveUtil.getExpressionType(mainOccurence, mainOccurence.getContainingFile()); - } - - private static boolean isValidIdentifier(String typeString, PsiElement context) - { - if(typeString == null) - { - return false; - } - Language language = context.getContainingFile().getLanguage(); - return NamesValidator.forLanguage(language).isIdentifier(typeString, context.getProject()); - } - - protected abstract JTextField getNameField(); - - protected abstract JPanel getPanel(); - - protected abstract JCheckBox getReplaceAllCheckBox(); - - private void initiateValidation() - { - myAlarm.cancelAllRequests(); - myAlarm.addRequest(new Runnable() - { - @Override - public void run() - { - final String nameCandidate = getNameField().getText(); - setOKActionEnabled(nameCandidate.length() != 0 && isValidName(nameCandidate)); - } - }, 100, Application.get().getCurrentModalityState()); - } - - @Override - public JComponent getPreferredFocusedComponent() - { - return getNameField(); - } - - @Override - protected JComponent createCenterPanel() - { - return getPanel(); - } - - @Override - protected void doOKAction() - { - final String name = getVariableName(); - if(name.length() == 0 || !isValidName(name)) - { - Messages.showErrorDialog(myProject, JavaScriptBundle.message("javascript.introduce.variable.invalid.name"), - JavaScriptBundle.message("javascript.introduce.variable.title")); - getNameField().requestFocus(); - return; - } - - if(!checkConflicts(name)) - { - return; - } - - super.doOKAction(); - } - - private boolean checkConflicts(final String name) - { - PsiElement tmp = isReplaceAllOccurences() ? PsiTreeUtil.findCommonParent(myOccurences) : myMainOccurence; - assert tmp != null; - JSElement scope = PsiTreeUtil.getNonStrictParentOfType(tmp, JSBlockStatement.class, JSFile.class, JSEmbeddedContentImpl.class); - assert scope != null; - - final Ref existing = new Ref(); - scope.accept(new JSElementVisitor() - { - @Override - public void visitJSElement(final JSElement node) - { - if(existing.isNull()) - { - node.acceptChildren(this); - } - } - - @Override - public void visitJSVariable(final JSVariable node) - { - if(name.equals(node.getName())) - { - existing.set(node); - } - super.visitJSVariable(node); - } - - @Override - public void visitJSFunctionDeclaration(final JSFunction node) - { - if(name.equals(node.getName())) - { - existing.set(node); - } - super.visitJSFunctionDeclaration(node); - } - }); - - if(existing.isNull()) - { - final ResolveProcessor processor = new ResolveProcessor(name); - JSResolveUtil.treeWalkUp(processor, scope, null, scope); - final PsiElement resolved = processor.getResult(); - if(resolved instanceof JSNamedElement) - { - existing.set((JSNamedElement) resolved); - } - } - - if(!existing.isNull()) - { - return showConflictsDialog(existing.get(), name); - } - - return true; - } - - private boolean showConflictsDialog(final JSNamedElement existing, final String name) - { - final String message = existing instanceof JSFunction ? JavaScriptBundle.message("javascript.introduce.variable.function.already.exists", - CommonRefactoringUtil.htmlEmphasize(name)) : JavaScriptBundle.message("javascript.introduce.variable.variable.already.exists", - CommonRefactoringUtil.htmlEmphasize(name)); - final ConflictsDialog conflictsDialog = new ConflictsDialog(myProject, message); - conflictsDialog.show(); - return conflictsDialog.isOK(); - } - - @Override - public boolean isReplaceAllOccurences() - { - return getReplaceAllCheckBox().isSelected(); - } - - @Override - public String getVariableName() - { - return getNameField().getText().trim(); - } - - @Override - public String getVariableType() - { - return (String) getVarTypeField().getSelectedItem(); - } - - private boolean isValidName(final String name) - { - final PsiFile containingFile = myMainOccurence.getContainingFile(); - return NamesValidator.forLanguage(containingFile.getLanguage()).isIdentifier(name, myProject); - } - - public abstract JComboBox getVarTypeField(); +public abstract class JSBaseIntroduceDialog extends DialogWrapper implements BaseIntroduceSettings { + private final Project myProject; + private final JSExpression[] myOccurrences; + protected final JSExpression myMainOccurrence; + + private Alarm myAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); + + @RequiredUIAccess + protected JSBaseIntroduceDialog( + Project project, + JSExpression[] occurrences, + JSExpression mainOccurrence, + @Nonnull LocalizeValue title + ) { + super(project, false); + + myProject = project; + myOccurrences = occurrences; + myMainOccurrence = mainOccurrence; + setTitle(title); + } + + @RequiredReadAction + protected void doInit() { + JCheckBox replaceAllCheckBox = getReplaceAllCheckBox(); + if (myOccurrences.length > 1) { + replaceAllCheckBox.setText(JavaScriptLocalize.javascriptIntroduceVariableReplaceAllOccurrences(myOccurrences.length).get()); + } + else { + replaceAllCheckBox.setVisible(false); + } + + JTextField nameField = getNameField(); + nameField.setText(suggestCandidateName(myMainOccurrence)); + nameField.selectAll(); + + nameField.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + initiateValidation(); + } + }); + + replaceAllCheckBox.setFocusable(false); + + JComboBox typeField = getVarTypeField(); + + List possibleTypes = new ArrayList<>(); + String type = JSResolveUtil.getExpressionType(myMainOccurrence, myMainOccurrence.getContainingFile()); + possibleTypes.add(type); + + typeField.setModel(new DefaultComboBoxModel(possibleTypes.toArray(new Object[possibleTypes.size()]))); + + init(); + + SwingUtilities.invokeLater(this::initiateValidation); + } + + @RequiredReadAction + protected String suggestCandidateName(JSExpression mainOccurrence) { + String s = evaluateCandidate(mainOccurrence); + return s != null ? s.replace('.', '_') : null; + } + + @RequiredReadAction + private static String evaluateCandidate(JSExpression mainOccurrence) { + if (mainOccurrence instanceof JSCallExpression call) { + mainOccurrence = call.getMethodExpression(); + } + + if (mainOccurrence instanceof JSReferenceExpression refExpr) { + ResolveResult[] results = refExpr.multiResolve(false); + + if (results.length > 0) { + PsiElement element = results[0].getElement(); + + if (element instanceof JSFunction function) { + String typeString = function.getReturnTypeString(); + if (isValidIdentifier(typeString, refExpr)) { + return typeString; + } + return function.getName(); + } + else if (element instanceof JSVariable variable) { + String typeString = variable.getTypeString(); + if (isValidIdentifier(typeString, refExpr)) { + return typeString; + } + return typeString; + } + } + + return refExpr.getReferencedName(); + } + else if (mainOccurrence.getParent() instanceof JSArgumentList argList) { + JSParameter param = JSResolveUtil.findParameterForUsedArgument(mainOccurrence, argList); + if (param != null) { + return param.getName(); + } + } + + return JSResolveUtil.getExpressionType(mainOccurrence, mainOccurrence.getContainingFile()); + } + + @RequiredReadAction + private static boolean isValidIdentifier(String typeString, PsiElement context) { + if (typeString == null) { + return false; + } + Language language = context.getContainingFile().getLanguage(); + return NamesValidator.forLanguage(language).isIdentifier(typeString, context.getProject()); + } + + protected abstract JTextField getNameField(); + + protected abstract JPanel getPanel(); + + protected abstract JCheckBox getReplaceAllCheckBox(); + + private void initiateValidation() { + myAlarm.cancelAllRequests(); + myAlarm.addRequest( + () -> { + String nameCandidate = getNameField().getText(); + setOKActionEnabled(nameCandidate.length() != 0 && isValidName(nameCandidate)); + }, + 100, + Application.get().getCurrentModalityState() + ); + } + + @Override + @RequiredUIAccess + public JComponent getPreferredFocusedComponent() { + return getNameField(); + } + + @Override + protected JComponent createCenterPanel() { + return getPanel(); + } + + @Override + @RequiredUIAccess + protected void doOKAction() { + String name = getVariableName(); + if (name.length() == 0 || !isValidName(name)) { + Messages.showErrorDialog( + myProject, + JavaScriptLocalize.javascriptIntroduceVariableInvalidName().get(), + JavaScriptLocalize.javascriptIntroduceVariableTitle().get() + ); + getNameField().requestFocus(); + return; + } + + if (!checkConflicts(name)) { + return; + } + + super.doOKAction(); + } + + @RequiredUIAccess + private boolean checkConflicts(String name) { + PsiElement tmp = isReplaceAllOccurences() ? PsiTreeUtil.findCommonParent(myOccurrences) : myMainOccurrence; + assert tmp != null; + JSElement scope = PsiTreeUtil.getNonStrictParentOfType(tmp, JSBlockStatement.class, JSFile.class, JSEmbeddedContentImpl.class); + assert scope != null; + + final SimpleReference existing = new SimpleReference<>(); + scope.accept(new JSElementVisitor() { + @Override + public void visitJSElement(@Nonnull JSElement node) { + if (existing.isNull()) { + node.acceptChildren(this); + } + } + + @Override + @RequiredReadAction + public void visitJSVariable(@Nonnull JSVariable node) { + if (name.equals(node.getName())) { + existing.set(node); + } + super.visitJSVariable(node); + } + + @Override + @RequiredReadAction + public void visitJSFunctionDeclaration(@Nonnull JSFunction node) { + if (name.equals(node.getName())) { + existing.set(node); + } + super.visitJSFunctionDeclaration(node); + } + }); + + if (existing.isNull()) { + ResolveProcessor processor = new ResolveProcessor(name); + JSResolveUtil.treeWalkUp(processor, scope, null, scope); + PsiElement resolved = processor.getResult(); + if (resolved instanceof JSNamedElement namedElement) { + existing.set(namedElement); + } + } + + return existing.isNull() || showConflictsDialog(existing.get(), name); + } + + @RequiredUIAccess + private boolean showConflictsDialog(JSNamedElement existing, String name) { + LocalizeValue message = existing instanceof JSFunction + ? JavaScriptLocalize.javascriptIntroduceVariableFunctionAlreadyExists(CommonRefactoringUtil.htmlEmphasize(name)) + : JavaScriptLocalize.javascriptIntroduceVariableVariableAlreadyExists(CommonRefactoringUtil.htmlEmphasize(name)); + ConflictsDialog conflictsDialog = new ConflictsDialog(myProject, message); + conflictsDialog.show(); + return conflictsDialog.isOK(); + } + + @Override + public boolean isReplaceAllOccurences() { + return getReplaceAllCheckBox().isSelected(); + } + + @Override + public String getVariableName() { + return getNameField().getText().trim(); + } + + @Override + public String getVariableType() { + return (String)getVarTypeField().getSelectedItem(); + } + + private boolean isValidName(String name) { + PsiFile containingFile = myMainOccurrence.getContainingFile(); + return NamesValidator.forLanguage(containingFile.getLanguage()).isIdentifier(name, myProject); + } + + public abstract JComboBox getVarTypeField(); } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/JSBaseIntroduceHandler.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/JSBaseIntroduceHandler.java index 07165223..b92c039a 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/JSBaseIntroduceHandler.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/JSBaseIntroduceHandler.java @@ -16,474 +16,415 @@ package com.intellij.lang.javascript.impl.refactoring; -import java.util.ArrayList; -import java.util.List; - -import javax.annotation.Nonnull; - -import consulo.application.ApplicationManager; -import consulo.codeEditor.Editor; -import consulo.colorScheme.TextAttributes; -import consulo.dataContext.DataContext; -import consulo.document.RangeMarker; -import consulo.language.editor.PsiEquivalenceUtil; -import consulo.language.editor.highlight.HighlightManager; -import consulo.language.editor.refactoring.RefactoringBundle; -import consulo.language.editor.refactoring.action.RefactoringActionHandler; -import consulo.project.ui.wm.WindowManager; -import consulo.ui.ex.awt.DialogWrapper; -import consulo.undoRedo.CommandProcessor; -import org.jetbrains.annotations.NonNls; - -import javax.annotation.Nullable; - import com.intellij.lang.javascript.JSTokenTypes; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.impl.JSChangeUtil; import com.intellij.lang.javascript.psi.impl.JSEmbeddedContentImpl; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; -import consulo.logging.Logger; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; +import consulo.codeEditor.Editor; import consulo.codeEditor.EditorColors; -import consulo.colorScheme.EditorColorsManager; import consulo.codeEditor.markup.RangeHighlighter; -import consulo.project.Project; +import consulo.colorScheme.EditorColorsManager; +import consulo.colorScheme.TextAttributes; +import consulo.dataContext.DataContext; +import consulo.document.RangeMarker; import consulo.document.util.TextRange; +import consulo.language.editor.PsiEquivalenceUtil; +import consulo.language.editor.highlight.HighlightManager; +import consulo.language.editor.refactoring.action.RefactoringActionHandler; +import consulo.language.editor.refactoring.localize.RefactoringLocalize; +import consulo.language.editor.refactoring.util.CommonRefactoringUtil; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiFile; import consulo.language.psi.PsiWhiteSpace; import consulo.language.psi.util.PsiTreeUtil; -import consulo.language.editor.refactoring.util.CommonRefactoringUtil; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import consulo.logging.Logger; +import consulo.project.Project; +import consulo.project.ui.wm.WindowManager; +import consulo.ui.annotation.RequiredUIAccess; +import consulo.ui.ex.awt.DialogWrapper; +import consulo.undoRedo.CommandProcessor; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; + +import java.util.ArrayList; +import java.util.List; /** * @author ven */ -public abstract class JSBaseIntroduceHandler implements - RefactoringActionHandler -{ - protected static final Logger LOG = Logger.getInstance("#com.intellij.lang.javascript.refactoring.JSBaseIntroduceHandler"); - - protected static JSExpression findExpressionInRange(PsiFile file, int startOffset, int endOffset) - { - PsiElement element1 = file.findElementAt(startOffset); - PsiElement element2 = file.findElementAt(endOffset - 1); - if(element1 instanceof PsiWhiteSpace) - { - startOffset = element1.getTextRange().getEndOffset(); - } - if(element2 instanceof PsiWhiteSpace) - { - endOffset = element2.getTextRange().getStartOffset(); - } - - JSExpression expression = PsiTreeUtil.findElementOfClassAtRange(file, startOffset, endOffset, JSExpression.class); - int expressionEnd; - PsiElement sibling; - - if(expression == null || (expressionEnd = expression.getTextRange().getEndOffset()) != endOffset && (expressionEnd != endOffset - 1 || - (sibling = expression.getNextSibling()) == null || - sibling.getNode().getElementType() != JSTokenTypes.SEMICOLON)) - { - return null; - } - - if(expression instanceof JSReferenceExpression && expression.getParent() instanceof JSCallExpression) - { - return null; - } - /*if(file.getLanguage() == JavaScriptSupportLoader.JSON) - { - expression = null; // there is no vars in json - }*/ - return expression; - } - - protected static JSExpression unparenthesize(JSExpression expression) - { - while(expression instanceof JSParenthesizedExpression) - { - expression = ((JSParenthesizedExpression) expression).getInnerExpression(); - } - - return expression; - } - - public static JSExpression[] findExpressionOccurrences(JSElement scope, JSExpression expr) - { - List array = new ArrayList(); - addExpressionOccurrences(unparenthesize(expr), array, scope); - return array.toArray(new JSExpression[array.size()]); - } - - protected static void addExpressionOccurrences(JSExpression expr, List array, PsiElement scope) - { - PsiElement[] children = scope.getChildren(); - - for(PsiElement child : children) - { - if(child instanceof JSExpression) - { - final JSExpression childExpression = unparenthesize((JSExpression) child); - - if(childExpression != null && - PsiEquivalenceUtil.areElementsEquivalent(childExpression, expr) && - !JSResolveUtil.isSelfReference(scope, child)) - { - array.add((JSExpression) child); - continue; - } - } - if(!(child instanceof JSFunction)) - { - addExpressionOccurrences(expr, array, child); - } - } - } - - @Override - public void invoke(@Nonnull final Project project, final Editor editor, PsiFile file, DataContext dataContext) - { - if(!editor.getSelectionModel().hasSelection()) - { - editor.getSelectionModel().selectLineAtCaret(); - } - int start = editor.getSelectionModel().getSelectionStart(); - int end = editor.getSelectionModel().getSelectionEnd(); - - final JSExpression expression = findIntroducedExpression(file, start, end, editor); - if(expression == null) - { - return; - } - - if(!CommonRefactoringUtil.checkReadOnlyStatus(project, file)) - { - return; - } - - editor.getSelectionModel().removeSelection(); - JSElement scope = findIntroducedScope(expression); - LOG.assertTrue(scope != null); - final JSExpression[] occurrences = findExpressionOccurrences(scope, expression); - final S settings = getSettings(project, editor, expression, occurrences); - if(settings == null) - { - return; - } - - CommandProcessor.getInstance().executeCommand(project, new Runnable() - { - @Override - public void run() - { - ApplicationManager.getApplication().runWriteAction(new Runnable() - { - @Override - public void run() - { - doRefactoring(project, editor, new BaseIntroduceContext(expression, occurrences, settings)); - } - }); - } - }, getRefactoringName(), null); - } - - protected static final class BaseIntroduceContext - { - public final S settings; - final JSExpression[] occurences; - public final JSExpression expression; - - public BaseIntroduceContext(JSExpression _mainoccurence, final JSExpression[] _occurences, S _settings) - { - occurences = _occurences; - expression = _mainoccurence; - settings = _settings; - } - } - - protected JSElement findIntroducedScope(final JSExpression expression) - { - return PsiTreeUtil.getParentOfType(expression, JSFunction.class, JSFile.class, JSEmbeddedContentImpl.class); - } - - protected abstract String getRefactoringName(); - - protected abstract String getCannotIntroduceMessagePropertyKey(); - - @Nullable - protected JSExpression findIntroducedExpression(final PsiFile file, final int start, final int end, Editor editor) - { - final JSExpression expression = findExpressionInRange(file, start, end); - if(expression == null) - { - CommonRefactoringUtil.showErrorHint(file.getProject(), editor, JavaScriptBundle.message(getCannotIntroduceMessagePropertyKey()), getRefactoringName(), - null); - } - return expression; - } - - @Nullable - protected S getSettings(Project project, Editor editor, JSExpression expression, final JSExpression[] occurrences) - { - ArrayList highlighters = null; - if(occurrences.length > 1) - { - highlighters = highlightOccurences(project, editor, occurrences); - } - - final D dialog = createDialog(project, expression, occurrences); - dialog.show(); - if(highlighters != null) - { - for(RangeHighlighter highlighter : highlighters) - { - HighlightManager.getInstance(project).removeSegmentHighlighter(editor, highlighter); - } - } - - if(dialog.getExitCode() != DialogWrapper.OK_EXIT_CODE) - { - return null; - } - - return createSettings(dialog); - } - - protected S createSettings(final D dialog) - { - return (S) dialog; - } - - protected abstract D createDialog(final Project project, final JSExpression expression, final JSExpression[] occurrences); - - private void doRefactoring(final Project project, final Editor editor, BaseIntroduceContext introduceContext) - { - final S settings = introduceContext.settings; - JSExpression expression = introduceContext.expression; - final JSExpression[] occurrences = introduceContext.occurences; - - final boolean replaceAllOccurences = settings.isReplaceAllOccurences(); - @NonNls String varDeclText = getDeclText(settings); - final PsiFile containingFile = expression.getContainingFile(); - final boolean ecma = false; - if(ecma) - { - String type = settings.getVariableType(); - if(type == null) - { - type = JSResolveUtil.getExpressionType(expression, containingFile); - } - varDeclText += ":" + type; - } - - try - { - T anchorStatement = findAnchor(introduceContext, replaceAllOccurences); - JSVarStatement declaration = prepareDeclaration(varDeclText, introduceContext, project); - - LOG.assertTrue(anchorStatement != null); - - boolean replacedOriginal = false; - - if(anchorStatement == expression.getParent() && anchorStatement instanceof JSExpressionStatement) - { - declaration = (JSVarStatement) anchorStatement.replace(declaration); - editor.getCaretModel().moveToOffset(declaration.getTextRange().getEndOffset()); - replacedOriginal = true; - } - else - { - JSExpression oldExpression = expression; - final TextRange expressionTextRange = expression.getTextRange(); - final TextRange statementTextRange = anchorStatement.getTextRange(); - - RangeMarker marker = editor.getDocument().createRangeMarker(expressionTextRange); - - // Adding declaration to anchorStatement may invalidate original expression so we need to find it in new tree - final T jsStatement = addStatementBefore(anchorStatement, declaration); - - if(!expression.isValid()) - { - final T newAnchorStatement = (T) PsiTreeUtil.getNextSiblingOfType(jsStatement, anchorStatement.getClass()); - final int relativeOffset = marker.getStartOffset() - statementTextRange.getStartOffset(); - JSExpression newExpression = PsiTreeUtil.getParentOfType(newAnchorStatement.findElementAt(relativeOffset), oldExpression.getClass()); - - if(newExpression == null) - { - assert false : "Could not find " + oldExpression.getClass() + " in " + newAnchorStatement.getText() + " with offset " + marker - .getStartOffset(); - } - - while(newExpression.getTextRange().getLength() != expressionTextRange.getLength()) - { - JSExpression candidateExpression = PsiTreeUtil.getParentOfType(newExpression, oldExpression.getClass()); - if(candidateExpression == null) - { - break; - } - if(candidateExpression.getTextRange().getStartOffset() - newAnchorStatement.getTextRange().getStartOffset() != marker.getStartOffset()) - { - break; - } - newExpression = candidateExpression; - } - - for(int i = 0; i < occurrences.length; ++i) - { - if(occurrences[i] == oldExpression) - { - occurrences[i] = newExpression; - break; - } - } - - expression = newExpression; - } - } - - final JSExpression refExpr = (JSExpression) JSChangeUtil.createExpressionFromText(project, settings.getVariableName()); - if(replaceAllOccurences) - { - List toHighight = new ArrayList(); - for(JSExpression occurence : occurrences) - { - if(occurence != expression || !replacedOriginal) - { - toHighight.add(occurence.replace(refExpr)); - } - else - { - toHighight.add(declaration.getVariables()[0].getInitializer()); - } - } - - highlightOccurences(project, editor, toHighight.toArray(new JSExpression[toHighight.size()])); - } - else if(!replacedOriginal) - { - expression.replace(refExpr); - } - } - catch(IncorrectOperationException e) - { - LOG.error(e); - } - } - - protected JSVarStatement prepareDeclaration(final String varDeclText, BaseIntroduceContext context, final Project project) throws IncorrectOperationException - { - JSVarStatement declaration = (JSVarStatement) JSChangeUtil.createStatementFromText(project, varDeclText + " = 0" + JSChangeUtil.getSemicolon - (project)).getPsi(); - declaration.getVariables()[0].getInitializer().replace(context.expression); - return declaration; - } - - @NonNls - protected String getDeclText(S settings) - { - return "var " + settings.getVariableName(); - } - - protected T addStatementBefore(final T anchorStatement, final JSVarStatement declaration) throws IncorrectOperationException - { - return (T) ((JSStatement) anchorStatement).addStatementBefore(declaration); - } - - protected T findAnchor(final BaseIntroduceContext context, final boolean replaceAllOccurences) - { - JSStatement anchorStatement = replaceAllOccurences ? getAnchorToInsert(context.occurences) : PsiTreeUtil.getParentOfType(context.expression, - JSStatement.class); - if(anchorStatement instanceof JSVarStatement && - anchorStatement.getParent() instanceof JSStatement && - !(anchorStatement.getParent() instanceof JSBlockStatement)) - { - anchorStatement = (JSStatement) anchorStatement.getParent(); - } - return (T) anchorStatement; - } - - private static ArrayList highlightOccurences(Project project, Editor editor, JSExpression[] occurences) - { - HighlightManager highlightManager = HighlightManager.getInstance(project); - EditorColorsManager colorsManager = EditorColorsManager.getInstance(); - TextAttributes attributes = colorsManager.getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES); - ArrayList result = new ArrayList(); - highlightManager.addOccurrenceHighlights(editor, occurences, attributes, true, result); - WindowManager.getInstance().getStatusBar(project).setInfo(RefactoringBundle.message("press.escape.to.remove.the.highlighting")); - return result; - } - - private static JSStatement getAnchorToInsert(final JSExpression[] expressions) - { - JSElement place = expressions[0]; - next: - do - { - JSStatement statement = PsiTreeUtil.getParentOfType(place, JSStatement.class); //this is the first expression textually - LOG.assertTrue(statement != null); - - final PsiElement parent = statement.getParent(); - for(JSExpression expression : expressions) - { - if(!PsiTreeUtil.isAncestor(parent, expression, true)) - { - place = statement; - continue next; - } - } - - return statement; - } - while(true); - } - - protected static JSElement findClassAnchor(final PsiElement expression) - { - PsiElement nearestParent = PsiTreeUtil.getParentOfType(expression, JSVarStatement.class, JSFunction.class); - while(nearestParent != null) - { - final PsiElement nextParent = PsiTreeUtil.getParentOfType(nearestParent, JSVarStatement.class, JSFunction.class); - if(nextParent == null) - { - break; - } - nearestParent = nextParent; - } - - if(nearestParent != null) - { - return (JSElement) nearestParent; - } - - JSElement parent = PsiTreeUtil.getParentOfType(expression, JSFile.class, JSClass.class); - - if(parent instanceof JSFile) - { - final PsiElement classRef = JSResolveUtil.getClassReferenceForXmlFromContext(parent); - if(classRef instanceof JSClass) - { - parent = (JSElement) classRef; - } - } - - return parent; - } - - protected static JSElement addToClassAnchor(final JSElement anchorStatement, final JSVarStatement declaration) throws IncorrectOperationException - { - if(!(anchorStatement instanceof JSClass)) - { - final JSElement element = findClassAnchor(anchorStatement); - return (JSElement) element.addBefore(declaration, anchorStatement); - } - return (JSElement) anchorStatement.add(declaration); - } - - @Override - public void invoke(@Nonnull Project project, @Nonnull PsiElement[] elements, DataContext dataContext) - { - throw new RuntimeException("Not implemented"); - } +public abstract class JSBaseIntroduceHandler + implements RefactoringActionHandler { + + protected static final Logger LOG = Logger.getInstance("#com.intellij.lang.javascript.refactoring.JSBaseIntroduceHandler"); + + @RequiredReadAction + protected static JSExpression findExpressionInRange(PsiFile file, int startOffset, int endOffset) { + PsiElement element1 = file.findElementAt(startOffset); + PsiElement element2 = file.findElementAt(endOffset - 1); + if (element1 instanceof PsiWhiteSpace whiteSpace) { + startOffset = whiteSpace.getTextRange().getEndOffset(); + } + if (element2 instanceof PsiWhiteSpace whiteSpace) { + endOffset = whiteSpace.getTextRange().getStartOffset(); + } + + JSExpression expression = PsiTreeUtil.findElementOfClassAtRange(file, startOffset, endOffset, JSExpression.class); + int expressionEnd; + PsiElement sibling; + + if (expression == null || (expressionEnd = + expression.getTextRange().getEndOffset()) != endOffset && (expressionEnd != endOffset - 1 || + (sibling = expression.getNextSibling()) == null || + sibling.getNode().getElementType() != JSTokenTypes.SEMICOLON)) { + return null; + } + + if (expression instanceof JSReferenceExpression refExpr && refExpr.getParent() instanceof JSCallExpression) { + return null; + } + /*if (file.getLanguage() == JavaScriptSupportLoader.JSON) { + expression = null; // there is no vars in json + }*/ + return expression; + } + + protected static JSExpression unparenthesize(JSExpression expression) { + while (expression instanceof JSParenthesizedExpression parenthesized) { + expression = parenthesized.getInnerExpression(); + } + + return expression; + } + + @RequiredReadAction + public static JSExpression[] findExpressionOccurrences(JSElement scope, JSExpression expr) { + List array = new ArrayList<>(); + addExpressionOccurrences(unparenthesize(expr), array, scope); + return array.toArray(new JSExpression[array.size()]); + } + + @RequiredReadAction + protected static void addExpressionOccurrences(JSExpression expr, List array, PsiElement scope) { + PsiElement[] children = scope.getChildren(); + + for (PsiElement child : children) { + if (child instanceof JSExpression childExpr) { + JSExpression childUnparenExpr = unparenthesize(childExpr); + + if (childUnparenExpr != null + && PsiEquivalenceUtil.areElementsEquivalent(childUnparenExpr, expr) + && !JSResolveUtil.isSelfReference(scope, childExpr)) { + array.add(childExpr); + continue; + } + } + + if (!(child instanceof JSFunction)) { + addExpressionOccurrences(expr, array, child); + } + } + } + + @Override + @RequiredWriteAction + public void invoke(@Nonnull Project project, Editor editor, PsiFile file, DataContext dataContext) { + if (!editor.getSelectionModel().hasSelection()) { + editor.getSelectionModel().selectLineAtCaret(); + } + int start = editor.getSelectionModel().getSelectionStart(); + int end = editor.getSelectionModel().getSelectionEnd(); + + JSExpression expression = findIntroducedExpression(file, start, end, editor); + if (expression == null) { + return; + } + + if (!CommonRefactoringUtil.checkReadOnlyStatus(project, file)) { + return; + } + + editor.getSelectionModel().removeSelection(); + JSElement scope = findIntroducedScope(expression); + LOG.assertTrue(scope != null); + JSExpression[] occurrences = findExpressionOccurrences(scope, expression); + S settings = getSettings(project, editor, expression, occurrences); + if (settings == null) { + return; + } + + CommandProcessor.getInstance().newCommand() + .project(project) + .name(LocalizeValue.ofNullable(getRefactoringName())) + .inWriteAction() + .run(() -> doRefactoring(project, editor, new BaseIntroduceContext<>(expression, occurrences, settings))); + } + + protected static final class BaseIntroduceContext { + public final S settings; + final JSExpression[] occurences; + public final JSExpression expression; + + public BaseIntroduceContext(JSExpression _mainoccurence, JSExpression[] _occurences, S _settings) { + occurences = _occurences; + expression = _mainoccurence; + settings = _settings; + } + } + + protected JSElement findIntroducedScope(JSExpression expression) { + return PsiTreeUtil.getParentOfType(expression, JSFunction.class, JSFile.class, JSEmbeddedContentImpl.class); + } + + protected abstract String getRefactoringName(); + + protected abstract LocalizeValue getCannotIntroduceMessage(); + + @Nullable + @RequiredUIAccess + protected JSExpression findIntroducedExpression(PsiFile file, int start, int end, Editor editor) { + JSExpression expression = findExpressionInRange(file, start, end); + if (expression == null) { + CommonRefactoringUtil.showErrorHint( + file.getProject(), + editor, + getCannotIntroduceMessage().get(), + getRefactoringName(), + null + ); + } + return expression; + } + + @Nullable + @RequiredUIAccess + protected S getSettings(Project project, Editor editor, JSExpression expression, JSExpression[] occurrences) { + ArrayList highlighters = null; + if (occurrences.length > 1) { + highlighters = highlightOccurences(project, editor, occurrences); + } + + D dialog = createDialog(project, expression, occurrences); + dialog.show(); + if (highlighters != null) { + for (RangeHighlighter highlighter : highlighters) { + HighlightManager.getInstance(project).removeSegmentHighlighter(editor, highlighter); + } + } + + if (dialog.getExitCode() != DialogWrapper.OK_EXIT_CODE) { + return null; + } + + return createSettings(dialog); + } + + @SuppressWarnings("unchecked") + protected S createSettings(D dialog) { + return (S)dialog; + } + + protected abstract D createDialog(Project project, JSExpression expression, JSExpression[] occurrences); + + @RequiredWriteAction + @SuppressWarnings("unchecked") + private void doRefactoring(Project project, Editor editor, BaseIntroduceContext introduceContext) { + S settings = introduceContext.settings; + JSExpression expression = introduceContext.expression; + JSExpression[] occurrences = introduceContext.occurences; + + boolean replaceAllOccurences = settings.isReplaceAllOccurences(); + String varDeclText = getDeclText(settings); + PsiFile containingFile = expression.getContainingFile(); + boolean ecma = false; + if (ecma) { + String type = settings.getVariableType(); + if (type == null) { + type = JSResolveUtil.getExpressionType(expression, containingFile); + } + varDeclText += ":" + type; + } + + try { + T anchorStatement = findAnchor(introduceContext, replaceAllOccurences); + JSVarStatement declaration = prepareDeclaration(varDeclText, introduceContext, project); + + LOG.assertTrue(anchorStatement != null); + + boolean replacedOriginal = false; + + if (anchorStatement == expression.getParent() && anchorStatement instanceof JSExpressionStatement anchorExpression) { + declaration = (JSVarStatement)anchorExpression.replace(declaration); + editor.getCaretModel().moveToOffset(declaration.getTextRange().getEndOffset()); + replacedOriginal = true; + } + else { + JSExpression oldExpression = expression; + TextRange expressionTextRange = expression.getTextRange(); + TextRange statementTextRange = anchorStatement.getTextRange(); + + RangeMarker marker = editor.getDocument().createRangeMarker(expressionTextRange); + + // Adding declaration to anchorStatement may invalidate original expression so we need to find it in new tree + T jsStatement = addStatementBefore(anchorStatement, declaration); + + if (!expression.isValid()) { + T newAnchorStatement = (T)PsiTreeUtil.getNextSiblingOfType(jsStatement, anchorStatement.getClass()); + int relativeOffset = marker.getStartOffset() - statementTextRange.getStartOffset(); + JSExpression newExpression = + PsiTreeUtil.getParentOfType(newAnchorStatement.findElementAt(relativeOffset), oldExpression.getClass()); + + if (newExpression == null) { + assert false : "Could not find " + oldExpression.getClass() + " in " + newAnchorStatement.getText() + " with offset " + marker + .getStartOffset(); + } + + while (newExpression.getTextRange().getLength() != expressionTextRange.getLength()) { + JSExpression candidateExpression = PsiTreeUtil.getParentOfType(newExpression, oldExpression.getClass()); + if (candidateExpression == null) { + break; + } + if (candidateExpression.getTextRange().getStartOffset() - newAnchorStatement.getTextRange() + .getStartOffset() != marker.getStartOffset()) { + break; + } + newExpression = candidateExpression; + } + + for (int i = 0; i < occurrences.length; ++i) { + if (occurrences[i] == oldExpression) { + occurrences[i] = newExpression; + break; + } + } + + expression = newExpression; + } + } + + JSExpression refExpr = JSChangeUtil.createExpressionFromText(project, settings.getVariableName()); + if (replaceAllOccurences) { + List toHighight = new ArrayList<>(); + for (JSExpression occurence : occurrences) { + if (occurence != expression || !replacedOriginal) { + toHighight.add(occurence.replace(refExpr)); + } + else { + toHighight.add(declaration.getVariables()[0].getInitializer()); + } + } + + highlightOccurences(project, editor, toHighight.toArray(new JSExpression[toHighight.size()])); + } + else if (!replacedOriginal) { + expression.replace(refExpr); + } + } + catch (IncorrectOperationException e) { + LOG.error(e); + } + } + + @RequiredWriteAction + protected JSVarStatement prepareDeclaration(String varDeclText, BaseIntroduceContext context, Project project) + throws IncorrectOperationException { + JSVarStatement declaration = (JSVarStatement)JSChangeUtil.createStatementFromText( + project, + varDeclText + " = 0" + JSChangeUtil.getSemicolon(project) + ).getPsi(); + declaration.getVariables()[0].getInitializer().replace(context.expression); + return declaration; + } + + protected String getDeclText(S settings) { + return "var " + settings.getVariableName(); + } + + @RequiredWriteAction + @SuppressWarnings("unchecked") + protected T addStatementBefore(T anchorStatement, JSVarStatement declaration) throws IncorrectOperationException { + return (T)((JSStatement)anchorStatement).addStatementBefore(declaration); + } + + @SuppressWarnings("unchecked") + protected T findAnchor(BaseIntroduceContext context, boolean replaceAllOccurences) { + JSStatement anchorStatement = replaceAllOccurences + ? getAnchorToInsert(context.occurences) + : PsiTreeUtil.getParentOfType(context.expression, JSStatement.class); + if (anchorStatement instanceof JSVarStatement varStatement + && varStatement.getParent() instanceof JSStatement statement + && !(statement instanceof JSBlockStatement)) { + anchorStatement = statement; + } + return (T)anchorStatement; + } + + private static ArrayList highlightOccurences(Project project, Editor editor, JSExpression[] occurences) { + HighlightManager highlightManager = HighlightManager.getInstance(project); + ArrayList result = new ArrayList<>(); + highlightManager.addOccurrenceHighlights(editor, occurences, EditorColors.SEARCH_RESULT_ATTRIBUTES, true, result); + return result; + } + + private static JSStatement getAnchorToInsert(JSExpression[] expressions) { + JSElement place = expressions[0]; + next: + do { + JSStatement statement = PsiTreeUtil.getParentOfType(place, JSStatement.class); //this is the first expression textually + LOG.assertTrue(statement != null); + + PsiElement parent = statement.getParent(); + for (JSExpression expression : expressions) { + if (!PsiTreeUtil.isAncestor(parent, expression, true)) { + place = statement; + continue next; + } + } + + return statement; + } + while (true); + } + + protected static JSElement findClassAnchor(PsiElement expression) { + PsiElement nearestParent = PsiTreeUtil.getParentOfType(expression, JSVarStatement.class, JSFunction.class); + while (nearestParent != null) { + PsiElement nextParent = PsiTreeUtil.getParentOfType(nearestParent, JSVarStatement.class, JSFunction.class); + if (nextParent == null) { + break; + } + nearestParent = nextParent; + } + + if (nearestParent != null) { + return (JSElement)nearestParent; + } + + JSElement parent = PsiTreeUtil.getParentOfType(expression, JSFile.class, JSClass.class); + + if (parent instanceof JSFile jsFile && JSResolveUtil.getClassReferenceForXmlFromContext(jsFile) instanceof JSClass jsClass) { + parent = jsClass; + } + + return parent; + } + + @RequiredWriteAction + protected static JSElement addToClassAnchor(JSElement anchorStatement, JSVarStatement declaration) throws IncorrectOperationException { + if (!(anchorStatement instanceof JSClass)) { + JSElement element = findClassAnchor(anchorStatement); + return (JSElement)element.addBefore(declaration, anchorStatement); + } + return (JSElement)anchorStatement.add(declaration); + } + + @Override + @RequiredUIAccess + public void invoke(@Nonnull Project project, @Nonnull PsiElement[] elements, DataContext dataContext) { + throw new RuntimeException("Not implemented"); + } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/JSNamesValidator.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/JSNamesValidator.java index c11d846e..6fed157e 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/JSNamesValidator.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/JSNamesValidator.java @@ -24,37 +24,29 @@ import consulo.language.editor.refactoring.NamesValidator; /** - * Created by IntelliJ IDEA. - * User: Maxim.Mossienko - * Date: Jun 27, 2006 - * Time: 8:28:35 PM - * To change this template use File | Settings | File Templates. + * @author Maxim.Mossienko + * @since 2006-06-27 */ -abstract class JSNamesValidator implements NamesValidator -{ - protected final Lexer myLexer; +abstract class JSNamesValidator implements NamesValidator { + protected final Lexer myLexer; - JSNamesValidator(DialectOptionHolder optionHolder) - { - myLexer = createLexer(optionHolder); - } + JSNamesValidator(DialectOptionHolder optionHolder) { + myLexer = createLexer(optionHolder); + } - protected Lexer createLexer(final DialectOptionHolder optionHolder) - { - return new JSFlexAdapter(false, optionHolder); - } + protected Lexer createLexer(DialectOptionHolder optionHolder) { + return new JSFlexAdapter(false, optionHolder); + } - @Override - public synchronized boolean isKeyword(String name, Project project) - { - myLexer.start(name, 0, name.length(), 0); - return JSTokenTypes.KEYWORDS.contains(myLexer.getTokenType()) && myLexer.getTokenEnd() == name.length(); - } + @Override + public synchronized boolean isKeyword(String name, Project project) { + myLexer.start(name, 0, name.length(), 0); + return JSTokenTypes.KEYWORDS.contains(myLexer.getTokenType()) && myLexer.getTokenEnd() == name.length(); + } - @Override - public synchronized boolean isIdentifier(String name, Project project) - { - myLexer.start(name, 0, name.length(), 0); - return JSTokenTypes.IDENTIFIER_TOKENS_SET.contains(myLexer.getTokenType()) && myLexer.getTokenEnd() == name.length(); - } + @Override + public synchronized boolean isIdentifier(String name, Project project) { + myLexer.start(name, 0, name.length(), 0); + return JSTokenTypes.IDENTIFIER_TOKENS_SET.contains(myLexer.getTokenType()) && myLexer.getTokenEnd() == name.length(); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/JavascriptRefactoringSupportProvider.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/JavascriptRefactoringSupportProvider.java index 71eca1dd..8676d7ec 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/JavascriptRefactoringSupportProvider.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/JavascriptRefactoringSupportProvider.java @@ -24,6 +24,7 @@ import com.intellij.lang.javascript.impl.refactoring.introduceField.JSIntroduceFieldHandler; import com.intellij.lang.javascript.impl.refactoring.introduceVariable.JSIntroduceVariableHandler; import com.intellij.lang.javascript.psi.*; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; import consulo.javascript.language.JavaScriptLanguage; import consulo.language.Language; @@ -31,58 +32,53 @@ import consulo.language.editor.refactoring.action.RefactoringActionHandler; import consulo.language.psi.PsiElement; import consulo.language.psi.scope.LocalSearchScope; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; @ExtensionImpl -public class JavascriptRefactoringSupportProvider extends RefactoringSupportProvider -{ - @Override - public boolean isSafeDeleteAvailable(PsiElement element) - { - boolean simpleElement = element instanceof JSFunction || element instanceof JSVariable || element instanceof JSDefinitionExpression || - element instanceof JSProperty || element instanceof JSClass; +public class JavascriptRefactoringSupportProvider extends RefactoringSupportProvider { + @Override + @RequiredReadAction + public boolean isSafeDeleteAvailable(PsiElement element) { + boolean simpleElement = element instanceof JSFunction + || element instanceof JSVariable + || element instanceof JSDefinitionExpression + || element instanceof JSProperty + || element instanceof JSClass; - return simpleElement && ((JSNamedElement) element).getName() != null; - } + return simpleElement && ((JSNamedElement)element).getName() != null; + } - @Override - @Nullable - public RefactoringActionHandler getIntroduceVariableHandler() - { - return new JSIntroduceVariableHandler(); - } + @Override + @Nullable + public RefactoringActionHandler getIntroduceVariableHandler() { + return new JSIntroduceVariableHandler(); + } - @Override - @Nullable - public RefactoringActionHandler getExtractMethodHandler() - { - return new JSExtractFunctionHandler(); - } + @Override + @Nullable + public RefactoringActionHandler getExtractMethodHandler() { + return new JSExtractFunctionHandler(); + } - @Override - public RefactoringActionHandler getIntroduceConstantHandler() - { - return new JSIntroduceConstantHandler(); - } + @Override + public RefactoringActionHandler getIntroduceConstantHandler() { + return new JSIntroduceConstantHandler(); + } - @Override - public RefactoringActionHandler getIntroduceFieldHandler() - { - return new JSIntroduceFieldHandler(); - } + @Override + public RefactoringActionHandler getIntroduceFieldHandler() { + return new JSIntroduceFieldHandler(); + } - @Override - public boolean isInplaceRenameAvailable(PsiElement element, PsiElement context) - { - return element instanceof JSNamedElement && element.getUseScope() instanceof LocalSearchScope; - } + @Override + public boolean isInplaceRenameAvailable(PsiElement element, PsiElement context) { + return element instanceof JSNamedElement namedElement && namedElement.getUseScope() instanceof LocalSearchScope; + } - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/extractMethod/JSExtractFunctionDialog.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/extractMethod/JSExtractFunctionDialog.java index 79cb490a..775bb5f7 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/extractMethod/JSExtractFunctionDialog.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/extractMethod/JSExtractFunctionDialog.java @@ -16,40 +16,33 @@ package com.intellij.lang.javascript.impl.refactoring.extractMethod; -import javax.swing.JComponent; -import javax.swing.JPanel; -import javax.swing.JTextField; - -import consulo.javascript.language.JavaScriptBundle; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.ui.ex.awt.DialogWrapper; +import javax.swing.*; + /** * @author Maxim.Mossienko - * Date: Aug 9, 2008 - * Time: 9:22:10 AM + * @since 2008-08-09 */ -public class JSExtractFunctionDialog extends DialogWrapper implements JSExtractFunctionSettings -{ - private JPanel myPanel; - private JTextField myFunctionName; - - JSExtractFunctionDialog() - { - super(false); - - setTitle(JavaScriptBundle.message("javascript.extract.method.title")); - init(); - } - - @Override - protected JComponent createCenterPanel() - { - return myPanel; - } - - @Override - public String getMethodName() - { - return myFunctionName.getText(); - } +public class JSExtractFunctionDialog extends DialogWrapper implements JSExtractFunctionSettings { + private JPanel myPanel; + private JTextField myFunctionName; + + JSExtractFunctionDialog() { + super(false); + + setTitle(JavaScriptLocalize.javascriptExtractMethodTitle()); + init(); + } + + @Override + protected JComponent createCenterPanel() { + return myPanel; + } + + @Override + public String getMethodName() { + return myFunctionName.getText(); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/extractMethod/JSExtractFunctionHandler.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/extractMethod/JSExtractFunctionHandler.java index 27a896ea..bf35c2ef 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/extractMethod/JSExtractFunctionHandler.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/extractMethod/JSExtractFunctionHandler.java @@ -16,83 +16,62 @@ package com.intellij.lang.javascript.impl.refactoring.extractMethod; -import javax.annotation.Nonnull; - -import consulo.javascript.language.JavaScriptBundle; +import consulo.codeEditor.Editor; +import consulo.dataContext.DataContext; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.editor.refactoring.action.RefactoringActionHandler; +import consulo.language.editor.refactoring.util.CommonRefactoringUtil; +import consulo.language.psi.PsiElement; import consulo.language.psi.PsiFile; -import consulo.undoRedo.CommandProcessor; -import consulo.codeEditor.Editor; import consulo.project.Project; +import consulo.ui.annotation.RequiredUIAccess; import consulo.ui.ex.awt.DialogWrapper; -import consulo.language.psi.PsiElement; -import consulo.language.editor.refactoring.util.CommonRefactoringUtil; -import consulo.application.ApplicationManager; -import consulo.dataContext.DataContext; +import consulo.undoRedo.CommandProcessor; +import jakarta.annotation.Nonnull; /** * @author Maxim.Mossienko - * Date: May 29, 2008 - * Time: 8:19:48 PM + * @since 2008-05-29 */ -public class JSExtractFunctionHandler implements RefactoringActionHandler -{ - @Override - public void invoke(@Nonnull final Project project, final Editor editor, PsiFile file, DataContext dataContext) - { - if(!editor.getSelectionModel().hasSelection()) - { - editor.getSelectionModel().selectLineAtCaret(); - } - int start = editor.getSelectionModel().getSelectionStart(); - int end = editor.getSelectionModel().getSelectionEnd(); +public class JSExtractFunctionHandler implements RefactoringActionHandler { + @Override + @RequiredUIAccess + public void invoke(@Nonnull Project project, Editor editor, PsiFile file, DataContext dataContext) { + if (!editor.getSelectionModel().hasSelection()) { + editor.getSelectionModel().selectLineAtCaret(); + } - if(!CommonRefactoringUtil.checkReadOnlyStatus(project, file)) - { - return; - } + if (!CommonRefactoringUtil.checkReadOnlyStatus(project, file)) { + return; + } - final JSExtractFunctionSettings settings = getSettings(project, editor); - if(settings == null) - { - return; - } + JSExtractFunctionSettings settings = getSettings(project, editor); + if (settings == null) { + return; + } - CommandProcessor.getInstance().executeCommand(project, new Runnable() - { - @Override - public void run() - { - ApplicationManager.getApplication().runWriteAction(new Runnable() - { - @Override - public void run() - { - doRefactoring(project, editor, settings); - } - }); - } - }, JavaScriptBundle.message("javascript.extract.method.title"), null); - } + CommandProcessor.getInstance().newCommand() + .project(project) + .name(JavaScriptLocalize.javascriptExtractMethodTitle()) + .run(() -> project.getApplication().runWriteAction(() -> doRefactoring(project, editor, settings))); + } - protected JSExtractFunctionSettings getSettings(final Project project, final Editor editor) - { - final JSExtractFunctionDialog dialog = new JSExtractFunctionDialog(); - dialog.show(); - if(dialog.getExitCode() != DialogWrapper.OK_EXIT_CODE) - { - return null; - } - return dialog; - } + @RequiredUIAccess + protected JSExtractFunctionSettings getSettings(Project project, Editor editor) { + JSExtractFunctionDialog dialog = new JSExtractFunctionDialog(); + dialog.show(); + if (dialog.getExitCode() != DialogWrapper.OK_EXIT_CODE) { + return null; + } + return dialog; + } - private void doRefactoring(final Project project, final Editor editor, final JSExtractFunctionSettings settings) - { - } + private void doRefactoring(Project project, Editor editor, JSExtractFunctionSettings settings) { + } - @Override - public void invoke(@Nonnull final Project project, @Nonnull final PsiElement[] elements, final DataContext dataContext) - { - throw new UnsupportedOperationException(); - } + @Override + @RequiredUIAccess + public void invoke(@Nonnull Project project, @Nonnull PsiElement[] elements, DataContext dataContext) { + throw new UnsupportedOperationException(); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/extractMethod/JSExtractFunctionSettings.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/extractMethod/JSExtractFunctionSettings.java index 510cc659..65d507ff 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/extractMethod/JSExtractFunctionSettings.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/extractMethod/JSExtractFunctionSettings.java @@ -19,7 +19,6 @@ /** * @author ven */ -public interface JSExtractFunctionSettings -{ - String getMethodName(); +public interface JSExtractFunctionSettings { + String getMethodName(); } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceConstant/JSIntroduceConstant.form b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceConstant/JSIntroduceConstant.form index 163b8f68..4f561f5f 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceConstant/JSIntroduceConstant.form +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceConstant/JSIntroduceConstant.form @@ -15,7 +15,7 @@ - + diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceConstant/JSIntroduceConstantDialog.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceConstant/JSIntroduceConstantDialog.java index 0925a1d5..685f703e 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceConstant/JSIntroduceConstantDialog.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceConstant/JSIntroduceConstantDialog.java @@ -16,90 +16,77 @@ package com.intellij.lang.javascript.impl.refactoring.introduceConstant; -import javax.swing.JCheckBox; -import javax.swing.JComboBox; -import javax.swing.JPanel; -import javax.swing.JRadioButton; -import javax.swing.JTextField; - -import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.impl.refactoring.JSBaseClassBasedIntroduceDialog; +import com.intellij.lang.javascript.psi.JSExpression; +import consulo.annotation.access.RequiredReadAction; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.project.Project; +import javax.swing.*; + /** * @author Maxim.Mossienko - * Date: Jul 24, 2008 - * Time: 8:48:34 PM + * @since 2008-07-24 */ -class JSIntroduceConstantDialog extends JSBaseClassBasedIntroduceDialog implements JSIntroduceConstantSettings -{ - private JTextField myNameField; - private JCheckBox myReplaceAllCheckBox; - private JPanel myPanel; - private JRadioButton myPrivate; - private JRadioButton myProtected; - private JRadioButton myPackageLocal; - private JRadioButton myPublic; - private JComboBox myVarType; +class JSIntroduceConstantDialog extends JSBaseClassBasedIntroduceDialog implements JSIntroduceConstantSettings { + private JTextField myNameField; + private JCheckBox myReplaceAllCheckBox; + private JPanel myPanel; + private JRadioButton myPrivate; + private JRadioButton myProtected; + private JRadioButton myPackageLocal; + private JRadioButton myPublic; + private JComboBox myVarType; - protected JSIntroduceConstantDialog(final Project project, final JSExpression[] occurences, final JSExpression mainOccurence) - { - super(project, occurences, mainOccurence, "javascript.introduce.constant.title"); + protected JSIntroduceConstantDialog(Project project, JSExpression[] occurences, JSExpression mainOccurence) { + super(project, occurences, mainOccurence, JavaScriptLocalize.javascriptIntroduceConstantTitle()); - doInit(); - } + doInit(); + } - @Override - protected JRadioButton getPrivateRadioButton() - { - return myPrivate; - } + @Override + protected JRadioButton getPrivateRadioButton() { + return myPrivate; + } - @Override - protected JRadioButton getPublicRadioButton() - { - return myPublic; - } + @Override + protected JRadioButton getPublicRadioButton() { + return myPublic; + } - @Override - protected JRadioButton getProtectedRadioButton() - { - return myProtected; - } + @Override + protected JRadioButton getProtectedRadioButton() { + return myProtected; + } - @Override - protected JRadioButton getPackageLocalRadioButton() - { - return myPackageLocal; - } + @Override + protected JRadioButton getPackageLocalRadioButton() { + return myPackageLocal; + } - @Override - protected JTextField getNameField() - { - return myNameField; - } + @Override + protected JTextField getNameField() { + return myNameField; + } - @Override - protected JPanel getPanel() - { - return myPanel; - } + @Override + protected JPanel getPanel() { + return myPanel; + } - @Override - protected JCheckBox getReplaceAllCheckBox() - { - return myReplaceAllCheckBox; - } + @Override + protected JCheckBox getReplaceAllCheckBox() { + return myReplaceAllCheckBox; + } - @Override - public JComboBox getVarTypeField() - { - return myVarType; - } + @Override + public JComboBox getVarTypeField() { + return myVarType; + } - @Override - protected String suggestCandidateName(final JSExpression mainOccurence) - { - return super.suggestCandidateName(mainOccurence).toUpperCase(); - } + @Override + @RequiredReadAction + protected String suggestCandidateName(JSExpression mainOccurrence) { + return super.suggestCandidateName(mainOccurrence).toUpperCase(); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceConstant/JSIntroduceConstantHandler.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceConstant/JSIntroduceConstantHandler.java index 04074409..f5a2dceb 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceConstant/JSIntroduceConstantHandler.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceConstant/JSIntroduceConstantHandler.java @@ -16,124 +16,121 @@ package com.intellij.lang.javascript.impl.refactoring.introduceConstant; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.JavaScriptSupportLoader; -import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.impl.refactoring.JSBaseIntroduceHandler; +import com.intellij.lang.javascript.psi.*; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.codeEditor.Editor; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.editor.refactoring.util.CommonRefactoringUtil; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiFile; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; import consulo.project.Project; -import consulo.util.lang.ref.Ref; -import org.jetbrains.annotations.NonNls; +import consulo.ui.annotation.RequiredUIAccess; +import consulo.util.lang.ref.SimpleReference; +import jakarta.annotation.Nonnull; /** * @author Maxim.Mossienko - * Date: May 29, 2008 - * Time: 8:20:03 PM + * @since 2008-05-29 */ -public class JSIntroduceConstantHandler extends JSBaseIntroduceHandler -{ - @Override - protected String getRefactoringName() - { - return JavaScriptBundle.message("javascript.introduce.constant.title"); - } +public class JSIntroduceConstantHandler extends JSBaseIntroduceHandler { + @Override + protected String getRefactoringName() { + return JavaScriptLocalize.javascriptIntroduceConstantTitle().get(); + } - @Override - protected String getCannotIntroduceMessagePropertyKey() - { - return "javascript.introduce.constant.error.no.expression.selected"; - } + @Override + protected LocalizeValue getCannotIntroduceMessage() { + return JavaScriptLocalize.javascriptIntroduceConstantErrorNoExpressionSelected(); + } - @Override - protected JSIntroduceConstantDialog createDialog(final Project project, final JSExpression expression, final JSExpression[] occurrences) - { - return new JSIntroduceConstantDialog(project, occurrences, expression); - } + @Override + protected JSIntroduceConstantDialog createDialog(Project project, JSExpression expression, JSExpression[] occurrences) { + return new JSIntroduceConstantDialog(project, occurrences, expression); + } - @Override - protected String getDeclText(final JSIntroduceConstantSettings settings) - { - @NonNls String baseDeclText = "static const " + settings.getVariableName(); - final JSAttributeList.AccessType type = settings.getAccessType(); - if(type != JSAttributeList.AccessType.PACKAGE_LOCAL) - { - baseDeclText = type.toString().toLowerCase() + " " + baseDeclText; - } + @Override + protected String getDeclText(JSIntroduceConstantSettings settings) { + String baseDeclText = "static const " + settings.getVariableName(); + JSAttributeList.AccessType type = settings.getAccessType(); + if (type != JSAttributeList.AccessType.PACKAGE_LOCAL) { + baseDeclText = type.toString().toLowerCase() + " " + baseDeclText; + } - return baseDeclText; - } + return baseDeclText; + } - @Override - protected JSElement findAnchor(final BaseIntroduceContext context, final boolean replaceAllOccurences) - { - return findClassAnchor(context.expression); - } + @Override + protected JSElement findAnchor(BaseIntroduceContext context, boolean replaceAllOccurences) { + return findClassAnchor(context.expression); + } - @Override - protected JSElement addStatementBefore(final JSElement anchorStatement, final JSVarStatement declaration) throws IncorrectOperationException - { - return addToClassAnchor(anchorStatement, declaration); - } + @Override + @RequiredWriteAction + protected JSElement addStatementBefore(JSElement anchorStatement, JSVarStatement declaration) throws IncorrectOperationException { + return addToClassAnchor(anchorStatement, declaration); + } - @Override - protected JSExpression findIntroducedExpression(final PsiFile file, final int start, final int end, Editor editor) - { - if(file.getLanguage() != JavaScriptSupportLoader.ECMA_SCRIPT_L4) - { - CommonRefactoringUtil.showErrorHint(file.getProject(), editor, JavaScriptBundle.message("javascript.introduce.constant.error.not.available.in.javascript" + - ".code"), getRefactoringName(), null); - return null; - } + @Override + @RequiredUIAccess + protected JSExpression findIntroducedExpression(PsiFile file, int start, int end, Editor editor) { + if (file.getLanguage() != JavaScriptSupportLoader.ECMA_SCRIPT_L4) { + CommonRefactoringUtil.showErrorHint( + file.getProject(), + editor, + JavaScriptLocalize.javascriptIntroduceConstantErrorNotAvailableInJavascriptCode().get(), + getRefactoringName(), + null + ); + return null; + } - final JSExpression expression = super.findIntroducedExpression(file, start, end, editor); - if(expression == null) - { - return null; - } + JSExpression expression = super.findIntroducedExpression(file, start, end, editor); + if (expression == null) { + return null; + } - final Ref hasAccesibilityProblem = new Ref(); - expression.accept(new JSElementVisitor() - { - @Override - public void visitJSReferenceExpression(final JSReferenceExpression node) - { - if(node.getQualifier() == null) - { - final PsiElement element = node.resolve(); + final SimpleReference hasAccesibilityProblem = new SimpleReference<>(); + expression.accept(new JSElementVisitor() { + @Override + @RequiredReadAction + public void visitJSReferenceExpression(@Nonnull JSReferenceExpression node) { + if (node.getQualifier() == null) { + PsiElement element = node.resolve(); - if(element instanceof JSAttributeListOwner && !(element instanceof JSClass)) - { - final JSAttributeList attributeList = ((JSAttributeListOwner) element).getAttributeList(); - if(attributeList == null || !attributeList.hasModifier(JSAttributeList.ModifierType.STATIC)) - { - hasAccesibilityProblem.set(Boolean.TRUE); - } - } - else if(element == null) - { - hasAccesibilityProblem.set(Boolean.TRUE); - } - } - super.visitJSReferenceExpression(node); - } + if (element instanceof JSAttributeListOwner attributeListOwner && !(element instanceof JSClass)) { + JSAttributeList attributeList = attributeListOwner.getAttributeList(); + if (attributeList == null || !attributeList.hasModifier(JSAttributeList.ModifierType.STATIC)) { + hasAccesibilityProblem.set(Boolean.TRUE); + } + } + else if (element == null) { + hasAccesibilityProblem.set(Boolean.TRUE); + } + } + super.visitJSReferenceExpression(node); + } - @Override - public void visitJSElement(final JSElement node) - { - node.acceptChildren(this); - } - }); + @Override + public void visitJSElement(@Nonnull JSElement node) { + node.acceptChildren(this); + } + }); - if(Boolean.TRUE.equals(hasAccesibilityProblem.get())) - { - CommonRefactoringUtil.showErrorHint(file.getProject(), editor, JavaScriptBundle.message("javascript.introduce.constant.error.not.constant.expression" + - ".selected"), getRefactoringName(), null); - return null; - } - return expression; - } + if (Boolean.TRUE.equals(hasAccesibilityProblem.get())) { + CommonRefactoringUtil.showErrorHint( + file.getProject(), + editor, + JavaScriptLocalize.javascriptIntroduceConstantErrorNotConstantExpressionSelected().get(), + getRefactoringName(), + null + ); + return null; + } + return expression; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceConstant/JSIntroduceConstantSettings.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceConstant/JSIntroduceConstantSettings.java index 90e29353..90fbf723 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceConstant/JSIntroduceConstantSettings.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceConstant/JSIntroduceConstantSettings.java @@ -22,7 +22,6 @@ /** * @author ven */ -public interface JSIntroduceConstantSettings extends BaseIntroduceSettings -{ - JSAttributeList.AccessType getAccessType(); +public interface JSIntroduceConstantSettings extends BaseIntroduceSettings { + JSAttributeList.AccessType getAccessType(); } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceField/JSIntroduceField.form b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceField/JSIntroduceField.form index 8f07f9cb..8084f9b3 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceField/JSIntroduceField.form +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceField/JSIntroduceField.form @@ -130,7 +130,7 @@ - + diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceField/JSIntroduceFieldDialog.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceField/JSIntroduceFieldDialog.java index 60b3aa22..80440c96 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceField/JSIntroduceFieldDialog.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceField/JSIntroduceFieldDialog.java @@ -17,181 +17,159 @@ package com.intellij.lang.javascript.impl.refactoring.introduceField; import com.intellij.lang.javascript.formatter.JSCodeStyleSettings; -import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.impl.refactoring.JSBaseClassBasedIntroduceDialog; +import com.intellij.lang.javascript.psi.*; +import consulo.annotation.access.RequiredReadAction; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.codeStyle.CodeStyleSettingsManager; import consulo.language.psi.PsiElement; import consulo.language.psi.ResolveResult; import consulo.project.Project; +import consulo.ui.annotation.RequiredUIAccess; import consulo.util.lang.StringUtil; -import consulo.util.lang.ref.Ref; +import consulo.util.lang.ref.SimpleReference; +import jakarta.annotation.Nonnull; import javax.swing.*; /** * @author Maxim.Mossienko - * Date: Jul 24, 2008 - * Time: 8:46:13 PM + * @author 2008-07-24 */ -class JSIntroduceFieldDialog extends JSBaseClassBasedIntroduceDialog implements JSIntroduceFieldSettings -{ - private JCheckBox myReplaceAllCheckBox; - private JTextField myNameField; - private JPanel myPanel; - private JRadioButton myPublic; - private JRadioButton myPackageLocal; - private JRadioButton myProtected; - private JRadioButton myPrivate; - private JComboBox myVarType; - - private JRadioButton myFieldDeclaration; - private JRadioButton myCurrentMethod; - private JRadioButton myConstructor; - - private static InitializationPlace lastInitializationPlace = InitializationPlace.FieldDeclaration; - - public JSIntroduceFieldDialog(final Project project, final JSExpression[] occurrences, final JSExpression expression) - { - super(project, occurrences, expression, "javascript.introduce.field.title"); - doInit(); - } - - @Override - protected void doInit() - { - super.doInit(); - - final Ref localContextDependent = new Ref(); - myMainOccurence.accept(new JSElementVisitor() - { - @Override - public void visitJSReferenceExpression(final JSReferenceExpression node) - { - if(node.getQualifier() == null) - { - final ResolveResult[] results = node.multiResolve(true); - if(results.length == 0) - { - localContextDependent.set(Boolean.TRUE); - } - else - { - final PsiElement element = results[0].getElement(); - if(element instanceof JSVariable && !(element.getParent().getParent() instanceof JSClass)) - { - localContextDependent.set(Boolean.TRUE); - } - } - } - super.visitJSReferenceExpression(node); - } - - @Override - public void visitJSElement(final JSElement node) - { - node.acceptChildren(this); - } - }); - - if(Boolean.TRUE.equals(localContextDependent.get())) - { - myConstructor.setEnabled(false); - myFieldDeclaration.setEnabled(false); - myCurrentMethod.setSelected(true); - } - else - { - if(lastInitializationPlace == InitializationPlace.Constructor) - { - myConstructor.setSelected(true); - } - else if(lastInitializationPlace == InitializationPlace.CurrentMethod) - { - myCurrentMethod.setSelected(true); - } - else - { - myFieldDeclaration.setSelected(true); - } - } - } - - @Override - protected JTextField getNameField() - { - return myNameField; - } - - @Override - protected JPanel getPanel() - { - return myPanel; - } - - @Override - protected JCheckBox getReplaceAllCheckBox() - { - return myReplaceAllCheckBox; - } - - @Override - public JComboBox getVarTypeField() - { - return myVarType; - } - - @Override - protected JRadioButton getPrivateRadioButton() - { - return myPrivate; - } - - @Override - protected JRadioButton getPublicRadioButton() - { - return myPublic; - } - - @Override - protected JRadioButton getProtectedRadioButton() - { - return myProtected; - } - - @Override - protected JRadioButton getPackageLocalRadioButton() - { - return myPackageLocal; - } - - @Override - public InitializationPlace getInitializationPlace() - { - return myFieldDeclaration.isSelected() ? InitializationPlace.FieldDeclaration : myCurrentMethod.isSelected() ? InitializationPlace.CurrentMethod : - InitializationPlace.Constructor; - } - - @Override - protected void doOKAction() - { - super.doOKAction(); - lastInitializationPlace = getInitializationPlace(); - } - - @Override - protected String suggestCandidateName(final JSExpression mainOccurence) - { - final String s = super.suggestCandidateName(mainOccurence); - final JSCodeStyleSettings jsCodeStyleSettings = CodeStyleSettingsManager.getSettings(mainOccurence.getProject()).getCustomSettings - (JSCodeStyleSettings.class); - if(jsCodeStyleSettings.FIELD_PREFIX.length() > 0) - { - return jsCodeStyleSettings.FIELD_PREFIX + s; - } - if(s.length() > 0) - { - return StringUtil.decapitalize(s); - } - return s; - } +class JSIntroduceFieldDialog extends JSBaseClassBasedIntroduceDialog implements JSIntroduceFieldSettings { + private JCheckBox myReplaceAllCheckBox; + private JTextField myNameField; + private JPanel myPanel; + private JRadioButton myPublic; + private JRadioButton myPackageLocal; + private JRadioButton myProtected; + private JRadioButton myPrivate; + private JComboBox myVarType; + + private JRadioButton myFieldDeclaration; + private JRadioButton myCurrentMethod; + private JRadioButton myConstructor; + + private static InitializationPlace lastInitializationPlace = InitializationPlace.FieldDeclaration; + + @RequiredUIAccess + public JSIntroduceFieldDialog(Project project, JSExpression[] occurrences, JSExpression expression) { + super(project, occurrences, expression, JavaScriptLocalize.javascriptIntroduceFieldTitle()); + doInit(); + } + + @Override + @RequiredReadAction + protected void doInit() { + super.doInit(); + + final SimpleReference localContextDependent = new SimpleReference<>(); + myMainOccurrence.accept(new JSElementVisitor() { + @Override + @RequiredReadAction + public void visitJSReferenceExpression(@Nonnull JSReferenceExpression node) { + if (node.getQualifier() == null) { + ResolveResult[] results = node.multiResolve(true); + if (results.length == 0) { + localContextDependent.set(Boolean.TRUE); + } + else { + PsiElement element = results[0].getElement(); + if (element instanceof JSVariable variable && !(variable.getParent().getParent() instanceof JSClass)) { + localContextDependent.set(Boolean.TRUE); + } + } + } + super.visitJSReferenceExpression(node); + } + + @Override + public void visitJSElement(@Nonnull JSElement node) { + node.acceptChildren(this); + } + }); + + if (Boolean.TRUE.equals(localContextDependent.get())) { + myConstructor.setEnabled(false); + myFieldDeclaration.setEnabled(false); + myCurrentMethod.setSelected(true); + } + else if (lastInitializationPlace == InitializationPlace.Constructor) { + myConstructor.setSelected(true); + } + else if (lastInitializationPlace == InitializationPlace.CurrentMethod) { + myCurrentMethod.setSelected(true); + } + else { + myFieldDeclaration.setSelected(true); + } + } + + @Override + protected JTextField getNameField() { + return myNameField; + } + + @Override + protected JPanel getPanel() { + return myPanel; + } + + @Override + protected JCheckBox getReplaceAllCheckBox() { + return myReplaceAllCheckBox; + } + + @Override + public JComboBox getVarTypeField() { + return myVarType; + } + + @Override + protected JRadioButton getPrivateRadioButton() { + return myPrivate; + } + + @Override + protected JRadioButton getPublicRadioButton() { + return myPublic; + } + + @Override + protected JRadioButton getProtectedRadioButton() { + return myProtected; + } + + @Override + protected JRadioButton getPackageLocalRadioButton() { + return myPackageLocal; + } + + @Override + public InitializationPlace getInitializationPlace() { + return myFieldDeclaration.isSelected() ? InitializationPlace.FieldDeclaration : myCurrentMethod.isSelected() ? InitializationPlace.CurrentMethod : + InitializationPlace.Constructor; + } + + @Override + @RequiredUIAccess + protected void doOKAction() { + super.doOKAction(); + lastInitializationPlace = getInitializationPlace(); + } + + @Override + @RequiredReadAction + protected String suggestCandidateName(JSExpression mainOccurrence) { + String s = super.suggestCandidateName(mainOccurrence); + JSCodeStyleSettings jsCodeStyleSettings = CodeStyleSettingsManager.getSettings(mainOccurrence.getProject()) + .getCustomSettings(JSCodeStyleSettings.class); + if (jsCodeStyleSettings.FIELD_PREFIX.length() > 0) { + return jsCodeStyleSettings.FIELD_PREFIX + s; + } + if (s.length() > 0) { + return StringUtil.decapitalize(s); + } + return s; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceField/JSIntroduceFieldHandler.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceField/JSIntroduceFieldHandler.java index d1816c94..e6d1aec1 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceField/JSIntroduceFieldHandler.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceField/JSIntroduceFieldHandler.java @@ -16,136 +16,133 @@ package com.intellij.lang.javascript.impl.refactoring.introduceField; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.JavaScriptSupportLoader; import com.intellij.lang.javascript.flex.XmlBackedJSClassImpl; +import com.intellij.lang.javascript.impl.refactoring.JSBaseIntroduceHandler; import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.impl.JSChangeUtil; -import com.intellij.lang.javascript.impl.refactoring.JSBaseIntroduceHandler; +import consulo.annotation.access.RequiredWriteAction; import consulo.codeEditor.Editor; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.codeStyle.CodeStyleManager; import consulo.language.editor.refactoring.util.CommonRefactoringUtil; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiFile; import consulo.language.psi.util.PsiTreeUtil; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; import consulo.project.Project; +import consulo.ui.annotation.RequiredUIAccess; import consulo.xml.psi.xml.XmlFile; -import org.jetbrains.annotations.NonNls; /** * @author Maxim.Mossienko - * Date: May 29, 2008 - * Time: 8:20:03 PM + * @since 2008-05-29 */ -public class JSIntroduceFieldHandler extends JSBaseIntroduceHandler -{ - @Override - protected String getRefactoringName() - { - return JavaScriptBundle.message("javascript.introduce.field.title"); - } - - @Override - protected String getCannotIntroduceMessagePropertyKey() - { - return "javascript.introduce.field.error.no.expression.selected"; - } - - @Override - protected JSIntroduceFieldDialog createDialog(final Project project, final JSExpression expression, final JSExpression[] occurrences) - { - return new JSIntroduceFieldDialog(project, occurrences, expression); - } - - @Override - protected JSElement findAnchor(final BaseIntroduceContext context, final boolean replaceAllOccurences) - { - return findClassAnchor(context.expression); - } - - @Override - protected JSElement addStatementBefore(final JSElement anchorStatement, final JSVarStatement declaration) throws IncorrectOperationException - { - return addToClassAnchor(anchorStatement, declaration); - } - - @Override - protected String getDeclText(final JSIntroduceFieldSettings settings) - { - @NonNls String baseDeclText = super.getDeclText(settings); - final JSAttributeList.AccessType type = settings.getAccessType(); - if(type != JSAttributeList.AccessType.PACKAGE_LOCAL) - { - baseDeclText = type.toString().toLowerCase() + " " + baseDeclText; - } - - return baseDeclText; - } - - @Override - protected JSExpression findIntroducedExpression(final PsiFile file, final int start, final int end, Editor editor) - { - if(file.getLanguage() != JavaScriptSupportLoader.ECMA_SCRIPT_L4) - { - CommonRefactoringUtil.showErrorHint(file.getProject(), editor, JavaScriptBundle.message("javascript.introduce.field.error.not.available.in.javascript" + - ".code"), getRefactoringName(), null); - return null; - } - - return super.findIntroducedExpression(file, start, end, editor); - } - - @Override - protected JSVarStatement prepareDeclaration(final String varDeclText, BaseIntroduceContext context, final Project project) throws IncorrectOperationException - { - final JSIntroduceFieldSettings.InitializationPlace place = context.settings.getInitializationPlace(); - - if(place == JSIntroduceFieldSettings.InitializationPlace.FieldDeclaration) - { - return super.prepareDeclaration(varDeclText, context, project); - } - else - { - final String assignmentText = context.settings.getVariableName() + "=" + context.expression.getText() + JSChangeUtil.getSemicolon(project); - final PsiElement psiToInsert = JSChangeUtil.createStatementFromText(project, assignmentText).getPsi(); - - if(place == JSIntroduceFieldSettings.InitializationPlace.CurrentMethod) - { - final JSElement element = super.findAnchor(context, context.settings.isReplaceAllOccurences()); - final PsiElement parent = element.getParent(); - final PsiElement addedElement = parent.addBefore(psiToInsert, element); - CodeStyleManager.getInstance(project).reformatNewlyAddedElement(parent.getNode(), addedElement.getNode()); - } - else - { - PsiElement parent = PsiTreeUtil.getParentOfType(context.expression, JSClass.class, JSFile.class); - if(parent instanceof JSFile) - { - final PsiFile containingFile = parent.getContext().getContainingFile(); - assert containingFile instanceof XmlFile; - parent = XmlBackedJSClassImpl.getXmlBackedClass((XmlFile) containingFile); - } - - assert parent instanceof JSClass; - final JSClass clazz = (JSClass) parent; - JSFunction fun = clazz.findFunctionByName(clazz.getName()); - - if(fun == null) - { - @NonNls String constr = "function " + clazz.getName() + "() {}"; - if(clazz.getAttributeList() != null && clazz.getAttributeList().getAccessType() == JSAttributeList.AccessType.PUBLIC) - { - constr = "public " + constr; - } - - fun = (JSFunction) clazz.add(JSChangeUtil.createJSTreeFromText(project, constr).getPsi()); - } - - fun.getBody()[0].add(psiToInsert); - } - - return (JSVarStatement) JSChangeUtil.createStatementFromText(project, varDeclText + JSChangeUtil.getSemicolon(project)).getPsi(); - } - } +public class JSIntroduceFieldHandler extends JSBaseIntroduceHandler { + @Override + protected String getRefactoringName() { + return JavaScriptLocalize.javascriptIntroduceFieldTitle().get(); + } + + @Override + protected LocalizeValue getCannotIntroduceMessage() { + return JavaScriptLocalize.javascriptIntroduceFieldErrorNoExpressionSelected(); + } + + @Override + @RequiredUIAccess + protected JSIntroduceFieldDialog createDialog(Project project, JSExpression expression, JSExpression[] occurrences) { + return new JSIntroduceFieldDialog(project, occurrences, expression); + } + + @Override + protected JSElement findAnchor(BaseIntroduceContext context, boolean replaceAllOccurences) { + return findClassAnchor(context.expression); + } + + @Override + @RequiredWriteAction + protected JSElement addStatementBefore(JSElement anchorStatement, JSVarStatement declaration) throws IncorrectOperationException { + return addToClassAnchor(anchorStatement, declaration); + } + + @Override + protected String getDeclText(JSIntroduceFieldSettings settings) { + String baseDeclText = super.getDeclText(settings); + JSAttributeList.AccessType type = settings.getAccessType(); + if (type != JSAttributeList.AccessType.PACKAGE_LOCAL) { + baseDeclText = type.toString().toLowerCase() + " " + baseDeclText; + } + + return baseDeclText; + } + + @Override + @RequiredUIAccess + protected JSExpression findIntroducedExpression(PsiFile file, int start, int end, Editor editor) { + if (file.getLanguage() != JavaScriptSupportLoader.ECMA_SCRIPT_L4) { + CommonRefactoringUtil.showErrorHint( + file.getProject(), + editor, + JavaScriptLocalize.javascriptIntroduceFieldErrorNotAvailableInJavascriptCode().get(), + getRefactoringName(), + null + ); + return null; + } + + return super.findIntroducedExpression(file, start, end, editor); + } + + @Override + @RequiredWriteAction + protected JSVarStatement prepareDeclaration( + String varDeclText, + BaseIntroduceContext context, + Project project + ) throws IncorrectOperationException { + JSIntroduceFieldSettings.InitializationPlace place = context.settings.getInitializationPlace(); + + if (place == JSIntroduceFieldSettings.InitializationPlace.FieldDeclaration) { + return super.prepareDeclaration(varDeclText, context, project); + } + else { + String assignmentText = + context.settings.getVariableName() + "=" + context.expression.getText() + JSChangeUtil.getSemicolon(project); + PsiElement psiToInsert = JSChangeUtil.createStatementFromText(project, assignmentText).getPsi(); + + if (place == JSIntroduceFieldSettings.InitializationPlace.CurrentMethod) { + JSElement element = super.findAnchor(context, context.settings.isReplaceAllOccurences()); + PsiElement parent = element.getParent(); + PsiElement addedElement = parent.addBefore(psiToInsert, element); + CodeStyleManager.getInstance(project).reformatNewlyAddedElement(parent.getNode(), addedElement.getNode()); + } + else { + PsiElement parent = PsiTreeUtil.getParentOfType(context.expression, JSClass.class, JSFile.class); + if (parent instanceof JSFile jsFile) { + PsiFile containingFile = jsFile.getContext().getContainingFile(); + assert containingFile instanceof XmlFile; + parent = XmlBackedJSClassImpl.getXmlBackedClass((XmlFile)containingFile); + } + + assert parent instanceof JSClass; + JSClass clazz = (JSClass)parent; + JSFunction fun = clazz.findFunctionByName(clazz.getName()); + + if (fun == null) { + String constr = "function " + clazz.getName() + "() {}"; + if (clazz.getAttributeList() != null && clazz.getAttributeList().getAccessType() == JSAttributeList.AccessType.PUBLIC) { + constr = "public " + constr; + } + + fun = (JSFunction)clazz.add(JSChangeUtil.createJSTreeFromText(project, constr).getPsi()); + } + + fun.getBody()[0].add(psiToInsert); + } + + return (JSVarStatement)JSChangeUtil.createStatementFromText(project, varDeclText + JSChangeUtil.getSemicolon(project)).getPsi(); + } + } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceField/JSIntroduceFieldSettings.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceField/JSIntroduceFieldSettings.java index f86bd5e6..28a31ee1 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceField/JSIntroduceFieldSettings.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceField/JSIntroduceFieldSettings.java @@ -22,14 +22,14 @@ /** * @author ven */ -public interface JSIntroduceFieldSettings extends BaseIntroduceSettings -{ - JSAttributeList.AccessType getAccessType(); +public interface JSIntroduceFieldSettings extends BaseIntroduceSettings { + JSAttributeList.AccessType getAccessType(); - enum InitializationPlace - { - CurrentMethod, FieldDeclaration, Constructor - } + enum InitializationPlace { + CurrentMethod, + FieldDeclaration, + Constructor + } - InitializationPlace getInitializationPlace(); + InitializationPlace getInitializationPlace(); } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceVariable/JSIntroduceVariable.form b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceVariable/JSIntroduceVariable.form index 8d2b3c62..88aa7510 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceVariable/JSIntroduceVariable.form +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceVariable/JSIntroduceVariable.form @@ -15,7 +15,7 @@ - + diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceVariable/JSIntroduceVariableDialog.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceVariable/JSIntroduceVariableDialog.java index a84a9c0e..61eae939 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceVariable/JSIntroduceVariableDialog.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceVariable/JSIntroduceVariableDialog.java @@ -16,103 +16,96 @@ package com.intellij.lang.javascript.impl.refactoring.introduceVariable; -import javax.swing.JCheckBox; -import javax.swing.JComboBox; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JRadioButton; -import javax.swing.JTextField; - -import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.impl.refactoring.JSBaseIntroduceDialog; +import com.intellij.lang.javascript.psi.JSExpression; +import consulo.annotation.access.RequiredReadAction; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.project.Project; +import consulo.ui.annotation.RequiredUIAccess; import consulo.util.lang.StringUtil; +import javax.swing.*; + /** * @author ven */ -public class JSIntroduceVariableDialog extends JSBaseIntroduceDialog implements Settings -{ - private JCheckBox myReplaceAllCheckBox; - private JTextField myNameField; - private JPanel myPanel; - - private JRadioButton myIntroduceLocalVariable; - private JRadioButton myIntroduceConstant; - private JRadioButton myIntroduceVariable; - private JComboBox myVarType; - private JLabel myVariableTypeLabel; - - private static IntroducedVarType ourLastIntroduceType = IntroducedVarType.VAR; - private IntroducedVarType myIntroducedVarType; - - protected JSIntroduceVariableDialog(final Project project, final JSExpression[] occurences, final JSExpression mainOccurence) - { - super(project, occurences, mainOccurence, "javascript.introduce.variable.title"); - - if(ourLastIntroduceType == Settings.IntroducedVarType.CONST) - { - myIntroduceConstant.setSelected(true); - } - else if(ourLastIntroduceType == Settings.IntroducedVarType.LET) - { - myIntroduceLocalVariable.setSelected(true); - } - else if(ourLastIntroduceType == Settings.IntroducedVarType.VAR) - { - myIntroduceVariable.setSelected(true); - } - - doInit(); - } - - @Override - protected JTextField getNameField() - { - return myNameField; - } - - @Override - protected JPanel getPanel() - { - return myPanel; - } - - @Override - protected JCheckBox getReplaceAllCheckBox() - { - return myReplaceAllCheckBox; - } - - @Override - protected void doOKAction() - { - super.doOKAction(); - - if(!isShowing()) - { - myIntroducedVarType = myIntroduceConstant.isSelected() ? Settings.IntroducedVarType.CONST : myIntroduceLocalVariable.isSelected() ? Settings - .IntroducedVarType.LET : myIntroduceVariable.isSelected() ? Settings.IntroducedVarType.VAR : Settings.IntroducedVarType.VAR; - - ourLastIntroduceType = myIntroducedVarType; - } - } - - @Override - public JComboBox getVarTypeField() - { - return myVarType; - } - - @Override - public IntroducedVarType getIntroducedVarType() - { - return myIntroducedVarType; - } - - @Override - protected String suggestCandidateName(final JSExpression mainOccurence) - { - return StringUtil.decapitalize(super.suggestCandidateName(mainOccurence)); - } +public class JSIntroduceVariableDialog extends JSBaseIntroduceDialog implements Settings { + private JCheckBox myReplaceAllCheckBox; + private JTextField myNameField; + private JPanel myPanel; + + private JRadioButton myIntroduceLocalVariable; + private JRadioButton myIntroduceConstant; + private JRadioButton myIntroduceVariable; + private JComboBox myVarType; + private JLabel myVariableTypeLabel; + + private static IntroducedVarType ourLastIntroduceType = IntroducedVarType.VAR; + private IntroducedVarType myIntroducedVarType; + + @RequiredUIAccess + protected JSIntroduceVariableDialog(Project project, JSExpression[] occurences, JSExpression mainOccurence) { + super(project, occurences, mainOccurence, JavaScriptLocalize.javascriptIntroduceVariableTitle()); + + if (ourLastIntroduceType == Settings.IntroducedVarType.CONST) { + myIntroduceConstant.setSelected(true); + } + else if (ourLastIntroduceType == Settings.IntroducedVarType.LET) { + myIntroduceLocalVariable.setSelected(true); + } + else if (ourLastIntroduceType == Settings.IntroducedVarType.VAR) { + myIntroduceVariable.setSelected(true); + } + + doInit(); + } + + @Override + protected JTextField getNameField() { + return myNameField; + } + + @Override + protected JPanel getPanel() { + return myPanel; + } + + @Override + protected JCheckBox getReplaceAllCheckBox() { + return myReplaceAllCheckBox; + } + + @Override + @RequiredUIAccess + protected void doOKAction() { + super.doOKAction(); + + if (!isShowing()) { + myIntroducedVarType = myIntroduceConstant.isSelected() + ? Settings.IntroducedVarType.CONST + : myIntroduceLocalVariable.isSelected() + ? Settings.IntroducedVarType.LET + : myIntroduceVariable.isSelected() + ? Settings.IntroducedVarType.VAR + : Settings.IntroducedVarType.VAR; + + ourLastIntroduceType = myIntroducedVarType; + } + } + + @Override + public JComboBox getVarTypeField() { + return myVarType; + } + + @Override + public IntroducedVarType getIntroducedVarType() { + return myIntroducedVarType; + } + + @Override + @RequiredReadAction + protected String suggestCandidateName(JSExpression mainOccurrence) { + return StringUtil.decapitalize(super.suggestCandidateName(mainOccurrence)); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceVariable/JSIntroduceVariableHandler.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceVariable/JSIntroduceVariableHandler.java index 76a27574..37a1b58d 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceVariable/JSIntroduceVariableHandler.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceVariable/JSIntroduceVariableHandler.java @@ -16,39 +16,36 @@ package com.intellij.lang.javascript.impl.refactoring.introduceVariable; -import consulo.javascript.language.JavaScriptBundle; +import com.intellij.lang.javascript.impl.refactoring.JSBaseIntroduceHandler; import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.JSStatement; -import com.intellij.lang.javascript.impl.refactoring.JSBaseIntroduceHandler; +import consulo.javascript.localize.JavaScriptLocalize; +import consulo.localize.LocalizeValue; import consulo.project.Project; +import consulo.ui.annotation.RequiredUIAccess; /** * @author ven */ -public class JSIntroduceVariableHandler extends JSBaseIntroduceHandler -{ - - @Override - protected String getRefactoringName() - { - return JavaScriptBundle.message("javascript.introduce.variable.title"); - } +public class JSIntroduceVariableHandler extends JSBaseIntroduceHandler { + @Override + protected String getRefactoringName() { + return JavaScriptLocalize.javascriptIntroduceVariableTitle().get(); + } - @Override - protected String getCannotIntroduceMessagePropertyKey() - { - return "javascript.introduce.variable.error.no.expression.selected"; - } + @Override + protected LocalizeValue getCannotIntroduceMessage() { + return JavaScriptLocalize.javascriptIntroduceVariableErrorNoExpressionSelected(); + } - @Override - protected String getDeclText(Settings settings) - { - return settings.getIntroducedVarType().toString().toLowerCase() + " " + settings.getVariableName(); - } + @Override + protected String getDeclText(Settings settings) { + return settings.getIntroducedVarType().toString().toLowerCase() + " " + settings.getVariableName(); + } - @Override - protected JSIntroduceVariableDialog createDialog(final Project project, final JSExpression expression, final JSExpression[] occurrences) - { - return new JSIntroduceVariableDialog(project, occurrences, expression); - } + @Override + @RequiredUIAccess + protected JSIntroduceVariableDialog createDialog(Project project, JSExpression expression, JSExpression[] occurrences) { + return new JSIntroduceVariableDialog(project, occurrences, expression); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceVariable/Settings.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceVariable/Settings.java index 6da63a20..6499fe7f 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceVariable/Settings.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/refactoring/introduceVariable/Settings.java @@ -21,12 +21,12 @@ /** * @author ven */ -public interface Settings extends BaseIntroduceSettings -{ - enum IntroducedVarType - { - VAR, CONST, LET - } +public interface Settings extends BaseIntroduceSettings { + enum IntroducedVarType { + VAR, + CONST, + LET + } - IntroducedVarType getIntroducedVarType(); + IntroducedVarType getIntroducedVarType(); } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/search/JSDeclarationRangeHandler.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/search/JSDeclarationRangeHandler.java index 47cd35ee..315a3711 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/search/JSDeclarationRangeHandler.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/search/JSDeclarationRangeHandler.java @@ -17,38 +17,36 @@ package com.intellij.lang.javascript.impl.search; import com.intellij.lang.javascript.psi.JSNamedElement; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; import consulo.document.util.TextRange; import consulo.language.editor.hint.DeclarationRangeHandler; import consulo.language.psi.PsiElement; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author Maxim.Mossienko - * Date: Apr 28, 2008 - * Time: 8:36:19 PM + * @since 2008-04-28 */ @ExtensionImpl -public class JSDeclarationRangeHandler implements DeclarationRangeHandler -{ - @Nonnull - @Override - public Class getElementClass() - { - return JSNamedElement.class; - } +public class JSDeclarationRangeHandler implements DeclarationRangeHandler { + @Nonnull + @Override + public Class getElementClass() { + return JSNamedElement.class; + } - @Override - @Nonnull - public TextRange getDeclarationRange(@Nonnull JSNamedElement namedElement) - { - final TextRange textRange = namedElement.getTextRange(); - final PsiElement nameIdentifier = namedElement.getNameIdentifier(); - final TextRange nameIdentifierRange = nameIdentifier != null ? nameIdentifier.getTextRange() : null; - int startOffset = nameIdentifierRange != null ? nameIdentifierRange.getStartOffset() : textRange.getStartOffset(); - int endOffset = nameIdentifierRange != null ? nameIdentifierRange.getEndOffset() : textRange.getEndOffset(); + @Nonnull + @Override + @RequiredReadAction + public TextRange getDeclarationRange(@Nonnull JSNamedElement namedElement) { + TextRange textRange = namedElement.getTextRange(); + PsiElement nameIdentifier = namedElement.getNameIdentifier(); + TextRange nameIdentifierRange = nameIdentifier != null ? nameIdentifier.getTextRange() : null; + int startOffset = nameIdentifierRange != null ? nameIdentifierRange.getStartOffset() : textRange.getStartOffset(); + int endOffset = nameIdentifierRange != null ? nameIdentifierRange.getEndOffset() : textRange.getEndOffset(); - return new TextRange(startOffset, endOffset); - } + return new TextRange(startOffset, endOffset); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/search/JSDefinitionsSearchExecutor.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/search/JSDefinitionsSearchExecutor.java index 2f1a8211..018c3cb1 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/search/JSDefinitionsSearchExecutor.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/search/JSDefinitionsSearchExecutor.java @@ -22,118 +22,85 @@ import com.intellij.lang.javascript.psi.JSFunction; import com.intellij.lang.javascript.psi.JSReferenceExpression; import com.intellij.lang.javascript.search.JSClassSearch; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; import consulo.application.util.function.Processor; import consulo.javascript.language.JavaScriptLanguage; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiNamedElement; -import consulo.language.psi.PsiReference; import consulo.language.psi.ResolveResult; import consulo.language.psi.scope.GlobalSearchScope; import consulo.language.psi.search.DefinitionsScopedSearch; import consulo.language.psi.search.DefinitionsScopedSearchExecutor; import consulo.language.psi.search.ReferencesSearch; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; + +import java.util.function.Predicate; /** * @author Maxim.Mossienko - * Date: Apr 28, 2008 - * Time: 8:34:30 PM + * @since 2008-04-28 */ @ExtensionImpl -public class JSDefinitionsSearchExecutor implements DefinitionsScopedSearchExecutor -{ - @Override - public boolean execute(@Nonnull final DefinitionsScopedSearch.SearchParameters parameters, @Nonnull final Processor consumer) - { - final PsiElement sourceElement = parameters.getElement(); - if(sourceElement instanceof PsiNamedElement && sourceElement.getLanguage().isKindOf(JavaScriptLanguage.INSTANCE)) - { - ReferencesSearch.search(sourceElement, GlobalSearchScope.projectScope(sourceElement.getProject())).forEach(new Processor() - { - @Override - public boolean process(final PsiReference t) - { - if(t instanceof JSReferenceExpression) - { - final PsiElement parent = ((JSReferenceExpression) t).getParent(); - final ResolveResult[] resolveResults = ((JSReferenceExpression) t).multiResolve(true); - - for(ResolveResult r : resolveResults) - { - PsiElement psiElement = r.getElement(); - - if(psiElement != null && - !JavaScriptIndex.isFromPredefinedFile(psiElement.getContainingFile()) && - sourceElement != psiElement) - { - if((psiElement instanceof JSFunction) && sourceElement instanceof JSFunction) - { - JSFunction fun = (JSFunction) psiElement; - JSFunction sourceFun = (JSFunction) sourceElement; +public class JSDefinitionsSearchExecutor implements DefinitionsScopedSearchExecutor { + @Override + @RequiredReadAction + public boolean execute( + @Nonnull DefinitionsScopedSearch.SearchParameters parameters, + @Nonnull Predicate consumer + ) { + PsiElement sourceElement = parameters.getElement(); + if (sourceElement instanceof PsiNamedElement namedElement && namedElement.getLanguage().isKindOf(JavaScriptLanguage.INSTANCE)) { + ReferencesSearch.search(sourceElement, GlobalSearchScope.projectScope(sourceElement.getProject())).forEach(t -> { + if (t instanceof JSReferenceExpression refExpr) { + PsiElement parent = refExpr.getParent(); + ResolveResult[] resolveResults = refExpr.multiResolve(true); - if((sourceFun.isGetProperty() && fun.isSetProperty()) || (sourceFun.isSetProperty() && fun.isGetProperty())) - { - return true; - } - } + for (ResolveResult r : resolveResults) { + PsiElement psiElement = r.getElement(); - if((psiElement != sourceElement || !(psiElement instanceof JSClass)) && !consumer.process(psiElement)) - { - return false; - } - } - } + if (psiElement != null + && !JavaScriptIndex.isFromPredefinedFile(psiElement.getContainingFile()) + && sourceElement != psiElement) { + if (psiElement instanceof JSFunction fun && sourceElement instanceof JSFunction sourceFun) { + if ((sourceFun.isGetProperty() && fun.isSetProperty()) + || (sourceFun.isSetProperty() && fun.isGetProperty())) { + return true; + } + } - if(!(parent instanceof JSDefinitionExpression)) - { - return false; - } - } - return true; - } - }); + if ((psiElement != sourceElement || !(psiElement instanceof JSClass)) && !consumer.test(psiElement)) { + return false; + } + } + } - if(sourceElement instanceof JSClass) - { - final JSClass clazz = (JSClass) sourceElement; + if (!(parent instanceof JSDefinitionExpression)) { + return false; + } + } + return true; + }); - final Processor delegatingProcessor = new Processor() - { - @Override - public boolean process(final JSClass jsClass) - { - return consumer.process(jsClass); - } - }; - JSClassSearch.searchClassInheritors(clazz, true).forEach(delegatingProcessor); + if (sourceElement instanceof JSClass clazz) { + Predicate delegatingProcessor = consumer::test; + JSClassSearch.searchClassInheritors(clazz, true).forEach(delegatingProcessor); - if(clazz.isInterface()) - { - JSClassSearch.searchInterfaceImplementations(clazz, true).forEach(delegatingProcessor); - } - } - else if(sourceElement instanceof JSFunction) - { - final JSFunction baseFunction = (JSFunction) sourceElement; - final Processor delegatingProcessor = new Processor() - { - @Override - public boolean process(final JSFunction jsFunction) - { - return consumer.process(jsFunction); - } - }; - JSFunctionsSearch.searchOverridingFunctions(baseFunction, true).forEach(delegatingProcessor); + if (clazz.isInterface()) { + JSClassSearch.searchInterfaceImplementations(clazz, true).forEach(delegatingProcessor); + } + } + else if (sourceElement instanceof JSFunction baseFunction) { + Predicate delegatingProcessor = consumer::test; + JSFunctionsSearch.searchOverridingFunctions(baseFunction, true).forEach(delegatingProcessor); - final PsiElement parent = baseFunction.getParent(); - if(parent instanceof JSClass && ((JSClass) parent).isInterface()) - { - JSFunctionsSearch.searchImplementingFunctions(baseFunction, true).forEach(delegatingProcessor); - } - } - } - return true; - } + PsiElement parent = baseFunction.getParent(); + if (parent instanceof JSClass jsClass && jsClass.isInterface()) { + JSFunctionsSearch.searchImplementingFunctions(baseFunction, true).forEach(delegatingProcessor); + } + } + } + return true; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/search/JSFunctionsSearch.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/search/JSFunctionsSearch.java index 3d02c5ec..81cf7f89 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/search/JSFunctionsSearch.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/search/JSFunctionsSearch.java @@ -20,99 +20,84 @@ import com.intellij.lang.javascript.psi.JSFunction; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; import com.intellij.lang.javascript.search.JSClassSearch; -import consulo.application.util.function.Processor; +import consulo.annotation.access.RequiredReadAction; import consulo.application.util.query.Query; import consulo.application.util.query.QueryExecutor; import consulo.application.util.query.QueryFactory; import consulo.language.psi.PsiElement; - -public abstract class JSFunctionsSearch implements QueryExecutor -{ - public static class SearchParameters - { - private JSFunction myBaseFunction; - private boolean myCheckDeepInheritance; - - public SearchParameters(final JSFunction baseFunction, final boolean checkDeepInheritance) - { - myBaseFunction = baseFunction; - myCheckDeepInheritance = checkDeepInheritance; - } - - public JSFunction getBaseFunction() - { - return myBaseFunction; - } - - public boolean isCheckDeepInheritance() - { - return myCheckDeepInheritance; - } - } - - public static Query searchOverridingFunctions(final JSFunction baseFunction, final boolean checkDeepInheritance) - { - final SearchParameters parameters = new SearchParameters(baseFunction, checkDeepInheritance); - return OVERRIDDEN_FUNCTIONS_QUERY_FACTORY.createUniqueResultsQuery(parameters); - } - - public static Query searchImplementingFunctions(final JSFunction baseFunction, final boolean checkDeepInheritance) - { - final SearchParameters parameters = new SearchParameters(baseFunction, checkDeepInheritance); - return IMPLEMENTING_FUNCTIONS_QUERY_FACTORY.createUniqueResultsQuery(parameters); - } - - private static QueryFactory OVERRIDDEN_FUNCTIONS_QUERY_FACTORY = new QueryFactory(); - private static QueryFactory IMPLEMENTING_FUNCTIONS_QUERY_FACTORY = new QueryFactory(); - - static - { - OVERRIDDEN_FUNCTIONS_QUERY_FACTORY.registerExecutor(new JSFunctionsSearch() - { - @Override - protected Query makeQuery(final SearchParameters queryParameters, final PsiElement parent) - { - return JSClassSearch.searchClassInheritors((JSClass) parent, queryParameters.isCheckDeepInheritance()); - } - }); - - IMPLEMENTING_FUNCTIONS_QUERY_FACTORY.registerExecutor(new ImplementingFunctionsSearch()); - } - - @Override - public boolean execute(final SearchParameters queryParameters, final Processor consumer) - { - final JSFunction baseFunction = queryParameters.getBaseFunction(); - PsiElement clazz = JSResolveUtil.findParent(baseFunction); - - if(!(clazz instanceof JSClass)) - { - return true; - } - - return makeQuery(queryParameters, clazz).forEach(new Processor() - { - @Override - public boolean process(final JSClass jsClass) - { - JSFunction function = jsClass.findFunctionByNameAndKind(baseFunction.getName(), baseFunction.getKind()); - if(function != null) - { - return consumer.process(function); - } - return true; - } - }); - } - - protected abstract Query makeQuery(final SearchParameters queryParameters, final PsiElement parent); - - private static class ImplementingFunctionsSearch extends JSFunctionsSearch - { - @Override - protected Query makeQuery(final SearchParameters queryParameters, final PsiElement parent) - { - return JSClassSearch.searchInterfaceImplementations((JSClass) parent, true); - } - } +import jakarta.annotation.Nonnull; + +import java.util.function.Predicate; + +public abstract class JSFunctionsSearch implements QueryExecutor { + public static class SearchParameters { + private JSFunction myBaseFunction; + private boolean myCheckDeepInheritance; + + public SearchParameters(JSFunction baseFunction, boolean checkDeepInheritance) { + myBaseFunction = baseFunction; + myCheckDeepInheritance = checkDeepInheritance; + } + + public JSFunction getBaseFunction() { + return myBaseFunction; + } + + public boolean isCheckDeepInheritance() { + return myCheckDeepInheritance; + } + } + + public static Query searchOverridingFunctions(JSFunction baseFunction, boolean checkDeepInheritance) { + SearchParameters parameters = new SearchParameters(baseFunction, checkDeepInheritance); + return OVERRIDDEN_FUNCTIONS_QUERY_FACTORY.createUniqueResultsQuery(parameters); + } + + public static Query searchImplementingFunctions(JSFunction baseFunction, boolean checkDeepInheritance) { + SearchParameters parameters = new SearchParameters(baseFunction, checkDeepInheritance); + return IMPLEMENTING_FUNCTIONS_QUERY_FACTORY.createUniqueResultsQuery(parameters); + } + + private static QueryFactory OVERRIDDEN_FUNCTIONS_QUERY_FACTORY = new QueryFactory<>(); + private static QueryFactory IMPLEMENTING_FUNCTIONS_QUERY_FACTORY = new QueryFactory<>(); + + static { + OVERRIDDEN_FUNCTIONS_QUERY_FACTORY.registerExecutor(new JSFunctionsSearch() { + @Override + protected Query makeQuery(SearchParameters queryParameters, PsiElement parent) { + return JSClassSearch.searchClassInheritors((JSClass)parent, queryParameters.isCheckDeepInheritance()); + } + }); + + IMPLEMENTING_FUNCTIONS_QUERY_FACTORY.registerExecutor(new ImplementingFunctionsSearch()); + } + + @Override + public boolean execute(SearchParameters queryParameters, final @Nonnull Predicate consumer) { + final JSFunction baseFunction = queryParameters.getBaseFunction(); + PsiElement clazz = JSResolveUtil.findParent(baseFunction); + + //noinspection SimplifiableIfStatement + if (!(clazz instanceof JSClass)) { + return true; + } + + return makeQuery(queryParameters, clazz).forEach(new Predicate<>() { + @Override + @RequiredReadAction + public boolean test(JSClass jsClass) { + JSFunction function = jsClass.findFunctionByNameAndKind(baseFunction.getName(), baseFunction.getKind()); + return function == null || consumer.test(function); + } + }); + } + + protected abstract Query makeQuery(SearchParameters queryParameters, PsiElement parent); + + private static class ImplementingFunctionsSearch extends JSFunctionsSearch { + @Override + protected Query makeQuery(SearchParameters queryParameters, PsiElement parent) { + return JSClassSearch.searchInterfaceImplementations((JSClass)parent, true); + } + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/search/JSGotoTargetRendererProvider.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/search/JSGotoTargetRendererProvider.java index c8f84bcc..cc950f91 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/search/JSGotoTargetRendererProvider.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/search/JSGotoTargetRendererProvider.java @@ -17,54 +17,42 @@ package com.intellij.lang.javascript.impl.search; import com.intellij.lang.javascript.psi.JSNamedElement; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; import consulo.ide.navigation.GotoTargetRendererProvider; import consulo.language.editor.ui.PsiElementListCellRenderer; import consulo.language.psi.PsiElement; import consulo.navigation.ItemPresentation; -import consulo.navigation.NavigationItem; - -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; /** * @author Maxim.Mossienko - * Date: Apr 28, 2008 - * Time: 8:14:14 PM + * @since 2008-04-28 */ @ExtensionImpl -public class JSGotoTargetRendererProvider implements GotoTargetRendererProvider -{ - static class JSClassListCellRenderer extends PsiElementListCellRenderer - { - @Override - public String getElementText(final JSNamedElement element) - { - return element.getName(); - } - - @Override - protected String getContainerText(final JSNamedElement element, final String name) - { - final ItemPresentation presentation = ((NavigationItem) element).getPresentation(); - return presentation != null ? presentation.getLocationString() : null; - } - - @Override - protected int getIconFlags() - { - return 0; - } - } - - @Nullable - @Override - public PsiElementListCellRenderer getRenderer(PsiElement element) - { - if(!(element instanceof JSNamedElement)) - { - return null; - } - - return new JSClassListCellRenderer(); - } +public class JSGotoTargetRendererProvider implements GotoTargetRendererProvider { + static class JSClassListCellRenderer extends PsiElementListCellRenderer { + @Override + @RequiredReadAction + public String getElementText(JSNamedElement element) { + return element.getName(); + } + + @Override + protected String getContainerText(JSNamedElement element, String name) { + ItemPresentation presentation = element.getPresentation(); + return presentation != null ? presentation.getLocationString() : null; + } + + @Override + protected int getIconFlags() { + return 0; + } + } + + @Nullable + @Override + public PsiElementListCellRenderer getRenderer(PsiElement element) { + return element instanceof JSNamedElement ? new JSClassListCellRenderer() : null; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/search/JSReferencesSearchExecutor.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/search/JSReferencesSearchExecutor.java deleted file mode 100644 index b1f96176..00000000 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/search/JSReferencesSearchExecutor.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2000-2005 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.lang.javascript.impl.search; - -import consulo.annotation.component.ExtensionImpl; -import consulo.application.ReadAction; -import consulo.application.util.function.Processor; -import consulo.javascript.language.JavaScriptFileType; -import consulo.javascript.language.JavaScriptLanguage; -import consulo.language.psi.PsiElement; -import consulo.language.psi.PsiFile; -import consulo.language.psi.PsiNamedElement; -import consulo.language.psi.PsiReference; -import consulo.language.psi.scope.GlobalSearchScope; -import consulo.language.psi.scope.LocalSearchScope; -import consulo.language.psi.search.PsiSearchHelper; -import consulo.language.psi.search.ReferencesSearch; -import consulo.language.psi.search.ReferencesSearchQueryExecutor; - -/** - * @author Maxim.Mossienko - * Date: Apr 28, 2008 - * Time: 8:34:20 PM - */ -@ExtensionImpl -public class JSReferencesSearchExecutor implements ReferencesSearchQueryExecutor -{ - @Override - public boolean execute(final ReferencesSearch.SearchParameters queryParameters, final Processor consumer) - { - final PsiElement sourceElement = queryParameters.getElementToSearch(); - - if(sourceElement instanceof PsiNamedElement && - sourceElement.getLanguage().isKindOf(JavaScriptLanguage.INSTANCE) && - queryParameters.getScope() instanceof GlobalSearchScope && - !(sourceElement.getUseScope() instanceof LocalSearchScope)) - { - final String s = ReadAction.compute(() -> ((PsiNamedElement) sourceElement).getName()); - if(s == null) - { - return true; - } - PsiSearchHelper.SERVICE.getInstance(sourceElement.getProject()).processAllFilesWithWordInLiterals(s, GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.projectScope - (sourceElement.getProject()), JavaScriptFileType.INSTANCE), new Processor() - { - @Override - public boolean process(final PsiFile psiFile) - { - /*if(psiFile.getLanguage() == JavaScriptSupportLoader.JSON) - { - ReferencesSearch.search(sourceElement, new LocalSearchScope(psiFile)).forEach(consumer); - } */ - return true; - } - }); - } - return true; - } -} diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/structureView/JSStructureItemPresentation.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/structureView/JSStructureItemPresentation.java index 004fd2ee..e95f58d8 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/structureView/JSStructureItemPresentation.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/structureView/JSStructureItemPresentation.java @@ -16,155 +16,116 @@ package com.intellij.lang.javascript.impl.structureView; -import consulo.javascript.language.JavaScriptBundle; -import com.intellij.lang.javascript.psi.JSAssignmentExpression; -import com.intellij.lang.javascript.psi.JSDefinitionExpression; -import com.intellij.lang.javascript.psi.JSExpression; -import com.intellij.lang.javascript.psi.JSFunction; -import com.intellij.lang.javascript.psi.JSObjectLiteralExpression; -import com.intellij.lang.javascript.psi.JSParameter; -import com.intellij.lang.javascript.psi.JSParameterList; -import com.intellij.lang.javascript.psi.JSProperty; -import com.intellij.lang.javascript.psi.JSReferenceExpression; +import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; +import consulo.annotation.access.RequiredReadAction; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.icon.IconDescriptorUpdaters; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiNamedElement; -import consulo.annotation.access.RequiredReadAction; import consulo.ui.image.Image; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author Maxim.Mossienko - * Date: Jul 23, 2008 - * Time: 6:54:27 PM + * @since 2008-07-23 */ -public class JSStructureItemPresentation extends JSStructureViewElement.JSStructureItemPresentationBase -{ - public JSStructureItemPresentation(final JSStructureViewElement jsStructureViewElement) - { - super(jsStructureViewElement); - } - - @Override - @RequiredReadAction - public String getPresentableText() - { - PsiElement psiElement = element.getUpToDateElement(); - if(psiElement == null || !psiElement.isValid()) - { - return "*invalid*"; - } - - return getName(psiElement); - } - - @RequiredReadAction - public static String getName(@Nonnull PsiElement psiElement) - { - if(psiElement instanceof JSObjectLiteralExpression) - { - if(psiElement.getParent() instanceof JSAssignmentExpression) - { - final JSExpression expression = ((JSDefinitionExpression) ((JSAssignmentExpression) psiElement.getParent()).getLOperand()).getExpression(); - return JSResolveUtil.findClassIdentifier(expression).getText(); - } - else - { - return JavaScriptBundle.message("javascript.language.term.prototype"); - } - } - - if(psiElement instanceof JSDefinitionExpression) - { - psiElement = ((JSDefinitionExpression) psiElement).getExpression(); - } - - if(psiElement instanceof JSReferenceExpression) - { - JSReferenceExpression expression = (JSReferenceExpression) psiElement; - - String s = expression.getReferencedName(); - - if(JSResolveUtil.PROTOTYPE_FIELD_NAME.equals(s)) - { - final JSExpression jsExpression = expression.getQualifier(); - if(jsExpression instanceof JSReferenceExpression) - { - s = ((JSReferenceExpression) jsExpression).getReferencedName(); - } - } - return s; - } - - if(!(psiElement instanceof PsiNamedElement)) - { - return psiElement.getText(); - } - - String name = ((PsiNamedElement) psiElement).getName(); - - if(psiElement instanceof JSProperty) - { - psiElement = ((JSProperty) psiElement).getValue(); - } - - if(psiElement instanceof JSFunction) - { - if(name == null) - { - name = ""; - } - name += "("; - JSParameterList parameterList = ((JSFunction) psiElement).getParameterList(); - if(parameterList != null) - { - for(JSParameter p : parameterList.getParameters()) - { - if(!name.endsWith("(")) - { - name += ", "; - } - name += p.getName(); - final String variableType = p.getTypeString(); - if(variableType != null) - { - name += ":" + variableType; - } - } - } - name += ")"; - - final String type = ((JSFunction) psiElement).getReturnTypeString(); - if(type != null) - { - name += ":" + type; - } - } - - if(name == null && psiElement.getParent() instanceof JSAssignmentExpression) - { - JSExpression lOperand = ((JSDefinitionExpression) ((JSAssignmentExpression) psiElement.getParent()).getLOperand()).getExpression(); - lOperand = JSResolveUtil.findClassIdentifier(lOperand); - if(lOperand instanceof JSReferenceExpression) - { - return ((JSReferenceExpression) lOperand).getReferencedName(); - } - return lOperand.getText(); - } - return name; - } - - @Override - @RequiredReadAction - public Image getIcon() - { - final PsiElement psiElement = this.element.getRealElement(); - if(!psiElement.isValid()) - { - return null; - } - return IconDescriptorUpdaters.getIcon(psiElement, 0); - } +public class JSStructureItemPresentation extends JSStructureViewElement.JSStructureItemPresentationBase { + public JSStructureItemPresentation(JSStructureViewElement jsStructureViewElement) { + super(jsStructureViewElement); + } + + @Override + @RequiredReadAction + public String getPresentableText() { + PsiElement psiElement = element.getUpToDateElement(); + if (psiElement == null || !psiElement.isValid()) { + return "*invalid*"; + } + + return getName(psiElement); + } + + @RequiredReadAction + public static String getName(@Nonnull PsiElement psiElement) { + if (psiElement instanceof JSObjectLiteralExpression objectLiteral) { + if (objectLiteral.getParent() instanceof JSAssignmentExpression assignment) { + JSDefinitionExpression lOperand = (JSDefinitionExpression)assignment.getLOperand(); + return JSResolveUtil.findClassIdentifier(lOperand.getExpression()).getText(); + } + else { + return JavaScriptLocalize.javascriptLanguageTermPrototype().get(); + } + } + + if (psiElement instanceof JSDefinitionExpression definition) { + psiElement = definition.getExpression(); + } + + if (psiElement instanceof JSReferenceExpression refExpr) { + String s = refExpr.getReferencedName(); + + if (JSResolveUtil.PROTOTYPE_FIELD_NAME.equals(s) + && refExpr.getQualifier() instanceof JSReferenceExpression qualifierRefExpr) { + s = qualifierRefExpr.getReferencedName(); + } + return s; + } + + if (!(psiElement instanceof PsiNamedElement)) { + return psiElement.getText(); + } + + String name = ((PsiNamedElement)psiElement).getName(); + + if (psiElement instanceof JSProperty property) { + psiElement = property.getValue(); + } + + if (psiElement instanceof JSFunction function) { + if (name == null) { + name = ""; + } + name += "("; + JSParameterList parameterList = function.getParameterList(); + if (parameterList != null) { + for (JSParameter p : parameterList.getParameters()) { + if (!name.endsWith("(")) { + name += ", "; + } + name += p.getName(); + String variableType = p.getTypeString(); + if (variableType != null) { + name += ":" + variableType; + } + } + } + name += ")"; + + String type = function.getReturnTypeString(); + if (type != null) { + name += ":" + type; + } + } + + if (name == null && psiElement.getParent() instanceof JSAssignmentExpression assignment) { + JSExpression lOperand = ((JSDefinitionExpression)assignment.getLOperand()).getExpression(); + lOperand = JSResolveUtil.findClassIdentifier(lOperand); + if (lOperand instanceof JSReferenceExpression lOperandRefExpr) { + return lOperandRefExpr.getReferencedName(); + } + return lOperand.getText(); + } + return name; + } + + @Override + @RequiredReadAction + public Image getIcon() { + PsiElement psiElement = this.element.getRealElement(); + if (!psiElement.isValid()) { + return null; + } + return IconDescriptorUpdaters.getIcon(psiElement, 0); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/structureView/JSStructureViewBuilderFactory.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/structureView/JSStructureViewBuilderFactory.java index e13ce8df..7c5f0a6f 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/structureView/JSStructureViewBuilderFactory.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/structureView/JSStructureViewBuilderFactory.java @@ -28,36 +28,29 @@ import consulo.language.Language; import consulo.language.editor.structureView.PsiStructureViewFactory; import consulo.language.psi.PsiFile; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; @ExtensionImpl -public class JSStructureViewBuilderFactory implements PsiStructureViewFactory -{ - @Override - public StructureViewBuilder getStructureViewBuilder(final PsiFile psiFile) - { - return new TreeBasedStructureViewBuilder() - { - @Override - @Nonnull - public StructureViewModel createStructureViewModel(Editor editor) - { - return new JSStructureViewModel(psiFile); - } +public class JSStructureViewBuilderFactory implements PsiStructureViewFactory { + @Override + public StructureViewBuilder getStructureViewBuilder(PsiFile psiFile) { + return new TreeBasedStructureViewBuilder() { + @Override + @Nonnull + public StructureViewModel createStructureViewModel(Editor editor) { + return new JSStructureViewModel(psiFile, editor); + } - @Override - public boolean isRootNodeShown() - { - return false; - } - }; - } + @Override + public boolean isRootNodeShown() { + return false; + } + }; + } - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/structureView/JSStructureViewElement.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/structureView/JSStructureViewElement.java index 7b664476..475312e3 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/structureView/JSStructureViewElement.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/structureView/JSStructureViewElement.java @@ -16,6 +16,7 @@ package com.intellij.lang.javascript.impl.structureView; +import consulo.annotation.access.RequiredReadAction; import consulo.document.util.TextRange; import consulo.fileEditor.structureView.StructureViewTreeElement; import consulo.language.inject.InjectedLanguageManager; @@ -31,425 +32,352 @@ import consulo.util.collection.primitive.ints.IntMaps; import consulo.util.collection.primitive.ints.IntObjectMap; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; + import java.util.*; /** * @author max */ -public class JSStructureViewElement implements StructureViewTreeElement -{ - protected PsiElement myElement; - private boolean myInherited; - - public JSStructureViewElement(final PsiElement element) - { - myElement = element; - } - - @Override - public PsiElement getValue() - { - return myElement; - } - - PsiElement getRealElement() - { - return myElement; - } - - @Override - public void navigate(boolean requestFocus) - { - ((Navigatable) myElement).navigate(requestFocus); - } - - @Override - public boolean canNavigate() - { - return ((Navigatable) myElement).canNavigate(); - } - - @Override - public boolean canNavigateToSource() - { - return canNavigate(); - } - - @Override - public StructureViewTreeElement[] getChildren() - { - final PsiElement element = getUpToDateElement(); - // since we use proxies for StructureViewElement then real element may invalidate due to structural change - if(element == null) - { - return EMPTY_ARRAY; - } - - final Set referencedNamedIds = new HashSet(); - - - List children = collectMyElements(referencedNamedIds); - - ArrayList elementsFromSupers = null; - - if(element instanceof JSClass) - { - for(JSClass clazz : ((JSClass) element).getSuperClasses()) - { - final StructureViewTreeElement[] structureViewTreeElements = createStructureViewElement(clazz).getChildren(); - - if(elementsFromSupers == null) - { - elementsFromSupers = new ArrayList(structureViewTreeElements.length); - } - else - { - elementsFromSupers.ensureCapacity(elementsFromSupers.size() + structureViewTreeElements.length); - } - - for(StructureViewTreeElement e : structureViewTreeElements) - { - if(!isVisible((PsiElement) e.getValue(), element)) - { - continue; - } - // TODO CSS styles can also be inherited, so we better show them - // This can't be done until 'inherited' property is elevated up to StructureViewTreeElement interface - if(!(e instanceof JSStructureViewElement)) - { - continue; - } - ((JSStructureViewElement) e).setInherited(true); - elementsFromSupers.add(e); - } - } - } - - - Collections.sort(children, new Comparator() - { - @Override - public int compare(final StructureViewTreeElement _o1, final StructureViewTreeElement _o2) - { - PsiElement e = getPsiElement(_o1); - PsiElement e2 = getPsiElement(_o2); - - TextRange t1 = InjectedLanguageManager.getInstance(e.getProject()).injectedToHost(e, e.getTextRange()); - TextRange t2 = InjectedLanguageManager.getInstance(e.getProject()).injectedToHost(e, e.getTextRange()); - final int offset = e.getTextOffset() + t1.getStartOffset(); - final int offset2 = e2.getTextOffset() + t2.getStartOffset(); - - return offset - offset2; - } - }); - - if(elementsFromSupers != null) - { - Map functionsByNames = new HashMap(); - for(StructureViewTreeElement child : children) - { - PsiElement el = getPsiElementResolveProxy(child); - if(el instanceof JSFunction) - { - JSFunction function = (JSFunction) el; - functionsByNames.put(function.getName(), function); - } - } - - for(StructureViewTreeElement superTreeElement : elementsFromSupers) - { - PsiElement superElement = getPsiElementResolveProxy(superTreeElement); - boolean addSuperElement = true; - if(superElement instanceof JSFunction) - { - JSFunction superFunction = (JSFunction) superElement; - JSFunction function = functionsByNames.get(superFunction.getName()); - if(function != null) - { - // TODO check signature - addSuperElement = false; - } - } - - if(addSuperElement) - { - children.add(superTreeElement); - } - } - } - return children.toArray(new StructureViewTreeElement[children.size()]); - } - - protected JSStructureViewElement createStructureViewElement(PsiElement element) - { - return new JSStructureViewElement(element); - } - - private static PsiElement getPsiElement(StructureViewTreeElement element) - { - PsiElement e; - if(element instanceof JSStructureViewElement) - { - final JSStructureViewElement o1 = (JSStructureViewElement) element; - e = o1.myElement; - } - else - { - e = (PsiElement) element.getValue(); - } - return e; - } - - public static PsiElement getPsiElementResolveProxy(StructureViewTreeElement element) - { - return getPsiElement(element); - } - - - protected List collectMyElements(final Set referencedNamedIds) - { - final IntObjectMap offset2Element = IntMaps.newIntObjectHashMap(); - - collectChildrenFromElement(myElement, referencedNamedIds, offset2Element); - - final List children = new ArrayList(offset2Element.size()); - offset2Element.forEach((textOffset, element) -> children.add(createStructureViewElement(element))); - return children; - } - - private static boolean isVisible(PsiElement namedElement, final PsiElement element) - { - if(namedElement instanceof JSAttributeListOwner) - { - final JSAttributeListOwner attributeListOwner = (JSAttributeListOwner) namedElement; - final JSAttributeList attributeList = attributeListOwner.getAttributeList(); - - if(attributeList != null) - { - final JSAttributeList.AccessType type = attributeList.getAccessType(); - - if(type == JSAttributeList.AccessType.PACKAGE_LOCAL) - { - final JSPackageStatement packageStatement = PsiTreeUtil.getParentOfType(namedElement, JSPackageStatement.class); - final JSPackageStatement packageStatement2 = PsiTreeUtil.getParentOfType(element, JSPackageStatement.class); - String packageQName; - - return packageStatement == packageStatement2 || (packageStatement != null && - packageStatement2 != null && - (packageQName = packageStatement.getQualifiedName()) != null && - packageQName.equals(packageStatement2.getQualifiedName())); - } - return type != JSAttributeList.AccessType.PRIVATE; - } - } - return true; - } - - private static void collectChildrenFromElement(final PsiElement element, final Set referencedNamedIds, final IntObjectMap offset2Element) - { - element.acceptChildren(new JSElementVisitor() - { - Set visited; - PsiElement context = element; - - @Override - public void visitElement(PsiElement element) - { - if(element instanceof JSNamedElement && - ((JSNamedElement) element).getName() != null && - !(element instanceof JSDefinitionExpression) && - !(element instanceof JSLabeledStatement) && - !(element instanceof JSPackageStatement) && - !(element instanceof JavaScriptImportStatementBase)) - { - if(!(element instanceof JSFunction) || !(element.getParent() instanceof JSProperty)) - { - addElement(element); - } - else - { - element.acceptChildren(this); - } - } - else - { - element.acceptChildren(this); - } - } - - @Override - public void visitJSParameter(final JSParameter node) - { - // Do not add parameters to structure view - } - - @Override - public void visitJSIncludeDirective(final JSIncludeDirective includeDirective) - { - final PsiFile file = includeDirective.resolveFile(); - if(file instanceof JSFile) - { - if(visited != null && visited.contains(file)) - { - return; - } - if(visited == null) - { - visited = new HashSet(); - } - visited.add(file); - - final PsiElement prevContext = context; - context = file; - context.putUserData(JSResolveUtil.contextKey, element); - file.acceptChildren(this); - context = prevContext; - } - } - - @Override - public void visitJSObjectLiteralExpression(final JSObjectLiteralExpression node) - { - final PsiElement parent = node.getParent(); - if(parent instanceof JSVariable || - parent instanceof JSProperty || - parent instanceof JSFile || - parent instanceof JSReturnStatement || - parent instanceof JSAssignmentExpression) - { - node.acceptChildren(this); - return; - } - if(parent instanceof JSArgumentList) - { - final JSElement expression = JSSymbolUtil.findQualifyingExpressionFromArgumentList((JSArgumentList) parent); - if(expression != null) - { - return; - } - } - if(node.getProperties().length > 0) - { - addElement(node); - } - } - - @Override - public void visitJSVariable(final JSVariable node) - { - if(element instanceof JSFunction) - { - return; - } - super.visitJSVariable(node); - } - - @Override - public void visitJSAssignmentExpression(final JSAssignmentExpression node) - { - JSExpression rOperand = node.getROperand(); - final JSExpression lOperand = node.getLOperand(); - - final boolean outsideFunction = PsiTreeUtil.getParentOfType(node, JSFunction.class) == null; - if(!outsideFunction) - { - return; - } - - if(rOperand instanceof JSCallExpression) - { - rOperand = ((JSCallExpression) rOperand).getMethodExpression(); - } - - if(rOperand instanceof JSFunction) - { - JSExpression qualifier = null; - final JSExpression operand = ((JSDefinitionExpression) lOperand).getExpression(); - - if(operand instanceof JSReferenceExpression) - { - qualifier = ((JSReferenceExpression) operand).getQualifier(); - } - if((qualifier == null || qualifier instanceof JSThisExpression)) - { - addElement(rOperand); - } - } - else if(lOperand != null) - { - final JSExpression operand = ((JSDefinitionExpression) lOperand).getExpression(); - if(operand instanceof JSReferenceExpression && ((JSReferenceExpression) operand).getQualifier() instanceof JSThisExpression) - { - final PsiElement resolved = ((JSReferenceExpression) operand).resolve(); - if(resolved == lOperand) - { - addElement(lOperand); - } - } - //super.visitJSAssignmentExpression(node); - } - } - - private void addElement(final PsiElement lOperand) - { - if(lOperand instanceof JSNamedElement) - { - final String namedId = ((JSNamedElement) lOperand).getName(); - if(referencedNamedIds.contains(namedId)) - { - return; - } - referencedNamedIds.add(namedId); - } - offset2Element.put(lOperand.getTextOffset(), lOperand); - } - }); - } - - @Override - public ItemPresentation getPresentation() - { - return new JSStructureItemPresentation(this); - } - - public boolean isInherited() - { - return myInherited; - } - - private void setInherited(boolean b) - { - myInherited = b; - } - - public - @Nullable - PsiElement getUpToDateElement() - { - boolean isValid = myElement.isValid(); - - if(!isValid) - { - return null; - } - - return myElement; - } - - static abstract class JSStructureItemPresentationBase implements ItemPresentation - { - final protected JSStructureViewElement element; - - JSStructureItemPresentationBase(JSStructureViewElement _element) - { - element = _element; - } - - @Override - public String getLocationString() - { - return null; - } - } +public class JSStructureViewElement implements StructureViewTreeElement { + protected PsiElement myElement; + private boolean myInherited; + + public JSStructureViewElement(PsiElement element) { + myElement = element; + } + + @Override + public PsiElement getValue() { + return myElement; + } + + PsiElement getRealElement() { + return myElement; + } + + @Override + public void navigate(boolean requestFocus) { + ((Navigatable)myElement).navigate(requestFocus); + } + + @Override + public boolean canNavigate() { + return ((Navigatable)myElement).canNavigate(); + } + + @Override + public boolean canNavigateToSource() { + return canNavigate(); + } + + @Nonnull + @Override + @RequiredReadAction + public StructureViewTreeElement[] getChildren() { + PsiElement element = getUpToDateElement(); + // since we use proxies for StructureViewElement then real element may invalidate due to structural change + if (element == null) { + return EMPTY_ARRAY; + } + + Set referencedNamedIds = new HashSet<>(); + + List children = collectMyElements(referencedNamedIds); + + ArrayList elementsFromSupers = null; + + if (element instanceof JSClass jsClass) { + for (JSClass superClass : jsClass.getSuperClasses()) { + StructureViewTreeElement[] structureViewTreeElements = createStructureViewElement(superClass).getChildren(); + + if (elementsFromSupers == null) { + elementsFromSupers = new ArrayList<>(structureViewTreeElements.length); + } + else { + elementsFromSupers.ensureCapacity(elementsFromSupers.size() + structureViewTreeElements.length); + } + + for (StructureViewTreeElement e : structureViewTreeElements) { + if (!isVisible((PsiElement)e.getValue(), element)) { + continue; + } + // TODO CSS styles can also be inherited, so we better show them + // This can't be done until 'inherited' property is elevated up to StructureViewTreeElement interface + if (!(e instanceof JSStructureViewElement)) { + continue; + } + ((JSStructureViewElement)e).setInherited(true); + elementsFromSupers.add(e); + } + } + } + + Collections.sort( + children, + (_o1, _o2) -> { + PsiElement e = getPsiElement(_o1); + PsiElement e2 = getPsiElement(_o2); + + TextRange t1 = InjectedLanguageManager.getInstance(e.getProject()).injectedToHost(e, e.getTextRange()); + TextRange t2 = InjectedLanguageManager.getInstance(e.getProject()).injectedToHost(e, e.getTextRange()); + int offset = e.getTextOffset() + t1.getStartOffset(); + int offset2 = e2.getTextOffset() + t2.getStartOffset(); + + return offset - offset2; + } + ); + + if (elementsFromSupers != null) { + Map functionsByNames = new HashMap<>(); + for (StructureViewTreeElement child : children) { + PsiElement el = getPsiElementResolveProxy(child); + if (el instanceof JSFunction function) { + functionsByNames.put(function.getName(), function); + } + } + + for (StructureViewTreeElement superTreeElement : elementsFromSupers) { + PsiElement superElement = getPsiElementResolveProxy(superTreeElement); + boolean addSuperElement = true; + if (superElement instanceof JSFunction superFunction) { + JSFunction function = functionsByNames.get(superFunction.getName()); + if (function != null) { + // TODO check signature + addSuperElement = false; + } + } + + if (addSuperElement) { + children.add(superTreeElement); + } + } + } + return children.toArray(new StructureViewTreeElement[children.size()]); + } + + protected JSStructureViewElement createStructureViewElement(PsiElement element) { + return new JSStructureViewElement(element); + } + + private static PsiElement getPsiElement(StructureViewTreeElement element) { + return element instanceof JSStructureViewElement structureViewElement + ? structureViewElement.myElement + : (PsiElement)element.getValue(); + } + + public static PsiElement getPsiElementResolveProxy(StructureViewTreeElement element) { + return getPsiElement(element); + } + + protected List collectMyElements(Set referencedNamedIds) { + IntObjectMap offset2Element = IntMaps.newIntObjectHashMap(); + + collectChildrenFromElement(myElement, referencedNamedIds, offset2Element); + + List children = new ArrayList<>(offset2Element.size()); + offset2Element.forEach((textOffset, element) -> children.add(createStructureViewElement(element))); + return children; + } + + @RequiredReadAction + private static boolean isVisible(PsiElement namedElement, PsiElement element) { + if (namedElement instanceof JSAttributeListOwner attributeListOwner) { + JSAttributeList attributeList = attributeListOwner.getAttributeList(); + + if (attributeList != null) { + JSAttributeList.AccessType type = attributeList.getAccessType(); + + if (type == JSAttributeList.AccessType.PACKAGE_LOCAL) { + JSPackageStatement packageStatement = PsiTreeUtil.getParentOfType(namedElement, JSPackageStatement.class); + JSPackageStatement packageStatement2 = PsiTreeUtil.getParentOfType(element, JSPackageStatement.class); + + return packageStatement == packageStatement2 + || (packageStatement != null && packageStatement2 != null + && Objects.equals(packageStatement.getQualifiedName(), packageStatement2.getQualifiedName())); + } + return type != JSAttributeList.AccessType.PRIVATE; + } + } + return true; + } + + private static void collectChildrenFromElement( + PsiElement element, + Set referencedNamedIds, + IntObjectMap offset2Element + ) { + element.acceptChildren(new JSElementVisitor() { + Set visited; + PsiElement context = element; + + @Override + @RequiredReadAction + public void visitElement(PsiElement element) { + if (element instanceof JSNamedElement namedElement + && namedElement.getName() != null + && !(element instanceof JSDefinitionExpression) + && !(element instanceof JSLabeledStatement) + && !(element instanceof JSPackageStatement) + && !(element instanceof JavaScriptImportStatementBase)) { + if (!(element instanceof JSFunction) || !(element.getParent() instanceof JSProperty)) { + addElement(element); + } + else { + element.acceptChildren(this); + } + } + else { + element.acceptChildren(this); + } + } + + @Override + public void visitJSParameter(@Nonnull JSParameter node) { + // Do not add parameters to structure view + } + + @Override + @RequiredReadAction + public void visitJSIncludeDirective(@Nonnull JSIncludeDirective includeDirective) { + if (includeDirective.resolveFile() instanceof JSFile jsFile) { + if (visited != null && visited.contains(jsFile)) { + return; + } + if (visited == null) { + visited = new HashSet<>(); + } + visited.add(jsFile); + + PsiElement prevContext = context; + context = jsFile; + context.putUserData(JSResolveUtil.contextKey, element); + jsFile.acceptChildren(this); + context = prevContext; + } + } + + @Override + public void visitJSObjectLiteralExpression(@Nonnull JSObjectLiteralExpression node) { + PsiElement parent = node.getParent(); + if (parent instanceof JSVariable + || parent instanceof JSProperty + || parent instanceof JSFile + || parent instanceof JSReturnStatement + || parent instanceof JSAssignmentExpression) { + node.acceptChildren(this); + return; + } + if (parent instanceof JSArgumentList argumentList) { + JSElement expression = JSSymbolUtil.findQualifyingExpressionFromArgumentList(argumentList); + if (expression != null) { + return; + } + } + + if (node.getProperties().length > 0) { + addElement(node); + } + } + + @Override + public void visitJSVariable(@Nonnull JSVariable node) { + if (element instanceof JSFunction) { + return; + } + super.visitJSVariable(node); + } + + @Override + @RequiredReadAction + public void visitJSAssignmentExpression(@Nonnull JSAssignmentExpression node) { + JSExpression rOperand = node.getROperand(); + JSExpression lOperand = node.getLOperand(); + + boolean outsideFunction = PsiTreeUtil.getParentOfType(node, JSFunction.class) == null; + if (!outsideFunction) { + return; + } + + if (rOperand instanceof JSCallExpression call) { + rOperand = call.getMethodExpression(); + } + + if (rOperand instanceof JSFunction function) { + JSExpression qualifier = null; + JSExpression operand = ((JSDefinitionExpression)lOperand).getExpression(); + + if (operand instanceof JSReferenceExpression operandRefExpr) { + qualifier = operandRefExpr.getQualifier(); + } + + if (qualifier == null || qualifier instanceof JSThisExpression) { + addElement(function); + } + } + else if (lOperand != null) { + JSExpression operand = ((JSDefinitionExpression)lOperand).getExpression(); + if (operand instanceof JSReferenceExpression operandRefExpr + && operandRefExpr.getQualifier() instanceof JSThisExpression) { + PsiElement resolved = operandRefExpr.resolve(); + if (resolved == lOperand) { + addElement(lOperand); + } + } + //super.visitJSAssignmentExpression(node); + } + } + + @RequiredReadAction + private void addElement(PsiElement lOperand) { + if (lOperand instanceof JSNamedElement namedElement) { + String namedId = namedElement.getName(); + if (referencedNamedIds.contains(namedId)) { + return; + } + referencedNamedIds.add(namedId); + } + offset2Element.put(lOperand.getTextOffset(), lOperand); + } + }); + } + + @Override + public ItemPresentation getPresentation() { + return new JSStructureItemPresentation(this); + } + + public boolean isInherited() { + return myInherited; + } + + private void setInherited(boolean b) { + myInherited = b; + } + + public + @Nullable + PsiElement getUpToDateElement() { + boolean isValid = myElement.isValid(); + + if (!isValid) { + return null; + } + + return myElement; + } + + static abstract class JSStructureItemPresentationBase implements ItemPresentation { + final protected JSStructureViewElement element; + + JSStructureItemPresentationBase(JSStructureViewElement _element) { + element = _element; + } + + @Override + public String getLocationString() { + return null; + } + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/structureView/JSStructureViewModel.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/structureView/JSStructureViewModel.java index bee312ad..e0b3a7b9 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/structureView/JSStructureViewModel.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/structureView/JSStructureViewModel.java @@ -18,11 +18,12 @@ import com.intellij.lang.javascript.index.JavaScriptIndex; import com.intellij.lang.javascript.psi.*; +import consulo.annotation.access.RequiredReadAction; import consulo.application.AllIcons; import consulo.codeEditor.Editor; import consulo.fileEditor.structureView.StructureViewTreeElement; import consulo.fileEditor.structureView.tree.*; -import consulo.ide.IdeBundle; +import consulo.ide.localize.IdeLocalize; import consulo.language.editor.structureView.TextEditorBasedStructureViewModel; import consulo.language.inject.InjectedLanguageManager; import consulo.language.psi.PsiElement; @@ -32,359 +33,288 @@ import consulo.platform.base.icon.PlatformIconGroup; import consulo.ui.ex.action.Shortcut; import consulo.ui.ex.keymap.KeymapManager; -import consulo.util.lang.ref.Ref; -import org.jetbrains.annotations.NonNls; +import consulo.util.lang.ref.SimpleReference; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; import java.util.Comparator; -import java.util.List; /** - * @by max, maxim + * @author max + * @author maxim */ -public class JSStructureViewModel extends TextEditorBasedStructureViewModel -{ - private PsiElement myRoot; - private Filter[] myFilters = new Filter[]{ - ourFieldsFilter, - ourInheritedFilter - }; - - @NonNls - private static final String ID = "KIND"; - private static Sorter ourKindSorter = new Sorter() - { - private Comparator myComparator = new Comparator() - { - @Override - public int compare(final Object o, final Object o2) - { - return getWeight(o) - getWeight(o2); - } - - private int getWeight(final Object s) - { - if(s instanceof JSSuperGroup) - { - return 5; - } - Object o = ((StructureViewTreeElement) s).getValue(); - - if(o instanceof JSProperty) - { - JSElement propertyValue = ((JSProperty) o).getValue(); - if(propertyValue instanceof JSFunction) - { - o = propertyValue; - } - } - - if(o instanceof JSClass) - { - return 7; - } - return 30; - } - }; - - @Override - public Comparator getComparator() - { - return myComparator; - } - - @Override - public boolean isVisible() - { - return false; - } - - @Override - @Nonnull - public ActionPresentation getPresentation() - { - return null; // will not be shown - } - - @Override - @Nonnull - public String getName() - { - return ID; - } - }; - - private Sorter[] mySorters = new Sorter[]{ - ourKindSorter, - Sorter.ALPHA_SORTER - }; - - private static Filter ourFieldsFilter = new Filter() - { - @NonNls - public static final String ID = "SHOW_FIELDS"; - - @Override - public boolean isVisible(TreeElement treeNode) - { - if(!(treeNode instanceof JSStructureViewElement)) - { - return true; - } - final PsiElement element = ((JSStructureViewElement) treeNode).getRealElement(); - - if(element instanceof JSClass) - { - return true; - } - - return element instanceof JSFunction || - (element instanceof JSProperty && ((JSProperty) element).getValue() instanceof JSFunction) || - element instanceof JSObjectLiteralExpression; - } - - @Override - public boolean isReverted() - { - return true; - } - - @Override - @Nonnull - public ActionPresentation getPresentation() - { - return new ActionPresentationData(IdeBundle.message("action.structureview.show.fields"), null, AllIcons.Nodes.Variable); - } - - @Override - @Nonnull - public String getName() - { - return ID; - } - }; - - private static final Filter ourInheritedFilter = new FileStructureFilter() - { - @NonNls - public static final String ID = "SHOW_INHERITED"; - - @Override - public boolean isVisible(TreeElement treeNode) - { - if(treeNode instanceof JSStructureViewElement) - { - return !((JSStructureViewElement) treeNode).isInherited(); - } - else - { - return true; - } - } - - @Override - @Nonnull - public ActionPresentation getPresentation() - { - return new ActionPresentationData(IdeBundle.message("action.structureview.show.inherited"), null, PlatformIconGroup.hierarchySupertypes()); - } - - @Override - @Nonnull - public String getName() - { - return ID; - } - - @Override - public boolean isReverted() - { - return true; - } - - @Override - public String getCheckBoxText() - { - return IdeBundle.message("file.structure.toggle.show.inherited"); - } - - @Override - public Shortcut[] getShortcut() - { - return KeymapManager.getInstance().getActiveKeymap().getShortcuts("FileStructurePopup"); - } - }; - - private static Grouper myInheritedGrouper = new JSSuperGrouper(); - - private Grouper[] myGroupers = new Grouper[]{ - myInheritedGrouper - }; - private final Class[] myClasses = new Class[]{ - JSFunction.class, - JSVariable.class, - JSDefinitionExpression.class, - JSClass.class, - JSProperty.class - }; - - public JSStructureViewModel(final PsiElement root) - { - super(root.getContainingFile()); - myRoot = root; - } - - public JSStructureViewModel(PsiElement root, final Editor editor) - { - super(editor); - myRoot = root; - } - - @Override - @Nonnull - public StructureViewTreeElement getRoot() - { - return new JSStructureViewElement(myRoot); - } - - @Override - @Nonnull - public Grouper[] getGroupers() - { - return myGroupers; - } - - @Override - @Nonnull - public Sorter[] getSorters() - { - return mySorters; - } - - @Override - @Nonnull - public Filter[] getFilters() - { - return myFilters; - } - - @Override - protected boolean isSuitable(final PsiElement element) - { - return super.isSuitable(element) && (!(element instanceof JSVariable) || PsiTreeUtil.getParentOfType(element, JSFunction.class) == null); - } - - @Override - public Object getCurrentEditorElement() - { - Object editorElement = super.getCurrentEditorElement(); - - final PsiFile file = getPsiFile(); - if(editorElement == null && !(file instanceof JSFile)) - { - final int offset = getEditor().getCaretModel().getOffset(); - final PsiElement at = file.findElementAt(offset); - final PsiLanguageInjectionHost injectionHost = PsiTreeUtil.getParentOfType(at, PsiLanguageInjectionHost.class); - - if(injectionHost != null) - { - final Ref ref = new Ref(); - InjectedLanguageManager.getInstance(file.getProject()).enumerate(injectionHost, new PsiLanguageInjectionHost.InjectedPsiVisitor() - { - @Override - public void visit(@Nonnull final PsiFile injectedPsi, @Nonnull final List places) - { - final PsiLanguageInjectionHost.Shred shred = places.get(0); - final int injectedStart = shred.getRangeInsideHost().getStartOffset() + shred.getHost().getTextOffset(); - final int offsetInInjected = offset - injectedStart; - - ref.set(injectedPsi.findElementAt(offsetInInjected)); - } - }); - - final PsiElement element = ref.get(); - if(element != null) - { - editorElement = findAcceptableElement(element); - return editorElement; - } - } - } - - if(editorElement instanceof JSDefinitionExpression) - { - final PsiElement element = ((PsiElement) editorElement).getParent(); - - if(element instanceof JSAssignmentExpression) - { - final JSExpression roperand = ((JSAssignmentExpression) element).getROperand(); - if(roperand instanceof JSFunctionExpression) - { - editorElement = roperand; - } - } - } - - if(editorElement instanceof JSNamedElement) - { - final PsiFile containingFile = ((PsiElement) editorElement).getContainingFile(); - final PsiElement context = containingFile.getContext(); - final int offset = ((PsiElement) editorElement).getTextOffset(); - final PsiElement element; - - if(context != null) - { - element = JavaScriptIndex.findSymbolWithNameAndOffsetInEntry(((JSNamedElement) editorElement).getName(), offset); - } - else - { - element = JavaScriptIndex.findSymbolByFileAndNameAndOffset(containingFile.getVirtualFile().getPath(), ((JSNamedElement) editorElement).getName(), - offset); - } - if(element != null) - { - editorElement = element; - } - } - return editorElement; - } - - @Override - protected PsiFile getPsiFile() - { - return myRoot.getContainingFile(); - } - - @Override - @Nonnull - protected Class[] getSuitableClasses() - { - return myClasses; - } - - public void setFilters(final Filter[] filters) - { - myFilters = filters; - } - - public void setGroupers(final Grouper[] groupers) - { - myGroupers = groupers; - } - - public void setSorters(final Sorter[] sorters) - { - mySorters = sorters; - } - - @Override - public boolean shouldEnterElement(final Object element) - { - return shouldEnterElementStatic(element); - } - - public static boolean shouldEnterElementStatic(final Object element) - { - return element instanceof JSClass; - } +public class JSStructureViewModel extends TextEditorBasedStructureViewModel { + private PsiElement myRoot; + private Filter[] myFilters = new Filter[]{ + ourFieldsFilter, + INHERITED_FILTER + }; + + private static final String ID = "KIND"; + private static Sorter ourKindSorter = new Sorter() { + private Comparator myComparator = new Comparator() { + @Override + @RequiredReadAction + public int compare(Object o, Object o2) { + return getWeight(o) - getWeight(o2); + } + + @RequiredReadAction + private int getWeight(Object s) { + if (s instanceof JSSuperGroup) { + return 5; + } + Object o = ((StructureViewTreeElement)s).getValue(); + + if (o instanceof JSProperty property && property.getValue() instanceof JSFunction function) { + o = function; + } + + if (o instanceof JSClass) { + return 7; + } + return 30; + } + }; + + @Override + public Comparator getComparator() { + return myComparator; + } + + @Override + public boolean isVisible() { + return false; + } + + @Override + @Nonnull + public ActionPresentation getPresentation() { + return null; // will not be shown + } + + @Override + @Nonnull + public String getName() { + return ID; + } + }; + + private Sorter[] mySorters = new Sorter[]{ + ourKindSorter, + Sorter.ALPHA_SORTER + }; + + private static Filter ourFieldsFilter = new Filter() { + public static final String ID = "SHOW_FIELDS"; + + @Override + @RequiredReadAction + public boolean isVisible(TreeElement treeNode) { + if (treeNode instanceof JSStructureViewElement structureViewElement) { + PsiElement element = structureViewElement.getRealElement(); + return element instanceof JSClass || element instanceof JSFunction + || (element instanceof JSProperty property && property.getValue() instanceof JSFunction) + || element instanceof JSObjectLiteralExpression; + } + return true; + } + + @Override + public boolean isReverted() { + return true; + } + + @Override + @Nonnull + public ActionPresentation getPresentation() { + return new ActionPresentationData(IdeLocalize.actionStructureviewShowFields().get(), null, AllIcons.Nodes.Variable); + } + + @Override + @Nonnull + public String getName() { + return ID; + } + }; + + private static final Filter INHERITED_FILTER = new FileStructureFilter() { + public static final String ID = "SHOW_INHERITED"; + + @Override + public boolean isVisible(TreeElement treeNode) { + return !(treeNode instanceof JSStructureViewElement structureViewElement && structureViewElement.isInherited()); + } + + @Override + @Nonnull + public ActionPresentation getPresentation() { + return new ActionPresentationData( + IdeLocalize.actionStructureviewShowInherited().get(), + null, + PlatformIconGroup.hierarchySupertypes() + ); + } + + @Override + @Nonnull + public String getName() { + return ID; + } + + @Override + public boolean isReverted() { + return true; + } + + @Override + public String getCheckBoxText() { + return IdeLocalize.fileStructureToggleShowInherited().get(); + } + + @Override + public Shortcut[] getShortcut() { + return KeymapManager.getInstance().getActiveKeymap().getShortcuts("FileStructurePopup"); + } + }; + + private static final Grouper INHERITED_GROUPER = new JSSuperGrouper(); + + private static final Class[] SUITABLE_CLASSES = new Class[]{ + JSFunction.class, + JSVariable.class, + JSDefinitionExpression.class, + JSClass.class, + JSProperty.class + }; + + private Grouper[] myGroupers = new Grouper[]{INHERITED_GROUPER}; + + public JSStructureViewModel(PsiElement root, Editor editor) { + super(editor); + myRoot = root; + } + + @Override + @Nonnull + public StructureViewTreeElement getRoot() { + return new JSStructureViewElement(myRoot); + } + + @Override + @Nonnull + public Grouper[] getGroupers() { + return myGroupers; + } + + @Override + @Nonnull + public Sorter[] getSorters() { + return mySorters; + } + + @Override + @Nonnull + public Filter[] getFilters() { + return myFilters; + } + + @Override + protected boolean isSuitable(PsiElement element) { + return super.isSuitable(element) + && !(element instanceof JSVariable variable && PsiTreeUtil.getParentOfType(variable, JSFunction.class) != null); + } + + @Override + @RequiredReadAction + public Object getCurrentEditorElement() { + Object editorElement = super.getCurrentEditorElement(); + + PsiFile file = getPsiFile(); + if (editorElement == null && !(file instanceof JSFile)) { + int offset = getEditor().getCaretModel().getOffset(); + PsiElement at = file.findElementAt(offset); + PsiLanguageInjectionHost injectionHost = PsiTreeUtil.getParentOfType(at, PsiLanguageInjectionHost.class); + + if (injectionHost != null) { + SimpleReference ref = new SimpleReference<>(); + InjectedLanguageManager.getInstance(file.getProject()).enumerate( + injectionHost, + (injectedPsi, places) -> { + PsiLanguageInjectionHost.Shred shred = places.get(0); + int injectedStart = shred.getRangeInsideHost().getStartOffset() + shred.getHost().getTextOffset(); + int offsetInInjected = offset - injectedStart; + + ref.set(injectedPsi.findElementAt(offsetInInjected)); + } + ); + + PsiElement element = ref.get(); + if (element != null) { + editorElement = findAcceptableElement(element); + return editorElement; + } + } + } + + if (editorElement instanceof JSDefinitionExpression definition + && definition.getParent() instanceof JSAssignmentExpression assignment + && assignment.getROperand() instanceof JSFunctionExpression functionExpr) { + editorElement = functionExpr; + } + + if (editorElement instanceof JSNamedElement namedElement) { + PsiFile containingFile = namedElement.getContainingFile(); + PsiElement context = containingFile.getContext(); + int offset = namedElement.getTextOffset(); + PsiElement element; + + if (context != null) { + element = JavaScriptIndex.findSymbolWithNameAndOffsetInEntry(namedElement.getName(), offset); + } + else { + element = JavaScriptIndex.findSymbolByFileAndNameAndOffset( + containingFile.getVirtualFile().getPath(), + namedElement.getName(), + offset + ); + } + + if (element != null) { + editorElement = element; + } + } + return editorElement; + } + + @Override + protected PsiFile getPsiFile() { + return myRoot.getContainingFile(); + } + + @Nonnull + @Override + protected Class[] getSuitableClasses() { + return SUITABLE_CLASSES; + } + + public void setFilters(Filter[] filters) { + myFilters = filters; + } + + public void setGroupers(Grouper[] groupers) { + myGroupers = groupers; + } + + public void setSorters(Sorter[] sorters) { + mySorters = sorters; + } + + @Override + public boolean shouldEnterElement(Object element) { + return shouldEnterElementStatic(element); + } + + public static boolean shouldEnterElementStatic(Object element) { + return element instanceof JSClass; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/structureView/JSSuperGroup.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/structureView/JSSuperGroup.java index 910aa90d..3053b8a3 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/structureView/JSSuperGroup.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/structureView/JSSuperGroup.java @@ -20,62 +20,53 @@ import java.util.Collection; import java.util.List; -import javax.annotation.Nullable; - -import consulo.application.AllIcons; import consulo.fileEditor.structureView.tree.Group; import consulo.navigation.ItemPresentation; import consulo.fileEditor.structureView.tree.TreeElement; +import consulo.platform.base.icon.PlatformIconGroup; import consulo.ui.image.Image; +import jakarta.annotation.Nullable; /** * @author Maxim.Mossienko */ -public class JSSuperGroup implements Group, ItemPresentation -{ - private final String myName; - private final List myChildren; +public class JSSuperGroup implements Group, ItemPresentation { + private final String myName; + private final List myChildren; - public JSSuperGroup(final String name) - { - myName = name; - myChildren = new ArrayList(); - } + public JSSuperGroup(String name) { + myName = name; + myChildren = new ArrayList<>(); + } - @Override - public ItemPresentation getPresentation() - { - return this; - } + @Override + public ItemPresentation getPresentation() { + return this; + } - @Override - public Collection getChildren() - { - return myChildren; - } + @Override + public Collection getChildren() { + return myChildren; + } - @Override - public String getPresentableText() - { - return myName; - } + @Override + public String getPresentableText() { + return myName; + } - @Override - @Nullable - public String getLocationString() - { - return null; - } + @Override + @Nullable + public String getLocationString() { + return null; + } - @Override - @Nullable - public Image getIcon() - { - return AllIcons.General.InheritedMethod; - } + @Override + @Nullable + public Image getIcon() { + return PlatformIconGroup.hierarchySubtypes(); + } - void addChild(TreeElement element) - { - myChildren.add(element); - } + void addChild(TreeElement element) { + myChildren.add(element); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/structureView/JSSuperGrouper.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/structureView/JSSuperGrouper.java index 5570172a..d0813dfa 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/structureView/JSSuperGrouper.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/structureView/JSSuperGrouper.java @@ -16,19 +16,19 @@ package com.intellij.lang.javascript.impl.structureView; -import consulo.fileEditor.structureView.tree.*; -import consulo.project.ui.view.tree.AbstractTreeNode; import com.intellij.lang.javascript.psi.JSClass; import com.intellij.lang.javascript.psi.JSFunction; import com.intellij.lang.javascript.psi.JSVarStatement; import com.intellij.lang.javascript.psi.JSVariable; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; +import consulo.annotation.access.RequiredReadAction; +import consulo.fileEditor.structureView.tree.*; +import consulo.ide.localize.IdeLocalize; import consulo.language.psi.PsiElement; -import consulo.ide.IdeBundle; import consulo.platform.base.icon.PlatformIconGroup; -import org.jetbrains.annotations.NonNls; +import consulo.project.ui.view.tree.AbstractTreeNode; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -37,103 +37,93 @@ /** * @author Maxim.Mossienko */ -class JSSuperGrouper implements Grouper -{ - @NonNls - private static final String SHOW_CLASSES = "SHOW_CLASSES"; +class JSSuperGrouper implements Grouper { + private static final String SHOW_CLASSES = "SHOW_CLASSES"; - @Override - @Nonnull - public Collection group(final Object parent, final Collection children) - { - if(isParentGrouped((AbstractTreeNode) parent)) - { - return Collections.emptyList(); - } - final Map groups = new HashMap(); + @Nonnull + @Override + @RequiredReadAction + public Collection group(Object parent, Collection children) { + AbstractTreeNode parentNode = (AbstractTreeNode)parent; + if (isParentGrouped(parentNode)) { + return Collections.emptyList(); + } + Map groups = new HashMap<>(); - for(TreeElement _child : children) - { - if(!(_child instanceof JSStructureViewElement)) - { - continue; - } - JSStructureViewElement child = (JSStructureViewElement) _child; - final PsiElement value = child.getValue(); + for (TreeElement _child : children) { + if (!(_child instanceof JSStructureViewElement)) { + continue; + } + JSStructureViewElement child = (JSStructureViewElement)_child; + PsiElement value = child.getValue(); - if(value instanceof JSVariable) - { - if(!child.isInherited()) - { - continue; - } - PsiElement parentElement = value.getParent(); - if(parentElement instanceof JSVarStatement) - { - parentElement = parentElement.getParent(); - } - if(parentElement instanceof JSClass) - { - addGroup(groups, _child, ((JSClass) parentElement).getQualifiedName()); - } - } - else if(value instanceof JSFunction) - { - processFunction((JSStructureViewElement) ((AbstractTreeNode) parent).getValue(), groups, _child, value); - } - } - return groups.values(); - } + if (value instanceof JSVariable variable) { + if (!child.isInherited()) { + continue; + } + PsiElement parentElement = variable.getParent(); + if (parentElement instanceof JSVarStatement varStatement) { + parentElement = varStatement.getParent(); + } + if (parentElement instanceof JSClass jsClass) { + addGroup(groups, _child, jsClass.getQualifiedName()); + } + } + else if (value instanceof JSFunction function) { + processFunction((JSStructureViewElement)parentNode.getValue(), groups, _child, function); + } + } + return groups.values(); + } - private static void processFunction(JSStructureViewElement parentElement, Map groups, TreeElement _child, PsiElement value) - { - final PsiElement element = JSStructureViewElement.getPsiElementResolveProxy(parentElement); - if(element instanceof JSClass) - { - JSClass parentClass = (JSClass) element; - JSClass declaringClass = JSResolveUtil.findDeclaringClass((JSFunction) value); - if(parentClass != declaringClass) - { - addGroup(groups, _child, declaringClass.getQualifiedName()); - } - } - } + @RequiredReadAction + private static void processFunction( + JSStructureViewElement parentElement, + Map groups, + TreeElement _child, + PsiElement value + ) { + PsiElement element = JSStructureViewElement.getPsiElementResolveProxy(parentElement); + if (element instanceof JSClass parentClass) { + JSClass declaringClass = JSResolveUtil.findDeclaringClass((JSFunction)value); + if (parentClass != declaringClass) { + addGroup(groups, _child, declaringClass.getQualifiedName()); + } + } + } - private static void addGroup(final Map groups, final TreeElement _child, final String qName) - { - JSSuperGroup group; - if((group = ((JSSuperGroup) groups.get(qName))) == null) - { - groups.put(qName, group = new JSSuperGroup(qName)); - } + private static void addGroup(Map groups, TreeElement _child, String qName) { + JSSuperGroup group = (JSSuperGroup)groups.get(qName); + if (group == null) { + groups.put(qName, group = new JSSuperGroup(qName)); + } - group.addChild(_child); - } + group.addChild(_child); + } - @Override - @Nonnull - public ActionPresentation getPresentation() - { - return new ActionPresentationData(IdeBundle.message("action.structureview.group.methods.by.defining.type"), null, PlatformIconGroup.generalImplementingmethod()); - } + @Override + @Nonnull + public ActionPresentation getPresentation() { + return new ActionPresentationData( + IdeLocalize.actionStructureviewGroupMethodsByDefiningType().get(), + null, + PlatformIconGroup.gutterImplementingmethod() + ); + } - @Override - @Nonnull - public String getName() - { - return SHOW_CLASSES; - } + @Override + @Nonnull + public String getName() { + return SHOW_CLASSES; + } - private static boolean isParentGrouped(AbstractTreeNode parent) - { - while(parent != null) - { - if(parent.getValue() instanceof JSSuperGroup) - { - return true; - } - parent = (AbstractTreeNode) parent.getParent(); - } - return false; - } + private static boolean isParentGrouped(AbstractTreeNode parent) { + while (parent != null) { + if (parent.getValue() instanceof JSSuperGroup) { + return true; + } + parent = (AbstractTreeNode)parent.getParent(); + } + return false; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSExpressionSurroundDescriptor.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSExpressionSurroundDescriptor.java index 9a7cb915..4a9ee296 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSExpressionSurroundDescriptor.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSExpressionSurroundDescriptor.java @@ -19,6 +19,7 @@ import com.intellij.lang.javascript.psi.JSCallExpression; import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.JSReferenceExpression; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; import consulo.javascript.language.JavaScriptLanguage; import consulo.language.Language; @@ -28,74 +29,63 @@ import consulo.language.psi.PsiFile; import consulo.language.psi.PsiWhiteSpace; import consulo.language.psi.util.PsiTreeUtil; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** - * User: yole - * Date: 12.07.2005 - * Time: 12:46:24 + * @author yole + * @since 2005-07-12 */ @ExtensionImpl -public class JSExpressionSurroundDescriptor implements SurroundDescriptor -{ - private static final Surrounder[] SURROUNDERS = { - new JSWithParenthesesSurrounder() - }; +public class JSExpressionSurroundDescriptor implements SurroundDescriptor { + private static final Surrounder[] SURROUNDERS = { + new JSWithParenthesesSurrounder() + }; - @Override - @Nonnull - public PsiElement[] getElementsToSurround(PsiFile file, int startOffset, int endOffset) - { - final JSExpression expr = findExpressionInRange(file, startOffset, endOffset); - if(expr == null) - { - return PsiElement.EMPTY_ARRAY; - } - return new PsiElement[]{expr}; - } + @Override + @Nonnull + @RequiredReadAction + public PsiElement[] getElementsToSurround(PsiFile file, int startOffset, int endOffset) { + JSExpression expr = findExpressionInRange(file, startOffset, endOffset); + if (expr == null) { + return PsiElement.EMPTY_ARRAY; + } + return new PsiElement[]{expr}; + } - @Override - @Nonnull - public Surrounder[] getSurrounders() - { - return SURROUNDERS; - } + @Override + @Nonnull + public Surrounder[] getSurrounders() { + return SURROUNDERS; + } - @Override - public boolean isExclusive() - { - return false; - } + @Override + public boolean isExclusive() { + return false; + } - private static JSExpression findExpressionInRange(PsiFile file, int startOffset, int endOffset) - { - PsiElement element1 = file.findElementAt(startOffset); - PsiElement element2 = file.findElementAt(endOffset - 1); - if(element1 instanceof PsiWhiteSpace) - { - startOffset = element1.getTextRange().getEndOffset(); - } - if(element2 instanceof PsiWhiteSpace) - { - endOffset = element2.getTextRange().getStartOffset(); - } - JSExpression expression = PsiTreeUtil.findElementOfClassAtRange(file, startOffset, endOffset, JSExpression.class); - if(expression == null || expression.getTextRange().getEndOffset() != endOffset) - { - return null; - } - if(expression instanceof JSReferenceExpression && expression.getParent() instanceof JSCallExpression) - { - return null; - } - return expression; - } + @RequiredReadAction + private static JSExpression findExpressionInRange(PsiFile file, int startOffset, int endOffset) { + PsiElement element1 = file.findElementAt(startOffset); + PsiElement element2 = file.findElementAt(endOffset - 1); + if (element1 instanceof PsiWhiteSpace whiteSpace) { + startOffset = whiteSpace.getTextRange().getEndOffset(); + } + if (element2 instanceof PsiWhiteSpace whiteSpace) { + endOffset = whiteSpace.getTextRange().getStartOffset(); + } + JSExpression expression = PsiTreeUtil.findElementOfClassAtRange(file, startOffset, endOffset, JSExpression.class); + if (expression == null || expression.getTextRange().getEndOffset() != endOffset) { + return null; + } + if (expression instanceof JSReferenceExpression && expression.getParent() instanceof JSCallExpression) { + return null; + } + return expression; + } - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSStatementSurrounder.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSStatementSurrounder.java index f98ff314..92ec0112 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSStatementSurrounder.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSStatementSurrounder.java @@ -16,67 +16,59 @@ package com.intellij.lang.javascript.impl.surroundWith; -import javax.annotation.Nonnull; - +import com.intellij.lang.javascript.psi.impl.JSChangeUtil; +import consulo.annotation.access.RequiredReadAction; import consulo.codeEditor.Editor; +import consulo.document.util.TextRange; +import consulo.language.ast.ASTNode; import consulo.language.codeStyle.CodeStyleManager; import consulo.language.editor.surroundWith.Surrounder; -import consulo.project.Project; -import consulo.language.util.IncorrectOperationException; -import org.jetbrains.annotations.NonNls; - -import javax.annotation.Nullable; -import consulo.language.ast.ASTNode; -import com.intellij.lang.javascript.psi.impl.JSChangeUtil; -import consulo.document.util.TextRange; import consulo.language.psi.PsiElement; +import consulo.language.util.IncorrectOperationException; +import consulo.project.Project; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** - * Created by IntelliJ IDEA. - * User: yole - * Date: 12.07.2005 - * Time: 16:50:58 - * To change this template use File | Settings | File Templates. + * @author yole + * @since 2005-07-12 */ -public abstract class JSStatementSurrounder implements Surrounder -{ - @Override - public boolean isApplicable(@Nonnull PsiElement[] elements) - { - return true; - } +public abstract class JSStatementSurrounder implements Surrounder { + @Override + public boolean isApplicable(@Nonnull PsiElement[] elements) { + return true; + } - @Override - @Nullable - public TextRange surroundElements(@Nonnull Project project, @Nonnull Editor editor, @Nonnull PsiElement[] elements) throws - IncorrectOperationException - { - ASTNode node = JSChangeUtil.createStatementFromText(project, getStatementTemplate(project, elements[0])); + @Override + @Nullable + @RequiredReadAction + public TextRange surroundElements(@Nonnull Project project, @Nonnull Editor editor, @Nonnull PsiElement[] elements) + throws IncorrectOperationException { + ASTNode node = JSChangeUtil.createStatementFromText(project, getStatementTemplate(project, elements[0])); - PsiElement container = elements[0].getParent(); - container.getNode().addChild(node, elements[0].getNode()); - final ASTNode insertBeforeNode = getInsertBeforeNode(node); + PsiElement container = elements[0].getParent(); + container.getNode().addChild(node, elements[0].getNode()); + ASTNode insertBeforeNode = getInsertBeforeNode(node); - for(int i = 0; i < elements.length; i++) - { - final ASTNode childNode = elements[i].getNode(); - final ASTNode childNodeCopy = childNode.copyElement(); + for (PsiElement element : elements) { + ASTNode childNode = element.getNode(); + ASTNode childNodeCopy = childNode.copyElement(); - container.getNode().removeChild(childNode); - insertBeforeNode.getTreeParent().addChild(childNodeCopy, insertBeforeNode); - } + container.getNode().removeChild(childNode); + insertBeforeNode.getTreeParent().addChild(childNodeCopy, insertBeforeNode); + } - final CodeStyleManager csManager = CodeStyleManager.getInstance(project); - csManager.reformat(node.getPsi()); + CodeStyleManager csManager = CodeStyleManager.getInstance(project); + csManager.reformat(node.getPsi()); - return getSurroundSelectionRange(node); - } + return getSurroundSelectionRange(node); + } - protected abstract - @NonNls - String getStatementTemplate(final Project project, PsiElement context); + protected abstract String getStatementTemplate(Project project, PsiElement context); - protected abstract ASTNode getInsertBeforeNode(final ASTNode statementNode); + @RequiredReadAction + protected abstract ASTNode getInsertBeforeNode(ASTNode statementNode); - protected abstract TextRange getSurroundSelectionRange(final ASTNode statementNode); + @RequiredReadAction + protected abstract TextRange getSurroundSelectionRange(ASTNode statementNode); } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSStatementsSurroundDescriptor.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSStatementsSurroundDescriptor.java index 8f651c80..145b8c48 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSStatementsSurroundDescriptor.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSStatementsSurroundDescriptor.java @@ -20,6 +20,7 @@ import com.intellij.lang.javascript.psi.JSFile; import com.intellij.lang.javascript.psi.JSStatement; import com.intellij.lang.javascript.psi.impl.JSEmbeddedContentImpl; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; import consulo.javascript.language.JavaScriptLanguage; import consulo.language.Language; @@ -32,159 +33,139 @@ import consulo.language.psi.PsiWhiteSpace; import consulo.language.psi.util.PsiTreeUtil; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; + import java.util.ArrayList; import java.util.List; /** - * User: yole - * Date: 12.07.2005 - * Time: 14:14:55 + * @author yole + * @since 2005-07-12 */ @ExtensionImpl -public class JSStatementsSurroundDescriptor implements SurroundDescriptor -{ - private static final Surrounder[] SURROUNDERS = { - new JSWithBlockSurrounder(), - new JSWithIfSurrounder(), - new JSWithIfElseSurrounder(), - new JSWithWhileSurrounder(), - new JSWithDoWhileSurrounder(), - new JSWithForSurrounder(), - new JSWithTryCatchSurrounder(), - new JSWithTryFinallySurrounder(), - new JSWithTryCatchFinallySurrounder(), - new JSWithWithSurrounder(), - new JSWithFunctionSurrounder(), - new JSWithFunctionExpressionSurrounder(), - }; - - @Override - @Nonnull - public PsiElement[] getElementsToSurround(PsiFile file, int startOffset, int endOffset) - { - final PsiElement[] statements = findStatementsInRange(file, startOffset, endOffset); - if(statements == null) - { - return PsiElement.EMPTY_ARRAY; - } - return statements; - } - - @Override - @Nonnull - public Surrounder[] getSurrounders() - { - return SURROUNDERS; - } - - @Override - public boolean isExclusive() - { - return false; - } - - private PsiElement[] findStatementsInRange(PsiFile file, int startOffset, int endOffset) - { - PsiElement element1 = file.findElementAt(startOffset); - PsiElement element2 = file.findElementAt(endOffset - 1); - if(element1 instanceof PsiWhiteSpace) - { - startOffset = element1.getTextRange().getEndOffset(); - element1 = file.findElementAt(startOffset); - } - if(element2 instanceof PsiWhiteSpace) - { - endOffset = element2.getTextRange().getStartOffset(); - element2 = file.findElementAt(endOffset - 1); - } - if(element1 == null || element2 == null) - { - return null; - } - - final JSStatement statement = PsiTreeUtil.getParentOfType(element1, JSStatement.class); - final JSStatement statement2 = PsiTreeUtil.getParentOfType(element2, JSStatement.class); - - PsiElement parent = PsiTreeUtil.findCommonParent(element1, element2); - while(true) - { - if(parent instanceof JSBlockStatement || ((parent instanceof JSEmbeddedContentImpl || parent instanceof JSFile) && (statement != null && - statement2 != null && PsiTreeUtil.isAncestor(parent, statement, false) && PsiTreeUtil.isAncestor(parent, statement2, false)))) - { - break; - } - if(parent instanceof JSStatement) - { - parent = parent.getParent(); - break; - } - if(parent instanceof PsiFile) - { - return null; - } - parent = parent.getParent(); - } - - - while(!element1.getParent().equals(parent)) - { - element1 = element1.getParent(); - } - if(startOffset != element1.getTextRange().getStartOffset()) - { - return null; - } - - while(!element2.getParent().equals(parent)) - { - element2 = element2.getParent(); - } - if(endOffset != element2.getTextRange().getEndOffset()) - { - return null; - } - - final ASTNode[] astNodes = parent.getNode().getChildren(null); - List children = new ArrayList(astNodes.length); - for(ASTNode node : astNodes) - { - children.add(node.getPsi()); - } - - ArrayList array = new ArrayList(); - boolean flag = false; - for(PsiElement child : children) - { - if(child.equals(element1)) - { - flag = true; - } - if(flag /*&& !(child instanceof PsiWhiteSpace)*/) - { - array.add(child); - } - if(child.equals(element2)) - { - break; - } - } - - for(PsiElement element : array) - { - if(!(element instanceof JSStatement || element instanceof PsiWhiteSpace || element instanceof PsiComment)) - { - return null; - } - } - - return array.toArray(new PsiElement[array.size()]); - } - - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } +public class JSStatementsSurroundDescriptor implements SurroundDescriptor { + private static final Surrounder[] SURROUNDERS = { + new JSWithBlockSurrounder(), + new JSWithIfSurrounder(), + new JSWithIfElseSurrounder(), + new JSWithWhileSurrounder(), + new JSWithDoWhileSurrounder(), + new JSWithForSurrounder(), + new JSWithTryCatchSurrounder(), + new JSWithTryFinallySurrounder(), + new JSWithTryCatchFinallySurrounder(), + new JSWithWithSurrounder(), + new JSWithFunctionSurrounder(), + new JSWithFunctionExpressionSurrounder(), + }; + + @Override + @Nonnull + @RequiredReadAction + public PsiElement[] getElementsToSurround(PsiFile file, int startOffset, int endOffset) { + PsiElement[] statements = findStatementsInRange(file, startOffset, endOffset); + if (statements == null) { + return PsiElement.EMPTY_ARRAY; + } + return statements; + } + + @Override + @Nonnull + public Surrounder[] getSurrounders() { + return SURROUNDERS; + } + + @Override + public boolean isExclusive() { + return false; + } + + @RequiredReadAction + private PsiElement[] findStatementsInRange(PsiFile file, int startOffset, int endOffset) { + PsiElement element1 = file.findElementAt(startOffset); + PsiElement element2 = file.findElementAt(endOffset - 1); + if (element1 instanceof PsiWhiteSpace whiteSpace) { + startOffset = whiteSpace.getTextRange().getEndOffset(); + element1 = file.findElementAt(startOffset); + } + + if (element2 instanceof PsiWhiteSpace whiteSpace) { + endOffset = whiteSpace.getTextRange().getStartOffset(); + element2 = file.findElementAt(endOffset - 1); + } + + if (element1 == null || element2 == null) { + return null; + } + + JSStatement statement = PsiTreeUtil.getParentOfType(element1, JSStatement.class); + JSStatement statement2 = PsiTreeUtil.getParentOfType(element2, JSStatement.class); + + PsiElement parent = PsiTreeUtil.findCommonParent(element1, element2); + while (true) { + if (parent instanceof JSBlockStatement || ((parent instanceof JSEmbeddedContentImpl || parent instanceof JSFile) + && (statement != null && statement2 != null && PsiTreeUtil.isAncestor(parent, statement, false) + && PsiTreeUtil.isAncestor(parent, statement2, false)))) { + break; + } + if (parent instanceof JSStatement parentStatement) { + parent = parentStatement.getParent(); + break; + } + if (parent instanceof PsiFile) { + return null; + } + parent = parent.getParent(); + } + + while (!element1.getParent().equals(parent)) { + element1 = element1.getParent(); + } + + if (startOffset != element1.getTextRange().getStartOffset()) { + return null; + } + + while (!element2.getParent().equals(parent)) { + element2 = element2.getParent(); + } + if (endOffset != element2.getTextRange().getEndOffset()) { + return null; + } + + ASTNode[] astNodes = parent.getNode().getChildren(null); + List children = new ArrayList<>(astNodes.length); + for (ASTNode node : astNodes) { + children.add(node.getPsi()); + } + + ArrayList array = new ArrayList<>(); + boolean flag = false; + for (PsiElement child : children) { + if (child.equals(element1)) { + flag = true; + } + if (flag /*&& !(child instanceof PsiWhiteSpace)*/) { + array.add(child); + } + if (child.equals(element2)) { + break; + } + } + + for (PsiElement element : array) { + if (!(element instanceof JSStatement || element instanceof PsiWhiteSpace || element instanceof PsiComment)) { + return null; + } + } + + return array.toArray(new PsiElement[array.size()]); + } + + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithBlockSurrounder.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithBlockSurrounder.java index 43a566f0..a432e959 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithBlockSurrounder.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithBlockSurrounder.java @@ -16,42 +16,38 @@ package com.intellij.lang.javascript.impl.surroundWith; +import consulo.annotation.access.RequiredReadAction; import consulo.document.util.TextRange; import consulo.language.ast.ASTNode; +import consulo.localize.LocalizeValue; import consulo.project.Project; import consulo.language.psi.PsiElement; /** - * Created by IntelliJ IDEA. - * User: yole - * Date: 12.07.2005 - * Time: 14:15:25 - * To change this template use File | Settings | File Templates. + * @author yole + * @since 2005-07-12 */ -public class JSWithBlockSurrounder extends JSStatementSurrounder -{ - @Override - public String getTemplateDescription() - { - return "{ }"; - } +public class JSWithBlockSurrounder extends JSStatementSurrounder { + @Override + public LocalizeValue getTemplateDescription() { + return LocalizeValue.localizeTODO("{ }"); + } - @Override - protected String getStatementTemplate(final Project project, PsiElement context) - { - return "{ }"; - } + @Override + protected String getStatementTemplate(Project project, PsiElement context) { + return "{ }"; + } - @Override - protected ASTNode getInsertBeforeNode(final ASTNode statementNode) - { - return statementNode.getLastChildNode(); - } + @Override + @RequiredReadAction + protected ASTNode getInsertBeforeNode(ASTNode statementNode) { + return statementNode.getLastChildNode(); + } - @Override - protected TextRange getSurroundSelectionRange(final ASTNode statementNode) - { - int endOffset = statementNode.getTextRange().getEndOffset(); - return new TextRange(endOffset, endOffset); - } + @Override + @RequiredReadAction + protected TextRange getSurroundSelectionRange(ASTNode statementNode) { + int endOffset = statementNode.getTextRange().getEndOffset(); + return new TextRange(endOffset, endOffset); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithDoWhileSurrounder.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithDoWhileSurrounder.java index d8423c32..2a3f142d 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithDoWhileSurrounder.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithDoWhileSurrounder.java @@ -16,45 +16,41 @@ package com.intellij.lang.javascript.impl.surroundWith; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.psi.JSDoWhileStatement; +import consulo.annotation.access.RequiredReadAction; import consulo.document.util.TextRange; +import consulo.javascript.localize.JavaScriptLocalize; +import consulo.language.ast.ASTNode; import consulo.language.psi.PsiElement; +import consulo.localize.LocalizeValue; import consulo.project.Project; -import consulo.language.ast.ASTNode; /** - * Created by IntelliJ IDEA. - * User: yole - * Date: 12.07.2005 - * Time: 18:07:02 - * To change this template use File | Settings | File Templates. + * @author yole + * @since 2005-07-12 */ -public class JSWithDoWhileSurrounder extends JSStatementSurrounder -{ - @Override - public String getTemplateDescription() - { - return JavaScriptBundle.message("javascript.surround.with.do.while"); - } +public class JSWithDoWhileSurrounder extends JSStatementSurrounder { + @Override + public LocalizeValue getTemplateDescription() { + return JavaScriptLocalize.javascriptSurroundWithDoWhile(); + } - @Override - protected String getStatementTemplate(final Project project, PsiElement context) - { - return "do { } while (true);"; - } + @Override + protected String getStatementTemplate(Project project, PsiElement context) { + return "do { } while (true);"; + } - @Override - protected ASTNode getInsertBeforeNode(final ASTNode statementNode) - { - JSDoWhileStatement stmt = (JSDoWhileStatement) statementNode.getPsi(); - return stmt.getBody().getLastChild().getNode(); - } + @Override + @RequiredReadAction + protected ASTNode getInsertBeforeNode(ASTNode statementNode) { + JSDoWhileStatement stmt = (JSDoWhileStatement)statementNode.getPsi(); + return stmt.getBody().getLastChild().getNode(); + } - @Override - protected TextRange getSurroundSelectionRange(final ASTNode statementNode) - { - JSDoWhileStatement stmt = (JSDoWhileStatement) statementNode.getPsi(); - return stmt.getCondition().getTextRange(); - } + @Override + @RequiredReadAction + protected TextRange getSurroundSelectionRange(ASTNode statementNode) { + JSDoWhileStatement stmt = (JSDoWhileStatement)statementNode.getPsi(); + return stmt.getCondition().getTextRange(); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithForSurrounder.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithForSurrounder.java index 393892bf..70f453bf 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithForSurrounder.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithForSurrounder.java @@ -16,61 +16,54 @@ package com.intellij.lang.javascript.impl.surroundWith; -import consulo.document.util.TextRange; -import consulo.language.ast.ASTNode; import com.intellij.lang.javascript.JSTokenTypes; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.JSForStatement; +import consulo.annotation.access.RequiredReadAction; +import consulo.document.util.TextRange; +import consulo.javascript.localize.JavaScriptLocalize; +import consulo.language.ast.ASTNode; import consulo.language.psi.PsiElement; -import consulo.project.Project; import consulo.language.psi.PsiWhiteSpace; +import consulo.localize.LocalizeValue; +import consulo.project.Project; /** - * Created by IntelliJ IDEA. - * User: yole - * Date: 12.07.2005 - * Time: 18:29:38 - * To change this template use File | Settings | File Templates. + * @author yole + * @since 2005-07-12 */ -public class JSWithForSurrounder extends JSStatementSurrounder -{ - @Override - public String getTemplateDescription() - { - return JavaScriptBundle.message("javascript.surround.with.for"); - } +public class JSWithForSurrounder extends JSStatementSurrounder { + @Override + public LocalizeValue getTemplateDescription() { + return JavaScriptLocalize.javascriptSurroundWithFor(); + } - @Override - protected String getStatementTemplate(final Project project, PsiElement context) - { - return "for(i=0; i<1; i++) { }"; - } + @Override + protected String getStatementTemplate(Project project, PsiElement context) { + return "for(i=0; i<1; i++) { }"; + } - @Override - protected ASTNode getInsertBeforeNode(final ASTNode statementNode) - { - JSForStatement forStatement = (JSForStatement) statementNode.getPsi(); - return forStatement.getBody().getLastChild().getNode(); - } + @Override + @RequiredReadAction + protected ASTNode getInsertBeforeNode(ASTNode statementNode) { + JSForStatement forStatement = (JSForStatement)statementNode.getPsi(); + return forStatement.getBody().getLastChild().getNode(); + } - @Override - protected TextRange getSurroundSelectionRange(final ASTNode statementNode) - { - for(ASTNode childNode : statementNode.getChildren(null)) - { - if(childNode.getElementType() == JSTokenTypes.SEMICOLON || - childNode.getPsi() instanceof PsiWhiteSpace || - childNode.getPsi() instanceof JSExpression) - { - statementNode.removeChild(childNode); - } - else if(childNode.getElementType() == JSTokenTypes.RPAR) - { - int offset = childNode.getStartOffset(); - return new TextRange(offset, offset); - } - } - return null; - } + @Override + @RequiredReadAction + protected TextRange getSurroundSelectionRange(ASTNode statementNode) { + for (ASTNode childNode : statementNode.getChildren(null)) { + if (childNode.getElementType() == JSTokenTypes.SEMICOLON + || childNode.getPsi() instanceof PsiWhiteSpace + || childNode.getPsi() instanceof JSExpression) { + statementNode.removeChild(childNode); + } + else if (childNode.getElementType() == JSTokenTypes.RPAR) { + int offset = childNode.getStartOffset(); + return new TextRange(offset, offset); + } + } + return null; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithFunctionExpressionSurrounder.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithFunctionExpressionSurrounder.java index 048a8872..9aee08d0 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithFunctionExpressionSurrounder.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithFunctionExpressionSurrounder.java @@ -16,50 +16,51 @@ package com.intellij.lang.javascript.impl.surroundWith; -import consulo.language.ast.ASTNode; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.psi.JSAssignmentExpression; import com.intellij.lang.javascript.psi.JSExpressionStatement; import com.intellij.lang.javascript.psi.JSFunctionExpression; import com.intellij.lang.javascript.psi.impl.JSChangeUtil; +import consulo.annotation.access.RequiredReadAction; import consulo.document.util.TextRange; +import consulo.javascript.localize.JavaScriptLocalize; +import consulo.language.ast.ASTNode; import consulo.language.psi.PsiElement; +import consulo.localize.LocalizeValue; import consulo.project.Project; -public class JSWithFunctionExpressionSurrounder extends JSStatementSurrounder -{ - @Override - public String getTemplateDescription() - { - return JavaScriptBundle.message("javascript.surround.with.function.expression"); - } +public class JSWithFunctionExpressionSurrounder extends JSStatementSurrounder { + @Override + public LocalizeValue getTemplateDescription() { + return JavaScriptLocalize.javascriptSurroundWithFunctionExpression(); + } - @Override - protected String getStatementTemplate(final Project project, PsiElement context) - { - return "aaa = function () { }" + JSChangeUtil.getSemicolon(project); - } + @Override + protected String getStatementTemplate(Project project, PsiElement context) { + return "aaa = function () { }" + JSChangeUtil.getSemicolon(project); + } - @Override - protected ASTNode getInsertBeforeNode(final ASTNode statementNode) - { - JSFunctionExpression stmt = getFunctionExpr(statementNode); - return stmt.getBody()[0].getLastChild().getNode(); - } + @Override + @RequiredReadAction + protected ASTNode getInsertBeforeNode(ASTNode statementNode) { + JSFunctionExpression stmt = getFunctionExpr(statementNode); + return stmt.getBody()[0].getLastChild().getNode(); + } - private static JSFunctionExpression getFunctionExpr(final ASTNode statementNode) - { - return (JSFunctionExpression) ((JSAssignmentExpression) ((JSExpressionStatement) statementNode.getPsi()).getExpression()).getROperand(); - } + @RequiredReadAction + private static JSFunctionExpression getFunctionExpr(ASTNode statementNode) { + JSExpressionStatement expression = (JSExpressionStatement)statementNode.getPsi(); + JSAssignmentExpression assignment = (JSAssignmentExpression)expression.getExpression(); + return (JSFunctionExpression)assignment.getROperand(); + } - @Override - protected TextRange getSurroundSelectionRange(final ASTNode statementNode) - { - JSFunctionExpression stmt = getFunctionExpr(statementNode); - ASTNode conditionNode = stmt.getNameIdentifier().getNode(); - int offset = conditionNode.getStartOffset(); - stmt.getParent().getNode().removeChild(conditionNode); + @Override + @RequiredReadAction + protected TextRange getSurroundSelectionRange(ASTNode statementNode) { + JSFunctionExpression stmt = getFunctionExpr(statementNode); + ASTNode conditionNode = stmt.getNameIdentifier().getNode(); + int offset = conditionNode.getStartOffset(); + stmt.getParent().getNode().removeChild(conditionNode); - return new TextRange(offset, offset); - } + return new TextRange(offset, offset); + } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithFunctionSurrounder.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithFunctionSurrounder.java index 1d7ce44f..055f8da2 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithFunctionSurrounder.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithFunctionSurrounder.java @@ -16,42 +16,41 @@ package com.intellij.lang.javascript.impl.surroundWith; -import consulo.language.ast.ASTNode; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.psi.JSFunction; -import consulo.project.Project; +import consulo.annotation.access.RequiredReadAction; import consulo.document.util.TextRange; +import consulo.javascript.localize.JavaScriptLocalize; +import consulo.language.ast.ASTNode; import consulo.language.psi.PsiElement; +import consulo.localize.LocalizeValue; +import consulo.project.Project; -public class JSWithFunctionSurrounder extends JSStatementSurrounder -{ - @Override - public String getTemplateDescription() - { - return JavaScriptBundle.message("javascript.surround.with.function"); - } +public class JSWithFunctionSurrounder extends JSStatementSurrounder { + @Override + public LocalizeValue getTemplateDescription() { + return JavaScriptLocalize.javascriptSurroundWithFunction(); + } - @Override - protected String getStatementTemplate(final Project project, PsiElement context) - { - return "function $name$() { }"; - } + @Override + protected String getStatementTemplate(Project project, PsiElement context) { + return "function $name$() { }"; + } - @Override - protected ASTNode getInsertBeforeNode(final ASTNode statementNode) - { - JSFunction stmt = (JSFunction) statementNode.getPsi(); - return stmt.getBody()[0].getLastChild().getNode(); - } + @Override + @RequiredReadAction + protected ASTNode getInsertBeforeNode(ASTNode statementNode) { + JSFunction stmt = (JSFunction)statementNode.getPsi(); + return stmt.getBody()[0].getLastChild().getNode(); + } - @Override - protected TextRange getSurroundSelectionRange(final ASTNode statementNode) - { - JSFunction stmt = (JSFunction) statementNode.getPsi(); - ASTNode conditionNode = stmt.getNameIdentifier().getNode(); - int offset = conditionNode.getStartOffset(); - stmt.getNode().removeChild(conditionNode); + @Override + @RequiredReadAction + protected TextRange getSurroundSelectionRange(ASTNode statementNode) { + JSFunction stmt = (JSFunction)statementNode.getPsi(); + ASTNode conditionNode = stmt.getNameIdentifier().getNode(); + int offset = conditionNode.getStartOffset(); + stmt.getNode().removeChild(conditionNode); - return new TextRange(offset, offset); - } + return new TextRange(offset, offset); + } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithIfElseSurrounder.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithIfElseSurrounder.java index 218eaf53..14e1dccf 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithIfElseSurrounder.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithIfElseSurrounder.java @@ -16,28 +16,23 @@ package com.intellij.lang.javascript.impl.surroundWith; -import consulo.javascript.language.JavaScriptBundle; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.psi.PsiElement; +import consulo.localize.LocalizeValue; import consulo.project.Project; /** - * Created by IntelliJ IDEA. - * User: yole - * Date: 12.07.2005 - * Time: 17:48:14 - * To change this template use File | Settings | File Templates. + * @author yole + * @since 2005-07-12 */ -public class JSWithIfElseSurrounder extends JSWithIfSurrounder -{ - @Override - public String getTemplateDescription() - { - return JavaScriptBundle.message("javascript.surround.with.if.else"); - } +public class JSWithIfElseSurrounder extends JSWithIfSurrounder { + @Override + public LocalizeValue getTemplateDescription() { + return JavaScriptLocalize.javascriptSurroundWithIfElse(); + } - @Override - protected String getStatementTemplate(final Project project, PsiElement context) - { - return "if (a) { } else { }"; - } + @Override + protected String getStatementTemplate(Project project, PsiElement context) { + return "if (a) { } else { }"; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithIfSurrounder.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithIfSurrounder.java index e05490d2..944c28dd 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithIfSurrounder.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithIfSurrounder.java @@ -16,51 +16,45 @@ package com.intellij.lang.javascript.impl.surroundWith; +import com.intellij.lang.javascript.psi.JSIfStatement; +import consulo.annotation.access.RequiredReadAction; import consulo.document.util.TextRange; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.ast.ASTNode; -import org.jetbrains.annotations.NonNls; -import consulo.javascript.language.JavaScriptBundle; -import com.intellij.lang.javascript.psi.JSIfStatement; -import consulo.project.Project; import consulo.language.psi.PsiElement; +import consulo.localize.LocalizeValue; +import consulo.project.Project; /** - * Created by IntelliJ IDEA. - * User: yole - * Date: 12.07.2005 - * Time: 16:33:55 - * To change this template use File | Settings | File Templates. + * @author yole + * @since 2005-07-12 */ -public class JSWithIfSurrounder extends JSStatementSurrounder -{ - @Override - public String getTemplateDescription() - { - return JavaScriptBundle.message("javascript.surround.with.if"); - } +public class JSWithIfSurrounder extends JSStatementSurrounder { + @Override + public LocalizeValue getTemplateDescription() { + return JavaScriptLocalize.javascriptSurroundWithIf(); + } - @Override - @NonNls - protected String getStatementTemplate(final Project project, PsiElement context) - { - return "if(a) { }"; - } + @Override + protected String getStatementTemplate(Project project, PsiElement context) { + return "if(a) { }"; + } - @Override - protected ASTNode getInsertBeforeNode(final ASTNode statementNode) - { - JSIfStatement stmt = (JSIfStatement) statementNode.getPsi(); - return stmt.getThen().getNode().getLastChildNode(); - } + @Override + @RequiredReadAction + protected ASTNode getInsertBeforeNode(ASTNode statementNode) { + JSIfStatement stmt = (JSIfStatement)statementNode.getPsi(); + return stmt.getThen().getNode().getLastChildNode(); + } - @Override - protected TextRange getSurroundSelectionRange(final ASTNode statementNode) - { - JSIfStatement stmt = (JSIfStatement) statementNode.getPsi(); - ASTNode conditionNode = stmt.getCondition().getNode(); - int offset = conditionNode.getStartOffset(); - stmt.getNode().removeChild(conditionNode); + @Override + @RequiredReadAction + protected TextRange getSurroundSelectionRange(ASTNode statementNode) { + JSIfStatement stmt = (JSIfStatement)statementNode.getPsi(); + ASTNode conditionNode = stmt.getCondition().getNode(); + int offset = conditionNode.getStartOffset(); + stmt.getNode().removeChild(conditionNode); - return new TextRange(offset, offset); - } + return new TextRange(offset, offset); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithParenthesesSurrounder.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithParenthesesSurrounder.java index 8cc6270e..b9576dea 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithParenthesesSurrounder.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithParenthesesSurrounder.java @@ -16,50 +16,46 @@ package com.intellij.lang.javascript.impl.surroundWith; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import consulo.language.ast.ASTNode; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.psi.JSExpression; import com.intellij.lang.javascript.psi.impl.JSChangeUtil; +import consulo.annotation.access.RequiredReadAction; import consulo.codeEditor.Editor; -import consulo.project.Project; import consulo.document.util.TextRange; -import consulo.language.psi.PsiElement; +import consulo.javascript.localize.JavaScriptLocalize; +import consulo.language.ast.ASTNode; import consulo.language.editor.surroundWith.Surrounder; +import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; +import consulo.project.Project; + +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** - * Created by IntelliJ IDEA. - * User: yole - * Date: 12.07.2005 - * Time: 12:47:49 - * To change this template use File | Settings | File Templates. + * @author yole + * @since 2005-07-12 */ -public class JSWithParenthesesSurrounder implements Surrounder -{ - @Override - public String getTemplateDescription() - { - return JavaScriptBundle.message("javascript.surround.with.parenthesis"); - } +public class JSWithParenthesesSurrounder implements Surrounder { + @Override + public LocalizeValue getTemplateDescription() { + return JavaScriptLocalize.javascriptSurroundWithParenthesis(); + } - @Override - public boolean isApplicable(@Nonnull PsiElement[] elements) - { - return true; - } + @Override + public boolean isApplicable(@Nonnull PsiElement[] elements) { + return true; + } - @Override - @Nullable - public TextRange surroundElements(@Nonnull Project project, @Nonnull Editor editor, @Nonnull PsiElement[] elements) throws - IncorrectOperationException - { - JSExpression expr = (JSExpression) elements[0]; - ASTNode parenthExprNode = JSChangeUtil.createExpressionFromText(project, "(" + expr.getText() + ")").getNode(); - expr.getNode().getTreeParent().replaceChild(expr.getNode(), parenthExprNode); - int offset = parenthExprNode.getTextRange().getEndOffset(); - return new TextRange(offset, offset); - } + @Nullable + @Override + @RequiredReadAction + public TextRange surroundElements(@Nonnull Project project, @Nonnull Editor editor, @Nonnull PsiElement[] elements) + throws IncorrectOperationException { + JSExpression expr = (JSExpression)elements[0]; + ASTNode parenthExprNode = JSChangeUtil.createExpressionFromText(project, "(" + expr.getText() + ")").getNode(); + expr.getNode().getTreeParent().replaceChild(expr.getNode(), parenthExprNode); + int offset = parenthExprNode.getTextRange().getEndOffset(); + return new TextRange(offset, offset); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithTryCatchFinallySurrounder.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithTryCatchFinallySurrounder.java index f3a08dd8..01e7f987 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithTryCatchFinallySurrounder.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithTryCatchFinallySurrounder.java @@ -16,73 +16,64 @@ package com.intellij.lang.javascript.impl.surroundWith; -import javax.annotation.Nonnull; - -import consulo.project.Project; -import org.jetbrains.annotations.NonNls; -import consulo.language.ast.ASTNode; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.JavaScriptSupportLoader; import com.intellij.lang.javascript.psi.JSCatchBlock; import com.intellij.lang.javascript.psi.JSStatement; import com.intellij.lang.javascript.psi.JSTryStatement; +import consulo.annotation.access.RequiredReadAction; import consulo.document.util.TextRange; +import consulo.javascript.localize.JavaScriptLocalize; +import consulo.language.ast.ASTNode; import consulo.language.psi.PsiElement; +import consulo.localize.LocalizeValue; +import consulo.project.Project; +import jakarta.annotation.Nonnull; /** - * Created by IntelliJ IDEA. - * User: yole - * Date: 12.07.2005 - * Time: 19:21:52 - * To change this template use File | Settings | File Templates. + * @author yole + * @since 2005-07-12 */ -public class JSWithTryCatchFinallySurrounder extends JSStatementSurrounder -{ - @Override - public String getTemplateDescription() - { - return JavaScriptBundle.message("javascript.surround.with.try.catch.finally"); - } +public class JSWithTryCatchFinallySurrounder extends JSStatementSurrounder { + @Override + public LocalizeValue getTemplateDescription() { + return JavaScriptLocalize.javascriptSurroundWithTryCatchFinally(); + } - @Override - @NonNls - protected String getStatementTemplate(final Project project, PsiElement context) - { - return "try { } catch(e" + getExceptionVarTypeBasedOnContext(context) + ") { } finally { }"; - } + @Override + @RequiredReadAction + protected String getStatementTemplate(Project project, PsiElement context) { + return "try { } catch(e" + getExceptionVarTypeBasedOnContext(context) + ") { } finally { }"; + } - protected static String getExceptionVarTypeBasedOnContext(@Nonnull PsiElement context) - { - if(context.getContainingFile().getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4) - { - return ":Error"; - } - return ""; - } + @RequiredReadAction + protected static String getExceptionVarTypeBasedOnContext(@Nonnull PsiElement context) { + if (context.getContainingFile().getLanguage() == JavaScriptSupportLoader.ECMA_SCRIPT_L4) { + return ":Error"; + } + return ""; + } - @Override - protected ASTNode getInsertBeforeNode(final ASTNode statementNode) - { - JSTryStatement stmt = (JSTryStatement) statementNode.getPsi(); - return stmt.getStatement().getLastChild().getNode(); - } + @Override + @RequiredReadAction + protected ASTNode getInsertBeforeNode(ASTNode statementNode) { + JSTryStatement stmt = (JSTryStatement)statementNode.getPsi(); + return stmt.getStatement().getLastChild().getNode(); + } - @Override - protected TextRange getSurroundSelectionRange(final ASTNode statementNode) - { - JSTryStatement stmt = (JSTryStatement) statementNode.getPsi(); - final JSCatchBlock catchBlock = stmt.getCatchBlock(); - if(catchBlock != null) - { - int offset = catchBlock.getStatement().getFirstChild().getNode().getStartOffset() + 1; - return new TextRange(offset, offset); - } - final JSStatement finallyStmt = stmt.getFinallyStatement(); - if(finallyStmt != null) - { - int offset = finallyStmt.getFirstChild().getNode().getStartOffset() + 1; - return new TextRange(offset, offset); - } - return null; - } + @Override + @RequiredReadAction + protected TextRange getSurroundSelectionRange(ASTNode statementNode) { + JSTryStatement stmt = (JSTryStatement)statementNode.getPsi(); + JSCatchBlock catchBlock = stmt.getCatchBlock(); + if (catchBlock != null) { + int offset = catchBlock.getStatement().getFirstChild().getNode().getStartOffset() + 1; + return new TextRange(offset, offset); + } + JSStatement finallyStmt = stmt.getFinallyStatement(); + if (finallyStmt != null) { + int offset = finallyStmt.getFirstChild().getNode().getStartOffset() + 1; + return new TextRange(offset, offset); + } + return null; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithTryCatchSurrounder.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithTryCatchSurrounder.java index 6305a51f..ce116642 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithTryCatchSurrounder.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithTryCatchSurrounder.java @@ -16,28 +16,25 @@ package com.intellij.lang.javascript.impl.surroundWith; -import consulo.javascript.language.JavaScriptBundle; +import consulo.annotation.access.RequiredReadAction; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.psi.PsiElement; +import consulo.localize.LocalizeValue; import consulo.project.Project; /** - * Created by IntelliJ IDEA. - * User: yole - * Date: 12.07.2005 - * Time: 19:29:10 - * To change this template use File | Settings | File Templates. + * @author yole + * @since 2005-07-12 */ -public class JSWithTryCatchSurrounder extends JSWithTryCatchFinallySurrounder -{ - @Override - public String getTemplateDescription() - { - return JavaScriptBundle.message("javascript.surround.with.try.catch"); - } +public class JSWithTryCatchSurrounder extends JSWithTryCatchFinallySurrounder { + @Override + public LocalizeValue getTemplateDescription() { + return JavaScriptLocalize.javascriptSurroundWithTryCatch(); + } - @Override - protected String getStatementTemplate(final Project project, PsiElement context) - { - return "try { } catch(e" + getExceptionVarTypeBasedOnContext(context) + ") { }"; - } + @Override + @RequiredReadAction + protected String getStatementTemplate(Project project, PsiElement context) { + return "try { } catch(e" + getExceptionVarTypeBasedOnContext(context) + ") { }"; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithTryFinallySurrounder.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithTryFinallySurrounder.java index b288ae48..7b393c2c 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithTryFinallySurrounder.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithTryFinallySurrounder.java @@ -16,28 +16,25 @@ package com.intellij.lang.javascript.impl.surroundWith; -import consulo.javascript.language.JavaScriptBundle; +import consulo.annotation.access.RequiredReadAction; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.psi.PsiElement; +import consulo.localize.LocalizeValue; import consulo.project.Project; /** - * Created by IntelliJ IDEA. - * User: yole - * Date: 12.07.2005 - * Time: 19:24:26 - * To change this template use File | Settings | File Templates. + * @author yole + * @since 2005-07-12 */ -public class JSWithTryFinallySurrounder extends JSWithTryCatchFinallySurrounder -{ - @Override - public String getTemplateDescription() - { - return JavaScriptBundle.message("javascript.surround.with.try.finally"); - } +public class JSWithTryFinallySurrounder extends JSWithTryCatchFinallySurrounder { + @Override + public LocalizeValue getTemplateDescription() { + return JavaScriptLocalize.javascriptSurroundWithTryFinally(); + } - @Override - protected String getStatementTemplate(final Project project, PsiElement context) - { - return "try { } finally { }"; - } + @Override + @RequiredReadAction + protected String getStatementTemplate(Project project, PsiElement context) { + return "try { } finally { }"; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithWhileSurrounder.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithWhileSurrounder.java index f9965a96..3c0a0341 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithWhileSurrounder.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithWhileSurrounder.java @@ -16,45 +16,41 @@ package com.intellij.lang.javascript.impl.surroundWith; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.psi.JSWhileStatement; +import consulo.annotation.access.RequiredReadAction; import consulo.document.util.TextRange; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.ast.ASTNode; import consulo.language.psi.PsiElement; +import consulo.localize.LocalizeValue; import consulo.project.Project; /** - * Created by IntelliJ IDEA. - * User: yole - * Date: 12.07.2005 - * Time: 18:03:50 - * To change this template use File | Settings | File Templates. + * @author yole + * @since 2005-07-12 */ -public class JSWithWhileSurrounder extends JSStatementSurrounder -{ - @Override - public String getTemplateDescription() - { - return JavaScriptBundle.message("javascript.surround.with.while"); - } +public class JSWithWhileSurrounder extends JSStatementSurrounder { + @Override + public LocalizeValue getTemplateDescription() { + return JavaScriptLocalize.javascriptSurroundWithWhile(); + } - @Override - protected String getStatementTemplate(final Project project, PsiElement context) - { - return "while(true) { }"; - } + @Override + protected String getStatementTemplate(Project project, PsiElement context) { + return "while(true) { }"; + } - @Override - protected ASTNode getInsertBeforeNode(ASTNode statementNode) - { - JSWhileStatement stmt = (JSWhileStatement) statementNode.getPsi(); - return stmt.getBody().getLastChild().getNode(); - } + @Override + @RequiredReadAction + protected ASTNode getInsertBeforeNode(ASTNode statementNode) { + JSWhileStatement stmt = (JSWhileStatement)statementNode.getPsi(); + return stmt.getBody().getLastChild().getNode(); + } - @Override - protected TextRange getSurroundSelectionRange(final ASTNode statementNode) - { - JSWhileStatement stmt = (JSWhileStatement) statementNode.getPsi(); - return stmt.getCondition().getTextRange(); - } + @Override + @RequiredReadAction + protected TextRange getSurroundSelectionRange(ASTNode statementNode) { + JSWhileStatement stmt = (JSWhileStatement)statementNode.getPsi(); + return stmt.getCondition().getTextRange(); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithWithSurrounder.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithWithSurrounder.java index 40290958..9c33351e 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithWithSurrounder.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/surroundWith/JSWithWithSurrounder.java @@ -16,49 +16,45 @@ package com.intellij.lang.javascript.impl.surroundWith; -import consulo.javascript.language.JavaScriptBundle; import com.intellij.lang.javascript.psi.JSWithStatement; -import consulo.project.Project; +import consulo.annotation.access.RequiredReadAction; import consulo.document.util.TextRange; -import consulo.language.psi.PsiElement; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.ast.ASTNode; +import consulo.language.psi.PsiElement; +import consulo.localize.LocalizeValue; +import consulo.project.Project; /** - * Created by IntelliJ IDEA. - * User: yole - * Date: 12.07.2005 - * Time: 19:34:54 - * To change this template use File | Settings | File Templates. + * @author yole + * @since 2005-07-12 */ -public class JSWithWithSurrounder extends JSStatementSurrounder -{ - @Override - public String getTemplateDescription() - { - return JavaScriptBundle.message("javascript.surround.with.with"); - } +public class JSWithWithSurrounder extends JSStatementSurrounder { + @Override + public LocalizeValue getTemplateDescription() { + return JavaScriptLocalize.javascriptSurroundWithWith(); + } - @Override - protected String getStatementTemplate(final Project project, PsiElement context) - { - return "with(a) { }"; - } + @Override + protected String getStatementTemplate(Project project, PsiElement context) { + return "with(a) { }"; + } - @Override - protected ASTNode getInsertBeforeNode(final ASTNode statementNode) - { - JSWithStatement stmt = (JSWithStatement) statementNode.getPsi(); - return stmt.getStatement().getLastChild().getNode(); - } + @Override + @RequiredReadAction + protected ASTNode getInsertBeforeNode(ASTNode statementNode) { + JSWithStatement stmt = (JSWithStatement)statementNode.getPsi(); + return stmt.getStatement().getLastChild().getNode(); + } - @Override - protected TextRange getSurroundSelectionRange(final ASTNode statementNode) - { - JSWithStatement stmt = (JSWithStatement) statementNode.getPsi(); - ASTNode conditionNode = stmt.getExpression().getNode(); - int offset = conditionNode.getStartOffset(); - stmt.getNode().removeChild(conditionNode); + @Override + @RequiredReadAction + protected TextRange getSurroundSelectionRange(ASTNode statementNode) { + JSWithStatement stmt = (JSWithStatement)statementNode.getPsi(); + ASTNode conditionNode = stmt.getExpression().getNode(); + int offset = conditionNode.getStartOffset(); + stmt.getNode().removeChild(conditionNode); - return new TextRange(offset, offset); - } + return new TextRange(offset, offset); + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/validation/BaseCreateMethodsFix.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/validation/BaseCreateMethodsFix.java index 8a406ee5..129eff78 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/validation/BaseCreateMethodsFix.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/validation/BaseCreateMethodsFix.java @@ -16,288 +16,228 @@ package com.intellij.lang.javascript.impl.validation; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; - -import consulo.language.ast.ASTNode; -import consulo.language.util.IncorrectOperationException; -import org.jetbrains.annotations.NonNls; -import javax.annotation.Nonnull; - import com.intellij.lang.javascript.JSTokenTypes; import com.intellij.lang.javascript.impl.flex.ImportUtils; import com.intellij.lang.javascript.impl.generation.JSNamedElementNode; -import com.intellij.lang.javascript.psi.JSAttributeList; -import com.intellij.lang.javascript.psi.JSAttributeListOwner; -import com.intellij.lang.javascript.psi.JSClass; -import com.intellij.lang.javascript.psi.JSFile; -import com.intellij.lang.javascript.psi.JSFunction; -import com.intellij.lang.javascript.psi.JSNamedElement; -import com.intellij.lang.javascript.psi.JSParameter; -import com.intellij.lang.javascript.psi.JSParameterList; -import com.intellij.lang.javascript.psi.JSVariable; +import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.impl.JSChangeUtil; import com.intellij.lang.javascript.psi.resolve.JSImportHandlingUtil; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.codeEditor.Editor; -import consulo.project.Project; +import consulo.language.ast.ASTNode; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiFile; import consulo.language.psi.PsiWhiteSpace; +import consulo.language.util.IncorrectOperationException; +import consulo.project.Project; +import consulo.util.lang.StringUtil; +import jakarta.annotation.Nonnull; + +import java.util.*; /** * @author Maxim.Mossienko - * Date: Jul 17, 2008 - * Time: 9:39:02 PM + * @since 2008-07-17 */ -public abstract class BaseCreateMethodsFix -{ - private final Set elementsToProcess = new LinkedHashSet(); - protected final JSClass myJsClass; - protected PsiElement anchor; - - public BaseCreateMethodsFix(final JSClass jsClass) - { - myJsClass = jsClass; - } - - public void invoke(@Nonnull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException - { - evalAnchor(editor, file); - for(T e : getElementsToProcess()) - { - anchor = doAddOneMethod(project, buildFunctionText(e), anchor); - } - } - - protected void evalAnchor(final Editor editor, final PsiFile file) - { - anchor = null; - final PsiElement at = file.findElementAt(editor.getCaretModel().getOffset()); - PsiElement parent; - - if(at != null && ((parent = at.getParent()) == myJsClass || (parent instanceof JSFile && myJsClass.getParent().getContainingFile() == parent - .getContext().getContainingFile()))) - { - final ASTNode atNode = at.getNode(); - if(atNode.getElementType() == JSTokenTypes.RBRACE) - { - return; - } - - for(ASTNode node = atNode; node != null; node = node.getTreeNext()) - { - if(node.getElementType() == JSTokenTypes.LBRACE) - { - return; - } - } - anchor = at; - } - } - - protected PsiElement doAddOneMethod(final Project project, final String functionText, PsiElement anchor) throws IncorrectOperationException - { - if(functionText != null && functionText.length() > 0) - { - PsiElement element = JSChangeUtil.createJSTreeFromText(project, functionText).getPsi(); - if(element instanceof PsiWhiteSpace) - { - element = element.getNextSibling(); - } - - boolean defaultAdd = true; - - if(anchor != null && anchor.isValid()) - { - String anchorText; - - if(!(anchor instanceof PsiWhiteSpace) || ((anchorText = anchor.getText()).indexOf("") == -1)) - { - defaultAdd = false; - anchor = anchor.getParent().addAfter(element, anchor); - } - } - - if(defaultAdd) - { - anchor = myJsClass.add(element); - } - } - - return anchor; - } - - public String buildFunctionText(final T fun) - { - final JSAttributeList attributeList = fun.getAttributeList(); - String attrText = attributeList != null ? attributeList.getText() : ""; - - attrText = buildFunctionAttrText(attrText, attributeList, fun); - - final JSFunction function = fun instanceof JSFunction ? (JSFunction) fun : null; - final JSVariable var = fun instanceof JSVariable ? (JSVariable) fun : null; - assert var != null || function != null; - - final JSParameterList parameterList = (function != null) ? function.getParameterList() : null; - final String typeString = importType(function != null ? function.getReturnTypeString() : var.getTypeString(), fun); - @NonNls String functionText = attrText; - if(functionText.length() > 0) - { - functionText += " "; - } - functionText += "function "; - - functionText += buildFunctionKind(fun); - - functionText += buildName(fun) + " " + buildParameterList(parameterList, fun); - if(typeString != null) - { - functionText += ":" + buildReturnType(typeString); - } - - functionText += buildFunctionBodyText(typeString, parameterList, fun); - return functionText; - } - - protected - @NonNls - String buildReturnType(final String typeString) - { - return typeString; - } - - protected String importType(final String s, T fun) - { - if(s == null) - { - return null; - } - if(fun instanceof JSFunction) - { - final String resolvedTypeName = JSImportHandlingUtil.resolveTypeName(s, fun); - - if(!resolvedTypeName.equals(s)) - { - ImportUtils.doImport(myJsClass, resolvedTypeName); - } - } - return s; - } - - protected String buildParameterList(final JSParameterList parameterList, final T fun) - { - if(parameterList != null) - { - for(JSParameter param : parameterList.getParameters()) - { - final String s = param.getTypeString(); - if(s != null) - { - importType(s, fun); - } - } - } - return (parameterList != null ? parameterList.getText() : "()"); - } - - protected String buildName(final T fun) - { - return fun.getName(); - } - - protected - @NonNls - String buildFunctionKind(final T fun) - { - if(fun instanceof JSFunction) - { - final JSFunction function = (JSFunction) fun; - if(function.isGetProperty()) - { - return "get "; - } - else if(function.isSetProperty()) - { - return "set "; - } - } - return ""; - } - - protected - @NonNls - String buildFunctionBodyText(@NonNls String retType, final JSParameterList parameterList, final T func) - { - return " {}"; - } - - protected - @NonNls - String buildFunctionAttrText(@NonNls String attrText, final JSAttributeList attributeList, final T function) - { - attrText = attrText.replace("native", "").trim(); - return attrText; - } - - public void addElementToProcess(final T function) - { - elementsToProcess.add(function); - } - - public void addElementsToProcessFrom(final Collection selectedElements) - { - for(JSNamedElementNode el : selectedElements) - { - addElementToProcess((T) el.getPsiElement()); - } - } - - public Set getElementsToProcess() - { - final T[] objects = (T[]) elementsToProcess.toArray(new JSNamedElement[elementsToProcess.size()]); - final Comparator tComparator = new Comparator() - { - @Override - public int compare(final T o1, final T o2) - { - return o1.getTextOffset() - o2.getTextOffset(); - } - }; - - final int size = elementsToProcess.size(); - final LinkedHashSet result = new LinkedHashSet(size); - final List objectsFromSameFile = new ArrayList(); - PsiFile containingFile = null; - - for(int i = 0; i < size; ++i) - { - final T object = objects[i]; - final PsiFile currentContainingFile = object.getContainingFile(); - - if(currentContainingFile != containingFile) - { - if(containingFile != null) - { - Collections.sort(objectsFromSameFile, tComparator); - result.addAll(objectsFromSameFile); - objectsFromSameFile.clear(); - } - containingFile = currentContainingFile; - } - - objectsFromSameFile.add(object); - } - - Collections.sort(objectsFromSameFile, tComparator); - result.addAll(objectsFromSameFile); - - elementsToProcess.clear(); - elementsToProcess.addAll(result); - return elementsToProcess; - } +public abstract class BaseCreateMethodsFix { + private final Set elementsToProcess = new LinkedHashSet<>(); + protected final JSClass myJsClass; + protected PsiElement anchor; + + public BaseCreateMethodsFix(JSClass jsClass) { + myJsClass = jsClass; + } + + @RequiredWriteAction + public void invoke(@Nonnull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + evalAnchor(editor, file); + for (T e : getElementsToProcess()) { + anchor = doAddOneMethod(project, buildFunctionText(e), anchor); + } + } + + @RequiredReadAction + protected void evalAnchor(Editor editor, PsiFile file) { + anchor = null; + PsiElement at = file.findElementAt(editor.getCaretModel().getOffset()); + PsiElement parent = at != null ? at.getParent() : null; + + if (parent == myJsClass || (parent instanceof JSFile jsFile + && myJsClass.getParent().getContainingFile() == jsFile.getContext().getContainingFile())) { + + ASTNode atNode = at.getNode(); + if (atNode.getElementType() == JSTokenTypes.RBRACE) { + return; + } + + for (ASTNode node = atNode; node != null; node = node.getTreeNext()) { + if (node.getElementType() == JSTokenTypes.LBRACE) { + return; + } + } + anchor = at; + } + } + + @RequiredWriteAction + protected PsiElement doAddOneMethod(Project project, String functionText, PsiElement anchor) + throws IncorrectOperationException { + if (StringUtil.isNotEmpty(functionText)) { + PsiElement element = JSChangeUtil.createJSTreeFromText(project, functionText).getPsi(); + if (element instanceof PsiWhiteSpace whiteSpace) { + element = whiteSpace.getNextSibling(); + } + + boolean defaultAdd = true; + + if (anchor != null && anchor.isValid()) { + String anchorText = anchor instanceof PsiWhiteSpace ? anchor.getText() : ""; + + if (!anchorText.contains("")) { + defaultAdd = false; + anchor = anchor.getParent().addAfter(element, anchor); + } + } + + if (defaultAdd) { + anchor = myJsClass.add(element); + } + } + + return anchor; + } + + @RequiredWriteAction + public String buildFunctionText(T fun) { + JSAttributeList attributeList = fun.getAttributeList(); + String attrText = attributeList != null ? attributeList.getText() : ""; + + attrText = buildFunctionAttrText(attrText, attributeList, fun); + + JSFunction function = fun instanceof JSFunction jsFun ? jsFun : null; + JSVariable var = fun instanceof JSVariable jsVar ? jsVar : null; + assert var != null || function != null; + + JSParameterList parameterList = (function != null) ? function.getParameterList() : null; + String typeString = importType(function != null ? function.getReturnTypeString() : var.getTypeString(), fun); + StringBuilder functionText = new StringBuilder(attrText); + if (!functionText.isEmpty()) { + functionText.append(" "); + } + functionText.append("function "); + + functionText.append(buildFunctionKind(fun)); + + functionText.append(buildName(fun)).append(" ").append(buildParameterList(parameterList, fun)); + if (typeString != null) { + functionText.append(":").append(buildReturnType(typeString)); + } + + functionText.append(buildFunctionBodyText(typeString, parameterList, fun)); + return functionText.toString(); + } + + protected String buildReturnType(String typeString) { + return typeString; + } + + @RequiredWriteAction + protected String importType(String s, T fun) { + if (s == null) { + return null; + } + if (fun instanceof JSFunction function) { + String resolvedTypeName = JSImportHandlingUtil.resolveTypeName(s, function); + + if (!resolvedTypeName.equals(s)) { + ImportUtils.doImport(myJsClass, resolvedTypeName); + } + } + return s; + } + + @RequiredWriteAction + protected String buildParameterList(JSParameterList parameterList, T fun) { + if (parameterList != null) { + for (JSParameter param : parameterList.getParameters()) { + String s = param.getTypeString(); + if (s != null) { + importType(s, fun); + } + } + } + return (parameterList != null ? parameterList.getText() : "()"); + } + + @RequiredReadAction + protected String buildName(T fun) { + return fun.getName(); + } + + @RequiredReadAction + protected String buildFunctionKind(T fun) { + if (fun instanceof JSFunction function) { + if (function.isGetProperty()) { + return "get "; + } + else if (function.isSetProperty()) { + return "set "; + } + } + return ""; + } + + protected String buildFunctionBodyText(String retType, JSParameterList parameterList, T func) { + return " {}"; + } + + protected String buildFunctionAttrText(String attrText, JSAttributeList attributeList, T function) { + return attrText.replace("native", "").trim(); + } + + public void addElementToProcess(T function) { + elementsToProcess.add(function); + } + + @SuppressWarnings("unchecked") + public void addElementsToProcessFrom(Collection selectedElements) { + for (JSNamedElementNode el : selectedElements) { + addElementToProcess((T)el.getPsiElement()); + } + } + + @SuppressWarnings("unchecked") + public Set getElementsToProcess() { + T[] objects = (T[])elementsToProcess.toArray(new JSNamedElement[elementsToProcess.size()]); + Comparator tComparator = (o1, o2) -> o1.getTextOffset() - o2.getTextOffset(); + + int size = elementsToProcess.size(); + LinkedHashSet result = new LinkedHashSet<>(size); + List objectsFromSameFile = new ArrayList<>(); + PsiFile containingFile = null; + + for (int i = 0; i < size; ++i) { + T object = objects[i]; + PsiFile currentContainingFile = object.getContainingFile(); + + if (currentContainingFile != containingFile) { + if (containingFile != null) { + Collections.sort(objectsFromSameFile, tComparator); + result.addAll(objectsFromSameFile); + objectsFromSameFile.clear(); + } + containingFile = currentContainingFile; + } + + objectsFromSameFile.add(object); + } + + Collections.sort(objectsFromSameFile, tComparator); + result.addAll(objectsFromSameFile); + + elementsToProcess.clear(); + elementsToProcess.addAll(result); + return elementsToProcess; + } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/validation/ImplementMethodsFix.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/validation/ImplementMethodsFix.java index dfbebfc6..5fc6bbad 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/validation/ImplementMethodsFix.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/validation/ImplementMethodsFix.java @@ -22,70 +22,59 @@ import com.intellij.lang.javascript.psi.JSParameterList; import com.intellij.lang.javascript.psi.impl.JSChangeUtil; import consulo.codeEditor.Editor; -import consulo.javascript.language.JavaScriptBundle; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.language.editor.intention.SyntheticIntentionAction; import consulo.language.psi.PsiFile; +import consulo.localize.LocalizeValue; import consulo.project.Project; -import org.jetbrains.annotations.NonNls; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author Maxim.Mossienko - * Date: Jul 17, 2008 - * Time: 9:39:02 PM + * @since 2008-07-17 */ public class ImplementMethodsFix extends BaseCreateMethodsFix implements SyntheticIntentionAction { - public ImplementMethodsFix(final JSClass jsClass) { - super(jsClass); - } - - @Override - @Nonnull - public String getText() { - return JavaScriptBundle.message("javascript.fix.implement.methods"); - } + public ImplementMethodsFix(JSClass jsClass) { + super(jsClass); + } - @Override - public boolean isAvailable(@Nonnull final Project project, final Editor editor, final PsiFile file) { - return myJsClass.isValid(); - } + @Override + @Nonnull + public LocalizeValue getText() { + return JavaScriptLocalize.javascriptFixImplementMethods(); + } - @Override - protected - @NonNls - String buildFunctionAttrText(@NonNls String attrText, final JSAttributeList attributeList, final JSFunction function) { - attrText = super.buildFunctionAttrText(attrText, attributeList, function); - if (attributeList == null || attributeList.getAccessType() != JSAttributeList.AccessType.PUBLIC) { - attrText = "public"; + @Override + public boolean isAvailable(@Nonnull Project project, Editor editor, PsiFile file) { + return myJsClass.isValid(); } - return attrText; - } - @Override - protected String buildFunctionBodyText(final String retType, final JSParameterList parameterList, final JSFunction func) { - @NonNls String s = "{\n"; - if (retType != null && !"void".equals(retType)) { - s += "return " + defaultValueOfType(retType) + JSChangeUtil.getSemicolon(func.getProject()) + "\n"; + @Override + protected String buildFunctionAttrText(String attrText, JSAttributeList attributeList, JSFunction function) { + return attributeList == null || attributeList.getAccessType() != JSAttributeList.AccessType.PUBLIC + ? "public" + : super.buildFunctionAttrText(attrText, attributeList, function); } - s += "}"; - return s; - } - private static - @NonNls - String defaultValueOfType(final @NonNls String retType) { - if ("int".equals(retType) || "uint".equals(retType) || "Number".equals(retType)) { - return "0"; + @Override + protected String buildFunctionBodyText(String retType, JSParameterList parameterList, JSFunction func) { + StringBuilder s = new StringBuilder("{\n"); + if (retType != null && !"void".equals(retType)) { + s.append("return ").append(defaultValueOfType(retType)).append(JSChangeUtil.getSemicolon(func.getProject())).append("\n"); + } + return s.append("}").toString(); } - if ("Boolean".equals(retType)) { - return "false"; + + private static String defaultValueOfType(String retType) { + return switch (retType) { + case "int", "uint", "Number" -> "0"; + case "Boolean" -> "false"; + default -> "null"; + }; } - return "null"; - } - @Override - public boolean startInWriteAction() { - return true; - } + @Override + public boolean startInWriteAction() { + return true; + } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/validation/ImplementedMethodProcessor.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/validation/ImplementedMethodProcessor.java index 6a0d4d84..72137e98 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/validation/ImplementedMethodProcessor.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/validation/ImplementedMethodProcessor.java @@ -22,171 +22,144 @@ import com.intellij.lang.javascript.psi.JSVariable; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; import com.intellij.lang.javascript.psi.resolve.ResolveProcessor; +import consulo.annotation.access.RequiredReadAction; import consulo.language.psi.PsiElement; import consulo.language.psi.resolve.ResolveState; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; -import javax.annotation.Nullable; import java.util.LinkedHashMap; import java.util.Map; import java.util.function.Function; /** * @author Maxim.Mossienko - * Date: Jul 17, 2008 - * Time: 9:50:49 PM + * @since 2008-07-17 */ -public abstract class ImplementedMethodProcessor extends JSResolveUtil.CollectMethodsToImplementProcessor -{ - protected final JSClass myJsClass; - - public ImplementedMethodProcessor(final JSClass jsClass) - { - super(null, null); - myJsClass = jsClass; - } - - @Override - protected boolean process(final ResolveProcessor processor) - { - Map functions = null; - - for(PsiElement _function : processor.getResults()) - { - if(!(_function instanceof JSFunction)) - { - continue; - } - final JSFunction function = (JSFunction) _function; - final String name = function.getName(); - - if(functions == null) - { - functions = collectAllVisibleClassFunctions(myJsClass, null, new Function() - { - @Override - public Boolean apply(final JSFunction jsFunction) - { - final JSAttributeList attributeList = jsFunction.getAttributeList(); - PsiElement parentClass = JSResolveUtil.findParent(jsFunction); - if((attributeList == null || attributeList.getAccessType() != JSAttributeList.AccessType.PUBLIC) && myJsClass != parentClass) - { - return Boolean.FALSE; - } - return Boolean.TRUE; - } - }); - } - - JSFunction o = findFunctionWithTheSameKind(functions, function, name); - - if(o == null) - { - if(function.isGetProperty() || function.isSetProperty()) - { - JSVariable var = myJsClass.findFieldByName(name); - if(var != null) - { - JSAttributeList attributeList = var.getAttributeList(); - if(attributeList != null && attributeList.getAccessType() == JSAttributeList.AccessType.PUBLIC) - { - continue; // implicit get and set methods - } - } - } - addNonimplementedFunction(function); - } - else - { - addImplementedFunction(function, o); - } - } - return true; - } - - protected void addImplementedFunction(final JSFunction interfaceFunction, final JSFunction implementationFunction) - { - } - - public static JSFunction findFunctionWithTheSameKind(final Map functions, final JSFunction function, final String name) - { - Object o = functions.get(name); - if(o instanceof JSFunction && ((JSFunction) o).getKind() != function.getKind()) - { - o = null; - } - else if(o instanceof JSFunction[]) - { - final JSFunction[] jsFunctions = (JSFunction[]) o; - o = null; - for(JSFunction fun : jsFunctions) - { - if(fun.getKind() == function.getKind()) - { - o = fun; - break; - } - } - } - return (JSFunction) o; - } - - public static Map collectAllVisibleClassFunctions(JSClass jsClass, Map _functions, - final @Nullable Function filter) - { - final Map functions = _functions != null ? _functions : new LinkedHashMap(); - jsClass.processDeclarations(new ResolveProcessor(null) - { - { - setToProcessHierarchy(true); - setLocalResolve(true); - } - - @Override - public boolean execute(final PsiElement element, final ResolveState state) - { - if(element instanceof JSFunction) - { - final JSFunction function = (JSFunction) element; - if(function.isConstructor()) - { - return true; // SWC stubs have constructor methods :( - } - - final JSAttributeList attributeList = function.getAttributeList(); - if(attributeList != null && attributeList.getAccessType() == JSAttributeList.AccessType.PRIVATE) - { - return true; - } - - Boolean filterValue; - if(filter != null && (filterValue = filter.apply(function)) != null && !filterValue.booleanValue()) - { - return true; - } - final String s = function.getName(); - final Object function1 = functions.get(s); - - if(function1 == null) - { - functions.put(s, function); - } - else if(function1 instanceof JSFunction) - { - final JSFunction function2 = (JSFunction) function1; - if(findFunctionWithTheSameKind(functions, function, s) == null) - { - functions.put(s, new JSFunction[]{ - function2, - function - }); - } - } - } - return true; - } - }, ResolveState.initial(), jsClass, jsClass); - return functions; - } - - protected abstract void addNonimplementedFunction(final JSFunction function); +public abstract class ImplementedMethodProcessor extends JSResolveUtil.CollectMethodsToImplementProcessor { + protected final JSClass myJsClass; + + public ImplementedMethodProcessor(JSClass jsClass) { + super(null, null); + myJsClass = jsClass; + } + + @Override + protected boolean process(ResolveProcessor processor) { + Map functions = null; + + for (PsiElement _function : processor.getResults()) { + if (!(_function instanceof JSFunction function)) { + continue; + } + String name = function.getName(); + + if (functions == null) { + functions = collectAllVisibleClassFunctions( + myJsClass, + null, + jsFunction -> { + JSAttributeList attributeList = jsFunction.getAttributeList(); + PsiElement parentClass = JSResolveUtil.findParent(jsFunction); + if ((attributeList == null || attributeList.getAccessType() != JSAttributeList.AccessType.PUBLIC) + && myJsClass != parentClass) { + return Boolean.FALSE; + } + return Boolean.TRUE; + } + ); + } + + JSFunction o = findFunctionWithTheSameKind(functions, function, name); + + if (o == null) { + if (function.isGetProperty() || function.isSetProperty()) { + JSVariable var = myJsClass.findFieldByName(name); + if (var != null) { + JSAttributeList attributeList = var.getAttributeList(); + if (attributeList != null && attributeList.getAccessType() == JSAttributeList.AccessType.PUBLIC) { + continue; // implicit get and set methods + } + } + } + addNonimplementedFunction(function); + } + else { + addImplementedFunction(function, o); + } + } + return true; + } + + protected void addImplementedFunction(JSFunction interfaceFunction, JSFunction implementationFunction) { + } + + @RequiredReadAction + public static JSFunction findFunctionWithTheSameKind(Map functions, JSFunction function, String name) { + Object o = functions.get(name); + if (o instanceof JSFunction fun) { + return fun.getKind() == function.getKind() ? fun : null; + } + else if (o instanceof JSFunction[] jsFunctions) { + for (JSFunction fun : jsFunctions) { + if (fun.getKind() == function.getKind()) { + return fun; + } + } + } + return null; + } + + public static Map collectAllVisibleClassFunctions( + JSClass jsClass, + Map _functions, + final @Nullable Function filter + ) { + final Map functions = _functions != null ? _functions : new LinkedHashMap<>(); + jsClass.processDeclarations( + new ResolveProcessor(null) { + { + setToProcessHierarchy(true); + setLocalResolve(true); + } + + @Override + @RequiredReadAction + public boolean execute(@Nonnull PsiElement element, ResolveState state) { + if (element instanceof JSFunction function) { + if (function.isConstructor()) { + return true; // SWC stubs have constructor methods :( + } + + JSAttributeList attributeList = function.getAttributeList(); + if (attributeList != null && attributeList.getAccessType() == JSAttributeList.AccessType.PRIVATE) { + return true; + } + + Boolean filterValue = filter != null ? filter.apply(function) : null; + if (filterValue != null && !filterValue) { + return true; + } + String s = function.getName(); + Object function1 = functions.get(s); + + if (function1 == null) { + functions.put(s, function); + } + else if (function1 instanceof JSFunction function2 + && findFunctionWithTheSameKind(functions, function, s) == null) { + functions.put(s, new JSFunction[]{function2, function}); + } + } + return true; + } + }, + ResolveState.initial(), + jsClass, + jsClass + ); + return functions; + } + + protected abstract void addNonimplementedFunction(JSFunction function); } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/validation/JSAnnotatingVisitor.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/validation/JSAnnotatingVisitor.java index e4315a64..6a84a4fd 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/validation/JSAnnotatingVisitor.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/validation/JSAnnotatingVisitor.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.lang.javascript.impl.validation; import com.intellij.lang.javascript.JSTokenTypes; @@ -23,19 +22,18 @@ import com.intellij.lang.javascript.psi.impl.JSPackageStatementImpl; import com.intellij.lang.javascript.psi.resolve.JSImportHandlingUtil; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; -import com.intellij.lang.javascript.psi.resolve.ResolveProcessor; import com.intellij.lang.javascript.psi.util.JSUtils; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.codeEditor.Editor; import consulo.document.util.TextRange; -import consulo.javascript.language.JavaScriptBundle; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.javascript.psi.JSSimpleLiteralExpression; import consulo.javascript.psi.JavaScriptLambdaExpression; import consulo.language.ast.ASTNode; import consulo.language.ast.IElementType; import consulo.language.editor.FileModificationService; -import consulo.language.editor.annotation.Annotation; -import consulo.language.editor.annotation.AnnotationHolder; -import consulo.language.editor.annotation.Annotator; +import consulo.language.editor.annotation.*; import consulo.language.editor.impl.intention.RenameFileFix; import consulo.language.editor.inspection.LocalQuickFix; import consulo.language.editor.inspection.LocalQuickFixProvider; @@ -49,1310 +47,1457 @@ import consulo.language.psi.*; import consulo.language.psi.util.PsiTreeUtil; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; import consulo.module.content.ProjectRootManager; import consulo.project.Project; -import consulo.util.lang.ref.Ref; +import consulo.ui.annotation.RequiredUIAccess; +import consulo.util.lang.ref.SimpleReference; import consulo.virtualFileSystem.VirtualFile; import consulo.xml.psi.xml.XmlAttributeValue; import consulo.xml.psi.xml.XmlTagChild; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.PropertyKey; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; -import java.text.MessageFormat; import java.util.*; /** - * @by max, maxim.mossienko + * @author max + * @author maxim.mossienko */ public class JSAnnotatingVisitor extends JSElementVisitor implements Annotator { - private AnnotationHolder myHolder; - - @Override - public synchronized void annotate(PsiElement psiElement, AnnotationHolder holder) { - myHolder = holder; - psiElement.accept(this); - myHolder = null; - } - - @Override - public void visitJSAttributeNameValuePair(final JSAttributeNameValuePair attributeNameValuePair) { - checkReferences(attributeNameValuePair, ProblemKind.ERROR); - } - - @Override - public void visitJSIncludeDirective(final JSIncludeDirective includeDirective) { - checkReferences(includeDirective, ProblemKind.ERROR); - } - - @Override - public void visitJSLiteralExpression(JSSimpleLiteralExpression node) { - checkReferences(node, ProblemKind.ERROR); - } - - static enum ProblemKind { - ERROR, - WARNING, - INFO - } - - private void checkReferences(final PsiElement includeDirective, ProblemKind kind) { - for (PsiReference ref : includeDirective.getReferences()) { - if (!ref.isSoft() && hasBadResolve(ref)) { - final TextRange elementRange = ref.getElement().getTextRange(); - final TextRange textRange = ref.getRangeInElement(); - - final TextRange range = - new TextRange(elementRange.getStartOffset() + textRange.getStartOffset(), elementRange.getStartOffset() + textRange - .getEndOffset()); - final String message = - MessageFormat.format(((EmptyResolveMessageProvider)ref).getUnresolvedMessagePattern(), ref.getCanonicalText()); - Annotation annotation = - kind == ProblemKind.ERROR ? myHolder.createErrorAnnotation(range, message) : kind == ProblemKind.WARNING ? myHolder - .createWarningAnnotation(range, message) : myHolder.createInfoAnnotation(range, message); - - if (ref instanceof LocalQuickFixProvider) { - for (LocalQuickFix fix : ((LocalQuickFixProvider)ref).getQuickFixes()) { - if (fix instanceof IntentionAction) { - annotation.registerFix((IntentionAction)fix, new TextRange(annotation.getStartOffset(), annotation.getEndOffset())); - } - } - } - } - } - } + private AnnotationHolder myHolder; - private boolean hasBadResolve(final PsiReference ref) { - if (ref instanceof PsiPolyVariantReference) { - return ((PsiPolyVariantReference)ref).multiResolve(false).length == 0; + @Override + public synchronized void annotate(PsiElement psiElement, @Nonnull AnnotationHolder holder) { + myHolder = holder; + psiElement.accept(this); + myHolder = null; } - return ref.resolve() == null; - } - @Override - public void visitJSCallExpression(final JSCallExpression node) { - final JSExpression methodExpression = node.getMethodExpression(); - - if (methodExpression instanceof JSLiteralExpression) { - myHolder.createErrorAnnotation(methodExpression, JavaScriptBundle.message("javascript.parser.message.expected.function.name")); - } - } - - @Override - public void visitJSDocTagValue(final JSDocTagValue tagValue) { - checkReferences(tagValue, ProblemKind.WARNING); - } - - @Override - public void visitJSDocTag(final JSDocTag tagValue) { - checkReferences(tagValue, ProblemKind.WARNING); - } - - @Override - public void visitJSReferenceList(final JSReferenceList referenceList) { - final JSClass jsClass = (JSClass)referenceList.getParent(); - if (JSResolveUtil.isArtificialClassUsedForReferenceList(jsClass)) { - return; // implements="MyInterface" in mxml has artificial class created + @Override + @RequiredReadAction + public void visitJSAttributeNameValuePair(JSAttributeNameValuePair attributeNameValuePair) { + checkReferences(attributeNameValuePair, HighlightSeverity.ERROR); } - final boolean withinExtends = jsClass.getExtendsList() == referenceList; - final boolean withinImplements = jsClass.getImplementsList() == referenceList; - - if (withinImplements && jsClass.isInterface()) { - myHolder.createErrorAnnotation(referenceList, - JavaScriptBundle.message("javascript.validation.message.implements.for.interface.not.allowed")); - return; + @Override + @RequiredReadAction + public void visitJSIncludeDirective(JSIncludeDirective includeDirective) { + checkReferences(includeDirective, HighlightSeverity.ERROR); } - final Map nameToExprMap = new HashMap(); - - final JSReferenceExpression[] referenceExpressions = referenceList.getExpressions(); - if (referenceExpressions != null) { - for (JSReferenceExpression expr : referenceExpressions) { - final String s = expr.getReferencedName(); - if (s != null) { - nameToExprMap.put(s, expr); + @Override + @RequiredReadAction + public void visitJSLiteralExpression(JSSimpleLiteralExpression node) { + checkReferences(node, HighlightSeverity.ERROR); + } + + @RequiredReadAction + private void checkReferences(PsiElement includeDirective, HighlightSeverity kind) { + for (PsiReference ref : includeDirective.getReferences()) { + if (!ref.isSoft() && hasBadResolve(ref)) { + TextRange elementRange = ref.getElement().getTextRange(); + TextRange textRange = ref.getRangeInElement(); + + TextRange range = new TextRange( + elementRange.getStartOffset() + textRange.getStartOffset(), + elementRange.getStartOffset() + textRange.getEndOffset() + ); + LocalizeValue value = ((EmptyResolveMessageProvider)ref).buildUnresolvedMessage(ref.getCanonicalText()); + AnnotationBuilder builder = myHolder.newAnnotation(kind, value).range(range); + + if (ref instanceof LocalQuickFixProvider localQuickFixProvider) { + for (LocalQuickFix fix : localQuickFixProvider.getQuickFixes()) { + if (fix instanceof IntentionAction intentionAction) { + builder = builder.withFix(intentionAction); + } + } + } + builder.create(); + } } - } } - for (JSClass clazz : referenceList.getReferencedClasses()) { - final boolean b = clazz.isInterface(); - final JSReferenceExpression expr = nameToExprMap.get(clazz.getName()); - - if (!b && withinImplements) { - myHolder.createErrorAnnotation(expr, JavaScriptBundle.message("javascript.validation.message.interface.name.expected.here")); - } - else if (withinExtends && b != jsClass.isInterface()) { - myHolder.createErrorAnnotation(expr, - JavaScriptBundle.message(!b ? "javascript.validation.message.interface.name.expected.here" : "javascript.validation" + - ".message.class.name.expected.here")); - } - if (clazz == jsClass) { - myHolder.createErrorAnnotation(expr, JavaScriptBundle.message("javascript.validation.message.circular.dependency")) - .registerFix(new RemoveASTNodeFix - (referenceList.getNode(), "javascript.fix.remove.circular.dependency")); - } + @RequiredReadAction + private boolean hasBadResolve(PsiReference ref) { + return ref instanceof PsiPolyVariantReference psiPolyVariantReference + ? psiPolyVariantReference.multiResolve(false).length == 0 + : ref.resolve() == null; } - if (withinImplements) { - checkImplementedMethods(jsClass, new SimpleErrorReportingClient()); + @Override + @RequiredReadAction + public void visitJSCallExpression(JSCallExpression node) { + JSExpression methodExpression = node.getMethodExpression(); + + if (methodExpression instanceof JSLiteralExpression literal) { + myHolder.newAnnotation(HighlightSeverity.ERROR, JavaScriptLocalize.javascriptParserMessageExpectedFunctionName()) + .range(literal) + .create(); + } } - } - public interface ErrorReportingClient { - enum ProblemKind { - ERROR, - WARNING + @Override + @RequiredReadAction + public void visitJSDocTagValue(@Nonnull JSDocTagValue tagValue) { + checkReferences(tagValue, HighlightSeverity.WARNING); } - void reportError(final ASTNode nameIdentifier, final String s, ProblemKind kind, final IntentionAction implementMethodsFix); + @Override + @RequiredReadAction + public void visitJSDocTag(@Nonnull JSDocTag tagValue) { + checkReferences(tagValue, HighlightSeverity.WARNING); + } - void reportError(final PsiElement nameIdentifier, final String s, ProblemKind kind, final IntentionAction implementMethodsFix); - } + @Override + @RequiredReadAction + public void visitJSReferenceList(JSReferenceList referenceList) { + JSClass jsClass = (JSClass)referenceList.getParent(); + if (JSResolveUtil.isArtificialClassUsedForReferenceList(jsClass)) { + return; // implements="MyInterface" in mxml has artificial class created + } - public static void checkImplementedMethods(final JSClass jsClass, final ErrorReportingClient reportingClient) { - final JSResolveUtil.CollectMethodsToImplementProcessor implementedMethodProcessor = new ImplementedMethodProcessor(jsClass) { - ImplementMethodsFix implementMethodsFix = null; + boolean withinExtends = jsClass.getExtendsList() == referenceList; + boolean withinImplements = jsClass.getImplementsList() == referenceList; - @Override - protected void addNonimplementedFunction(final JSFunction function) { - final PsiElement node = myJsClass.getNameIdentifier(); - if (node == null) { - return; - } - if (implementMethodsFix == null) { - implementMethodsFix = new ImplementMethodsFix(myJsClass); - } - implementMethodsFix.addElementToProcess(function); - reportingClient.reportError(node, - JavaScriptBundle.message("javascript.validation.message.interface.method.not.implemented", - function.getName(), - ((JSClass)JSResolveUtil.findParent(function)).getQualifiedName()), - ErrorReportingClient.ProblemKind.ERROR, - implementMethodsFix); - } - - @Override - protected void addImplementedFunction(final JSFunction interfaceFunction, final JSFunction implementationFunction) { - final JSAttributeList attributeList = implementationFunction.getAttributeList(); - if (attributeList == null || attributeList.getAccessType() != JSAttributeList.AccessType.PUBLIC) { - final ASTNode node = findElementForAccessModifierError(implementationFunction, attributeList); - reportingClient.reportError(node, - JavaScriptBundle.message("javascript.validation.message.interface.method.invalid.access.modifier"), - ErrorReportingClient.ProblemKind.ERROR, - null - // TODO: quickfix - ); - } - - final SignatureMatchResult incompatibleSignature = checkCompatibleSignature(implementationFunction, interfaceFunction); - - if (incompatibleSignature != SignatureMatchResult.COMPATIBLE_SIGNATURE) { - PsiElement parent = JSResolveUtil.findParent(implementationFunction); - if (parent instanceof JSFile) { - parent = JSResolveUtil.getClassReferenceForXmlFromContext(parent); - } - - if (parent != myJsClass) { - // some parent incorrectly implements method from our interface - addNonimplementedFunction(interfaceFunction); + if (withinImplements && jsClass.isInterface()) { + myHolder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageImplementsForInterfaceNotAllowed() + ) + .range(referenceList) + .create(); return; - } - - if (incompatibleSignature == SignatureMatchResult.PARAMETERS_DIFFERS) { - final JSParameterList parameterList = implementationFunction.getParameterList(); - final JSParameterList expectedParameterList = interfaceFunction.getParameterList(); - reportingClient.reportError(parameterList.getNode(), - JavaScriptBundle.message("javascript.validation.message.interface.method.invalid.signature", - expectedParameterList != null ? expectedParameterList.getText() : "()"), - ErrorReportingClient.ProblemKind.ERROR, - null); // TODO: quickfix - } - else if (incompatibleSignature == SignatureMatchResult.RETURN_TYPE_DIFFERS) { - PsiElement implementationReturnTypeExpr = implementationFunction.getReturnTypeElement(); - PsiElement interfaceReturnTypeExpr = interfaceFunction.getReturnTypeElement(); - reportingClient.reportError(implementationReturnTypeExpr != null ? implementationReturnTypeExpr : implementationFunction - .getNameIdentifier(), - JavaScriptBundle.message("javascript.validation.message.interface.method.invalid.signature2", - interfaceReturnTypeExpr != null ? interfaceReturnTypeExpr.getText() : "*"), - ErrorReportingClient.ProblemKind.ERROR, - null); // TODO: quickfix - } - } - } - }; - JSResolveUtil.processInterfaceMethods(jsClass, implementedMethodProcessor); - } - - private static ASTNode findElementForAccessModifierError(final @Nonnull JSFunction o, final JSAttributeList attributeList) { - if (attributeList != null) { - final PsiElement accessTypeElement = attributeList.findAccessTypeElement(); - if (accessTypeElement != null) { - return accessTypeElement.getNode(); - } - } - PsiElement nameIdentifier = o.getNameIdentifier(); - return nameIdentifier == null ? null : nameIdentifier.getNode(); - } + } + + Map nameToExprMap = new HashMap<>(); - @Override - public void visitJSAttributeList(JSAttributeList attributeList) { - PsiElement parentForCheckingNsOrAccessModifier = null; + JSReferenceExpression[] referenceExpressions = referenceList.getExpressions(); + if (referenceExpressions != null) { + for (JSReferenceExpression expr : referenceExpressions) { + String s = expr.getReferencedName(); + if (s != null) { + nameToExprMap.put(s, expr); + } + } + } - PsiElement namespaceElement = attributeList.getNamespaceElement(); - PsiElement accessTypeElement = attributeList.findAccessTypeElement(); - PsiElement namespaceOrAccessModifierElement = namespaceElement; + for (JSClass clazz : referenceList.getReferencedClasses()) { + boolean isInterface = clazz.isInterface(); + JSReferenceExpression expr = nameToExprMap.get(clazz.getName()); + + if (!isInterface && withinImplements) { + myHolder.newAnnotation(HighlightSeverity.ERROR, JavaScriptLocalize.javascriptValidationMessageInterfaceNameExpectedHere()) + .range(expr) + .create(); + } + else if (withinExtends && isInterface != jsClass.isInterface()) { + myHolder.newAnnotation( + HighlightSeverity.ERROR, + isInterface + ? JavaScriptLocalize.javascriptValidationMessageClassNameExpectedHere() + : JavaScriptLocalize.javascriptValidationMessageInterfaceNameExpectedHere() + ) + .range(expr) + .create(); + } + if (clazz == jsClass) { + myHolder.newAnnotation(HighlightSeverity.ERROR, JavaScriptLocalize.javascriptValidationMessageCircularDependency()) + .range(expr) + .withFix(new RemoveASTNodeFix(referenceList.getNode(), JavaScriptLocalize.javascriptFixRemoveCircularDependency())) + .create(); + } + } - if (namespaceOrAccessModifierElement == null) { - namespaceOrAccessModifierElement = accessTypeElement; + if (withinImplements) { + checkImplementedMethods(jsClass, myHolder); + } } - else if (accessTypeElement != null) { - myHolder.createErrorAnnotation(namespaceOrAccessModifierElement, - JavaScriptBundle.message("javascript.validation.message.use.namespace.reference.or" + - ".access.modifier")) - .registerFix(new RemoveASTNodeFix(namespaceOrAccessModifierElement.getNode(), "javascript.fix.remove.namespace.reference")); - - myHolder.createErrorAnnotation(accessTypeElement, - JavaScriptBundle.message("javascript.validation.message.use.namespace.reference.or.access.modifier")) - .registerFix(new RemoveASTNodeFix(accessTypeElement.getNode(), "javascript.fix.remove.namespace.reference")); + + public static void checkImplementedMethods(final JSClass jsClass, final AnnotationHolder holder) { + JSResolveUtil.CollectMethodsToImplementProcessor implementedMethodProcessor = new ImplementedMethodProcessor(jsClass) { + ImplementMethodsFix implementMethodsFix = null; + + @Override + @RequiredReadAction + protected void addNonimplementedFunction(JSFunction function) { + PsiElement node = myJsClass.getNameIdentifier(); + if (node == null) { + return; + } + if (implementMethodsFix == null) { + implementMethodsFix = new ImplementMethodsFix(myJsClass); + } + implementMethodsFix.addElementToProcess(function); + holder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageInterfaceMethodNotImplemented( + function.getName(), + ((JSClass)JSResolveUtil.findParent(function)).getQualifiedName() + ) + ) + .range(node) + .withFix(implementMethodsFix) + .create(); + } + + @Override + @RequiredReadAction + protected void addImplementedFunction(JSFunction interfaceFunction, JSFunction implementationFunction) { + JSAttributeList attributeList = implementationFunction.getAttributeList(); + if (attributeList == null || attributeList.getAccessType() != JSAttributeList.AccessType.PUBLIC) { + ASTNode node = findElementForAccessModifierError(implementationFunction, attributeList); + holder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageInterfaceMethodInvalidAccessModifier() + ) + .range(node) + .create(); // TODO: quickfix + } + + SignatureMatchResult incompatibleSignature = checkCompatibleSignature(implementationFunction, interfaceFunction); + + if (incompatibleSignature != SignatureMatchResult.COMPATIBLE_SIGNATURE) { + PsiElement parent = JSResolveUtil.findParent(implementationFunction); + if (parent instanceof JSFile jsFile) { + parent = JSResolveUtil.getClassReferenceForXmlFromContext(jsFile); + } + + if (parent != myJsClass) { + // some parent incorrectly implements method from our interface + addNonimplementedFunction(interfaceFunction); + return; + } + + if (incompatibleSignature == SignatureMatchResult.PARAMETERS_DIFFERS) { + JSParameterList parameterList = implementationFunction.getParameterList(); + JSParameterList expectedParameterList = interfaceFunction.getParameterList(); + holder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageInterfaceMethodInvalidSignature( + expectedParameterList != null ? expectedParameterList.getText() : "()" + ) + ) + .range(parameterList.getNode()) + .create(); // TODO: quickfix + } + else if (incompatibleSignature == SignatureMatchResult.RETURN_TYPE_DIFFERS) { + PsiElement implementationReturnTypeExpr = implementationFunction.getReturnTypeElement(); + PsiElement interfaceReturnTypeExpr = interfaceFunction.getReturnTypeElement(); + holder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageInterfaceMethodInvalidSignature2( + interfaceReturnTypeExpr != null ? interfaceReturnTypeExpr.getText() : "*" + ) + ) + .range( + implementationReturnTypeExpr != null + ? implementationReturnTypeExpr + : implementationFunction.getNameIdentifier() + ) + .create(); // TODO: quickfix + } + } + } + }; + JSResolveUtil.processInterfaceMethods(jsClass, implementedMethodProcessor); } - if (namespaceOrAccessModifierElement != null) { - parentForCheckingNsOrAccessModifier = JSResolveUtil.findParent(attributeList.getParent()); - if (!(parentForCheckingNsOrAccessModifier instanceof JSClass)) { - String typeElementText; - boolean nodeUnderPackage; - - if (((!(nodeUnderPackage = - (parentForCheckingNsOrAccessModifier instanceof JSPackageStatement)) && (!(parentForCheckingNsOrAccessModifier - instanceof JSFile) || attributeList.getAccessType() != JSAttributeList.AccessType.PACKAGE_LOCAL)) || (!"public".equals( - typeElementText = - namespaceOrAccessModifierElement.getText())) && !"internal".equals(typeElementText))) { - boolean nsRef = namespaceOrAccessModifierElement instanceof JSReferenceExpression; - myHolder.createErrorAnnotation(namespaceOrAccessModifierElement, - JavaScriptBundle.message(nodeUnderPackage ? "javascript.validation.message.access" + - ".modifier.allowed.only.for.package.members" : nsRef ? "javascript.validation.message.namespace.allowed.only.for.class.members" : "javascript" + - ".validation.message.access.modifier.allowed.only.for.class.members")) - .registerFix(new RemoveASTNodeFix(namespaceOrAccessModifierElement - .getNode(), - nsRef ? "javascript.fix.remove.namespace.reference" : "javascript.fix.remove.access.modifier")); - } - } - else if (((JSClass)parentForCheckingNsOrAccessModifier).isInterface()) { - - if (attributeList.getAccessType() != JSAttributeList.AccessType.PACKAGE_LOCAL || attributeList.getNode() - .findChildByType(JSTokenTypes - .INTERNAL_KEYWORD) != null - - ) { - final ASTNode astNode = attributeList.getNode().findChildByType(JSTokenTypes.ACCESS_MODIFIERS); - final Annotation annotation = - myHolder.createErrorAnnotation(astNode, JavaScriptBundle.message("javascript.validation.message.interface.members.cannot" + - ".have.access.modifiers")); - - annotation.registerFix(new RemoveASTNodeFix(astNode, "javascript.fix.remove.access.modifier")); - } - } + @RequiredReadAction + private static ASTNode findElementForAccessModifierError(@Nonnull JSFunction o, JSAttributeList attributeList) { + if (attributeList != null) { + PsiElement accessTypeElement = attributeList.findAccessTypeElement(); + if (accessTypeElement != null) { + return accessTypeElement.getNode(); + } + } + PsiElement nameIdentifier = o.getNameIdentifier(); + return nameIdentifier == null ? null : nameIdentifier.getNode(); } - } - @Override - public void visitJSReferenceExpression(final JSReferenceExpression node) { - final PsiElement parent = node.getParent(); + @Override + @RequiredReadAction + public void visitJSAttributeList(JSAttributeList attributeList) { + PsiElement parentForCheckingNsOrAccessModifier = null; - if (parent instanceof JSNamedElement) { - JSNamedElement namedElement = (JSNamedElement)parent; - final PsiElement nameIdentifier = namedElement.getNameIdentifier(); + PsiElement namespaceElement = attributeList.getNamespaceElement(); + PsiElement accessTypeElement = attributeList.findAccessTypeElement(); + PsiElement namespaceOrAccessModifierElement = namespaceElement; - if (nameIdentifier != null && nameIdentifier == node) { - if (parent instanceof JSPackageStatement) { - checkPackageStatement((JSPackageStatement)parent); + if (namespaceOrAccessModifierElement == null) { + namespaceOrAccessModifierElement = accessTypeElement; } - else if (!(parent instanceof JSImportStatement) && parent.getParent() instanceof JSPackageStatement) { - checkNamedObjectIsInCorrespondingFile(namedElement); + else if (accessTypeElement != null) { + myHolder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageUseNamespaceReferenceOrAccessModifier() + ) + .range(namespaceOrAccessModifierElement) + .withFix(new RemoveASTNodeFix( + namespaceOrAccessModifierElement.getNode(), + JavaScriptLocalize.javascriptFixRemoveNamespaceReference() + )) + .create(); + + myHolder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageUseNamespaceReferenceOrAccessModifier() + ) + .range(accessTypeElement) + .withFix(new RemoveASTNodeFix(accessTypeElement.getNode(), JavaScriptLocalize.javascriptFixRemoveNamespaceReference())) + .create(); } - else if (parent instanceof JSFunction) { - JSFunction function = (JSFunction)parent; - if (function.isConstructor()) { - final JSClass clazz; - if (parent.getParent() instanceof JSClass) { - clazz = (JSClass)parent.getParent(); + if (namespaceOrAccessModifierElement != null) { + parentForCheckingNsOrAccessModifier = JSResolveUtil.findParent(attributeList.getParent()); + if (!(parentForCheckingNsOrAccessModifier instanceof JSClass)) { + String typeElementText; + boolean nodeUnderPackage; + + if (((!(nodeUnderPackage = (parentForCheckingNsOrAccessModifier instanceof JSPackageStatement)) + && (!(parentForCheckingNsOrAccessModifier instanceof JSFile) + || attributeList.getAccessType() != JSAttributeList.AccessType.PACKAGE_LOCAL)) + || (!"public".equals(typeElementText = namespaceOrAccessModifierElement.getText())) + && !"internal".equals(typeElementText))) { + boolean nsRef = namespaceOrAccessModifierElement instanceof JSReferenceExpression; + myHolder.newAnnotation( + HighlightSeverity.ERROR, + nodeUnderPackage ? + JavaScriptLocalize.javascriptValidationMessageAccessModifierAllowedOnlyForPackageMembers() + : nsRef + ? JavaScriptLocalize.javascriptValidationMessageNamespaceAllowedOnlyForClassMembers() + : JavaScriptLocalize.javascriptValidationMessageAccessModifierAllowedOnlyForClassMembers() + ) + .range(namespaceOrAccessModifierElement) + .withFix(new RemoveASTNodeFix( + namespaceOrAccessModifierElement.getNode(), + nsRef + ? JavaScriptLocalize.javascriptFixRemoveNamespaceReference() + : JavaScriptLocalize.javascriptFixRemoveAccessModifier() + )) + .create(); + } } - else { - assert parent.getParent() instanceof JSFile; - clazz = JSResolveUtil.getXmlBackedClass((JSFile)parent.getParent()); - assert clazz != null; + else if (((JSClass)parentForCheckingNsOrAccessModifier).isInterface()) { + if (attributeList.getAccessType() != JSAttributeList.AccessType.PACKAGE_LOCAL + || attributeList.getNode().findChildByType(JSTokenTypes.INTERNAL_KEYWORD) != null + ) { + ASTNode astNode = attributeList.getNode().findChildByType(JSTokenTypes.ACCESS_MODIFIERS); + myHolder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageInterfaceMembersCannotHaveAccessModifiers() + ) + .range(astNode) + .withFix(new RemoveASTNodeFix(astNode, JavaScriptLocalize.javascriptFixRemoveAccessModifier())) + .create(); + } } + } + } - checkMissedSuperCall(node, function, clazz); - } - else if (function.isSetProperty()) { - String typeString = function.getReturnTypeString(); + @Override + @RequiredReadAction + public void visitJSReferenceExpression(JSReferenceExpression node) { + PsiElement parent = node.getParent(); - if (typeString != null && !"void".equals(typeString)) { - // TODO: fix! - myHolder.createErrorAnnotation(function.getReturnTypeElement(), - JavaScriptBundle.message("javascript.validation.message.set.method.should.be.void.or" + - ".without.type")); - } + if (parent instanceof JSNamedElement namedElement) { + PsiElement nameIdentifier = namedElement.getNameIdentifier(); - JSParameterList parameterList = function.getParameterList(); - if (parameterList != null && parameterList.getParameters().length != 1) { - // TODO: fix! - myHolder.createErrorAnnotation(parameterList, - JavaScriptBundle.message("javascript.validation.message.set.method.should.have.one.parameter")); - } - } - else if (function.isGetProperty()) { - String typeString = function.getReturnTypeString(); + if (nameIdentifier != null && nameIdentifier == node) { + if (parent instanceof JSPackageStatement packageStatement) { + checkPackageStatement(packageStatement); + } + else if (!(parent instanceof JSImportStatement) && parent.getParent() instanceof JSPackageStatement) { + checkNamedObjectIsInCorrespondingFile(namedElement); + } + else if (parent instanceof JSFunction function) { + if (function.isConstructor()) { + JSClass clazz; + if (parent.getParent() instanceof JSClass jsClass) { + clazz = jsClass; + } + else { + assert parent.getParent() instanceof JSFile; + clazz = JSResolveUtil.getXmlBackedClass((JSFile)parent.getParent()); + assert clazz != null; + } + + checkMissedSuperCall(node, function, clazz); + } + else if (function.isSetProperty()) { + String typeString = function.getReturnTypeString(); + + if (typeString != null && !"void".equals(typeString)) { + // TODO: fix! + myHolder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageSetMethodShouldBeVoidOrWithoutType() + ) + .range(function.getReturnTypeElement()) + .create(); + } + + JSParameterList parameterList = function.getParameterList(); + if (parameterList != null && parameterList.getParameters().length != 1) { + // TODO: fix! + myHolder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageSetMethodShouldHaveOneParameter() + ) + .range(parameterList) + .create(); + } + } + else if (function.isGetProperty()) { + String typeString = function.getReturnTypeString(); + + if (typeString == null || "void".equals(typeString)) { + // TODO: fix! + myHolder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageGetMethodShouldBeValidType( + typeString != null ? typeString : "empty" + ) + ) + .range(typeString != null ? function.getReturnTypeElement() : nameIdentifier) + .create(); + } + + JSParameterList parameterList = function.getParameterList(); + if (parameterList != null && parameterList.getParameters().length != 0) { + // TODO: fix! + myHolder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageGetMethodShouldHaveNoParameter() + ) + .range(parameterList) + .create(); + } + } + } - if (typeString == null || "void".equals(typeString)) { - // TODO: fix! - myHolder.createErrorAnnotation(typeString != null ? function.getReturnTypeElement() : nameIdentifier, - JavaScriptBundle.message("javascript.validation.message.get.method.should.be.valid.type", - typeString != null ? typeString : "empty")); + if (parent instanceof JSClass jsClass) { + JSFunction constructor = jsClass.findFunctionByName(jsClass.getName()); + if (constructor == null) { + checkMissedSuperCall(node, constructor, jsClass); + } + + PsiElement clazzParent = jsClass.getParent(); + if (!(clazzParent instanceof JSPackageStatement || clazzParent instanceof JSFile)) { + myHolder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageNestedClassesAreNotAllowed() + ) + .range(node) + .create(); + } + } } + } - JSParameterList parameterList = function.getParameterList(); - if (parameterList != null && parameterList.getParameters().length != 0) { - // TODO: fix! - myHolder.createErrorAnnotation(parameterList, - JavaScriptBundle.message("javascript.validation.message.get.method.should.have.no.parameter")); + if (node.getQualifier() == null && !(parent instanceof JSCallExpression) && "arguments".equals(node.getText())) { + JSFunction fun = PsiTreeUtil.getParentOfType(node, JSFunction.class); + if (fun == null) { + myHolder.newAnnotation(HighlightSeverity.ERROR, JavaScriptLocalize.javascriptValidationMessageArgumentsOutOfFunction()) + .range(node) + .create(); + } + else { + JSParameterList parameterList = fun.getParameterList(); + if (parameterList != null) { + for (JSParameter p : parameterList.getParameters()) { + if (p.isRest()) { + myHolder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageArgumentsWithRestParameter() + ) + .range(node); + } + } + } } - } } + } - if (parent instanceof JSClass) { - final JSClass jsClass = (JSClass)parent; - final JSFunction constructor = jsClass.findFunctionByName(jsClass.getName()); - if (constructor == null) { - checkMissedSuperCall(node, constructor, jsClass); - } - - PsiElement clazzParent = jsClass.getParent(); - if (!(clazzParent instanceof JSPackageStatement) && !(clazzParent instanceof JSFile)) { - myHolder.createErrorAnnotation(node, JavaScriptBundle.message("javascript.validation.message.nested.classes.are.not.allowed")); - } + @RequiredReadAction + private void checkMissedSuperCall(JSReferenceExpression node, JSFunction constructor, JSClass jsClass) { + if (jsClass.isInterface()) { + return; + } + JSFunction nontrivialSuperClassConstructor = getNontrivialSuperClassConstructor(jsClass); + + if (nontrivialSuperClassConstructor != null && !hasSuperConstructorCall(constructor)) { + myHolder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageMissedSuperConstructorCall() + ) + .range(node) + .withFix( + constructor == null + ? new AddConstructorAndSuperInvokationFix(node, nontrivialSuperClassConstructor) + : new AddSuperInvokationFix(node, nontrivialSuperClassConstructor) + ) + .create(); } - } } - if (node.getQualifier() == null) { - if (!(parent instanceof JSCallExpression)) { - if ("arguments".equals(node.getText())) { - JSFunction fun = PsiTreeUtil.getParentOfType(node, JSFunction.class); - if (fun == null) { - myHolder.createErrorAnnotation(node, JavaScriptBundle.message("javascript.validation.message.arguments.out.of.function")); - } - else { - JSParameterList parameterList = fun.getParameterList(); - if (parameterList != null) { - for (JSParameter p : parameterList.getParameters()) { - if (p.isRest()) { - myHolder.createErrorAnnotation(node, - JavaScriptBundle.message("javascript.validation.message.arguments.with.rest.parameter")); - } - } + @RequiredReadAction + private boolean hasSuperConstructorCall(JSFunction jsFunction) { + if (jsFunction == null) { + return false; + } + JSSourceElement[] body = jsFunction.getBody(); + JSStatement[] statements = body.length > 0 ? ((JSBlockStatement)body[0]).getStatements() : JSStatement.EMPTY; + + for (JSStatement st : statements) { + if (st instanceof JSExpressionStatement expression + && expression.getExpression() instanceof JSCallExpression call + && call.getMethodExpression() instanceof JSSuperExpression) { + return true; } - } } - } - } - } - private void checkMissedSuperCall(JSReferenceExpression node, JSFunction constructor, JSClass jsClass) { - if (jsClass.isInterface()) { - return; + return false; } - JSFunction nontrivialSuperClassConstructor = getNontrivialSuperClassConstructor(jsClass); - if (nontrivialSuperClassConstructor != null) { - Annotation annotation = null; + @RequiredReadAction + public static JSFunction getNontrivialSuperClassConstructor(JSClass clazz) { + JSClass[] classes = clazz.getSuperClasses(); - if (!hasSuperConstructorCall(constructor)) { - annotation = - myHolder.createErrorAnnotation(node, JavaScriptBundle.message("javascript.validation.message.missed.super.constructor.call")); - } + if (classes.length > 0) { + JSFunction constructor = classes[0].findFunctionByName(classes[0].getName()); - if (annotation != null) { - if (constructor == null) { - annotation.registerFix(new AddConstructorAndSuperInvokationFix(node, nontrivialSuperClassConstructor)); - } - else { - annotation.registerFix(new AddSuperInvokationFix(node, nontrivialSuperClassConstructor)); + if (constructor != null) { + JSParameter[] jsParameters = constructor.getParameterList().getParameters(); + boolean hasRequiredParameters = false; + for (JSParameter p : jsParameters) { + if (!p.isRest() && !p.hasInitializer()) { + hasRequiredParameters = true; + break; + } + } + return hasRequiredParameters ? constructor : null; + } } - } - } - } - private boolean hasSuperConstructorCall(JSFunction jsFunction) { - if (jsFunction == null) { - return false; - } - final JSSourceElement[] body = (jsFunction).getBody(); - final JSStatement[] statements = body.length > 0 ? ((JSBlockStatement)body[0]).getStatements() : JSStatement.EMPTY; - JSExpression expr; - - for (JSStatement st : statements) { - if (st instanceof JSExpressionStatement && - (expr = ((JSExpressionStatement)st).getExpression()) instanceof JSCallExpression && - (((JSCallExpression)expr).getMethodExpression()) instanceof JSSuperExpression) { - return true; - } + return null; } - return false; - } + @Override + @RequiredReadAction + public void visitJSParameterList(JSParameterList node) { + boolean foundRest = false; + boolean initializerPresent = false; - public static JSFunction getNontrivialSuperClassConstructor(JSClass clazz) { - final JSClass[] classes = clazz.getSuperClasses(); + for (JSParameter parameter : node.getParameters()) { + JSExpression initializer = parameter.getInitializer(); + boolean hasInitializer = initializer != null; - if (classes.length > 0) { - final JSFunction constructor = classes[0].findFunctionByName(classes[0].getName()); + if (hasInitializer && !initializerPresent) { + initializerPresent = true; + } + else if (!hasInitializer && initializerPresent && !parameter.isRest()) { + myHolder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageParameterShouldBeInitialized() + ) + .range(parameter) + .withFix(new RemoveASTNodeFix(parameter.getNode(), JavaScriptLocalize.javascriptFixRemoveParameter())) + .create(); + } + else if (hasInitializer && parameter.isRest()) { + myHolder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageRestParameterShouldNotBeInitialized() + ) + .range(parameter) + .withFix(new RemoveASTNodeFix( + JavaScriptLocalize.javascriptFixRemoveInitializer(), + getNodesBefore(initializer, JSTokenTypes.EQ) + )) + .create(); + } - if (constructor != null) { - final JSParameter[] jsParameters = constructor.getParameterList().getParameters(); - boolean hasRequiredParameters = false; - for (JSParameter p : jsParameters) { - if (!p.isRest() && !p.hasInitializer()) { - hasRequiredParameters = true; - break; - } + if (parameter.isRest() && !foundRest) { + foundRest = true; + PsiElement typeElement = parameter.getTypeElement(); + if (typeElement != null && !"Array".equals(typeElement.getText())) { + myHolder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageUnexpectedTypeForRestParameter() + ) + .range(typeElement) + .withFix(new RemoveASTNodeFix( + JavaScriptLocalize.javascriptFixRemoveTypeReference(), + getNodesBefore(typeElement, JSTokenTypes.COLON) + )) + .create(); + } + } + else if (foundRest) { + myHolder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageParameterIsNotAllowedAfterRestParameter() + ) + .range(parameter) + .withFix(new RemoveASTNodeFix(parameter.getNode(), JavaScriptLocalize.javascriptFixRemoveParameter())) + .create(); + } } - return hasRequiredParameters ? constructor : null; - } } - return null; - } - - @Override - public void visitJSParameterList(JSParameterList node) { - boolean foundRest = false; - boolean initializerPresent = false; - - for (JSParameter parameter : node.getParameters()) { - JSExpression initializer = parameter.getInitializer(); - boolean hasInitializer = initializer != null; - - if (hasInitializer && !initializerPresent) { - initializerPresent = true; - } - else if (!hasInitializer && initializerPresent && !parameter.isRest()) { - myHolder.createErrorAnnotation(parameter, JavaScriptBundle.message("javascript.validation.message.parameter.should.be.initialized")) - .registerFix(new - RemoveASTNodeFix(parameter.getNode(), "javascript.fix.remove.parameter")); - } - else if (hasInitializer && parameter.isRest()) { - myHolder.createErrorAnnotation(parameter, - JavaScriptBundle.message("javascript.validation.message.rest.parameter.should.not.be.initialized")) - .registerFix(new RemoveASTNodeFix("javascript.fix.remove.initializer", getNodesBefore(initializer, JSTokenTypes.EQ))); - } - - if (parameter.isRest() && !foundRest) { - foundRest = true; - PsiElement typeElement = parameter.getTypeElement(); - if (typeElement != null && !"Array".equals(typeElement.getText())) { - myHolder.createErrorAnnotation(typeElement, - JavaScriptBundle.message("javascript.validation.message.unexpected.type.for.rest.parameter")) - .registerFix - (new RemoveASTNodeFix("javascript.fix.remove.type.reference", getNodesBefore(typeElement, JSTokenTypes.COLON))); - } - } - else if (foundRest) { - myHolder.createErrorAnnotation(parameter, - JavaScriptBundle.message( - "javascript.validation.message.parameter.is.not.allowed.after.rest.parameter")) - .registerFix(new RemoveASTNodeFix(parameter.getNode(), "javascript.fix.remove.parameter")); - } - } - } + @RequiredReadAction + private static ASTNode[] getNodesBefore(PsiElement initializer, IElementType eq) { + List nodes = new ArrayList<>(); + PsiElement element = initializer.getPrevSibling(); + PsiElement lastElement = element; - private static ASTNode[] getNodesBefore(PsiElement initializer, IElementType eq) { - List nodes = new ArrayList(); - PsiElement element = initializer.getPrevSibling(); - PsiElement lastElement = element; + if (element instanceof PsiWhiteSpace whiteSpace) { + nodes.add(whiteSpace.getNode()); + lastElement = whiteSpace.getPrevSibling(); + } - if (element instanceof PsiWhiteSpace) { - nodes.add(element.getNode()); - lastElement = element.getPrevSibling(); - } + if (lastElement != null && lastElement.getNode().getElementType() == eq) { + nodes.add(lastElement.getNode()); + } - if (lastElement != null && lastElement.getNode().getElementType() == eq) { - nodes.add(lastElement.getNode()); + nodes.add(initializer.getNode()); + return nodes.toArray(new ASTNode[nodes.size()]); } - nodes.add(initializer.getNode()); - return nodes.toArray(new ASTNode[nodes.size()]); - } - - @Override - public void visitJSPackageStatement(final JSPackageStatement packageStatement) { - for (PsiElement el = packageStatement.getPrevSibling(); el != null; el = el.getPrevSibling()) { - if (!(el instanceof PsiWhiteSpace) && !(el instanceof PsiComment)) { - myHolder.createErrorAnnotation(packageStatement.getFirstChild().getNode(), - JavaScriptBundle.message("javascript.validation.message.package.shouldbe" + - ".first.statement")); - break; - } - } - final PsiElement node = packageStatement.getNameIdentifier(); - if (node == null) { - checkPackageStatement(packageStatement); + @Override + @RequiredReadAction + public void visitJSPackageStatement(JSPackageStatement packageStatement) { + for (PsiElement el = packageStatement.getPrevSibling(); el != null; el = el.getPrevSibling()) { + if (!(el instanceof PsiWhiteSpace || el instanceof PsiComment)) { + myHolder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessagePackageShouldbeFirstStatement() + ) + .range(packageStatement.getFirstChild().getNode()) + .create(); + break; + } + } + PsiElement node = packageStatement.getNameIdentifier(); + if (node == null) { + checkPackageStatement(packageStatement); + } } - } - @Override - public void visitJSAssignmentExpression(final JSAssignmentExpression expression) { - JSExpression lExpr = expression.getLOperand(); - if (lExpr == null) { - return; - } - if (lExpr instanceof JSDefinitionExpression) { - lExpr = ((JSDefinitionExpression)lExpr).getExpression(); - } + @Override + @RequiredReadAction + public void visitJSAssignmentExpression(JSAssignmentExpression expression) { + JSExpression lExpr = expression.getLOperand(); + if (lExpr == null) { + return; + } + if (lExpr instanceof JSDefinitionExpression definitionExpression) { + lExpr = definitionExpression.getExpression(); + } - if (lExpr instanceof JSReferenceExpression) { - PsiElement resolved = ((JSReferenceExpression)lExpr).resolve(); - if (resolved instanceof JSVariable && ((JSVariable)resolved).isConst()) { - myHolder.createErrorAnnotation(lExpr, JavaScriptBundle.message("javascript.validation.message.assignment.to.const")); - } - } + if (lExpr instanceof JSReferenceExpression lRefExpr) { + PsiElement resolved = lRefExpr.resolve(); + if (resolved instanceof JSVariable variable && variable.isConst()) { + myHolder.newAnnotation(HighlightSeverity.ERROR, JavaScriptLocalize.javascriptValidationMessageAssignmentToConst()) + .range(lExpr) + .create(); + } + } - if (!JSUtils.isLHSExpression(lExpr)) { - myHolder.createErrorAnnotation(lExpr, JavaScriptBundle.message("javascript.validation.message.must.be.lvalue")); - } - } - - @Override - public void visitJSArrayLiteralExpression(final JSArrayLiteralExpression node) { - final PsiElement lastChild = node.getLastChild(); - PsiElement child = lastChild != null ? lastChild.getPrevSibling() : null; - if (child instanceof PsiWhiteSpace) { - child = child.getPrevSibling(); + if (!JSUtils.isLHSExpression(lExpr)) { + myHolder.newAnnotation(HighlightSeverity.ERROR, JavaScriptLocalize.javascriptValidationMessageMustBeLvalue()) + .range(lExpr) + .create(); + } } - ASTNode childNode; - if (child != null && (childNode = child.getNode()) != null && childNode.getElementType() == JSTokenTypes.COMMA) { - final Annotation annotation = - myHolder.createWarningAnnotation(child, JavaScriptBundle.message("javascript.validation.message.unneeded.comma")); - annotation.registerFix(new RemoveASTNodeFix(childNode, "javascript.validation.message.remove.unneeded.comma.fix")); + @Override + @RequiredReadAction + public void visitJSArrayLiteralExpression(JSArrayLiteralExpression node) { + PsiElement lastChild = node.getLastChild(); + PsiElement child = lastChild != null ? lastChild.getPrevSibling() : null; + if (child instanceof PsiWhiteSpace whiteSpace) { + child = whiteSpace.getPrevSibling(); + } + ASTNode childNode; + + if (child != null && (childNode = child.getNode()) != null && childNode.getElementType() == JSTokenTypes.COMMA) { + myHolder.newAnnotation(HighlightSeverity.WARNING, JavaScriptLocalize.javascriptValidationMessageUnneededComma()) + .range(child) + .withFix(new RemoveASTNodeFix(childNode, JavaScriptLocalize.javascriptValidationMessageRemoveUnneededCommaFix())) + .create(); + } } - } - @Override - public void visitJSTryStatement(final JSTryStatement node) { - final JSCatchBlock[] blocks = node.getAllCatchBlocks(); + @Override + @RequiredReadAction + public void visitJSTryStatement(JSTryStatement node) { + JSCatchBlock[] blocks = node.getAllCatchBlocks(); - if (blocks.length > 1) { - final Set typeToCatch = new HashSet(); + if (blocks.length > 1) { + Set typeToCatch = new HashSet<>(); - for (JSCatchBlock block : blocks) { - final JSParameter p = block.getParameter(); - if (p == null) { - continue; - } + for (JSCatchBlock block : blocks) { + JSParameter p = block.getParameter(); + if (p == null) { + continue; + } - String s = p.getTypeString(); - if (s == null) { - s = ""; - } + String s = p.getTypeString(); + if (s == null) { + s = ""; + } - if (typeToCatch.contains(s)) { - final Annotation annotation = - myHolder.createErrorAnnotation(block, JavaScriptBundle.message("javascript.validation.message.duplicated.catch.block")); - annotation.registerFix(new RemoveASTNodeFix(block.getNode(), "javascript.validation.message.duplicated.catch.block.fix")); - } - else { - typeToCatch.add(s); + if (typeToCatch.contains(s)) { + myHolder.newAnnotation(HighlightSeverity.ERROR, JavaScriptLocalize.javascriptValidationMessageDuplicatedCatchBlock()) + .range(block) + .withFix(new RemoveASTNodeFix( + block.getNode(), + JavaScriptLocalize.javascriptValidationMessageDuplicatedCatchBlockFix() + )) + .create(); + } + else { + typeToCatch.add(s); + } + } } - } - } - } - - @Override - public void visitJSVariable(final JSVariable var) { - if (var.isConst() && var.getInitializer() == null) { - if (var.getParent() instanceof JSVarStatement && var.getParent().getParent() instanceof JSForInStatement) { - return; - } - - JSAttributeList attributeList = var.getAttributeList(); - if (attributeList == null || attributeList.getAttributesByName("Embed").length == 0) { - myHolder.createWarningAnnotation(var, - JavaScriptBundle.message("javascript.validation.message.const.variable.without.initializer.")); - } } - if (var.getParent().getParent() instanceof JSPackageStatement) { - checkNamedObjectIsInCorrespondingFile(var); - } - } + @Override + @RequiredReadAction + public void visitJSVariable(JSVariable var) { + if (var.isConst() && var.getInitializer() == null) { + if (var.getParent() instanceof JSVarStatement varStatement && varStatement.getParent() instanceof JSForInStatement) { + return; + } - @Override - public void visitJSContinueStatement(final JSContinueStatement node) { - if (node.getStatementToContinue() == null) { - myHolder.createErrorAnnotation(node, JavaScriptBundle.message("javascript.validation.message.continue.without.target")); - } - } + JSAttributeList attributeList = var.getAttributeList(); + if (attributeList == null || attributeList.getAttributesByName("Embed").length == 0) { + myHolder.newAnnotation( + HighlightSeverity.WARNING, + JavaScriptLocalize.javascriptValidationMessageConstVariableWithoutInitializer() + ) + .range(var) + .create(); + } + } - @Override - public void visitJSBreakStatement(final JSBreakStatement node) { - if (node.getStatementToBreak() == null) { - myHolder.createErrorAnnotation(node, JavaScriptBundle.message("javascript.validation.message.break.without.target")); - } - } - - @Override - public void visitJSThisExpression(final JSThisExpression node) { - checkClassReferenceInStaticContext(node, "javascript.validation.message.this.referenced.from.static.context"); - } - - private void checkClassReferenceInStaticContext(final JSExpression node, - @PropertyKey(resourceBundle = JavaScriptBundle.BUNDLE) String key) { - PsiElement element = PsiTreeUtil.getParentOfType(node, JSFunction.class, JSFile.class, JSClass.class, JSObjectLiteralExpression.class, - XmlTagChild.class); - - if (element instanceof JSFunction) { - final JSFunction function = (JSFunction)element; - - final JSAttributeList attributeList = function.getAttributeList(); - if (attributeList != null && attributeList.hasModifier(JSAttributeList.ModifierType.STATIC)) { - myHolder.createErrorAnnotation(node, JavaScriptBundle.message(key)); - return; - } + if (var.getParent().getParent() instanceof JSPackageStatement) { + checkNamedObjectIsInCorrespondingFile(var); + } } - PsiElement elementParent; - if (node instanceof JSSuperExpression && (element == null || (!((elementParent = - element.getParent()) instanceof JSClass) && (!(elementParent - instanceof JSFile) || elementParent.getContext() == null)))) { - myHolder.createErrorAnnotation(node, - JavaScriptBundle.message( - "javascript.validation.message.super.referenced.without.class.instance.context")); + @Override + @RequiredReadAction + public void visitJSContinueStatement(JSContinueStatement node) { + if (node.getStatementToContinue() == null) { + myHolder.newAnnotation(HighlightSeverity.ERROR, JavaScriptLocalize.javascriptValidationMessageContinueWithoutTarget()) + .range(node) + .create(); + } } - } - - @Override - public void visitJSSuperExpression(final JSSuperExpression node) { - checkClassReferenceInStaticContext(node, "javascript.validation.message.super.referenced.from.static.context"); - } - - @Override - public void visitJSFunctionDeclaration(final JSFunction node) { - final PsiElement nameIdentifier = node.getNameIdentifier(); - if (nameIdentifier == null) { - return; + + @Override + @RequiredReadAction + public void visitJSBreakStatement(JSBreakStatement node) { + if (node.getStatementToBreak() == null) { + myHolder.newAnnotation(HighlightSeverity.ERROR, JavaScriptLocalize.javascriptValidationMessageBreakWithoutTarget()) + .range(node) + .create(); + } } - PsiElement parent = node.getParent(); - if (parent instanceof JSFile) { - parent = JSResolveUtil.getClassReferenceForXmlFromContext(parent); + @Override + @RequiredReadAction + public void visitJSThisExpression(@Nonnull JSThisExpression node) { + checkClassReferenceInStaticContext(node, JavaScriptLocalize.javascriptValidationMessageThisReferencedFromStaticContext()); + } + + @RequiredReadAction + @SuppressWarnings("unchecked") + private void checkClassReferenceInStaticContext(JSExpression node, LocalizeValue message) { + PsiElement element = PsiTreeUtil.getParentOfType( + node, + JSFunction.class, + JSFile.class, + JSClass.class, + JSObjectLiteralExpression.class, + XmlTagChild.class + ); + + if (element instanceof JSFunction function) { + JSAttributeList attributeList = function.getAttributeList(); + if (attributeList != null && attributeList.hasModifier(JSAttributeList.ModifierType.STATIC)) { + myHolder.newAnnotation(HighlightSeverity.ERROR, message) + .range(node) + .create(); + return; + } + } - if (parent instanceof JSClass && node.getName().equals(((JSClass)parent).getName()) && JavaScriptSupportLoader.isFlexMxmFile(parent - .getContainingFile())) { - final Annotation annotation = - myHolder.createErrorAnnotation(nameIdentifier, JavaScriptBundle.message("javascript.validation.message.constructor.in.mxml" + - ".is.not.allowed")); + if (!(node instanceof JSSuperExpression)) { + return; + } - annotation.registerFix(new RemoveASTNodeFix(node.getNode(), "javascript.fix.remove.constructor")); - } + PsiElement elementParent = element != null ? element.getParent() : null; + if (element == null + || !(elementParent instanceof JSClass || elementParent instanceof JSFile jsFile && jsFile.getContext() != null)) { + myHolder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageSuperReferencedWithoutClassInstanceContext() + ) + .range(node) + .create(); + } } - if (parent instanceof JSPackageStatement) { - checkNamedObjectIsInCorrespondingFile(node); + @Override + @RequiredReadAction + public void visitJSSuperExpression(@Nonnull JSSuperExpression node) { + checkClassReferenceInStaticContext(node, JavaScriptLocalize.javascriptValidationMessageSuperReferencedFromStaticContext()); } - if (parent instanceof JSClass && !node.isConstructor()) { - final JSAttributeList attributeList = node.getAttributeList(); - final JSClass clazz = (JSClass)parent; - - if (attributeList == null || (!attributeList.hasModifier(JSAttributeList.ModifierType.STATIC) && (attributeList.getAccessType() != JSAttributeList - .AccessType.PRIVATE || attributeList.hasModifier(JSAttributeList.ModifierType.OVERRIDE)))) { - final String qName = clazz.getQualifiedName(); - final boolean hasOverride = attributeList != null ? attributeList.hasModifier(JSAttributeList.ModifierType.OVERRIDE) : false; - - final Ref set = new Ref(); - boolean b = JSResolveUtil.iterateType(node, parent, qName, new JSResolveUtil.OverrideHandler() { - @Override - public boolean process(final ResolveProcessor processor, final PsiElement scope, final String className) { - if (qName == className || (qName != null && qName.equals(className))) { - return true; - } - set.set((JSFunction)processor.getResult()); - if ("Object".equals(className)) { - if (hasOverride && !attributeList.hasModifier(JSAttributeList.ModifierType.NATIVE)) { /*native modifier is written always*/ - final ASTNode astNode = attributeList.getNode().findChildByType(JSTokenTypes.OVERRIDE_KEYWORD); - final Annotation annotation = - myHolder.createErrorAnnotation(astNode, JavaScriptBundle.message("javascript.validation.message.function.override.for" + - ".object.method")); - - annotation.registerFix(new RemoveASTNodeFix(astNode, "javascript.fix.remove.override.modifier")); - } - return false; + @Override + @RequiredReadAction + public void visitJSFunctionDeclaration(JSFunction node) { + PsiElement nameIdentifier = node.getNameIdentifier(); + if (nameIdentifier == null) { + return; + } + PsiElement parent = node.getParent(); + + if (parent instanceof JSFile file) { + parent = JSResolveUtil.getClassReferenceForXmlFromContext(file); + + if (parent instanceof JSClass jsClass && node.getName().equals(jsClass.getName()) + && JavaScriptSupportLoader.isFlexMxmFile(parent.getContainingFile())) { + myHolder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageConstructorInMxmlIsNotAllowed() + ) + .range(nameIdentifier) + .withFix(new RemoveASTNodeFix(node.getNode(), JavaScriptLocalize.javascriptFixRemoveConstructor())) + .create(); } - else if (!hasOverride) { - final Annotation annotation = - myHolder.createErrorAnnotation(nameIdentifier, JavaScriptBundle.message("javascript.validation.message.function" + - ".override.without.override.modifier", - className)); + } + + if (parent instanceof JSPackageStatement) { + checkNamedObjectIsInCorrespondingFile(node); + } + + if (parent instanceof JSClass clazz && !node.isConstructor()) { + JSAttributeList attributeList = node.getAttributeList(); + + if (attributeList == null || (!attributeList.hasModifier(JSAttributeList.ModifierType.STATIC) + && (attributeList.getAccessType() != JSAttributeList.AccessType.PRIVATE + || attributeList.hasModifier(JSAttributeList.ModifierType.OVERRIDE)))) { + String qName = clazz.getQualifiedName(); + boolean hasOverride = attributeList != null && attributeList.hasModifier(JSAttributeList.ModifierType.OVERRIDE); + + SimpleReference set = new SimpleReference<>(); + boolean b = JSResolveUtil.iterateType( + node, + parent, + qName, + (processor, scope, className) -> { + if (qName == className || (qName != null && qName.equals(className))) { + return true; + } + set.set((JSFunction)processor.getResult()); + if ("Object".equals(className)) { + /*native modifier is written always*/ + if (hasOverride && !attributeList.hasModifier(JSAttributeList.ModifierType.NATIVE)) { + ASTNode astNode = attributeList.getNode().findChildByType(JSTokenTypes.OVERRIDE_KEYWORD); + //noinspection RequiredXAction + myHolder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageFunctionOverrideForObjectMethod() + ) + .range(astNode) + .withFix(new RemoveASTNodeFix(astNode, JavaScriptLocalize.javascriptFixRemoveOverrideModifier())) + .create(); + } + return false; + } + else if (!hasOverride) { + //noinspection RequiredXAction + myHolder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageFunctionOverrideWithoutOverrideModifier(className) + ) + .range(nameIdentifier) + .withFix(new AddOverrideIntentionAction(node)) + .create(); + } + return false; + } + ); + + if (b && hasOverride) { + ASTNode astNode = attributeList.getNode().findChildByType(JSTokenTypes.OVERRIDE_KEYWORD); + myHolder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageFunctionOverrideWithoutParentMethod() + ) + .range(astNode) + .withFix(new RemoveASTNodeFix(astNode, JavaScriptLocalize.javascriptFixRemoveOverrideModifier())) + .create(); + } - annotation.registerFix(new AddOverrideIntentionAction(node)); + if (!b && hasOverride) { + JSFunction override = set.get(); + JSAttributeList overrideAttrList = override.getAttributeList(); + String overrideNs = null; + + if ((overrideAttrList == null && (attributeList.getAccessType() != JSAttributeList.AccessType.PACKAGE_LOCAL)) + || (overrideAttrList != null && attributeList.getAccessType() != overrideAttrList.getAccessType()) + || overrideAttrList != null + && (overrideNs = overrideAttrList.getNamespace()) != null && !overrideNs.equals(attributeList.getNamespace())) { + String accessType = overrideNs != null ? overrideNs : ( + overrideAttrList != null + ? overrideAttrList.getAccessType() + : JSAttributeList.AccessType.PACKAGE_LOCAL + ).toString().toLowerCase(); + myHolder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageFunctionOverrideIncompatibleAccessModifier(accessType) + ) + .range(findElementForAccessModifierError(node, attributeList)) + .create(); + + // TODO: quickfix + //annotation.registerFix( + // new RemoveASTNodeFix(astNode,"javascript.fix.remove.override.modifier") + //); + } + + SignatureMatchResult incompatibleSignature = checkCompatibleSignature(node, override); + + if (incompatibleSignature == SignatureMatchResult.PARAMETERS_DIFFERS) { + JSParameterList nodeParameterList = node.getParameterList(); + JSParameterList overrideParameterList = override.getParameterList(); + + String params = overrideParameterList != null ? overrideParameterList.getText() : "()"; + myHolder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageFunctionOverrideIncompatibleSignature(params) + ) + .range(nodeParameterList != null ? nodeParameterList : node.getNameIdentifier()) + .create(); + + // TODO: quickfix + //annotation.registerFix( + // new RemoveASTNodeFix(astNode,"javascript.fix.remove.override.modifier") + //); + } + else if (incompatibleSignature == SignatureMatchResult.RETURN_TYPE_DIFFERS) { + PsiElement returnTypeExpr = node.getReturnTypeElement(); + PsiElement overrideReturnTypeExpr = override.getReturnTypeElement(); + String retType = overrideReturnTypeExpr != null ? overrideReturnTypeExpr.getText() : "*"; + myHolder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageFunctionOverrideIncompatibleSignature2(retType) + ) + .range(returnTypeExpr != null ? returnTypeExpr : node.getNameIdentifier()) + .create(); + + // TODO: quickfix + //annotation.registerFix( + // new RemoveASTNodeFix(astNode,"javascript.fix.remove.override.modifier") + //); + } + } } - return false; - } - }); - - if (b && hasOverride) { - final ASTNode astNode = attributeList.getNode().findChildByType(JSTokenTypes.OVERRIDE_KEYWORD); - final Annotation annotation = - myHolder.createErrorAnnotation(astNode, JavaScriptBundle.message("javascript.validation.message.function.override.without" + - ".parent.method")); - - annotation.registerFix(new RemoveASTNodeFix(astNode, "javascript.fix.remove.override.modifier")); - } - - if (!b && hasOverride) { - final JSFunction override = set.get(); - final JSAttributeList overrideAttrList = override.getAttributeList(); - String overrideNs = null; - - if ((overrideAttrList == null && (attributeList.getAccessType() != JSAttributeList.AccessType.PACKAGE_LOCAL)) || - (overrideAttrList != null && attributeList.getAccessType() != overrideAttrList.getAccessType()) || - overrideAttrList != null && (overrideNs = - overrideAttrList.getNamespace()) != null && !overrideNs.equals(attributeList.getNamespace())) { - final Annotation annotation1 = myHolder.createErrorAnnotation(findElementForAccessModifierError(node, attributeList), - JavaScriptBundle.message( - "javascript.validation.message.function.override.incompatible.access.modifier", - overrideNs != null ? overrideNs : (overrideAttrList != null ? overrideAttrList - .getAccessType() - .toString() : JSAttributeList.AccessType - .PACKAGE_LOCAL.toString()).toLowerCase())); - - // TODO: quickfix - //annotation.registerFix( - // new RemoveASTNodeFix(astNode,"javascript.fix.remove.override.modifier") - //); - } - - final SignatureMatchResult incompatibleSignature = checkCompatibleSignature(node, override); - - if (incompatibleSignature == SignatureMatchResult.PARAMETERS_DIFFERS) { - final JSParameterList nodeParameterList = node.getParameterList(); - final JSParameterList overrideParameterList = override.getParameterList(); - - final Annotation annotation = - myHolder.createErrorAnnotation(nodeParameterList != null ? nodeParameterList : node.getNameIdentifier(), - JavaScriptBundle.message( - "javascript.validation.message.function.override.incompatible.signature", - overrideParameterList != null ? overrideParameterList.getText() : "()")); - - // TODO: quickfix - //annotation.registerFix( - // new RemoveASTNodeFix(astNode,"javascript.fix.remove.override.modifier") - //); - } - else if (incompatibleSignature == SignatureMatchResult.RETURN_TYPE_DIFFERS) { - PsiElement returnTypeExpr = node.getReturnTypeElement(); - PsiElement overrideReturnTypeExpr = override.getReturnTypeElement(); - final Annotation annotation = myHolder.createErrorAnnotation(returnTypeExpr != null ? returnTypeExpr : node.getNameIdentifier(), - JavaScriptBundle.message( - "javascript.validation.message.function.override.incompatible.signature2", - overrideReturnTypeExpr != null ? overrideReturnTypeExpr.getText() : "*")); - - // TODO: quickfix - //annotation.registerFix( - // new RemoveASTNodeFix(astNode,"javascript.fix.remove.override.modifier") - //); - } - } - } - } - } - - enum SignatureMatchResult { - PARAMETERS_DIFFERS, - RETURN_TYPE_DIFFERS, - COMPATIBLE_SIGNATURE - } - - private static SignatureMatchResult checkCompatibleSignature(final JSFunction fun, final JSFunction override) { - JSParameterList nodeParameterList = fun.getParameterList(); - JSParameterList overrideParameterList = override.getParameterList(); - final JSParameter[] parameters = nodeParameterList != null ? nodeParameterList.getParameters() : JSParameter.EMPTY_ARRAY; - final JSParameter[] overrideParameters = - overrideParameterList != null ? overrideParameterList.getParameters() : JSParameter.EMPTY_ARRAY; - - SignatureMatchResult result = - parameters.length != overrideParameters.length ? SignatureMatchResult.PARAMETERS_DIFFERS : SignatureMatchResult - .COMPATIBLE_SIGNATURE; - - if (result == SignatureMatchResult.COMPATIBLE_SIGNATURE) { - for (int i = 0; i < parameters.length; ++i) { - if (!compatibleType(overrideParameters[i].getTypeString(), parameters[i].getTypeString(), overrideParameterList, - nodeParameterList) || overrideParameters[i].hasInitializer() != parameters[i].hasInitializer()) { - result = SignatureMatchResult.PARAMETERS_DIFFERS; - break; - } - } + } } - if (result == SignatureMatchResult.COMPATIBLE_SIGNATURE) { - if (!compatibleType(override.getReturnTypeString(), fun.getReturnTypeString(), override, fun)) { - result = SignatureMatchResult.RETURN_TYPE_DIFFERS; - } - } - return result; - } - - private static boolean compatibleType(String overrideParameterType, - String parameterType, - PsiElement overrideContext, - PsiElement funContext) { - // TODO: This should be more accurate - if (overrideParameterType != null && !overrideParameterType.equals(parameterType)) { - parameterType = JSImportHandlingUtil.resolveTypeName(parameterType, funContext); - overrideParameterType = JSImportHandlingUtil.resolveTypeName(overrideParameterType, overrideContext); - - return overrideParameterType.equals(parameterType); - } - else if (overrideParameterType == null && parameterType != null && !"*".equals(parameterType)) { - return false; + enum SignatureMatchResult { + PARAMETERS_DIFFERS, + RETURN_TYPE_DIFFERS, + COMPATIBLE_SIGNATURE + } + + @RequiredReadAction + private static SignatureMatchResult checkCompatibleSignature(JSFunction fun, JSFunction override) { + JSParameterList nodeParameterList = fun.getParameterList(); + JSParameterList overrideParameterList = override.getParameterList(); + JSParameter[] parameters = nodeParameterList != null ? nodeParameterList.getParameters() : JSParameter.EMPTY_ARRAY; + JSParameter[] overrideParameters = overrideParameterList != null + ? overrideParameterList.getParameters() + : JSParameter.EMPTY_ARRAY; + + SignatureMatchResult result = parameters.length != overrideParameters.length + ? SignatureMatchResult.PARAMETERS_DIFFERS + : SignatureMatchResult.COMPATIBLE_SIGNATURE; + + if (result == SignatureMatchResult.COMPATIBLE_SIGNATURE) { + for (int i = 0; i < parameters.length; ++i) { + if (!compatibleType( + overrideParameters[i].getTypeString(), + parameters[i].getTypeString(), + overrideParameterList, + nodeParameterList + ) || overrideParameters[i].hasInitializer() != parameters[i].hasInitializer()) { + result = SignatureMatchResult.PARAMETERS_DIFFERS; + break; + } + } + } + + if (result == SignatureMatchResult.COMPATIBLE_SIGNATURE + && !compatibleType(override.getReturnTypeString(), fun.getReturnTypeString(), override, fun)) { + result = SignatureMatchResult.RETURN_TYPE_DIFFERS; + } + return result; } - return true; - } - - @Override - public void visitJSReturnStatement(final JSReturnStatement node) { - final PsiElement element = PsiTreeUtil.getParentOfType(node, - JSFunction.class, - XmlTagChild.class, - XmlAttributeValue.class, - JSFile.class, - JavaScriptLambdaExpression.class); - if ((element instanceof JSFile && !(element.getContext() instanceof PsiLanguageInjectionHost)) || (element instanceof XmlTagChild && !(element - .getParent() instanceof XmlAttributeValue))) { - myHolder.createErrorAnnotation(node, JavaScriptBundle.message("javascript.validation.message.return.outside.function.definition")); + private static boolean compatibleType( + String overrideParameterType, + String parameterType, + PsiElement overrideContext, + PsiElement funContext + ) { + // TODO: This should be more accurate + if (overrideParameterType != null && !overrideParameterType.equals(parameterType)) { + parameterType = JSImportHandlingUtil.resolveTypeName(parameterType, funContext); + overrideParameterType = JSImportHandlingUtil.resolveTypeName(overrideParameterType, overrideContext); + + return overrideParameterType.equals(parameterType); + } + else if (overrideParameterType == null && parameterType != null && !"*".equals(parameterType)) { + return false; + } + + return true; } - if (element instanceof JSFunction) { - final @NonNls String typeString = ((JSFunction)element).getReturnTypeString(); - if (typeString != null && !"void".equals(typeString) && node.getExpression() == null) { - myHolder.createErrorAnnotation(node, - JavaScriptBundle.message("javascript.validation.message.return.value.of.type.is.required", - typeString)); - } + @Override + @RequiredReadAction + @SuppressWarnings("unchecked") + public void visitJSReturnStatement(@Nonnull JSReturnStatement node) { + PsiElement element = PsiTreeUtil.getParentOfType( + node, + JSFunction.class, + XmlTagChild.class, + XmlAttributeValue.class, + JSFile.class, + JavaScriptLambdaExpression.class + ); + if ((element instanceof JSFile jsFile && !(jsFile.getContext() instanceof PsiLanguageInjectionHost)) + || (element instanceof XmlTagChild xmlTagChild && !(xmlTagChild.getParent() instanceof XmlAttributeValue))) { + myHolder.newAnnotation(HighlightSeverity.ERROR, JavaScriptLocalize.javascriptValidationMessageReturnOutsideFunctionDefinition()) + .range(node) + .create(); + } + + if (element instanceof JSFunction function) { + String typeString = function.getReturnTypeString(); + if (typeString != null && !"void".equals(typeString) && node.getExpression() == null) { + myHolder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageReturnValueOfTypeIsRequired(typeString) + ) + .range(node) + .create(); + } + } } - } - - @Override - public void visitJSLabeledStatement(final JSLabeledStatement node) { - final String label = node.getLabel(); - if (label != null) { - PsiElement run = node.getParent(); - while (run != null) { - if (run instanceof JSLabeledStatement) { - if (label.equals(((JSLabeledStatement)run).getLabel())) { - myHolder.createErrorAnnotation(node.getLabelIdentifier(), - JavaScriptBundle.message("javascript.validation.message.duplicate.label")); - break; - } - } - - if (run instanceof JSFunction) { - break; - } - run = run.getParent(); - } + + @Override + @RequiredReadAction + public void visitJSLabeledStatement(JSLabeledStatement node) { + String label = node.getLabel(); + if (label != null) { + PsiElement run = node.getParent(); + while (run != null) { + if (run instanceof JSLabeledStatement labeledStatement && label.equals(labeledStatement.getLabel())) { + myHolder.newAnnotation(HighlightSeverity.ERROR, JavaScriptLocalize.javascriptValidationMessageDuplicateLabel()) + .range(node.getNameIdentifier()) + .create(); + break; + } + + if (run instanceof JSFunction) { + break; + } + run = run.getParent(); + } + } } - } - private void checkNamedObjectIsInCorrespondingFile(final JSNamedElement aClass) { - final PsiFile containingFile = aClass.getContainingFile(); + @RequiredReadAction + private void checkNamedObjectIsInCorrespondingFile(JSNamedElement aClass) { + PsiFile containingFile = aClass.getContainingFile(); + + if (containingFile.getContext() != null) { + return; + } + VirtualFile file = containingFile.getVirtualFile(); + + if (file != null && !file.getNameWithoutExtension().equals(aClass.getName())) { + PsiElement node = aClass.getNameIdentifier(); + + if (node != null) { + String name = aClass.getName(); + String nameWithExtension = name + "." + file.getExtension(); + LocalizeValue message = aClass instanceof JSClass + ? JavaScriptLocalize.javascriptValidationMessageClassShouldBeInFile(name, nameWithExtension) + : aClass instanceof JSNamespaceDeclaration + ? JavaScriptLocalize.javascriptValidationMessageNamespaceShouldBeInFile(name, nameWithExtension) + : aClass instanceof JSVariable + ? JavaScriptLocalize.javascriptValidationMessageVariableShouldBeInFile(name, nameWithExtension) + : JavaScriptLocalize.javascriptValidationMessageFunctionShouldBeInFile(name, nameWithExtension); + myHolder.newAnnotation(HighlightSeverity.ERROR, message) + .range(node) + .withFix(new RenameFileFix(nameWithExtension)) + .create(); + /*annotation.registerFix(new RenamePublicClassFix(aClass) { + String text; + String familyName; + + { + String term = getTerm(message); + text = super.getText().replace("class", StringUtil.decapitalize(term)); + familyName = super.getFamilyName().replace("Class", term); + } + + @NotNull + @Override + public String getText() { + return text; + } + + @NotNull + @Override + public String getFamilyName() { + return familyName; + } + });*/ + } + } - if (containingFile.getContext() != null) { - return; + checkFileUnderSourceRoot(aClass, myHolder); } - final VirtualFile file = containingFile.getVirtualFile(); - - if (file != null && !file.getNameWithoutExtension().equals(aClass.getName())) { - final PsiElement node = aClass.getNameIdentifier(); - - if (node != null) { - final String name = aClass.getName(); - String nameWithExtension = name + "." + file.getExtension(); - final String message = - JavaScriptBundle.message(aClass instanceof JSClass ? "javascript.validation.message.class.should.be.in.file" : aClass instanceof - JSNamespaceDeclaration ? "javascript.validation.message.namespace.should.be.in.file" : aClass instanceof JSVariable ? "javascript.validation" + - ".message.variable.should.be.in.file" : "javascript.validation.message.function.should.be.in.file", name, nameWithExtension); - final Annotation annotation = myHolder.createErrorAnnotation(node, message); - - annotation.registerFix(new RenameFileFix(nameWithExtension)); - /*annotation.registerFix(new RenamePublicClassFix(aClass) { - final String text; - final String familyName; - - { - String term = getTerm(message); - text = super.getText().replace("class", StringUtil.decapitalize(term)); - familyName = super.getFamilyName().replace("Class", term); - } - @NotNull - @Override - public String getText() { - return text; - } - - @NotNull - @Override - public String getFamilyName() { - return familyName; - } - }); */ - } + + private String getTerm(String message) { + String term = message.substring(0, message.indexOf(' ')); + return term; } - checkFileUnderSourceRoot(aClass, new SimpleErrorReportingClient()); - } + @RequiredReadAction + public static void checkFileUnderSourceRoot(JSNamedElement aClass, AnnotationHolder holder) { + PsiElement nameIdentifier = aClass.getNameIdentifier(); + if (nameIdentifier == null) { + nameIdentifier = aClass.getFirstChild(); + } - private String getTerm(String message) { - String term = message.substring(0, message.indexOf(' ')); - return term; - } + PsiFile containingFile = aClass.getContainingFile(); + VirtualFile file = containingFile.getVirtualFile(); + if (file == null) { + return; + } + VirtualFile rootForFile = ProjectRootManager.getInstance(containingFile.getProject()).getFileIndex().getSourceRootForFile(file); - public static void checkFileUnderSourceRoot(final JSNamedElement aClass, ErrorReportingClient client) { - PsiElement nameIdentifier = aClass.getNameIdentifier(); - if (nameIdentifier == null) { - nameIdentifier = aClass.getFirstChild(); + if (rootForFile == null) { + holder.newAnnotation(HighlightSeverity.WARNING, JavaScriptLocalize.javascriptValidationMessageFileShouldBeUnderSourceRoot()) + .range(nameIdentifier.getNode()) + .create(); + } } - final PsiFile containingFile = aClass.getContainingFile(); - final VirtualFile file = containingFile.getVirtualFile(); - if (file == null) { - return; - } - final VirtualFile rootForFile = ProjectRootManager.getInstance(containingFile.getProject()).getFileIndex().getSourceRootForFile(file); + @RequiredReadAction + private void checkPackageStatement(JSPackageStatement packageStatement) { + String s = packageStatement.getQualifiedName(); + + PsiFile containingFile = packageStatement.getContainingFile(); + String expected = JSResolveUtil.getExpectedPackageNameFromFile( + containingFile.getVirtualFile(), + containingFile.getProject(), + true + ); + + if (expected != null && ((s == null && expected.length() != 0) || (s != null && !expected.equals(s)))) { + PsiElement nameIdentifier = packageStatement.getNameIdentifier(); + myHolder.newAnnotation(HighlightSeverity.ERROR, JavaScriptLocalize.javascriptValidationMessageIncorrectPackageName(s, expected)) + .range(nameIdentifier != null ? nameIdentifier : packageStatement.getFirstChild()) + .withFix(new SyntheticIntentionAction() { + @Nonnull + @Override + public LocalizeValue getText() { + return JavaScriptLocalize.javascriptFixPackageName(expected); + } + + @Override + public boolean isAvailable(@Nonnull Project project, Editor editor, PsiFile file) { + return packageStatement.isValid(); + } + + @Override + @RequiredWriteAction + public void invoke(@Nonnull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + JSPackageStatementImpl.doChangeName(project, packageStatement, expected); + } + + @Override + public boolean startInWriteAction() { + return true; + } + }) + .create(); + } + + Set elements = new HashSet<>(); + + for (JSSourceElement statement : packageStatement.getStatements()) { + if (statement instanceof JSNamedElement namedElement && !(statement instanceof JSImportStatement)) { + elements.add(namedElement); + } + } + + if (elements.size() > 1) { + for (JSNamedElement el : elements) { + PsiElement nameIdentifier = el.getNameIdentifier(); + myHolder.newAnnotation( + HighlightSeverity.ERROR, + JavaScriptLocalize.javascriptValidationMessageMoreThanOneExternallyVisibleSymbol() + ) + .range(nameIdentifier != null ? nameIdentifier : el.getFirstChild()) + .withFix(new RemoveASTNodeFix(el.getNode(), JavaScriptLocalize.javascriptFixRemoveExternallyVisibleSymbol())) + .create(); + } + } - if (rootForFile == null) { - client.reportError(nameIdentifier.getNode(), - JavaScriptBundle.message("javascript.validation.message.file.should.be.under.source.root"), - ErrorReportingClient.ProblemKind.WARNING, - null); + checkFileUnderSourceRoot(packageStatement, myHolder); } - } - private void checkPackageStatement(final JSPackageStatement packageStatement) { - final String s = packageStatement.getQualifiedName(); + public static class RemoveASTNodeFix implements SyntheticIntentionAction, LocalQuickFix { + private ASTNode[] myAstNodes; + private LocalizeValue myProp; - final PsiFile containingFile = packageStatement.getContainingFile(); - final String expected = - JSResolveUtil.getExpectedPackageNameFromFile(containingFile.getVirtualFile(), containingFile.getProject(), true); + public RemoveASTNodeFix(ASTNode astNode, LocalizeValue prop) { + this(prop, astNode); + } - if (expected != null && ((s == null && expected.length() != 0) || (s != null && !expected.equals(s)))) { - final PsiElement nameIdentifier = packageStatement.getNameIdentifier(); - final Annotation annotation = - myHolder.createErrorAnnotation(nameIdentifier != null ? nameIdentifier : packageStatement.getFirstChild() - , JavaScriptBundle.message("javascript.validation.message.incorrect.package.name", s, expected)); - annotation.registerFix(new SyntheticIntentionAction() { - @Override - @Nonnull - public String getText() { - return JavaScriptBundle.message("javascript.fix.package.name", expected); + public RemoveASTNodeFix(LocalizeValue prop, ASTNode... astNodes) { + myProp = prop; + myAstNodes = astNodes; } @Override - public boolean isAvailable(@Nonnull final Project project, final Editor editor, final PsiFile file) { - return packageStatement.isValid(); + @Nonnull + public LocalizeValue getText() { + return myProp; } @Override - public void invoke(@Nonnull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException { - JSPackageStatementImpl.doChangeName(project, packageStatement, expected); + @Nonnull + public LocalizeValue getName() { + return getText(); } @Override - public boolean startInWriteAction() { - return true; + @RequiredUIAccess + public void applyFix(@Nonnull Project project, @Nonnull ProblemDescriptor descriptor) { + invoke(project, null, descriptor.getPsiElement().getContainingFile()); } - }); - } - - final Set elements = new HashSet(); - for (JSSourceElement statement : packageStatement.getStatements()) { - if (statement instanceof JSNamedElement && !(statement instanceof JSImportStatement)) { - elements.add((JSNamedElement)statement); - } - } - - if (elements.size() > 1) { - for (JSNamedElement el : elements) { - final PsiElement nameIdentifier = el.getNameIdentifier(); - myHolder.createErrorAnnotation(nameIdentifier != null ? nameIdentifier : el.getFirstChild(), - JavaScriptBundle.message("javascript.validation.message.more.than.one.externally.visible.symbol")) - .registerFix(new RemoveASTNodeFix(el.getNode(), - "javascript.fix.remove.externally.visible.symbol")); - } - } + @Override + public boolean isAvailable(@Nonnull Project project, Editor editor, PsiFile file) { + for (ASTNode astNode : myAstNodes) { + if (!astNode.getPsi().isValid()) { + return false; + } + } - checkFileUnderSourceRoot(packageStatement, new SimpleErrorReportingClient()); - } + return true; + } - public static class RemoveASTNodeFix implements IntentionAction, LocalQuickFix { - private final ASTNode[] myAstNodes; - private final String myPropKey; + @Override + @RequiredUIAccess + public void invoke(@Nonnull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + if (!FileModificationService.getInstance().prepareFileForWrite(file)) { + return; + } + for (ASTNode astNode : myAstNodes) { + if (astNode.getPsi().isValid()) { + astNode.getPsi().delete(); + } + } + } - public RemoveASTNodeFix(final ASTNode astNode, @PropertyKey(resourceBundle = JavaScriptBundle.BUNDLE) String propKey) { - this(propKey, astNode); + @Override + public boolean startInWriteAction() { + return true; + } } - public RemoveASTNodeFix(@PropertyKey(resourceBundle = JavaScriptBundle.BUNDLE) String propKey, final ASTNode... astNodes) { - myPropKey = propKey; - myAstNodes = astNodes; - } + private static class AddOverrideIntentionAction implements SyntheticIntentionAction { + private final JSFunction myNode; - @Override - @Nonnull - public String getText() { - return JavaScriptBundle.message(myPropKey); - } + public AddOverrideIntentionAction(JSFunction node) { + myNode = node; + } - @Override - @Nonnull - public String getName() { - return getText(); - } + @Override + @Nonnull + public LocalizeValue getText() { + return JavaScriptLocalize.javascriptFixAddOverrideModifier(); + } - @Override - @Nonnull - public String getFamilyName() { - return getText(); - } + @Override + public boolean isAvailable(@Nonnull Project project, Editor editor, PsiFile file) { + return myNode.isValid(); + } - @Override - public void applyFix(@Nonnull Project project, @Nonnull ProblemDescriptor descriptor) { - invoke(project, null, descriptor.getPsiElement().getContainingFile()); - } + @Override + @RequiredUIAccess + public void invoke(@Nonnull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + if (!FileModificationService.getInstance().prepareFileForWrite(file)) { + return; + } + ASTNode fromText = JSChangeUtil.createJSTreeFromText(project, "override class A {}"); + JSAttributeList jsAttributeList = myNode.getAttributeList(); + JSAttributeList createdAttrList = ((JSClass)fromText.getPsi()).getAttributeList(); - @Override - public boolean isAvailable(@Nonnull final Project project, final Editor editor, final PsiFile file) { - for (ASTNode astNode : myAstNodes) { - if (!astNode.getPsi().isValid()) { - return false; + if (jsAttributeList != null) { + jsAttributeList.add(createdAttrList.getFirstChild()); + } + else { + myNode.addBefore(createdAttrList, myNode.getFirstChild()); + } } - } - - return true; - } - @Override - public void invoke(@Nonnull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException { - if (!FileModificationService.getInstance().prepareFileForWrite(file)) { - return; - } - for (ASTNode astNode : myAstNodes) { - if (astNode.getPsi().isValid()) { - astNode.getPsi().delete(); - } - } + @Override + public boolean startInWriteAction() { + return true; + } } - @Override - public boolean startInWriteAction() { - return true; - } - } + private static class AddSuperInvokationFix implements SyntheticIntentionAction { + private final JSReferenceExpression node; + private final JSFunction superConstructor; - private static class AddOverrideIntentionAction implements SyntheticIntentionAction { - private final JSFunction myNode; + public AddSuperInvokationFix(JSReferenceExpression node, JSFunction superConstructor) { + this.node = node; + this.superConstructor = superConstructor; + } - public AddOverrideIntentionAction(final JSFunction node) { - myNode = node; - } + @Override + @Nonnull + public LocalizeValue getText() { + return JavaScriptLocalize.javascriptFixCreateInvokeSuper(); + } - @Override - @Nonnull - public String getText() { - return JavaScriptBundle.message("javascript.fix.add.override.modifier"); - } + @Override + public boolean isAvailable(@Nonnull Project project, Editor editor, PsiFile file) { + return superConstructor.isValid() && node.isValid(); + } - @Override - public boolean isAvailable(@Nonnull final Project project, final Editor editor, final PsiFile file) { - return myNode.isValid(); - } + @Override + @RequiredUIAccess + public void invoke(@Nonnull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + if (!FileModificationService.getInstance().prepareFileForWrite(file)) { + return; + } + Template t = TemplateManager.getInstance(project).createTemplate("", ""); + t.setToReformat(true); - @Override - public void invoke(@Nonnull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException { - if (!FileModificationService.getInstance().prepareFileForWrite(file)) { - return; - } - final ASTNode fromText = JSChangeUtil.createJSTreeFromText(project, "override class A {}"); - final JSAttributeList jsAttributeList = myNode.getAttributeList(); - final JSAttributeList createdAttrList = ((JSClass)fromText.getPsi()).getAttributeList(); - - if (jsAttributeList != null) { - jsAttributeList.add(createdAttrList.getFirstChild()); - } - else { - myNode.addBefore(createdAttrList, myNode.getFirstChild()); - } - } + t.addTextSegment("super("); + boolean first = true; + for (JSParameter p : superConstructor.getParameterList().getParameters()) { + if (p.isRest()) { + break; + } + if (!first) { + t.addTextSegment(", "); + } + first = false; + MacroCallNode node = new MacroCallNode(new CompleteMacro()); + t.addVariable(p.getName(), node, node, true); + } + t.addTextSegment(")"); + String s = JSChangeUtil.getSemicolon(project); + if (s.length() > 0) { + t.addTextSegment(s); + } - @Override - public boolean startInWriteAction() { - return true; - } - } + JSFunction fun = PsiTreeUtil.getParentOfType(node, JSFunction.class); + JSSourceElement[] body = fun != null ? fun.getBody() : JSSourceElement.EMPTY_ARRAY; - private class SimpleErrorReportingClient implements ErrorReportingClient { - @Override - public void reportError(final ASTNode nameIdentifier, final String s, ProblemKind kind, final IntentionAction implementMethodsFix) { - final Annotation annotation = kind == ProblemKind.ERROR ? myHolder.createErrorAnnotation(nameIdentifier, - s) : myHolder.createWarningAnnotation( - nameIdentifier, - s); - if (implementMethodsFix != null) { - annotation.registerFix(implementMethodsFix); - } - } + if (body.length > 0 && body[0] instanceof JSBlockStatement blockStatement) { + PsiElement firstChild = blockStatement.getFirstChild(); + editor.getCaretModel().moveToOffset(firstChild.getTextRange().getEndOffset()); + TemplateManager.getInstance(project).startTemplate(editor, t); + } + } - @Override - public void reportError(PsiElement nameIdentifier, String s, ProblemKind kind, IntentionAction implementMethodsFix) { - final Annotation annotation = kind == ProblemKind.ERROR ? myHolder.createErrorAnnotation(nameIdentifier, - s) : myHolder.createWarningAnnotation( - nameIdentifier, - s); - if (implementMethodsFix != null) { - annotation.registerFix(implementMethodsFix); - } + @Override + public boolean startInWriteAction() { + return false; + } } - } - private static class AddSuperInvokationFix implements SyntheticIntentionAction { - private final JSReferenceExpression node; - private final JSFunction superConstructor; + private static class AddConstructorAndSuperInvokationFix implements SyntheticIntentionAction { + private final JSReferenceExpression node; + private final JSFunction superConstructor; - public AddSuperInvokationFix(JSReferenceExpression node, JSFunction superConstructor) { - this.node = node; - this.superConstructor = superConstructor; - } - - @Override - @Nonnull - public String getText() { - return JavaScriptBundle.message("javascript.fix.create.invoke.super"); - } + AddConstructorAndSuperInvokationFix(JSReferenceExpression _node, JSFunction _superCall) { + node = _node; + superConstructor = _superCall; + } - @Override - public boolean isAvailable(@Nonnull Project project, Editor editor, PsiFile file) { - return superConstructor.isValid() && node.isValid(); - } + @Override + @Nonnull + public LocalizeValue getText() { + return JavaScriptLocalize.javascriptFixCreateConstructorInvokeSuper(); + } - @Override - public void invoke(@Nonnull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - if (!FileModificationService.getInstance().prepareFileForWrite(file)) { - return; - } - Template t = TemplateManager.getInstance(project).createTemplate("", ""); - t.setToReformat(true); - - t.addTextSegment("super("); - boolean first = true; - for (JSParameter p : superConstructor.getParameterList().getParameters()) { - if (p.isRest()) { - break; - } - if (!first) { - t.addTextSegment(", "); - } - first = false; - MacroCallNode node = new MacroCallNode(new CompleteMacro()); - t.addVariable(p.getName(), node, node, true); - } - t.addTextSegment(")"); - String s = JSChangeUtil.getSemicolon(project); - if (s.length() > 0) { - t.addTextSegment(s); - } - - JSFunction fun = PsiTreeUtil.getParentOfType(node, JSFunction.class); - JSSourceElement[] body = fun != null ? fun.getBody() : JSSourceElement.EMPTY_ARRAY; - - if (body.length > 0 && body[0] instanceof JSBlockStatement) { - PsiElement firstChild = body[0].getFirstChild(); - editor.getCaretModel().moveToOffset(firstChild.getTextRange().getEndOffset()); - TemplateManager.getInstance(project).startTemplate(editor, t); - } - } + @Override + public boolean isAvailable(@Nonnull Project project, Editor editor, PsiFile file) { + return node.isValid() && superConstructor.isValid(); + } - @Override - public boolean startInWriteAction() { - return false; - } - } + @Override + @RequiredUIAccess + public void invoke(@Nonnull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + if (!FileModificationService.getInstance().prepareFileForWrite(file)) { + return; + } + JSClass jsClass = PsiTreeUtil.getParentOfType(node, JSClass.class); + if (jsClass == null) { + return; + } + JSAttributeList attributeList = jsClass.getAttributeList(); + StringBuilder fun = new StringBuilder(); - private static class AddConstructorAndSuperInvokationFix implements SyntheticIntentionAction { - private final JSReferenceExpression node; - private final JSFunction superConstructor; + if (attributeList != null && attributeList.getAccessType() == JSAttributeList.AccessType.PUBLIC) { + fun.append("public "); + } - AddConstructorAndSuperInvokationFix(JSReferenceExpression _node, JSFunction _superCall) { - node = _node; - superConstructor = _superCall; - } + fun.append("function "); - @Override - @Nonnull - public String getText() { - return JavaScriptBundle.message("javascript.fix.create.constructor.invoke.super"); - } + JSParameterList parameterList = superConstructor.getParameterList(); + fun.append(jsClass.getName()).append(parameterList.getText()).append("{\n"); + fun.append("super("); + int i = 0; - @Override - public boolean isAvailable(@Nonnull Project project, Editor editor, PsiFile file) { - return node.isValid() && superConstructor.isValid(); - } + for (JSParameter p : parameterList.getParameters()) { + if (i != 0) { + fun.append(","); + } + ++i; + fun.append(p.getName()); + } + fun.append(")").append(JSChangeUtil.getSemicolon(project)); + fun.append("\n}"); - @Override - public void invoke(@Nonnull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - if (!FileModificationService.getInstance().prepareFileForWrite(file)) { - return; - } - final JSClass jsClass = PsiTreeUtil.getParentOfType(node, JSClass.class); - if (jsClass == null) { - return; - } - final JSAttributeList attributeList = jsClass.getAttributeList(); - String fun = ""; - - if (attributeList != null && attributeList.getAccessType() == JSAttributeList.AccessType.PUBLIC) { - fun += "public "; - } - - fun += "function "; - - final JSParameterList parameterList = superConstructor.getParameterList(); - fun += jsClass.getName() + parameterList.getText() + "{\n"; - fun += "super("; - int i = 0; - - for (JSParameter p : parameterList.getParameters()) { - if (i != 0) { - fun += ","; - } - ++i; - fun += p.getName(); - } - fun += ")" + JSChangeUtil.getSemicolon(project); - fun += "\n}"; - - jsClass.add(JSChangeUtil.createJSTreeFromText(project, fun).getPsi()); - } + jsClass.add(JSChangeUtil.createJSTreeFromText(project, fun.toString()).getPsi()); + } - @Override - public boolean startInWriteAction() { - return true; + @Override + public boolean startInWriteAction() { + return true; + } } - } } diff --git a/plugin/src/main/java/com/intellij/lang/javascript/impl/validation/JSAnnotatorFactory.java b/plugin/src/main/java/com/intellij/lang/javascript/impl/validation/JSAnnotatorFactory.java index d371e790..656c9df2 100644 --- a/plugin/src/main/java/com/intellij/lang/javascript/impl/validation/JSAnnotatorFactory.java +++ b/plugin/src/main/java/com/intellij/lang/javascript/impl/validation/JSAnnotatorFactory.java @@ -6,27 +6,24 @@ import consulo.language.editor.annotation.Annotator; import consulo.language.editor.annotation.AnnotatorFactory; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL - * @since 29-Aug-22 + * @since 2022-08-29 */ @ExtensionImpl -public class JSAnnotatorFactory implements AnnotatorFactory -{ - @Nullable - @Override - public Annotator createAnnotator() - { - return new JSAnnotatingVisitor(); - } +public class JSAnnotatorFactory implements AnnotatorFactory { + @Nullable + @Override + public Annotator createAnnotator() { + return new JSAnnotatingVisitor(); + } - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } } diff --git a/plugin/src/main/java/consulo/javascript/impl/JavaScriptIconDescriptorUpdater.java b/plugin/src/main/java/consulo/javascript/impl/JavaScriptIconDescriptorUpdater.java index 67506cea..98f6e6e6 100644 --- a/plugin/src/main/java/consulo/javascript/impl/JavaScriptIconDescriptorUpdater.java +++ b/plugin/src/main/java/consulo/javascript/impl/JavaScriptIconDescriptorUpdater.java @@ -29,183 +29,138 @@ import consulo.platform.base.icon.PlatformIconGroup; import consulo.ui.image.Image; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL * @since 05.12.2015 */ @ExtensionImpl -public class JavaScriptIconDescriptorUpdater implements IconDescriptorUpdater -{ - @RequiredReadAction - @Override - public void updateIcon(@Nonnull IconDescriptor iconDescriptor, @Nonnull PsiElement element, int flags) - { - if(element instanceof JSProperty) - { - if(element instanceof JSFunction && ((JSFunction) element).isGetProperty()) - { - iconDescriptor.setMainIcon(PlatformIconGroup.nodesPropertyread()); - } - else if(element instanceof JSFunction && ((JSFunction) element).isSetProperty()) - { - iconDescriptor.setMainIcon(PlatformIconGroup.nodesPropertywrite()); - } - else - { - iconDescriptor.setMainIcon(AllIcons.Nodes.Property); - } +public class JavaScriptIconDescriptorUpdater implements IconDescriptorUpdater { + @RequiredReadAction + @Override + public void updateIcon(@Nonnull IconDescriptor iconDescriptor, @Nonnull PsiElement element, int flags) { + if (element instanceof JSProperty) { + if (element instanceof JSFunction && ((JSFunction)element).isGetProperty()) { + iconDescriptor.setMainIcon(PlatformIconGroup.nodesPropertyread()); + } + else if (element instanceof JSFunction && ((JSFunction)element).isSetProperty()) { + iconDescriptor.setMainIcon(PlatformIconGroup.nodesPropertywrite()); + } + else { + iconDescriptor.setMainIcon(AllIcons.Nodes.Property); + } - JSExpression value = ((JSProperty) element).getValue(); - if(value instanceof JSFunctionExpression) - { - iconDescriptor.setMainIcon(AllIcons.Nodes.Function); - } + JSExpression value = ((JSProperty)element).getValue(); + if (value instanceof JSFunctionExpression) { + iconDescriptor.setMainIcon(AllIcons.Nodes.Function); + } - if(BitUtil.isSet(flags, Iconable.ICON_FLAG_VISIBILITY)) - { - iconDescriptor.setRightIcon(AllIcons.Nodes.C_public); - } - } - else if(element instanceof JSClass) - { - final JSAttributeList attributeList = ((JSClass) element).getAttributeList(); + if (BitUtil.isSet(flags, Iconable.ICON_FLAG_VISIBILITY)) { + iconDescriptor.setRightIcon(AllIcons.Nodes.C_public); + } + } + else if (element instanceof JSClass) { + JSAttributeList attributeList = ((JSClass)element).getAttributeList(); - iconDescriptor.setMainIcon(((JSClass) element).isInterface() ? AllIcons.Nodes.Interface : AllIcons.Nodes.Class); - addStaticAndFinalIcons(iconDescriptor, attributeList); + iconDescriptor.setMainIcon(((JSClass)element).isInterface() ? AllIcons.Nodes.Interface : AllIcons.Nodes.Class); + addStaticAndFinalIcons(iconDescriptor, attributeList); - if(BitUtil.isSet(flags, Iconable.ICON_FLAG_VISIBILITY)) - { - final JSAttributeList.AccessType accessType = attributeList != null ? attributeList.getAccessType() : JSAttributeList.AccessType.PACKAGE_LOCAL; - iconDescriptor.setRightIcon(getAccessIcon(accessType)); - } - } - else if(element instanceof JSParameter) - { - iconDescriptor.setMainIcon(AllIcons.Nodes.Parameter); - if(BitUtil.isSet(flags, Iconable.ICON_FLAG_VISIBILITY)) - { - iconDescriptor.setRightIcon(AllIcons.Nodes.C_plocal); - } - } - else if(element instanceof JSVariable) - { - iconDescriptor.setMainIcon(AllIcons.Nodes.Variable); + if (BitUtil.isSet(flags, Iconable.ICON_FLAG_VISIBILITY)) { + JSAttributeList.AccessType accessType = + attributeList != null ? attributeList.getAccessType() : JSAttributeList.AccessType.PACKAGE_LOCAL; + iconDescriptor.setRightIcon(getAccessIcon(accessType)); + } + } + else if (element instanceof JSParameter) { + iconDescriptor.setMainIcon(AllIcons.Nodes.Parameter); + if (BitUtil.isSet(flags, Iconable.ICON_FLAG_VISIBILITY)) { + iconDescriptor.setRightIcon(AllIcons.Nodes.C_plocal); + } + } + else if (element instanceof JSVariable) { + iconDescriptor.setMainIcon(AllIcons.Nodes.Variable); - final PsiElement grandParent = JSResolveUtil.findParent(element); + PsiElement grandParent = JSResolveUtil.findParent(element); - if(grandParent instanceof JSClass) - { - final JSAttributeList attributeList = ((JSVariable) element).getAttributeList(); - if(attributeList != null) - { - addStaticAndFinalIcons(iconDescriptor, attributeList); + if (grandParent instanceof JSClass) { + JSAttributeList attributeList = ((JSVariable)element).getAttributeList(); + if (attributeList != null) { + addStaticAndFinalIcons(iconDescriptor, attributeList); - if(BitUtil.isSet(flags, Iconable.ICON_FLAG_VISIBILITY)) - { - iconDescriptor.setRightIcon(getAccessIcon(attributeList.getAccessType())); - } - } - else - { - if(BitUtil.isSet(flags, Iconable.ICON_FLAG_VISIBILITY)) - { - iconDescriptor.setRightIcon(getAccessIcon(JSAttributeList.AccessType.PUBLIC)); - } - } - } - else if(grandParent instanceof JSBlockStatement || grandParent instanceof JSLoopStatement) - { - if(BitUtil.isSet(flags, Iconable.ICON_FLAG_VISIBILITY)) - { - iconDescriptor.setRightIcon(AllIcons.Nodes.C_private); - } - } - else - { - if(BitUtil.isSet(flags, Iconable.ICON_FLAG_VISIBILITY)) - { - iconDescriptor.setRightIcon(AllIcons.Nodes.C_public); - } - } - } - else if(element instanceof JSNamespaceDeclaration) - { - iconDescriptor.setMainIcon(AllIcons.Nodes.Package); - } - else if(element instanceof JSFunction) - { - iconDescriptor.setMainIcon(AllIcons.Nodes.Function); + if (BitUtil.isSet(flags, Iconable.ICON_FLAG_VISIBILITY)) { + iconDescriptor.setRightIcon(getAccessIcon(attributeList.getAccessType())); + } + } + else if (BitUtil.isSet(flags, Iconable.ICON_FLAG_VISIBILITY)) { + iconDescriptor.setRightIcon(getAccessIcon(JSAttributeList.AccessType.PUBLIC)); + } + } + else if (grandParent instanceof JSBlockStatement || grandParent instanceof JSLoopStatement) { + if (BitUtil.isSet(flags, Iconable.ICON_FLAG_VISIBILITY)) { + iconDescriptor.setRightIcon(AllIcons.Nodes.C_private); + } + } + else if (BitUtil.isSet(flags, Iconable.ICON_FLAG_VISIBILITY)) { + iconDescriptor.setRightIcon(AllIcons.Nodes.C_public); + } + } + else if (element instanceof JSNamespaceDeclaration) { + iconDescriptor.setMainIcon(AllIcons.Nodes.Package); + } + else if (element instanceof JSFunction) { + iconDescriptor.setMainIcon(AllIcons.Nodes.Function); - final PsiElement parent = JSResolveUtil.findParent(element); - if(parent instanceof JSBlockStatement) - { - if(BitUtil.isSet(flags, Iconable.ICON_FLAG_VISIBILITY)) - { - iconDescriptor.setRightIcon(AllIcons.Nodes.C_private); - } - } - else if(parent instanceof JSClass) - { - final JSAttributeList attributeList = ((JSFunction) element).getAttributeList(); - if(attributeList != null) - { - addStaticAndFinalIcons(iconDescriptor, attributeList); - if(BitUtil.isSet(flags, Iconable.ICON_FLAG_VISIBILITY)) - { - iconDescriptor.setRightIcon(getAccessIcon(attributeList.getAccessType())); - } - } - else - { - if(BitUtil.isSet(flags, Iconable.ICON_FLAG_VISIBILITY)) - { - iconDescriptor.setRightIcon(getAccessIcon(JSAttributeList.AccessType.PUBLIC)); - } - } - } - else - { - if(BitUtil.isSet(flags, Iconable.ICON_FLAG_VISIBILITY)) - { - iconDescriptor.setRightIcon(getAccessIcon(JSAttributeList.AccessType.PUBLIC)); - } - } - } - } + PsiElement parent = JSResolveUtil.findParent(element); + if (parent instanceof JSBlockStatement) { + if (BitUtil.isSet(flags, Iconable.ICON_FLAG_VISIBILITY)) { + iconDescriptor.setRightIcon(AllIcons.Nodes.C_private); + } + } + else if (parent instanceof JSClass) { + JSAttributeList attributeList = ((JSFunction)element).getAttributeList(); + if (attributeList != null) { + addStaticAndFinalIcons(iconDescriptor, attributeList); + if (BitUtil.isSet(flags, Iconable.ICON_FLAG_VISIBILITY)) { + iconDescriptor.setRightIcon(getAccessIcon(attributeList.getAccessType())); + } + } + else if (BitUtil.isSet(flags, Iconable.ICON_FLAG_VISIBILITY)) { + iconDescriptor.setRightIcon(getAccessIcon(JSAttributeList.AccessType.PUBLIC)); + } + } + else if (BitUtil.isSet(flags, Iconable.ICON_FLAG_VISIBILITY)) { + iconDescriptor.setRightIcon(getAccessIcon(JSAttributeList.AccessType.PUBLIC)); + } + } + } - @Nullable - public Image getAccessIcon(JSAttributeList.AccessType accessType) - { - switch(accessType) - { - case PUBLIC: - return AllIcons.Nodes.C_public; - case PRIVATE: - return AllIcons.Nodes.C_private; - case PROTECTED: - return AllIcons.Nodes.C_protected; - case PACKAGE_LOCAL: - return AllIcons.Nodes.C_plocal; - } - return null; - } + @Nullable + public Image getAccessIcon(JSAttributeList.AccessType accessType) { + switch (accessType) { + case PUBLIC: + return AllIcons.Nodes.C_public; + case PRIVATE: + return AllIcons.Nodes.C_private; + case PROTECTED: + return AllIcons.Nodes.C_protected; + case PACKAGE_LOCAL: + return AllIcons.Nodes.C_plocal; + } + return null; + } - private static void addStaticAndFinalIcons(IconDescriptor iconDescriptor, JSAttributeList attrList) - { - if(attrList == null) - { - return; - } - if(attrList.hasModifier(JSAttributeList.ModifierType.STATIC) || attrList.hasModifier(JSAttributeList.ModifierType.DYNAMIC)) // dynamic? - { - iconDescriptor.addLayerIcon(AllIcons.Nodes.StaticMark); - } - if(attrList.hasModifier(JSAttributeList.ModifierType.FINAL)) - { - iconDescriptor.addLayerIcon(AllIcons.Nodes.FinalMark); - } - } + private static void addStaticAndFinalIcons(IconDescriptor iconDescriptor, JSAttributeList attrList) { + if (attrList == null) { + return; + } + if (attrList.hasModifier(JSAttributeList.ModifierType.STATIC) || attrList.hasModifier(JSAttributeList.ModifierType.DYNAMIC)) // dynamic? + { + iconDescriptor.addLayerIcon(AllIcons.Nodes.StaticMark); + } + if (attrList.hasModifier(JSAttributeList.ModifierType.FINAL)) { + iconDescriptor.addLayerIcon(AllIcons.Nodes.FinalMark); + } + } } diff --git a/plugin/src/main/java/consulo/javascript/impl/copyright/UpdateJavaScriptFileCopyright.java b/plugin/src/main/java/consulo/javascript/impl/copyright/UpdateJavaScriptFileCopyright.java index 164ae2b7..176d4aa1 100644 --- a/plugin/src/main/java/consulo/javascript/impl/copyright/UpdateJavaScriptFileCopyright.java +++ b/plugin/src/main/java/consulo/javascript/impl/copyright/UpdateJavaScriptFileCopyright.java @@ -23,49 +23,38 @@ import consulo.language.psi.PsiElement; import consulo.language.psi.PsiFile; import consulo.language.psi.PsiWhiteSpace; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; +public class UpdateJavaScriptFileCopyright extends UpdatePsiFileCopyright { + public UpdateJavaScriptFileCopyright(@Nonnull PsiFile psiFile, @Nonnull CopyrightProfile copyrightProfile) { + super(psiFile, copyrightProfile); + } -public class UpdateJavaScriptFileCopyright extends UpdatePsiFileCopyright -{ - public UpdateJavaScriptFileCopyright(@Nonnull PsiFile psiFile, @Nonnull CopyrightProfile copyrightProfile) - { - super(psiFile, copyrightProfile); - } + protected void scanFile() { + PsiElement first = getFile().getFirstChild(); + if (first != null) { + PsiElement child = first.getFirstChild(); + if (child instanceof PsiComment) { + first = child; + } + } + PsiElement last = first; + PsiElement next = first; + while (next != null) { + if (next instanceof PsiComment || next instanceof PsiWhiteSpace) { + next = getNextSibling(next); + } + else { + break; + } + last = next; + } - protected void scanFile() - { - PsiElement first = getFile().getFirstChild(); - if(first != null) - { - final PsiElement child = first.getFirstChild(); - if(child instanceof PsiComment) - { - first = child; - } - } - PsiElement last = first; - PsiElement next = first; - while(next != null) - { - if(next instanceof PsiComment || next instanceof PsiWhiteSpace) - { - next = getNextSibling(next); - } - else - { - break; - } - last = next; - } - - if(first != null) - { - checkComments(first, last, true); - } - else - { - checkComments(null, null, true); - } - } + if (first != null) { + checkComments(first, last, true); + } + else { + checkComments(null, null, true); + } + } } \ No newline at end of file diff --git a/plugin/src/main/java/consulo/javascript/impl/copyright/UpdateJavaScriptFileCopyrightProvider.java b/plugin/src/main/java/consulo/javascript/impl/copyright/UpdateJavaScriptFileCopyrightProvider.java index c832e012..585a489c 100644 --- a/plugin/src/main/java/consulo/javascript/impl/copyright/UpdateJavaScriptFileCopyrightProvider.java +++ b/plugin/src/main/java/consulo/javascript/impl/copyright/UpdateJavaScriptFileCopyrightProvider.java @@ -11,40 +11,39 @@ import consulo.project.Project; import consulo.virtualFileSystem.fileType.FileType; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 16.02.2015 */ @ExtensionImpl -public class UpdateJavaScriptFileCopyrightProvider extends UpdateCopyrightsProvider -{ - @Nonnull - @Override - public FileType getFileType() - { - return JavaScriptFileType.INSTANCE; - } +public class UpdateJavaScriptFileCopyrightProvider extends UpdateCopyrightsProvider { + @Nonnull + @Override + public FileType getFileType() { + return JavaScriptFileType.INSTANCE; + } - @Nonnull - @Override - public UpdatePsiFileCopyright createInstance(@Nonnull PsiFile file, @Nonnull CopyrightProfile copyrightProfile) - { - return new UpdateJavaScriptFileCopyright(file, copyrightProfile); - } + @Nonnull + @Override + public UpdatePsiFileCopyright createInstance(@Nonnull PsiFile file, @Nonnull CopyrightProfile copyrightProfile) { + return new UpdateJavaScriptFileCopyright(file, copyrightProfile); + } - @Nonnull - @Override - public CopyrightFileConfig createDefaultOptions() - { - return new CopyrightFileConfig(); - } + @Nonnull + @Override + public CopyrightFileConfig createDefaultOptions() { + return new CopyrightFileConfig(); + } - @Nonnull - @Override - public TemplateCommentPanel createConfigurable(@Nonnull Project project, @Nonnull TemplateCommentPanel parentPane, @Nonnull FileType fileType) - { - return new TemplateCommentPanel(fileType, parentPane, project); - } + @Nonnull + @Override + public TemplateCommentPanel createConfigurable( + @Nonnull Project project, + @Nonnull TemplateCommentPanel parentPane, + @Nonnull FileType fileType + ) { + return new TemplateCommentPanel(fileType, parentPane, project); + } } diff --git a/plugin/src/main/java/consulo/javascript/impl/findUsages/JavaScriptFindUsagesHandlerFactory.java b/plugin/src/main/java/consulo/javascript/impl/findUsages/JavaScriptFindUsagesHandlerFactory.java index edceabde..820a60f0 100644 --- a/plugin/src/main/java/consulo/javascript/impl/findUsages/JavaScriptFindUsagesHandlerFactory.java +++ b/plugin/src/main/java/consulo/javascript/impl/findUsages/JavaScriptFindUsagesHandlerFactory.java @@ -6,29 +6,25 @@ import com.intellij.lang.javascript.psi.JSDefinitionExpression; import consulo.language.psi.PsiElement; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL * @since 2019-12-16 */ @ExtensionImpl -public class JavaScriptFindUsagesHandlerFactory extends FindUsagesHandlerFactory -{ - @Override - public boolean canFindUsages(@Nonnull PsiElement element) - { - return element instanceof JSDefinitionExpression; - } +public class JavaScriptFindUsagesHandlerFactory extends FindUsagesHandlerFactory { + @Override + public boolean canFindUsages(@Nonnull PsiElement element) { + return element instanceof JSDefinitionExpression; + } - @Nullable - @Override - public FindUsagesHandler createFindUsagesHandler(@Nonnull PsiElement element, boolean forHighlightUsages) - { - return new FindUsagesHandler(element) - { + @Nullable + @Override + public FindUsagesHandler createFindUsagesHandler(@Nonnull PsiElement element, boolean forHighlightUsages) { + return new FindUsagesHandler(element) { - }; - } + }; + } } diff --git a/plugin/src/main/java/consulo/javascript/impl/formatter/JavaScriptCodeStyleConfigurable.java b/plugin/src/main/java/consulo/javascript/impl/formatter/JavaScriptCodeStyleConfigurable.java index 108e3799..64d75048 100644 --- a/plugin/src/main/java/consulo/javascript/impl/formatter/JavaScriptCodeStyleConfigurable.java +++ b/plugin/src/main/java/consulo/javascript/impl/formatter/JavaScriptCodeStyleConfigurable.java @@ -1,6 +1,7 @@ package consulo.javascript.impl.formatter; -import javax.annotation.Nonnull; +import consulo.javascript.localize.JavaScriptLocalize; +import jakarta.annotation.Nonnull; import consulo.language.codeStyle.ui.setting.CodeStyleAbstractConfigurable; import consulo.language.codeStyle.CodeStyleSettings; @@ -10,22 +11,18 @@ * @author VISTALL * @since 16.02.2015 */ -public class JavaScriptCodeStyleConfigurable extends CodeStyleAbstractConfigurable -{ - public JavaScriptCodeStyleConfigurable(@Nonnull CodeStyleSettings settings, CodeStyleSettings cloneSettings) - { - super(settings, cloneSettings, "JavaScript"); - } +public class JavaScriptCodeStyleConfigurable extends CodeStyleAbstractConfigurable { + public JavaScriptCodeStyleConfigurable(@Nonnull CodeStyleSettings settings, CodeStyleSettings cloneSettings) { + super(settings, cloneSettings, JavaScriptLocalize.javascriptName()); + } - @Override - protected CodeStyleAbstractPanel createPanel(CodeStyleSettings settings) - { - return new JavaScriptCodeStylePanel(getCurrentSettings(), settings); - } + @Override + protected CodeStyleAbstractPanel createPanel(CodeStyleSettings settings) { + return new JavaScriptCodeStylePanel(getCurrentSettings(), settings); + } - @Override - public String getHelpTopic() - { - return "reference.settingsdialog.codestyle.javascript"; - } + @Override + public String getHelpTopic() { + return "reference.settingsdialog.codestyle.javascript"; + } } \ No newline at end of file diff --git a/plugin/src/main/java/consulo/javascript/impl/formatter/JavaScriptCodeStylePanel.java b/plugin/src/main/java/consulo/javascript/impl/formatter/JavaScriptCodeStylePanel.java index 1ef0d456..85492813 100644 --- a/plugin/src/main/java/consulo/javascript/impl/formatter/JavaScriptCodeStylePanel.java +++ b/plugin/src/main/java/consulo/javascript/impl/formatter/JavaScriptCodeStylePanel.java @@ -9,17 +9,14 @@ * @author VISTALL * @since 16.02.2015 */ -public class JavaScriptCodeStylePanel extends TabbedLanguageCodeStylePanel -{ - public JavaScriptCodeStylePanel(CodeStyleSettings currentSettings, CodeStyleSettings cloneSettings) - { - super(JavaScriptLanguage.INSTANCE, currentSettings, cloneSettings); - } +public class JavaScriptCodeStylePanel extends TabbedLanguageCodeStylePanel { + public JavaScriptCodeStylePanel(CodeStyleSettings currentSettings, CodeStyleSettings cloneSettings) { + super(JavaScriptLanguage.INSTANCE, currentSettings, cloneSettings); + } - @Override - protected void initTabs(CodeStyleSettings settings) - { - super.initTabs(settings); - addTab(new JSCodeStylePanel(settings)); - } + @Override + protected void initTabs(CodeStyleSettings settings) { + super.initTabs(settings); + addTab(new JSCodeStylePanel(settings)); + } } diff --git a/plugin/src/main/java/consulo/javascript/impl/formatter/JavaScriptLanguageCodeStyleSettingsProvider.java b/plugin/src/main/java/consulo/javascript/impl/formatter/JavaScriptLanguageCodeStyleSettingsProvider.java index b404c3b1..3242968a 100644 --- a/plugin/src/main/java/consulo/javascript/impl/formatter/JavaScriptLanguageCodeStyleSettingsProvider.java +++ b/plugin/src/main/java/consulo/javascript/impl/formatter/JavaScriptLanguageCodeStyleSettingsProvider.java @@ -10,7 +10,8 @@ import consulo.language.codeStyle.ui.setting.SmartIndentOptionsEditor; import consulo.util.io.FileUtil; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; + import java.io.IOException; /** @@ -18,83 +19,124 @@ * @since 16.02.2015 */ @ExtensionImpl -public class JavaScriptLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSettingsProvider -{ - @Override - public IndentOptionsEditor getIndentOptionsEditor() - { - return new SmartIndentOptionsEditor(); - } +public class JavaScriptLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSettingsProvider { + @Override + public IndentOptionsEditor getIndentOptionsEditor() { + return new SmartIndentOptionsEditor(); + } - @Override - public CommonCodeStyleSettings getDefaultCommonSettings() - { - CommonCodeStyleSettings defaultSettings = new CommonCodeStyleSettings(getLanguage()); - CommonCodeStyleSettings.IndentOptions indentOptions = defaultSettings.initIndentOptions(); - indentOptions.INDENT_SIZE = 2; - indentOptions.CONTINUATION_INDENT_SIZE = 4; - indentOptions.TAB_SIZE = 2; + @Override + public CommonCodeStyleSettings getDefaultCommonSettings() { + CommonCodeStyleSettings defaultSettings = new CommonCodeStyleSettings(getLanguage()); + CommonCodeStyleSettings.IndentOptions indentOptions = defaultSettings.initIndentOptions(); + indentOptions.INDENT_SIZE = 2; + indentOptions.CONTINUATION_INDENT_SIZE = 4; + indentOptions.TAB_SIZE = 2; - defaultSettings.KEEP_LINE_BREAKS = false; + defaultSettings.KEEP_LINE_BREAKS = false; - return defaultSettings; - } + return defaultSettings; + } - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } - @Override - public void customizeSettings(@Nonnull CodeStyleSettingsCustomizable consumer, @Nonnull SettingsType settingsType) - { - if(settingsType == SettingsType.SPACING_SETTINGS) - { - consumer.showStandardOptions("SPACE_BEFORE_METHOD_CALL_PARENTHESES", "SPACE_BEFORE_METHOD_PARENTHESES", "SPACE_BEFORE_IF_PARENTHESES", - "SPACE_BEFORE_WHILE_PARENTHESES", "SPACE_BEFORE_FOR_PARENTHESES", "SPACE_BEFORE_CATCH_PARENTHESES", - "SPACE_BEFORE_SWITCH_PARENTHESES", "SPACE_AROUND_ASSIGNMENT_OPERATORS", "SPACE_AROUND_LOGICAL_OPERATORS", - "SPACE_AROUND_EQUALITY_OPERATORS", "SPACE_AROUND_RELATIONAL_OPERATORS", "SPACE_AROUND_ADDITIVE_OPERATORS", - "SPACE_AROUND_MULTIPLICATIVE_OPERATORS", "SPACE_AROUND_SHIFT_OPERATORS", "SPACE_BEFORE_CLASS_LBRACE", - "SPACE_BEFORE_METHOD_LBRACE", "SPACE_BEFORE_IF_LBRACE", "SPACE_BEFORE_ELSE_LBRACE", "SPACE_BEFORE_WHILE_LBRACE", - "SPACE_BEFORE_FOR_LBRACE", "SPACE_BEFORE_SWITCH_LBRACE", "SPACE_BEFORE_TRY_LBRACE", "SPACE_BEFORE_CATCH_LBRACE", - "SPACE_BEFORE_WHILE_KEYWORD", "SPACE_BEFORE_ELSE_KEYWORD", "SPACE_BEFORE_CATCH_KEYWORD", "SPACE_WITHIN_METHOD_CALL_PARENTHESES", - "SPACE_WITHIN_METHOD_PARENTHESES", "SPACE_WITHIN_IF_PARENTHESES", "SPACE_WITHIN_WHILE_PARENTHESES", - "SPACE_WITHIN_FOR_PARENTHESES", "SPACE_WITHIN_CATCH_PARENTHESES", "SPACE_WITHIN_SWITCH_PARENTHESES", "SPACE_BEFORE_QUEST", - "SPACE_AFTER_QUEST", "SPACE_BEFORE_COLON", "SPACE_AFTER_COLON", "SPACE_AFTER_COMMA", "SPACE_AFTER_COMMA_IN_TYPE_ARGUMENTS", - "SPACE_BEFORE_COMMA", "SPACE_AROUND_UNARY_OPERATOR", "SPACE_WITHIN_BRACKETS", "SPACE_BEFORE_METHOD_PARENTHESES"); - } - else if(settingsType == SettingsType.BLANK_LINES_SETTINGS) - { - consumer.showStandardOptions("KEEP_BLANK_LINES_IN_CODE"); - } - else if(settingsType == SettingsType.WRAPPING_AND_BRACES_SETTINGS) - { - consumer.showStandardOptions("KEEP_LINE_BREAKS", "KEEP_FIRST_COLUMN_COMMENT", "BRACE_STYLE", "CLASS_BRACE_STYLE", "METHOD_BRACE_STYLE", - "CALL_PARAMETERS_WRAP", "CALL_PARAMETERS_LPAREN_ON_NEXT_LINE", "CALL_PARAMETERS_RPAREN_ON_NEXT_LINE", "METHOD_PARAMETERS_WRAP", - "METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE", "METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE", "ELSE_ON_NEW_LINE", "WHILE_ON_NEW_LINE", - "CATCH_ON_NEW_LINE", "ALIGN_MULTILINE_PARAMETERS", "ALIGN_MULTILINE_PARAMETERS_IN_CALLS", "ALIGN_MULTILINE_BINARY_OPERATION", - "BINARY_OPERATION_WRAP", "BINARY_OPERATION_SIGN_ON_NEXT_LINE", "TERNARY_OPERATION_WRAP", "TERNARY_OPERATION_SIGNS_ON_NEXT_LINE", - "PARENTHESES_EXPRESSION_LPAREN_WRAP", "PARENTHESES_EXPRESSION_RPAREN_WRAP", "ALIGN_MULTILINE_TERNARY_OPERATION"); - } - } + @Override + public void customizeSettings(@Nonnull CodeStyleSettingsCustomizable consumer, @Nonnull SettingsType settingsType) { + if (settingsType == SettingsType.SPACING_SETTINGS) { + consumer.showStandardOptions( + "SPACE_BEFORE_METHOD_CALL_PARENTHESES", + "SPACE_BEFORE_METHOD_PARENTHESES", + "SPACE_BEFORE_IF_PARENTHESES", + "SPACE_BEFORE_WHILE_PARENTHESES", + "SPACE_BEFORE_FOR_PARENTHESES", + "SPACE_BEFORE_CATCH_PARENTHESES", + "SPACE_BEFORE_SWITCH_PARENTHESES", + "SPACE_AROUND_ASSIGNMENT_OPERATORS", + "SPACE_AROUND_LOGICAL_OPERATORS", + "SPACE_AROUND_EQUALITY_OPERATORS", + "SPACE_AROUND_RELATIONAL_OPERATORS", + "SPACE_AROUND_ADDITIVE_OPERATORS", + "SPACE_AROUND_MULTIPLICATIVE_OPERATORS", + "SPACE_AROUND_SHIFT_OPERATORS", + "SPACE_BEFORE_CLASS_LBRACE", + "SPACE_BEFORE_METHOD_LBRACE", + "SPACE_BEFORE_IF_LBRACE", + "SPACE_BEFORE_ELSE_LBRACE", + "SPACE_BEFORE_WHILE_LBRACE", + "SPACE_BEFORE_FOR_LBRACE", + "SPACE_BEFORE_SWITCH_LBRACE", + "SPACE_BEFORE_TRY_LBRACE", + "SPACE_BEFORE_CATCH_LBRACE", + "SPACE_BEFORE_WHILE_KEYWORD", + "SPACE_BEFORE_ELSE_KEYWORD", + "SPACE_BEFORE_CATCH_KEYWORD", + "SPACE_WITHIN_METHOD_CALL_PARENTHESES", + "SPACE_WITHIN_METHOD_PARENTHESES", + "SPACE_WITHIN_IF_PARENTHESES", + "SPACE_WITHIN_WHILE_PARENTHESES", + "SPACE_WITHIN_FOR_PARENTHESES", + "SPACE_WITHIN_CATCH_PARENTHESES", + "SPACE_WITHIN_SWITCH_PARENTHESES", + "SPACE_BEFORE_QUEST", + "SPACE_AFTER_QUEST", + "SPACE_BEFORE_COLON", + "SPACE_AFTER_COLON", + "SPACE_AFTER_COMMA", + "SPACE_AFTER_COMMA_IN_TYPE_ARGUMENTS", + "SPACE_BEFORE_COMMA", + "SPACE_AROUND_UNARY_OPERATOR", + "SPACE_WITHIN_BRACKETS", + "SPACE_BEFORE_METHOD_PARENTHESES" + ); + } + else if (settingsType == SettingsType.BLANK_LINES_SETTINGS) { + consumer.showStandardOptions("KEEP_BLANK_LINES_IN_CODE"); + } + else if (settingsType == SettingsType.WRAPPING_AND_BRACES_SETTINGS) { + consumer.showStandardOptions( + "KEEP_LINE_BREAKS", + "KEEP_FIRST_COLUMN_COMMENT", + "BRACE_STYLE", + "CLASS_BRACE_STYLE", + "METHOD_BRACE_STYLE", + "CALL_PARAMETERS_WRAP", + "CALL_PARAMETERS_LPAREN_ON_NEXT_LINE", + "CALL_PARAMETERS_RPAREN_ON_NEXT_LINE", + "METHOD_PARAMETERS_WRAP", + "METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE", + "METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE", + "ELSE_ON_NEW_LINE", + "WHILE_ON_NEW_LINE", + "CATCH_ON_NEW_LINE", + "ALIGN_MULTILINE_PARAMETERS", + "ALIGN_MULTILINE_PARAMETERS_IN_CALLS", + "ALIGN_MULTILINE_BINARY_OPERATION", + "BINARY_OPERATION_WRAP", + "BINARY_OPERATION_SIGN_ON_NEXT_LINE", + "TERNARY_OPERATION_WRAP", + "TERNARY_OPERATION_SIGNS_ON_NEXT_LINE", + "PARENTHESES_EXPRESSION_LPAREN_WRAP", + "PARENTHESES_EXPRESSION_RPAREN_WRAP", + "ALIGN_MULTILINE_TERNARY_OPERATION" + ); + } + } - @Override - public String getCodeSample(@Nonnull SettingsType settingsType) - { - return loadPreview("codeStyle.txt"); - } + @Override + public String getCodeSample(@Nonnull SettingsType settingsType) { + return loadPreview("codeStyle.txt"); + } - private static String loadPreview(String file) - { - try - { - return FileUtil.loadTextAndClose(JavaScriptLanguageCodeStyleSettingsProvider.class.getResourceAsStream("/codeStyle" + file)); - } - catch(IOException e) - { - throw new Error(e); - } - } + private static String loadPreview(String file) { + try { + return FileUtil.loadTextAndClose(JavaScriptLanguageCodeStyleSettingsProvider.class.getResourceAsStream("/codeStyle/" + file)); + } + catch (IOException e) { + throw new Error(e); + } + } } diff --git a/plugin/src/main/java/consulo/javascript/impl/html/JavaScriptEmbeddedTokenHighlighter.java b/plugin/src/main/java/consulo/javascript/impl/html/JavaScriptEmbeddedTokenHighlighter.java new file mode 100644 index 00000000..5e515c57 --- /dev/null +++ b/plugin/src/main/java/consulo/javascript/impl/html/JavaScriptEmbeddedTokenHighlighter.java @@ -0,0 +1,25 @@ +package consulo.javascript.impl.html; + +import com.intellij.xml.highlighter.EmbeddedTokenHighlighter; +import consulo.annotation.component.ExtensionImpl; +import consulo.colorScheme.TextAttributesKey; +import consulo.javascript.ide.hightlight.JavaScriptHighlighter; +import consulo.language.ast.IElementType; +import consulo.util.collection.MultiMap; +import consulo.xml.lang.xml.XMLLanguage; +import jakarta.annotation.Nonnull; + +/** + * @author VISTALL + * @since 2024-04-19 + */ +@ExtensionImpl +public class JavaScriptEmbeddedTokenHighlighter implements EmbeddedTokenHighlighter { + @Nonnull + @Override + public MultiMap getEmbeddedTokenAttributes(@Nonnull XMLLanguage language) { + MultiMap keys = MultiMap.createLinked(); + JavaScriptHighlighter.storeDefaults(keys); + return keys; + } +} diff --git a/plugin/src/main/java/consulo/javascript/impl/html/JavaScriptHtmlScriptContentProvider.java b/plugin/src/main/java/consulo/javascript/impl/html/JavaScriptHtmlScriptContentProvider.java new file mode 100644 index 00000000..66a6f987 --- /dev/null +++ b/plugin/src/main/java/consulo/javascript/impl/html/JavaScriptHtmlScriptContentProvider.java @@ -0,0 +1,37 @@ +package consulo.javascript.impl.html; + +import com.intellij.lang.javascript.JSElementTypes; +import consulo.annotation.component.ExtensionImpl; +import consulo.javascript.lang.lexer.JavaScript15Lexer; +import consulo.javascript.language.JavaScriptLanguage; +import consulo.language.Language; +import consulo.language.ast.IElementType; +import consulo.language.lexer.Lexer; +import consulo.xml.lang.HtmlScriptContentProvider; +import jakarta.annotation.Nonnull; + +import jakarta.annotation.Nullable; + +/** + * @author VISTALL + * @since 2024-04-19 + */ +@ExtensionImpl +public class JavaScriptHtmlScriptContentProvider implements HtmlScriptContentProvider { + @Override + public IElementType getScriptElementType() { + return JSElementTypes.EMBEDDED_CONTENT; + } + + @Nullable + @Override + public Lexer getHighlightingLexer() { + return new JavaScript15Lexer(); + } + + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } +} diff --git a/plugin/src/main/java/consulo/javascript/impl/ide/actions/JavaScriptCreateFileAction.java b/plugin/src/main/java/consulo/javascript/impl/ide/actions/JavaScriptCreateFileAction.java index b36a182e..cbf8fc69 100644 --- a/plugin/src/main/java/consulo/javascript/impl/ide/actions/JavaScriptCreateFileAction.java +++ b/plugin/src/main/java/consulo/javascript/impl/ide/actions/JavaScriptCreateFileAction.java @@ -1,90 +1,84 @@ package consulo.javascript.impl.ide.actions; -import consulo.javascript.language.JavaScriptFileType; import consulo.annotation.access.RequiredReadAction; +import consulo.application.ReadAction; import consulo.dataContext.DataContext; import consulo.ide.IdeView; import consulo.ide.action.CreateFileFromTemplateAction; import consulo.ide.action.CreateFileFromTemplateDialog; +import consulo.javascript.language.JavaScriptFileType; +import consulo.javascript.localize.JavaScriptLocalize; import consulo.javascript.module.extension.JavaScriptModuleExtension; -import consulo.language.editor.CommonDataKeys; import consulo.language.psi.PsiDirectory; import consulo.language.util.ModuleUtilCore; import consulo.localize.LocalizeValue; import consulo.module.Module; import consulo.module.content.NewFileModuleResolver; import consulo.project.Project; -import consulo.ui.annotation.RequiredUIAccess; import consulo.virtualFileSystem.fileType.FileType; - -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL * @since 06.12.2015 */ -public class JavaScriptCreateFileAction extends CreateFileFromTemplateAction -{ - public JavaScriptCreateFileAction() - { - super(LocalizeValue.empty(), LocalizeValue.empty(), JavaScriptFileType.INSTANCE.getIcon()); - } +public class JavaScriptCreateFileAction extends CreateFileFromTemplateAction { + public JavaScriptCreateFileAction() { + super( + JavaScriptLocalize.actionJavascriptFileText(), + JavaScriptLocalize.actionJavascriptFileText(), + JavaScriptFileType.INSTANCE.getIcon() + ); + } - @Override - @RequiredUIAccess - protected boolean isAvailable(DataContext dataContext) - { - if(!super.isAvailable(dataContext)) - { - return false; - } - Module module = findModule(dataContext); - return module != null && ModuleUtilCore.getExtension(module, JavaScriptModuleExtension.class) != null; - } + @Override + protected boolean isAvailable(DataContext dataContext) { + if (!super.isAvailable(dataContext)) { + return false; + } + Module module = ReadAction.compute(() -> findModule(dataContext)); + return module != null && ModuleUtilCore.getExtension(module, JavaScriptModuleExtension.class) != null; + } - @Nullable - @Override - protected FileType getFileTypeForModuleResolve() - { - return JavaScriptFileType.INSTANCE; - } + @Nullable + @Override + protected FileType getFileTypeForModuleResolve() { + return JavaScriptFileType.INSTANCE; + } - @RequiredReadAction - private static Module findModule(DataContext dataContext) - { - Project project = dataContext.getData(CommonDataKeys.PROJECT); - assert project != null; - final IdeView view = dataContext.getData(IdeView.KEY); - if(view == null) - { - return null; - } + @RequiredReadAction + private static Module findModule(DataContext dataContext) { + Project project = dataContext.getData(Project.KEY); + assert project != null; + IdeView view = dataContext.getData(IdeView.KEY); + if (view == null) { + return null; + } - final PsiDirectory directory = view.getOrChooseDirectory(); - if(directory == null) - { - return null; - } + PsiDirectory directory = view.getOrChooseDirectory(); + if (directory == null) { + return null; + } - Module resolvedModule = NewFileModuleResolver.resolveModule(directory.getProject(), directory.getVirtualFile(), JavaScriptFileType.INSTANCE); - if(resolvedModule != null) - { - return resolvedModule; - } - return dataContext.getData(Module.KEY); - } + Module resolvedModule = + NewFileModuleResolver.resolveModule(directory.getProject(), directory.getVirtualFile(), JavaScriptFileType.INSTANCE); + if (resolvedModule != null) { + return resolvedModule; + } + return dataContext.getData(Module.KEY); + } - @Override - protected void buildDialog(Project project, PsiDirectory directory, CreateFileFromTemplateDialog.Builder builder) - { - builder.setTitle("Create JavaScript File"); + @Override + protected void buildDialog(Project project, PsiDirectory directory, CreateFileFromTemplateDialog.Builder builder) { + builder.setTitle(JavaScriptLocalize.actionJavascriptFileTitleText()); - builder.addKind("Empty File", JavaScriptFileType.INSTANCE.getIcon(), "JavaScriptFile"); - } + builder.addKind(JavaScriptLocalize.actionJavascriptFileEmptyFileKind(), JavaScriptFileType.INSTANCE.getIcon(), "JavaScriptFile"); + } - @Override - protected String getActionName(PsiDirectory directory, String newName, String templateName) - { - return "Create JavaScript File"; - } + @Nonnull + @Override + protected LocalizeValue getActionName(PsiDirectory directory, String newName, String templateName) { + return JavaScriptLocalize.actionJavascriptFileTitleText(); + } } diff --git a/plugin/src/main/java/consulo/javascript/impl/ide/actions/JavaScriptFileTemplateContributor.java b/plugin/src/main/java/consulo/javascript/impl/ide/actions/JavaScriptFileTemplateContributor.java index 66a4c5d7..9c216013 100644 --- a/plugin/src/main/java/consulo/javascript/impl/ide/actions/JavaScriptFileTemplateContributor.java +++ b/plugin/src/main/java/consulo/javascript/impl/ide/actions/JavaScriptFileTemplateContributor.java @@ -3,19 +3,16 @@ import consulo.annotation.component.ExtensionImpl; import consulo.fileTemplate.FileTemplateContributor; import consulo.fileTemplate.FileTemplateRegistrator; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 29-Aug-22 */ @ExtensionImpl -public class JavaScriptFileTemplateContributor implements FileTemplateContributor -{ - @Override - public void register(@Nonnull FileTemplateRegistrator fileTemplateRegistrator) - { - fileTemplateRegistrator.registerInternalTemplate("JavaScriptFile"); - } +public class JavaScriptFileTemplateContributor implements FileTemplateContributor { + @Override + public void register(@Nonnull FileTemplateRegistrator fileTemplateRegistrator) { + fileTemplateRegistrator.registerInternalTemplate("JavaScriptFile"); + } } diff --git a/plugin/src/main/java/consulo/javascript/impl/ide/completion/JavaScriptKeywordCompletionContributor.java b/plugin/src/main/java/consulo/javascript/impl/ide/completion/JavaScriptKeywordCompletionContributor.java index 08601a22..adad88a8 100644 --- a/plugin/src/main/java/consulo/javascript/impl/ide/completion/JavaScriptKeywordCompletionContributor.java +++ b/plugin/src/main/java/consulo/javascript/impl/ide/completion/JavaScriptKeywordCompletionContributor.java @@ -30,65 +30,64 @@ import consulo.language.psi.PsiElement; import consulo.language.util.ProcessingContext; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 20.12.2015 */ @ExtensionImpl -public class JavaScriptKeywordCompletionContributor extends CompletionContributor -{ - public JavaScriptKeywordCompletionContributor() - { - extend(CompletionType.BASIC, StandardPatterns.psiElement().withParent(JSReferenceExpression.class), new CompletionProvider() - { - @RequiredReadAction - @Override - public void addCompletions(@Nonnull CompletionParameters parameters, ProcessingContext context, @Nonnull CompletionResultSet result) - { - PsiElement position = parameters.getPosition(); - JSReferenceExpression parent = (JSReferenceExpression) position.getParent(); - if(parent.getQualifier() != null) - { - return; - } +public class JavaScriptKeywordCompletionContributor extends CompletionContributor { + public JavaScriptKeywordCompletionContributor() { + extend( + CompletionType.BASIC, + StandardPatterns.psiElement().withParent(JSReferenceExpression.class), + new CompletionProvider() { + @RequiredReadAction + @Override + public void addCompletions( + @Nonnull CompletionParameters parameters, + ProcessingContext context, + @Nonnull CompletionResultSet result + ) { + PsiElement position = parameters.getPosition(); + JSReferenceExpression parent = (JSReferenceExpression)position.getParent(); + if (parent.getQualifier() != null) { + return; + } - boolean parentIsStatement = parent.getParent() instanceof JSExpressionStatement; + boolean parentIsStatement = parent.getParent() instanceof JSExpressionStatement; - LookupElementBuilder functionKeyword = LookupElementBuilder.create("function"); - functionKeyword = functionKeyword.bold(); - if(parentIsStatement) - { - functionKeyword = functionKeyword.withInsertHandler(SpaceInsertHandler.INSTANCE); - } - else - { - functionKeyword = functionKeyword.withInsertHandler(ParenthesesInsertHandler.getInstance(false)); - functionKeyword = functionKeyword.withPresentableText("function()"); - } + LookupElementBuilder functionKeyword = LookupElementBuilder.create("function"); + functionKeyword = functionKeyword.bold(); + if (parentIsStatement) { + functionKeyword = functionKeyword.withInsertHandler(SpaceInsertHandler.INSTANCE); + } + else { + functionKeyword = functionKeyword.withInsertHandler(ParenthesesInsertHandler.getInstance(false)); + functionKeyword = functionKeyword.withPresentableText("function()"); + } - result.addElement(functionKeyword); + result.addElement(functionKeyword); - result.addElement(LookupElementBuilder.create("var").withInsertHandler(SpaceInsertHandler.INSTANCE).bold()); - result.addElement(LookupElementBuilder.create("const").withInsertHandler(SpaceInsertHandler.INSTANCE).bold()); + result.addElement(LookupElementBuilder.create("var").withInsertHandler(SpaceInsertHandler.INSTANCE).bold()); + result.addElement(LookupElementBuilder.create("const").withInsertHandler(SpaceInsertHandler.INSTANCE).bold()); - result.addElement(LookupElementBuilder.create("if").bold()); - result.addElement(LookupElementBuilder.create("for").bold()); - result.addElement(LookupElementBuilder.create("return").bold()); + result.addElement(LookupElementBuilder.create("if").bold()); + result.addElement(LookupElementBuilder.create("for").bold()); + result.addElement(LookupElementBuilder.create("return").bold()); - for(JavaScriptKeywordCompletionExtender extender : JavaScriptKeywordCompletionExtender.EP_NAME.getExtensionList()) - { - extender.fillCompletion(parameters, context, result); - } - } - }); - } + for (JavaScriptKeywordCompletionExtender extender : JavaScriptKeywordCompletionExtender.EP_NAME.getExtensionList()) { + extender.fillCompletion(parameters, context, result); + } + } + } + ); + } - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } } diff --git a/plugin/src/main/java/consulo/javascript/impl/ide/completion/JavaScriptSkipAutopopupInStrings.java b/plugin/src/main/java/consulo/javascript/impl/ide/completion/JavaScriptSkipAutopopupInStrings.java index 07e554ac..2d72af51 100644 --- a/plugin/src/main/java/consulo/javascript/impl/ide/completion/JavaScriptSkipAutopopupInStrings.java +++ b/plugin/src/main/java/consulo/javascript/impl/ide/completion/JavaScriptSkipAutopopupInStrings.java @@ -5,19 +5,17 @@ import consulo.language.Language; import consulo.language.editor.completion.SkipAutopopupInStrings; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 29-Aug-22 */ @ExtensionImpl -public class JavaScriptSkipAutopopupInStrings extends SkipAutopopupInStrings -{ - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } +public class JavaScriptSkipAutopopupInStrings extends SkipAutopopupInStrings { + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } } diff --git a/plugin/src/main/java/consulo/javascript/impl/ide/completion/SpaceInsertHandler.java b/plugin/src/main/java/consulo/javascript/impl/ide/completion/SpaceInsertHandler.java index cbea4f2f..0923166b 100644 --- a/plugin/src/main/java/consulo/javascript/impl/ide/completion/SpaceInsertHandler.java +++ b/plugin/src/main/java/consulo/javascript/impl/ide/completion/SpaceInsertHandler.java @@ -25,18 +25,15 @@ * @author VISTALL * @since 20.12.2015 */ -public class SpaceInsertHandler implements InsertHandler -{ - public static final SpaceInsertHandler INSTANCE = new SpaceInsertHandler(); +public class SpaceInsertHandler implements InsertHandler { + public static final SpaceInsertHandler INSTANCE = new SpaceInsertHandler(); - @Override - public void handleInsert(InsertionContext context, LookupElement item) - { - if(context.getCompletionChar() != ' ') - { - int tailOffset = context.getTailOffset(); - TailType.insertChar(context.getEditor(), tailOffset, ' '); - context.getEditor().getCaretModel().moveToOffset(tailOffset + 1); - } - } + @Override + public void handleInsert(InsertionContext context, LookupElement item) { + if (context.getCompletionChar() != ' ') { + int tailOffset = context.getTailOffset(); + TailType.insertChar(context.getEditor(), tailOffset, ' '); + context.getEditor().getCaretModel().moveToOffset(tailOffset + 1); + } + } } diff --git a/plugin/src/main/java/consulo/javascript/impl/ide/navigationToolbar/JavaScriptNavBarModelExtension.java b/plugin/src/main/java/consulo/javascript/impl/ide/navigationToolbar/JavaScriptNavBarModelExtension.java index ac0ae4ce..5426ea5c 100644 --- a/plugin/src/main/java/consulo/javascript/impl/ide/navigationToolbar/JavaScriptNavBarModelExtension.java +++ b/plugin/src/main/java/consulo/javascript/impl/ide/navigationToolbar/JavaScriptNavBarModelExtension.java @@ -7,29 +7,26 @@ import consulo.language.psi.PsiElement; import consulo.annotation.access.RequiredReadAction; import consulo.javascript.language.JavaScriptLanguage; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; /** * @author VISTALL * @since 17/01/2021 */ @ExtensionImpl -public class JavaScriptNavBarModelExtension extends StructureAwareNavBarModelExtension -{ - @Nonnull - @Override - protected Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } +public class JavaScriptNavBarModelExtension extends StructureAwareNavBarModelExtension { + @Nonnull + @Override + protected Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } - @Nullable - @Override - @RequiredReadAction - public String getPresentableText(Object object) - { - return object instanceof PsiElement ? JSStructureItemPresentation.getName((PsiElement) object) : null; - } + @Nullable + @Override + @RequiredReadAction + public String getPresentableText(Object object) { + return object instanceof PsiElement ? JSStructureItemPresentation.getName((PsiElement)object) : null; + } } diff --git a/plugin/src/main/java/consulo/javascript/impl/lang/JavaScriptFileTypeFactory.java b/plugin/src/main/java/consulo/javascript/impl/lang/JavaScriptFileTypeFactory.java index 09529cfb..5e3500e9 100644 --- a/plugin/src/main/java/consulo/javascript/impl/lang/JavaScriptFileTypeFactory.java +++ b/plugin/src/main/java/consulo/javascript/impl/lang/JavaScriptFileTypeFactory.java @@ -21,18 +21,16 @@ import consulo.virtualFileSystem.fileType.FileTypeConsumer; import consulo.virtualFileSystem.fileType.FileTypeFactory; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 11.12.2015 */ @ExtensionImpl -public class JavaScriptFileTypeFactory extends FileTypeFactory -{ - @Override - public void createFileTypes(@Nonnull FileTypeConsumer consumer) - { - consumer.consume(JavaScriptFileType.INSTANCE); - } +public class JavaScriptFileTypeFactory extends FileTypeFactory { + @Override + public void createFileTypes(@Nonnull FileTypeConsumer consumer) { + consumer.consume(JavaScriptFileType.INSTANCE); + } } diff --git a/plugin/src/main/java/consulo/javascript/impl/lang/JavaScriptLanguageVersionPusher.java b/plugin/src/main/java/consulo/javascript/impl/lang/JavaScriptLanguageVersionPusher.java index 661a185e..2570f9f8 100644 --- a/plugin/src/main/java/consulo/javascript/impl/lang/JavaScriptLanguageVersionPusher.java +++ b/plugin/src/main/java/consulo/javascript/impl/lang/JavaScriptLanguageVersionPusher.java @@ -1,9 +1,8 @@ package consulo.javascript.impl.lang; -import consulo.javascript.language.JavaScriptFileType; import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; -import consulo.component.messagebus.MessageBus; +import consulo.javascript.language.JavaScriptFileType; import consulo.javascript.language.JavaScriptLanguage; import consulo.javascript.language.StandardJavaScriptVersions; import consulo.javascript.module.extension.JavaScriptModuleExtension; @@ -12,179 +11,118 @@ import consulo.module.Module; import consulo.module.content.FilePropertyPusher; import consulo.module.content.PushedFilePropertiesUpdater; -import consulo.module.extension.ModuleExtension; -import consulo.module.extension.event.ModuleExtensionChangeListener; import consulo.project.Project; import consulo.util.dataholder.Key; import consulo.util.lang.ObjectUtil; import consulo.virtualFileSystem.FileAttribute; import consulo.virtualFileSystem.VirtualFile; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; -import java.util.HashSet; -import java.util.Set; /** * @author VISTALL * @since 2020-06-14 */ @ExtensionImpl -public class JavaScriptLanguageVersionPusher implements FilePropertyPusher -{ - private static final FileAttribute ourFileAttribute = new FileAttribute("javascript-version", 2, false); - - private static final Key> ourChangedModulesKey = Key.create("javascript-change-marker"); - - @Override - public void initExtra(@Nonnull Project project, @Nonnull MessageBus messageBus) - { - project.getMessageBus().connect().subscribe(ModuleExtensionChangeListener.class, (oldExtension, newExtension) -> - { - if(oldExtension instanceof JavaScriptModuleExtension && newExtension instanceof JavaScriptModuleExtension) - { - if(((JavaScriptModuleExtension) oldExtension).getLanguageVersion() != ((JavaScriptModuleExtension) newExtension).getLanguageVersion()) - { - addChanged(project, newExtension); - } - } - }); - } - - private void addChanged(Project project, ModuleExtension newExtension) - { - Set changedModules = project.getUserData(ourChangedModulesKey); - if(changedModules == null) - { - changedModules = new HashSet<>(); - } - - project.putUserData(ourChangedModulesKey, changedModules); - - changedModules.add(newExtension.getModule().getName()); - } - - @Nonnull - @Override - public Key getFileDataKey() - { - return LanguageVersion.KEY; - } - - @Override - public boolean pushDirectoriesOnly() - { - return false; - } - - @Nonnull - @Override - public LanguageVersion getDefaultValue() - { - return StandardJavaScriptVersions.getInstance().getDefaultVersion(); - } - - @Nullable - @Override - @RequiredReadAction - public LanguageVersion getImmediateValue(@Nonnull Project project, @Nullable VirtualFile virtualFile) - { - if(virtualFile == null) - { - return getDefaultValue(); - } - - Module moduleForFile = ModuleUtilCore.findModuleForFile(virtualFile, project); - return moduleForFile == null ? getDefaultValue() : getImmediateValue(moduleForFile); - } - - @Nullable - @Override - @RequiredReadAction - public LanguageVersion getImmediateValue(@Nonnull Module module) - { - JavaScriptModuleExtension extension = ModuleUtilCore.getExtension(module, JavaScriptModuleExtension.class); - if(extension != null) - { - return extension.getLanguageVersion(); - } - return getDefaultValue(); - } - - @Override - public boolean acceptsFile(@Nonnull VirtualFile virtualFile) - { - return virtualFile.getFileType() == JavaScriptFileType.INSTANCE; - } - - @Override - public boolean acceptsDirectory(@Nonnull VirtualFile virtualFile, @Nonnull Project project) - { - return false; - } - - @Override - public void persistAttribute(@Nonnull Project project, @Nonnull VirtualFile virtualFile, @Nonnull LanguageVersion newAttribute) throws IOException - { - DataInputStream inputStream = ourFileAttribute.readAttribute(virtualFile); - if(inputStream != null) - { - try - { - LanguageVersion oldAttribute = read(inputStream); - if(oldAttribute.equals(newAttribute) && oldAttribute != getDefaultValue()) - { - return; - } - } - catch(IOException e) - { - inputStream.close(); - } - } - - if(newAttribute != getDefaultValue() || inputStream != null) - { - try (DataOutputStream oStream = ourFileAttribute.writeAttribute(virtualFile)) - { - write(newAttribute, oStream); - } - - PushedFilePropertiesUpdater.getInstance(project).filePropertiesChanged(virtualFile, file -> true); - } - } - - @Override - public void afterRootsChanged(@Nonnull Project project) - { - Set changedModules = project.getUserData(ourChangedModulesKey); - if(changedModules == null) - { - return; - } - - project.putUserData(ourChangedModulesKey, null); - - if(!changedModules.isEmpty()) - { - PushedFilePropertiesUpdater.getInstance(project).pushAll(this); - } - } - - @Nonnull - private LanguageVersion read(DataInputStream stream) throws IOException - { - String id = stream.readUTF(); - LanguageVersion version = JavaScriptLanguage.INSTANCE.getVersionById(id); - return ObjectUtil.notNull(version, getDefaultValue()); - - } - - private void write(LanguageVersion jsVersion, DataOutputStream stream) throws IOException - { - stream.writeUTF(jsVersion.getId()); - } +public class JavaScriptLanguageVersionPusher implements FilePropertyPusher { + private static final FileAttribute ourFileAttribute = new FileAttribute("javascript-version", 2, false); + + @Nonnull + @Override + public Key getFileDataKey() { + return LanguageVersion.KEY; + } + + @Override + public boolean pushDirectoriesOnly() { + return false; + } + + @Nonnull + @Override + public LanguageVersion getDefaultValue() { + return StandardJavaScriptVersions.getInstance().getDefaultVersion(); + } + + @Nullable + @Override + @RequiredReadAction + public LanguageVersion getImmediateValue(@Nonnull Project project, @Nullable VirtualFile virtualFile) { + if (virtualFile == null) { + return getDefaultValue(); + } + + Module moduleForFile = ModuleUtilCore.findModuleForFile(virtualFile, project); + return moduleForFile == null ? getDefaultValue() : getImmediateValue(moduleForFile); + } + + @Nullable + @Override + @RequiredReadAction + public LanguageVersion getImmediateValue(@Nonnull Module module) { + JavaScriptModuleExtension extension = ModuleUtilCore.getExtension(module, JavaScriptModuleExtension.class); + if (extension != null) { + return extension.getLanguageVersion(); + } + return getDefaultValue(); + } + + @Override + public boolean acceptsFile(@Nonnull VirtualFile file, @Nonnull Project project) { + return file.getFileType() == JavaScriptFileType.INSTANCE; + } + + @Override + public boolean acceptsDirectory(@Nonnull VirtualFile virtualFile, @Nonnull Project project) { + return false; + } + + @Override + public void persistAttribute( + @Nonnull Project project, + @Nonnull VirtualFile virtualFile, + @Nonnull LanguageVersion newAttribute + ) throws IOException { + DataInputStream inputStream = ourFileAttribute.readAttribute(virtualFile); + if (inputStream != null) { + try { + LanguageVersion oldAttribute = read(inputStream); + if (oldAttribute.equals(newAttribute) && oldAttribute != getDefaultValue()) { + return; + } + } + catch (IOException e) { + inputStream.close(); + } + } + + if (newAttribute != getDefaultValue() || inputStream != null) { + try (DataOutputStream oStream = ourFileAttribute.writeAttribute(virtualFile)) { + write(newAttribute, oStream); + } + + PushedFilePropertiesUpdater.getInstance(project).filePropertiesChanged(virtualFile, file -> true); + } + } + + @Override + public void afterRootsChanged(@Nonnull Project project) { + PushedFilePropertiesUpdater.getInstance(project).pushAll(this); + } + + @Nonnull + private LanguageVersion read(DataInputStream stream) throws IOException { + String id = stream.readUTF(); + LanguageVersion version = JavaScriptLanguage.INSTANCE.getVersionById(id); + return ObjectUtil.notNull(version, getDefaultValue()); + + } + + private void write(LanguageVersion jsVersion, DataOutputStream stream) throws IOException { + stream.writeUTF(jsVersion.getId()); + } } diff --git a/plugin/src/main/java/consulo/javascript/impl/lang/JavaScriptLanguageVersionResolver.java b/plugin/src/main/java/consulo/javascript/impl/lang/JavaScriptLanguageVersionResolver.java index 664aaa9c..ddfd5c6d 100644 --- a/plugin/src/main/java/consulo/javascript/impl/lang/JavaScriptLanguageVersionResolver.java +++ b/plugin/src/main/java/consulo/javascript/impl/lang/JavaScriptLanguageVersionResolver.java @@ -32,60 +32,52 @@ import consulo.language.version.LanguageVersionResolver; import consulo.language.Language; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL * @since 11.12.2015 */ @ExtensionImpl -public class JavaScriptLanguageVersionResolver implements LanguageVersionResolver -{ - @RequiredReadAction - @Nonnull - @Override - public LanguageVersion getLanguageVersion(@Nonnull Language language, @Nullable PsiElement element) - { - PsiFile containingFile = element == null ? null : element.getContainingFile(); - if(containingFile == null) - { - return StandardJavaScriptVersions.getInstance().getDefaultVersion(); - } - FileType fileType = containingFile.getFileType(); - if(fileType instanceof JavaScriptFileTypeWithVersion) - { - Module module = ModuleUtilCore.findModuleForPsiElement(element); - return ((JavaScriptFileTypeWithVersion) fileType).getLanguageVersion(module, element.getContainingFile().getVirtualFile()); - } +public class JavaScriptLanguageVersionResolver implements LanguageVersionResolver { + @RequiredReadAction + @Nonnull + @Override + public LanguageVersion getLanguageVersion(@Nonnull Language language, @Nullable PsiElement element) { + PsiFile containingFile = element == null ? null : element.getContainingFile(); + if (containingFile == null) { + return StandardJavaScriptVersions.getInstance().getDefaultVersion(); + } + FileType fileType = containingFile.getFileType(); + if (fileType instanceof JavaScriptFileTypeWithVersion) { + Module module = element.getModule(); + return ((JavaScriptFileTypeWithVersion)fileType).getLanguageVersion(module, element.getContainingFile().getVirtualFile()); + } - return StandardJavaScriptVersions.getInstance().getDefaultVersion(); - } + return StandardJavaScriptVersions.getInstance().getDefaultVersion(); + } - @Nonnull - @RequiredReadAction - @Override - public LanguageVersion getLanguageVersion(@Nonnull Language language, @Nullable Project project, @Nullable VirtualFile virtualFile) - { - if(project == null || virtualFile == null) - { - return StandardJavaScriptVersions.getInstance().getDefaultVersion(); - } + @Nonnull + @RequiredReadAction + @Override + public LanguageVersion getLanguageVersion(@Nonnull Language language, @Nullable Project project, @Nullable VirtualFile virtualFile) { + if (project == null || virtualFile == null) { + return StandardJavaScriptVersions.getInstance().getDefaultVersion(); + } - FileType fileType = virtualFile.getFileType(); - if(fileType instanceof JavaScriptFileTypeWithVersion) - { - Module module = ModuleUtilCore.findModuleForFile(virtualFile, project); - return ((JavaScriptFileTypeWithVersion) fileType).getLanguageVersion(module, virtualFile); - } + FileType fileType = virtualFile.getFileType(); + if (fileType instanceof JavaScriptFileTypeWithVersion) { + Module module = ModuleUtilCore.findModuleForFile(virtualFile, project); + return ((JavaScriptFileTypeWithVersion)fileType).getLanguageVersion(module, virtualFile); + } - return StandardJavaScriptVersions.getInstance().getDefaultVersion(); - } + return StandardJavaScriptVersions.getInstance().getDefaultVersion(); + } - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } } diff --git a/plugin/src/main/java/consulo/javascript/impl/lang/JavaScriptParsingDefinition.java b/plugin/src/main/java/consulo/javascript/impl/lang/JavaScriptParsingDefinition.java index dd3720e7..85aae054 100644 --- a/plugin/src/main/java/consulo/javascript/impl/lang/JavaScriptParsingDefinition.java +++ b/plugin/src/main/java/consulo/javascript/impl/lang/JavaScriptParsingDefinition.java @@ -34,64 +34,54 @@ import consulo.language.psi.PsiFile; import consulo.language.util.LanguageUtil; import consulo.language.version.LanguageVersionableParserDefinition; - -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 24.08.14 */ @ExtensionImpl -public class JavaScriptParsingDefinition extends LanguageVersionableParserDefinition -{ - @Nonnull - @Override - public Language getLanguage() - { - return JavaScriptLanguage.INSTANCE; - } +public class JavaScriptParsingDefinition extends LanguageVersionableParserDefinition { + @Nonnull + @Override + public Language getLanguage() { + return JavaScriptLanguage.INSTANCE; + } - @Nonnull - @Override - public IFileElementType getFileNodeType() - { - return JSElementTypes.FILE; - } + @Nonnull + @Override + public IFileElementType getFileNodeType() { + return JSElementTypes.FILE; + } - @Nonnull - @Override - public PsiElement createElement(ASTNode node) - { - final IElementType type = node.getElementType(); + @Nonnull + @Override + public PsiElement createElement(ASTNode node) { + IElementType type = node.getElementType(); - if(type == JSElementTypes.EMBEDDED_CONTENT) - { - return new JSEmbeddedContentImpl(node); - } - else if(type == JSTokenTypes.XML_JS_SCRIPT) - { - return new JSEmbeddedContentImpl(node); - } - else if(type == JSTokenTypes.DOC_COMMENT) - { - return new JSDocCommentImpl(node); - } + if (type == JSElementTypes.EMBEDDED_CONTENT) { + return new JSEmbeddedContentImpl(node); + } + else if (type == JSTokenTypes.XML_JS_SCRIPT) { + return new JSEmbeddedContentImpl(node); + } + else if (type == JSTokenTypes.DOC_COMMENT) { + return new JSDocCommentImpl(node); + } - return new ASTWrapperPsiElement(node); - } + return new ASTWrapperPsiElement(node); + } - @Override - public PsiFile createFile(FileViewProvider fileViewProvider) - { - return new JSFileImpl(fileViewProvider); - } + @Override + public PsiFile createFile(FileViewProvider fileViewProvider) { + return new JSFileImpl(fileViewProvider); + } - @Nonnull - @Override - public SpaceRequirements spaceExistanceTypeBetweenTokens(ASTNode left, ASTNode right) - { - PsiElement leftPsi = left.getPsi(); - final Lexer lexer = createLexer(leftPsi.getLanguageVersion()); - return LanguageUtil.canStickTokensTogetherByLexer(left, right, lexer); - } + @Nonnull + @Override + public SpaceRequirements spaceExistanceTypeBetweenTokens(ASTNode left, ASTNode right) { + PsiElement leftPsi = left.getPsi(); + Lexer lexer = createLexer(leftPsi.getLanguageVersion()); + return LanguageUtil.canStickTokensTogetherByLexer(left, right, lexer); + } } diff --git a/plugin/src/main/java/consulo/javascript/impl/lang/navigation/JavaScriptClassContributor.java b/plugin/src/main/java/consulo/javascript/impl/lang/navigation/JavaScriptClassContributor.java index c4212f48..6848bff8 100644 --- a/plugin/src/main/java/consulo/javascript/impl/lang/navigation/JavaScriptClassContributor.java +++ b/plugin/src/main/java/consulo/javascript/impl/lang/navigation/JavaScriptClassContributor.java @@ -29,35 +29,41 @@ import consulo.navigation.NavigationItem; import consulo.project.Project; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; + import java.util.Collection; /** * @author VISTALL */ @ExtensionImpl -public class JavaScriptClassContributor implements GotoClassOrTypeContributor -{ - @Override - public void processNames(@Nonnull Processor processor, @Nonnull SearchScope searchScope, @Nullable IdFilter idFilter) - { - StubIndex.getInstance().processAllKeys(JavaScriptIndexKeys.CLASSES_BY_NAME, processor, (GlobalSearchScope) searchScope, idFilter); - } +public class JavaScriptClassContributor implements GotoClassOrTypeContributor { + @Override + public void processNames(@Nonnull Processor processor, @Nonnull SearchScope searchScope, @Nullable IdFilter idFilter) { + StubIndex.getInstance().processAllKeys(JavaScriptIndexKeys.CLASSES_BY_NAME, processor, (GlobalSearchScope)searchScope, idFilter); + } - @Override - public void processElementsWithName(@Nonnull String name, @Nonnull Processor processor, @Nonnull FindSymbolParameters findSymbolParameters) - { - Project project = findSymbolParameters.getProject(); - Collection elements = StubIndex.getElements(JavaScriptIndexKeys.CLASSES_BY_NAME, name, project, GlobalSearchScope.allScope(project), findSymbolParameters.getIdFilter(), JSClass - .class); + @Override + public void processElementsWithName( + @Nonnull String name, + @Nonnull Processor processor, + @Nonnull FindSymbolParameters findSymbolParameters + ) { + Project project = findSymbolParameters.getProject(); + Collection elements = StubIndex.getElements( + JavaScriptIndexKeys.CLASSES_BY_NAME, + name, + project, + GlobalSearchScope.allScope(project), + findSymbolParameters.getIdFilter(), + JSClass.class + ); - for(JSClass element : elements) - { - if(!processor.process(element)) - { - break; - } - } - } + for (JSClass element : elements) { + if (!processor.process(element)) { + break; + } + } + } } diff --git a/plugin/src/main/java/consulo/javascript/impl/lang/psi/JavaScriptSimpleType.java b/plugin/src/main/java/consulo/javascript/impl/lang/psi/JavaScriptSimpleType.java deleted file mode 100644 index 0b7f5ec3..00000000 --- a/plugin/src/main/java/consulo/javascript/impl/lang/psi/JavaScriptSimpleType.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2013-2015 must-be.org - * - * 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 consulo.javascript.impl.lang.psi; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import consulo.annotation.access.RequiredReadAction; -import consulo.javascript.language.psi.JavaScriptType; -import consulo.language.psi.PsiElement; - -/** - * @author VISTALL - * @since 13.12.2015 - */ -public class JavaScriptSimpleType implements JavaScriptType -{ - private String myReferenceName; - private PsiElement myElement; - - public JavaScriptSimpleType(@Nonnull String referenceName, @Nullable PsiElement element) - { - myReferenceName = referenceName; - myElement = element; - } - - @RequiredReadAction - @Nonnull - @Override - public String getPresentableText() - { - return myReferenceName; - } - - @Nullable - @Override - public PsiElement getTargetElement() - { - return myElement; - } - - @Override - public String toString() - { - return "JavaScriptSimpleType: " + myReferenceName; - } -} diff --git a/plugin/src/main/java/consulo/javascript/impl/psi/impl/reference/DefaultJSPropertyNameReferenceProvider.java b/plugin/src/main/java/consulo/javascript/impl/psi/impl/reference/DefaultJSPropertyNameReferenceProvider.java index 11621ffc..001fda5f 100644 --- a/plugin/src/main/java/consulo/javascript/impl/psi/impl/reference/DefaultJSPropertyNameReferenceProvider.java +++ b/plugin/src/main/java/consulo/javascript/impl/psi/impl/reference/DefaultJSPropertyNameReferenceProvider.java @@ -25,23 +25,21 @@ import consulo.language.psi.PsiElement; import consulo.language.psi.PsiReference; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL * @since 02.12.2015 */ @ExtensionImpl(id = "default", order = "last") -public class DefaultJSPropertyNameReferenceProvider implements JSPropertyNameReferenceProvider -{ - @RequiredReadAction - @Nullable - @Override - public PsiReference getReference(@Nonnull JSProperty property) - { - PsiElement nameIdentifier = property.getNameIdentifier(); - assert nameIdentifier != null; - return new JSPropertyNameReference(property, nameIdentifier); - } +public class DefaultJSPropertyNameReferenceProvider implements JSPropertyNameReferenceProvider { + @RequiredReadAction + @Nullable + @Override + public PsiReference getReference(@Nonnull JSProperty property) { + PsiElement nameIdentifier = property.getNameIdentifier(); + assert nameIdentifier != null; + return new JSPropertyNameReference(property, nameIdentifier); + } } diff --git a/plugin/src/main/java/module-info.java b/plugin/src/main/java/module-info.java index 7fe58218..25b52a99 100644 --- a/plugin/src/main/java/module-info.java +++ b/plugin/src/main/java/module-info.java @@ -2,50 +2,49 @@ * @author VISTALL * @since 23-Aug-22 */ -open module consulo.javascript -{ - requires transitive consulo.javascript.base.api; - requires transitive consulo.javascript.base.impl; +open module consulo.javascript { + requires transitive consulo.javascript.base.api; + requires transitive consulo.javascript.base.impl; - requires consulo.language.editor.impl; + requires consulo.language.editor.impl; - requires com.intellij.xml; + requires com.intellij.xml; - // TODO remove in future - requires java.desktop; + // TODO remove in future + requires java.desktop; + requires forms.rt; - exports com.intellij.javascript; - exports com.intellij.javascript.manipulators; - exports com.intellij.lang.javascript.impl; - exports com.intellij.lang.javascript.impl.findUsages; - exports com.intellij.lang.javascript.impl.flex; - exports com.intellij.lang.javascript.impl.flex.importer; - exports com.intellij.lang.javascript.impl.folding; - exports com.intellij.lang.javascript.impl.formatter; - exports com.intellij.lang.javascript.impl.formatter.blocks; - exports com.intellij.lang.javascript.impl.generation; - exports com.intellij.lang.javascript.impl.highlighting; - exports com.intellij.lang.javascript.impl.index.predefined; - exports com.intellij.lang.javascript.impl.inspections; - exports com.intellij.lang.javascript.impl.navigation; - exports com.intellij.lang.javascript.impl.refactoring; - exports com.intellij.lang.javascript.impl.refactoring.extractMethod; - exports com.intellij.lang.javascript.impl.refactoring.introduceConstant; - exports com.intellij.lang.javascript.impl.refactoring.introduceField; - exports com.intellij.lang.javascript.impl.refactoring.introduceVariable; - exports com.intellij.lang.javascript.impl.search; - exports com.intellij.lang.javascript.impl.structureView; - exports com.intellij.lang.javascript.impl.surroundWith; - exports consulo.javascript.impl; - exports consulo.javascript.impl.copyright; - exports consulo.javascript.impl.findUsages; - exports consulo.javascript.impl.formatter; - exports consulo.javascript.impl.ide.actions; - exports consulo.javascript.impl.ide.completion; - exports consulo.javascript.impl.ide.navigationToolbar; - exports consulo.javascript.impl.lang; - exports consulo.javascript.impl.lang.navigation; - exports consulo.javascript.impl.lang.psi; - exports consulo.javascript.impl.psi.impl.reference; - exports com.intellij.lang.javascript.impl.validation; + exports com.intellij.javascript; + exports com.intellij.javascript.manipulators; + exports com.intellij.lang.javascript.impl; + exports com.intellij.lang.javascript.impl.findUsages; + exports com.intellij.lang.javascript.impl.flex; + exports com.intellij.lang.javascript.impl.flex.importer; + exports com.intellij.lang.javascript.impl.folding; + exports com.intellij.lang.javascript.impl.formatter; + exports com.intellij.lang.javascript.impl.formatter.blocks; + exports com.intellij.lang.javascript.impl.generation; + exports com.intellij.lang.javascript.impl.highlighting; + exports com.intellij.lang.javascript.impl.index.predefined; + exports com.intellij.lang.javascript.impl.inspections; + exports com.intellij.lang.javascript.impl.navigation; + exports com.intellij.lang.javascript.impl.refactoring; + exports com.intellij.lang.javascript.impl.refactoring.extractMethod; + exports com.intellij.lang.javascript.impl.refactoring.introduceConstant; + exports com.intellij.lang.javascript.impl.refactoring.introduceField; + exports com.intellij.lang.javascript.impl.refactoring.introduceVariable; + exports com.intellij.lang.javascript.impl.search; + exports com.intellij.lang.javascript.impl.structureView; + exports com.intellij.lang.javascript.impl.surroundWith; + exports consulo.javascript.impl; + exports consulo.javascript.impl.copyright; + exports consulo.javascript.impl.findUsages; + exports consulo.javascript.impl.formatter; + exports consulo.javascript.impl.ide.actions; + exports consulo.javascript.impl.ide.completion; + exports consulo.javascript.impl.ide.navigationToolbar; + exports consulo.javascript.impl.lang; + exports consulo.javascript.impl.lang.navigation; + exports consulo.javascript.impl.psi.impl.reference; + exports com.intellij.lang.javascript.impl.validation; } \ No newline at end of file diff --git a/plugin/src/main/resources/META-INF/plugin.xml b/plugin/src/main/resources/META-INF/plugin.xml index de3e1796..180e1e42 100644 --- a/plugin/src/main/resources/META-INF/plugin.xml +++ b/plugin/src/main/resources/META-INF/plugin.xml @@ -1,5 +1,5 @@ - 4.0.0 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 - - consulo - arch.managment - 3-SNAPSHOT - - + + consulo + arch.managment + 3-SNAPSHOT + + - - - consulo - https://maven.consulo.io/repository/snapshots/ - - true - interval:60 - - - + + + consulo + https://maven.consulo.dev/repository/snapshots/ + + true + interval:60 + + + - consulo.plugin - consulo.javascript.parent - 3-SNAPSHOT - pom + consulo.plugin + consulo.javascript.parent + 3-SNAPSHOT + pom - - base-api - base-impl - inspections - intentions - - web-browser-impl - debugger/debugger-impl - debugger/v8-debugger-impl - lang-version-impl/javascript16-impl - lang-version-impl/javascript17-impl - lang-version-impl/javascript18-impl - lang-version-impl/typescript-impl - lang-version-impl/actionscript-impl - lang-version-impl/ecmascript4-impl - lang-version-impl/ecmascript-impl - lang-version-impl/json-javascript-impl - regexp-impl - plugin - + + base-api + base-impl + inspections + intentions + + web-browser-impl + debugger/debugger-impl + debugger/browser-debugger-impl + debugger/cdt-debugger-impl + lang-version-impl/javascript16-impl + lang-version-impl/javascript17-impl + lang-version-impl/javascript18-impl + lang-version-impl/typescript-impl + lang-version-impl/actionscript-impl + lang-version-impl/ecmascript4-impl + lang-version-impl/ecmascript-impl + regexp-impl + plugin + \ No newline at end of file diff --git a/regexp-impl/pom.xml b/regexp-impl/pom.xml index 7e6beacc..de8bd5d2 100644 --- a/regexp-impl/pom.xml +++ b/regexp-impl/pom.xml @@ -32,7 +32,7 @@ consulo - https://maven.consulo.io/repository/snapshots/ + https://maven.consulo.dev/repository/snapshots/ true interval:60 diff --git a/regexp-impl/src/main/java/consulo/javascript/regexp/impl/JavaScriptRegExpLiteralLanguageHost.java b/regexp-impl/src/main/java/consulo/javascript/regexp/impl/JavaScriptRegExpLiteralLanguageHost.java index c79e6a84..de39f74e 100644 --- a/regexp-impl/src/main/java/consulo/javascript/regexp/impl/JavaScriptRegExpLiteralLanguageHost.java +++ b/regexp-impl/src/main/java/consulo/javascript/regexp/impl/JavaScriptRegExpLiteralLanguageHost.java @@ -8,93 +8,79 @@ import org.intellij.lang.regexp.psi.RegExpGroup; import org.intellij.lang.regexp.psi.RegExpNamedGroupRef; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL * @since 21/12/2021 */ @ExtensionImpl -public class JavaScriptRegExpLiteralLanguageHost implements RegExpLanguageHost -{ - @Nonnull - @Override - public Class getHostClass() - { - return JSRegExpLiteralExpressionImpl.class; - } +public class JavaScriptRegExpLiteralLanguageHost implements RegExpLanguageHost { + @Nonnull + @Override + public Class getHostClass() { + return JSRegExpLiteralExpressionImpl.class; + } - @Override - public boolean characterNeedsEscaping(char c) - { - if(c == '/') - { - return true; - } - return false; - } + @Override + public boolean characterNeedsEscaping(char c) { + if (c == '/') { + return true; + } + return false; + } - @Override - public boolean supportsPerl5EmbeddedComments() - { - return false; - } + @Override + public boolean supportsPerl5EmbeddedComments() { + return false; + } - @Override - public boolean supportsPossessiveQuantifiers() - { - return false; - } + @Override + public boolean supportsPossessiveQuantifiers() { + return false; + } - @Override - public boolean supportsPythonConditionalRefs() - { - return false; - } + @Override + public boolean supportsPythonConditionalRefs() { + return false; + } - @Override - public boolean supportsNamedGroupSyntax(RegExpGroup group) - { - return false; - } + @Override + public boolean supportsNamedGroupSyntax(RegExpGroup group) { + return false; + } - @Override - public boolean supportsNamedGroupRefSyntax(RegExpNamedGroupRef ref) - { - return false; - } + @Override + public boolean supportsNamedGroupRefSyntax(RegExpNamedGroupRef ref) { + return false; + } - @Override - public boolean supportsExtendedHexCharacter(RegExpChar regExpChar) - { - return false; - } + @Override + public boolean supportsExtendedHexCharacter(RegExpChar regExpChar) { + return false; + } - @Override - public boolean isValidCategory(@Nonnull String category) - { - return DefaultRegExpPropertiesProvider.getInstance().isValidCategory(category); - } + @Override + public boolean isValidCategory(@Nonnull String category) { + return DefaultRegExpPropertiesProvider.getInstance().isValidCategory(category); + } - @Nonnull - @Override - public String[][] getAllKnownProperties() - { - return DefaultRegExpPropertiesProvider.getInstance().getAllKnownProperties(); - } + @Nonnull + @Override + public String[][] getAllKnownProperties() { + return DefaultRegExpPropertiesProvider.getInstance().getAllKnownProperties(); + } - @Nullable - @Override - public String getPropertyDescription(@Nullable String name) - { - return DefaultRegExpPropertiesProvider.getInstance().getPropertyDescription(name); - } + @Nullable + @Override + public String getPropertyDescription(@Nullable String name) { + return DefaultRegExpPropertiesProvider.getInstance().getPropertyDescription(name); + } - @Nonnull - @Override - public String[][] getKnownCharacterClasses() - { - return DefaultRegExpPropertiesProvider.getInstance().getKnownCharacterClasses(); - } + @Nonnull + @Override + public String[][] getKnownCharacterClasses() { + return DefaultRegExpPropertiesProvider.getInstance().getKnownCharacterClasses(); + } } diff --git a/regexp-impl/src/main/java/consulo/javascript/regexp/impl/JavaScriptRegexpMultiHostInjector.java b/regexp-impl/src/main/java/consulo/javascript/regexp/impl/JavaScriptRegexpMultiHostInjector.java index bd3b6efe..ad1f4108 100644 --- a/regexp-impl/src/main/java/consulo/javascript/regexp/impl/JavaScriptRegexpMultiHostInjector.java +++ b/regexp-impl/src/main/java/consulo/javascript/regexp/impl/JavaScriptRegexpMultiHostInjector.java @@ -26,39 +26,36 @@ import consulo.language.psi.PsiLanguageInjectionHost; import org.intellij.lang.regexp.RegExpLanguage; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL * @since 11.12.2015 */ @ExtensionImpl -public class JavaScriptRegexpMultiHostInjector implements MultiHostInjector -{ - @Nonnull - @Override - public Class getElementClass() - { - return JSRegExpLiteralExpressionImpl.class; - } +public class JavaScriptRegexpMultiHostInjector implements MultiHostInjector { + @Nonnull + @Override + public Class getElementClass() { + return JSRegExpLiteralExpressionImpl.class; + } - @Override - @RequiredReadAction - public void injectLanguages(@Nonnull MultiHostRegistrar registrar, @Nonnull PsiElement context) - { - if(context instanceof JSRegExpLiteralExpressionImpl) - { - String text = context.getText(); + @Override + @RequiredReadAction + public void injectLanguages(@Nonnull MultiHostRegistrar registrar, @Nonnull PsiElement context) { + if (context instanceof JSRegExpLiteralExpressionImpl) { + String text = context.getText(); - // ignore flags for regexp - int lastIndex = text.lastIndexOf('/'); - // empty regexp - if(lastIndex == 0) - { - return; - } + // ignore flags for regexp + int lastIndex = text.lastIndexOf('/'); + // empty regexp + if (lastIndex == 0) { + return; + } - registrar.startInjecting(RegExpLanguage.INSTANCE).addPlace(null, null, (PsiLanguageInjectionHost) context, new TextRange(1, lastIndex)).doneInjecting(); - } - } + registrar.startInjecting(RegExpLanguage.INSTANCE) + .addPlace(null, null, (PsiLanguageInjectionHost)context, new TextRange(1, lastIndex)) + .doneInjecting(); + } + } } diff --git a/regexp-impl/src/main/java/module-info.java b/regexp-impl/src/main/java/module-info.java index 27b41292..f02a05fa 100644 --- a/regexp-impl/src/main/java/module-info.java +++ b/regexp-impl/src/main/java/module-info.java @@ -2,8 +2,7 @@ * @author VISTALL * @since 18-Sep-22 */ -module consulo.javascript.regexp.impl -{ - requires com.intellij.regexp; - requires consulo.javascript.base.impl; +module consulo.javascript.regexp.impl { + requires com.intellij.regexp; + requires consulo.javascript.base.impl; } \ No newline at end of file diff --git a/web-browser-impl/pom.xml b/web-browser-impl/pom.xml index 17aeac49..0a293587 100644 --- a/web-browser-impl/pom.xml +++ b/web-browser-impl/pom.xml @@ -32,7 +32,7 @@ consulo - https://maven.consulo.io/repository/snapshots/ + https://maven.consulo.dev/repository/snapshots/ true interval:60 diff --git a/web-browser-impl/src/main/java/consulo/javascript/client/module/extension/ClientJavaScriptModuleExtension.java b/web-browser-impl/src/main/java/consulo/javascript/client/module/extension/ClientJavaScriptModuleExtension.java index c957f371..a59d185e 100644 --- a/web-browser-impl/src/main/java/consulo/javascript/client/module/extension/ClientJavaScriptModuleExtension.java +++ b/web-browser-impl/src/main/java/consulo/javascript/client/module/extension/ClientJavaScriptModuleExtension.java @@ -16,111 +16,95 @@ import consulo.module.extension.ModuleInheritableNamedPointer; import org.jdom.Element; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL - * @since 29.06.14 + * @since 2014-06-29 */ -public class ClientJavaScriptModuleExtension extends ModuleExtensionBase implements JavaScriptModuleExtension -{ - private SdkModuleInheritableNamedPointerImpl myPointer; +public class ClientJavaScriptModuleExtension extends ModuleExtensionBase implements JavaScriptModuleExtension { + private SdkModuleInheritableNamedPointerImpl myPointer; - protected LanguageVersion myLanguageVersion = StandardJavaScriptVersions.getInstance().getDefaultVersion(); + protected LanguageVersion myLanguageVersion = StandardJavaScriptVersions.getInstance().getDefaultVersion(); - public ClientJavaScriptModuleExtension(@Nonnull String id, @Nonnull ModuleRootLayer rootLayer) - { - super(id, rootLayer); - myPointer = new SdkModuleInheritableNamedPointerImpl(rootLayer, id) - { - @Nullable - @Override - public String getItemNameFromModule(@Nonnull Module module) - { - ClientJavaScriptModuleExtension extension = ModuleUtilCore.getExtension(module, ClientJavaScriptModuleExtension.class); - if(extension == null) - { - return null; - } - return extension.getSdkName(); - } + public ClientJavaScriptModuleExtension(@Nonnull String id, @Nonnull ModuleRootLayer rootLayer) { + super(id, rootLayer); + myPointer = new SdkModuleInheritableNamedPointerImpl(rootLayer, id) { + @Nullable + @Override + public String getItemNameFromModule(@Nonnull Module module) { + ClientJavaScriptModuleExtension extension = ModuleUtilCore.getExtension(module, ClientJavaScriptModuleExtension.class); + if (extension == null) { + return null; + } + return extension.getSdkName(); + } - @Nullable - @Override - public Sdk getItemFromModule(@Nonnull Module module) - { - ClientJavaScriptModuleExtension extension = ModuleUtilCore.getExtension(module, ClientJavaScriptModuleExtension.class); - if(extension == null) - { - return null; - } - return extension.getSdk(); - } - }; + @Nullable + @Override + public Sdk getItemFromModule(@Nonnull Module module) { + ClientJavaScriptModuleExtension extension = ModuleUtilCore.getExtension(module, ClientJavaScriptModuleExtension.class); + if (extension == null) { + return null; + } + return extension.getSdk(); + } + }; - Sdk sdkByType = SdkTable.getInstance().findPredefinedSdkByType(ClientJavaScriptSdkType.getInstance()); - myPointer.set(null, sdkByType); - } + Sdk sdkByType = SdkTable.getInstance().findPredefinedSdkByType(ClientJavaScriptSdkType.getInstance()); + myPointer.set(null, sdkByType); + } - @RequiredReadAction - @Override - protected void loadStateImpl(@Nonnull Element element) - { - super.loadStateImpl(element); - myLanguageVersion = StandardJavaScriptVersions.getInstance().findVersionById(element.getAttributeValue("language-version")); - } + @RequiredReadAction + @Override + protected void loadStateImpl(@Nonnull Element element) { + super.loadStateImpl(element); + myLanguageVersion = StandardJavaScriptVersions.getInstance().findVersionById(element.getAttributeValue("language-version")); + } - @Override - protected void getStateImpl(@Nonnull Element element) - { - super.getStateImpl(element); - if(myLanguageVersion != StandardJavaScriptVersions.getInstance().getDefaultVersion()) - { - element.setAttribute("language-version", myLanguageVersion.getId()); - } - } + @Override + protected void getStateImpl(@Nonnull Element element) { + super.getStateImpl(element); + if (myLanguageVersion != StandardJavaScriptVersions.getInstance().getDefaultVersion()) { + element.setAttribute("language-version", myLanguageVersion.getId()); + } + } - @Nonnull - @Override - public ModuleInheritableNamedPointer getInheritableSdk() - { - return myPointer; - } + @Nonnull + @Override + public ModuleInheritableNamedPointer getInheritableSdk() { + return myPointer; + } - @Nullable - @Override - public Sdk getSdk() - { - return myPointer.get(); - } + @Nullable + @Override + public Sdk getSdk() { + return myPointer.get(); + } - @Nullable - @Override - public String getSdkName() - { - return myPointer.getName(); - } + @Nullable + @Override + public String getSdkName() { + return myPointer.getName(); + } - @Nonnull - @Override - public Class getSdkTypeClass() - { - throw new IllegalArgumentException(); - } + @Nonnull + @Override + public Class getSdkTypeClass() { + throw new IllegalArgumentException(); + } - @Nonnull - @Override - public LanguageVersion getLanguageVersion() - { - return myLanguageVersion; - } + @Nonnull + @Override + public LanguageVersion getLanguageVersion() { + return myLanguageVersion; + } - @RequiredReadAction - @Override - public void commit(@Nonnull ClientJavaScriptModuleExtension mutableModuleExtension) - { - super.commit(mutableModuleExtension); - myLanguageVersion = mutableModuleExtension.getLanguageVersion(); - } + @RequiredReadAction + @Override + public void commit(@Nonnull ClientJavaScriptModuleExtension mutableModuleExtension) { + super.commit(mutableModuleExtension); + myLanguageVersion = mutableModuleExtension.getLanguageVersion(); + } } diff --git a/web-browser-impl/src/main/java/consulo/javascript/client/module/extension/ClientJavaScriptModuleExtensionPanel.java b/web-browser-impl/src/main/java/consulo/javascript/client/module/extension/ClientJavaScriptModuleExtensionPanel.java index b06b1750..fbaf1e38 100644 --- a/web-browser-impl/src/main/java/consulo/javascript/client/module/extension/ClientJavaScriptModuleExtensionPanel.java +++ b/web-browser-impl/src/main/java/consulo/javascript/client/module/extension/ClientJavaScriptModuleExtensionPanel.java @@ -16,56 +16,48 @@ package consulo.javascript.client.module.extension; -import consulo.language.version.LanguageVersion; -import consulo.ui.ex.awt.*; -import consulo.ui.ex.awt.CollectionComboBoxModel; -import consulo.ui.ex.awt.ColoredListCellRenderer; -import consulo.javascript.lang.BaseJavaScriptLanguageVersion; import consulo.javascript.language.JavaScriptLanguageVersion; import consulo.javascript.language.StandardJavaScriptVersions; import consulo.javascript.module.extension.JavaScriptMutableModuleExtension; -import consulo.ui.ex.awt.LabeledComponent; +import consulo.language.version.LanguageVersion; +import consulo.ui.ex.awt.*; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; import javax.swing.*; import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; import java.util.List; /** * @author VISTALL - * @since 12.12.2015 + * @since 2015-12-12 */ -public class ClientJavaScriptModuleExtensionPanel extends JPanel -{ - public ClientJavaScriptModuleExtensionPanel(final JavaScriptMutableModuleExtension extension) - { - super(new VerticalFlowLayout(true, false)); +public class ClientJavaScriptModuleExtensionPanel extends JPanel { + public ClientJavaScriptModuleExtensionPanel(JavaScriptMutableModuleExtension extension) { + super(new VerticalFlowLayout(true, false)); - List validLanguageVersions = StandardJavaScriptVersions.getInstance().getValidLanguageVersions(); + List validLanguageVersions = StandardJavaScriptVersions.getInstance().getValidLanguageVersions(); - ComboBox languageVersionComboBox = new ComboBox(new CollectionComboBoxModel(validLanguageVersions, extension.getLanguageVersion())); - languageVersionComboBox.addItemListener(new ItemListener() - { - @Override - public void itemStateChanged(ItemEvent e) - { - if(e.getStateChange() == ItemEvent.SELECTED) - { - //noinspection unchecked - extension.setLanguageVersion((LanguageVersion) e.getItem()); - } - } - }); - languageVersionComboBox.setRenderer(new ColoredListCellRenderer() - { - @Override - protected void customizeCellRenderer(@Nonnull JList list, BaseJavaScriptLanguageVersion value, int index, boolean selected, boolean hasFocus) - { - append(value.getPresentableName()); - } - }); + ComboBox languageVersionComboBox = + new ComboBox<>(new CollectionComboBoxModel<>(validLanguageVersions, (JavaScriptLanguageVersion)extension.getLanguageVersion())); + languageVersionComboBox.addItemListener(e -> { + if (e.getStateChange() == ItemEvent.SELECTED) { + //noinspection unchecked + extension.setLanguageVersion((LanguageVersion)e.getItem()); + } + }); + languageVersionComboBox.setRenderer(new ColoredListCellRenderer<>() { + @Override + protected void customizeCellRenderer( + @Nonnull JList list, + JavaScriptLanguageVersion value, + int index, + boolean selected, + boolean hasFocus + ) { + append(value.getPresentableName()); + } + }); - add(LabeledComponent.create(languageVersionComboBox, "Default Version")); - } + add(LabeledComponent.create(languageVersionComboBox, "Default Version")); + } } diff --git a/web-browser-impl/src/main/java/consulo/javascript/client/module/extension/ClientJavaScriptModuleExtensionProvider.java b/web-browser-impl/src/main/java/consulo/javascript/client/module/extension/ClientJavaScriptModuleExtensionProvider.java index a288b88d..b2876acb 100644 --- a/web-browser-impl/src/main/java/consulo/javascript/client/module/extension/ClientJavaScriptModuleExtensionProvider.java +++ b/web-browser-impl/src/main/java/consulo/javascript/client/module/extension/ClientJavaScriptModuleExtensionProvider.java @@ -9,53 +9,46 @@ import consulo.module.extension.MutableModuleExtension; import consulo.ui.image.Image; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; /** * @author VISTALL - * @since 29-Aug-22 + * @since 2022-08-29 */ @ExtensionImpl -public class ClientJavaScriptModuleExtensionProvider implements ModuleExtensionProvider -{ - @Nonnull - @Override - public String getId() - { - return "client-javascript"; - } - - @Override - public boolean isAllowMixin() - { - return true; - } - - @Nonnull - @Override - public LocalizeValue getName() - { - return LocalizeValue.localizeTODO("JavaScript (Client)"); - } - - @Nonnull - @Override - public Image getIcon() - { - return JavaScriptIconGroup.javascript(); - } - - @Nonnull - @Override - public ModuleExtension createImmutableExtension(@Nonnull ModuleRootLayer moduleRootLayer) - { - return new ClientJavaScriptModuleExtension(getId(), moduleRootLayer); - } - - @Nonnull - @Override - public MutableModuleExtension createMutableExtension(@Nonnull ModuleRootLayer moduleRootLayer) - { - return new ClientJavaScriptMutableModuleExtension(getId(), moduleRootLayer); - } +public class ClientJavaScriptModuleExtensionProvider implements ModuleExtensionProvider { + @Nonnull + @Override + public String getId() { + return "client-javascript"; + } + + @Override + public boolean isAllowMixin() { + return true; + } + + @Nonnull + @Override + public LocalizeValue getName() { + return LocalizeValue.localizeTODO("JavaScript (Client)"); + } + + @Nonnull + @Override + public Image getIcon() { + return JavaScriptIconGroup.javascriptmodule(); + } + + @Nonnull + @Override + public ModuleExtension createImmutableExtension(@Nonnull ModuleRootLayer moduleRootLayer) { + return new ClientJavaScriptModuleExtension(getId(), moduleRootLayer); + } + + @Nonnull + @Override + public MutableModuleExtension createMutableExtension(@Nonnull ModuleRootLayer moduleRootLayer) { + return new ClientJavaScriptMutableModuleExtension(getId(), moduleRootLayer); + } } diff --git a/web-browser-impl/src/main/java/consulo/javascript/client/module/extension/ClientJavaScriptMutableModuleExtension.java b/web-browser-impl/src/main/java/consulo/javascript/client/module/extension/ClientJavaScriptMutableModuleExtension.java index 88eca5df..0608aa3f 100644 --- a/web-browser-impl/src/main/java/consulo/javascript/client/module/extension/ClientJavaScriptMutableModuleExtension.java +++ b/web-browser-impl/src/main/java/consulo/javascript/client/module/extension/ClientJavaScriptMutableModuleExtension.java @@ -12,59 +12,52 @@ import consulo.ui.annotation.RequiredUIAccess; import consulo.ui.layout.VerticalLayout; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; + import javax.swing.*; /** * @author VISTALL - * @since 29.06.14 + * @since 2014-06-29 */ -public class ClientJavaScriptMutableModuleExtension extends ClientJavaScriptModuleExtension implements JavaScriptMutableModuleExtension, SwingMutableModuleExtension -{ - public ClientJavaScriptMutableModuleExtension(@Nonnull String id, @Nonnull ModuleRootLayer rootModel) - { - super(id, rootModel); - } - - @Nonnull - @Override - public MutableModuleInheritableNamedPointer getInheritableSdk() - { - return (MutableModuleInheritableNamedPointer) super.getInheritableSdk(); - } - - @RequiredUIAccess - @Nullable - @Override - public Component createConfigurationComponent(@Nonnull Disposable disposable, @Nonnull Runnable runnable) - { - return VerticalLayout.create().add(Label.create("Unsupported UI")); - } - - @RequiredUIAccess - @Nullable - @Override - public JComponent createConfigurablePanel(@Nonnull Disposable disposable, @Nonnull Runnable runnable) - { - return new ClientJavaScriptModuleExtensionPanel(this); - } - - @Override - public void setEnabled(boolean val) - { - myIsEnabled = val; - } - - @Override - public boolean isModified(@Nonnull ClientJavaScriptModuleExtension originalExtension) - { - return myIsEnabled != originalExtension.isEnabled() || myLanguageVersion != originalExtension.getLanguageVersion(); - } - - @Override - public void setLanguageVersion(@Nonnull LanguageVersion languageVersion) - { - myLanguageVersion = languageVersion; - } +public class ClientJavaScriptMutableModuleExtension extends ClientJavaScriptModuleExtension implements JavaScriptMutableModuleExtension, SwingMutableModuleExtension { + public ClientJavaScriptMutableModuleExtension(@Nonnull String id, @Nonnull ModuleRootLayer rootModel) { + super(id, rootModel); + } + + @Nonnull + @Override + public MutableModuleInheritableNamedPointer getInheritableSdk() { + return (MutableModuleInheritableNamedPointer)super.getInheritableSdk(); + } + + @RequiredUIAccess + @Nullable + @Override + public Component createConfigurationComponent(@Nonnull Disposable disposable, @Nonnull Runnable runnable) { + return VerticalLayout.create().add(Label.create("Unsupported UI")); + } + + @RequiredUIAccess + @Nullable + @Override + public JComponent createConfigurablePanel(@Nonnull Disposable disposable, @Nonnull Runnable runnable) { + return new ClientJavaScriptModuleExtensionPanel(this); + } + + @Override + public void setEnabled(boolean val) { + myIsEnabled = val; + } + + @Override + public boolean isModified(@Nonnull ClientJavaScriptModuleExtension originalExtension) { + return myIsEnabled != originalExtension.isEnabled() || myLanguageVersion != originalExtension.getLanguageVersion(); + } + + @Override + public void setLanguageVersion(@Nonnull LanguageVersion languageVersion) { + myLanguageVersion = languageVersion; + } } diff --git a/web-browser-impl/src/main/java/consulo/javascript/client/module/sdk/ClientJavaScriptPredefinedBundlesProvider.java b/web-browser-impl/src/main/java/consulo/javascript/client/module/sdk/ClientJavaScriptPredefinedBundlesProvider.java index b1627237..7c376ece 100644 --- a/web-browser-impl/src/main/java/consulo/javascript/client/module/sdk/ClientJavaScriptPredefinedBundlesProvider.java +++ b/web-browser-impl/src/main/java/consulo/javascript/client/module/sdk/ClientJavaScriptPredefinedBundlesProvider.java @@ -9,55 +9,48 @@ import consulo.content.bundle.SdkModificator; import consulo.virtualFileSystem.LocalFileSystem; import consulo.virtualFileSystem.VirtualFile; +import jakarta.annotation.Nonnull; -import javax.annotation.Nonnull; import java.io.File; import java.util.Map; /** * @author VISTALL - * @since 29.06.14 + * @since 2014-06-29 */ @ExtensionImpl -public class ClientJavaScriptPredefinedBundlesProvider extends PredefinedBundlesProvider -{ - public static final String ANY_JAVASCRIPT_SDK = "JavaScript SDK (Any Browser)"; - - private Map ourMapping = Map.of("clientAny", ANY_JAVASCRIPT_SDK); - - @Override - public void createBundles(@Nonnull Context context) - { - File sdkDir = new File(PluginManager.getPluginPath(ClientJavaScriptPredefinedBundlesProvider.class), "sdk"); - if(!sdkDir.exists()) - { - return; - } - - for(File file : sdkDir.listFiles()) - { - String name = ourMapping.get(file.getName()); - if(name == null) - { - continue; - } - - VirtualFile fileByIoFile = LocalFileSystem.getInstance().findFileByIoFile(file); - if(fileByIoFile == null) - { - continue; - } - Sdk sdk = context.createSdkWithName(ClientJavaScriptSdkType.getInstance(), name); - - SdkModificator modificator = sdk.getSdkModificator(); - modificator.setHomePath(fileByIoFile.getPath()); - modificator.setVersionString("1"); - for(VirtualFile child : fileByIoFile.getChildren()) - { - modificator.addRoot(child, BinariesOrderRootType.getInstance()); - modificator.addRoot(child, SourcesOrderRootType.getInstance()); - } - modificator.commitChanges(); - } - } +public class ClientJavaScriptPredefinedBundlesProvider extends PredefinedBundlesProvider { + public static final String ANY_JAVASCRIPT_SDK = "JavaScript SDK (Any Browser)"; + + private Map ourMapping = Map.of("clientAny", ANY_JAVASCRIPT_SDK); + + @Override + public void createBundles(@Nonnull Context context) { + File sdkDir = new File(PluginManager.getPluginPath(ClientJavaScriptPredefinedBundlesProvider.class), "sdk"); + if (!sdkDir.exists()) { + return; + } + + for (File file : sdkDir.listFiles()) { + String name = ourMapping.get(file.getName()); + if (name == null) { + continue; + } + + VirtualFile fileByIoFile = LocalFileSystem.getInstance().findFileByIoFile(file); + if (fileByIoFile == null) { + continue; + } + Sdk sdk = context.createSdkWithName(ClientJavaScriptSdkType.getInstance(), name); + + SdkModificator modificator = sdk.getSdkModificator(); + modificator.setHomePath(fileByIoFile.getPath()); + modificator.setVersionString("1"); + for (VirtualFile child : fileByIoFile.getChildren()) { + modificator.addRoot(child, BinariesOrderRootType.getInstance()); + modificator.addRoot(child, SourcesOrderRootType.getInstance()); + } + modificator.commitChanges(); + } + } } diff --git a/web-browser-impl/src/main/java/consulo/javascript/client/module/sdk/ClientJavaScriptSdkType.java b/web-browser-impl/src/main/java/consulo/javascript/client/module/sdk/ClientJavaScriptSdkType.java index 96a286b9..e7add553 100644 --- a/web-browser-impl/src/main/java/consulo/javascript/client/module/sdk/ClientJavaScriptSdkType.java +++ b/web-browser-impl/src/main/java/consulo/javascript/client/module/sdk/ClientJavaScriptSdkType.java @@ -1,76 +1,55 @@ package consulo.javascript.client.module.sdk; import consulo.annotation.component.ExtensionImpl; +import consulo.application.Application; import consulo.content.OrderRootType; import consulo.content.base.BinariesOrderRootType; import consulo.content.base.SourcesOrderRootType; import consulo.content.bundle.SdkType; import consulo.javascript.icon.JavaScriptIconGroup; -import consulo.ui.image.Image; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; /** * @author VISTALL - * @since 29.06.14 + * @since 2014-06-29 */ @ExtensionImpl -public class ClientJavaScriptSdkType extends SdkType -{ - @Nonnull - public static ClientJavaScriptSdkType getInstance() - { - return EP_NAME.findExtensionOrFail(ClientJavaScriptSdkType.class); - } - - public ClientJavaScriptSdkType() - { - super("CLIENT_JAVASCRIPT_SDK_TYPE"); - } - - @Override - public boolean supportsUserAdd() - { - return false; - } - - @Override - public boolean isRootTypeApplicable(OrderRootType type) - { - return type == BinariesOrderRootType.getInstance() || type == SourcesOrderRootType.getInstance(); - } - - @Nullable - @Override - public Image getIcon() - { - return JavaScriptIconGroup.javascript(); - } - - @Override - public boolean isValidSdkHome(String path) - { - return false; - } - - @Nullable - @Override - public String getVersionString(String sdkHome) - { - return "1"; - } - - @Override - public String suggestSdkName(String currentSdkName, String sdkHome) - { - return currentSdkName; - } - - @Nonnull - @Override - public String getPresentableName() - { - return "Client JavaScript"; - } +public class ClientJavaScriptSdkType extends SdkType { + @Nonnull + public static ClientJavaScriptSdkType getInstance() { + return Application.get().getExtensionPoint(SdkType.class).findExtensionOrFail(ClientJavaScriptSdkType.class); + } + + public ClientJavaScriptSdkType() { + super("CLIENT_JAVASCRIPT_SDK_TYPE", LocalizeValue.localizeTODO("Client JavaScript"), JavaScriptIconGroup.javascriptmodule()); + } + + @Override + public boolean supportsUserAdd() { + return false; + } + + @Override + public boolean isRootTypeApplicable(OrderRootType type) { + return type == BinariesOrderRootType.getInstance() || type == SourcesOrderRootType.getInstance(); + } + + @Override + public boolean isValidSdkHome(String path) { + return false; + } + + @Nullable + @Override + public String getVersionString(String sdkHome) { + return "1"; + } + + @Nonnull + @Override + public String suggestSdkName(String currentSdkName, String sdkHome) { + return currentSdkName; + } } diff --git a/web-browser-impl/src/main/java/module-info.java b/web-browser-impl/src/main/java/module-info.java index 84b86bbd..4aea4fec 100644 --- a/web-browser-impl/src/main/java/module-info.java +++ b/web-browser-impl/src/main/java/module-info.java @@ -1,11 +1,11 @@ /** * @author VISTALL - * @since 29-Aug-22 + * @since 2022-08-29 */ module consulo.javascript.web.browser.impl { - // TODO remove in future - requires java.desktop; + // TODO remove in future + requires java.desktop; - requires consulo.javascript.base.impl; + requires consulo.javascript.base.impl; } \ No newline at end of file