You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@netbeans.apache.org by GitBox <gi...@apache.org> on 2022/09/19 13:36:43 UTC

[GitHub] [netbeans] lahodaj commented on a diff in pull request #4592: Provide hints for conversion to Virtual thread executor when thread pools are used

lahodaj commented on code in PR #4592:
URL: https://github.com/apache/netbeans/pull/4592#discussion_r974237529


##########
java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertToVT.java:
##########
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.netbeans.modules.java.hints.jdk;
+
+import com.sun.source.tree.AssignmentTree;
+import com.sun.source.tree.ExpressionStatementTree;
+import com.sun.source.tree.IdentifierTree;
+import com.sun.source.tree.MemberSelectTree;
+import com.sun.source.tree.MethodInvocationTree;
+import com.sun.source.tree.VariableTree;
+import com.sun.source.util.TreePath;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import org.netbeans.api.java.queries.CompilerOptionsQuery;
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.api.java.source.WorkingCopy;
+import org.netbeans.modules.java.hints.errors.Utilities;
+import org.netbeans.spi.editor.hints.ErrorDescription;
+import org.netbeans.spi.editor.hints.Fix;
+import org.netbeans.spi.java.hints.ErrorDescriptionFactory;
+import org.netbeans.spi.java.hints.Hint;
+import org.netbeans.spi.java.hints.HintContext;
+import org.netbeans.spi.java.hints.JavaFix;
+import org.netbeans.spi.java.hints.TriggerPattern;
+import org.netbeans.spi.java.hints.TriggerPatterns;
+import org.openide.util.NbBundle;
+
+/**
+ *
+ * @author mjayan
+ */
+@NbBundle.Messages({
+    "DN_ConvertToVT=Convert to Virtual Thread Executor",
+    "DESC_ConvertToVT=Convert to Virtual Thread Executor",
+    "ERR_ConvertToVT=Convert to Virtual Thread Executor",
+    "FIX_ConvertToVT=Convert to Virtual Thread Executor",
+    "ERR_ConvertToThreadPerTask=Convert to newThreadPerTask executor"
+})
+@Hint(displayName = "#DN_ConvertToVT", description = "#DESC_ConvertToVT", category = "rules15",
+        minSourceVersion = "19")
+public class ConvertToVT {
+
+    private static final int VT_PREVIEW_JDK_VERSION = 19;
+
+    @TriggerPatterns({
+        @TriggerPattern(value = "$var = $expr2.$meth1($var1$);"),

Review Comment:
   I'm afraid the hint is written in a way that is not ideal. Using `$expr2.$meth1`, and then checking inside the hint whether or not is error prone and relatively slow.
   
   Doing something like:
   ```
   @TriggerPattern(value="java.util.concurrent.Executors.newFixedThreadPool($size)" /*maybe a Constraint requiring that $size is an `int`*/)
   @TriggerPattern(value="java.util.concurrent.Executors.newFixedThreadPool($size, $factory)" /*maybe a Constraint requiring that $size is an `int` and $factory is a ThreadFactory*/)
   ```
   
   would avoid a lot of corner case states in the hint. (Patterns are meant to be cheap, so even some duplication should not be a problem, but if it is important to verify that the result is assigned into a variable, checking the enclosing AST node  in the hint might be more viable.) In this case, saying `java.util.concurrent.Executors.newFixedThreadPool` will tell the framework to not call the hint at all unless the `newFixedThreadPool` method on `java.util.concurrent.Executors` is called, which should be much faster (the framework should be able to eliminate non-matching patterns fairly quickly).



##########
java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertToVT.java:
##########
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.netbeans.modules.java.hints.jdk;
+
+import com.sun.source.tree.AssignmentTree;
+import com.sun.source.tree.ExpressionStatementTree;
+import com.sun.source.tree.IdentifierTree;
+import com.sun.source.tree.MemberSelectTree;
+import com.sun.source.tree.MethodInvocationTree;
+import com.sun.source.tree.VariableTree;
+import com.sun.source.util.TreePath;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import org.netbeans.api.java.queries.CompilerOptionsQuery;
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.api.java.source.WorkingCopy;
+import org.netbeans.modules.java.hints.errors.Utilities;
+import org.netbeans.spi.editor.hints.ErrorDescription;
+import org.netbeans.spi.editor.hints.Fix;
+import org.netbeans.spi.java.hints.ErrorDescriptionFactory;
+import org.netbeans.spi.java.hints.Hint;
+import org.netbeans.spi.java.hints.HintContext;
+import org.netbeans.spi.java.hints.JavaFix;
+import org.netbeans.spi.java.hints.TriggerPattern;
+import org.netbeans.spi.java.hints.TriggerPatterns;
+import org.openide.util.NbBundle;
+
+/**
+ *
+ * @author mjayan
+ */
+@NbBundle.Messages({
+    "DN_ConvertToVT=Convert to Virtual Thread Executor",
+    "DESC_ConvertToVT=Convert to Virtual Thread Executor",
+    "ERR_ConvertToVT=Convert to Virtual Thread Executor",
+    "FIX_ConvertToVT=Convert to Virtual Thread Executor",
+    "ERR_ConvertToThreadPerTask=Convert to newThreadPerTask executor"
+})
+@Hint(displayName = "#DN_ConvertToVT", description = "#DESC_ConvertToVT", category = "rules15",
+        minSourceVersion = "19")
+public class ConvertToVT {
+
+    private static final int VT_PREVIEW_JDK_VERSION = 19;
+
+    @TriggerPatterns({
+        @TriggerPattern(value = "$var = $expr2.$meth1($var1$);"),
+        @TriggerPattern(value = "$type $var = $expr2.$meth1($var1$);")
+    })
+    public static ErrorDescription compute(HintContext ctx) {
+        if (Utilities.isJDKVersionLower(VT_PREVIEW_JDK_VERSION) && !CompilerOptionsQuery.getOptions(ctx.getInfo().getFileObject()).getArguments().contains("--enable-preview")) {
+            return null;
+        }
+        List<String> methList = Arrays.asList("newFixedThreadPool", "newCachedThreadPool");
+        String expr = ctx.getInfo().getTrees().getElement(ctx.getVariables().get("$expr2")).getSimpleName().toString();

Review Comment:
   Please note that `Trees.getElement` may, in general, return `null`.



##########
java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertToVT.java:
##########
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.netbeans.modules.java.hints.jdk;
+
+import com.sun.source.tree.AssignmentTree;
+import com.sun.source.tree.ExpressionStatementTree;
+import com.sun.source.tree.IdentifierTree;
+import com.sun.source.tree.MemberSelectTree;
+import com.sun.source.tree.MethodInvocationTree;
+import com.sun.source.tree.VariableTree;
+import com.sun.source.util.TreePath;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import org.netbeans.api.java.queries.CompilerOptionsQuery;
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.api.java.source.WorkingCopy;
+import org.netbeans.modules.java.hints.errors.Utilities;
+import org.netbeans.spi.editor.hints.ErrorDescription;
+import org.netbeans.spi.editor.hints.Fix;
+import org.netbeans.spi.java.hints.ErrorDescriptionFactory;
+import org.netbeans.spi.java.hints.Hint;
+import org.netbeans.spi.java.hints.HintContext;
+import org.netbeans.spi.java.hints.JavaFix;
+import org.netbeans.spi.java.hints.TriggerPattern;
+import org.netbeans.spi.java.hints.TriggerPatterns;
+import org.openide.util.NbBundle;
+
+/**
+ *
+ * @author mjayan
+ */
+@NbBundle.Messages({
+    "DN_ConvertToVT=Convert to Virtual Thread Executor",
+    "DESC_ConvertToVT=Convert to Virtual Thread Executor",
+    "ERR_ConvertToVT=Convert to Virtual Thread Executor",
+    "FIX_ConvertToVT=Convert to Virtual Thread Executor",
+    "ERR_ConvertToThreadPerTask=Convert to newThreadPerTask executor"
+})
+@Hint(displayName = "#DN_ConvertToVT", description = "#DESC_ConvertToVT", category = "rules15",
+        minSourceVersion = "19")
+public class ConvertToVT {
+
+    private static final int VT_PREVIEW_JDK_VERSION = 19;
+
+    @TriggerPatterns({
+        @TriggerPattern(value = "$var = $expr2.$meth1($var1$);"),
+        @TriggerPattern(value = "$type $var = $expr2.$meth1($var1$);")
+    })
+    public static ErrorDescription compute(HintContext ctx) {
+        if (Utilities.isJDKVersionLower(VT_PREVIEW_JDK_VERSION) && !CompilerOptionsQuery.getOptions(ctx.getInfo().getFileObject()).getArguments().contains("--enable-preview")) {
+            return null;
+        }
+        List<String> methList = Arrays.asList("newFixedThreadPool", "newCachedThreadPool");
+        String expr = ctx.getInfo().getTrees().getElement(ctx.getVariables().get("$expr2")).getSimpleName().toString();
+        String method = ctx.getVariableNames().get("$meth1");
+        Collection<? extends TreePath> treePaths = ctx.getMultiVariables().get("$var1$");
+        boolean factory = false;
+        for (TreePath treePath : treePaths) {
+            if (treePath.getLeaf() instanceof IdentifierTree) {
+                factory = true;
+            }
+        }
+        if (expr.equals("Executors") && methList.contains(method)) {

Review Comment:
   Note that matching simple names is usually not very reliable. The user may have `Executors` class in their own package, and we probably should not be rewriting those.



##########
java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertToVT.java:
##########
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.netbeans.modules.java.hints.jdk;
+
+import com.sun.source.tree.AssignmentTree;
+import com.sun.source.tree.ExpressionStatementTree;
+import com.sun.source.tree.IdentifierTree;
+import com.sun.source.tree.MemberSelectTree;
+import com.sun.source.tree.MethodInvocationTree;
+import com.sun.source.tree.VariableTree;
+import com.sun.source.util.TreePath;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import org.netbeans.api.java.queries.CompilerOptionsQuery;
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.api.java.source.WorkingCopy;
+import org.netbeans.modules.java.hints.errors.Utilities;
+import org.netbeans.spi.editor.hints.ErrorDescription;
+import org.netbeans.spi.editor.hints.Fix;
+import org.netbeans.spi.java.hints.ErrorDescriptionFactory;
+import org.netbeans.spi.java.hints.Hint;
+import org.netbeans.spi.java.hints.HintContext;
+import org.netbeans.spi.java.hints.JavaFix;
+import org.netbeans.spi.java.hints.TriggerPattern;
+import org.netbeans.spi.java.hints.TriggerPatterns;
+import org.openide.util.NbBundle;
+
+/**
+ *
+ * @author mjayan
+ */
+@NbBundle.Messages({
+    "DN_ConvertToVT=Convert to Virtual Thread Executor",
+    "DESC_ConvertToVT=Convert to Virtual Thread Executor",
+    "ERR_ConvertToVT=Convert to Virtual Thread Executor",
+    "FIX_ConvertToVT=Convert to Virtual Thread Executor",
+    "ERR_ConvertToThreadPerTask=Convert to newThreadPerTask executor"
+})
+@Hint(displayName = "#DN_ConvertToVT", description = "#DESC_ConvertToVT", category = "rules15",
+        minSourceVersion = "19")
+public class ConvertToVT {
+
+    private static final int VT_PREVIEW_JDK_VERSION = 19;
+
+    @TriggerPatterns({
+        @TriggerPattern(value = "$var = $expr2.$meth1($var1$);"),
+        @TriggerPattern(value = "$type $var = $expr2.$meth1($var1$);")
+    })
+    public static ErrorDescription compute(HintContext ctx) {
+        if (Utilities.isJDKVersionLower(VT_PREVIEW_JDK_VERSION) && !CompilerOptionsQuery.getOptions(ctx.getInfo().getFileObject()).getArguments().contains("--enable-preview")) {
+            return null;
+        }
+        List<String> methList = Arrays.asList("newFixedThreadPool", "newCachedThreadPool");
+        String expr = ctx.getInfo().getTrees().getElement(ctx.getVariables().get("$expr2")).getSimpleName().toString();
+        String method = ctx.getVariableNames().get("$meth1");
+        Collection<? extends TreePath> treePaths = ctx.getMultiVariables().get("$var1$");
+        boolean factory = false;
+        for (TreePath treePath : treePaths) {
+            if (treePath.getLeaf() instanceof IdentifierTree) {

Review Comment:
   Not sure why `IdentifierTree` is important here - I can imagine cases like:
   `Executors.newFixedThreadPool(size)`, which will contain and identifier, and cases like:
   `Executors.newFixedThreadPool(1, new ThreadFactory() {...})`, which will not.
   
   I think that matching based on the specific method overload would be better.
   
   Also, checking `Tree`s, `Element`s or `TypeMirror`s using `instanceof` is not completely reliable, I'm afraid.



##########
java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertToVT.java:
##########
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.netbeans.modules.java.hints.jdk;
+
+import com.sun.source.tree.AssignmentTree;
+import com.sun.source.tree.ExpressionStatementTree;
+import com.sun.source.tree.IdentifierTree;
+import com.sun.source.tree.MemberSelectTree;
+import com.sun.source.tree.MethodInvocationTree;
+import com.sun.source.tree.VariableTree;
+import com.sun.source.util.TreePath;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import org.netbeans.api.java.queries.CompilerOptionsQuery;
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.api.java.source.WorkingCopy;
+import org.netbeans.modules.java.hints.errors.Utilities;
+import org.netbeans.spi.editor.hints.ErrorDescription;
+import org.netbeans.spi.editor.hints.Fix;
+import org.netbeans.spi.java.hints.ErrorDescriptionFactory;
+import org.netbeans.spi.java.hints.Hint;
+import org.netbeans.spi.java.hints.HintContext;
+import org.netbeans.spi.java.hints.JavaFix;
+import org.netbeans.spi.java.hints.TriggerPattern;
+import org.netbeans.spi.java.hints.TriggerPatterns;
+import org.openide.util.NbBundle;
+
+/**
+ *
+ * @author mjayan
+ */
+@NbBundle.Messages({
+    "DN_ConvertToVT=Convert to Virtual Thread Executor",
+    "DESC_ConvertToVT=Convert to Virtual Thread Executor",
+    "ERR_ConvertToVT=Convert to Virtual Thread Executor",
+    "FIX_ConvertToVT=Convert to Virtual Thread Executor",
+    "ERR_ConvertToThreadPerTask=Convert to newThreadPerTask executor"
+})
+@Hint(displayName = "#DN_ConvertToVT", description = "#DESC_ConvertToVT", category = "rules15",
+        minSourceVersion = "19")
+public class ConvertToVT {
+
+    private static final int VT_PREVIEW_JDK_VERSION = 19;
+
+    @TriggerPatterns({
+        @TriggerPattern(value = "$var = $expr2.$meth1($var1$);"),
+        @TriggerPattern(value = "$type $var = $expr2.$meth1($var1$);")
+    })
+    public static ErrorDescription compute(HintContext ctx) {
+        if (Utilities.isJDKVersionLower(VT_PREVIEW_JDK_VERSION) && !CompilerOptionsQuery.getOptions(ctx.getInfo().getFileObject()).getArguments().contains("--enable-preview")) {
+            return null;
+        }
+        List<String> methList = Arrays.asList("newFixedThreadPool", "newCachedThreadPool");
+        String expr = ctx.getInfo().getTrees().getElement(ctx.getVariables().get("$expr2")).getSimpleName().toString();
+        String method = ctx.getVariableNames().get("$meth1");
+        Collection<? extends TreePath> treePaths = ctx.getMultiVariables().get("$var1$");
+        boolean factory = false;
+        for (TreePath treePath : treePaths) {
+            if (treePath.getLeaf() instanceof IdentifierTree) {
+                factory = true;
+            }
+        }
+        if (expr.equals("Executors") && methList.contains(method)) {
+            Fix fix = new FixImpl(ctx.getInfo(), ctx.getPath(), factory).toEditorFix();
+            if (factory) {
+                return ErrorDescriptionFactory.forName(ctx, ctx.getPath(), Bundle.ERR_ConvertToThreadPerTask(), fix);
+            } else {
+                return ErrorDescriptionFactory.forName(ctx, ctx.getPath(), Bundle.ERR_ConvertToVT(), fix);
+            }
+        }
+        return null;
+    }
+
+    private static final class FixImpl extends JavaFix {
+
+        boolean factory;
+
+        public FixImpl(CompilationInfo info, TreePath main, boolean factory) {
+            super(info, main);
+            this.factory = factory;
+        }
+
+        @Override
+        protected String getText() {
+            if (!factory) {
+                return Bundle.FIX_ConvertToVT();
+            } else {
+                return Bundle.ERR_ConvertToThreadPerTask();
+            }
+        }
+
+        @Override
+        protected void performRewrite(TransformationContext ctx) throws Exception {
+            if (!factory) {
+                WorkingCopy wc = ctx.getWorkingCopy();

Review Comment:
   FWIW, there is:
   `org.netbeans.spi.java.hints.JavaFixUtilities.rewriteFix` which allows to specify the re-write in a textual form. E.g.:
   `$var = $expr2.newVirtualThreadPerTaskExecutor($var1$);` (or, better: `java.util.concurrent.Executors.newVirtualThreadPerTaskExecutor()`, if the first suggestion is adopted.)



##########
java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertToVT.java:
##########
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.netbeans.modules.java.hints.jdk;
+
+import com.sun.source.tree.AssignmentTree;
+import com.sun.source.tree.ExpressionStatementTree;
+import com.sun.source.tree.IdentifierTree;
+import com.sun.source.tree.MemberSelectTree;
+import com.sun.source.tree.MethodInvocationTree;
+import com.sun.source.tree.VariableTree;
+import com.sun.source.util.TreePath;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import org.netbeans.api.java.queries.CompilerOptionsQuery;
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.api.java.source.WorkingCopy;
+import org.netbeans.modules.java.hints.errors.Utilities;
+import org.netbeans.spi.editor.hints.ErrorDescription;
+import org.netbeans.spi.editor.hints.Fix;
+import org.netbeans.spi.java.hints.ErrorDescriptionFactory;
+import org.netbeans.spi.java.hints.Hint;
+import org.netbeans.spi.java.hints.HintContext;
+import org.netbeans.spi.java.hints.JavaFix;
+import org.netbeans.spi.java.hints.TriggerPattern;
+import org.netbeans.spi.java.hints.TriggerPatterns;
+import org.openide.util.NbBundle;
+
+/**
+ *
+ * @author mjayan
+ */
+@NbBundle.Messages({
+    "DN_ConvertToVT=Convert to Virtual Thread Executor",
+    "DESC_ConvertToVT=Convert to Virtual Thread Executor",
+    "ERR_ConvertToVT=Convert to Virtual Thread Executor",
+    "FIX_ConvertToVT=Convert to Virtual Thread Executor",
+    "ERR_ConvertToThreadPerTask=Convert to newThreadPerTask executor"
+})
+@Hint(displayName = "#DN_ConvertToVT", description = "#DESC_ConvertToVT", category = "rules15",
+        minSourceVersion = "19")
+public class ConvertToVT {
+
+    private static final int VT_PREVIEW_JDK_VERSION = 19;
+
+    @TriggerPatterns({
+        @TriggerPattern(value = "$var = $expr2.$meth1($var1$);"),
+        @TriggerPattern(value = "$type $var = $expr2.$meth1($var1$);")
+    })
+    public static ErrorDescription compute(HintContext ctx) {
+        if (Utilities.isJDKVersionLower(VT_PREVIEW_JDK_VERSION) && !CompilerOptionsQuery.getOptions(ctx.getInfo().getFileObject()).getArguments().contains("--enable-preview")) {
+            return null;
+        }
+        List<String> methList = Arrays.asList("newFixedThreadPool", "newCachedThreadPool");
+        String expr = ctx.getInfo().getTrees().getElement(ctx.getVariables().get("$expr2")).getSimpleName().toString();
+        String method = ctx.getVariableNames().get("$meth1");
+        Collection<? extends TreePath> treePaths = ctx.getMultiVariables().get("$var1$");
+        boolean factory = false;
+        for (TreePath treePath : treePaths) {
+            if (treePath.getLeaf() instanceof IdentifierTree) {
+                factory = true;
+            }
+        }
+        if (expr.equals("Executors") && methList.contains(method)) {
+            Fix fix = new FixImpl(ctx.getInfo(), ctx.getPath(), factory).toEditorFix();
+            if (factory) {
+                return ErrorDescriptionFactory.forName(ctx, ctx.getPath(), Bundle.ERR_ConvertToThreadPerTask(), fix);

Review Comment:
   As far as I can tell, the fix is not doing anything for `factory==true`, so maybe it should not be used at all? It is OK to have a warning if we don't/can't have a fix, but showing a fix to the user that then doing nothing feels confusing.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@netbeans.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@netbeans.apache.org
For additional commands, e-mail: notifications-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists